]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/hmac.c
Backport from BEE
[bacula/bacula] / bacula / src / lib / hmac.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2001-2014 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from many
7    others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    Bacula® is a registered trademark of Kern Sibbald.
15 */
16
17 /*
18  *  Hashed Message Authentication Code using MD5 (HMAC-MD5)
19  *
20  * hmac_md5 was based on sample code in RFC2104 (thanks guys).
21  *
22  * Adapted to Bacula by Kern E. Sibbald, February MMI.
23  *
24  */
25
26 #include "bacula.h"
27
28 #define PAD_LEN 64           /* PAD length */
29 #define SIG_LEN MD5HashSize  /* MD5 digest length */
30
31 void
32 hmac_md5(
33     uint8_t*  text,            /* pointer to data stream */
34     int   text_len,            /* length of data stream */
35     uint8_t*  key,             /* pointer to authentication key */
36     int   key_len,             /* length of authentication key */
37     uint8_t  *hmac)            /* returned hmac-md5 */
38 {
39    MD5Context md5c;
40    uint8_t k_ipad[PAD_LEN];    /* inner padding - key XORd with ipad */
41    uint8_t k_opad[PAD_LEN];    /* outer padding - key XORd with opad */
42    uint8_t keysig[SIG_LEN];
43    int i;
44
45    /* if key is longer than PAD length, reset it to key=MD5(key) */
46    if (key_len > PAD_LEN) {
47       MD5Context md5key;
48
49       MD5Init(&md5key);
50       MD5Update(&md5key, key, key_len);
51       MD5Final(keysig, &md5key);
52
53       key = keysig;
54       key_len = SIG_LEN;
55    }
56
57    /*
58     * the HMAC_MD5 transform looks like:
59     *
60     * MD5(Key XOR opad, MD5(Key XOR ipad, text))
61     *
62     * where Key is an n byte key
63     * ipad is the byte 0x36 repeated 64 times
64
65     * opad is the byte 0x5c repeated 64 times
66     * and text is the data being protected
67     */
68
69    /* Zero pads and store key */
70    memset(k_ipad, 0, PAD_LEN);
71    memcpy(k_ipad, key, key_len);
72    memcpy(k_opad, k_ipad, PAD_LEN);
73
74    /* XOR key with ipad and opad values */
75    for (i=0; i<PAD_LEN; i++) {
76       k_ipad[i] ^= 0x36;
77       k_opad[i] ^= 0x5c;
78    }
79
80    /* perform inner MD5 */
81    MD5Init(&md5c);                    /* start inner hash */
82    MD5Update(&md5c, k_ipad, PAD_LEN); /* hash inner pad */
83    MD5Update(&md5c, text, text_len);  /* hash text */
84    MD5Final(hmac, &md5c);             /* store inner hash */
85
86    /* perform outer MD5 */
87    MD5Init(&md5c);                    /* start outer hash */
88    MD5Update(&md5c, k_opad, PAD_LEN); /* hash outer pad */
89    MD5Update(&md5c, hmac, SIG_LEN);   /* hash inner hash */
90    MD5Final(hmac, &md5c);             /* store results */
91 }
92 /*
93 Test Vectors (Trailing '\0' of a character string not included in test):
94
95   key =         0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
96   key_len =     16 bytes
97   data =        "Hi There"
98   data_len =    8  bytes
99   digest =      0x9294727a3638bb1c13f48ef8158bfc9d
100
101   key =         "Jefe"
102   data =        "what do ya want for nothing?"
103   data_len =    28 bytes
104   digest =      0x750c783e6ab0b503eaa86e310a5db738
105
106   key =         0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
107
108   key_len       16 bytes
109   data =        0xDDDDDDDDDDDDDDDDDDDD...
110                 ..DDDDDDDDDDDDDDDDDDDD...
111                 ..DDDDDDDDDDDDDDDDDDDD...
112                 ..DDDDDDDDDDDDDDDDDDDD...
113                 ..DDDDDDDDDDDDDDDDDDDD
114   data_len =    50 bytes
115   digest =      0x56be34521d144c88dbb8c733f0e8b3f6
116 */