blob: e1346f427f265bb4f07064a299d4c24bc4154f68 [file] [log] [blame]
Brian Silverman41cdd3e2019-01-19 19:48:58 -08001/*
2 sha1.cpp - source code of
3
4 ============
5 SHA-1 in C++
6 ============
7
8 100% Public Domain.
9
10 Original C Code
11 -- Steve Reid <steve@edmweb.com>
12 Small changes to fit into bglibs
13 -- Bruce Guenter <bruce@untroubled.org>
14 Translation to simpler C++ Code
15 -- Volker Grabsch <vog@notjusthosting.com>
16 Safety fixes
17 -- Eugene Hopkinson <slowriot at voxelstorm dot com>
18*/
19
20#include "wpi/sha1.h"
21
22#include "wpi/SmallVector.h"
23#include "wpi/StringExtras.h"
24#include "wpi/raw_istream.h"
25#include "wpi/raw_ostream.h"
26
27using namespace wpi;
28
29static const size_t BLOCK_INTS =
30 16; /* number of 32bit integers per SHA1 block */
31static const size_t BLOCK_BYTES = BLOCK_INTS * 4;
32
33static void reset(uint32_t digest[], size_t& buf_size, uint64_t& transforms) {
34 /* SHA1 initialization constants */
35 digest[0] = 0x67452301;
36 digest[1] = 0xefcdab89;
37 digest[2] = 0x98badcfe;
38 digest[3] = 0x10325476;
39 digest[4] = 0xc3d2e1f0;
40
41 /* Reset counters */
42 buf_size = 0;
43 transforms = 0;
44}
45
46static uint32_t rol(const uint32_t value, const size_t bits) {
47 return (value << bits) | (value >> (32 - bits));
48}
49
50static uint32_t blk(const uint32_t block[BLOCK_INTS], const size_t i) {
51 return rol(block[(i + 13) & 15] ^ block[(i + 8) & 15] ^ block[(i + 2) & 15] ^
52 block[i],
53 1);
54}
55
56/*
57 * (R0+R1), R2, R3, R4 are the different operations used in SHA1
58 */
59
60static void R0(const uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t& w,
61 const uint32_t x, const uint32_t y, uint32_t& z,
62 const size_t i) {
63 z += ((w & (x ^ y)) ^ y) + block[i] + 0x5a827999 + rol(v, 5);
64 w = rol(w, 30);
65}
66
67static void R1(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t& w,
68 const uint32_t x, const uint32_t y, uint32_t& z,
69 const size_t i) {
70 block[i] = blk(block, i);
71 z += ((w & (x ^ y)) ^ y) + block[i] + 0x5a827999 + rol(v, 5);
72 w = rol(w, 30);
73}
74
75static void R2(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t& w,
76 const uint32_t x, const uint32_t y, uint32_t& z,
77 const size_t i) {
78 block[i] = blk(block, i);
79 z += (w ^ x ^ y) + block[i] + 0x6ed9eba1 + rol(v, 5);
80 w = rol(w, 30);
81}
82
83static void R3(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t& w,
84 const uint32_t x, const uint32_t y, uint32_t& z,
85 const size_t i) {
86 block[i] = blk(block, i);
87 z += (((w | x) & y) | (w & x)) + block[i] + 0x8f1bbcdc + rol(v, 5);
88 w = rol(w, 30);
89}
90
91static void R4(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t& w,
92 const uint32_t x, const uint32_t y, uint32_t& z,
93 const size_t i) {
94 block[i] = blk(block, i);
95 z += (w ^ x ^ y) + block[i] + 0xca62c1d6 + rol(v, 5);
96 w = rol(w, 30);
97}
98
99/*
100 * Hash a single 512-bit block. This is the core of the algorithm.
101 */
102
103static void do_transform(uint32_t digest[], uint32_t block[BLOCK_INTS],
104 uint64_t& transforms) {
105 /* Copy digest[] to working vars */
106 uint32_t a = digest[0];
107 uint32_t b = digest[1];
108 uint32_t c = digest[2];
109 uint32_t d = digest[3];
110 uint32_t e = digest[4];
111
112 /* 4 rounds of 20 operations each. Loop unrolled. */
113 R0(block, a, b, c, d, e, 0);
114 R0(block, e, a, b, c, d, 1);
115 R0(block, d, e, a, b, c, 2);
116 R0(block, c, d, e, a, b, 3);
117 R0(block, b, c, d, e, a, 4);
118 R0(block, a, b, c, d, e, 5);
119 R0(block, e, a, b, c, d, 6);
120 R0(block, d, e, a, b, c, 7);
121 R0(block, c, d, e, a, b, 8);
122 R0(block, b, c, d, e, a, 9);
123 R0(block, a, b, c, d, e, 10);
124 R0(block, e, a, b, c, d, 11);
125 R0(block, d, e, a, b, c, 12);
126 R0(block, c, d, e, a, b, 13);
127 R0(block, b, c, d, e, a, 14);
128 R0(block, a, b, c, d, e, 15);
129 R1(block, e, a, b, c, d, 0);
130 R1(block, d, e, a, b, c, 1);
131 R1(block, c, d, e, a, b, 2);
132 R1(block, b, c, d, e, a, 3);
133 R2(block, a, b, c, d, e, 4);
134 R2(block, e, a, b, c, d, 5);
135 R2(block, d, e, a, b, c, 6);
136 R2(block, c, d, e, a, b, 7);
137 R2(block, b, c, d, e, a, 8);
138 R2(block, a, b, c, d, e, 9);
139 R2(block, e, a, b, c, d, 10);
140 R2(block, d, e, a, b, c, 11);
141 R2(block, c, d, e, a, b, 12);
142 R2(block, b, c, d, e, a, 13);
143 R2(block, a, b, c, d, e, 14);
144 R2(block, e, a, b, c, d, 15);
145 R2(block, d, e, a, b, c, 0);
146 R2(block, c, d, e, a, b, 1);
147 R2(block, b, c, d, e, a, 2);
148 R2(block, a, b, c, d, e, 3);
149 R2(block, e, a, b, c, d, 4);
150 R2(block, d, e, a, b, c, 5);
151 R2(block, c, d, e, a, b, 6);
152 R2(block, b, c, d, e, a, 7);
153 R3(block, a, b, c, d, e, 8);
154 R3(block, e, a, b, c, d, 9);
155 R3(block, d, e, a, b, c, 10);
156 R3(block, c, d, e, a, b, 11);
157 R3(block, b, c, d, e, a, 12);
158 R3(block, a, b, c, d, e, 13);
159 R3(block, e, a, b, c, d, 14);
160 R3(block, d, e, a, b, c, 15);
161 R3(block, c, d, e, a, b, 0);
162 R3(block, b, c, d, e, a, 1);
163 R3(block, a, b, c, d, e, 2);
164 R3(block, e, a, b, c, d, 3);
165 R3(block, d, e, a, b, c, 4);
166 R3(block, c, d, e, a, b, 5);
167 R3(block, b, c, d, e, a, 6);
168 R3(block, a, b, c, d, e, 7);
169 R3(block, e, a, b, c, d, 8);
170 R3(block, d, e, a, b, c, 9);
171 R3(block, c, d, e, a, b, 10);
172 R3(block, b, c, d, e, a, 11);
173 R4(block, a, b, c, d, e, 12);
174 R4(block, e, a, b, c, d, 13);
175 R4(block, d, e, a, b, c, 14);
176 R4(block, c, d, e, a, b, 15);
177 R4(block, b, c, d, e, a, 0);
178 R4(block, a, b, c, d, e, 1);
179 R4(block, e, a, b, c, d, 2);
180 R4(block, d, e, a, b, c, 3);
181 R4(block, c, d, e, a, b, 4);
182 R4(block, b, c, d, e, a, 5);
183 R4(block, a, b, c, d, e, 6);
184 R4(block, e, a, b, c, d, 7);
185 R4(block, d, e, a, b, c, 8);
186 R4(block, c, d, e, a, b, 9);
187 R4(block, b, c, d, e, a, 10);
188 R4(block, a, b, c, d, e, 11);
189 R4(block, e, a, b, c, d, 12);
190 R4(block, d, e, a, b, c, 13);
191 R4(block, c, d, e, a, b, 14);
192 R4(block, b, c, d, e, a, 15);
193
194 /* Add the working vars back into digest[] */
195 digest[0] += a;
196 digest[1] += b;
197 digest[2] += c;
198 digest[3] += d;
199 digest[4] += e;
200
201 /* Count the number of transformations */
202 transforms++;
203}
204
205static void buffer_to_block(const unsigned char* buffer,
206 uint32_t block[BLOCK_INTS]) {
207 /* Convert the std::string (byte buffer) to a uint32_t array (MSB) */
208 for (size_t i = 0; i < BLOCK_INTS; i++) {
209 block[i] = (buffer[4 * i + 3] & 0xff) | (buffer[4 * i + 2] & 0xff) << 8 |
210 (buffer[4 * i + 1] & 0xff) << 16 |
211 (buffer[4 * i + 0] & 0xff) << 24;
212 }
213}
214
215SHA1::SHA1() { reset(digest, buf_size, transforms); }
216
217void SHA1::Update(StringRef s) {
218 raw_mem_istream is(makeArrayRef(s.data(), s.size()));
219 Update(is);
220}
221
222void SHA1::Update(raw_istream& is) {
223 while (true) {
224 buf_size += is.readsome(&buffer[buf_size], BLOCK_BYTES - buf_size);
225 if (buf_size != BLOCK_BYTES) {
226 return;
227 }
228 uint32_t block[BLOCK_INTS];
229 buffer_to_block(buffer, block);
230 do_transform(digest, block, transforms);
231 buf_size = 0;
232 }
233}
234
235/*
236 * Add padding and return the message digest.
237 */
238
239static void finalize(uint32_t digest[], unsigned char* buffer, size_t& buf_size,
240 uint64_t& transforms, raw_ostream& os, bool hex) {
241 /* Total number of hashed bits */
242 uint64_t total_bits = (transforms * BLOCK_BYTES + buf_size) * 8;
243
244 /* Padding */
245 buffer[buf_size++] = 0x80;
246 for (size_t i = buf_size; i < BLOCK_BYTES; ++i) {
247 buffer[i] = 0x00;
248 }
249
250 uint32_t block[BLOCK_INTS];
251 buffer_to_block(buffer, block);
252
253 if (buf_size > BLOCK_BYTES - 8) {
254 do_transform(digest, block, transforms);
255 for (size_t i = 0; i < BLOCK_INTS - 2; i++) {
256 block[i] = 0;
257 }
258 }
259
260 /* Append total_bits, split this uint64_t into two uint32_t */
261 block[BLOCK_INTS - 1] = total_bits;
262 block[BLOCK_INTS - 2] = (total_bits >> 32);
263 do_transform(digest, block, transforms);
264
265 /* Hex string */
266 static const char* const LUT = "0123456789abcdef";
267 for (size_t i = 0; i < 5; i++) {
268 uint32_t v = digest[i];
269 if (hex) {
270 os << LUT[(v >> 28) & 0xf] << LUT[(v >> 24) & 0xf] << LUT[(v >> 20) & 0xf]
271 << LUT[(v >> 16) & 0xf] << LUT[(v >> 12) & 0xf] << LUT[(v >> 8) & 0xf]
272 << LUT[(v >> 4) & 0xf] << LUT[(v >> 0) & 0xf];
273 } else {
274 os.write(static_cast<unsigned char>((v >> 24) & 0xff));
275 os.write(static_cast<unsigned char>((v >> 16) & 0xff));
276 os.write(static_cast<unsigned char>((v >> 8) & 0xff));
277 os.write(static_cast<unsigned char>((v >> 0) & 0xff));
278 }
279 }
280
281 /* Reset for next run */
282 reset(digest, buf_size, transforms);
283}
284
285std::string SHA1::Final() {
286 std::string out;
287 raw_string_ostream os(out);
288
289 finalize(digest, buffer, buf_size, transforms, os, true);
290
291 return os.str();
292}
293
294StringRef SHA1::Final(SmallVectorImpl<char>& buf) {
295 raw_svector_ostream os(buf);
296
297 finalize(digest, buffer, buf_size, transforms, os, true);
298
299 return os.str();
300}
301
302StringRef SHA1::RawFinal(SmallVectorImpl<char>& buf) {
303 raw_svector_ostream os(buf);
304
305 finalize(digest, buffer, buf_size, transforms, os, false);
306
307 return os.str();
308}
309
310std::string SHA1::FromFile(StringRef filename) {
311 std::error_code ec;
312 raw_fd_istream stream(filename, ec);
313 SHA1 checksum;
314 checksum.Update(stream);
315 return checksum.Final();
316}