xref: /netbsd-src/lib/libresolv/hmac_link.c (revision 95e3bb37fdecf1b5d8521606397d20523e33a932)
1*95e3bb37Schristos /*	$NetBSD: hmac_link.c,v 1.3 2016/03/07 14:35:39 christos Exp $	*/
2ccd87bacSchristos 
3ccd87bacSchristos /*
4ccd87bacSchristos  * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
5ccd87bacSchristos  *
6ccd87bacSchristos  * Permission to use, copy modify, and distribute this software for any
7ccd87bacSchristos  * purpose with or without fee is hereby granted, provided that the above
8ccd87bacSchristos  * copyright notice and this permission notice appear in all copies.
9ccd87bacSchristos  *
10ccd87bacSchristos  * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
11ccd87bacSchristos  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
12ccd87bacSchristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL
13ccd87bacSchristos  * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
14ccd87bacSchristos  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
15ccd87bacSchristos  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
16ccd87bacSchristos  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
17ccd87bacSchristos  * WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
18ccd87bacSchristos  */
19ccd87bacSchristos #include <sys/cdefs.h>
20ccd87bacSchristos #if 0
21ccd87bacSchristos static const char rcsid[] = "Header: /proj/cvs/prod/libbind/dst/hmac_link.c,v 1.8 2007/09/24 17:18:25 each Exp ";
22ccd87bacSchristos #else
23*95e3bb37Schristos __RCSID("$NetBSD: hmac_link.c,v 1.3 2016/03/07 14:35:39 christos Exp $");
24ccd87bacSchristos #endif
25ccd87bacSchristos 
26ccd87bacSchristos /*%
27ccd87bacSchristos  * This file contains an implementation of the HMAC-MD5 algorithm.
28ccd87bacSchristos  */
29ccd87bacSchristos #include "port_before.h"
30ccd87bacSchristos 
31ccd87bacSchristos #include <stdio.h>
32ccd87bacSchristos #include <unistd.h>
33ccd87bacSchristos #include <stdlib.h>
34ccd87bacSchristos #include <string.h>
35ccd87bacSchristos #include <memory.h>
36ccd87bacSchristos #include <sys/param.h>
37ccd87bacSchristos #include <sys/time.h>
38ccd87bacSchristos #include <netinet/in.h>
39ccd87bacSchristos #include <arpa/nameser.h>
40ccd87bacSchristos #include <resolv.h>
41ccd87bacSchristos 
42ccd87bacSchristos #include "dst_internal.h"
43ccd87bacSchristos 
44ccd87bacSchristos #include <md5.h>
45ccd87bacSchristos #include "port_after.h"
46ccd87bacSchristos 
47ccd87bacSchristos 
48ccd87bacSchristos #define HMAC_LEN	64
49ccd87bacSchristos #define HMAC_IPAD	0x36
50ccd87bacSchristos #define HMAC_OPAD	0x5c
51ccd87bacSchristos #define MD5_LEN		16
52ccd87bacSchristos 
53ccd87bacSchristos 
54ccd87bacSchristos typedef struct hmackey {
55ccd87bacSchristos 	u_char hk_ipad[64], hk_opad[64];
56ccd87bacSchristos } HMAC_Key;
57ccd87bacSchristos 
58ccd87bacSchristos 
59ccd87bacSchristos /**************************************************************************
60ccd87bacSchristos  * dst_hmac_md5_sign
61ccd87bacSchristos  *     Call HMAC signing functions to sign a block of data.
62ccd87bacSchristos  *     There are three steps to signing, INIT (initialize structures),
63ccd87bacSchristos  *     UPDATE (hash (more) data), FINAL (generate a signature).  This
64ccd87bacSchristos  *     routine performs one or more of these steps.
65ccd87bacSchristos  * Parameters
66ccd87bacSchristos  *     mode	SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
67ccd87bacSchristos  *     priv_key    key to use for signing.
68ccd87bacSchristos  *     context   the context to be used in this digest
69ccd87bacSchristos  *     data	data to be signed.
70ccd87bacSchristos  *     len	 length in bytes of data.
71ccd87bacSchristos  *     signature   location to store signature.
72ccd87bacSchristos  *     sig_len     size of the signature location
73ccd87bacSchristos  * returns
74ccd87bacSchristos  *	N  Success on SIG_MODE_FINAL = returns signature length in bytes
75ccd87bacSchristos  *	0  Success on SIG_MODE_INIT  and UPDATE
76ccd87bacSchristos  *	 <0  Failure
77ccd87bacSchristos  */
78ccd87bacSchristos 
79ccd87bacSchristos static int
dst_hmac_md5_sign(const int mode,DST_KEY * d_key,void ** context,const u_char * data,const int len,u_char * signature,const int sig_len)80ccd87bacSchristos dst_hmac_md5_sign(const int mode, DST_KEY *d_key, void **context,
81ccd87bacSchristos 		  const u_char *data, const int len,
82ccd87bacSchristos 		  u_char *signature, const int sig_len)
83ccd87bacSchristos {
84ccd87bacSchristos 	HMAC_Key *key;
85ccd87bacSchristos 	int sign_len = 0;
86ccd87bacSchristos 	MD5_CTX *ctx = NULL;
87ccd87bacSchristos 
88ccd87bacSchristos 	if (d_key == NULL || d_key->dk_KEY_struct == NULL)
89ccd87bacSchristos 		return (-1);
90ccd87bacSchristos 
91ccd87bacSchristos 	if (mode & SIG_MODE_INIT)
92ccd87bacSchristos 		ctx = (MD5_CTX *) malloc(sizeof(*ctx));
93ccd87bacSchristos 	else if (context)
94ccd87bacSchristos 		ctx = (MD5_CTX *) *context;
95ccd87bacSchristos 	if (ctx == NULL)
96ccd87bacSchristos 		return (-1);
97ccd87bacSchristos 
98ccd87bacSchristos 	key = (HMAC_Key *) d_key->dk_KEY_struct;
99ccd87bacSchristos 
100ccd87bacSchristos 	if (mode & SIG_MODE_INIT) {
101ccd87bacSchristos 		MD5Init(ctx);
102ccd87bacSchristos 		MD5Update(ctx, key->hk_ipad, HMAC_LEN);
103ccd87bacSchristos 	}
104ccd87bacSchristos 
105ccd87bacSchristos 	if ((mode & SIG_MODE_UPDATE) && (data && len > 0))
106678bca00Schristos 		MD5Update(ctx, data, (unsigned int)len);
107ccd87bacSchristos 
108ccd87bacSchristos 	if (mode & SIG_MODE_FINAL) {
109ccd87bacSchristos 		if (signature == NULL || sig_len < MD5_LEN)
110ccd87bacSchristos 			return (SIGN_FINAL_FAILURE);
111ccd87bacSchristos 		MD5Final(signature, ctx);
112ccd87bacSchristos 
113ccd87bacSchristos 		/* perform outer MD5 */
114ccd87bacSchristos 		MD5Init(ctx);
115ccd87bacSchristos 		MD5Update(ctx, key->hk_opad, HMAC_LEN);
116ccd87bacSchristos 		MD5Update(ctx, signature, MD5_LEN);
117ccd87bacSchristos 		MD5Final(signature, ctx);
118ccd87bacSchristos 		sign_len = MD5_LEN;
119ccd87bacSchristos 		SAFE_FREE(ctx);
120ccd87bacSchristos 	}
121ccd87bacSchristos 	else {
122ccd87bacSchristos 		if (context == NULL)
123ccd87bacSchristos 			return (-1);
124ccd87bacSchristos 		*context = (void *) ctx;
125ccd87bacSchristos 	}
126ccd87bacSchristos 	return (sign_len);
127ccd87bacSchristos }
128ccd87bacSchristos 
129ccd87bacSchristos 
130ccd87bacSchristos /**************************************************************************
131ccd87bacSchristos  * dst_hmac_md5_verify()
132ccd87bacSchristos  *     Calls HMAC verification routines.  There are three steps to
133ccd87bacSchristos  *     verification, INIT (initialize structures), UPDATE (hash (more) data),
134ccd87bacSchristos  *     FINAL (generate a signature).  This routine performs one or more of
135ccd87bacSchristos  *     these steps.
136ccd87bacSchristos  * Parameters
137ccd87bacSchristos  *     mode	SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
138ccd87bacSchristos  *     dkey	key to use for verify.
139ccd87bacSchristos  *     data	data signed.
140ccd87bacSchristos  *     len	 length in bytes of data.
141ccd87bacSchristos  *     signature   signature.
142ccd87bacSchristos  *     sig_len     length in bytes of signature.
143ccd87bacSchristos  * returns
144ccd87bacSchristos  *     0  Success
145ccd87bacSchristos  *    <0  Failure
146ccd87bacSchristos  */
147ccd87bacSchristos 
148ccd87bacSchristos static int
dst_hmac_md5_verify(const int mode,DST_KEY * d_key,void ** context,const u_char * data,const int len,const u_char * signature,const int sig_len)149ccd87bacSchristos dst_hmac_md5_verify(const int mode, DST_KEY *d_key, void **context,
150ccd87bacSchristos 		const u_char *data, const int len,
151ccd87bacSchristos 		const u_char *signature, const int sig_len)
152ccd87bacSchristos {
153ccd87bacSchristos 	HMAC_Key *key;
154ccd87bacSchristos 	MD5_CTX *ctx = NULL;
155ccd87bacSchristos 
156ccd87bacSchristos 	if (d_key == NULL || d_key->dk_KEY_struct == NULL)
157ccd87bacSchristos 		return (-1);
158ccd87bacSchristos 
159ccd87bacSchristos 	if (mode & SIG_MODE_INIT)
160ccd87bacSchristos 		ctx = (MD5_CTX *) malloc(sizeof(*ctx));
161ccd87bacSchristos 	else if (context)
162ccd87bacSchristos 		ctx = (MD5_CTX *) *context;
163ccd87bacSchristos 	if (ctx == NULL)
164ccd87bacSchristos 		return (-1);
165ccd87bacSchristos 
166ccd87bacSchristos 	key = (HMAC_Key *) d_key->dk_KEY_struct;
167ccd87bacSchristos 	if (mode & SIG_MODE_INIT) {
168ccd87bacSchristos 		MD5Init(ctx);
169ccd87bacSchristos 		MD5Update(ctx, key->hk_ipad, HMAC_LEN);
170ccd87bacSchristos 	}
171ccd87bacSchristos 	if ((mode & SIG_MODE_UPDATE) && (data && len > 0))
172ccd87bacSchristos 		MD5Update(ctx, data, (unsigned int)len);
173ccd87bacSchristos 
174ccd87bacSchristos 	if (mode & SIG_MODE_FINAL) {
175ccd87bacSchristos 		u_char digest[MD5_LEN];
176ccd87bacSchristos 		if (signature == NULL || key == NULL || sig_len != MD5_LEN)
177ccd87bacSchristos 			return (VERIFY_FINAL_FAILURE);
178ccd87bacSchristos 		MD5Final(digest, ctx);
179ccd87bacSchristos 
180ccd87bacSchristos 		/* perform outer MD5 */
181ccd87bacSchristos 		MD5Init(ctx);
182ccd87bacSchristos 		MD5Update(ctx, key->hk_opad, HMAC_LEN);
183ccd87bacSchristos 		MD5Update(ctx, digest, MD5_LEN);
184ccd87bacSchristos 		MD5Final(digest, ctx);
185ccd87bacSchristos 
186ccd87bacSchristos 		SAFE_FREE(ctx);
187ccd87bacSchristos 		if (memcmp(digest, signature, MD5_LEN) != 0)
188ccd87bacSchristos 			return (VERIFY_FINAL_FAILURE);
189ccd87bacSchristos 	}
190ccd87bacSchristos 	else {
191ccd87bacSchristos 		if (context == NULL)
192ccd87bacSchristos 			return (-1);
193ccd87bacSchristos 		*context = (void *) ctx;
194ccd87bacSchristos 	}
195ccd87bacSchristos 	return (0);
196ccd87bacSchristos }
197ccd87bacSchristos 
198ccd87bacSchristos 
199ccd87bacSchristos /**************************************************************************
200ccd87bacSchristos  * dst_buffer_to_hmac_md5
201ccd87bacSchristos  *     Converts key from raw data to an HMAC Key
202ccd87bacSchristos  *     This function gets in a pointer to the data
203ccd87bacSchristos  * Parameters
204ccd87bacSchristos  *     hkey	the HMAC key to be filled in
205ccd87bacSchristos  *     key	the key in raw format
206ccd87bacSchristos  *     keylen	the length of the key
207ccd87bacSchristos  * Return
208ccd87bacSchristos  *	0	Success
209ccd87bacSchristos  *	<0	Failure
210ccd87bacSchristos  */
211ccd87bacSchristos static int
dst_buffer_to_hmac_md5(DST_KEY * dkey,const u_char * key,const int keylen)212ccd87bacSchristos dst_buffer_to_hmac_md5(DST_KEY *dkey, const u_char *key, const int keylen)
213ccd87bacSchristos {
214ccd87bacSchristos 	int i;
215ccd87bacSchristos 	HMAC_Key *hkey = NULL;
216ccd87bacSchristos 	MD5_CTX ctx;
217ccd87bacSchristos 	int local_keylen = keylen;
218ccd87bacSchristos 	u_char tk[MD5_LEN];
219ccd87bacSchristos 
220ccd87bacSchristos 	if (dkey == NULL || key == NULL || keylen < 0)
221ccd87bacSchristos 		return (-1);
222ccd87bacSchristos 
223ccd87bacSchristos 	if ((hkey = (HMAC_Key *) malloc(sizeof(HMAC_Key))) == NULL)
224ccd87bacSchristos 		  return (-2);
225ccd87bacSchristos 
226ccd87bacSchristos 	memset(hkey->hk_ipad, 0, sizeof(hkey->hk_ipad));
227ccd87bacSchristos 	memset(hkey->hk_opad, 0, sizeof(hkey->hk_opad));
228ccd87bacSchristos 
229ccd87bacSchristos 	/* if key is longer than HMAC_LEN bytes reset it to key=MD5(key) */
230ccd87bacSchristos 	if (keylen > HMAC_LEN) {
231ccd87bacSchristos 		MD5Init(&ctx);
232ccd87bacSchristos 		MD5Update(&ctx, key, (unsigned int)keylen);
233ccd87bacSchristos 		MD5Final(tk, &ctx);
234ccd87bacSchristos 		memset((void *) &ctx, 0, sizeof(ctx));
235ccd87bacSchristos 		key = tk;
236ccd87bacSchristos 		local_keylen = MD5_LEN;
237ccd87bacSchristos 	}
238ccd87bacSchristos 	/* start out by storing key in pads */
239ccd87bacSchristos 	memcpy(hkey->hk_ipad, key, local_keylen);
240ccd87bacSchristos 	memcpy(hkey->hk_opad, key, local_keylen);
241ccd87bacSchristos 
242ccd87bacSchristos 	/* XOR key with hk_ipad and opad values */
243ccd87bacSchristos 	for (i = 0; i < HMAC_LEN; i++) {
244ccd87bacSchristos 		hkey->hk_ipad[i] ^= HMAC_IPAD;
245ccd87bacSchristos 		hkey->hk_opad[i] ^= HMAC_OPAD;
246ccd87bacSchristos 	}
247ccd87bacSchristos 	dkey->dk_key_size = local_keylen;
248ccd87bacSchristos 	dkey->dk_KEY_struct = (void *) hkey;
249ccd87bacSchristos 	return (1);
250ccd87bacSchristos }
251ccd87bacSchristos 
252ccd87bacSchristos 
253ccd87bacSchristos /**************************************************************************
254ccd87bacSchristos  *  dst_hmac_md5_key_to_file_format
255ccd87bacSchristos  *	Encodes an HMAC Key into the portable file format.
256ccd87bacSchristos  *  Parameters
257ccd87bacSchristos  *	hkey      HMAC KEY structure
258ccd87bacSchristos  *	buff      output buffer
259ccd87bacSchristos  *	buff_len  size of output buffer
260ccd87bacSchristos  *  Return
261ccd87bacSchristos  *	0  Failure - null input hkey
262ccd87bacSchristos  *     -1  Failure - not enough space in output area
263ccd87bacSchristos  *	N  Success - Length of data returned in buff
264ccd87bacSchristos  */
265ccd87bacSchristos 
266ccd87bacSchristos static int
dst_hmac_md5_key_to_file_format(const DST_KEY * dkey,char * buff,const int buff_len)267ccd87bacSchristos dst_hmac_md5_key_to_file_format(const DST_KEY *dkey, char *buff,
268ccd87bacSchristos 			        const int buff_len)
269ccd87bacSchristos {
270ccd87bacSchristos 	char *bp;
271*95e3bb37Schristos #define BUF_LEFT (size_t)(buff_len - (bp - buff))
272*95e3bb37Schristos 	int len, key_len;
273ccd87bacSchristos 	u_char key[HMAC_LEN];
274ccd87bacSchristos 	HMAC_Key *hkey;
275*95e3bb37Schristos 	static const char keystr[] = "Key: ";
276*95e3bb37Schristos 
277*95e3bb37Schristos 	if (buff == NULL)
278*95e3bb37Schristos 		return -1;	/*%< no output area */
279ccd87bacSchristos 
280ccd87bacSchristos 	if (dkey == NULL || dkey->dk_KEY_struct == NULL)
281*95e3bb37Schristos 		return 0;
282*95e3bb37Schristos 
283ccd87bacSchristos 	/* write file header */
284*95e3bb37Schristos 	hkey = (HMAC_Key *) dkey->dk_KEY_struct;
285*95e3bb37Schristos 	len = snprintf(buff, buff_len, KEY_FILE_FMT_STR, KEY_FILE_FORMAT,
286ccd87bacSchristos 	    KEY_HMAC_MD5, "HMAC");
287*95e3bb37Schristos 	if (len < 0 || len >= buff_len)
288*95e3bb37Schristos 		return -1; 	/*%< not enough space in output area */
289*95e3bb37Schristos 	bp = buff + len;
290*95e3bb37Schristos 	if (BUF_LEFT < sizeof(keystr))
291*95e3bb37Schristos 		return -1;
292ccd87bacSchristos 
293*95e3bb37Schristos 	memcpy(bp, keystr, sizeof(keystr) - 1);
294*95e3bb37Schristos 	bp += sizeof(keystr) - 1;
295ccd87bacSchristos 
296*95e3bb37Schristos 	for (key_len = 0; key_len < HMAC_LEN; key_len++)
297*95e3bb37Schristos 		key[key_len] = hkey->hk_ipad[key_len] ^ HMAC_IPAD;
298*95e3bb37Schristos 	for (key_len = HMAC_LEN - 1; key_len >= 0; key_len--)
299*95e3bb37Schristos 		if (key[key_len] != 0)
300ccd87bacSchristos 			break;
301*95e3bb37Schristos 	key_len++;
302ccd87bacSchristos 
303*95e3bb37Schristos 	len = b64_ntop(key, key_len, bp, BUF_LEFT);
304ccd87bacSchristos 	if (len < 0)
305*95e3bb37Schristos 		return -1;
306ccd87bacSchristos 	bp += len;
307*95e3bb37Schristos 
308*95e3bb37Schristos 	if (BUF_LEFT < 2)
309*95e3bb37Schristos 		return -1;
310ccd87bacSchristos 	*(bp++) = '\n';
311*95e3bb37Schristos 
312*95e3bb37Schristos 	memset(bp, 0, BUF_LEFT);
313ccd87bacSchristos 
314ccd87bacSchristos 	return (int)(bp - buff);
315ccd87bacSchristos }
316ccd87bacSchristos 
317ccd87bacSchristos 
318ccd87bacSchristos /**************************************************************************
319ccd87bacSchristos  * dst_hmac_md5_key_from_file_format
320ccd87bacSchristos  *     Converts contents of a key file into an HMAC key.
321ccd87bacSchristos  * Parameters
322ccd87bacSchristos  *     hkey    structure to put key into
323ccd87bacSchristos  *     buff       buffer containing the encoded key
324ccd87bacSchristos  *     buff_len   the length of the buffer
325ccd87bacSchristos  * Return
326ccd87bacSchristos  *     n >= 0 Foot print of the key converted
327ccd87bacSchristos  *     n <  0 Error in conversion
328ccd87bacSchristos  */
329ccd87bacSchristos 
330ccd87bacSchristos static int
dst_hmac_md5_key_from_file_format(DST_KEY * dkey,const char * buff,const int buff_len)331ccd87bacSchristos dst_hmac_md5_key_from_file_format(DST_KEY *dkey, const char *buff,
332ccd87bacSchristos 			      const int buff_len)
333ccd87bacSchristos {
334ccd87bacSchristos 	const char *p = buff, *eol;
335ccd87bacSchristos 	u_char key[HMAC_LEN+1];	/* b64_pton needs more than 64 bytes do decode
336ccd87bacSchristos 				 * it should probably be fixed rather than doing
337ccd87bacSchristos 				 * this
338ccd87bacSchristos 				 */
339ccd87bacSchristos 	u_char *tmp;
340ccd87bacSchristos 	int key_len, len;
341ccd87bacSchristos 
342ccd87bacSchristos 	if (dkey == NULL)
343ccd87bacSchristos 		return (-2);
344ccd87bacSchristos 	if (buff == NULL || buff_len < 0)
345ccd87bacSchristos 		return (-1);
346ccd87bacSchristos 
347ccd87bacSchristos 	memset(key, 0, sizeof(key));
348ccd87bacSchristos 
349ccd87bacSchristos 	if (!dst_s_verify_str(&p, "Key: "))
350ccd87bacSchristos 		return (-3);
351ccd87bacSchristos 
352ccd87bacSchristos 	eol = strchr(p, '\n');
353ccd87bacSchristos 	if (eol == NULL)
354ccd87bacSchristos 		return (-4);
355ccd87bacSchristos 	len = (int)(eol - p);
356ccd87bacSchristos 	tmp = malloc(len + 2);
357ccd87bacSchristos 	if (tmp == NULL)
358ccd87bacSchristos 		return (-5);
359ccd87bacSchristos 	memcpy(tmp, p, len);
360ccd87bacSchristos 	*(tmp + len) = 0x0;
361ccd87bacSchristos 	key_len = b64_pton((char *)tmp, key, HMAC_LEN+1);	/*%< see above */
362ccd87bacSchristos 	SAFE_FREE2(tmp, len + 2);
363ccd87bacSchristos 
364ccd87bacSchristos 	if (dst_buffer_to_hmac_md5(dkey, key, key_len) < 0) {
365ccd87bacSchristos 		return (-6);
366ccd87bacSchristos 	}
367ccd87bacSchristos 	return (0);
368ccd87bacSchristos }
369ccd87bacSchristos 
370ccd87bacSchristos /*%
371ccd87bacSchristos  * dst_hmac_md5_to_dns_key()
372ccd87bacSchristos  *         function to extract hmac key from DST_KEY structure
373ccd87bacSchristos  * intput:
374ccd87bacSchristos  *      in_key:  HMAC-MD5 key
375ccd87bacSchristos  * output:
376ccd87bacSchristos  *	out_str: buffer to write ot
377ccd87bacSchristos  *      out_len: size of output buffer
378ccd87bacSchristos  * returns:
379ccd87bacSchristos  *      number of bytes written to output buffer
380ccd87bacSchristos  */
381ccd87bacSchristos static int
dst_hmac_md5_to_dns_key(const DST_KEY * in_key,u_char * out_str,const int out_len)382ccd87bacSchristos dst_hmac_md5_to_dns_key(const DST_KEY *in_key, u_char *out_str,
383ccd87bacSchristos 			const int out_len)
384ccd87bacSchristos {
385ccd87bacSchristos 
386ccd87bacSchristos 	HMAC_Key *hkey;
387ccd87bacSchristos 	int i;
388ccd87bacSchristos 
389ccd87bacSchristos 	if (in_key == NULL || in_key->dk_KEY_struct == NULL ||
390ccd87bacSchristos 	    out_len <= in_key->dk_key_size || out_str == NULL)
391ccd87bacSchristos 		return (-1);
392ccd87bacSchristos 
393ccd87bacSchristos 	hkey = (HMAC_Key *) in_key->dk_KEY_struct;
394ccd87bacSchristos 	for (i = 0; i < in_key->dk_key_size; i++)
395ccd87bacSchristos 		out_str[i] = hkey->hk_ipad[i] ^ HMAC_IPAD;
396ccd87bacSchristos 	return (i);
397ccd87bacSchristos }
398ccd87bacSchristos 
399ccd87bacSchristos /**************************************************************************
400ccd87bacSchristos  *  dst_hmac_md5_compare_keys
401ccd87bacSchristos  *	Compare two keys for equality.
402ccd87bacSchristos  *  Return
403ccd87bacSchristos  *	0	  The keys are equal
404ccd87bacSchristos  *	NON-ZERO   The keys are not equal
405ccd87bacSchristos  */
406ccd87bacSchristos 
407ccd87bacSchristos static int
dst_hmac_md5_compare_keys(const DST_KEY * key1,const DST_KEY * key2)408ccd87bacSchristos dst_hmac_md5_compare_keys(const DST_KEY *key1, const DST_KEY *key2)
409ccd87bacSchristos {
410ccd87bacSchristos 	HMAC_Key *hkey1 = (HMAC_Key *) key1->dk_KEY_struct;
411ccd87bacSchristos 	HMAC_Key *hkey2 = (HMAC_Key *) key2->dk_KEY_struct;
412ccd87bacSchristos 	return memcmp(hkey1->hk_ipad, hkey2->hk_ipad, HMAC_LEN);
413ccd87bacSchristos }
414ccd87bacSchristos 
415ccd87bacSchristos /**************************************************************************
416ccd87bacSchristos  * dst_hmac_md5_free_key_structure
417ccd87bacSchristos  *     Frees all (none) dynamically allocated structures in hkey
418ccd87bacSchristos  */
419ccd87bacSchristos 
420ccd87bacSchristos static void *
dst_hmac_md5_free_key_structure(void * key)421ccd87bacSchristos dst_hmac_md5_free_key_structure(void *key)
422ccd87bacSchristos {
423ccd87bacSchristos 	HMAC_Key *hkey = key;
424ccd87bacSchristos 	SAFE_FREE(hkey);
425ccd87bacSchristos 	return (NULL);
426ccd87bacSchristos }
427ccd87bacSchristos 
428ccd87bacSchristos 
429ccd87bacSchristos /***************************************************************************
430ccd87bacSchristos  * dst_hmac_md5_generate_key
431ccd87bacSchristos  *     Creates a HMAC key of size size with a maximum size of 63 bytes
432ccd87bacSchristos  *     generating a HMAC key larger than 63 bytes makes no sense as that key
433ccd87bacSchristos  *     is digested before use.
434ccd87bacSchristos  */
435ccd87bacSchristos 
436ccd87bacSchristos static int
437ccd87bacSchristos /*ARGSUSED*/
dst_hmac_md5_generate_key(DST_KEY * key,const int nothing)438ccd87bacSchristos dst_hmac_md5_generate_key(DST_KEY *key, const int nothing)
439ccd87bacSchristos {
440ccd87bacSchristos 	return (-1);
441ccd87bacSchristos }
442ccd87bacSchristos 
443ccd87bacSchristos /*%
444ccd87bacSchristos  * dst_hmac_md5_init()  Function to answer set up function pointers for HMAC
445ccd87bacSchristos  *	   related functions
446ccd87bacSchristos  */
447ccd87bacSchristos int
448ccd87bacSchristos #ifdef	SUNW_LIBMD5
dst_md5_hmac_init(void)449ccd87bacSchristos dst_md5_hmac_init(void)
450ccd87bacSchristos #else
451ccd87bacSchristos dst_hmac_md5_init(void)
452ccd87bacSchristos #endif
453ccd87bacSchristos {
454ccd87bacSchristos 	if (dst_t_func[KEY_HMAC_MD5] != NULL)
455ccd87bacSchristos 		return (1);
456ccd87bacSchristos 	dst_t_func[KEY_HMAC_MD5] = malloc(sizeof(struct dst_func));
457ccd87bacSchristos 	if (dst_t_func[KEY_HMAC_MD5] == NULL)
458ccd87bacSchristos 		return (0);
459ccd87bacSchristos 	memset(dst_t_func[KEY_HMAC_MD5], 0, sizeof(struct dst_func));
460ccd87bacSchristos 	dst_t_func[KEY_HMAC_MD5]->sign = dst_hmac_md5_sign;
461ccd87bacSchristos 	dst_t_func[KEY_HMAC_MD5]->verify = dst_hmac_md5_verify;
462ccd87bacSchristos 	dst_t_func[KEY_HMAC_MD5]->compare = dst_hmac_md5_compare_keys;
463ccd87bacSchristos 	dst_t_func[KEY_HMAC_MD5]->generate = dst_hmac_md5_generate_key;
464ccd87bacSchristos 	dst_t_func[KEY_HMAC_MD5]->destroy = dst_hmac_md5_free_key_structure;
465ccd87bacSchristos 	dst_t_func[KEY_HMAC_MD5]->to_dns_key = dst_hmac_md5_to_dns_key;
466ccd87bacSchristos 	dst_t_func[KEY_HMAC_MD5]->from_dns_key = dst_buffer_to_hmac_md5;
467ccd87bacSchristos 	dst_t_func[KEY_HMAC_MD5]->to_file_fmt = dst_hmac_md5_key_to_file_format;
468ccd87bacSchristos 	dst_t_func[KEY_HMAC_MD5]->from_file_fmt = dst_hmac_md5_key_from_file_format;
469ccd87bacSchristos 	return (1);
470ccd87bacSchristos }
471ccd87bacSchristos 
472ccd87bacSchristos /*! \file */
473