/src/ntp-dev/lib/isc/sha1.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") |
3 | | * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. |
4 | | * |
5 | | * Permission to use, copy, modify, and/or distribute this software for any |
6 | | * purpose with or without fee is hereby granted, provided that the above |
7 | | * copyright notice and this permission notice appear in all copies. |
8 | | * |
9 | | * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH |
10 | | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY |
11 | | * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, |
12 | | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM |
13 | | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE |
14 | | * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
15 | | * PERFORMANCE OF THIS SOFTWARE. |
16 | | */ |
17 | | |
18 | | /* $Id$ */ |
19 | | |
20 | | /* $NetBSD: sha1.c,v 1.5 2000/01/22 22:19:14 mycroft Exp $ */ |
21 | | /* $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $ */ |
22 | | |
23 | | /*! \file |
24 | | * SHA-1 in C |
25 | | * \author By Steve Reid <steve@edmweb.com> |
26 | | * 100% Public Domain |
27 | | * \verbatim |
28 | | * Test Vectors (from FIPS PUB 180-1) |
29 | | * "abc" |
30 | | * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D |
31 | | * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" |
32 | | * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 |
33 | | * A million repetitions of "a" |
34 | | * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F |
35 | | * \endverbatim |
36 | | */ |
37 | | |
38 | | #include "config.h" |
39 | | |
40 | | #include <isc/assertions.h> |
41 | | #include <isc/platform.h> |
42 | | #include <isc/sha1.h> |
43 | | #include <isc/string.h> |
44 | | #include <isc/types.h> |
45 | | #include <isc/util.h> |
46 | | |
47 | | #ifdef ISC_PLATFORM_OPENSSLHASH |
48 | | |
49 | | void |
50 | | isc_sha1_init(isc_sha1_t *context) |
51 | | { |
52 | | INSIST(context != NULL); |
53 | | |
54 | | EVP_DigestInit(context, EVP_sha1()); |
55 | | } |
56 | | |
57 | | void |
58 | | isc_sha1_invalidate(isc_sha1_t *context) { |
59 | | EVP_MD_CTX_cleanup(context); |
60 | | } |
61 | | |
62 | | void |
63 | | isc_sha1_update(isc_sha1_t *context, const unsigned char *data, |
64 | | unsigned int len) |
65 | | { |
66 | | INSIST(context != 0); |
67 | | INSIST(data != 0); |
68 | | |
69 | | EVP_DigestUpdate(context, (const void *) data, (size_t) len); |
70 | | } |
71 | | |
72 | | void |
73 | | isc_sha1_final(isc_sha1_t *context, unsigned char *digest) { |
74 | | INSIST(digest != 0); |
75 | | INSIST(context != 0); |
76 | | |
77 | | EVP_DigestFinal(context, digest, NULL); |
78 | | } |
79 | | |
80 | | #else |
81 | | |
82 | 0 | #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) |
83 | | |
84 | | /*@{*/ |
85 | | /*! |
86 | | * blk0() and blk() perform the initial expand. |
87 | | * I got the idea of expanding during the round function from SSLeay |
88 | | */ |
89 | | #if !defined(WORDS_BIGENDIAN) |
90 | | # define blk0(i) \ |
91 | 0 | (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) \ |
92 | 0 | | (rol(block->l[i], 8) & 0x00FF00FF)) |
93 | | #else |
94 | | # define blk0(i) block->l[i] |
95 | | #endif |
96 | | #define blk(i) \ |
97 | 0 | (block->l[i & 15] = rol(block->l[(i + 13) & 15] \ |
98 | 0 | ^ block->l[(i + 8) & 15] \ |
99 | 0 | ^ block->l[(i + 2) & 15] \ |
100 | 0 | ^ block->l[i & 15], 1)) |
101 | | |
102 | | /*@}*/ |
103 | | /*@{*/ |
104 | | /*! |
105 | | * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 |
106 | | */ |
107 | | #define R0(v,w,x,y,z,i) \ |
108 | 0 | z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \ |
109 | 0 | w = rol(w, 30); |
110 | | #define R1(v,w,x,y,z,i) \ |
111 | 0 | z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ |
112 | 0 | w = rol(w, 30); |
113 | | #define R2(v,w,x,y,z,i) \ |
114 | 0 | z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \ |
115 | 0 | w = rol(w, 30); |
116 | | #define R3(v,w,x,y,z,i) \ |
117 | 0 | z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ |
118 | 0 | w = rol(w, 30); |
119 | | #define R4(v,w,x,y,z,i) \ |
120 | 0 | z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ |
121 | 0 | w = rol(w, 30); |
122 | | |
123 | | /*@}*/ |
124 | | |
125 | | typedef union { |
126 | | unsigned char c[64]; |
127 | | unsigned int l[16]; |
128 | | } CHAR64LONG16; |
129 | | |
130 | | #ifdef __sparc_v9__ |
131 | | static void do_R01(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c, |
132 | | isc_uint32_t *d, isc_uint32_t *e, CHAR64LONG16 *); |
133 | | static void do_R2(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c, |
134 | | isc_uint32_t *d, isc_uint32_t *e, CHAR64LONG16 *); |
135 | | static void do_R3(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c, |
136 | | isc_uint32_t *d, isc_uint32_t *e, CHAR64LONG16 *); |
137 | | static void do_R4(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c, |
138 | | isc_uint32_t *d, isc_uint32_t *e, CHAR64LONG16 *); |
139 | | |
140 | | #define nR0(v,w,x,y,z,i) R0(*v,*w,*x,*y,*z,i) |
141 | | #define nR1(v,w,x,y,z,i) R1(*v,*w,*x,*y,*z,i) |
142 | | #define nR2(v,w,x,y,z,i) R2(*v,*w,*x,*y,*z,i) |
143 | | #define nR3(v,w,x,y,z,i) R3(*v,*w,*x,*y,*z,i) |
144 | | #define nR4(v,w,x,y,z,i) R4(*v,*w,*x,*y,*z,i) |
145 | | |
146 | | static void |
147 | | do_R01(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c, isc_uint32_t *d, |
148 | | isc_uint32_t *e, CHAR64LONG16 *block) |
149 | | { |
150 | | nR0(a,b,c,d,e, 0); nR0(e,a,b,c,d, 1); nR0(d,e,a,b,c, 2); |
151 | | nR0(c,d,e,a,b, 3); nR0(b,c,d,e,a, 4); nR0(a,b,c,d,e, 5); |
152 | | nR0(e,a,b,c,d, 6); nR0(d,e,a,b,c, 7); nR0(c,d,e,a,b, 8); |
153 | | nR0(b,c,d,e,a, 9); nR0(a,b,c,d,e,10); nR0(e,a,b,c,d,11); |
154 | | nR0(d,e,a,b,c,12); nR0(c,d,e,a,b,13); nR0(b,c,d,e,a,14); |
155 | | nR0(a,b,c,d,e,15); nR1(e,a,b,c,d,16); nR1(d,e,a,b,c,17); |
156 | | nR1(c,d,e,a,b,18); nR1(b,c,d,e,a,19); |
157 | | } |
158 | | |
159 | | static void |
160 | | do_R2(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c, isc_uint32_t *d, |
161 | | isc_uint32_t *e, CHAR64LONG16 *block) |
162 | | { |
163 | | nR2(a,b,c,d,e,20); nR2(e,a,b,c,d,21); nR2(d,e,a,b,c,22); |
164 | | nR2(c,d,e,a,b,23); nR2(b,c,d,e,a,24); nR2(a,b,c,d,e,25); |
165 | | nR2(e,a,b,c,d,26); nR2(d,e,a,b,c,27); nR2(c,d,e,a,b,28); |
166 | | nR2(b,c,d,e,a,29); nR2(a,b,c,d,e,30); nR2(e,a,b,c,d,31); |
167 | | nR2(d,e,a,b,c,32); nR2(c,d,e,a,b,33); nR2(b,c,d,e,a,34); |
168 | | nR2(a,b,c,d,e,35); nR2(e,a,b,c,d,36); nR2(d,e,a,b,c,37); |
169 | | nR2(c,d,e,a,b,38); nR2(b,c,d,e,a,39); |
170 | | } |
171 | | |
172 | | static void |
173 | | do_R3(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c, isc_uint32_t *d, |
174 | | isc_uint32_t *e, CHAR64LONG16 *block) |
175 | | { |
176 | | nR3(a,b,c,d,e,40); nR3(e,a,b,c,d,41); nR3(d,e,a,b,c,42); |
177 | | nR3(c,d,e,a,b,43); nR3(b,c,d,e,a,44); nR3(a,b,c,d,e,45); |
178 | | nR3(e,a,b,c,d,46); nR3(d,e,a,b,c,47); nR3(c,d,e,a,b,48); |
179 | | nR3(b,c,d,e,a,49); nR3(a,b,c,d,e,50); nR3(e,a,b,c,d,51); |
180 | | nR3(d,e,a,b,c,52); nR3(c,d,e,a,b,53); nR3(b,c,d,e,a,54); |
181 | | nR3(a,b,c,d,e,55); nR3(e,a,b,c,d,56); nR3(d,e,a,b,c,57); |
182 | | nR3(c,d,e,a,b,58); nR3(b,c,d,e,a,59); |
183 | | } |
184 | | |
185 | | static void |
186 | | do_R4(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c, isc_uint32_t *d, |
187 | | isc_uint32_t *e, CHAR64LONG16 *block) |
188 | | { |
189 | | nR4(a,b,c,d,e,60); nR4(e,a,b,c,d,61); nR4(d,e,a,b,c,62); |
190 | | nR4(c,d,e,a,b,63); nR4(b,c,d,e,a,64); nR4(a,b,c,d,e,65); |
191 | | nR4(e,a,b,c,d,66); nR4(d,e,a,b,c,67); nR4(c,d,e,a,b,68); |
192 | | nR4(b,c,d,e,a,69); nR4(a,b,c,d,e,70); nR4(e,a,b,c,d,71); |
193 | | nR4(d,e,a,b,c,72); nR4(c,d,e,a,b,73); nR4(b,c,d,e,a,74); |
194 | | nR4(a,b,c,d,e,75); nR4(e,a,b,c,d,76); nR4(d,e,a,b,c,77); |
195 | | nR4(c,d,e,a,b,78); nR4(b,c,d,e,a,79); |
196 | | } |
197 | | #endif |
198 | | |
199 | | /*! |
200 | | * Hash a single 512-bit block. This is the core of the algorithm. |
201 | | */ |
202 | | static void |
203 | 0 | transform(isc_uint32_t state[5], const unsigned char buffer[64]) { |
204 | 0 | isc_uint32_t a, b, c, d, e; |
205 | 0 | CHAR64LONG16 *block; |
206 | 0 | CHAR64LONG16 workspace; |
207 | |
|
208 | 0 | INSIST(buffer != NULL); |
209 | 0 | INSIST(state != NULL); |
210 | | |
211 | 0 | block = &workspace; |
212 | 0 | (void)memcpy(block, buffer, 64); |
213 | | |
214 | | /* Copy context->state[] to working vars */ |
215 | 0 | a = state[0]; |
216 | 0 | b = state[1]; |
217 | 0 | c = state[2]; |
218 | 0 | d = state[3]; |
219 | 0 | e = state[4]; |
220 | |
|
221 | | #ifdef __sparc_v9__ |
222 | | do_R01(&a, &b, &c, &d, &e, block); |
223 | | do_R2(&a, &b, &c, &d, &e, block); |
224 | | do_R3(&a, &b, &c, &d, &e, block); |
225 | | do_R4(&a, &b, &c, &d, &e, block); |
226 | | #else |
227 | | /* 4 rounds of 20 operations each. Loop unrolled. */ |
228 | 0 | R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); |
229 | 0 | R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); |
230 | 0 | R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); |
231 | 0 | R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); |
232 | 0 | R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); |
233 | 0 | R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); |
234 | 0 | R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); |
235 | 0 | R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); |
236 | 0 | R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); |
237 | 0 | R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); |
238 | 0 | R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); |
239 | 0 | R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); |
240 | 0 | R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); |
241 | 0 | R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); |
242 | 0 | R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); |
243 | 0 | R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); |
244 | 0 | R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); |
245 | 0 | R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); |
246 | 0 | R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); |
247 | 0 | R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); |
248 | 0 | #endif |
249 | | |
250 | | /* Add the working vars back into context.state[] */ |
251 | 0 | state[0] += a; |
252 | 0 | state[1] += b; |
253 | 0 | state[2] += c; |
254 | 0 | state[3] += d; |
255 | 0 | state[4] += e; |
256 | | |
257 | | /* Wipe variables */ |
258 | 0 | a = b = c = d = e = 0; |
259 | | /* Avoid compiler warnings */ |
260 | 0 | POST(a); POST(b); POST(c); POST(d); POST(e); |
261 | 0 | } |
262 | | |
263 | | |
264 | | /*! |
265 | | * isc_sha1_init - Initialize new context |
266 | | */ |
267 | | void |
268 | | isc_sha1_init(isc_sha1_t *context) |
269 | 0 | { |
270 | 0 | INSIST(context != NULL); |
271 | | |
272 | | /* SHA1 initialization constants */ |
273 | 0 | context->state[0] = 0x67452301; |
274 | 0 | context->state[1] = 0xEFCDAB89; |
275 | 0 | context->state[2] = 0x98BADCFE; |
276 | 0 | context->state[3] = 0x10325476; |
277 | 0 | context->state[4] = 0xC3D2E1F0; |
278 | 0 | context->count[0] = 0; |
279 | 0 | context->count[1] = 0; |
280 | 0 | } |
281 | | |
282 | | void |
283 | 0 | isc_sha1_invalidate(isc_sha1_t *context) { |
284 | 0 | memset(context, 0, sizeof(isc_sha1_t)); |
285 | 0 | } |
286 | | |
287 | | /*! |
288 | | * Run your data through this. |
289 | | */ |
290 | | void |
291 | | isc_sha1_update(isc_sha1_t *context, const unsigned char *data, |
292 | | unsigned int len) |
293 | 0 | { |
294 | 0 | unsigned int i, j; |
295 | |
|
296 | 0 | INSIST(context != 0); |
297 | 0 | INSIST(data != 0); |
298 | | |
299 | 0 | j = context->count[0]; |
300 | 0 | if ((context->count[0] += len << 3) < j) |
301 | 0 | context->count[1] += (len >> 29) + 1; |
302 | 0 | j = (j >> 3) & 63; |
303 | 0 | if ((j + len) > 63) { |
304 | 0 | (void)memcpy(&context->buffer[j], data, (i = 64 - j)); |
305 | 0 | transform(context->state, context->buffer); |
306 | 0 | for (; i + 63 < len; i += 64) |
307 | 0 | transform(context->state, &data[i]); |
308 | 0 | j = 0; |
309 | 0 | } else { |
310 | 0 | i = 0; |
311 | 0 | } |
312 | |
|
313 | 0 | (void)memcpy(&context->buffer[j], &data[i], len - i); |
314 | 0 | } |
315 | | |
316 | | |
317 | | /*! |
318 | | * Add padding and return the message digest. |
319 | | */ |
320 | | |
321 | | static const unsigned char final_200 = 128; |
322 | | static const unsigned char final_0 = 0; |
323 | | |
324 | | void |
325 | 0 | isc_sha1_final(isc_sha1_t *context, unsigned char *digest) { |
326 | 0 | unsigned int i; |
327 | 0 | unsigned char finalcount[8]; |
328 | |
|
329 | 0 | INSIST(digest != 0); |
330 | 0 | INSIST(context != 0); |
331 | | |
332 | 0 | for (i = 0; i < 8; i++) { |
333 | | /* Endian independent */ |
334 | 0 | finalcount[i] = (unsigned char) |
335 | 0 | ((context->count[(i >= 4 ? 0 : 1)] |
336 | 0 | >> ((3 - (i & 3)) * 8)) & 255); |
337 | 0 | } |
338 | |
|
339 | 0 | isc_sha1_update(context, &final_200, 1); |
340 | 0 | while ((context->count[0] & 504) != 448) |
341 | 0 | isc_sha1_update(context, &final_0, 1); |
342 | | /* The next Update should cause a transform() */ |
343 | 0 | isc_sha1_update(context, finalcount, 8); |
344 | |
|
345 | 0 | if (digest) { |
346 | 0 | for (i = 0; i < 20; i++) |
347 | 0 | digest[i] = (unsigned char) |
348 | 0 | ((context->state[i >> 2] |
349 | 0 | >> ((3 - (i & 3)) * 8)) & 255); |
350 | 0 | } |
351 | |
|
352 | 0 | memset(context, 0, sizeof(isc_sha1_t)); |
353 | 0 | } |
354 | | #endif |