4 static const char rcsid
[] = "$Header: /Users/Shared/libresolv_2/libresolv/dst_hmac_link.c,v 1.1 2006/03/01 19:01:36 majka Exp $";
9 * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
11 * Permission to use, copy modify, and distribute this software for any
12 * purpose with or without fee is hereby granted, provided that the above
13 * copyright notice and this permission notice appear in all copies.
15 * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
16 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
18 * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
19 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
20 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
21 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
22 * WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
26 * This file contains an implementation of the HMAC-MD5 algorithm.
29 #include "port_before.h"
37 #include <sys/param.h>
39 #include <netinet/in.h>
40 #include <arpa/nameser.h>
43 #include "dst_internal.h"
47 # define _MD5_H_ 1 /* make sure we do not include rsaref md5.h file */
52 #include "port_after.h"
57 #define HMAC_IPAD 0x36
58 #define HMAC_OPAD 0x5c
62 typedef struct hmackey
{
63 u_char hk_ipad
[64], hk_opad
[64];
67 /**************************************************************************
69 * Call HMAC signing functions to sign a block of data.
70 * There are three steps to signing, INIT (initialize structures),
71 * UPDATE (hash (more) data), FINAL (generate a signature). This
72 * routine performs one or more of these steps.
74 * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
75 * priv_key key to use for signing.
76 * context the context to be used in this digest
77 * data data to be signed.
78 * len length in bytes of data.
79 * signature location to store signature.
80 * sig_len size of the signature location
82 * N Success on SIG_MODE_FINAL = returns signature length in bytes
83 * 0 Success on SIG_MODE_INIT and UPDATE
88 dst_hmac_md5_sign(const int mode
, DST_KEY
*d_key
, void **context
,
89 const u_char
*data
, const int len
,
90 u_char
*signature
, const int sig_len
)
96 if (mode
& SIG_MODE_INIT
)
97 ctx
= (MD5_CTX
*) malloc(sizeof(*ctx
));
99 ctx
= (MD5_CTX
*) *context
;
103 if (d_key
== NULL
|| d_key
->dk_KEY_struct
== NULL
)
105 key
= (HMAC_Key
*) d_key
->dk_KEY_struct
;
107 if (mode
& SIG_MODE_INIT
) {
109 MD5Update(ctx
, key
->hk_ipad
, HMAC_LEN
);
112 if ((mode
& SIG_MODE_UPDATE
) && (data
&& len
> 0))
113 MD5Update(ctx
, data
, len
);
115 if (mode
& SIG_MODE_FINAL
) {
116 if (signature
== NULL
|| sig_len
< MD5_LEN
)
117 return (SIGN_FINAL_FAILURE
);
118 MD5Final(signature
, ctx
);
120 /* perform outer MD5 */
122 MD5Update(ctx
, key
->hk_opad
, HMAC_LEN
);
123 MD5Update(ctx
, signature
, MD5_LEN
);
124 MD5Final(signature
, ctx
);
131 *context
= (void *) ctx
;
137 /**************************************************************************
138 * dst_hmac_md5_verify()
139 * Calls HMAC verification routines. There are three steps to
140 * verification, INIT (initialize structures), UPDATE (hash (more) data),
141 * FINAL (generate a signature). This routine performs one or more of
144 * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
145 * dkey key to use for verify.
147 * len length in bytes of data.
148 * signature signature.
149 * sig_len length in bytes of signature.
156 dst_hmac_md5_verify(const int mode
, DST_KEY
*d_key
, void **context
,
157 const u_char
*data
, const int len
,
158 const u_char
*signature
, const int sig_len
)
163 if (mode
& SIG_MODE_INIT
)
164 ctx
= (MD5_CTX
*) malloc(sizeof(*ctx
));
166 ctx
= (MD5_CTX
*) *context
;
170 if (d_key
== NULL
|| d_key
->dk_KEY_struct
== NULL
)
173 key
= (HMAC_Key
*) d_key
->dk_KEY_struct
;
174 if (mode
& SIG_MODE_INIT
) {
176 MD5Update(ctx
, key
->hk_ipad
, HMAC_LEN
);
178 if ((mode
& SIG_MODE_UPDATE
) && (data
&& len
> 0))
179 MD5Update(ctx
, data
, len
);
181 if (mode
& SIG_MODE_FINAL
) {
182 u_char digest
[MD5_LEN
];
183 if (signature
== NULL
|| key
== NULL
|| sig_len
!= MD5_LEN
)
184 return (VERIFY_FINAL_FAILURE
);
185 MD5Final(digest
, ctx
);
187 /* perform outer MD5 */
189 MD5Update(ctx
, key
->hk_opad
, HMAC_LEN
);
190 MD5Update(ctx
, digest
, MD5_LEN
);
191 MD5Final(digest
, ctx
);
194 if (memcmp(digest
, signature
, MD5_LEN
) != 0)
195 return (VERIFY_FINAL_FAILURE
);
200 *context
= (void *) ctx
;
206 /**************************************************************************
207 * dst_buffer_to_hmac_md5
208 * Converts key from raw data to an HMAC Key
209 * This function gets in a pointer to the data
211 * hkey the HMAC key to be filled in
212 * key the key in raw format
213 * keylen the length of the key
219 dst_buffer_to_hmac_md5(DST_KEY
*dkey
, const u_char
*key
, const int keylen
)
222 HMAC_Key
*hkey
= NULL
;
224 int local_keylen
= keylen
;
226 if (dkey
== NULL
|| key
== NULL
|| keylen
< 0)
229 if ((hkey
= (HMAC_Key
*) malloc(sizeof(HMAC_Key
))) == NULL
)
232 memset(hkey
->hk_ipad
, 0, sizeof(hkey
->hk_ipad
));
233 memset(hkey
->hk_opad
, 0, sizeof(hkey
->hk_opad
));
235 /* if key is longer than HMAC_LEN bytes reset it to key=MD5(key) */
236 if (keylen
> HMAC_LEN
) {
239 MD5Update(&ctx
, key
, keylen
);
241 memset((void *) &ctx
, 0, sizeof(ctx
));
243 local_keylen
= MD5_LEN
;
245 /* start out by storing key in pads */
246 memcpy(hkey
->hk_ipad
, key
, local_keylen
);
247 memcpy(hkey
->hk_opad
, key
, local_keylen
);
249 /* XOR key with hk_ipad and opad values */
250 for (i
= 0; i
< HMAC_LEN
; i
++) {
251 hkey
->hk_ipad
[i
] ^= HMAC_IPAD
;
252 hkey
->hk_opad
[i
] ^= HMAC_OPAD
;
254 dkey
->dk_key_size
= local_keylen
;
255 dkey
->dk_KEY_struct
= (void *) hkey
;
260 /**************************************************************************
261 * dst_hmac_md5_key_to_file_format
262 * Encodes an HMAC Key into the portable file format.
264 * hkey HMAC KEY structure
266 * buff_len size of output buffer
268 * 0 Failure - null input hkey
269 * -1 Failure - not enough space in output area
270 * N Success - Length of data returned in buff
274 dst_hmac_md5_key_to_file_format(const DST_KEY
*dkey
, char *buff
,
278 int len
, b_len
, i
, key_len
;
279 u_char key
[HMAC_LEN
];
282 if (dkey
== NULL
|| dkey
->dk_KEY_struct
== NULL
)
284 if (buff
== NULL
|| buff_len
<= (int) strlen(key_file_fmt_str
))
285 return (-1); /* no OR not enough space in output area */
287 hkey
= (HMAC_Key
*) dkey
->dk_KEY_struct
;
288 memset(buff
, 0, buff_len
); /* just in case */
289 /* write file header */
290 sprintf(buff
, key_file_fmt_str
, KEY_FILE_FORMAT
, KEY_HMAC_MD5
, "HMAC");
292 bp
= (char *) strchr(buff
, '\0');
293 b_len
= buff_len
- (bp
- buff
);
295 memset(key
, 0, HMAC_LEN
);
296 for (i
= 0; i
< HMAC_LEN
; i
++)
297 key
[i
] = hkey
->hk_ipad
[i
] ^ HMAC_IPAD
;
298 for (i
= HMAC_LEN
- 1; i
>= 0; i
--)
304 bp
+= strlen("Key: ");
305 b_len
= buff_len
- (bp
- buff
);
307 len
= b64_ntop(key
, key_len
, bp
, b_len
);
313 b_len
= buff_len
- (bp
- buff
);
315 return (buff_len
- b_len
);
319 /**************************************************************************
320 * dst_hmac_md5_key_from_file_format
321 * Converts contents of a key file into an HMAC key.
323 * hkey structure to put key into
324 * buff buffer containing the encoded key
325 * buff_len the length of the buffer
327 * n >= 0 Foot print of the key converted
328 * n < 0 Error in conversion
332 dst_hmac_md5_key_from_file_format(DST_KEY
*dkey
, const char *buff
,
335 const char *p
= buff
, *eol
;
336 u_char key
[HMAC_LEN
+1]; /* b64_pton needs more than 64 bytes do decode
337 * it should probably be fixed rather than doing
345 if (buff
== NULL
|| buff_len
< 0)
348 memset(key
, 0, sizeof(key
));
350 if (!dst_s_verify_str(&p
, "Key: "))
353 eol
= strchr(p
, '\n');
357 tmp
= malloc(len
+ 2);
360 key_len
= b64_pton((char *)tmp
, key
, HMAC_LEN
+1); /* see above */
361 SAFE_FREE2(tmp
, len
+ 2);
363 if (dst_buffer_to_hmac_md5(dkey
, key
, key_len
) < 0) {
370 * dst_hmac_md5_to_dns_key()
371 * function to extract hmac key from DST_KEY structure
373 * in_key: HMAC-MD5 key
375 * out_str: buffer to write ot
376 * out_len: size of output buffer
378 * number of bytes written to output buffer
381 dst_hmac_md5_to_dns_key(const DST_KEY
*in_key
, u_char
*out_str
,
388 if (in_key
== NULL
|| in_key
->dk_KEY_struct
== NULL
||
389 out_len
<= in_key
->dk_key_size
|| out_str
== NULL
)
392 hkey
= (HMAC_Key
*) in_key
->dk_KEY_struct
;
393 for (i
= 0; i
< in_key
->dk_key_size
; i
++)
394 out_str
[i
] = hkey
->hk_ipad
[i
] ^ HMAC_IPAD
;
398 /**************************************************************************
399 * dst_hmac_md5_compare_keys
400 * Compare two keys for equality.
402 * 0 The keys are equal
403 * NON-ZERO The keys are not equal
407 dst_hmac_md5_compare_keys(const DST_KEY
*key1
, const DST_KEY
*key2
)
409 HMAC_Key
*hkey1
= (HMAC_Key
*) key1
->dk_KEY_struct
;
410 HMAC_Key
*hkey2
= (HMAC_Key
*) key2
->dk_KEY_struct
;
411 return memcmp(hkey1
->hk_ipad
, hkey2
->hk_ipad
, HMAC_LEN
);
414 /**************************************************************************
415 * dst_hmac_md5_free_key_structure
416 * Frees all (none) dynamically allocated structures in hkey
420 dst_hmac_md5_free_key_structure(void *key
)
422 HMAC_Key
*hkey
= key
;
428 /***************************************************************************
429 * dst_hmac_md5_generate_key
430 * Creates a HMAC key of size size with a maximum size of 63 bytes
431 * generating a HMAC key larger than 63 bytes makes no sense as that key
432 * is digested before use.
436 dst_hmac_md5_generate_key(DST_KEY
*key
, const int nothing
)
444 * dst_hmac_md5_init() Function to answer set up function pointers for HMAC
450 if (dst_t_func
[KEY_HMAC_MD5
] != NULL
)
452 dst_t_func
[KEY_HMAC_MD5
] = malloc(sizeof(struct dst_func
));
453 if (dst_t_func
[KEY_HMAC_MD5
] == NULL
)
455 memset(dst_t_func
[KEY_HMAC_MD5
], 0, sizeof(struct dst_func
));
456 dst_t_func
[KEY_HMAC_MD5
]->sign
= dst_hmac_md5_sign
;
457 dst_t_func
[KEY_HMAC_MD5
]->verify
= dst_hmac_md5_verify
;
458 dst_t_func
[KEY_HMAC_MD5
]->compare
= dst_hmac_md5_compare_keys
;
459 dst_t_func
[KEY_HMAC_MD5
]->generate
= dst_hmac_md5_generate_key
;
460 dst_t_func
[KEY_HMAC_MD5
]->destroy
= dst_hmac_md5_free_key_structure
;
461 dst_t_func
[KEY_HMAC_MD5
]->to_dns_key
= dst_hmac_md5_to_dns_key
;
462 dst_t_func
[KEY_HMAC_MD5
]->from_dns_key
= dst_buffer_to_hmac_md5
;
463 dst_t_func
[KEY_HMAC_MD5
]->to_file_fmt
= dst_hmac_md5_key_to_file_format
;
464 dst_t_func
[KEY_HMAC_MD5
]->from_file_fmt
= dst_hmac_md5_key_from_file_format
;
469 #include "dst_internal.h"
470 #define dst_hmac_md5_init res_9_dst_hmac_md5_init