2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
12 #include <ByteOrder.h>
18 static const uint32 kChunkSize
= 64; // 64 bytes == 512 bits
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
30 static const uint32 kHash
[8] = {
31 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
32 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
37 rotate_right(uint32 value
, int bits
)
39 return (value
>> bits
) | (value
<< (32 - bits
));
60 memcpy(fHash
, kHash
, sizeof(kHash
));
69 SHA256::Update(const void* _buffer
, size_t size
)
71 const uint8
* buffer
= (const uint8
*)_buffer
;
74 while (fBytesInBuffer
+ size
>= kChunkSize
) {
75 size_t toCopy
= kChunkSize
- fBytesInBuffer
;
76 memcpy((uint8
*)fBuffer
+ fBytesInBuffer
, buffer
, toCopy
);
85 memcpy((uint8
*)fBuffer
+ fBytesInBuffer
, buffer
, size
);
86 fBytesInBuffer
+= size
;
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
101 ((uint8
*)fBuffer
)[fBytesInBuffer
] = 0x80;
104 // if the message size doesn't fit anymore, we pad the chunk and
106 if (fBytesInBuffer
> kChunkSize
- 8) {
107 memset((uint8
*)fBuffer
+ fBytesInBuffer
, 0,
108 kChunkSize
- fBytesInBuffer
);
114 if (fBytesInBuffer
< kChunkSize
- 8) {
115 memset((uint8
*)fBuffer
+ fBytesInBuffer
, 0,
116 kChunkSize
- 8 - fBytesInBuffer
);
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);
126 for (int i
= 0; i
< 8; i
++)
127 fDigest
[i
] = B_HOST_TO_BENDIAN_INT32(fHash
[i
]);
132 return (uint8
*)fDigest
;
137 SHA256::_ProcessChunk()
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
]);
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
;
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
];
196 } // namespace BPrivate