/src/openvswitch/lib/sha1.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * This file is from the Apache Portable Runtime Library. |
3 | | * The full upstream copyright and license statement is included below. |
4 | | * Modifications copyright (c) 2009, 2010 Nicira, Inc. |
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 |
13 | | * |
14 | | * http://www.apache.org/licenses/LICENSE-2.0 |
15 | | * |
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: |
24 | | * |
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 |
30 | | */ |
31 | | |
32 | | #include <config.h> |
33 | | #include "sha1.h" |
34 | | |
35 | | #ifdef HAVE_OPENSSL |
36 | | #include <openssl/err.h> |
37 | | #include <openssl/evp.h> |
38 | | #endif |
39 | | |
40 | | #include <ctype.h> |
41 | | #include <string.h> |
42 | | #include "compiler.h" |
43 | | #include "openvswitch/vlog.h" |
44 | | #include "util.h" |
45 | | |
46 | | VLOG_DEFINE_THIS_MODULE(sha1); |
47 | | |
48 | | #ifdef HAVE_OPENSSL |
49 | | static void |
50 | | log_openssl_err(const char *func) |
51 | 0 | { |
52 | 0 | char buf[1024]; |
53 | |
|
54 | 0 | ERR_error_string_n(ERR_get_error(), buf, 1024); |
55 | 0 | VLOG_FATAL("%s failed: %s", func, buf); |
56 | 0 | } |
57 | | #endif |
58 | | |
59 | | /* |
60 | | * Initialize the SHA digest. |
61 | | * context: The SHA context to initialize |
62 | | */ |
63 | | void |
64 | | sha1_init(struct sha1_ctx *sha_info) |
65 | 0 | { |
66 | 0 | #ifdef HAVE_OPENSSL |
67 | 0 | sha_info->ctx = EVP_MD_CTX_create(); |
68 | 0 | if (!EVP_DigestInit_ex(sha_info->ctx, EVP_sha1(), NULL)) { |
69 | 0 | log_openssl_err("EVP_DigestInit_ex"); |
70 | 0 | } |
71 | | #else |
72 | | ovs_sha1_init(sha_info); |
73 | | #endif |
74 | 0 | } |
75 | | |
76 | | /* |
77 | | * Update the SHA digest. |
78 | | * context: The SHA1 context to update. |
79 | | * input: The buffer to add to the SHA digest. |
80 | | * inputLen: The length of the input buffer. |
81 | | */ |
82 | | void |
83 | | sha1_update(struct sha1_ctx *ctx, const void *buffer_, uint32_t count) |
84 | 0 | { |
85 | 0 | #ifdef HAVE_OPENSSL |
86 | 0 | if (!EVP_DigestUpdate(ctx->ctx, buffer_, count)) { |
87 | 0 | log_openssl_err("EVP_DigestUpdate"); |
88 | 0 | } |
89 | | #else |
90 | | ovs_sha1_update(ctx, buffer_, count); |
91 | | #endif |
92 | 0 | } |
93 | | |
94 | | /* |
95 | | * Finish computing the SHA digest. |
96 | | * digest: the output buffer in which to store the digest. |
97 | | * context: The context to finalize. |
98 | | */ |
99 | | void |
100 | | sha1_final(struct sha1_ctx *ctx, uint8_t digest[SHA1_DIGEST_SIZE]) |
101 | 0 | { |
102 | 0 | #ifdef HAVE_OPENSSL |
103 | 0 | unsigned int len; |
104 | |
|
105 | 0 | if (!EVP_DigestFinal_ex(ctx->ctx, digest, &len)) { |
106 | 0 | log_openssl_err("EVP_DigestFinal_ex"); |
107 | 0 | } |
108 | 0 | ovs_assert(len == SHA1_DIGEST_SIZE); |
109 | 0 | EVP_MD_CTX_destroy(ctx->ctx); |
110 | | #else |
111 | | ovs_sha1_final(ctx, digest); |
112 | | #endif |
113 | 0 | } |
114 | | |
115 | | /* Computes the hash of 'n' bytes in 'data' into 'digest'. */ |
116 | | void |
117 | | sha1_bytes(const void *data, uint32_t n, uint8_t digest[SHA1_DIGEST_SIZE]) |
118 | 0 | { |
119 | 0 | struct sha1_ctx ctx; |
120 | |
|
121 | 0 | sha1_init(&ctx); |
122 | 0 | sha1_update(&ctx, data, n); |
123 | 0 | sha1_final(&ctx, digest); |
124 | 0 | } |
125 | | |
126 | | void |
127 | | sha1_to_hex(const uint8_t digest[SHA1_DIGEST_SIZE], |
128 | | char hex[SHA1_HEX_DIGEST_LEN + 1]) |
129 | 0 | { |
130 | 0 | int i; |
131 | |
|
132 | 0 | for (i = 0; i < SHA1_DIGEST_SIZE; i++) { |
133 | 0 | *hex++ = "0123456789abcdef"[digest[i] >> 4]; |
134 | 0 | *hex++ = "0123456789abcdef"[digest[i] & 15]; |
135 | 0 | } |
136 | 0 | *hex = '\0'; |
137 | 0 | } |
138 | | |
139 | | bool |
140 | | sha1_from_hex(uint8_t digest[SHA1_DIGEST_SIZE], const char *hex) |
141 | 0 | { |
142 | 0 | int i; |
143 | |
|
144 | 0 | for (i = 0; i < SHA1_DIGEST_SIZE; i++) { |
145 | 0 | bool ok; |
146 | |
|
147 | 0 | digest[i] = hexits_value(hex, 2, &ok); |
148 | 0 | if (!ok) { |
149 | 0 | return false; |
150 | 0 | } |
151 | 0 | hex += 2; |
152 | 0 | } |
153 | 0 | return true; |
154 | 0 | } |
155 | | |
156 | | /* Generic implementation for the case where OpenSSL is not available. */ |
157 | | |
158 | | /* A bit faster & bigger, if defined */ |
159 | | #define UNROLL_LOOPS |
160 | | |
161 | | /* SHA f()-functions */ |
162 | | static inline uint32_t |
163 | | f1(uint32_t x, uint32_t y, uint32_t z) |
164 | 0 | { |
165 | 0 | return (x & y) | (~x & z); |
166 | 0 | } |
167 | | |
168 | | static inline uint32_t |
169 | | f2(uint32_t x, uint32_t y, uint32_t z) |
170 | 0 | { |
171 | 0 | return x ^ y ^ z; |
172 | 0 | } |
173 | | |
174 | | static inline uint32_t |
175 | | f3(uint32_t x, uint32_t y, uint32_t z) |
176 | 0 | { |
177 | 0 | return (x & y) | (x & z) | (y & z); |
178 | 0 | } |
179 | | |
180 | | static inline uint32_t |
181 | | f4(uint32_t x, uint32_t y, uint32_t z) |
182 | 0 | { |
183 | 0 | return x ^ y ^ z; |
184 | 0 | } |
185 | | |
186 | | /* SHA constants */ |
187 | 0 | #define CONST1 0x5a827999L |
188 | 0 | #define CONST2 0x6ed9eba1L |
189 | 0 | #define CONST3 0x8f1bbcdcL |
190 | 0 | #define CONST4 0xca62c1d6L |
191 | | |
192 | | /* 32-bit rotate */ |
193 | | static inline uint32_t |
194 | | rotate32(uint32_t x, int n) |
195 | 0 | { |
196 | 0 | return ((x << n) | (x >> (32 - n))); |
197 | 0 | } |
198 | | |
199 | | #define FUNC(n, i) \ |
200 | 0 | do { \ |
201 | 0 | temp = rotate32(A, 5) + f##n(B, C, D) + E + W[i] + CONST##n; \ |
202 | 0 | E = D; \ |
203 | 0 | D = C; \ |
204 | 0 | C = rotate32(B, 30); \ |
205 | 0 | B = A; \ |
206 | 0 | A = temp; \ |
207 | 0 | } while (0) |
208 | | |
209 | 0 | #define SHA_BLOCK_SIZE 64 |
210 | | |
211 | | /* Do SHA transformation. */ |
212 | | static void |
213 | | sha_transform(struct sha1_ctx *sha_info) |
214 | 0 | { |
215 | 0 | int i; |
216 | 0 | uint32_t temp, A, B, C, D, E, W[80]; |
217 | |
|
218 | 0 | for (i = 0; i < 16; ++i) { |
219 | 0 | W[i] = sha_info->data[i]; |
220 | 0 | } |
221 | 0 | for (i = 16; i < 80; ++i) { |
222 | 0 | W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]; |
223 | 0 | W[i] = rotate32(W[i], 1); |
224 | 0 | } |
225 | 0 | A = sha_info->digest[0]; |
226 | 0 | B = sha_info->digest[1]; |
227 | 0 | C = sha_info->digest[2]; |
228 | 0 | D = sha_info->digest[3]; |
229 | 0 | E = sha_info->digest[4]; |
230 | 0 | #ifdef UNROLL_LOOPS |
231 | 0 | FUNC(1, 0); FUNC(1, 1); FUNC(1, 2); FUNC(1, 3); FUNC(1, 4); |
232 | 0 | FUNC(1, 5); FUNC(1, 6); FUNC(1, 7); FUNC(1, 8); FUNC(1, 9); |
233 | 0 | FUNC(1,10); FUNC(1,11); FUNC(1,12); FUNC(1,13); FUNC(1,14); |
234 | 0 | FUNC(1,15); FUNC(1,16); FUNC(1,17); FUNC(1,18); FUNC(1,19); |
235 | |
|
236 | 0 | FUNC(2,20); FUNC(2,21); FUNC(2,22); FUNC(2,23); FUNC(2,24); |
237 | 0 | FUNC(2,25); FUNC(2,26); FUNC(2,27); FUNC(2,28); FUNC(2,29); |
238 | 0 | FUNC(2,30); FUNC(2,31); FUNC(2,32); FUNC(2,33); FUNC(2,34); |
239 | 0 | FUNC(2,35); FUNC(2,36); FUNC(2,37); FUNC(2,38); FUNC(2,39); |
240 | |
|
241 | 0 | FUNC(3,40); FUNC(3,41); FUNC(3,42); FUNC(3,43); FUNC(3,44); |
242 | 0 | FUNC(3,45); FUNC(3,46); FUNC(3,47); FUNC(3,48); FUNC(3,49); |
243 | 0 | FUNC(3,50); FUNC(3,51); FUNC(3,52); FUNC(3,53); FUNC(3,54); |
244 | 0 | FUNC(3,55); FUNC(3,56); FUNC(3,57); FUNC(3,58); FUNC(3,59); |
245 | |
|
246 | 0 | FUNC(4,60); FUNC(4,61); FUNC(4,62); FUNC(4,63); FUNC(4,64); |
247 | 0 | FUNC(4,65); FUNC(4,66); FUNC(4,67); FUNC(4,68); FUNC(4,69); |
248 | 0 | FUNC(4,70); FUNC(4,71); FUNC(4,72); FUNC(4,73); FUNC(4,74); |
249 | 0 | FUNC(4,75); FUNC(4,76); FUNC(4,77); FUNC(4,78); FUNC(4,79); |
250 | | #else /* !UNROLL_LOOPS */ |
251 | | for (i = 0; i < 20; ++i) { |
252 | | FUNC(1,i); |
253 | | } |
254 | | for (i = 20; i < 40; ++i) { |
255 | | FUNC(2,i); |
256 | | } |
257 | | for (i = 40; i < 60; ++i) { |
258 | | FUNC(3,i); |
259 | | } |
260 | | for (i = 60; i < 80; ++i) { |
261 | | FUNC(4,i); |
262 | | } |
263 | | #endif /* !UNROLL_LOOPS */ |
264 | 0 | sha_info->digest[0] += A; |
265 | 0 | sha_info->digest[1] += B; |
266 | 0 | sha_info->digest[2] += C; |
267 | 0 | sha_info->digest[3] += D; |
268 | 0 | sha_info->digest[4] += E; |
269 | 0 | } |
270 | | |
271 | | /* 'count' is the number of bytes to do an endian flip. */ |
272 | | static void |
273 | | maybe_byte_reverse(uint32_t *buffer OVS_UNUSED, int count OVS_UNUSED) |
274 | 0 | { |
275 | 0 | #if !WORDS_BIGENDIAN |
276 | 0 | int i; |
277 | 0 | uint8_t ct[4], *cp; |
278 | |
|
279 | 0 | count /= sizeof(uint32_t); |
280 | 0 | cp = (uint8_t *) buffer; |
281 | 0 | for (i = 0; i < count; i++) { |
282 | 0 | ct[0] = cp[0]; |
283 | 0 | ct[1] = cp[1]; |
284 | 0 | ct[2] = cp[2]; |
285 | 0 | ct[3] = cp[3]; |
286 | 0 | cp[0] = ct[3]; |
287 | 0 | cp[1] = ct[2]; |
288 | 0 | cp[2] = ct[1]; |
289 | 0 | cp[3] = ct[0]; |
290 | 0 | cp += sizeof(uint32_t); |
291 | 0 | } |
292 | 0 | #endif |
293 | 0 | } |
294 | | |
295 | | /* |
296 | | * Initialize the SHA digest. |
297 | | * context: The SHA context to initialize |
298 | | */ |
299 | | void |
300 | | ovs_sha1_init(struct sha1_ctx *sha_info) |
301 | 0 | { |
302 | 0 | sha_info->digest[0] = 0x67452301L; |
303 | 0 | sha_info->digest[1] = 0xefcdab89L; |
304 | 0 | sha_info->digest[2] = 0x98badcfeL; |
305 | 0 | sha_info->digest[3] = 0x10325476L; |
306 | 0 | sha_info->digest[4] = 0xc3d2e1f0L; |
307 | 0 | sha_info->count_lo = 0L; |
308 | 0 | sha_info->count_hi = 0L; |
309 | 0 | sha_info->local = 0; |
310 | 0 | } |
311 | | |
312 | | /* |
313 | | * Update the SHA digest. |
314 | | * context: The SHA1 context to update. |
315 | | * input: The buffer to add to the SHA digest. |
316 | | * inputLen: The length of the input buffer. |
317 | | */ |
318 | | void |
319 | | ovs_sha1_update(struct sha1_ctx *ctx, const void *buffer_, uint32_t count) |
320 | 0 | { |
321 | 0 | const uint8_t *buffer = buffer_; |
322 | 0 | unsigned int i; |
323 | |
|
324 | 0 | if ((ctx->count_lo + (count << 3)) < ctx->count_lo) { |
325 | 0 | ctx->count_hi++; |
326 | 0 | } |
327 | 0 | ctx->count_lo += count << 3; |
328 | 0 | ctx->count_hi += count >> 29; |
329 | 0 | if (ctx->local) { |
330 | 0 | i = SHA_BLOCK_SIZE - ctx->local; |
331 | 0 | if (i > count) { |
332 | 0 | i = count; |
333 | 0 | } |
334 | 0 | memcpy(((uint8_t *) ctx->data) + ctx->local, buffer, i); |
335 | 0 | count -= i; |
336 | 0 | buffer += i; |
337 | 0 | ctx->local += i; |
338 | 0 | if (ctx->local == SHA_BLOCK_SIZE) { |
339 | 0 | maybe_byte_reverse(ctx->data, SHA_BLOCK_SIZE); |
340 | 0 | sha_transform(ctx); |
341 | 0 | } else { |
342 | 0 | return; |
343 | 0 | } |
344 | 0 | } |
345 | 0 | while (count >= SHA_BLOCK_SIZE) { |
346 | 0 | memcpy(ctx->data, buffer, SHA_BLOCK_SIZE); |
347 | 0 | buffer += SHA_BLOCK_SIZE; |
348 | 0 | count -= SHA_BLOCK_SIZE; |
349 | 0 | maybe_byte_reverse(ctx->data, SHA_BLOCK_SIZE); |
350 | 0 | sha_transform(ctx); |
351 | 0 | } |
352 | 0 | memcpy(ctx->data, buffer, count); |
353 | 0 | ctx->local = count; |
354 | 0 | } |
355 | | |
356 | | /* |
357 | | * Finish computing the SHA digest. |
358 | | * digest: the output buffer in which to store the digest. |
359 | | * context: The context to finalize. |
360 | | */ |
361 | | void |
362 | | ovs_sha1_final(struct sha1_ctx *ctx, uint8_t digest[SHA1_DIGEST_SIZE]) |
363 | 0 | { |
364 | 0 | int count, i, j; |
365 | 0 | uint32_t lo_bit_count, hi_bit_count, k; |
366 | |
|
367 | 0 | lo_bit_count = ctx->count_lo; |
368 | 0 | hi_bit_count = ctx->count_hi; |
369 | 0 | count = (int) ((lo_bit_count >> 3) & 0x3f); |
370 | 0 | ((uint8_t *) ctx->data)[count++] = 0x80; |
371 | 0 | if (count > SHA_BLOCK_SIZE - 8) { |
372 | 0 | memset(((uint8_t *) ctx->data) + count, 0, SHA_BLOCK_SIZE - count); |
373 | 0 | maybe_byte_reverse(ctx->data, SHA_BLOCK_SIZE); |
374 | 0 | sha_transform(ctx); |
375 | 0 | memset((uint8_t *) ctx->data, 0, SHA_BLOCK_SIZE - 8); |
376 | 0 | } else { |
377 | 0 | memset(((uint8_t *) ctx->data) + count, 0, |
378 | 0 | SHA_BLOCK_SIZE - 8 - count); |
379 | 0 | } |
380 | 0 | maybe_byte_reverse(ctx->data, SHA_BLOCK_SIZE); |
381 | 0 | ctx->data[14] = hi_bit_count; |
382 | 0 | ctx->data[15] = lo_bit_count; |
383 | 0 | sha_transform(ctx); |
384 | |
|
385 | 0 | for (i = j = 0; j < SHA1_DIGEST_SIZE; i++) { |
386 | 0 | k = ctx->digest[i]; |
387 | 0 | digest[j++] = k >> 24; |
388 | 0 | digest[j++] = k >> 16; |
389 | 0 | digest[j++] = k >> 8; |
390 | 0 | digest[j++] = k; |
391 | 0 | } |
392 | 0 | } |
393 | | |
394 | | /* Computes the hash of 'n' bytes in 'data' into 'digest'. */ |
395 | | void |
396 | | ovs_sha1_bytes(const void *data, uint32_t n, uint8_t digest[SHA1_DIGEST_SIZE]) |
397 | 0 | { |
398 | 0 | struct sha1_ctx ctx; |
399 | |
|
400 | 0 | ovs_sha1_init(&ctx); |
401 | 0 | ovs_sha1_update(&ctx, data, n); |
402 | 0 | ovs_sha1_final(&ctx, digest); |
403 | 0 | } |