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