VST3: fetch midi mappings all at once, use it for note/sound-off
[carla.git] / source / utils / CarlaSha1Utils.hpp
blobf6a8026d182b81f00aa69729430ee1b80968b2a5
1 /*
2 * Carla sha1 utils
3 * Copyright (C) 2023 Filipe Coelho <falktx@falktx.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #ifndef CARLA_SHA1_UTILS_HPP_INCLUDED
19 #define CARLA_SHA1_UTILS_HPP_INCLUDED
21 #include "CarlaUtils.hpp"
23 #if defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
24 # define CARLA_SHA1_BIG_ENDIAN
25 #endif
27 /*!
28 * Simple, single-use SHA1 class.
29 * Must be discarded after use.
31 * Based on libcrypt by Wei Dai and other contributors (originally in the public domain)
33 class CarlaSha1 {
34 static constexpr const size_t BLOCK_LENGTH = 64;
36 union {
37 uint8_t u8[BLOCK_LENGTH];
38 uint32_t u32[BLOCK_LENGTH/sizeof(uint32_t)];
39 } buffer;
40 uint32_t state[5];
41 uint32_t byteCount;
42 uint8_t bufferOffset;
43 char resultstr[41];
45 static_assert(sizeof(buffer.u8) == sizeof(buffer.u32), "valid size");
47 public:
49 * Constructor.
51 CarlaSha1() noexcept
52 : byteCount(0),
53 bufferOffset(0)
55 state[0] = 0x67452301;
56 state[1] = 0xefcdab89;
57 state[2] = 0x98badcfe;
58 state[3] = 0x10325476;
59 state[4] = 0xc3d2e1f0;
63 * Write a single byte of data.
65 void writeByte(const uint8_t data) noexcept
67 ++byteCount;
68 _addUncounted(data);
72 * Write a custom blob of data.
74 void write(const void* const data, size_t len) noexcept
76 const uint8_t* u8data = static_cast<const uint8_t*>(data);
78 while (len--)
79 writeByte(*u8data++);
83 * Return hash result as byte array (20 characters).
84 * @note must be called only once!
86 const uint8_t* resultAsHash() noexcept
88 // Pad to complete the last block
89 _pad();
91 #ifndef CARLA_SHA1_BIG_ENDIAN
92 // Swap byte order back
93 for (int i=0; i<5; ++i)
95 state[i] = ((state[i] << 24) & 0xff000000)
96 | ((state[i] << 8) & 0x00ff0000)
97 | ((state[i] >> 8) & 0x0000ff00)
98 | ((state[i] >> 24) & 0x000000ff);
100 #endif
102 return static_cast<uint8_t*>(static_cast<void*>(state));
106 * Return hash result as null-terminated string.
107 * @note must be called only once!
109 const char* resultAsString() noexcept
111 const uint8_t* const hash = resultAsHash();
113 for (int i=0; i<20; ++i)
114 std::snprintf(resultstr + (i * 2), 3, "%02x", hash[i]);
116 resultstr[40] = '\0';
118 return resultstr;
121 private:
122 void _addUncounted(const uint8_t data) noexcept
124 #ifdef CARLA_SHA1_BIG_ENDIAN
125 buffer.u8[bufferOffset] = data;
126 #else
127 buffer.u8[bufferOffset ^ 3] = data;
128 #endif
129 if (++bufferOffset == BLOCK_LENGTH)
131 bufferOffset = 0;
132 _hashBlock();
136 void _hashBlock() noexcept
138 uint32_t a = state[0];
139 uint32_t b = state[1];
140 uint32_t c = state[2];
141 uint32_t d = state[3];
142 uint32_t e = state[4];
143 uint32_t t;
145 for (uint8_t i=0; i<80; ++i)
147 if (i >= 16)
149 t = buffer.u32[(i + 13) & 15]
150 ^ buffer.u32[(i + 8) & 15]
151 ^ buffer.u32[(i + 2) & 15]
152 ^ buffer.u32[i & 15];
153 buffer.u32[i & 15] = _rol32(t, 1);
155 if (i < 20)
157 t = (d ^ (b & (c ^ d))) + 0x5a827999;
159 else if (i < 40)
161 t = (b ^ c ^ d) + 0x6ed9eba1;
163 else if (i < 60)
165 t = ((b & c) | (d & (b | c))) + 0x8f1bbcdc;
167 else
169 t = (b ^ c ^ d) + 0xca62c1d6;
171 t += _rol32(a, 5) + e + buffer.u32[i & 15];
172 e = d;
173 d = c;
174 c = _rol32(b, 30);
175 b = a;
176 a = t;
179 state[0] += a;
180 state[1] += b;
181 state[2] += c;
182 state[3] += d;
183 state[4] += e;
186 // Implement SHA-1 padding (fips180-2 ยง5.1.1)
187 void _pad() noexcept
189 // Pad with 0x80 followed by 0x00 until the end of the block
190 _addUncounted(0x80);
191 while (bufferOffset != 56) _addUncounted(0x00);
193 // Append length in the last 8 bytes
194 _addUncounted(0); // We're only using 32 bit lengths
195 _addUncounted(0); // But SHA-1 supports 64 bit lengths
196 _addUncounted(0); // So zero pad the top bits
197 _addUncounted(byteCount >> 29); // Shifting to multiply by 8
198 _addUncounted(byteCount >> 21); // as SHA-1 supports bitstreams as well as
199 _addUncounted(byteCount >> 13); // byte.
200 _addUncounted(byteCount >> 5);
201 _addUncounted(byteCount << 3);
204 static uint32_t _rol32(const uint32_t number, const uint8_t bits) noexcept
206 return (number << bits) | (number >> (32 - bits));
210 #endif // CARLA_SHA1_UTILS_HPP_INCLUDED