17c478bd9Sstevel@tonic-gate /* 2*9525b14bSRao Shoaib * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate 77c478bd9Sstevel@tonic-gate #ifdef HMAC_MD5 87c478bd9Sstevel@tonic-gate #ifndef LINT 9*9525b14bSRao Shoaib static const char rcsid[] = "$Header: /proj/cvs/prod/libbind/dst/hmac_link.c,v 1.8 2007/09/24 17:18:25 each Exp $"; 107c478bd9Sstevel@tonic-gate #endif 117c478bd9Sstevel@tonic-gate /* 127c478bd9Sstevel@tonic-gate * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * Permission to use, copy modify, and distribute this software for any 157c478bd9Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 167c478bd9Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 177c478bd9Sstevel@tonic-gate * 187c478bd9Sstevel@tonic-gate * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS 197c478bd9Sstevel@tonic-gate * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 207c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 217c478bd9Sstevel@tonic-gate * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, 227c478bd9Sstevel@tonic-gate * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING 237c478bd9Sstevel@tonic-gate * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 247c478bd9Sstevel@tonic-gate * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 257c478bd9Sstevel@tonic-gate * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 28*9525b14bSRao Shoaib /*% 297c478bd9Sstevel@tonic-gate * This file contains an implementation of the HMAC-MD5 algorithm. 307c478bd9Sstevel@tonic-gate */ 317c478bd9Sstevel@tonic-gate #include "port_before.h" 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include <stdio.h> 347c478bd9Sstevel@tonic-gate #include <unistd.h> 357c478bd9Sstevel@tonic-gate #include <stdlib.h> 367c478bd9Sstevel@tonic-gate #include <string.h> 377c478bd9Sstevel@tonic-gate #include <memory.h> 387c478bd9Sstevel@tonic-gate #include <sys/param.h> 397c478bd9Sstevel@tonic-gate #include <sys/time.h> 407c478bd9Sstevel@tonic-gate #include <netinet/in.h> 417c478bd9Sstevel@tonic-gate #include <arpa/nameser.h> 427c478bd9Sstevel@tonic-gate #include <resolv.h> 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate #include "dst_internal.h" 45*9525b14bSRao Shoaib 467c478bd9Sstevel@tonic-gate #ifdef USE_MD5 47*9525b14bSRao Shoaib # ifndef HAVE_MD5 487c478bd9Sstevel@tonic-gate # include "md5.h" 497c478bd9Sstevel@tonic-gate # else 50*9525b14bSRao Shoaib # ifdef SOLARIS2 517c478bd9Sstevel@tonic-gate # include <sys/md5.h> 527c478bd9Sstevel@tonic-gate # endif 53*9525b14bSRao Shoaib # endif 547c478bd9Sstevel@tonic-gate # ifndef _MD5_H_ 55*9525b14bSRao Shoaib # define _MD5_H_ 1 /*%< make sure we do not include rsaref md5.h file */ 567c478bd9Sstevel@tonic-gate # endif 577c478bd9Sstevel@tonic-gate #endif 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate #include "port_after.h" 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate #define HMAC_LEN 64 637c478bd9Sstevel@tonic-gate #define HMAC_IPAD 0x36 647c478bd9Sstevel@tonic-gate #define HMAC_OPAD 0x5c 657c478bd9Sstevel@tonic-gate #define MD5_LEN 16 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate typedef struct hmackey { 697c478bd9Sstevel@tonic-gate u_char hk_ipad[64], hk_opad[64]; 707c478bd9Sstevel@tonic-gate } HMAC_Key; 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate /************************************************************************** 747c478bd9Sstevel@tonic-gate * dst_hmac_md5_sign 757c478bd9Sstevel@tonic-gate * Call HMAC signing functions to sign a block of data. 767c478bd9Sstevel@tonic-gate * There are three steps to signing, INIT (initialize structures), 777c478bd9Sstevel@tonic-gate * UPDATE (hash (more) data), FINAL (generate a signature). This 787c478bd9Sstevel@tonic-gate * routine performs one or more of these steps. 797c478bd9Sstevel@tonic-gate * Parameters 807c478bd9Sstevel@tonic-gate * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. 817c478bd9Sstevel@tonic-gate * priv_key key to use for signing. 827c478bd9Sstevel@tonic-gate * context the context to be used in this digest 837c478bd9Sstevel@tonic-gate * data data to be signed. 847c478bd9Sstevel@tonic-gate * len length in bytes of data. 857c478bd9Sstevel@tonic-gate * signature location to store signature. 867c478bd9Sstevel@tonic-gate * sig_len size of the signature location 877c478bd9Sstevel@tonic-gate * returns 887c478bd9Sstevel@tonic-gate * N Success on SIG_MODE_FINAL = returns signature length in bytes 897c478bd9Sstevel@tonic-gate * 0 Success on SIG_MODE_INIT and UPDATE 907c478bd9Sstevel@tonic-gate * <0 Failure 917c478bd9Sstevel@tonic-gate */ 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate static int 947c478bd9Sstevel@tonic-gate dst_hmac_md5_sign(const int mode, DST_KEY *d_key, void **context, 957c478bd9Sstevel@tonic-gate const u_char *data, const int len, 967c478bd9Sstevel@tonic-gate u_char *signature, const int sig_len) 977c478bd9Sstevel@tonic-gate { 987c478bd9Sstevel@tonic-gate HMAC_Key *key; 997c478bd9Sstevel@tonic-gate int sign_len = 0; 1007c478bd9Sstevel@tonic-gate MD5_CTX *ctx = NULL; 1017c478bd9Sstevel@tonic-gate 102*9525b14bSRao Shoaib if (d_key == NULL || d_key->dk_KEY_struct == NULL) 103*9525b14bSRao Shoaib return (-1); 104*9525b14bSRao Shoaib 1057c478bd9Sstevel@tonic-gate if (mode & SIG_MODE_INIT) 1067c478bd9Sstevel@tonic-gate ctx = (MD5_CTX *) malloc(sizeof(*ctx)); 1077c478bd9Sstevel@tonic-gate else if (context) 1087c478bd9Sstevel@tonic-gate ctx = (MD5_CTX *) *context; 1097c478bd9Sstevel@tonic-gate if (ctx == NULL) 1107c478bd9Sstevel@tonic-gate return (-1); 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate key = (HMAC_Key *) d_key->dk_KEY_struct; 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate if (mode & SIG_MODE_INIT) { 1157c478bd9Sstevel@tonic-gate MD5Init(ctx); 1167c478bd9Sstevel@tonic-gate MD5Update(ctx, key->hk_ipad, HMAC_LEN); 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) 1207c478bd9Sstevel@tonic-gate MD5Update(ctx, data, len); 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate if (mode & SIG_MODE_FINAL) { 1237c478bd9Sstevel@tonic-gate if (signature == NULL || sig_len < MD5_LEN) 1247c478bd9Sstevel@tonic-gate return (SIGN_FINAL_FAILURE); 1257c478bd9Sstevel@tonic-gate MD5Final(signature, ctx); 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate /* perform outer MD5 */ 1287c478bd9Sstevel@tonic-gate MD5Init(ctx); 1297c478bd9Sstevel@tonic-gate MD5Update(ctx, key->hk_opad, HMAC_LEN); 1307c478bd9Sstevel@tonic-gate MD5Update(ctx, signature, MD5_LEN); 1317c478bd9Sstevel@tonic-gate MD5Final(signature, ctx); 1327c478bd9Sstevel@tonic-gate sign_len = MD5_LEN; 1337c478bd9Sstevel@tonic-gate SAFE_FREE(ctx); 1347c478bd9Sstevel@tonic-gate } 1357c478bd9Sstevel@tonic-gate else { 1367c478bd9Sstevel@tonic-gate if (context == NULL) 1377c478bd9Sstevel@tonic-gate return (-1); 1387c478bd9Sstevel@tonic-gate *context = (void *) ctx; 1397c478bd9Sstevel@tonic-gate } 1407c478bd9Sstevel@tonic-gate return (sign_len); 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate /************************************************************************** 1457c478bd9Sstevel@tonic-gate * dst_hmac_md5_verify() 1467c478bd9Sstevel@tonic-gate * Calls HMAC verification routines. There are three steps to 1477c478bd9Sstevel@tonic-gate * verification, INIT (initialize structures), UPDATE (hash (more) data), 1487c478bd9Sstevel@tonic-gate * FINAL (generate a signature). This routine performs one or more of 1497c478bd9Sstevel@tonic-gate * these steps. 1507c478bd9Sstevel@tonic-gate * Parameters 1517c478bd9Sstevel@tonic-gate * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. 1527c478bd9Sstevel@tonic-gate * dkey key to use for verify. 1537c478bd9Sstevel@tonic-gate * data data signed. 1547c478bd9Sstevel@tonic-gate * len length in bytes of data. 1557c478bd9Sstevel@tonic-gate * signature signature. 1567c478bd9Sstevel@tonic-gate * sig_len length in bytes of signature. 1577c478bd9Sstevel@tonic-gate * returns 1587c478bd9Sstevel@tonic-gate * 0 Success 1597c478bd9Sstevel@tonic-gate * <0 Failure 1607c478bd9Sstevel@tonic-gate */ 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate static int 1637c478bd9Sstevel@tonic-gate dst_hmac_md5_verify(const int mode, DST_KEY *d_key, void **context, 1647c478bd9Sstevel@tonic-gate const u_char *data, const int len, 1657c478bd9Sstevel@tonic-gate const u_char *signature, const int sig_len) 1667c478bd9Sstevel@tonic-gate { 1677c478bd9Sstevel@tonic-gate HMAC_Key *key; 1687c478bd9Sstevel@tonic-gate MD5_CTX *ctx = NULL; 1697c478bd9Sstevel@tonic-gate 170*9525b14bSRao Shoaib if (d_key == NULL || d_key->dk_KEY_struct == NULL) 171*9525b14bSRao Shoaib return (-1); 172*9525b14bSRao Shoaib 1737c478bd9Sstevel@tonic-gate if (mode & SIG_MODE_INIT) 1747c478bd9Sstevel@tonic-gate ctx = (MD5_CTX *) malloc(sizeof(*ctx)); 1757c478bd9Sstevel@tonic-gate else if (context) 1767c478bd9Sstevel@tonic-gate ctx = (MD5_CTX *) *context; 1777c478bd9Sstevel@tonic-gate if (ctx == NULL) 1787c478bd9Sstevel@tonic-gate return (-1); 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate key = (HMAC_Key *) d_key->dk_KEY_struct; 1817c478bd9Sstevel@tonic-gate if (mode & SIG_MODE_INIT) { 1827c478bd9Sstevel@tonic-gate MD5Init(ctx); 1837c478bd9Sstevel@tonic-gate MD5Update(ctx, key->hk_ipad, HMAC_LEN); 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) 1867c478bd9Sstevel@tonic-gate MD5Update(ctx, data, len); 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate if (mode & SIG_MODE_FINAL) { 1897c478bd9Sstevel@tonic-gate u_char digest[MD5_LEN]; 1907c478bd9Sstevel@tonic-gate if (signature == NULL || key == NULL || sig_len != MD5_LEN) 1917c478bd9Sstevel@tonic-gate return (VERIFY_FINAL_FAILURE); 1927c478bd9Sstevel@tonic-gate MD5Final(digest, ctx); 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* perform outer MD5 */ 1957c478bd9Sstevel@tonic-gate MD5Init(ctx); 1967c478bd9Sstevel@tonic-gate MD5Update(ctx, key->hk_opad, HMAC_LEN); 1977c478bd9Sstevel@tonic-gate MD5Update(ctx, digest, MD5_LEN); 1987c478bd9Sstevel@tonic-gate MD5Final(digest, ctx); 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate SAFE_FREE(ctx); 2017c478bd9Sstevel@tonic-gate if (memcmp(digest, signature, MD5_LEN) != 0) 2027c478bd9Sstevel@tonic-gate return (VERIFY_FINAL_FAILURE); 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate else { 2057c478bd9Sstevel@tonic-gate if (context == NULL) 2067c478bd9Sstevel@tonic-gate return (-1); 2077c478bd9Sstevel@tonic-gate *context = (void *) ctx; 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate return (0); 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate /************************************************************************** 2147c478bd9Sstevel@tonic-gate * dst_buffer_to_hmac_md5 2157c478bd9Sstevel@tonic-gate * Converts key from raw data to an HMAC Key 2167c478bd9Sstevel@tonic-gate * This function gets in a pointer to the data 2177c478bd9Sstevel@tonic-gate * Parameters 2187c478bd9Sstevel@tonic-gate * hkey the HMAC key to be filled in 2197c478bd9Sstevel@tonic-gate * key the key in raw format 2207c478bd9Sstevel@tonic-gate * keylen the length of the key 2217c478bd9Sstevel@tonic-gate * Return 2227c478bd9Sstevel@tonic-gate * 0 Success 2237c478bd9Sstevel@tonic-gate * <0 Failure 2247c478bd9Sstevel@tonic-gate */ 2257c478bd9Sstevel@tonic-gate static int 2267c478bd9Sstevel@tonic-gate dst_buffer_to_hmac_md5(DST_KEY *dkey, const u_char *key, const int keylen) 2277c478bd9Sstevel@tonic-gate { 2287c478bd9Sstevel@tonic-gate int i; 2297c478bd9Sstevel@tonic-gate HMAC_Key *hkey = NULL; 2307c478bd9Sstevel@tonic-gate MD5_CTX ctx; 2317c478bd9Sstevel@tonic-gate int local_keylen = keylen; 232*9525b14bSRao Shoaib u_char tk[MD5_LEN]; 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate if (dkey == NULL || key == NULL || keylen < 0) 2357c478bd9Sstevel@tonic-gate return (-1); 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate if ((hkey = (HMAC_Key *) malloc(sizeof(HMAC_Key))) == NULL) 2387c478bd9Sstevel@tonic-gate return (-2); 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate memset(hkey->hk_ipad, 0, sizeof(hkey->hk_ipad)); 2417c478bd9Sstevel@tonic-gate memset(hkey->hk_opad, 0, sizeof(hkey->hk_opad)); 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate /* if key is longer than HMAC_LEN bytes reset it to key=MD5(key) */ 2447c478bd9Sstevel@tonic-gate if (keylen > HMAC_LEN) { 2457c478bd9Sstevel@tonic-gate MD5Init(&ctx); 2467c478bd9Sstevel@tonic-gate MD5Update(&ctx, key, keylen); 2477c478bd9Sstevel@tonic-gate MD5Final(tk, &ctx); 2487c478bd9Sstevel@tonic-gate memset((void *) &ctx, 0, sizeof(ctx)); 2497c478bd9Sstevel@tonic-gate key = tk; 2507c478bd9Sstevel@tonic-gate local_keylen = MD5_LEN; 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate /* start out by storing key in pads */ 2537c478bd9Sstevel@tonic-gate memcpy(hkey->hk_ipad, key, local_keylen); 2547c478bd9Sstevel@tonic-gate memcpy(hkey->hk_opad, key, local_keylen); 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate /* XOR key with hk_ipad and opad values */ 2577c478bd9Sstevel@tonic-gate for (i = 0; i < HMAC_LEN; i++) { 2587c478bd9Sstevel@tonic-gate hkey->hk_ipad[i] ^= HMAC_IPAD; 2597c478bd9Sstevel@tonic-gate hkey->hk_opad[i] ^= HMAC_OPAD; 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate dkey->dk_key_size = local_keylen; 2627c478bd9Sstevel@tonic-gate dkey->dk_KEY_struct = (void *) hkey; 2637c478bd9Sstevel@tonic-gate return (1); 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate /************************************************************************** 2687c478bd9Sstevel@tonic-gate * dst_hmac_md5_key_to_file_format 2697c478bd9Sstevel@tonic-gate * Encodes an HMAC Key into the portable file format. 2707c478bd9Sstevel@tonic-gate * Parameters 2717c478bd9Sstevel@tonic-gate * hkey HMAC KEY structure 2727c478bd9Sstevel@tonic-gate * buff output buffer 2737c478bd9Sstevel@tonic-gate * buff_len size of output buffer 2747c478bd9Sstevel@tonic-gate * Return 2757c478bd9Sstevel@tonic-gate * 0 Failure - null input hkey 2767c478bd9Sstevel@tonic-gate * -1 Failure - not enough space in output area 2777c478bd9Sstevel@tonic-gate * N Success - Length of data returned in buff 2787c478bd9Sstevel@tonic-gate */ 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate static int 2817c478bd9Sstevel@tonic-gate dst_hmac_md5_key_to_file_format(const DST_KEY *dkey, char *buff, 2827c478bd9Sstevel@tonic-gate const int buff_len) 2837c478bd9Sstevel@tonic-gate { 2847c478bd9Sstevel@tonic-gate char *bp; 285*9525b14bSRao Shoaib int len, i, key_len; 2867c478bd9Sstevel@tonic-gate u_char key[HMAC_LEN]; 2877c478bd9Sstevel@tonic-gate HMAC_Key *hkey; 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate if (dkey == NULL || dkey->dk_KEY_struct == NULL) 2907c478bd9Sstevel@tonic-gate return (0); 291*9525b14bSRao Shoaib /* 292*9525b14bSRao Shoaib * Using snprintf() would be so much simpler here. 293*9525b14bSRao Shoaib */ 294*9525b14bSRao Shoaib if (buff == NULL || 295*9525b14bSRao Shoaib buff_len <= (int)(strlen(key_file_fmt_str) + 296*9525b14bSRao Shoaib strlen(KEY_FILE_FORMAT) + 4)) 297*9525b14bSRao Shoaib return (-1); /*%< no OR not enough space in output area */ 2987c478bd9Sstevel@tonic-gate hkey = (HMAC_Key *) dkey->dk_KEY_struct; 299*9525b14bSRao Shoaib memset(buff, 0, buff_len); /*%< just in case */ 3007c478bd9Sstevel@tonic-gate /* write file header */ 3017c478bd9Sstevel@tonic-gate sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_HMAC_MD5, "HMAC"); 3027c478bd9Sstevel@tonic-gate 303*9525b14bSRao Shoaib bp = buff + strlen(buff); 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate memset(key, 0, HMAC_LEN); 3067c478bd9Sstevel@tonic-gate for (i = 0; i < HMAC_LEN; i++) 3077c478bd9Sstevel@tonic-gate key[i] = hkey->hk_ipad[i] ^ HMAC_IPAD; 3087c478bd9Sstevel@tonic-gate for (i = HMAC_LEN - 1; i >= 0; i--) 3097c478bd9Sstevel@tonic-gate if (key[i] != 0) 3107c478bd9Sstevel@tonic-gate break; 3117c478bd9Sstevel@tonic-gate key_len = i + 1; 3127c478bd9Sstevel@tonic-gate 313*9525b14bSRao Shoaib if (buff_len - (bp - buff) < 6) 314*9525b14bSRao Shoaib return (-1); 3157c478bd9Sstevel@tonic-gate strcat(bp, "Key: "); 3167c478bd9Sstevel@tonic-gate bp += strlen("Key: "); 3177c478bd9Sstevel@tonic-gate 318*9525b14bSRao Shoaib len = b64_ntop(key, key_len, bp, buff_len - (bp - buff)); 3197c478bd9Sstevel@tonic-gate if (len < 0) 3207c478bd9Sstevel@tonic-gate return (-1); 3217c478bd9Sstevel@tonic-gate bp += len; 322*9525b14bSRao Shoaib if (buff_len - (bp - buff) < 2) 323*9525b14bSRao Shoaib return (-1); 3247c478bd9Sstevel@tonic-gate *(bp++) = '\n'; 3257c478bd9Sstevel@tonic-gate *bp = '\0'; 3267c478bd9Sstevel@tonic-gate 327*9525b14bSRao Shoaib return (bp - buff); 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate /************************************************************************** 3327c478bd9Sstevel@tonic-gate * dst_hmac_md5_key_from_file_format 3337c478bd9Sstevel@tonic-gate * Converts contents of a key file into an HMAC key. 3347c478bd9Sstevel@tonic-gate * Parameters 3357c478bd9Sstevel@tonic-gate * hkey structure to put key into 3367c478bd9Sstevel@tonic-gate * buff buffer containing the encoded key 3377c478bd9Sstevel@tonic-gate * buff_len the length of the buffer 3387c478bd9Sstevel@tonic-gate * Return 3397c478bd9Sstevel@tonic-gate * n >= 0 Foot print of the key converted 3407c478bd9Sstevel@tonic-gate * n < 0 Error in conversion 3417c478bd9Sstevel@tonic-gate */ 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate static int 3447c478bd9Sstevel@tonic-gate dst_hmac_md5_key_from_file_format(DST_KEY *dkey, const char *buff, 3457c478bd9Sstevel@tonic-gate const int buff_len) 3467c478bd9Sstevel@tonic-gate { 3477c478bd9Sstevel@tonic-gate const char *p = buff, *eol; 3487c478bd9Sstevel@tonic-gate u_char key[HMAC_LEN+1]; /* b64_pton needs more than 64 bytes do decode 3497c478bd9Sstevel@tonic-gate * it should probably be fixed rather than doing 3507c478bd9Sstevel@tonic-gate * this 3517c478bd9Sstevel@tonic-gate */ 3527c478bd9Sstevel@tonic-gate u_char *tmp; 3537c478bd9Sstevel@tonic-gate int key_len, len; 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate if (dkey == NULL) 3567c478bd9Sstevel@tonic-gate return (-2); 3577c478bd9Sstevel@tonic-gate if (buff == NULL || buff_len < 0) 3587c478bd9Sstevel@tonic-gate return (-1); 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate memset(key, 0, sizeof(key)); 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate if (!dst_s_verify_str(&p, "Key: ")) 3637c478bd9Sstevel@tonic-gate return (-3); 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate eol = strchr(p, '\n'); 3667c478bd9Sstevel@tonic-gate if (eol == NULL) 3677c478bd9Sstevel@tonic-gate return (-4); 3687c478bd9Sstevel@tonic-gate len = eol - p; 3697c478bd9Sstevel@tonic-gate tmp = malloc(len + 2); 370*9525b14bSRao Shoaib if (tmp == NULL) 371*9525b14bSRao Shoaib return (-5); 3727c478bd9Sstevel@tonic-gate memcpy(tmp, p, len); 3737c478bd9Sstevel@tonic-gate *(tmp + len) = 0x0; 374*9525b14bSRao Shoaib key_len = b64_pton((char *)tmp, key, HMAC_LEN+1); /*%< see above */ 3757c478bd9Sstevel@tonic-gate SAFE_FREE2(tmp, len + 2); 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate if (dst_buffer_to_hmac_md5(dkey, key, key_len) < 0) { 3787c478bd9Sstevel@tonic-gate return (-6); 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate return (0); 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate 383*9525b14bSRao Shoaib /*% 3847c478bd9Sstevel@tonic-gate * dst_hmac_md5_to_dns_key() 3857c478bd9Sstevel@tonic-gate * function to extract hmac key from DST_KEY structure 3867c478bd9Sstevel@tonic-gate * intput: 3877c478bd9Sstevel@tonic-gate * in_key: HMAC-MD5 key 3887c478bd9Sstevel@tonic-gate * output: 3897c478bd9Sstevel@tonic-gate * out_str: buffer to write ot 3907c478bd9Sstevel@tonic-gate * out_len: size of output buffer 3917c478bd9Sstevel@tonic-gate * returns: 3927c478bd9Sstevel@tonic-gate * number of bytes written to output buffer 3937c478bd9Sstevel@tonic-gate */ 3947c478bd9Sstevel@tonic-gate static int 3957c478bd9Sstevel@tonic-gate dst_hmac_md5_to_dns_key(const DST_KEY *in_key, u_char *out_str, 3967c478bd9Sstevel@tonic-gate const int out_len) 3977c478bd9Sstevel@tonic-gate { 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate HMAC_Key *hkey; 4007c478bd9Sstevel@tonic-gate int i; 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate if (in_key == NULL || in_key->dk_KEY_struct == NULL || 4037c478bd9Sstevel@tonic-gate out_len <= in_key->dk_key_size || out_str == NULL) 4047c478bd9Sstevel@tonic-gate return (-1); 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate hkey = (HMAC_Key *) in_key->dk_KEY_struct; 4077c478bd9Sstevel@tonic-gate for (i = 0; i < in_key->dk_key_size; i++) 4087c478bd9Sstevel@tonic-gate out_str[i] = hkey->hk_ipad[i] ^ HMAC_IPAD; 4097c478bd9Sstevel@tonic-gate return (i); 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate /************************************************************************** 4137c478bd9Sstevel@tonic-gate * dst_hmac_md5_compare_keys 4147c478bd9Sstevel@tonic-gate * Compare two keys for equality. 4157c478bd9Sstevel@tonic-gate * Return 4167c478bd9Sstevel@tonic-gate * 0 The keys are equal 4177c478bd9Sstevel@tonic-gate * NON-ZERO The keys are not equal 4187c478bd9Sstevel@tonic-gate */ 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate static int 4217c478bd9Sstevel@tonic-gate dst_hmac_md5_compare_keys(const DST_KEY *key1, const DST_KEY *key2) 4227c478bd9Sstevel@tonic-gate { 4237c478bd9Sstevel@tonic-gate HMAC_Key *hkey1 = (HMAC_Key *) key1->dk_KEY_struct; 4247c478bd9Sstevel@tonic-gate HMAC_Key *hkey2 = (HMAC_Key *) key2->dk_KEY_struct; 4257c478bd9Sstevel@tonic-gate return memcmp(hkey1->hk_ipad, hkey2->hk_ipad, HMAC_LEN); 4267c478bd9Sstevel@tonic-gate } 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate /************************************************************************** 4297c478bd9Sstevel@tonic-gate * dst_hmac_md5_free_key_structure 4307c478bd9Sstevel@tonic-gate * Frees all (none) dynamically allocated structures in hkey 4317c478bd9Sstevel@tonic-gate */ 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate static void * 4347c478bd9Sstevel@tonic-gate dst_hmac_md5_free_key_structure(void *key) 4357c478bd9Sstevel@tonic-gate { 4367c478bd9Sstevel@tonic-gate HMAC_Key *hkey = key; 4377c478bd9Sstevel@tonic-gate SAFE_FREE(hkey); 4387c478bd9Sstevel@tonic-gate return (NULL); 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate /*************************************************************************** 4437c478bd9Sstevel@tonic-gate * dst_hmac_md5_generate_key 4447c478bd9Sstevel@tonic-gate * Creates a HMAC key of size size with a maximum size of 63 bytes 4457c478bd9Sstevel@tonic-gate * generating a HMAC key larger than 63 bytes makes no sense as that key 4467c478bd9Sstevel@tonic-gate * is digested before use. 4477c478bd9Sstevel@tonic-gate */ 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate static int 4507c478bd9Sstevel@tonic-gate dst_hmac_md5_generate_key(DST_KEY *key, const int nothing) 4517c478bd9Sstevel@tonic-gate { 452*9525b14bSRao Shoaib (void)key; 453*9525b14bSRao Shoaib (void)nothing; 4547c478bd9Sstevel@tonic-gate return (-1); 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate 457*9525b14bSRao Shoaib /*% 4587c478bd9Sstevel@tonic-gate * dst_hmac_md5_init() Function to answer set up function pointers for HMAC 4597c478bd9Sstevel@tonic-gate * related functions 4607c478bd9Sstevel@tonic-gate */ 4617c478bd9Sstevel@tonic-gate int 4627c478bd9Sstevel@tonic-gate dst_hmac_md5_init() 4637c478bd9Sstevel@tonic-gate { 4647c478bd9Sstevel@tonic-gate if (dst_t_func[KEY_HMAC_MD5] != NULL) 4657c478bd9Sstevel@tonic-gate return (1); 4667c478bd9Sstevel@tonic-gate dst_t_func[KEY_HMAC_MD5] = malloc(sizeof(struct dst_func)); 4677c478bd9Sstevel@tonic-gate if (dst_t_func[KEY_HMAC_MD5] == NULL) 4687c478bd9Sstevel@tonic-gate return (0); 4697c478bd9Sstevel@tonic-gate memset(dst_t_func[KEY_HMAC_MD5], 0, sizeof(struct dst_func)); 4707c478bd9Sstevel@tonic-gate dst_t_func[KEY_HMAC_MD5]->sign = dst_hmac_md5_sign; 4717c478bd9Sstevel@tonic-gate dst_t_func[KEY_HMAC_MD5]->verify = dst_hmac_md5_verify; 4727c478bd9Sstevel@tonic-gate dst_t_func[KEY_HMAC_MD5]->compare = dst_hmac_md5_compare_keys; 4737c478bd9Sstevel@tonic-gate dst_t_func[KEY_HMAC_MD5]->generate = dst_hmac_md5_generate_key; 4747c478bd9Sstevel@tonic-gate dst_t_func[KEY_HMAC_MD5]->destroy = dst_hmac_md5_free_key_structure; 4757c478bd9Sstevel@tonic-gate dst_t_func[KEY_HMAC_MD5]->to_dns_key = dst_hmac_md5_to_dns_key; 4767c478bd9Sstevel@tonic-gate dst_t_func[KEY_HMAC_MD5]->from_dns_key = dst_buffer_to_hmac_md5; 4777c478bd9Sstevel@tonic-gate dst_t_func[KEY_HMAC_MD5]->to_file_fmt = dst_hmac_md5_key_to_file_format; 4787c478bd9Sstevel@tonic-gate dst_t_func[KEY_HMAC_MD5]->from_file_fmt = dst_hmac_md5_key_from_file_format; 4797c478bd9Sstevel@tonic-gate return (1); 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate #else 483*9525b14bSRao Shoaib #define dst_hmac_md5_init __dst_hmac_md5_init 484*9525b14bSRao Shoaib 4857c478bd9Sstevel@tonic-gate int 4867c478bd9Sstevel@tonic-gate dst_hmac_md5_init(){ 4877c478bd9Sstevel@tonic-gate return (0); 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate #endif 4907c478bd9Sstevel@tonic-gate 491*9525b14bSRao Shoaib /*! \file */ 492