1 /**
2  * @file hmac_sha1.c  Implements HMAC-SHA1 as of RFC 2202
3  *
4  * Copyright (C) 2010 Creytiv.com
5  */
6 #include <string.h>
7 #include <re_types.h>
8 #ifdef USE_OPENSSL
9 #include <openssl/sha.h>
10 #include <openssl/hmac.h>
11 #include <openssl/err.h>
12 #else
13 #include <re_sha.h>
14 #endif
15 #include <re_hmac.h>
16 
17 
18 /** SHA-1 Block size */
19 #ifndef SHA_BLOCKSIZE
20 #define SHA_BLOCKSIZE   64
21 #endif
22 
23 
24 /**
25  * Function to compute the digest
26  *
27  * @param k   Secret key
28  * @param lk  Length of the key in bytes
29  * @param d   Data
30  * @param ld  Length of data in bytes
31  * @param out Digest output
32  * @param t   Size of digest output
33  */
hmac_sha1(const uint8_t * k,size_t lk,const uint8_t * d,size_t ld,uint8_t * out,size_t t)34 void hmac_sha1(const uint8_t *k,  /* secret key */
35 	       size_t   lk,       /* length of the key in bytes */
36 	       const uint8_t *d,  /* data */
37 	       size_t   ld,       /* length of data in bytes */
38 	       uint8_t *out,      /* output buffer, at least "t" bytes */
39 	       size_t   t)
40 {
41 #ifdef USE_OPENSSL
42 	(void)t;
43 
44 	if (!HMAC(EVP_sha1(), k, (int)lk, d, ld, out, NULL))
45 		ERR_clear_error();
46 #else
47 	SHA_CTX ictx, octx;
48 	uint8_t isha[SHA_DIGEST_LENGTH], osha[SHA_DIGEST_LENGTH];
49 	uint8_t key[SHA_DIGEST_LENGTH];
50 	uint8_t buf[SHA_BLOCKSIZE];
51 	size_t  i;
52 
53 	if (lk > SHA_BLOCKSIZE) {
54 		SHA_CTX tctx;
55 
56 		SHA1_Init(&tctx);
57 		SHA1_Update(&tctx, k, lk);
58 		SHA1_Final(key, &tctx);
59 
60 		k = key;
61 		lk = SHA_DIGEST_LENGTH;
62 	}
63 
64 	/**** Inner Digest ****/
65 
66 	SHA1_Init(&ictx);
67 
68 	/* Pad the key for inner digest */
69 	for (i = 0 ; i < lk ; ++i)
70 		buf[i] = k[i] ^ 0x36;
71 	for (i = lk ; i < SHA_BLOCKSIZE ; ++i)
72 		buf[i] = 0x36;
73 
74 	SHA1_Update(&ictx, buf, SHA_BLOCKSIZE);
75 	SHA1_Update(&ictx, d, ld);
76 
77 	SHA1_Final(isha, &ictx);
78 
79 	/**** Outer Digest ****/
80 
81 	SHA1_Init(&octx);
82 
83 	/* Pad the key for outter digest */
84 
85 	for (i = 0 ; i < lk ; ++i)
86 		buf[i] = k[i] ^ 0x5c;
87 	for (i = lk ; i < SHA_BLOCKSIZE ; ++i)
88 		buf[i] = 0x5c;
89 
90 	SHA1_Update(&octx, buf, SHA_BLOCKSIZE);
91 	SHA1_Update(&octx, isha, SHA_DIGEST_LENGTH);
92 
93 	SHA1_Final(osha, &octx);
94 
95 	/* truncate and print the results */
96 	t = t > SHA_DIGEST_LENGTH ? SHA_DIGEST_LENGTH : t;
97 	memcpy(out, osha, t);
98 #endif
99 }
100