]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // |
b32b8144 | 2 | // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) |
7c673cae FG |
3 | // |
4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | // | |
b32b8144 FG |
7 | // Official repository: https://github.com/boostorg/beast |
8 | // | |
7c673cae | 9 | |
b32b8144 FG |
10 | #ifndef BOOST_BEAST_DETAIL_SHA1_HPP |
11 | #define BOOST_BEAST_DETAIL_SHA1_HPP | |
7c673cae FG |
12 | |
13 | #include <algorithm> | |
14 | #include <cstdint> | |
15 | #include <cstring> | |
16 | ||
17 | // Based on https://github.com/vog/sha1 | |
18 | /* | |
19 | Original authors: | |
20 | Steve Reid (Original C Code) | |
21 | Bruce Guenter (Small changes to fit into bglibs) | |
22 | Volker Grabsch (Translation to simpler C++ Code) | |
23 | Eugene Hopkinson (Safety improvements) | |
24 | Vincent Falco (beast adaptation) | |
25 | */ | |
26 | ||
b32b8144 | 27 | namespace boost { |
7c673cae FG |
28 | namespace beast { |
29 | namespace detail { | |
30 | ||
31 | namespace sha1 { | |
32 | ||
33 | static std::size_t constexpr BLOCK_INTS = 16; | |
34 | static std::size_t constexpr BLOCK_BYTES = 64; | |
35 | static std::size_t constexpr DIGEST_BYTES = 20; | |
36 | ||
37 | inline | |
38 | std::uint32_t | |
39 | rol(std::uint32_t value, std::size_t bits) | |
40 | { | |
41 | return (value << bits) | (value >> (32 - bits)); | |
42 | } | |
43 | ||
44 | inline | |
45 | std::uint32_t | |
46 | blk(std::uint32_t block[BLOCK_INTS], std::size_t i) | |
47 | { | |
48 | return rol( | |
49 | block[(i+13)&15] ^ block[(i+8)&15] ^ | |
50 | block[(i+2)&15] ^ block[i], 1); | |
51 | } | |
52 | ||
53 | inline | |
54 | void | |
55 | R0(std::uint32_t block[BLOCK_INTS], std::uint32_t v, | |
56 | std::uint32_t &w, std::uint32_t x, std::uint32_t y, | |
57 | std::uint32_t &z, std::size_t i) | |
58 | { | |
59 | z += ((w&(x^y))^y) + block[i] + 0x5a827999 + rol(v, 5); | |
60 | w = rol(w, 30); | |
61 | } | |
62 | ||
63 | ||
64 | inline | |
65 | void | |
66 | R1(std::uint32_t block[BLOCK_INTS], std::uint32_t v, | |
67 | std::uint32_t &w, std::uint32_t x, std::uint32_t y, | |
68 | std::uint32_t &z, std::size_t i) | |
69 | { | |
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 | ||
75 | inline | |
76 | void | |
77 | R2(std::uint32_t block[BLOCK_INTS], std::uint32_t v, | |
78 | std::uint32_t &w, std::uint32_t x, std::uint32_t y, | |
79 | std::uint32_t &z, std::size_t i) | |
80 | { | |
81 | block[i] = blk(block, i); | |
82 | z += (w^x^y) + block[i] + 0x6ed9eba1 + rol(v, 5); | |
83 | w = rol(w, 30); | |
84 | } | |
85 | ||
86 | inline | |
87 | void | |
88 | R3(std::uint32_t block[BLOCK_INTS], std::uint32_t v, | |
89 | std::uint32_t &w, std::uint32_t x, std::uint32_t y, | |
90 | std::uint32_t &z, std::size_t i) | |
91 | { | |
92 | block[i] = blk(block, i); | |
93 | z += (((w|x)&y)|(w&x)) + block[i] + 0x8f1bbcdc + rol(v, 5); | |
94 | w = rol(w, 30); | |
95 | } | |
96 | ||
97 | inline | |
98 | void | |
99 | R4(std::uint32_t block[BLOCK_INTS], std::uint32_t v, | |
100 | std::uint32_t &w, std::uint32_t x, std::uint32_t y, | |
101 | std::uint32_t &z, std::size_t i) | |
102 | { | |
103 | block[i] = blk(block, i); | |
104 | z += (w^x^y) + block[i] + 0xca62c1d6 + rol(v, 5); | |
105 | w = rol(w, 30); | |
106 | } | |
107 | ||
108 | inline | |
109 | void | |
110 | make_block(std::uint8_t const* p, | |
111 | std::uint32_t block[BLOCK_INTS]) | |
112 | { | |
113 | for(std::size_t i = 0; i < BLOCK_INTS; i++) | |
114 | block[i] = | |
115 | (static_cast<std::uint32_t>(p[4*i+3])) | | |
116 | (static_cast<std::uint32_t>(p[4*i+2]))<< 8 | | |
117 | (static_cast<std::uint32_t>(p[4*i+1]))<<16 | | |
118 | (static_cast<std::uint32_t>(p[4*i+0]))<<24; | |
119 | } | |
120 | ||
121 | template<class = void> | |
122 | void | |
123 | transform( | |
124 | std::uint32_t digest[], std::uint32_t block[BLOCK_INTS]) | |
125 | { | |
126 | std::uint32_t a = digest[0]; | |
127 | std::uint32_t b = digest[1]; | |
128 | std::uint32_t c = digest[2]; | |
129 | std::uint32_t d = digest[3]; | |
130 | std::uint32_t e = digest[4]; | |
131 | ||
132 | R0(block, a, b, c, d, e, 0); | |
133 | R0(block, e, a, b, c, d, 1); | |
134 | R0(block, d, e, a, b, c, 2); | |
135 | R0(block, c, d, e, a, b, 3); | |
136 | R0(block, b, c, d, e, a, 4); | |
137 | R0(block, a, b, c, d, e, 5); | |
138 | R0(block, e, a, b, c, d, 6); | |
139 | R0(block, d, e, a, b, c, 7); | |
140 | R0(block, c, d, e, a, b, 8); | |
141 | R0(block, b, c, d, e, a, 9); | |
142 | R0(block, a, b, c, d, e, 10); | |
143 | R0(block, e, a, b, c, d, 11); | |
144 | R0(block, d, e, a, b, c, 12); | |
145 | R0(block, c, d, e, a, b, 13); | |
146 | R0(block, b, c, d, e, a, 14); | |
147 | R0(block, a, b, c, d, e, 15); | |
148 | R1(block, e, a, b, c, d, 0); | |
149 | R1(block, d, e, a, b, c, 1); | |
150 | R1(block, c, d, e, a, b, 2); | |
151 | R1(block, b, c, d, e, a, 3); | |
152 | R2(block, a, b, c, d, e, 4); | |
153 | R2(block, e, a, b, c, d, 5); | |
154 | R2(block, d, e, a, b, c, 6); | |
155 | R2(block, c, d, e, a, b, 7); | |
156 | R2(block, b, c, d, e, a, 8); | |
157 | R2(block, a, b, c, d, e, 9); | |
158 | R2(block, e, a, b, c, d, 10); | |
159 | R2(block, d, e, a, b, c, 11); | |
160 | R2(block, c, d, e, a, b, 12); | |
161 | R2(block, b, c, d, e, a, 13); | |
162 | R2(block, a, b, c, d, e, 14); | |
163 | R2(block, e, a, b, c, d, 15); | |
164 | R2(block, d, e, a, b, c, 0); | |
165 | R2(block, c, d, e, a, b, 1); | |
166 | R2(block, b, c, d, e, a, 2); | |
167 | R2(block, a, b, c, d, e, 3); | |
168 | R2(block, e, a, b, c, d, 4); | |
169 | R2(block, d, e, a, b, c, 5); | |
170 | R2(block, c, d, e, a, b, 6); | |
171 | R2(block, b, c, d, e, a, 7); | |
172 | R3(block, a, b, c, d, e, 8); | |
173 | R3(block, e, a, b, c, d, 9); | |
174 | R3(block, d, e, a, b, c, 10); | |
175 | R3(block, c, d, e, a, b, 11); | |
176 | R3(block, b, c, d, e, a, 12); | |
177 | R3(block, a, b, c, d, e, 13); | |
178 | R3(block, e, a, b, c, d, 14); | |
179 | R3(block, d, e, a, b, c, 15); | |
180 | R3(block, c, d, e, a, b, 0); | |
181 | R3(block, b, c, d, e, a, 1); | |
182 | R3(block, a, b, c, d, e, 2); | |
183 | R3(block, e, a, b, c, d, 3); | |
184 | R3(block, d, e, a, b, c, 4); | |
185 | R3(block, c, d, e, a, b, 5); | |
186 | R3(block, b, c, d, e, a, 6); | |
187 | R3(block, a, b, c, d, e, 7); | |
188 | R3(block, e, a, b, c, d, 8); | |
189 | R3(block, d, e, a, b, c, 9); | |
190 | R3(block, c, d, e, a, b, 10); | |
191 | R3(block, b, c, d, e, a, 11); | |
192 | R4(block, a, b, c, d, e, 12); | |
193 | R4(block, e, a, b, c, d, 13); | |
194 | R4(block, d, e, a, b, c, 14); | |
195 | R4(block, c, d, e, a, b, 15); | |
196 | R4(block, b, c, d, e, a, 0); | |
197 | R4(block, a, b, c, d, e, 1); | |
198 | R4(block, e, a, b, c, d, 2); | |
199 | R4(block, d, e, a, b, c, 3); | |
200 | R4(block, c, d, e, a, b, 4); | |
201 | R4(block, b, c, d, e, a, 5); | |
202 | R4(block, a, b, c, d, e, 6); | |
203 | R4(block, e, a, b, c, d, 7); | |
204 | R4(block, d, e, a, b, c, 8); | |
205 | R4(block, c, d, e, a, b, 9); | |
206 | R4(block, b, c, d, e, a, 10); | |
207 | R4(block, a, b, c, d, e, 11); | |
208 | R4(block, e, a, b, c, d, 12); | |
209 | R4(block, d, e, a, b, c, 13); | |
210 | R4(block, c, d, e, a, b, 14); | |
211 | R4(block, b, c, d, e, a, 15); | |
212 | ||
213 | digest[0] += a; | |
214 | digest[1] += b; | |
215 | digest[2] += c; | |
216 | digest[3] += d; | |
217 | digest[4] += e; | |
218 | } | |
219 | ||
220 | } // sha1 | |
221 | ||
222 | struct sha1_context | |
223 | { | |
224 | static unsigned int constexpr block_size = sha1::BLOCK_BYTES; | |
225 | static unsigned int constexpr digest_size = 20; | |
226 | ||
227 | std::size_t buflen; | |
228 | std::size_t blocks; | |
229 | std::uint32_t digest[5]; | |
230 | std::uint8_t buf[block_size]; | |
231 | }; | |
232 | ||
233 | template<class = void> | |
234 | void | |
235 | init(sha1_context& ctx) noexcept | |
236 | { | |
237 | ctx.buflen = 0; | |
238 | ctx.blocks = 0; | |
239 | ctx.digest[0] = 0x67452301; | |
240 | ctx.digest[1] = 0xefcdab89; | |
241 | ctx.digest[2] = 0x98badcfe; | |
242 | ctx.digest[3] = 0x10325476; | |
243 | ctx.digest[4] = 0xc3d2e1f0; | |
244 | } | |
245 | ||
246 | template<class = void> | |
247 | void | |
248 | update(sha1_context& ctx, | |
249 | void const* message, std::size_t size) noexcept | |
250 | { | |
251 | auto p = reinterpret_cast< | |
252 | std::uint8_t const*>(message); | |
253 | for(;;) | |
254 | { | |
255 | auto const n = (std::min)( | |
256 | size, sizeof(ctx.buf) - ctx.buflen); | |
257 | std::memcpy(ctx.buf + ctx.buflen, p, n); | |
258 | ctx.buflen += n; | |
259 | if(ctx.buflen != 64) | |
260 | return; | |
261 | p += n; | |
262 | size -= n; | |
263 | ctx.buflen = 0; | |
264 | std::uint32_t block[sha1::BLOCK_INTS]; | |
265 | sha1::make_block(ctx.buf, block); | |
266 | sha1::transform(ctx.digest, block); | |
267 | ++ctx.blocks; | |
268 | } | |
269 | } | |
270 | ||
271 | template<class = void> | |
272 | void | |
273 | finish(sha1_context& ctx, void* digest) noexcept | |
274 | { | |
275 | using sha1::BLOCK_INTS; | |
276 | using sha1::BLOCK_BYTES; | |
277 | ||
278 | std::uint64_t total_bits = | |
279 | (ctx.blocks*64 + ctx.buflen) * 8; | |
280 | // pad | |
281 | ctx.buf[ctx.buflen++] = 0x80; | |
282 | auto const buflen = ctx.buflen; | |
283 | while(ctx.buflen < 64) | |
284 | ctx.buf[ctx.buflen++] = 0x00; | |
285 | std::uint32_t block[BLOCK_INTS]; | |
286 | sha1::make_block(ctx.buf, block); | |
287 | if(buflen > BLOCK_BYTES - 8) | |
288 | { | |
289 | sha1::transform(ctx.digest, block); | |
290 | for(size_t i = 0; i < BLOCK_INTS - 2; i++) | |
291 | block[i] = 0; | |
292 | } | |
293 | ||
294 | /* Append total_bits, split this uint64_t into two uint32_t */ | |
295 | block[BLOCK_INTS - 1] = total_bits & 0xffffffff; | |
296 | block[BLOCK_INTS - 2] = (total_bits >> 32); | |
297 | sha1::transform(ctx.digest, block); | |
298 | for(std::size_t i = 0; i < sha1::DIGEST_BYTES/4; i++) | |
299 | { | |
300 | std::uint8_t* d = | |
301 | reinterpret_cast<std::uint8_t*>(digest) + 4 * i; | |
302 | d[3] = ctx.digest[i] & 0xff; | |
303 | d[2] = (ctx.digest[i] >> 8) & 0xff; | |
304 | d[1] = (ctx.digest[i] >> 16) & 0xff; | |
305 | d[0] = (ctx.digest[i] >> 24) & 0xff; | |
306 | } | |
307 | } | |
308 | ||
309 | } // detail | |
310 | } // beast | |
b32b8144 | 311 | } // boost |
7c673cae FG |
312 | |
313 | #endif |