1 /* 2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "SHA256.h" 8 9 #include <stdio.h> 10 #include <string.h> 11 12 #include <ByteOrder.h> 13 14 15 namespace BPrivate { 16 17 18 static const uint32 kChunkSize = 64; // 64 bytes == 512 bits 19 20 static const uint32 kRounds[64] = { 21 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 22 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 23 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 24 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 25 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 26 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 27 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 28 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 29 }; 30 static const uint32 kHash[8] = { 31 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 32 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 33 }; 34 35 36 static inline uint32 37 rotate_right(uint32 value, int bits) 38 { 39 return (value >> bits) | (value << (32 - bits)); 40 } 41 42 43 // #pragma mark - 44 45 46 SHA256::SHA256() 47 { 48 Init(); 49 } 50 51 52 SHA256::~SHA256() 53 { 54 } 55 56 57 void 58 SHA256::Init() 59 { 60 memcpy(fHash, kHash, sizeof(kHash)); 61 62 fBytesInBuffer = 0; 63 fMessageSize = 0; 64 fDigested = false; 65 } 66 67 68 void 69 SHA256::Update(const void* _buffer, size_t size) 70 { 71 const uint8* buffer = (const uint8*)_buffer; 72 fMessageSize += size; 73 74 while (fBytesInBuffer + size >= kChunkSize) { 75 size_t toCopy = kChunkSize - fBytesInBuffer; 76 memcpy((uint8*)fBuffer + fBytesInBuffer, buffer, toCopy); 77 buffer += toCopy; 78 size -= toCopy; 79 80 _ProcessChunk(); 81 fBytesInBuffer = 0; 82 } 83 84 if (size > 0) { 85 memcpy((uint8*)fBuffer + fBytesInBuffer, buffer, size); 86 fBytesInBuffer += size; 87 } 88 } 89 90 91 const uint8* 92 SHA256::Digest() 93 { 94 if (!fDigested) { 95 // We need to append a 1 bit, append padding with 0 bits, and append 96 // the message size in bits (64 bit big-endian int), so that the whole 97 // is chunk-aligned. So we either have to process one last chunk or two 98 // chunks. 99 100 // append the 1 bit 101 ((uint8*)fBuffer)[fBytesInBuffer] = 0x80; 102 fBytesInBuffer++; 103 104 // if the message size doesn't fit anymore, we pad the chunk and 105 // process it 106 if (fBytesInBuffer > kChunkSize - 8) { 107 memset((uint8*)fBuffer + fBytesInBuffer, 0, 108 kChunkSize - fBytesInBuffer); 109 _ProcessChunk(); 110 fBytesInBuffer = 0; 111 } 112 113 // pad the buffer 114 if (fBytesInBuffer < kChunkSize - 8) { 115 memset((uint8*)fBuffer + fBytesInBuffer, 0, 116 kChunkSize - 8 - fBytesInBuffer); 117 } 118 119 // write the (big-endian) message size in bits 120 uint64* target = (uint64*)((uint8*)fBuffer + kChunkSize - 8); 121 *target = B_HOST_TO_BENDIAN_INT64((uint64)fMessageSize * 8); 122 123 _ProcessChunk(); 124 125 // set digest 126 for (int i = 0; i < 8; i++) 127 fDigest[i] = B_HOST_TO_BENDIAN_INT32(fHash[i]); 128 129 fDigested = true; 130 } 131 132 return (uint8*)fDigest; 133 } 134 135 136 void 137 SHA256::_ProcessChunk() 138 { 139 // convert endianess -- the data are supposed to be a stream of 140 // 32 bit big-endian integers 141 #if B_HOST_IS_LENDIAN 142 for (int i = 0; i < (int)kChunkSize / 4; i++) 143 fBuffer[i] = B_SWAP_INT32(fBuffer[i]); 144 #endif 145 146 // pre-process buffer (extend to 64 elements) 147 for (int i = 16; i < 64; i++) { 148 uint32 v0 = fBuffer[i - 15]; 149 uint32 v1 = fBuffer[i - 2]; 150 uint32 s0 = rotate_right(v0, 7) ^ rotate_right(v0, 18) ^ (v0 >> 3); 151 uint32 s1 = rotate_right(v1, 17) ^ rotate_right(v1, 19) ^ (v1 >> 10); 152 fBuffer[i] = fBuffer[i - 16] + s0 + fBuffer[i - 7] + s1; 153 } 154 155 uint32 a = fHash[0]; 156 uint32 b = fHash[1]; 157 uint32 c = fHash[2]; 158 uint32 d = fHash[3]; 159 uint32 e = fHash[4]; 160 uint32 f = fHash[5]; 161 uint32 g = fHash[6]; 162 uint32 h = fHash[7]; 163 164 // process the buffer 165 for (int i = 0; i < 64; i++) { 166 uint32 s0 = rotate_right(a, 2) ^ rotate_right(a, 13) 167 ^ rotate_right(a, 22); 168 uint32 maj = (a & b) ^ (a & c) ^ (b & c); 169 uint32 t2 = s0 + maj; 170 uint32 s1 = rotate_right(e, 6) ^ rotate_right(e, 11) 171 ^ rotate_right(e, 25); 172 uint32 ch = (e & f) ^ (~e & g); 173 uint32 t1 = h + s1 + ch + kRounds[i] + fBuffer[i]; 174 175 h = g; 176 g = f; 177 f = e; 178 e = d + t1; 179 d = c; 180 c = b; 181 b = a; 182 a = t1 + t2; 183 } 184 185 fHash[0] += a; 186 fHash[1] += b; 187 fHash[2] += c; 188 fHash[3] += d; 189 fHash[4] += e; 190 fHash[5] += f; 191 fHash[6] += g; 192 fHash[7] += h; 193 } 194 195 196 } // namespace BPrivate 197