# BRCM_VERSION=3
[bcm963xx.git] / userapps / opensource / sshd / libtomcrypt / hmac.c
1 /* Submited by Dobes Vandermeer  (dobes@smartt.com) */
2
3 #include "mycrypt.h"
4
5 /*
6     (1) append zeros to the end of K to create a B byte string
7         (e.g., if K is of length 20 bytes and B=64, then K will be
8          appended with 44 zero bytes 0x00)
9     (2) XOR (bitwise exclusive-OR) the B byte string computed in step
10         (1) with ipad (ipad = the byte 0x36 repeated B times)
11     (3) append the stream of data 'text' to the B byte string resulting
12         from step (2)
13     (4) apply H to the stream generated in step (3)
14     (5) XOR (bitwise exclusive-OR) the B byte string computed in
15         step (1) with opad (opad = the byte 0x5C repeated B times.)
16     (6) append the H result from step (4) to the B byte string
17         resulting from step (5)
18     (7) apply H to the stream generated in step (6) and output
19         the result
20 */
21
22 #ifdef HMAC
23
24 #define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize
25
26 int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen)
27 {
28     unsigned char buf[MAXBLOCKSIZE];
29     unsigned long hashsize;
30     unsigned long i, z;
31     int err;
32
33     _ARGCHK(hmac != NULL);
34     _ARGCHK(key != NULL);
35
36     if ((err = hash_is_valid(hash)) != CRYPT_OK) {
37         return err;
38     }
39
40     if (keylen == 0) {
41         return CRYPT_INVALID_KEYSIZE;
42     }
43
44     hmac->hash = hash;
45
46     // (1) make sure we have a large enough key
47     hmac->hashsize = hashsize = hash_descriptor[hash].hashsize;
48     if(keylen > HMAC_BLOCKSIZE) {
49         z = (unsigned long)sizeof(hmac->key);
50         if ((err = hash_memory(hash, key, keylen, hmac->key, &z)) != CRYPT_OK) {
51            return err;
52         }
53         if(hashsize < HMAC_BLOCKSIZE) {
54             zeromem((hmac->key) + hashsize, (size_t)(HMAC_BLOCKSIZE - hashsize));
55         }
56     } else {
57         memcpy(hmac->key, key, (size_t)keylen);
58         if(keylen < HMAC_BLOCKSIZE) {
59             zeromem((hmac->key) + keylen, (size_t)(HMAC_BLOCKSIZE - keylen));
60         }
61     }
62
63     // Create the initial vector for step (3)
64     for(i=0; i < keylen;   i++) {
65        buf[i] = hmac->key[i] ^ 0x36;
66     }
67
68     for(   ; i < HMAC_BLOCKSIZE; i++) { 
69        buf[i] = 0x36;
70     }
71
72     // Pre-pend that to the hash data
73     hash_descriptor[hash].init(&hmac->md);
74     hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE);
75
76     return CRYPT_OK;
77 }
78
79 int hmac_process(hmac_state *hmac, const unsigned char *buf, unsigned long len)
80 {
81     int err;
82     _ARGCHK(hmac != NULL);
83     _ARGCHK(buf != NULL);
84     if ((err = hash_is_valid(hmac->hash)) != CRYPT_OK) {
85         return err;
86     }
87     hash_descriptor[hmac->hash].process(&hmac->md, buf, len);
88     return CRYPT_OK;
89 }
90
91 int hmac_done(hmac_state *hmac, unsigned char *hashOut)
92 {
93     unsigned char buf[MAXBLOCKSIZE];
94     unsigned char isha[MAXBLOCKSIZE];
95     unsigned long hashsize, i;
96     int hash, err;
97
98     _ARGCHK(hmac != NULL);
99     _ARGCHK(hashOut != NULL);
100
101     hash = hmac->hash;
102     if((err = hash_is_valid(hash)) != CRYPT_OK) {
103         return err;
104     }
105
106     // Get the hash of the first HMAC vector plus the data
107     hash_descriptor[hash].done(&hmac->md, isha);
108
109     // Create the second HMAC vector vector for step (3)
110     hashsize = hash_descriptor[hash].hashsize;
111     for(i=0; i < HMAC_BLOCKSIZE; i++) {
112         buf[i] = hmac->key[i] ^ 0x5C;
113     }
114
115     // Now calculate the "outer" hash for step (5), (6), and (7)
116     hash_descriptor[hash].init(&hmac->md);
117     hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE);
118     hash_descriptor[hash].process(&hmac->md, isha, hashsize);
119     hash_descriptor[hash].done(&hmac->md, hashOut);
120
121 #ifdef CLEAN_STACK
122     zeromem(hmac->key, sizeof(hmac->key));
123 #endif
124     return CRYPT_OK;
125 }
126
127 int hmac_memory(int hash, const unsigned char *key, unsigned long keylen,
128                 const unsigned char *data, unsigned long len, 
129                 unsigned char *dst, unsigned long *dstlen)
130 {
131     hmac_state hmac;
132     int err;
133
134     _ARGCHK(key != NULL);
135     _ARGCHK(data != NULL);
136     _ARGCHK(dst != NULL);
137     
138     if((err = hash_is_valid(hash)) != CRYPT_OK) {
139         return err;
140     }
141     if (hash_descriptor[hash].hashsize > *dstlen) {
142        return CRYPT_BUFFER_OVERFLOW;
143     }
144     *dstlen = hash_descriptor[hash].hashsize;
145
146     if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) {
147         return err;
148     }
149   
150     if ((err = hmac_process(&hmac, data, len)) != CRYPT_OK) {
151        return err;
152     }
153
154     if ((err = hmac_done(&hmac, dst)) != CRYPT_OK) {
155        return err;
156     }
157     return CRYPT_OK;
158 }
159
160 /* hmac_file added by Tom St Denis */
161 int hmac_file(int hash, const char *fname, const unsigned char *key,
162                 unsigned long keylen, 
163                 unsigned char *dst, unsigned long *dstlen)
164 {
165 #ifdef NO_FILE
166     return CRYPT_ERROR;
167 #else
168    hmac_state hmac;
169    FILE *in;
170    unsigned char buf[512];
171    size_t x;
172    int err;
173
174    _ARGCHK(fname != NULL);
175    _ARGCHK(key != NULL);
176    _ARGCHK(dst != NULL);
177    
178    if((err = hash_is_valid(hash)) != CRYPT_OK) {
179        return err;
180    }
181    if (hash_descriptor[hash].hashsize > *dstlen) {
182       return CRYPT_BUFFER_OVERFLOW;
183    }
184    *dstlen = hash_descriptor[hash].hashsize;
185
186    if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) {
187        return err;
188    }
189
190    in = fopen(fname, "rb");
191    if (in == NULL) {
192       return CRYPT_INVALID_ARG;
193    }
194
195    /* process the file contents */
196    do {
197       x = fread(buf, 1, sizeof(buf), in);
198       if ((err = hmac_process(&hmac, buf, (unsigned long)x)) != CRYPT_OK) { 
199          (void)fclose(in);
200          return err;
201       }
202    } while (x == sizeof(buf));
203    (void)fclose(in);
204
205    /* get final hmac */
206    if ((err = hmac_done(&hmac, dst)) != CRYPT_OK) {
207       return err;
208    }
209
210 #ifdef CLEAN_STACK
211    /* clear memory */
212    zeromem(buf, sizeof(buf));
213 #endif   
214    return CRYPT_OK;
215 #endif
216 }
217
218 /*
219
220     TEST CASES SOURCE:
221
222 Network Working Group                                          P. Cheng
223 Request for Comments: 2202                                          IBM
224 Category: Informational                                        R. Glenn
225                                                                    NIST
226                                                          September 1997
227
228                  Test Cases for HMAC-MD5 and HMAC-SHA-1
229 */
230
231
232 int hmac_test(void)
233 {
234  #ifndef LTC_TEST
235     return CRYPT_NOP;
236  #else    
237     unsigned char digest[MAXBLOCKSIZE];
238     int i;
239
240     struct hmac_test_case {
241         int num;
242         char *algo;
243         unsigned char key[128];
244         unsigned long keylen;
245         unsigned char data[128];
246         unsigned long datalen;
247         unsigned char digest[MAXBLOCKSIZE];
248     } cases[] = {
249         /*
250         3. Test Cases for HMAC-SHA-1
251
252         test_case =     1
253         key =           0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
254         key_len =       20
255         data =          "Hi Ther     20
256         digest =        0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04
257         digest-96 =     0x4c1a03424b55e07fe7f27be1
258         */
259         { 5, "sha1",
260             {0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
261              0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
262              0x0c, 0x0c, 0x0c, 0x0c}, 20,
263             "Test With Truncation", 20,
264             {0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2,
265              0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04} },
266
267         /*
268         test_case =     6
269         key =           0xaa repeated 80 times
270         key_len =       80
271         data =          "Test Using Larger Than Block-Size Key - Hash Key First"
272         data_len =      54
273         digest =        0xaa4ae5e15272d00e95705637ce8a3b55ed402112
274         */
275         { 6, "sha1",
276             {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
277              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
278              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
279              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
280              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
281              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
282              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
283              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
284              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
285              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80,
286             "Test Using Larger Than Block-Size Key - Hash Key First", 54,
287             {0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e,
288              0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, 
289              0xed, 0x40, 0x21, 0x12} },
290
291         /*
292         test_case =     7
293         key =           0xaa repeated 80 times
294         key_len =       80
295         data =          "Test Using Larger Than Block-Size Key and Larger
296                         Than One Block-Size Data"
297         data_len =      73
298         digest =        0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91
299         */
300         { 7, "sha1",
301             {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
302              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
303              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
304              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
305              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
306              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
307              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
308              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
309              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
310              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80,
311             "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73,
312             {0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d,
313              0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91} },
314
315         /*
316         2. Test Cases for HMAC-MD5
317
318         test_case =     1
319         key =           0x0b 0b 0b 0b 
320                           0b 0b 0b 0b
321                           0b 0b 0b 0b
322                           0b 0b 0b 0b
323         key_len =       16
324         data =          "Hi There"
325         data_len =      8
326         digest =        0x92 94 72 7a 
327                           36 38 bb 1c 
328                           13 f4 8e f8 
329                           15 8b fc 9d
330         */
331         { 1, "md5",
332             {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 
333              0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 16,
334             "Hi There", 8,
335             {0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, 
336              0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d}  },
337         /*
338         test_case =     2
339         key =           "Jefe"
340         key_len =       4
341         data =          "what do ya want for nothing?"
342         data_len =      28
343         digest =        0x750c783e6ab0b503eaa86e310a5db738
344         */
345         { 2, "md5",
346             "Jefe", 4,
347             "what do ya want for nothing?", 28,
348             {0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, 
349              0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38} },
350
351         /*
352         test_case =     3
353         key =           0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
354         key_len         16
355         data =          0xdd repeated 50 times
356         data_len =      50
357         digest =        0x56be34521d144c88dbb8c733f0e8b3f6
358         */
359         { 3, "md5",
360             {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
361              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 16,
362             {0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
363              0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
364              0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
365              0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
366              0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd}, 50,
367             {0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
368              0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6} },
369         /*
370
371         test_case =     4
372         key = 0x0102030405060708090a0b0c0d0e0f10111213141516171819
373         key_len         25
374         data =          0xcd repeated 50 times
375         data_len =      50
376         digest =        0x697eaf0aca3a3aea3a75164746ffaa79
377         */
378         { 4, "md5",
379             {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
380              0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
381              0x15, 0x16, 0x17, 0x18, 0x19}, 25,
382             {0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
383              0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
384              0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
385              0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
386              0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd}, 50,
387             {0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea, 
388              0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79} },
389
390
391         /*
392  
393         test_case =     5
394         key =           0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
395         key_len =       16
396         data =          "Test With Truncation"
397         data_len =      20
398         digest =        0x56461ef2342edc00f9bab995690efd4c
399         digest-96       0x56461ef2342edc00f9bab995
400         */
401         { 5, "md5",
402             {0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
403              0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c}, 16,
404             "Test With Truncation", 20,
405             {0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00, 
406              0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c} },
407
408         /*
409
410         test_case =     6
411         key =           0xaa repeated 80 times
412         key_len =       80
413         data =          "Test Using Larger Than Block-Size Key - Hash 
414 Key First"
415         data_len =      54
416         digest =        0x6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd
417         */
418         { 6, "md5",
419             {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
420              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
421              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
422              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
423              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
424              
425              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
426              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
427              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
428              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
429              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80,
430             "Test Using Larger Than Block-Size Key - Hash Key First", 54,
431             {0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f, 
432              0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd} },
433
434         /*
435
436         test_case =     7
437         key =           0xaa repeated 80 times
438         key_len =       80
439         data =          "Test Using Larger Than Block-Size Key and Larger
440                         Than One Block-Size Data"
441         data_len =      73
442         digest =        0x6f630fad67cda0ee1fb1f562db3aa53e
443         */
444         { 7, "md5",
445             {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
446              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
447              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
448              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
449              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
450              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
451              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
452              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
453              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
454              0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80,
455             "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73,
456             {0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee,
457              0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e} }
458     };
459
460     unsigned long outlen;
461     int err;
462     int tested=0,failed=0;
463     for(i=0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) {
464         int hash = find_hash(cases[i].algo);
465         if (hash == -1) continue;
466         ++tested;
467         outlen = sizeof(digest);
468         if((err = hmac_memory(hash, cases[i].key, cases[i].keylen, cases[i].data, cases[i].datalen, digest, &outlen)) != CRYPT_OK) {
469 #if 0
470             printf("HMAC-%s test #%d\n", cases[i].algo, cases[i].num);
471 #endif
472             return err;
473         }
474
475         if(memcmp(digest, cases[i].digest, (size_t)hash_descriptor[hash].hashsize) != 0)  {
476 #if 0
477             unsigned int j;
478             printf("\nHMAC-%s test #%d:\n", cases[i].algo, cases[i].num);
479             printf(  "Result:  0x");
480             for(j=0; j < hash_descriptor[hash].hashsize; j++) {
481                 printf("%2x ", digest[j]);
482             }
483             printf("\nCorrect: 0x");
484             for(j=0; j < hash_descriptor[hash].hashsize; j++) {
485                printf("%2x ", cases[i].digest[j]);
486             }
487             printf("\n");
488 #endif
489             failed++;
490             //return CRYPT_ERROR;
491         } else {
492             /* printf("HMAC-%s test #%d: Passed\n", cases[i].algo, cases[i].num); */
493         }
494     }
495
496     if (failed != 0) {
497         return CRYPT_FAIL_TESTVECTOR;
498     } else if (tested == 0) {
499         return CRYPT_NOP;
500     } else {
501         return CRYPT_OK;
502     }
503  #endif
504 }
505
506 #endif
507