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