]>
Commit | Line | Data |
---|---|---|
064af421 | 1 | /* |
5eccf359 BP |
2 | * This file is from the Apache Portable Runtime Library. |
3 | * The full upstream copyright and license statement is included below. | |
bf971267 | 4 | * Modifications copyright (c) 2009, 2010 Nicira Networks. |
5eccf359 BP |
5 | */ |
6 | ||
7 | /* Licensed to the Apache Software Foundation (ASF) under one or more | |
8 | * contributor license agreements. See the NOTICE file distributed with | |
9 | * this work for additional information regarding copyright ownership. | |
10 | * The ASF licenses this file to You under the Apache License, Version 2.0 | |
11 | * (the "License"); you may not use this file except in compliance with | |
12 | * the License. You may obtain a copy of the License at | |
064af421 | 13 | * |
5eccf359 | 14 | * http://www.apache.org/licenses/LICENSE-2.0 |
064af421 | 15 | * |
5eccf359 BP |
16 | * Unless required by applicable law or agreed to in writing, software |
17 | * distributed under the License is distributed on an "AS IS" BASIS, | |
18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
19 | * See the License for the specific language governing permissions and | |
20 | * limitations under the License. | |
21 | */ | |
22 | ||
23 | /* This software also makes use of the following component: | |
064af421 | 24 | * |
5eccf359 BP |
25 | * NIST Secure Hash Algorithm |
26 | * heavily modified by Uwe Hollerbach uh@alumni.caltech edu | |
27 | * from Peter C. Gutmann's implementation as found in | |
28 | * Applied Cryptography by Bruce Schneier | |
29 | * This code is hereby placed in the public domain | |
064af421 BP |
30 | */ |
31 | ||
5eccf359 | 32 | #include <config.h> |
064af421 | 33 | #include "sha1.h" |
e7f1bf58 | 34 | #include <ctype.h> |
5eccf359 | 35 | #include <string.h> |
e7f1bf58 | 36 | #include "util.h" |
064af421 | 37 | |
5eccf359 BP |
38 | /* a bit faster & bigger, if defined */ |
39 | #define UNROLL_LOOPS | |
064af421 | 40 | |
5eccf359 BP |
41 | /* SHA f()-functions */ |
42 | static inline uint32_t | |
43 | f1(uint32_t x, uint32_t y, uint32_t z) | |
44 | { | |
45 | return (x & y) | (~x & z); | |
46 | } | |
064af421 | 47 | |
5eccf359 BP |
48 | static inline uint32_t |
49 | f2(uint32_t x, uint32_t y, uint32_t z) | |
064af421 | 50 | { |
5eccf359 BP |
51 | return x ^ y ^ z; |
52 | } | |
064af421 | 53 | |
5eccf359 BP |
54 | static inline uint32_t |
55 | f3(uint32_t x, uint32_t y, uint32_t z) | |
56 | { | |
57 | return (x & y) | (x & z) | (y & z); | |
58 | } | |
064af421 | 59 | |
5eccf359 BP |
60 | static inline uint32_t |
61 | f4(uint32_t x, uint32_t y, uint32_t z) | |
62 | { | |
63 | return x ^ y ^ z; | |
64 | } | |
064af421 | 65 | |
5eccf359 BP |
66 | /* SHA constants */ |
67 | #define CONST1 0x5a827999L | |
68 | #define CONST2 0x6ed9eba1L | |
69 | #define CONST3 0x8f1bbcdcL | |
70 | #define CONST4 0xca62c1d6L | |
064af421 | 71 | |
5eccf359 BP |
72 | /* 32-bit rotate */ |
73 | static inline uint32_t | |
74 | rotate32(uint32_t x, int n) | |
75 | { | |
76 | return ((x << n) | (x >> (32 - n))); | |
064af421 BP |
77 | } |
78 | ||
5eccf359 BP |
79 | #define FUNC(n, i) \ |
80 | do { \ | |
81 | temp = rotate32(A, 5) + f##n(B, C, D) + E + W[i] + CONST##n; \ | |
82 | E = D; \ | |
83 | D = C; \ | |
84 | C = rotate32(B, 30); \ | |
85 | B = A; \ | |
86 | A = temp; \ | |
87 | } while (0) | |
88 | ||
89 | #define SHA_BLOCK_SIZE 64 | |
90 | ||
91 | /* Do SHA transformation. */ | |
92 | static void | |
93 | sha_transform(struct sha1_ctx *sha_info) | |
064af421 BP |
94 | { |
95 | int i; | |
5eccf359 | 96 | uint32_t temp, A, B, C, D, E, W[80]; |
064af421 | 97 | |
5eccf359 BP |
98 | for (i = 0; i < 16; ++i) { |
99 | W[i] = sha_info->data[i]; | |
064af421 | 100 | } |
5eccf359 BP |
101 | for (i = 16; i < 80; ++i) { |
102 | W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]; | |
103 | W[i] = rotate32(W[i], 1); | |
064af421 | 104 | } |
5eccf359 BP |
105 | A = sha_info->digest[0]; |
106 | B = sha_info->digest[1]; | |
107 | C = sha_info->digest[2]; | |
108 | D = sha_info->digest[3]; | |
109 | E = sha_info->digest[4]; | |
110 | #ifdef UNROLL_LOOPS | |
111 | FUNC(1, 0); FUNC(1, 1); FUNC(1, 2); FUNC(1, 3); FUNC(1, 4); | |
112 | FUNC(1, 5); FUNC(1, 6); FUNC(1, 7); FUNC(1, 8); FUNC(1, 9); | |
113 | FUNC(1,10); FUNC(1,11); FUNC(1,12); FUNC(1,13); FUNC(1,14); | |
114 | FUNC(1,15); FUNC(1,16); FUNC(1,17); FUNC(1,18); FUNC(1,19); | |
115 | ||
116 | FUNC(2,20); FUNC(2,21); FUNC(2,22); FUNC(2,23); FUNC(2,24); | |
117 | FUNC(2,25); FUNC(2,26); FUNC(2,27); FUNC(2,28); FUNC(2,29); | |
118 | FUNC(2,30); FUNC(2,31); FUNC(2,32); FUNC(2,33); FUNC(2,34); | |
119 | FUNC(2,35); FUNC(2,36); FUNC(2,37); FUNC(2,38); FUNC(2,39); | |
120 | ||
121 | FUNC(3,40); FUNC(3,41); FUNC(3,42); FUNC(3,43); FUNC(3,44); | |
122 | FUNC(3,45); FUNC(3,46); FUNC(3,47); FUNC(3,48); FUNC(3,49); | |
123 | FUNC(3,50); FUNC(3,51); FUNC(3,52); FUNC(3,53); FUNC(3,54); | |
124 | FUNC(3,55); FUNC(3,56); FUNC(3,57); FUNC(3,58); FUNC(3,59); | |
125 | ||
126 | FUNC(4,60); FUNC(4,61); FUNC(4,62); FUNC(4,63); FUNC(4,64); | |
127 | FUNC(4,65); FUNC(4,66); FUNC(4,67); FUNC(4,68); FUNC(4,69); | |
128 | FUNC(4,70); FUNC(4,71); FUNC(4,72); FUNC(4,73); FUNC(4,74); | |
129 | FUNC(4,75); FUNC(4,76); FUNC(4,77); FUNC(4,78); FUNC(4,79); | |
130 | #else /* !UNROLL_LOOPS */ | |
131 | for (i = 0; i < 20; ++i) { | |
132 | FUNC(1,i); | |
064af421 | 133 | } |
5eccf359 BP |
134 | for (i = 20; i < 40; ++i) { |
135 | FUNC(2,i); | |
136 | } | |
137 | for (i = 40; i < 60; ++i) { | |
138 | FUNC(3,i); | |
139 | } | |
140 | for (i = 60; i < 80; ++i) { | |
141 | FUNC(4,i); | |
064af421 | 142 | } |
5eccf359 BP |
143 | #endif /* !UNROLL_LOOPS */ |
144 | sha_info->digest[0] += A; | |
145 | sha_info->digest[1] += B; | |
146 | sha_info->digest[2] += C; | |
147 | sha_info->digest[3] += D; | |
148 | sha_info->digest[4] += E; | |
149 | } | |
064af421 | 150 | |
5eccf359 BP |
151 | /* 'count' is the number of bytes to do an endian flip. */ |
152 | static void | |
153 | maybe_byte_reverse(uint32_t *buffer, int count) | |
154 | { | |
155 | int i; | |
156 | uint8_t ct[4], *cp; | |
157 | ||
158 | #if !WORDS_BIGENDIAN | |
159 | count /= sizeof(uint32_t); | |
160 | cp = (uint8_t *) buffer; | |
161 | for (i = 0; i < count; i++) { | |
162 | ct[0] = cp[0]; | |
163 | ct[1] = cp[1]; | |
164 | ct[2] = cp[2]; | |
165 | ct[3] = cp[3]; | |
166 | cp[0] = ct[3]; | |
167 | cp[1] = ct[2]; | |
168 | cp[2] = ct[1]; | |
169 | cp[3] = ct[0]; | |
170 | cp += sizeof(uint32_t); | |
171 | } | |
172 | #endif | |
064af421 BP |
173 | } |
174 | ||
175 | /* | |
5eccf359 BP |
176 | * Initialize the SHA digest. |
177 | * context: The SHA context to initialize | |
064af421 | 178 | */ |
5eccf359 BP |
179 | void |
180 | sha1_init(struct sha1_ctx *sha_info) | |
064af421 | 181 | { |
5eccf359 BP |
182 | sha_info->digest[0] = 0x67452301L; |
183 | sha_info->digest[1] = 0xefcdab89L; | |
184 | sha_info->digest[2] = 0x98badcfeL; | |
185 | sha_info->digest[3] = 0x10325476L; | |
186 | sha_info->digest[4] = 0xc3d2e1f0L; | |
187 | sha_info->count_lo = 0L; | |
188 | sha_info->count_hi = 0L; | |
189 | sha_info->local = 0; | |
064af421 BP |
190 | } |
191 | ||
192 | /* | |
5eccf359 BP |
193 | * Update the SHA digest. |
194 | * context: The SHA1 context to update. | |
195 | * input: The buffer to add to the SHA digest. | |
196 | * inputLen: The length of the input buffer. | |
064af421 | 197 | */ |
5eccf359 BP |
198 | void |
199 | sha1_update(struct sha1_ctx *ctx, const void *buffer_, size_t count) | |
064af421 | 200 | { |
5eccf359 BP |
201 | const uint8_t *buffer = buffer_; |
202 | unsigned int i; | |
064af421 | 203 | |
5eccf359 BP |
204 | if ((ctx->count_lo + (count << 3)) < ctx->count_lo) { |
205 | ctx->count_hi++; | |
064af421 | 206 | } |
5eccf359 BP |
207 | ctx->count_lo += count << 3; |
208 | ctx->count_hi += count >> 29; | |
209 | if (ctx->local) { | |
210 | i = SHA_BLOCK_SIZE - ctx->local; | |
211 | if (i > count) { | |
212 | i = count; | |
213 | } | |
214 | memcpy(((uint8_t *) ctx->data) + ctx->local, buffer, i); | |
215 | count -= i; | |
216 | buffer += i; | |
217 | ctx->local += i; | |
218 | if (ctx->local == SHA_BLOCK_SIZE) { | |
219 | maybe_byte_reverse(ctx->data, SHA_BLOCK_SIZE); | |
220 | sha_transform(ctx); | |
221 | } else { | |
222 | return; | |
223 | } | |
064af421 | 224 | } |
5eccf359 BP |
225 | while (count >= SHA_BLOCK_SIZE) { |
226 | memcpy(ctx->data, buffer, SHA_BLOCK_SIZE); | |
227 | buffer += SHA_BLOCK_SIZE; | |
228 | count -= SHA_BLOCK_SIZE; | |
229 | maybe_byte_reverse(ctx->data, SHA_BLOCK_SIZE); | |
230 | sha_transform(ctx); | |
064af421 | 231 | } |
5eccf359 BP |
232 | memcpy(ctx->data, buffer, count); |
233 | ctx->local = count; | |
064af421 BP |
234 | } |
235 | ||
064af421 | 236 | /* |
5eccf359 BP |
237 | * Finish computing the SHA digest. |
238 | * digest: the output buffer in which to store the digest. | |
239 | * context: The context to finalize. | |
064af421 | 240 | */ |
5eccf359 BP |
241 | void |
242 | sha1_final(struct sha1_ctx *ctx, uint8_t digest[SHA1_DIGEST_SIZE]) | |
064af421 | 243 | { |
5eccf359 BP |
244 | int count, i, j; |
245 | uint32_t lo_bit_count, hi_bit_count, k; | |
246 | ||
247 | lo_bit_count = ctx->count_lo; | |
248 | hi_bit_count = ctx->count_hi; | |
249 | count = (int) ((lo_bit_count >> 3) & 0x3f); | |
250 | ((uint8_t *) ctx->data)[count++] = 0x80; | |
251 | if (count > SHA_BLOCK_SIZE - 8) { | |
252 | memset(((uint8_t *) ctx->data) + count, 0, SHA_BLOCK_SIZE - count); | |
253 | maybe_byte_reverse(ctx->data, SHA_BLOCK_SIZE); | |
254 | sha_transform(ctx); | |
255 | memset((uint8_t *) ctx->data, 0, SHA_BLOCK_SIZE - 8); | |
256 | } else { | |
257 | memset(((uint8_t *) ctx->data) + count, 0, | |
258 | SHA_BLOCK_SIZE - 8 - count); | |
064af421 | 259 | } |
5eccf359 BP |
260 | maybe_byte_reverse(ctx->data, SHA_BLOCK_SIZE); |
261 | ctx->data[14] = hi_bit_count; | |
262 | ctx->data[15] = lo_bit_count; | |
263 | sha_transform(ctx); | |
264 | ||
265 | for (i = j = 0; j < SHA1_DIGEST_SIZE; i++) { | |
266 | k = ctx->digest[i]; | |
267 | digest[j++] = k >> 24; | |
268 | digest[j++] = k >> 16; | |
269 | digest[j++] = k >> 8; | |
270 | digest[j++] = k; | |
064af421 | 271 | } |
064af421 BP |
272 | } |
273 | ||
5eccf359 | 274 | /* Computes the hash of 'n' bytes in 'data' into 'digest'. */ |
064af421 | 275 | void |
5eccf359 | 276 | sha1_bytes(const void *data, size_t n, uint8_t digest[SHA1_DIGEST_SIZE]) |
064af421 | 277 | { |
5eccf359 BP |
278 | struct sha1_ctx ctx; |
279 | ||
280 | sha1_init(&ctx); | |
281 | sha1_update(&ctx, data, n); | |
282 | sha1_final(&ctx, digest); | |
064af421 | 283 | } |
e7f1bf58 BP |
284 | |
285 | void | |
286 | sha1_to_hex(const uint8_t digest[SHA1_DIGEST_SIZE], | |
287 | char hex[SHA1_HEX_DIGEST_LEN + 1]) | |
288 | { | |
289 | int i; | |
290 | ||
291 | for (i = 0; i < SHA1_DIGEST_SIZE; i++) { | |
292 | *hex++ = "0123456789abcdef"[digest[i] >> 4]; | |
293 | *hex++ = "0123456789abcdef"[digest[i] & 15]; | |
294 | } | |
295 | *hex = '\0'; | |
296 | } | |
297 | ||
298 | bool | |
299 | sha1_from_hex(uint8_t digest[SHA1_DIGEST_SIZE], const char *hex) | |
300 | { | |
301 | int i; | |
302 | ||
303 | for (i = 0; i < SHA1_DIGEST_SIZE; i++) { | |
bf971267 BP |
304 | bool ok; |
305 | ||
306 | digest[i] = hexits_value(hex, 2, &ok); | |
307 | if (!ok) { | |
e7f1bf58 BP |
308 | return false; |
309 | } | |
e7f1bf58 BP |
310 | hex += 2; |
311 | } | |
312 | return true; | |
313 | } | |
314 |