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

source code of boost/libs/beast/include/boost/beast/core/detail/sha1.ipp