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