1 /*
2 * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3 */
4 #include "linkkit/infra/infra_config.h"
5
6 #ifdef INFRA_SHA1
7
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include "linkkit/infra/infra_sha1.h"
12
13 #define SHA1_KEY_IOPAD_SIZE (64)
14 #define SHA1_DIGEST_SIZE (20)
15
16 /* Implementation that should never be optimized out by the compiler */
utils_sha1_zeroize(void * v,uint32_t n)17 static void utils_sha1_zeroize(void *v, uint32_t n)
18 {
19 volatile unsigned char *p = (unsigned char *)v; // avoid be optimized by the compiler
20 while (n--)
21 *p++ = 0;
22 }
23
24 /*
25 * 32-bit integer manipulation macros (big endian)
26 */
27 #ifndef GET_UINT32_BE
28 #define GET_UINT32_BE(n, b, i) \
29 { \
30 (n) = ((uint32_t)(b)[(i)] << 24) | ((uint32_t)(b)[(i) + 1] << 16) | \
31 ((uint32_t)(b)[(i) + 2] << 8) | ((uint32_t)(b)[(i) + 3]); \
32 }
33 #endif
34
35 #ifndef PUT_UINT32_BE
36 #define PUT_UINT32_BE(n, b, i) \
37 { \
38 (b)[(i)] = (unsigned char)((n) >> 24); \
39 (b)[(i) + 1] = (unsigned char)((n) >> 16); \
40 (b)[(i) + 2] = (unsigned char)((n) >> 8); \
41 (b)[(i) + 3] = (unsigned char)((n)); \
42 }
43 #endif
44
utils_sha1_init(iot_sha1_context * ctx)45 void utils_sha1_init(iot_sha1_context *ctx)
46 {
47 memset(ctx, 0, sizeof(iot_sha1_context));
48 }
49
utils_sha1_free(iot_sha1_context * ctx)50 void utils_sha1_free(iot_sha1_context *ctx)
51 {
52 if (ctx == NULL) {
53 return;
54 }
55
56 utils_sha1_zeroize(ctx, sizeof(iot_sha1_context));
57 }
58
utils_sha1_clone(iot_sha1_context * dst,const iot_sha1_context * src)59 void utils_sha1_clone(iot_sha1_context *dst, const iot_sha1_context *src)
60 {
61 *dst = *src;
62 }
63
64 /*
65 * SHA-1 context setup
66 */
utils_sha1_starts(iot_sha1_context * ctx)67 void utils_sha1_starts(iot_sha1_context *ctx)
68 {
69 ctx->total[0] = 0;
70 ctx->total[1] = 0;
71
72 ctx->state[0] = 0x67452301;
73 ctx->state[1] = 0xEFCDAB89;
74 ctx->state[2] = 0x98BADCFE;
75 ctx->state[3] = 0x10325476;
76 ctx->state[4] = 0xC3D2E1F0;
77 }
78
utils_sha1_process(iot_sha1_context * ctx,const unsigned char data[64])79 void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64])
80 {
81 uint32_t temp, W[16], A, B, C, D, E;
82
83 GET_UINT32_BE(W[0], data, 0);
84 GET_UINT32_BE(W[1], data, 4);
85 GET_UINT32_BE(W[2], data, 8);
86 GET_UINT32_BE(W[3], data, 12);
87 GET_UINT32_BE(W[4], data, 16);
88 GET_UINT32_BE(W[5], data, 20);
89 GET_UINT32_BE(W[6], data, 24);
90 GET_UINT32_BE(W[7], data, 28);
91 GET_UINT32_BE(W[8], data, 32);
92 GET_UINT32_BE(W[9], data, 36);
93 GET_UINT32_BE(W[10], data, 40);
94 GET_UINT32_BE(W[11], data, 44);
95 GET_UINT32_BE(W[12], data, 48);
96 GET_UINT32_BE(W[13], data, 52);
97 GET_UINT32_BE(W[14], data, 56);
98 GET_UINT32_BE(W[15], data, 60);
99
100 #define S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
101
102 #define R(t) \
103 (temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ W[(t - 14) & 0x0F] ^ \
104 W[t & 0x0F], \
105 (W[t & 0x0F] = S(temp, 1)))
106
107 #define P(a, b, c, d, e, x) \
108 { \
109 e += S(a, 5) + F(b, c, d) + K + x; \
110 b = S(b, 30); \
111 }
112
113 A = ctx->state[0];
114 B = ctx->state[1];
115 C = ctx->state[2];
116 D = ctx->state[3];
117 E = ctx->state[4];
118
119 #define F(x, y, z) (z ^ (x & (y ^ z)))
120 #define K 0x5A827999
121
122 P(A, B, C, D, E, W[0]);
123 P(E, A, B, C, D, W[1]);
124 P(D, E, A, B, C, W[2]);
125 P(C, D, E, A, B, W[3]);
126 P(B, C, D, E, A, W[4]);
127 P(A, B, C, D, E, W[5]);
128 P(E, A, B, C, D, W[6]);
129 P(D, E, A, B, C, W[7]);
130 P(C, D, E, A, B, W[8]);
131 P(B, C, D, E, A, W[9]);
132 P(A, B, C, D, E, W[10]);
133 P(E, A, B, C, D, W[11]);
134 P(D, E, A, B, C, W[12]);
135 P(C, D, E, A, B, W[13]);
136 P(B, C, D, E, A, W[14]);
137 P(A, B, C, D, E, W[15]);
138 P(E, A, B, C, D, R(16));
139 P(D, E, A, B, C, R(17));
140 P(C, D, E, A, B, R(18));
141 P(B, C, D, E, A, R(19));
142
143 #undef K
144 #undef F
145
146 #define F(x, y, z) (x ^ y ^ z)
147 #define K 0x6ED9EBA1
148
149 P(A, B, C, D, E, R(20));
150 P(E, A, B, C, D, R(21));
151 P(D, E, A, B, C, R(22));
152 P(C, D, E, A, B, R(23));
153 P(B, C, D, E, A, R(24));
154 P(A, B, C, D, E, R(25));
155 P(E, A, B, C, D, R(26));
156 P(D, E, A, B, C, R(27));
157 P(C, D, E, A, B, R(28));
158 P(B, C, D, E, A, R(29));
159 P(A, B, C, D, E, R(30));
160 P(E, A, B, C, D, R(31));
161 P(D, E, A, B, C, R(32));
162 P(C, D, E, A, B, R(33));
163 P(B, C, D, E, A, R(34));
164 P(A, B, C, D, E, R(35));
165 P(E, A, B, C, D, R(36));
166 P(D, E, A, B, C, R(37));
167 P(C, D, E, A, B, R(38));
168 P(B, C, D, E, A, R(39));
169
170 #undef K
171 #undef F
172
173 #define F(x, y, z) ((x & y) | (z & (x | y)))
174 #define K 0x8F1BBCDC
175
176 P(A, B, C, D, E, R(40));
177 P(E, A, B, C, D, R(41));
178 P(D, E, A, B, C, R(42));
179 P(C, D, E, A, B, R(43));
180 P(B, C, D, E, A, R(44));
181 P(A, B, C, D, E, R(45));
182 P(E, A, B, C, D, R(46));
183 P(D, E, A, B, C, R(47));
184 P(C, D, E, A, B, R(48));
185 P(B, C, D, E, A, R(49));
186 P(A, B, C, D, E, R(50));
187 P(E, A, B, C, D, R(51));
188 P(D, E, A, B, C, R(52));
189 P(C, D, E, A, B, R(53));
190 P(B, C, D, E, A, R(54));
191 P(A, B, C, D, E, R(55));
192 P(E, A, B, C, D, R(56));
193 P(D, E, A, B, C, R(57));
194 P(C, D, E, A, B, R(58));
195 P(B, C, D, E, A, R(59));
196
197 #undef K
198 #undef F
199
200 #define F(x, y, z) (x ^ y ^ z)
201 #define K 0xCA62C1D6
202
203 P(A, B, C, D, E, R(60));
204 P(E, A, B, C, D, R(61));
205 P(D, E, A, B, C, R(62));
206 P(C, D, E, A, B, R(63));
207 P(B, C, D, E, A, R(64));
208 P(A, B, C, D, E, R(65));
209 P(E, A, B, C, D, R(66));
210 P(D, E, A, B, C, R(67));
211 P(C, D, E, A, B, R(68));
212 P(B, C, D, E, A, R(69));
213 P(A, B, C, D, E, R(70));
214 P(E, A, B, C, D, R(71));
215 P(D, E, A, B, C, R(72));
216 P(C, D, E, A, B, R(73));
217 P(B, C, D, E, A, R(74));
218 P(A, B, C, D, E, R(75));
219 P(E, A, B, C, D, R(76));
220 P(D, E, A, B, C, R(77));
221 P(C, D, E, A, B, R(78));
222 P(B, C, D, E, A, R(79));
223
224 #undef K
225 #undef F
226
227 ctx->state[0] += A;
228 ctx->state[1] += B;
229 ctx->state[2] += C;
230 ctx->state[3] += D;
231 ctx->state[4] += E;
232 }
233
234 /*
235 * SHA-1 process buffer
236 */
utils_sha1_update(iot_sha1_context * ctx,const unsigned char * input,uint32_t ilen)237 void utils_sha1_update(iot_sha1_context *ctx, const unsigned char *input,
238 uint32_t ilen)
239 {
240 uint32_t fill;
241 uint32_t left;
242
243 if (ilen == 0)
244 return;
245
246 left = ctx->total[0] & 0x3F;
247 fill = 64 - left;
248
249 ctx->total[0] += (uint32_t)ilen;
250 ctx->total[0] &= 0xFFFFFFFF;
251
252 if (ctx->total[0] < (uint32_t)ilen)
253 ctx->total[1]++;
254
255 if (left && ilen >= fill) {
256 memcpy((void *)(ctx->buffer + left), input, fill);
257 utils_sha1_process(ctx, ctx->buffer);
258 input += fill;
259 ilen -= fill;
260 left = 0;
261 }
262
263 while (ilen >= 64) {
264 utils_sha1_process(ctx, input);
265 input += 64;
266 ilen -= 64;
267 }
268
269 if (ilen > 0)
270 memcpy((void *)(ctx->buffer + left), input, ilen);
271 }
272
273 static const unsigned char sha1_padding[64] = {
274 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
275 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
276 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
277 };
278
279 /*
280 * SHA-1 final digest
281 */
utils_sha1_finish(iot_sha1_context * ctx,unsigned char output[20])282 void utils_sha1_finish(iot_sha1_context *ctx, unsigned char output[20])
283 {
284 uint32_t last, padn;
285 uint32_t high, low;
286 unsigned char msglen[8];
287
288 high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
289 low = (ctx->total[0] << 3);
290
291 PUT_UINT32_BE(high, msglen, 0);
292 PUT_UINT32_BE(low, msglen, 4);
293
294 last = ctx->total[0] & 0x3F;
295 padn = (last < 56) ? (56 - last) : (120 - last);
296
297 utils_sha1_update(ctx, sha1_padding, padn);
298 utils_sha1_update(ctx, msglen, 8);
299
300 PUT_UINT32_BE(ctx->state[0], output, 0);
301 PUT_UINT32_BE(ctx->state[1], output, 4);
302 PUT_UINT32_BE(ctx->state[2], output, 8);
303 PUT_UINT32_BE(ctx->state[3], output, 12);
304 PUT_UINT32_BE(ctx->state[4], output, 16);
305 }
306
307 /*
308 * output = SHA-1( input buffer )
309 */
utils_sha1(const unsigned char * input,uint32_t ilen,unsigned char output[20])310 void utils_sha1(const unsigned char *input, uint32_t ilen,
311 unsigned char output[20])
312 {
313 iot_sha1_context ctx;
314
315 utils_sha1_init(&ctx);
316 utils_sha1_starts(&ctx);
317 utils_sha1_update(&ctx, input, ilen);
318 utils_sha1_finish(&ctx, output);
319 utils_sha1_free(&ctx);
320 }
321
utils_hb2hex(uint8_t hb)322 static int8_t utils_hb2hex(uint8_t hb)
323 {
324 hb = hb & 0xF;
325 return (int8_t)(hb < 10 ? '0' + hb : hb - 10 + 'a');
326 }
327
utils_hmac_sha1(const char * msg,int msg_len,char * digest,const char * key,int key_len)328 void utils_hmac_sha1(const char *msg, int msg_len, char *digest,
329 const char *key, int key_len)
330 {
331 iot_sha1_context context;
332 unsigned char
333 k_ipad[SHA1_KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */
334 unsigned char
335 k_opad[SHA1_KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */
336 unsigned char out[SHA1_DIGEST_SIZE];
337 int i;
338
339 if ((NULL == msg) || (NULL == digest) || (NULL == key)) {
340 return;
341 }
342
343 if (key_len > SHA1_KEY_IOPAD_SIZE) {
344 return;
345 }
346
347 /* start out by storing key in pads */
348 memset(k_ipad, 0, sizeof(k_ipad));
349 memset(k_opad, 0, sizeof(k_opad));
350 memcpy(k_ipad, key, key_len);
351 memcpy(k_opad, key, key_len);
352
353 /* XOR key with ipad and opad values */
354 for (i = 0; i < SHA1_KEY_IOPAD_SIZE; i++) {
355 k_ipad[i] ^= 0x36;
356 k_opad[i] ^= 0x5c;
357 }
358
359 /* perform inner SHA */
360 utils_sha1_init(&context); /* init context for 1st pass */
361 utils_sha1_starts(&context); /* setup context for 1st pass */
362 utils_sha1_update(&context, k_ipad,
363 SHA1_KEY_IOPAD_SIZE); /* start with inner pad */
364 utils_sha1_update(&context, (unsigned char *)msg,
365 msg_len); /* then text of datagram */
366 utils_sha1_finish(&context, out); /* finish up 1st pass */
367
368 /* perform outer SHA */
369 utils_sha1_init(&context); /* init context for 2nd pass */
370 utils_sha1_starts(&context); /* setup context for 2nd pass */
371 utils_sha1_update(&context, k_opad,
372 SHA1_KEY_IOPAD_SIZE); /* start with outer pad */
373 utils_sha1_update(&context, out,
374 SHA1_DIGEST_SIZE); /* then results of 1st hash */
375 utils_sha1_finish(&context, out); /* finish up 2nd pass */
376
377 for (i = 0; i < SHA1_DIGEST_SIZE; ++i) {
378 digest[i * 2] = utils_hb2hex(out[i] >> 4);
379 digest[i * 2 + 1] = utils_hb2hex(out[i]);
380 }
381 }
382
utils_hmac_sha1_hex(const char * msg,int msg_len,char * digest,const char * key,int key_len)383 void utils_hmac_sha1_hex(const char *msg, int msg_len, char *digest,
384 const char *key, int key_len)
385 {
386 iot_sha1_context context;
387 unsigned char
388 k_ipad[SHA1_KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */
389 unsigned char
390 k_opad[SHA1_KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */
391 unsigned char out[SHA1_DIGEST_SIZE];
392 int i;
393
394 if ((NULL == msg) || (NULL == digest) || (NULL == key)) {
395 return;
396 }
397
398 if (key_len > SHA1_KEY_IOPAD_SIZE) {
399 return;
400 }
401
402 /* start out by storing key in pads */
403 memset(k_ipad, 0, sizeof(k_ipad));
404 memset(k_opad, 0, sizeof(k_opad));
405 memcpy(k_ipad, key, key_len);
406 memcpy(k_opad, key, key_len);
407
408 /* XOR key with ipad and opad values */
409 for (i = 0; i < SHA1_KEY_IOPAD_SIZE; i++) {
410 k_ipad[i] ^= 0x36;
411 k_opad[i] ^= 0x5c;
412 }
413
414 /* perform inner SHA */
415 utils_sha1_init(&context); /* init context for 1st pass */
416 utils_sha1_starts(&context); /* setup context for 1st pass */
417 utils_sha1_update(&context, k_ipad,
418 SHA1_KEY_IOPAD_SIZE); /* start with inner pad */
419 utils_sha1_update(&context, (unsigned char *)msg,
420 msg_len); /* then text of datagram */
421 utils_sha1_finish(&context, out); /* finish up 1st pass */
422
423 /* perform outer SHA */
424 utils_sha1_init(&context); /* init context for 2nd pass */
425 utils_sha1_starts(&context); /* setup context for 2nd pass */
426 utils_sha1_update(&context, k_opad,
427 SHA1_KEY_IOPAD_SIZE); /* start with outer pad */
428 utils_sha1_update(&context, out,
429 SHA1_DIGEST_SIZE); /* then results of 1st hash */
430 utils_sha1_finish(&context, out); /* finish up 2nd pass */
431 memcpy(digest, out, SHA1_DIGEST_SIZE);
432 }
433
434 #endif
435