]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/hmac.c
bb8e46508f0a538e71145334484f589659b31494
[bacula/bacula] / bacula / src / lib / hmac.c
1 /*
2  *  Hashed Message Authentication Code using MD5 (HMAC-MD5)
3  *
4  * hmac_md5 was based on sample code in RFC2104 (thanks guys).
5  * 
6  * Adapted to Bacula by Kern E. Sibbald, February MMI.
7  */
8 /*
9    Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
10
11    This program is free software; you can redistribute it and/or
12    modify it under the terms of the GNU General Public License as
13    published by the Free Software Foundation; either version 2 of
14    the License, or (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19    General Public License for more details.
20
21    You should have received a copy of the GNU General Public
22    License along with this program; if not, write to the Free
23    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
24    MA 02111-1307, USA.
25
26  */
27
28 #include "bacula.h"
29
30 #define PAD_LEN 64                    /* PAD length */
31 #define SIG_LEN 16                    /* MD5 signature length */
32
33 void
34 hmac_md5(
35     uint8_t*  text,            /* pointer to data stream */
36     int   text_len,            /* length of data stream */
37     uint8_t*  key,             /* pointer to authentication key */
38     int   key_len,             /* length of authentication key */
39     uint8_t  *hmac)            /* returned hmac-md5 */
40 {
41    MD5Context md5c;
42    uint8_t k_ipad[PAD_LEN];    /* inner padding - key XORd with ipad */
43    uint8_t k_opad[PAD_LEN];    /* outer padding - key XORd with opad */
44    uint8_t keysig[SIG_LEN];
45    int i;
46
47    /* if key is longer than PAD length, reset it to key=MD5(key) */
48    if (key_len > PAD_LEN) {
49       MD5Context md5key;
50
51       MD5Init(&md5key);
52       MD5Update(&md5key, key, key_len);
53       MD5Final(keysig, &md5key);
54
55       key = keysig;
56       key_len = SIG_LEN;
57    }
58
59    /*
60     * the HMAC_MD5 transform looks like:
61     *
62     * MD5(Key XOR opad, MD5(Key XOR ipad, text))
63     *
64     * where Key is an n byte key
65     * ipad is the byte 0x36 repeated 64 times
66
67     * opad is the byte 0x5c repeated 64 times
68     * and text is the data being protected
69     */
70
71    /* Zero pads and store key */
72    memset(k_ipad, 0, PAD_LEN);
73    memcpy(k_ipad, key, key_len);
74    memcpy(k_opad, k_ipad, PAD_LEN); 
75
76    /* XOR key with ipad and opad values */
77    for (i=0; i<PAD_LEN; i++) {
78       k_ipad[i] ^= 0x36;
79       k_opad[i] ^= 0x5c;
80    }
81
82    /* perform inner MD5 */
83    MD5Init(&md5c);                    /* start inner hash */
84    MD5Update(&md5c, k_ipad, PAD_LEN); /* hash inner pad */
85    MD5Update(&md5c, text, text_len);  /* hash text */
86    MD5Final(hmac, &md5c);             /* store inner hash */
87
88    /* perform outer MD5 */
89    MD5Init(&md5c);                    /* start outer hash */
90    MD5Update(&md5c, k_opad, PAD_LEN); /* hash outer pad */
91    MD5Update(&md5c, hmac, SIG_LEN);   /* hash inner hash */
92    MD5Final(hmac, &md5c);             /* store results */
93 }
94 /*
95 Test Vectors (Trailing '\0' of a character string not included in test):
96
97   key =         0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
98   key_len =     16 bytes
99   data =        "Hi There"
100   data_len =    8  bytes
101   digest =      0x9294727a3638bb1c13f48ef8158bfc9d
102
103   key =         "Jefe"
104   data =        "what do ya want for nothing?"
105   data_len =    28 bytes
106   digest =      0x750c783e6ab0b503eaa86e310a5db738
107
108   key =         0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
109
110   key_len       16 bytes
111   data =        0xDDDDDDDDDDDDDDDDDDDD...
112                 ..DDDDDDDDDDDDDDDDDDDD...
113                 ..DDDDDDDDDDDDDDDDDDDD...
114                 ..DDDDDDDDDDDDDDDDDDDD...
115                 ..DDDDDDDDDDDDDDDDDDDD
116   data_len =    50 bytes
117   digest =      0x56be34521d144c88dbb8c733f0e8b3f6
118 */