diff --git a/3rd_party/hash_library/sha256.cpp b/3rd_party/hash_library/sha256.cpp index fbeab6c..70a19e7 100644 --- a/3rd_party/hash_library/sha256.cpp +++ b/3rd_party/hash_library/sha256.cpp @@ -13,58 +13,50 @@ #include #endif -//#define SHA2_224_SEED_VECTOR - +// #define SHA2_224_SEED_VECTOR /// same as reset() -SHA256::SHA256() -{ - reset(); +SHA256::SHA256() { + reset(); } - /// restart -void SHA256::reset() -{ - m_numBytes = 0; - m_bufferSize = 0; - - // according to RFC 1321 - // "These words were obtained by taking the first thirty-two bits of the - // fractional parts of the square roots of the first eight prime numbers" - m_hash[0] = 0x6a09e667; - m_hash[1] = 0xbb67ae85; - m_hash[2] = 0x3c6ef372; - m_hash[3] = 0xa54ff53a; - m_hash[4] = 0x510e527f; - m_hash[5] = 0x9b05688c; - m_hash[6] = 0x1f83d9ab; - m_hash[7] = 0x5be0cd19; +void SHA256::reset() { + m_numBytes = 0; + m_bufferSize = 0; + + // according to RFC 1321 + // "These words were obtained by taking the first thirty-two bits of the + // fractional parts of the square roots of the first eight prime numbers" + m_hash[0] = 0x6a09e667; + m_hash[1] = 0xbb67ae85; + m_hash[2] = 0x3c6ef372; + m_hash[3] = 0xa54ff53a; + m_hash[4] = 0x510e527f; + m_hash[5] = 0x9b05688c; + m_hash[6] = 0x1f83d9ab; + m_hash[7] = 0x5be0cd19; #ifdef SHA2_224_SEED_VECTOR - // if you want SHA2-224 instead then use these seeds - // and throw away the last 32 bits of getHash - m_hash[0] = 0xc1059ed8; - m_hash[1] = 0x367cd507; - m_hash[2] = 0x3070dd17; - m_hash[3] = 0xf70e5939; - m_hash[4] = 0xffc00b31; - m_hash[5] = 0x68581511; - m_hash[6] = 0x64f98fa7; - m_hash[7] = 0xbefa4fa4; + // if you want SHA2-224 instead then use these seeds + // and throw away the last 32 bits of getHash + m_hash[0] = 0xc1059ed8; + m_hash[1] = 0x367cd507; + m_hash[2] = 0x3070dd17; + m_hash[3] = 0xf70e5939; + m_hash[4] = 0xffc00b31; + m_hash[5] = 0x68581511; + m_hash[6] = 0x64f98fa7; + m_hash[7] = 0xbefa4fa4; #endif } - -namespace -{ - inline uint32_t rotate(uint32_t a, uint32_t c) - { +namespace { +inline uint32_t rotate(uint32_t a, uint32_t c) { return (a >> c) | (a << (32 - c)); - } +} - inline uint32_t swap(uint32_t x) - { +inline uint32_t swap(uint32_t x) { #if defined(__GNUC__) || defined(__clang__) return __builtin_bswap32(x); #endif @@ -72,359 +64,513 @@ namespace return _byteswap_ulong(x); #endif - return (x >> 24) | - ((x >> 8) & 0x0000FF00) | - ((x << 8) & 0x00FF0000) | - (x << 24); - } + return (x >> 24) | ((x >> 8) & 0x0000FF00) | ((x << 8) & 0x00FF0000) | (x << 24); +} - // mix functions for processBlock() - inline uint32_t f1(uint32_t e, uint32_t f, uint32_t g) - { +// mix functions for processBlock() +inline uint32_t f1(uint32_t e, uint32_t f, uint32_t g) { uint32_t term1 = rotate(e, 6) ^ rotate(e, 11) ^ rotate(e, 25); uint32_t term2 = (e & f) ^ (~e & g); //(g ^ (e & (f ^ g))) return term1 + term2; - } +} - inline uint32_t f2(uint32_t a, uint32_t b, uint32_t c) - { +inline uint32_t f2(uint32_t a, uint32_t b, uint32_t c) { uint32_t term1 = rotate(a, 2) ^ rotate(a, 13) ^ rotate(a, 22); uint32_t term2 = ((a | b) & c) | (a & b); //(a & (b ^ c)) ^ (b & c); return term1 + term2; - } } - +} // namespace /// process 64 bytes -void SHA256::processBlock(const void* data) -{ - // get last hash - uint32_t a = m_hash[0]; - uint32_t b = m_hash[1]; - uint32_t c = m_hash[2]; - uint32_t d = m_hash[3]; - uint32_t e = m_hash[4]; - uint32_t f = m_hash[5]; - uint32_t g = m_hash[6]; - uint32_t h = m_hash[7]; - - // data represented as 16x 32-bit words - const uint32_t* input = (uint32_t*) data; - // convert to big endian - uint32_t words[64]; - int i; - for (i = 0; i < 16; i++) +void SHA256::processBlock(const void* data) { + // get last hash + uint32_t a = m_hash[0]; + uint32_t b = m_hash[1]; + uint32_t c = m_hash[2]; + uint32_t d = m_hash[3]; + uint32_t e = m_hash[4]; + uint32_t f = m_hash[5]; + uint32_t g = m_hash[6]; + uint32_t h = m_hash[7]; + + // data represented as 16x 32-bit words + const uint32_t* input = (uint32_t*)data; + // convert to big endian + uint32_t words[64]; + int i; + for (i = 0; i < 16; i++) #if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN) - words[i] = input[i]; + words[i] = input[i]; #else - words[i] = swap(input[i]); + words[i] = swap(input[i]); #endif - uint32_t x,y; // temporaries - - // first round - x = h + f1(e,f,g) + 0x428a2f98 + words[ 0]; y = f2(a,b,c); d += x; h = x + y; - x = g + f1(d,e,f) + 0x71374491 + words[ 1]; y = f2(h,a,b); c += x; g = x + y; - x = f + f1(c,d,e) + 0xb5c0fbcf + words[ 2]; y = f2(g,h,a); b += x; f = x + y; - x = e + f1(b,c,d) + 0xe9b5dba5 + words[ 3]; y = f2(f,g,h); a += x; e = x + y; - x = d + f1(a,b,c) + 0x3956c25b + words[ 4]; y = f2(e,f,g); h += x; d = x + y; - x = c + f1(h,a,b) + 0x59f111f1 + words[ 5]; y = f2(d,e,f); g += x; c = x + y; - x = b + f1(g,h,a) + 0x923f82a4 + words[ 6]; y = f2(c,d,e); f += x; b = x + y; - x = a + f1(f,g,h) + 0xab1c5ed5 + words[ 7]; y = f2(b,c,d); e += x; a = x + y; - - // secound round - x = h + f1(e,f,g) + 0xd807aa98 + words[ 8]; y = f2(a,b,c); d += x; h = x + y; - x = g + f1(d,e,f) + 0x12835b01 + words[ 9]; y = f2(h,a,b); c += x; g = x + y; - x = f + f1(c,d,e) + 0x243185be + words[10]; y = f2(g,h,a); b += x; f = x + y; - x = e + f1(b,c,d) + 0x550c7dc3 + words[11]; y = f2(f,g,h); a += x; e = x + y; - x = d + f1(a,b,c) + 0x72be5d74 + words[12]; y = f2(e,f,g); h += x; d = x + y; - x = c + f1(h,a,b) + 0x80deb1fe + words[13]; y = f2(d,e,f); g += x; c = x + y; - x = b + f1(g,h,a) + 0x9bdc06a7 + words[14]; y = f2(c,d,e); f += x; b = x + y; - x = a + f1(f,g,h) + 0xc19bf174 + words[15]; y = f2(b,c,d); e += x; a = x + y; - - // extend to 24 words - for (; i < 24; i++) - words[i] = words[i-16] + - (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + - words[i-7] + - (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); - - // third round - x = h + f1(e,f,g) + 0xe49b69c1 + words[16]; y = f2(a,b,c); d += x; h = x + y; - x = g + f1(d,e,f) + 0xefbe4786 + words[17]; y = f2(h,a,b); c += x; g = x + y; - x = f + f1(c,d,e) + 0x0fc19dc6 + words[18]; y = f2(g,h,a); b += x; f = x + y; - x = e + f1(b,c,d) + 0x240ca1cc + words[19]; y = f2(f,g,h); a += x; e = x + y; - x = d + f1(a,b,c) + 0x2de92c6f + words[20]; y = f2(e,f,g); h += x; d = x + y; - x = c + f1(h,a,b) + 0x4a7484aa + words[21]; y = f2(d,e,f); g += x; c = x + y; - x = b + f1(g,h,a) + 0x5cb0a9dc + words[22]; y = f2(c,d,e); f += x; b = x + y; - x = a + f1(f,g,h) + 0x76f988da + words[23]; y = f2(b,c,d); e += x; a = x + y; - - // extend to 32 words - for (; i < 32; i++) - words[i] = words[i-16] + - (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + - words[i-7] + - (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); - - // fourth round - x = h + f1(e,f,g) + 0x983e5152 + words[24]; y = f2(a,b,c); d += x; h = x + y; - x = g + f1(d,e,f) + 0xa831c66d + words[25]; y = f2(h,a,b); c += x; g = x + y; - x = f + f1(c,d,e) + 0xb00327c8 + words[26]; y = f2(g,h,a); b += x; f = x + y; - x = e + f1(b,c,d) + 0xbf597fc7 + words[27]; y = f2(f,g,h); a += x; e = x + y; - x = d + f1(a,b,c) + 0xc6e00bf3 + words[28]; y = f2(e,f,g); h += x; d = x + y; - x = c + f1(h,a,b) + 0xd5a79147 + words[29]; y = f2(d,e,f); g += x; c = x + y; - x = b + f1(g,h,a) + 0x06ca6351 + words[30]; y = f2(c,d,e); f += x; b = x + y; - x = a + f1(f,g,h) + 0x14292967 + words[31]; y = f2(b,c,d); e += x; a = x + y; - - // extend to 40 words - for (; i < 40; i++) - words[i] = words[i-16] + - (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + - words[i-7] + - (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); - - // fifth round - x = h + f1(e,f,g) + 0x27b70a85 + words[32]; y = f2(a,b,c); d += x; h = x + y; - x = g + f1(d,e,f) + 0x2e1b2138 + words[33]; y = f2(h,a,b); c += x; g = x + y; - x = f + f1(c,d,e) + 0x4d2c6dfc + words[34]; y = f2(g,h,a); b += x; f = x + y; - x = e + f1(b,c,d) + 0x53380d13 + words[35]; y = f2(f,g,h); a += x; e = x + y; - x = d + f1(a,b,c) + 0x650a7354 + words[36]; y = f2(e,f,g); h += x; d = x + y; - x = c + f1(h,a,b) + 0x766a0abb + words[37]; y = f2(d,e,f); g += x; c = x + y; - x = b + f1(g,h,a) + 0x81c2c92e + words[38]; y = f2(c,d,e); f += x; b = x + y; - x = a + f1(f,g,h) + 0x92722c85 + words[39]; y = f2(b,c,d); e += x; a = x + y; - - // extend to 48 words - for (; i < 48; i++) - words[i] = words[i-16] + - (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + - words[i-7] + - (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); - - // sixth round - x = h + f1(e,f,g) + 0xa2bfe8a1 + words[40]; y = f2(a,b,c); d += x; h = x + y; - x = g + f1(d,e,f) + 0xa81a664b + words[41]; y = f2(h,a,b); c += x; g = x + y; - x = f + f1(c,d,e) + 0xc24b8b70 + words[42]; y = f2(g,h,a); b += x; f = x + y; - x = e + f1(b,c,d) + 0xc76c51a3 + words[43]; y = f2(f,g,h); a += x; e = x + y; - x = d + f1(a,b,c) + 0xd192e819 + words[44]; y = f2(e,f,g); h += x; d = x + y; - x = c + f1(h,a,b) + 0xd6990624 + words[45]; y = f2(d,e,f); g += x; c = x + y; - x = b + f1(g,h,a) + 0xf40e3585 + words[46]; y = f2(c,d,e); f += x; b = x + y; - x = a + f1(f,g,h) + 0x106aa070 + words[47]; y = f2(b,c,d); e += x; a = x + y; - - // extend to 56 words - for (; i < 56; i++) - words[i] = words[i-16] + - (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + - words[i-7] + - (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); - - // seventh round - x = h + f1(e,f,g) + 0x19a4c116 + words[48]; y = f2(a,b,c); d += x; h = x + y; - x = g + f1(d,e,f) + 0x1e376c08 + words[49]; y = f2(h,a,b); c += x; g = x + y; - x = f + f1(c,d,e) + 0x2748774c + words[50]; y = f2(g,h,a); b += x; f = x + y; - x = e + f1(b,c,d) + 0x34b0bcb5 + words[51]; y = f2(f,g,h); a += x; e = x + y; - x = d + f1(a,b,c) + 0x391c0cb3 + words[52]; y = f2(e,f,g); h += x; d = x + y; - x = c + f1(h,a,b) + 0x4ed8aa4a + words[53]; y = f2(d,e,f); g += x; c = x + y; - x = b + f1(g,h,a) + 0x5b9cca4f + words[54]; y = f2(c,d,e); f += x; b = x + y; - x = a + f1(f,g,h) + 0x682e6ff3 + words[55]; y = f2(b,c,d); e += x; a = x + y; - - // extend to 64 words - for (; i < 64; i++) - words[i] = words[i-16] + - (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + - words[i-7] + - (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); - - // eigth round - x = h + f1(e,f,g) + 0x748f82ee + words[56]; y = f2(a,b,c); d += x; h = x + y; - x = g + f1(d,e,f) + 0x78a5636f + words[57]; y = f2(h,a,b); c += x; g = x + y; - x = f + f1(c,d,e) + 0x84c87814 + words[58]; y = f2(g,h,a); b += x; f = x + y; - x = e + f1(b,c,d) + 0x8cc70208 + words[59]; y = f2(f,g,h); a += x; e = x + y; - x = d + f1(a,b,c) + 0x90befffa + words[60]; y = f2(e,f,g); h += x; d = x + y; - x = c + f1(h,a,b) + 0xa4506ceb + words[61]; y = f2(d,e,f); g += x; c = x + y; - x = b + f1(g,h,a) + 0xbef9a3f7 + words[62]; y = f2(c,d,e); f += x; b = x + y; - x = a + f1(f,g,h) + 0xc67178f2 + words[63]; y = f2(b,c,d); e += x; a = x + y; - - // update hash - m_hash[0] += a; - m_hash[1] += b; - m_hash[2] += c; - m_hash[3] += d; - m_hash[4] += e; - m_hash[5] += f; - m_hash[6] += g; - m_hash[7] += h; + uint32_t x, y; // temporaries + + // first round + x = h + f1(e, f, g) + 0x428a2f98 + words[0]; + y = f2(a, b, c); + d += x; + h = x + y; + x = g + f1(d, e, f) + 0x71374491 + words[1]; + y = f2(h, a, b); + c += x; + g = x + y; + x = f + f1(c, d, e) + 0xb5c0fbcf + words[2]; + y = f2(g, h, a); + b += x; + f = x + y; + x = e + f1(b, c, d) + 0xe9b5dba5 + words[3]; + y = f2(f, g, h); + a += x; + e = x + y; + x = d + f1(a, b, c) + 0x3956c25b + words[4]; + y = f2(e, f, g); + h += x; + d = x + y; + x = c + f1(h, a, b) + 0x59f111f1 + words[5]; + y = f2(d, e, f); + g += x; + c = x + y; + x = b + f1(g, h, a) + 0x923f82a4 + words[6]; + y = f2(c, d, e); + f += x; + b = x + y; + x = a + f1(f, g, h) + 0xab1c5ed5 + words[7]; + y = f2(b, c, d); + e += x; + a = x + y; + + // secound round + x = h + f1(e, f, g) + 0xd807aa98 + words[8]; + y = f2(a, b, c); + d += x; + h = x + y; + x = g + f1(d, e, f) + 0x12835b01 + words[9]; + y = f2(h, a, b); + c += x; + g = x + y; + x = f + f1(c, d, e) + 0x243185be + words[10]; + y = f2(g, h, a); + b += x; + f = x + y; + x = e + f1(b, c, d) + 0x550c7dc3 + words[11]; + y = f2(f, g, h); + a += x; + e = x + y; + x = d + f1(a, b, c) + 0x72be5d74 + words[12]; + y = f2(e, f, g); + h += x; + d = x + y; + x = c + f1(h, a, b) + 0x80deb1fe + words[13]; + y = f2(d, e, f); + g += x; + c = x + y; + x = b + f1(g, h, a) + 0x9bdc06a7 + words[14]; + y = f2(c, d, e); + f += x; + b = x + y; + x = a + f1(f, g, h) + 0xc19bf174 + words[15]; + y = f2(b, c, d); + e += x; + a = x + y; + + // extend to 24 words + for (; i < 24; i++) + words[i] = words[i - 16] + (rotate(words[i - 15], 7) ^ rotate(words[i - 15], 18) ^ (words[i - 15] >> 3)) + + words[i - 7] + (rotate(words[i - 2], 17) ^ rotate(words[i - 2], 19) ^ (words[i - 2] >> 10)); + + // third round + x = h + f1(e, f, g) + 0xe49b69c1 + words[16]; + y = f2(a, b, c); + d += x; + h = x + y; + x = g + f1(d, e, f) + 0xefbe4786 + words[17]; + y = f2(h, a, b); + c += x; + g = x + y; + x = f + f1(c, d, e) + 0x0fc19dc6 + words[18]; + y = f2(g, h, a); + b += x; + f = x + y; + x = e + f1(b, c, d) + 0x240ca1cc + words[19]; + y = f2(f, g, h); + a += x; + e = x + y; + x = d + f1(a, b, c) + 0x2de92c6f + words[20]; + y = f2(e, f, g); + h += x; + d = x + y; + x = c + f1(h, a, b) + 0x4a7484aa + words[21]; + y = f2(d, e, f); + g += x; + c = x + y; + x = b + f1(g, h, a) + 0x5cb0a9dc + words[22]; + y = f2(c, d, e); + f += x; + b = x + y; + x = a + f1(f, g, h) + 0x76f988da + words[23]; + y = f2(b, c, d); + e += x; + a = x + y; + + // extend to 32 words + for (; i < 32; i++) + words[i] = words[i - 16] + (rotate(words[i - 15], 7) ^ rotate(words[i - 15], 18) ^ (words[i - 15] >> 3)) + + words[i - 7] + (rotate(words[i - 2], 17) ^ rotate(words[i - 2], 19) ^ (words[i - 2] >> 10)); + + // fourth round + x = h + f1(e, f, g) + 0x983e5152 + words[24]; + y = f2(a, b, c); + d += x; + h = x + y; + x = g + f1(d, e, f) + 0xa831c66d + words[25]; + y = f2(h, a, b); + c += x; + g = x + y; + x = f + f1(c, d, e) + 0xb00327c8 + words[26]; + y = f2(g, h, a); + b += x; + f = x + y; + x = e + f1(b, c, d) + 0xbf597fc7 + words[27]; + y = f2(f, g, h); + a += x; + e = x + y; + x = d + f1(a, b, c) + 0xc6e00bf3 + words[28]; + y = f2(e, f, g); + h += x; + d = x + y; + x = c + f1(h, a, b) + 0xd5a79147 + words[29]; + y = f2(d, e, f); + g += x; + c = x + y; + x = b + f1(g, h, a) + 0x06ca6351 + words[30]; + y = f2(c, d, e); + f += x; + b = x + y; + x = a + f1(f, g, h) + 0x14292967 + words[31]; + y = f2(b, c, d); + e += x; + a = x + y; + + // extend to 40 words + for (; i < 40; i++) + words[i] = words[i - 16] + (rotate(words[i - 15], 7) ^ rotate(words[i - 15], 18) ^ (words[i - 15] >> 3)) + + words[i - 7] + (rotate(words[i - 2], 17) ^ rotate(words[i - 2], 19) ^ (words[i - 2] >> 10)); + + // fifth round + x = h + f1(e, f, g) + 0x27b70a85 + words[32]; + y = f2(a, b, c); + d += x; + h = x + y; + x = g + f1(d, e, f) + 0x2e1b2138 + words[33]; + y = f2(h, a, b); + c += x; + g = x + y; + x = f + f1(c, d, e) + 0x4d2c6dfc + words[34]; + y = f2(g, h, a); + b += x; + f = x + y; + x = e + f1(b, c, d) + 0x53380d13 + words[35]; + y = f2(f, g, h); + a += x; + e = x + y; + x = d + f1(a, b, c) + 0x650a7354 + words[36]; + y = f2(e, f, g); + h += x; + d = x + y; + x = c + f1(h, a, b) + 0x766a0abb + words[37]; + y = f2(d, e, f); + g += x; + c = x + y; + x = b + f1(g, h, a) + 0x81c2c92e + words[38]; + y = f2(c, d, e); + f += x; + b = x + y; + x = a + f1(f, g, h) + 0x92722c85 + words[39]; + y = f2(b, c, d); + e += x; + a = x + y; + + // extend to 48 words + for (; i < 48; i++) + words[i] = words[i - 16] + (rotate(words[i - 15], 7) ^ rotate(words[i - 15], 18) ^ (words[i - 15] >> 3)) + + words[i - 7] + (rotate(words[i - 2], 17) ^ rotate(words[i - 2], 19) ^ (words[i - 2] >> 10)); + + // sixth round + x = h + f1(e, f, g) + 0xa2bfe8a1 + words[40]; + y = f2(a, b, c); + d += x; + h = x + y; + x = g + f1(d, e, f) + 0xa81a664b + words[41]; + y = f2(h, a, b); + c += x; + g = x + y; + x = f + f1(c, d, e) + 0xc24b8b70 + words[42]; + y = f2(g, h, a); + b += x; + f = x + y; + x = e + f1(b, c, d) + 0xc76c51a3 + words[43]; + y = f2(f, g, h); + a += x; + e = x + y; + x = d + f1(a, b, c) + 0xd192e819 + words[44]; + y = f2(e, f, g); + h += x; + d = x + y; + x = c + f1(h, a, b) + 0xd6990624 + words[45]; + y = f2(d, e, f); + g += x; + c = x + y; + x = b + f1(g, h, a) + 0xf40e3585 + words[46]; + y = f2(c, d, e); + f += x; + b = x + y; + x = a + f1(f, g, h) + 0x106aa070 + words[47]; + y = f2(b, c, d); + e += x; + a = x + y; + + // extend to 56 words + for (; i < 56; i++) + words[i] = words[i - 16] + (rotate(words[i - 15], 7) ^ rotate(words[i - 15], 18) ^ (words[i - 15] >> 3)) + + words[i - 7] + (rotate(words[i - 2], 17) ^ rotate(words[i - 2], 19) ^ (words[i - 2] >> 10)); + + // seventh round + x = h + f1(e, f, g) + 0x19a4c116 + words[48]; + y = f2(a, b, c); + d += x; + h = x + y; + x = g + f1(d, e, f) + 0x1e376c08 + words[49]; + y = f2(h, a, b); + c += x; + g = x + y; + x = f + f1(c, d, e) + 0x2748774c + words[50]; + y = f2(g, h, a); + b += x; + f = x + y; + x = e + f1(b, c, d) + 0x34b0bcb5 + words[51]; + y = f2(f, g, h); + a += x; + e = x + y; + x = d + f1(a, b, c) + 0x391c0cb3 + words[52]; + y = f2(e, f, g); + h += x; + d = x + y; + x = c + f1(h, a, b) + 0x4ed8aa4a + words[53]; + y = f2(d, e, f); + g += x; + c = x + y; + x = b + f1(g, h, a) + 0x5b9cca4f + words[54]; + y = f2(c, d, e); + f += x; + b = x + y; + x = a + f1(f, g, h) + 0x682e6ff3 + words[55]; + y = f2(b, c, d); + e += x; + a = x + y; + + // extend to 64 words + for (; i < 64; i++) + words[i] = words[i - 16] + (rotate(words[i - 15], 7) ^ rotate(words[i - 15], 18) ^ (words[i - 15] >> 3)) + + words[i - 7] + (rotate(words[i - 2], 17) ^ rotate(words[i - 2], 19) ^ (words[i - 2] >> 10)); + + // eigth round + x = h + f1(e, f, g) + 0x748f82ee + words[56]; + y = f2(a, b, c); + d += x; + h = x + y; + x = g + f1(d, e, f) + 0x78a5636f + words[57]; + y = f2(h, a, b); + c += x; + g = x + y; + x = f + f1(c, d, e) + 0x84c87814 + words[58]; + y = f2(g, h, a); + b += x; + f = x + y; + x = e + f1(b, c, d) + 0x8cc70208 + words[59]; + y = f2(f, g, h); + a += x; + e = x + y; + x = d + f1(a, b, c) + 0x90befffa + words[60]; + y = f2(e, f, g); + h += x; + d = x + y; + x = c + f1(h, a, b) + 0xa4506ceb + words[61]; + y = f2(d, e, f); + g += x; + c = x + y; + x = b + f1(g, h, a) + 0xbef9a3f7 + words[62]; + y = f2(c, d, e); + f += x; + b = x + y; + x = a + f1(f, g, h) + 0xc67178f2 + words[63]; + y = f2(b, c, d); + e += x; + a = x + y; + + // update hash + m_hash[0] += a; + m_hash[1] += b; + m_hash[2] += c; + m_hash[3] += d; + m_hash[4] += e; + m_hash[5] += f; + m_hash[6] += g; + m_hash[7] += h; } - /// add arbitrary number of bytes -void SHA256::add(const void* data, size_t numBytes) -{ - const uint8_t* current = (const uint8_t*) data; - - if (m_bufferSize > 0) - { - while (numBytes > 0 && m_bufferSize < BlockSize) - { - m_buffer[m_bufferSize++] = *current++; - numBytes--; +void SHA256::add(const void* data, size_t numBytes) { + const uint8_t* current = (const uint8_t*)data; + + if (m_bufferSize > 0) { + while (numBytes > 0 && m_bufferSize < BlockSize) { + m_buffer[m_bufferSize++] = *current++; + numBytes--; + } } - } - // full buffer - if (m_bufferSize == BlockSize) - { - processBlock(m_buffer); - m_numBytes += BlockSize; - m_bufferSize = 0; - } - - // no more data ? - if (numBytes == 0) - return; - - // process full blocks - while (numBytes >= BlockSize) - { - processBlock(current); - current += BlockSize; - m_numBytes += BlockSize; - numBytes -= BlockSize; - } - - // keep remaining bytes in buffer - while (numBytes > 0) - { - m_buffer[m_bufferSize++] = *current++; - numBytes--; - } -} + // full buffer + if (m_bufferSize == BlockSize) { + processBlock(m_buffer); + m_numBytes += BlockSize; + m_bufferSize = 0; + } + // no more data ? + if (numBytes == 0) + return; -/// process final block, less than 64 bytes -void SHA256::processBuffer() -{ - // the input bytes are considered as bits strings, where the first bit is the most significant bit of the byte - - // - append "1" bit to message - // - append "0" bits until message length in bit mod 512 is 448 - // - append length as 64 bit integer - - // number of bits - size_t paddedLength = m_bufferSize * 8; - - // plus one bit set to 1 (always appended) - paddedLength++; - - // number of bits must be (numBits % 512) = 448 - size_t lower11Bits = paddedLength & 511; - if (lower11Bits <= 448) - paddedLength += 448 - lower11Bits; - else - paddedLength += 512 + 448 - lower11Bits; - // convert from bits to bytes - paddedLength /= 8; - - // only needed if additional data flows over into a second block - unsigned char extra[BlockSize]; - - // append a "1" bit, 128 => binary 10000000 - if (m_bufferSize < BlockSize) - m_buffer[m_bufferSize] = 128; - else - extra[0] = 128; - - size_t i; - for (i = m_bufferSize + 1; i < BlockSize; i++) - m_buffer[i] = 0; - for (; i < paddedLength; i++) - extra[i - BlockSize] = 0; - - // add message length in bits as 64 bit number - uint64_t msgBits = 8 * (m_numBytes + m_bufferSize); - // find right position - unsigned char* addLength; - if (paddedLength < BlockSize) - addLength = m_buffer + paddedLength; - else - addLength = extra + paddedLength - BlockSize; - - // must be big endian - *addLength++ = (unsigned char)((msgBits >> 56) & 0xFF); - *addLength++ = (unsigned char)((msgBits >> 48) & 0xFF); - *addLength++ = (unsigned char)((msgBits >> 40) & 0xFF); - *addLength++ = (unsigned char)((msgBits >> 32) & 0xFF); - *addLength++ = (unsigned char)((msgBits >> 24) & 0xFF); - *addLength++ = (unsigned char)((msgBits >> 16) & 0xFF); - *addLength++ = (unsigned char)((msgBits >> 8) & 0xFF); - *addLength = (unsigned char)( msgBits & 0xFF); - - // process blocks - processBlock(m_buffer); - // flowed over into a second block ? - if (paddedLength > BlockSize) - processBlock(extra); + // process full blocks + while (numBytes >= BlockSize) { + processBlock(current); + current += BlockSize; + m_numBytes += BlockSize; + numBytes -= BlockSize; + } + + // keep remaining bytes in buffer + while (numBytes > 0) { + m_buffer[m_bufferSize++] = *current++; + numBytes--; + } } +/// process final block, less than 64 bytes +void SHA256::processBuffer() { + // the input bytes are considered as bits strings, where the first bit is the most significant bit of the byte + + // - append "1" bit to message + // - append "0" bits until message length in bit mod 512 is 448 + // - append length as 64 bit integer + + // number of bits + size_t paddedLength = m_bufferSize * 8; + + // plus one bit set to 1 (always appended) + paddedLength++; + + // number of bits must be (numBits % 512) = 448 + size_t lower11Bits = paddedLength & 511; + if (lower11Bits <= 448) + paddedLength += 448 - lower11Bits; + else + paddedLength += 512 + 448 - lower11Bits; + // convert from bits to bytes + paddedLength /= 8; + + // only needed if additional data flows over into a second block + unsigned char extra[BlockSize]; + + // append a "1" bit, 128 => binary 10000000 + if (m_bufferSize < BlockSize) + m_buffer[m_bufferSize] = 128; + else + extra[0] = 128; + + size_t i; + for (i = m_bufferSize + 1; i < BlockSize; i++) + m_buffer[i] = 0; + for (; i < paddedLength; i++) + extra[i - BlockSize] = 0; + + // add message length in bits as 64 bit number + uint64_t msgBits = 8 * (m_numBytes + m_bufferSize); + // find right position + unsigned char* addLength; + if (paddedLength < BlockSize) + addLength = m_buffer + paddedLength; + else + addLength = extra + paddedLength - BlockSize; + + // must be big endian + *addLength++ = (unsigned char)((msgBits >> 56) & 0xFF); + *addLength++ = (unsigned char)((msgBits >> 48) & 0xFF); + *addLength++ = (unsigned char)((msgBits >> 40) & 0xFF); + *addLength++ = (unsigned char)((msgBits >> 32) & 0xFF); + *addLength++ = (unsigned char)((msgBits >> 24) & 0xFF); + *addLength++ = (unsigned char)((msgBits >> 16) & 0xFF); + *addLength++ = (unsigned char)((msgBits >> 8) & 0xFF); + *addLength = (unsigned char)(msgBits & 0xFF); + + // process blocks + processBlock(m_buffer); + // flowed over into a second block ? + if (paddedLength > BlockSize) + processBlock(extra); +} /// return latest hash as 64 hex characters -std::string SHA256::getHash() -{ - // compute hash (as raw bytes) - unsigned char rawHash[HashBytes]; - getHash(rawHash); - - // convert to hex string - std::string result; - result.reserve(2 * HashBytes); - for (int i = 0; i < HashBytes; i++) - { - static const char dec2hex[16+1] = "0123456789abcdef"; - result += dec2hex[(rawHash[i] >> 4) & 15]; - result += dec2hex[ rawHash[i] & 15]; - } - - return result; -} +std::string SHA256::getHash() { + // compute hash (as raw bytes) + unsigned char rawHash[HashBytes]; + getHash(rawHash); + + // convert to hex string + std::string result; + result.reserve(2 * HashBytes); + for (int i = 0; i < HashBytes; i++) { + static const char dec2hex[16 + 1] = "0123456789abcdef"; + result += dec2hex[(rawHash[i] >> 4) & 15]; + result += dec2hex[rawHash[i] & 15]; + } + return result; +} /// return latest hash as bytes -void SHA256::getHash(unsigned char buffer[SHA256::HashBytes]) -{ - // save old hash if buffer is partially filled - uint32_t oldHash[HashValues]; - for (int i = 0; i < HashValues; i++) - oldHash[i] = m_hash[i]; - - // process remaining bytes - processBuffer(); - - unsigned char* current = buffer; - for (int i = 0; i < HashValues; i++) - { - *current++ = (m_hash[i] >> 24) & 0xFF; - *current++ = (m_hash[i] >> 16) & 0xFF; - *current++ = (m_hash[i] >> 8) & 0xFF; - *current++ = m_hash[i] & 0xFF; - - // restore old hash - m_hash[i] = oldHash[i]; - } +void SHA256::getHash(unsigned char buffer[SHA256::HashBytes]) { + // save old hash if buffer is partially filled + uint32_t oldHash[HashValues]; + for (int i = 0; i < HashValues; i++) + oldHash[i] = m_hash[i]; + + // process remaining bytes + processBuffer(); + + unsigned char* current = buffer; + for (int i = 0; i < HashValues; i++) { + *current++ = (m_hash[i] >> 24) & 0xFF; + *current++ = (m_hash[i] >> 16) & 0xFF; + *current++ = (m_hash[i] >> 8) & 0xFF; + *current++ = m_hash[i] & 0xFF; + + // restore old hash + m_hash[i] = oldHash[i]; + } } - /// compute SHA256 of a memory block -std::string SHA256::operator()(const void* data, size_t numBytes) -{ - reset(); - add(data, numBytes); - return getHash(); +std::string SHA256::operator()(const void* data, size_t numBytes) { + reset(); + add(data, numBytes); + return getHash(); } - /// compute SHA256 of a string, excluding final zero -std::string SHA256::operator()(const std::string& text) -{ - reset(); - add(text.c_str(), text.size()); - return getHash(); +std::string SHA256::operator()(const std::string& text) { + reset(); + add(text.c_str(), text.size()); + return getHash(); } diff --git a/CMakeLists.txt b/CMakeLists.txt index fe1c7aa..196e739 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.11) -project(slac VERSION 0.2.0 +project(slac VERSION 0.3.0 DESCRIPTION "Simple ISO15118-3 SLAC implementation" LANGUAGES CXX C ) diff --git a/include/slac/slac.hpp b/include/slac/slac.hpp index 536866b..6c89ce5 100644 --- a/include/slac/slac.hpp +++ b/include/slac/slac.hpp @@ -3,8 +3,10 @@ #ifndef SLAC_SLAC_HPP #define SLAC_SLAC_HPP +#include +#include + #include -#include namespace slac { @@ -16,7 +18,11 @@ namespace defs { const uint16_t ETH_P_HOMEPLUG_GREENPHY = 0x88E1; -const uint8_t MMV_HOMEPLUG_GREENPHY = 0x01; +enum class MMV : uint8_t { + AV_1_0 = 0x0, + AV_1_1 = 0x1, + AV_2_0 = 0x2, +}; const int MME_MIN_LENGTH = 60; @@ -57,6 +63,23 @@ const uint16_t MMTYPE_CM_VALIDATE = 0x6078; const uint16_t MMTYPE_CM_SLAC_MATCH = 0x607C; const uint16_t MMTYPE_CM_ATTEN_PROFILE = 0x6084; +// Qualcomm Vendor MMEs +namespace qualcomm { +const uint16_t MMTYPE_CM_RESET_DEVICE = 0xA01C; +const uint16_t MMTYPE_LINK_STATUS = 0xA0B8; +const uint16_t MMTYPE_OP_ATTR = 0xA068; +const uint16_t MMTYPE_NW_INFO = 0xA038; +const uint16_t MMTYPE_GET_SW = 0xA000; +} // namespace qualcomm + +// Lumissil Vendor MMEs +namespace lumissil { +const uint16_t MMTYPE_NSCM_RESET_DEVICE = 0xAC70; +const uint16_t MMTYPE_NSCM_GET_VERSION = 0xAC6C; +const uint16_t MMTYPE_NSCM_GET_D_LINK_STATUS = 0xAC9C; +} // namespace lumissil + +// Standard mmtypes const uint16_t MMTYPE_MODE_REQ = 0x0000; const uint16_t MMTYPE_MODE_CNF = 0x0001; const uint16_t MMTYPE_MODE_IND = 0x0002; @@ -113,37 +136,41 @@ typedef struct { struct { uint8_t mmv; // management message version uint16_t mmtype; // management message type - uint8_t fmni; // fragmentation management number information - uint8_t fmsn; // fragmentation message sequence number + } __attribute__((packed)) homeplug_header; // the rest of this message is potentially payload data - uint8_t mmentry[ETH_FRAME_LEN - ETH_HLEN - sizeof(homeplug_header)]; + uint8_t payload[ETH_FRAME_LEN - ETH_HLEN - sizeof(homeplug_header)]; } __attribute__((packed)) homeplug_message; +typedef struct { + uint8_t fmni; // fragmentation management number information + uint8_t fmsn; // fragmentation message sequence number +} __attribute__((packed)) homeplug_fragmentation_part; + class HomeplugMessage { public: - HomeplugMessage() { - raw_msg.homeplug_header.fmni = 0; // not used - raw_msg.homeplug_header.fmsn = 0; // not used - } - - homeplug_message& get_raw_message() { - return raw_msg; + homeplug_message* get_raw_message_ptr() { + return &raw_msg; }; int get_raw_msg_len() const { return raw_msg_len; } - void setup_payload(void* payload, int len, uint16_t mmtype); + void setup_payload(void const* payload, int len, uint16_t mmtype, const defs::MMV mmv); void setup_ethernet_header(const uint8_t dst_mac_addr[ETH_ALEN], const uint8_t src_mac_addr[ETH_ALEN] = nullptr); - uint16_t get_mmtype(); - const uint8_t* get_src_mac(); + uint16_t get_mmtype() const; + uint8_t* get_src_mac(); template const T& get_payload() { - return *reinterpret_cast(raw_msg.mmentry); + if (raw_msg.homeplug_header.mmv == static_cast>(defs::MMV::AV_1_0)) { + return *reinterpret_cast(raw_msg.payload); + } + + // if not av 1.0 message, we need to shift by the fragmentation part + return *reinterpret_cast(raw_msg.payload + sizeof(homeplug_fragmentation_part)); } bool is_valid() const; @@ -153,6 +180,7 @@ class HomeplugMessage { private: homeplug_message raw_msg; + int raw_msg_len{-1}; bool keep_src_mac{false}; }; @@ -301,6 +329,102 @@ typedef struct { uint8_t cco_capability; } __attribute__((packed)) cm_set_key_cnf; +namespace qualcomm { + +typedef struct { + uint8_t vendor_mme[3] = {0x00, 0xb0, 0x52}; // Qualcomm Vendor MME code +} __attribute__((packed)) cm_reset_device_req; + +typedef struct { + uint8_t vendor_mme[3]; // Vendor MME code + uint8_t success; +} __attribute__((packed)) cm_reset_device_cnf; + +typedef struct { + uint8_t vendor_mme[3] = {0x00, 0xb0, 0x52}; // Qualcomm Vendor MME code +} __attribute__((packed)) link_status_req; + +typedef struct { + uint8_t vendor_mme[3]; // Vendor MME code + uint8_t reserved; + uint8_t link_status; +} __attribute__((packed)) link_status_cnf; + +typedef struct { + uint8_t vendor_mme[3] = {0x00, 0xb0, 0x52}; // Qualcomm Vendor MME code + uint32_t cookie{0x12345}; // some cookie we will also get in the reply + uint8_t report_type{0}; // binary report +} __attribute__((packed)) op_attr_req; + +typedef struct { + uint8_t vendor_mme[3]; // Vendor MME code + uint16_t success; // 0x00 means success + uint32_t cookie; + uint8_t report_type; // should be 0x00 (binary) + uint16_t size; // should be 118, otherwise we do not know the structure + uint8_t hw_platform[16]; + uint8_t sw_platform[16]; + uint32_t version_major; + uint32_t version_minor; + uint32_t version_pib; + uint32_t version_build; + uint32_t reserved; + uint8_t build_date[8]; + uint8_t release_type[12]; + uint8_t sdram_type; + uint8_t reserved2; + uint8_t line_freq_zc; + uint32_t sdram_size; + uint8_t authorization_mode; +} __attribute__((packed)) op_attr_cnf; + +} // namespace qualcomm + +namespace lumissil { + +typedef struct { + uint16_t version; + uint32_t reserved; + uint8_t request_id; + uint8_t reserved2[12]; +} __attribute__((packed)) lms_header; + +typedef struct { + uint8_t vendor_mme[3] = {0x00, 0x16, 0xE8}; // Lumissil Vendor MME code + lms_header lms; + uint8_t mode{0}; // Normal reset +} __attribute__((packed)) nscm_reset_device_req; + +typedef struct { + uint8_t vendor_mme[3] = {0x00, 0x16, 0xE8}; // Lumissil Vendor MME code + lms_header lms; +} __attribute__((packed)) nscm_get_version_req; + +typedef struct { + uint8_t vendor_mme[3] = {0x00, 0x16, 0xE8}; // Lumissil Vendor MME code + lms_header lms; + uint16_t version_major; + uint16_t version_minor; + uint16_t version_patch; + uint16_t version_build; + uint16_t reserved; +} __attribute__((packed)) nscm_get_version_cnf; + +typedef struct { + uint8_t vendor_mme[3] = {0x00, 0x16, 0xE8}; // Lumissil Vendor MME code + lms_header lms; +} __attribute__((packed)) nscm_get_d_link_status_req; + +typedef struct { + uint8_t vendor_mme[3] = {0x00, 0x16, 0xE8}; // Lumissil Vendor MME code + lms_header lms; + uint8_t link_status; +} __attribute__((packed)) nscm_get_d_link_status_cnf; + +// There is no CNF for this reset packet + +} // namespace lumissil + } // namespace messages } // namespace slac diff --git a/src/channel.cpp b/src/channel.cpp index e64a2d4..811b643 100644 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -38,7 +38,7 @@ bool Channel::read(slac::messages::HomeplugMessage& msg, int timeout) { did_timeout = false; using IOResult = ::utils::PacketSocket::IOResult; if (socket) { - switch (socket->read(reinterpret_cast(&msg.get_raw_message()), timeout)) { + switch (socket->read(reinterpret_cast(msg.get_raw_message_ptr()), timeout)) { // FIXME (aw): this enum conversion looks ugly case IOResult::Failure: error = socket->get_error(); @@ -63,11 +63,11 @@ bool Channel::write(slac::messages::HomeplugMessage& msg, int timeout) { did_timeout = false; if (socket) { - auto& raw_msg = msg.get_raw_message(); + auto raw_msg_ether_shost = msg.get_src_mac(); if (!msg.keep_source_mac()) { - memcpy(raw_msg.ethernet_header.ether_shost, orig_if_mac, sizeof(orig_if_mac)); + memcpy(raw_msg_ether_shost, orig_if_mac, sizeof(orig_if_mac)); } - switch (socket->write(&raw_msg, msg.get_raw_msg_len(), timeout)) { + switch (socket->write(msg.get_raw_message_ptr(), msg.get_raw_msg_len(), timeout)) { case IOResult::Failure: error = socket->get_error(); return false; diff --git a/src/slac.cpp b/src/slac.cpp index e12126d..f8f7972 100644 --- a/src/slac.cpp +++ b/src/slac.cpp @@ -65,30 +65,51 @@ void generate_nid_from_nmk(uint8_t nid[slac::defs::NID_LEN], const uint8_t nmk[s } // namespace utils namespace messages { -void HomeplugMessage::setup_payload(void* payload, int len, uint16_t mmtype) { - assert(("Homeplug Payload length too long", len < sizeof(raw_msg.mmentry))); - // setup homeplug mme header - raw_msg.homeplug_header.mmv = defs::MMV_HOMEPLUG_GREENPHY; +static constexpr auto effective_payload_length(const defs::MMV mmv) { + if (mmv == defs::MMV::AV_1_0) { + return sizeof(homeplug_message::payload); + } else { + return sizeof(homeplug_message::payload) - sizeof(homeplug_fragmentation_part); + } +} + +void HomeplugMessage::setup_payload(void const* payload, int len, uint16_t mmtype, const defs::MMV mmv) { + // FIXME (aw): shouldn't this assert test for "<="? Furthermore it will just crash the client code ... + assert(("Homeplug Payload length too long", len < effective_payload_length(mmv))); + raw_msg.homeplug_header.mmv = static_cast>(mmv); raw_msg.homeplug_header.mmtype = htole16(mmtype); - raw_msg.homeplug_header.fmni = 0; // not used - raw_msg.homeplug_header.fmsn = 0; // not used - // copy payload - memcpy(raw_msg.mmentry, payload, len); + uint8_t* dst = raw_msg.payload; - // set the message size to at least MME_MIN_LENGTH - int padding_len = defs::MME_MIN_LENGTH - (sizeof(raw_msg.ethernet_header) + sizeof(raw_msg.homeplug_header) + len); - if (padding_len > 0) { - memset(raw_msg.mmentry + len, 0x00, padding_len); + if (mmv != defs::MMV::AV_1_0) { + homeplug_fragmentation_part fragmentation_part{}; + fragmentation_part.fmni = 0; // not implemented + fragmentation_part.fmsn = 0; // not implemented + memcpy(dst, &fragmentation_part, sizeof(fragmentation_part)); + dst += sizeof(fragmentation_part); // adjust effective payload start } - raw_msg_len = - std::max(sizeof(raw_msg.ethernet_header) + sizeof(raw_msg.homeplug_header) + len, (size_t)defs::MME_MIN_LENGTH); + // copy payload into place + memcpy(dst, payload, len); + + // get pointer to the end of buffer + uint8_t* dst_end = dst + len; + + // calculate raw message length + raw_msg_len = dst_end - reinterpret_cast(&raw_msg); + + // do padding + auto padding_len = defs::MME_MIN_LENGTH - raw_msg_len; + if (padding_len > 0) { + memset(dst_end, 0x00, padding_len); + raw_msg_len = defs::MME_MIN_LENGTH; + } } void HomeplugMessage::setup_ethernet_header(const uint8_t dst_mac_addr[ETH_ALEN], const uint8_t src_mac_addr[ETH_ALEN]) { + // ethernet frame byte order is big endian raw_msg.ethernet_header.ether_type = htons(defs::ETH_P_HOMEPLUG_GREENPHY); if (dst_mac_addr) { @@ -103,11 +124,11 @@ void HomeplugMessage::setup_ethernet_header(const uint8_t dst_mac_addr[ETH_ALEN] } } -uint16_t HomeplugMessage::get_mmtype() { +uint16_t HomeplugMessage::get_mmtype() const { return le16toh(raw_msg.homeplug_header.mmtype); } -const uint8_t* HomeplugMessage::get_src_mac() { +uint8_t* HomeplugMessage::get_src_mac() { return raw_msg.ethernet_header.ether_shost; }