/src/BearSSL/src/hash/sha1.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org> |
3 | | * |
4 | | * Permission is hereby granted, free of charge, to any person obtaining |
5 | | * a copy of this software and associated documentation files (the |
6 | | * "Software"), to deal in the Software without restriction, including |
7 | | * without limitation the rights to use, copy, modify, merge, publish, |
8 | | * distribute, sublicense, and/or sell copies of the Software, and to |
9 | | * permit persons to whom the Software is furnished to do so, subject to |
10 | | * the following conditions: |
11 | | * |
12 | | * The above copyright notice and this permission notice shall be |
13 | | * included in all copies or substantial portions of the Software. |
14 | | * |
15 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
16 | | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
17 | | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
18 | | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
19 | | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
20 | | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
21 | | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
22 | | * SOFTWARE. |
23 | | */ |
24 | | |
25 | | #include "inner.h" |
26 | | |
27 | 4.33M | #define F(B, C, D) ((((C) ^ (D)) & (B)) ^ (D)) |
28 | 8.67M | #define G(B, C, D) ((B) ^ (C) ^ (D)) |
29 | 4.33M | #define H(B, C, D) (((D) & (C)) | (((D) | (C)) & (B))) |
30 | 4.33M | #define I(B, C, D) G(B, C, D) |
31 | | |
32 | 48.6M | #define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) |
33 | | |
34 | 4.33M | #define K1 ((uint32_t)0x5A827999) |
35 | 4.33M | #define K2 ((uint32_t)0x6ED9EBA1) |
36 | 4.33M | #define K3 ((uint32_t)0x8F1BBCDC) |
37 | 4.33M | #define K4 ((uint32_t)0xCA62C1D6) |
38 | | |
39 | | /* see inner.h */ |
40 | | const uint32_t br_sha1_IV[5] = { |
41 | | 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 |
42 | | }; |
43 | | |
44 | | /* see inner.h */ |
45 | | void |
46 | | br_sha1_round(const unsigned char *buf, uint32_t *val) |
47 | 216k | { |
48 | 216k | uint32_t m[80]; |
49 | 216k | uint32_t a, b, c, d, e; |
50 | 216k | int i; |
51 | | |
52 | 216k | a = val[0]; |
53 | 216k | b = val[1]; |
54 | 216k | c = val[2]; |
55 | 216k | d = val[3]; |
56 | 216k | e = val[4]; |
57 | 216k | br_range_dec32be(m, 16, buf); |
58 | 14.1M | for (i = 16; i < 80; i ++) { |
59 | 13.8M | uint32_t x = m[i - 3] ^ m[i - 8] ^ m[i - 14] ^ m[i - 16]; |
60 | 13.8M | m[i] = ROTL(x, 1); |
61 | 13.8M | } |
62 | | |
63 | 1.08M | for (i = 0; i < 20; i += 5) { |
64 | 867k | e += ROTL(a, 5) + F(b, c, d) + K1 + m[i + 0]; b = ROTL(b, 30); |
65 | 867k | d += ROTL(e, 5) + F(a, b, c) + K1 + m[i + 1]; a = ROTL(a, 30); |
66 | 867k | c += ROTL(d, 5) + F(e, a, b) + K1 + m[i + 2]; e = ROTL(e, 30); |
67 | 867k | b += ROTL(c, 5) + F(d, e, a) + K1 + m[i + 3]; d = ROTL(d, 30); |
68 | 867k | a += ROTL(b, 5) + F(c, d, e) + K1 + m[i + 4]; c = ROTL(c, 30); |
69 | 867k | } |
70 | 1.08M | for (i = 20; i < 40; i += 5) { |
71 | 867k | e += ROTL(a, 5) + G(b, c, d) + K2 + m[i + 0]; b = ROTL(b, 30); |
72 | 867k | d += ROTL(e, 5) + G(a, b, c) + K2 + m[i + 1]; a = ROTL(a, 30); |
73 | 867k | c += ROTL(d, 5) + G(e, a, b) + K2 + m[i + 2]; e = ROTL(e, 30); |
74 | 867k | b += ROTL(c, 5) + G(d, e, a) + K2 + m[i + 3]; d = ROTL(d, 30); |
75 | 867k | a += ROTL(b, 5) + G(c, d, e) + K2 + m[i + 4]; c = ROTL(c, 30); |
76 | 867k | } |
77 | 1.08M | for (i = 40; i < 60; i += 5) { |
78 | 867k | e += ROTL(a, 5) + H(b, c, d) + K3 + m[i + 0]; b = ROTL(b, 30); |
79 | 867k | d += ROTL(e, 5) + H(a, b, c) + K3 + m[i + 1]; a = ROTL(a, 30); |
80 | 867k | c += ROTL(d, 5) + H(e, a, b) + K3 + m[i + 2]; e = ROTL(e, 30); |
81 | 867k | b += ROTL(c, 5) + H(d, e, a) + K3 + m[i + 3]; d = ROTL(d, 30); |
82 | 867k | a += ROTL(b, 5) + H(c, d, e) + K3 + m[i + 4]; c = ROTL(c, 30); |
83 | 867k | } |
84 | 1.08M | for (i = 60; i < 80; i += 5) { |
85 | 867k | e += ROTL(a, 5) + I(b, c, d) + K4 + m[i + 0]; b = ROTL(b, 30); |
86 | 867k | d += ROTL(e, 5) + I(a, b, c) + K4 + m[i + 1]; a = ROTL(a, 30); |
87 | 867k | c += ROTL(d, 5) + I(e, a, b) + K4 + m[i + 2]; e = ROTL(e, 30); |
88 | 867k | b += ROTL(c, 5) + I(d, e, a) + K4 + m[i + 3]; d = ROTL(d, 30); |
89 | 867k | a += ROTL(b, 5) + I(c, d, e) + K4 + m[i + 4]; c = ROTL(c, 30); |
90 | 867k | } |
91 | | |
92 | 216k | val[0] += a; |
93 | 216k | val[1] += b; |
94 | 216k | val[2] += c; |
95 | 216k | val[3] += d; |
96 | 216k | val[4] += e; |
97 | 216k | } |
98 | | |
99 | | /* see bearssl.h */ |
100 | | void |
101 | | br_sha1_init(br_sha1_context *cc) |
102 | 41.7k | { |
103 | 41.7k | cc->vtable = &br_sha1_vtable; |
104 | 41.7k | memcpy(cc->val, br_sha1_IV, sizeof cc->val); |
105 | 41.7k | cc->count = 0; |
106 | 41.7k | } |
107 | | |
108 | | /* see bearssl.h */ |
109 | | void |
110 | | br_sha1_update(br_sha1_context *cc, const void *data, size_t len) |
111 | 91.0k | { |
112 | 91.0k | const unsigned char *buf; |
113 | 91.0k | size_t ptr; |
114 | | |
115 | 91.0k | buf = data; |
116 | 91.0k | ptr = (size_t)cc->count & 63; |
117 | 270k | while (len > 0) { |
118 | 179k | size_t clen; |
119 | | |
120 | 179k | clen = 64 - ptr; |
121 | 179k | if (clen > len) { |
122 | 57.7k | clen = len; |
123 | 57.7k | } |
124 | 179k | memcpy(cc->buf + ptr, buf, clen); |
125 | 179k | ptr += clen; |
126 | 179k | buf += clen; |
127 | 179k | len -= clen; |
128 | 179k | cc->count += (uint64_t)clen; |
129 | 179k | if (ptr == 64) { |
130 | 121k | br_sha1_round(cc->buf, cc->val); |
131 | 121k | ptr = 0; |
132 | 121k | } |
133 | 179k | } |
134 | 91.0k | } |
135 | | |
136 | | /* see bearssl.h */ |
137 | | void |
138 | | br_sha1_out(const br_sha1_context *cc, void *dst) |
139 | 40.2k | { |
140 | 40.2k | unsigned char buf[64]; |
141 | 40.2k | uint32_t val[5]; |
142 | 40.2k | size_t ptr; |
143 | | |
144 | 40.2k | ptr = (size_t)cc->count & 63; |
145 | 40.2k | memcpy(buf, cc->buf, ptr); |
146 | 40.2k | memcpy(val, cc->val, sizeof val); |
147 | 40.2k | buf[ptr ++] = 0x80; |
148 | 40.2k | if (ptr > 56) { |
149 | 597 | memset(buf + ptr, 0, 64 - ptr); |
150 | 597 | br_sha1_round(buf, val); |
151 | 597 | memset(buf, 0, 56); |
152 | 39.6k | } else { |
153 | 39.6k | memset(buf + ptr, 0, 56 - ptr); |
154 | 39.6k | } |
155 | 40.2k | br_enc64be(buf + 56, cc->count << 3); |
156 | 40.2k | br_sha1_round(buf, val); |
157 | 40.2k | br_range_enc32be(dst, val, 5); |
158 | 40.2k | } |
159 | | |
160 | | /* see bearssl.h */ |
161 | | uint64_t |
162 | | br_sha1_state(const br_sha1_context *cc, void *dst) |
163 | 1.42k | { |
164 | 1.42k | br_range_enc32be(dst, cc->val, 5); |
165 | 1.42k | return cc->count; |
166 | 1.42k | } |
167 | | |
168 | | /* see bearssl.h */ |
169 | | void |
170 | | br_sha1_set_state(br_sha1_context *cc, const void *stb, uint64_t count) |
171 | 39.7k | { |
172 | 39.7k | br_range_dec32be(cc->val, 5, stb); |
173 | 39.7k | cc->count = count; |
174 | 39.7k | } |
175 | | |
176 | | /* see bearssl.h */ |
177 | | const br_hash_class br_sha1_vtable = { |
178 | | sizeof(br_sha1_context), |
179 | | BR_HASHDESC_ID(br_sha1_ID) |
180 | | | BR_HASHDESC_OUT(20) |
181 | | | BR_HASHDESC_STATE(20) |
182 | | | BR_HASHDESC_LBLEN(6) |
183 | | | BR_HASHDESC_MD_PADDING |
184 | | | BR_HASHDESC_MD_PADDING_BE, |
185 | | (void (*)(const br_hash_class **))&br_sha1_init, |
186 | | (void (*)(const br_hash_class **, const void *, size_t))&br_sha1_update, |
187 | | (void (*)(const br_hash_class *const *, void *))&br_sha1_out, |
188 | | (uint64_t (*)(const br_hash_class *const *, void *))&br_sha1_state, |
189 | | (void (*)(const br_hash_class **, const void *, uint64_t)) |
190 | | &br_sha1_set_state |
191 | | }; |