All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hmacsha1.c
Go to the documentation of this file.
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 RCSID("$Id: c3cbd87a2c13c47da93fdb1bdfbf6da4c22aaac5 $")
12 
13 #include <freeradius-devel/libradius.h>
14 
15 #ifdef HMAC_SHA1_DATA_PROBLEMS
16 unsigned int sha1_data_problems = 0;
17 #endif
18 
19 /** Calculate HMAC using SHA1
20  *
21  * @param digest Caller digest to be filled in.
22  * @param text Pointer to data stream.
23  * @param text_len length of data stream.
24  * @param key Pointer to authentication key.
25  * @param key_len Length of authentication key.
26 
27  */
28 void fr_hmac_sha1(uint8_t digest[SHA1_DIGEST_LENGTH], uint8_t const *text, size_t text_len,
29  uint8_t const *key, size_t key_len)
30 {
31  fr_sha1_ctx context;
32  uint8_t k_ipad[65]; /* inner padding - key XORd with ipad */
33  uint8_t k_opad[65]; /* outer padding - key XORd with opad */
34  uint8_t tk[20];
35  int i;
36  /* if key is longer than 64 bytes reset it to key=SHA1(key) */
37  if (key_len > 64) {
38 
39  fr_sha1_ctx tctx;
40 
41  fr_sha1_init(&tctx);
42  fr_sha1_update(&tctx, key, key_len);
43  fr_sha1_final(tk, &tctx);
44 
45  key = tk;
46  key_len = 20;
47  }
48 
49 #ifdef HMAC_SHA1_DATA_PROBLEMS
50  if(sha1_data_problems)
51  {
52  int j,k;
53 
54  printf("\nhmac-sha1 key(%d): ", key_len);
55  j=0; k=0;
56  for (i = 0; i < key_len; i++) {
57  if(j==4) {
58  printf("_");
59  j=0;
60  }
61  j++;
62 
63  printf("%02x", key[i]);
64  }
65  printf("\nDATA: (%d) ",text_len);
66 
67  j=0; k=0;
68  for (i = 0; i < text_len; i++) {
69  if(k==20) {
70  printf("\n ");
71  k=0;
72  j=0;
73  }
74  if(j==4) {
75  printf("_");
76  j=0;
77  }
78  k++;
79  j++;
80 
81  printf("%02x", text[i]);
82  }
83  printf("\n");
84  }
85 #endif
86 
87 
88  /*
89  * the HMAC_SHA1 transform looks like:
90  *
91  * SHA1(K XOR opad, SHA1(K XOR ipad, text))
92  *
93  * where K is an n byte key
94  * ipad is the byte 0x36 repeated 64 times
95 
96  * opad is the byte 0x5c repeated 64 times
97  * and text is the data being protected
98  */
99 
100  /* start out by storing key in pads */
101  memset(k_ipad, 0, sizeof(k_ipad));
102  memset(k_opad, 0, sizeof(k_opad));
103  memcpy(k_ipad, key, key_len);
104  memcpy(k_opad, key, key_len);
105 
106  /* XOR key with ipad and opad values */
107  for (i = 0; i < 64; i++) {
108  k_ipad[i] ^= 0x36;
109  k_opad[i] ^= 0x5c;
110  }
111  /*
112  * perform inner SHA1
113  */
114  fr_sha1_init(&context); /* init context for 1st pass */
115  fr_sha1_update(&context, k_ipad, 64); /* start with inner pad */
116  fr_sha1_update(&context, text, text_len); /* then text of datagram */
117  fr_sha1_final(digest, &context); /* finish up 1st pass */
118  /*
119  * perform outer SHA1
120  */
121  fr_sha1_init(&context); /* init context for 2nd pass */
122  fr_sha1_update(&context, k_opad, 64); /* start with outer pad */
123  fr_sha1_update(&context, digest, 20); /* then results of 1st hash */
124  fr_sha1_final(digest, &context); /* finish up 2nd pass */
125 
126 #ifdef HMAC_SHA1_DATA_PROBLEMS
127  if (sha1_data_problems) {
128  int j;
129 
130  printf("\nhmac-sha1 mac(20): ");
131  j=0;
132  for (i = 0; i < 20; i++) {
133  if(j==4) {
134  printf("_");
135  j=0;
136  }
137  j++;
138 
139  printf("%02x", digest[i]);
140  }
141  printf("\n");
142  }
143 #endif
144 }
145 
146 /*
147 Test Vectors (Trailing '\0' of a character string not included in test):
148 
149  key = "Jefe"
150  data = "what do ya want for nothing?"
151  data_len = 28 bytes
152  digest = effcdf6ae5eb2fa2d27416d5f184df9c259a7c79
153 
154  key = 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
155 
156  key_len 16 bytes
157  data = 0xDDDDDDDDDDDDDDDDDDDD...
158  ..DDDDDDDDDDDDDDDDDDDD...
159  ..DDDDDDDDDDDDDDDDDDDD...
160  ..DDDDDDDDDDDDDDDDDDDD...
161  ..DDDDDDDDDDDDDDDDDDDD
162  data_len = 50 bytes
163  digest = 0x56be34521d144c88dbb8c733f0e8b3f6
164 */
165 
166 #ifdef TESTING
167 /*
168  * cc -DTESTING -I ../include/ hmac.c sha1.c -o hmac
169  *
170  * ./hmac Jefe "what do ya want for nothing?"
171  */
172 int main(int argc, char **argv)
173 {
174  uint8_t digest[20];
175  char *key;
176  int key_len;
177  char *text;
178  int text_len;
179  int i;
180 
181  key = argv[1];
182  key_len = strlen(key);
183 
184  text = argv[2];
185  text_len = strlen(text);
186 
187  fr_hmac_sha1(digest, text, text_len, key, key_len);
188 
189  for (i = 0; i < 20; i++) {
190  printf("%02x", digest[i]);
191  }
192  printf("\n");
193 
194  exit(0);
195  return 0;
196 }
197 
198 #endif
void fr_sha1_update(fr_sha1_ctx *context, uint8_t const *data, size_t len)
Definition: sha1.c:106
#define SHA1_DIGEST_LENGTH
Definition: sha1.h:18
void fr_sha1_init(fr_sha1_ctx *context)
Definition: sha1.c:94
int sha1_data_problems
void fr_hmac_sha1(uint8_t digest[SHA1_DIGEST_LENGTH], uint8_t const *text, size_t text_len, uint8_t const *key, size_t key_len)
Calculate HMAC using SHA1.
Definition: hmacsha1.c:28
void fr_sha1_final(uint8_t digest[20], fr_sha1_ctx *context)
Definition: sha1.c:132
int main(int argc, char *argv[])
Definition: radattr.c:959
#define RCSID(id)
Definition: build.h:135