Base SoH code for Microsoft NAP.
[freeradius.git] / src / lib / hmacsha1.c
1 /*
2  * Adapted from hmac.c (HMAC-MD5) for use by SHA1.
3  * by <mcr@sandelman.ottawa.on.ca>. Test cases from RFC2202.
4  *
5  */
6
7 /*
8 ** Function: hmac_sha1
9 */
10
11 #include <freeradius-devel/ident.h>
12 RCSID("$Id$")
13
14 #include <freeradius-devel/libradius.h>
15 #include <freeradius-devel/sha1.h>
16
17
18 /*
19 uint8_t*  text;                pointer to data stream
20 int             text_len;            length of data stream
21 uint8_t*  key;                 pointer to authentication key
22 int             key_len;             length of authentication key
23 uint8_t*  digest;              caller digest to be filled in
24 */
25
26 #ifdef HMAC_SHA1_DATA_PROBLEMS
27 unsigned int sha1_data_problems = 0;
28 #endif
29
30 void
31 fr_hmac_sha1(const uint8_t *text, int text_len,
32                const uint8_t *key, int key_len,
33                uint8_t *digest)
34 {
35         fr_SHA1_CTX context;
36         uint8_t k_ipad[65];    /* inner padding -
37                                       * key XORd with ipad
38                                       */
39         uint8_t k_opad[65];    /* outer padding -
40                                       * key XORd with opad
41                                       */
42         uint8_t tk[20];
43         int i;
44         /* if key is longer than 64 bytes reset it to key=SHA1(key) */
45         if (key_len > 64) {
46
47                 fr_SHA1_CTX      tctx;
48
49                 fr_SHA1Init(&tctx);
50                 fr_SHA1Update(&tctx, key, key_len);
51                 fr_SHA1Final(tk, &tctx);
52
53                 key = tk;
54                 key_len = 20;
55         }
56
57 #ifdef HMAC_SHA1_DATA_PROBLEMS
58         if(sha1_data_problems)
59         {
60                 int j,k;
61
62                 printf("\nhmac-sha1 key(%d): ", key_len);
63                 j=0; k=0;
64                 for (i = 0; i < key_len; i++) {
65                         if(j==4) {
66                                 printf("_");
67                                 j=0;
68                         }
69                         j++;
70
71                         printf("%02x", key[i]);
72                 }
73                 printf("\nDATA: (%d)    ",text_len);
74
75                 j=0; k=0;
76                 for (i = 0; i < text_len; i++) {
77                   if(k==20) {
78                     printf("\n            ");
79                     k=0;
80                     j=0;
81                   }
82                   if(j==4) {
83                     printf("_");
84                     j=0;
85                   }
86                   k++;
87                   j++;
88
89                   printf("%02x", text[i]);
90                 }
91                 printf("\n");
92         }
93 #endif
94
95
96         /*
97          * the HMAC_SHA1 transform looks like:
98          *
99          * SHA1(K XOR opad, SHA1(K XOR ipad, text))
100          *
101          * where K is an n byte key
102          * ipad is the byte 0x36 repeated 64 times
103
104          * opad is the byte 0x5c repeated 64 times
105          * and text is the data being protected
106          */
107
108         /* start out by storing key in pads */
109         memset( k_ipad, 0, sizeof(k_ipad));
110         memset( k_opad, 0, sizeof(k_opad));
111         memcpy( k_ipad, key, key_len);
112         memcpy( k_opad, key, key_len);
113
114         /* XOR key with ipad and opad values */
115         for (i = 0; i < 64; i++) {
116                 k_ipad[i] ^= 0x36;
117                 k_opad[i] ^= 0x5c;
118         }
119         /*
120          * perform inner SHA1
121          */
122         fr_SHA1Init(&context);                   /* init context for 1st
123                                               * pass */
124         fr_SHA1Update(&context, k_ipad, 64);      /* start with inner pad */
125         fr_SHA1Update(&context, text, text_len); /* then text of datagram */
126         fr_SHA1Final(digest, &context);          /* finish up 1st pass */
127         /*
128          * perform outer MD5
129          */
130         fr_SHA1Init(&context);                   /* init context for 2nd
131                                               * pass */
132         fr_SHA1Update(&context, k_opad, 64);     /* start with outer pad */
133         fr_SHA1Update(&context, digest, 20);     /* then results of 1st
134                                               * hash */
135         fr_SHA1Final(digest, &context);          /* finish up 2nd pass */
136
137 #ifdef HMAC_SHA1_DATA_PROBLEMS
138         if(sha1_data_problems)
139         {
140           int j;
141
142                 printf("\nhmac-sha1 mac(20): ");
143                 j=0;
144                 for (i = 0; i < 20; i++) {
145                         if(j==4) {
146                                 printf("_");
147                                 j=0;
148                         }
149                         j++;
150
151                         printf("%02x", digest[i]);
152                 }
153                 printf("\n");
154         }
155 #endif
156 }
157
158 /*
159 Test Vectors (Trailing '\0' of a character string not included in test):
160
161   key =         "Jefe"
162   data =        "what do ya want for nothing?"
163   data_len =    28 bytes
164   digest =      effcdf6ae5eb2fa2d27416d5f184df9c259a7c79
165
166   key =         0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
167
168   key_len       16 bytes
169   data =        0xDDDDDDDDDDDDDDDDDDDD...
170                 ..DDDDDDDDDDDDDDDDDDDD...
171                 ..DDDDDDDDDDDDDDDDDDDD...
172                 ..DDDDDDDDDDDDDDDDDDDD...
173                 ..DDDDDDDDDDDDDDDDDDDD
174   data_len =    50 bytes
175   digest =      0x56be34521d144c88dbb8c733f0e8b3f6
176 */
177
178 #ifdef TESTING
179 /*
180  *  cc -DTESTING -I ../include/ hmac.c sha1.c -o hmac
181  *
182  *  ./hmac Jefe "what do ya want for nothing?"
183  */
184
185 #include <stdlib.h>
186
187 int main(int argc, char **argv)
188 {
189   uint8_t digest[20];
190   char *key;
191   int key_len;
192   char *text;
193   int text_len;
194   int i;
195
196   key = argv[1];
197   key_len = strlen(key);
198
199   text = argv[2];
200   text_len = strlen(text);
201
202   fr_hmac_sha1(text, text_len, key, key_len, digest);
203
204   for (i = 0; i < 20; i++) {
205     printf("%02x", digest[i]);
206   }
207   printf("\n");
208
209   exit(0);
210   return 0;
211 }
212
213 #endif