Print this page


   1 /*
   2  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
   3  * Use is subject to license terms.
   4  */
   5 
   6 #pragma ident   "%Z%%M% %I%     %E% SMI"
   7 
   8 #ifdef HMAC_MD5
   9 #ifndef LINT
  10 static const char rcsid[] = "$Header: /proj/cvs/isc/bind8/src/lib/dst/hmac_link.c,v 1.9 2001/05/29 05:48:10 marka Exp $";
  11 #endif
  12 /*
  13  * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
  14  *
  15  * Permission to use, copy modify, and distribute this software for any
  16  * purpose with or without fee is hereby granted, provided that the above
  17  * copyright notice and this permission notice appear in all copies.
  18  *
  19  * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
  20  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
  21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL
  22  * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
  23  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
  24  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  25  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  26  * WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
  27  */
  28 
  29 /* 
  30  * This file contains an implementation of the HMAC-MD5 algorithm.
  31  */
  32 #include "port_before.h"
  33 
  34 #include <stdio.h>
  35 #include <unistd.h>
  36 #include <stdlib.h>
  37 #include <string.h>
  38 #include <memory.h>
  39 #include <sys/param.h>
  40 #include <sys/time.h>
  41 #include <netinet/in.h>
  42 #include <arpa/nameser.h>
  43 #include <resolv.h>
  44 
  45 #include "dst_internal.h"

  46 #ifdef USE_MD5
  47 #ifndef SUNW_LIBMD5
  48 # include "md5.h"
  49 #else
  50 #include <sys/md5.h>
  51 #endif


  52 # ifndef _MD5_H_
  53 #  define _MD5_H_ 1     /* make sure we do not include rsaref md5.h file */
  54 # endif
  55 #endif
  56 
  57 #include "port_after.h"
  58 
  59 
  60 #define HMAC_LEN        64
  61 #define HMAC_IPAD       0x36
  62 #define HMAC_OPAD       0x5c
  63 #define MD5_LEN         16
  64 
  65 
  66 typedef struct hmackey {
  67         u_char hk_ipad[64], hk_opad[64];
  68 } HMAC_Key;
  69 
  70 
  71 /************************************************************************** 
  72  * dst_hmac_md5_sign
  73  *     Call HMAC signing functions to sign a block of data.


  80  *     context   the context to be used in this digest
  81  *     data     data to be signed.
  82  *     len       length in bytes of data.
  83  *     signature   location to store signature.
  84  *     sig_len     size of the signature location
  85  * returns 
  86  *      N  Success on SIG_MODE_FINAL = returns signature length in bytes
  87  *      0  Success on SIG_MODE_INIT  and UPDATE
  88  *       <0  Failure
  89  */
  90 
  91 static int
  92 dst_hmac_md5_sign(const int mode, DST_KEY *d_key, void **context, 
  93                   const u_char *data, const int len, 
  94                   u_char *signature, const int sig_len)
  95 {
  96         HMAC_Key *key;
  97         int sign_len = 0;
  98         MD5_CTX *ctx = NULL;
  99 



 100         if (mode & SIG_MODE_INIT) 
 101                 ctx = (MD5_CTX *) malloc(sizeof(*ctx));
 102         else if (context)
 103                 ctx = (MD5_CTX *) *context;
 104         if (ctx == NULL) 
 105                 return (-1);
 106 
 107         if (d_key == NULL || d_key->dk_KEY_struct == NULL)
 108                 return (-1);
 109         key = (HMAC_Key *) d_key->dk_KEY_struct;
 110 
 111         if (mode & SIG_MODE_INIT) {
 112                 MD5Init(ctx);
 113                 MD5Update(ctx, key->hk_ipad, HMAC_LEN);
 114         }
 115 
 116         if ((mode & SIG_MODE_UPDATE) && (data && len > 0))
 117                 MD5Update(ctx, data, len);
 118 
 119         if (mode & SIG_MODE_FINAL) {
 120                 if (signature == NULL || sig_len < MD5_LEN)
 121                         return (SIGN_FINAL_FAILURE);
 122                 MD5Final(signature, ctx);
 123 
 124                 /* perform outer MD5 */
 125                 MD5Init(ctx);
 126                 MD5Update(ctx, key->hk_opad, HMAC_LEN);
 127                 MD5Update(ctx, signature, MD5_LEN);
 128                 MD5Final(signature, ctx);


 147  * Parameters
 148  *     mode     SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
 149  *     dkey     key to use for verify.
 150  *     data     data signed.
 151  *     len       length in bytes of data.
 152  *     signature   signature.
 153  *     sig_len     length in bytes of signature.
 154  * returns 
 155  *     0  Success 
 156  *    <0  Failure
 157  */
 158 
 159 static int
 160 dst_hmac_md5_verify(const int mode, DST_KEY *d_key, void **context,
 161                 const u_char *data, const int len,
 162                 const u_char *signature, const int sig_len)
 163 {
 164         HMAC_Key *key;
 165         MD5_CTX *ctx = NULL;
 166 



 167         if (mode & SIG_MODE_INIT) 
 168                 ctx = (MD5_CTX *) malloc(sizeof(*ctx));
 169         else if (context)
 170                 ctx = (MD5_CTX *) *context;
 171         if (ctx == NULL) 
 172                 return (-1);
 173 
 174         if (d_key == NULL || d_key->dk_KEY_struct == NULL)
 175                 return (-1);
 176 
 177         key = (HMAC_Key *) d_key->dk_KEY_struct;
 178         if (mode & SIG_MODE_INIT) {
 179                 MD5Init(ctx);
 180                 MD5Update(ctx, key->hk_ipad, HMAC_LEN);
 181         }
 182         if ((mode & SIG_MODE_UPDATE) && (data && len > 0))
 183                 MD5Update(ctx, data, len);
 184 
 185         if (mode & SIG_MODE_FINAL) {
 186                 u_char digest[MD5_LEN];
 187                 if (signature == NULL || key == NULL || sig_len != MD5_LEN)
 188                         return (VERIFY_FINAL_FAILURE);
 189                 MD5Final(digest, ctx);
 190 
 191                 /* perform outer MD5 */
 192                 MD5Init(ctx);
 193                 MD5Update(ctx, key->hk_opad, HMAC_LEN);
 194                 MD5Update(ctx, digest, MD5_LEN);
 195                 MD5Final(digest, ctx);
 196 


 209 
 210 /************************************************************************** 
 211  * dst_buffer_to_hmac_md5
 212  *     Converts key from raw data to an HMAC Key
 213  *     This function gets in a pointer to the data
 214  * Parameters
 215  *     hkey     the HMAC key to be filled in
 216  *     key      the key in raw format
 217  *     keylen   the length of the key
 218  * Return
 219  *      0       Success
 220  *      <0   Failure
 221  */
 222 static int
 223 dst_buffer_to_hmac_md5(DST_KEY *dkey, const u_char *key, const int keylen)
 224 {
 225         int i;
 226         HMAC_Key *hkey = NULL;
 227         MD5_CTX ctx;
 228         int local_keylen = keylen;

 229 
 230         if (dkey == NULL || key == NULL || keylen < 0)
 231                 return (-1);
 232 
 233         if ((hkey = (HMAC_Key *) malloc(sizeof(HMAC_Key))) == NULL)
 234                   return (-2);
 235 
 236         memset(hkey->hk_ipad, 0, sizeof(hkey->hk_ipad));
 237         memset(hkey->hk_opad, 0, sizeof(hkey->hk_opad));
 238 
 239         /* if key is longer than HMAC_LEN bytes reset it to key=MD5(key) */
 240         if (keylen > HMAC_LEN) {
 241                 u_char tk[MD5_LEN];
 242                 MD5Init(&ctx);
 243                 MD5Update(&ctx, key, keylen);
 244                 MD5Final(tk, &ctx);
 245                 memset((void *) &ctx, 0, sizeof(ctx));
 246                 key = tk;
 247                 local_keylen = MD5_LEN;
 248         }
 249         /* start out by storing key in pads */
 250         memcpy(hkey->hk_ipad, key, local_keylen);
 251         memcpy(hkey->hk_opad, key, local_keylen);
 252 
 253         /* XOR key with hk_ipad and opad values */
 254         for (i = 0; i < HMAC_LEN; i++) {
 255                 hkey->hk_ipad[i] ^= HMAC_IPAD;
 256                 hkey->hk_opad[i] ^= HMAC_OPAD;
 257         }
 258         dkey->dk_key_size = local_keylen;
 259         dkey->dk_KEY_struct = (void *) hkey;
 260         return (1);
 261 }
 262 
 263 
 264 /************************************************************************** 
 265  *  dst_hmac_md5_key_to_file_format
 266  *      Encodes an HMAC Key into the portable file format.
 267  *  Parameters 
 268  *      hkey      HMAC KEY structure 
 269  *      buff      output buffer
 270  *      buff_len  size of output buffer 
 271  *  Return
 272  *      0  Failure - null input hkey
 273  *     -1  Failure - not enough space in output area
 274  *      N  Success - Length of data returned in buff
 275  */
 276 
 277 static int
 278 dst_hmac_md5_key_to_file_format(const DST_KEY *dkey, char *buff,
 279                             const int buff_len)
 280 {
 281         char *bp;
 282         int len, b_len, i, key_len;
 283         u_char key[HMAC_LEN];
 284         HMAC_Key *hkey;
 285 
 286         if (dkey == NULL || dkey->dk_KEY_struct == NULL) 
 287                 return (0);
 288         if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str))
 289                 return (-1);    /* no OR not enough space in output area */
 290 




 291         hkey = (HMAC_Key *) dkey->dk_KEY_struct;
 292         memset(buff, 0, buff_len);      /* just in case */
 293         /* write file header */
 294         sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_HMAC_MD5, "HMAC");
 295 
 296         bp = (char *) strchr(buff, '\0');
 297         b_len = buff_len - (bp - buff);
 298 
 299         memset(key, 0, HMAC_LEN);
 300         for (i = 0; i < HMAC_LEN; i++)
 301                 key[i] = hkey->hk_ipad[i] ^ HMAC_IPAD;
 302         for (i = HMAC_LEN - 1; i >= 0; i--)
 303                 if (key[i] != 0)
 304                         break;
 305         key_len = i + 1;
 306 


 307         strcat(bp, "Key: ");
 308         bp += strlen("Key: ");
 309         b_len = buff_len - (bp - buff);
 310 
 311         len = b64_ntop(key, key_len, bp, b_len);
 312         if (len < 0) 
 313                 return (-1);
 314         bp += len;


 315         *(bp++) = '\n';
 316         *bp = '\0';
 317         b_len = buff_len - (bp - buff);
 318 
 319         return (buff_len - b_len);
 320 }
 321 
 322 
 323 /************************************************************************** 
 324  * dst_hmac_md5_key_from_file_format
 325  *     Converts contents of a key file into an HMAC key. 
 326  * Parameters 
 327  *     hkey    structure to put key into 
 328  *     buff       buffer containing the encoded key 
 329  *     buff_len   the length of the buffer
 330  * Return
 331  *     n >= 0 Foot print of the key converted 
 332  *     n <  0 Error in conversion 
 333  */
 334 
 335 static int
 336 dst_hmac_md5_key_from_file_format(DST_KEY *dkey, const char *buff,
 337                               const int buff_len)
 338 {
 339         const char *p = buff, *eol;


 342                                                          * this
 343                                                          */
 344         u_char *tmp;
 345         int key_len, len;
 346 
 347         if (dkey == NULL)
 348                 return (-2);
 349         if (buff == NULL || buff_len < 0)
 350                 return (-1);
 351 
 352         memset(key, 0, sizeof(key));
 353 
 354         if (!dst_s_verify_str(&p, "Key: "))
 355                 return (-3);
 356 
 357         eol = strchr(p, '\n');
 358         if (eol == NULL)
 359                 return (-4);
 360         len = eol - p;
 361         tmp = malloc(len + 2);


 362         memcpy(tmp, p, len);
 363         *(tmp + len) = 0x0;
 364         key_len = b64_pton((char *)tmp, key, HMAC_LEN+1);       /* see above */
 365         SAFE_FREE2(tmp, len + 2);
 366 
 367         if (dst_buffer_to_hmac_md5(dkey, key, key_len) < 0) {
 368                 return (-6);
 369         }
 370         return (0);
 371 }
 372 
 373 /*
 374  * dst_hmac_md5_to_dns_key() 
 375  *         function to extract hmac key from DST_KEY structure 
 376  * intput: 
 377  *      in_key:  HMAC-MD5 key 
 378  * output: 
 379  *      out_str: buffer to write ot
 380  *      out_len: size of output buffer 
 381  * returns:
 382  *      number of bytes written to output buffer 
 383  */
 384 static int
 385 dst_hmac_md5_to_dns_key(const DST_KEY *in_key, u_char *out_str,
 386                         const int out_len)
 387 {
 388 
 389         HMAC_Key *hkey;
 390         int i;
 391         
 392         if (in_key == NULL || in_key->dk_KEY_struct == NULL ||
 393             out_len <= in_key->dk_key_size || out_str == NULL)


 422 
 423 static void *
 424 dst_hmac_md5_free_key_structure(void *key)
 425 {
 426         HMAC_Key *hkey = key;
 427         SAFE_FREE(hkey);
 428         return (NULL);
 429 }
 430 
 431 
 432 /*************************************************************************** 
 433  * dst_hmac_md5_generate_key
 434  *     Creates a HMAC key of size size with a maximum size of 63 bytes
 435  *     generating a HMAC key larger than 63 bytes makes no sense as that key 
 436  *     is digested before use. 
 437  */
 438 
 439 static int
 440 dst_hmac_md5_generate_key(DST_KEY *key, const int nothing)
 441 {
 442         u_char *buff;
 443         int i, n, size;
 444 
 445         i = nothing;
 446 
 447         if (key == NULL || key->dk_alg != KEY_HMAC_MD5)
 448                 return (0);
 449         size = (key->dk_key_size + 7) / 8; /* convert to bytes */
 450         if (size <= 0)
 451                 return(0);
 452         
 453         i = size > 64 ? 64 : size;
 454         buff = malloc(i+8);
 455 
 456         n = dst_random(DST_RAND_SEMI, i, buff);
 457         n += dst_random(DST_RAND_KEY, i, buff);
 458         if (n <= i) {        /* failed getting anything */
 459                 SAFE_FREE2(buff, i);
 460                 return (-1);
 461         }
 462         n = dst_buffer_to_hmac_md5(key, buff, i);
 463         SAFE_FREE2(buff, i);
 464         if (n <= 0)
 465                 return (n);
 466         return (1);
 467 }
 468 
 469 /*
 470  * dst_hmac_md5_init()  Function to answer set up function pointers for HMAC
 471  *         related functions 
 472  */
 473 int
 474 #ifdef  ORIGINAL_ISC_CODE
 475 dst_hmac_md5_init()
 476 #else
 477 dst_md5_hmac_init()
 478 #endif
 479 {
 480         if (dst_t_func[KEY_HMAC_MD5] != NULL)
 481                 return (1);
 482         dst_t_func[KEY_HMAC_MD5] = malloc(sizeof(struct dst_func));
 483         if (dst_t_func[KEY_HMAC_MD5] == NULL)
 484                 return (0);
 485         memset(dst_t_func[KEY_HMAC_MD5], 0, sizeof(struct dst_func));
 486         dst_t_func[KEY_HMAC_MD5]->sign = dst_hmac_md5_sign;
 487         dst_t_func[KEY_HMAC_MD5]->verify = dst_hmac_md5_verify;
 488         dst_t_func[KEY_HMAC_MD5]->compare = dst_hmac_md5_compare_keys;
 489         dst_t_func[KEY_HMAC_MD5]->generate = dst_hmac_md5_generate_key;
 490         dst_t_func[KEY_HMAC_MD5]->destroy = dst_hmac_md5_free_key_structure;
 491         dst_t_func[KEY_HMAC_MD5]->to_dns_key = dst_hmac_md5_to_dns_key;
 492         dst_t_func[KEY_HMAC_MD5]->from_dns_key = dst_buffer_to_hmac_md5;
 493         dst_t_func[KEY_HMAC_MD5]->to_file_fmt = dst_hmac_md5_key_to_file_format;
 494         dst_t_func[KEY_HMAC_MD5]->from_file_fmt = dst_hmac_md5_key_from_file_format;
 495         return (1);
 496 }
 497 
 498 #else 


 499 int
 500 dst_hmac_md5_init(){
 501         return (0);
 502 }
 503 #endif
 504 
 505 
 506 
 507 
 508 
 509 
 510 
   1 /*
   2  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
   3  * Use is subject to license terms.
   4  */
   5 

   6 
   7 #ifdef HMAC_MD5
   8 #ifndef LINT
   9 static const char rcsid[] = "$Header: /proj/cvs/prod/libbind/dst/hmac_link.c,v 1.8 2007/09/24 17:18:25 each Exp $";
  10 #endif
  11 /*
  12  * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
  13  *
  14  * Permission to use, copy modify, and distribute this software for any
  15  * purpose with or without fee is hereby granted, provided that the above
  16  * copyright notice and this permission notice appear in all copies.
  17  *
  18  * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
  19  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
  20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL
  21  * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
  22  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
  23  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  24  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  25  * WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
  26  */
  27 
  28 /*%
  29  * This file contains an implementation of the HMAC-MD5 algorithm.
  30  */
  31 #include "port_before.h"
  32 
  33 #include <stdio.h>
  34 #include <unistd.h>
  35 #include <stdlib.h>
  36 #include <string.h>
  37 #include <memory.h>
  38 #include <sys/param.h>
  39 #include <sys/time.h>
  40 #include <netinet/in.h>
  41 #include <arpa/nameser.h>
  42 #include <resolv.h>
  43 
  44 #include "dst_internal.h"
  45 
  46 #ifdef USE_MD5
  47 # ifndef HAVE_MD5
  48 #  include "md5.h"
  49 # else
  50 #  ifdef SOLARIS2
  51 #   include <sys/md5.h>
  52 #  endif
  53 # endif
  54 # ifndef _MD5_H_
  55 #  define _MD5_H_ 1     /*%< make sure we do not include rsaref md5.h file */
  56 # endif
  57 #endif
  58 
  59 #include "port_after.h"
  60 
  61 
  62 #define HMAC_LEN        64
  63 #define HMAC_IPAD       0x36
  64 #define HMAC_OPAD       0x5c
  65 #define MD5_LEN         16
  66 
  67 
  68 typedef struct hmackey {
  69         u_char hk_ipad[64], hk_opad[64];
  70 } HMAC_Key;
  71 
  72 
  73 /************************************************************************** 
  74  * dst_hmac_md5_sign
  75  *     Call HMAC signing functions to sign a block of data.


  82  *     context   the context to be used in this digest
  83  *     data     data to be signed.
  84  *     len       length in bytes of data.
  85  *     signature   location to store signature.
  86  *     sig_len     size of the signature location
  87  * returns 
  88  *      N  Success on SIG_MODE_FINAL = returns signature length in bytes
  89  *      0  Success on SIG_MODE_INIT  and UPDATE
  90  *       <0  Failure
  91  */
  92 
  93 static int
  94 dst_hmac_md5_sign(const int mode, DST_KEY *d_key, void **context, 
  95                   const u_char *data, const int len, 
  96                   u_char *signature, const int sig_len)
  97 {
  98         HMAC_Key *key;
  99         int sign_len = 0;
 100         MD5_CTX *ctx = NULL;
 101 
 102         if (d_key == NULL || d_key->dk_KEY_struct == NULL)
 103                 return (-1);
 104 
 105         if (mode & SIG_MODE_INIT) 
 106                 ctx = (MD5_CTX *) malloc(sizeof(*ctx));
 107         else if (context)
 108                 ctx = (MD5_CTX *) *context;
 109         if (ctx == NULL) 
 110                 return (-1);
 111 


 112         key = (HMAC_Key *) d_key->dk_KEY_struct;
 113 
 114         if (mode & SIG_MODE_INIT) {
 115                 MD5Init(ctx);
 116                 MD5Update(ctx, key->hk_ipad, HMAC_LEN);
 117         }
 118 
 119         if ((mode & SIG_MODE_UPDATE) && (data && len > 0))
 120                 MD5Update(ctx, data, len);
 121 
 122         if (mode & SIG_MODE_FINAL) {
 123                 if (signature == NULL || sig_len < MD5_LEN)
 124                         return (SIGN_FINAL_FAILURE);
 125                 MD5Final(signature, ctx);
 126 
 127                 /* perform outer MD5 */
 128                 MD5Init(ctx);
 129                 MD5Update(ctx, key->hk_opad, HMAC_LEN);
 130                 MD5Update(ctx, signature, MD5_LEN);
 131                 MD5Final(signature, ctx);


 150  * Parameters
 151  *     mode     SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
 152  *     dkey     key to use for verify.
 153  *     data     data signed.
 154  *     len       length in bytes of data.
 155  *     signature   signature.
 156  *     sig_len     length in bytes of signature.
 157  * returns 
 158  *     0  Success 
 159  *    <0  Failure
 160  */
 161 
 162 static int
 163 dst_hmac_md5_verify(const int mode, DST_KEY *d_key, void **context,
 164                 const u_char *data, const int len,
 165                 const u_char *signature, const int sig_len)
 166 {
 167         HMAC_Key *key;
 168         MD5_CTX *ctx = NULL;
 169 
 170         if (d_key == NULL || d_key->dk_KEY_struct == NULL)
 171                 return (-1);
 172 
 173         if (mode & SIG_MODE_INIT) 
 174                 ctx = (MD5_CTX *) malloc(sizeof(*ctx));
 175         else if (context)
 176                 ctx = (MD5_CTX *) *context;
 177         if (ctx == NULL) 
 178                 return (-1);
 179 



 180         key = (HMAC_Key *) d_key->dk_KEY_struct;
 181         if (mode & SIG_MODE_INIT) {
 182                 MD5Init(ctx);
 183                 MD5Update(ctx, key->hk_ipad, HMAC_LEN);
 184         }
 185         if ((mode & SIG_MODE_UPDATE) && (data && len > 0))
 186                 MD5Update(ctx, data, len);
 187 
 188         if (mode & SIG_MODE_FINAL) {
 189                 u_char digest[MD5_LEN];
 190                 if (signature == NULL || key == NULL || sig_len != MD5_LEN)
 191                         return (VERIFY_FINAL_FAILURE);
 192                 MD5Final(digest, ctx);
 193 
 194                 /* perform outer MD5 */
 195                 MD5Init(ctx);
 196                 MD5Update(ctx, key->hk_opad, HMAC_LEN);
 197                 MD5Update(ctx, digest, MD5_LEN);
 198                 MD5Final(digest, ctx);
 199 


 212 
 213 /************************************************************************** 
 214  * dst_buffer_to_hmac_md5
 215  *     Converts key from raw data to an HMAC Key
 216  *     This function gets in a pointer to the data
 217  * Parameters
 218  *     hkey     the HMAC key to be filled in
 219  *     key      the key in raw format
 220  *     keylen   the length of the key
 221  * Return
 222  *      0       Success
 223  *      <0   Failure
 224  */
 225 static int
 226 dst_buffer_to_hmac_md5(DST_KEY *dkey, const u_char *key, const int keylen)
 227 {
 228         int i;
 229         HMAC_Key *hkey = NULL;
 230         MD5_CTX ctx;
 231         int local_keylen = keylen;
 232         u_char tk[MD5_LEN];
 233 
 234         if (dkey == NULL || key == NULL || keylen < 0)
 235                 return (-1);
 236 
 237         if ((hkey = (HMAC_Key *) malloc(sizeof(HMAC_Key))) == NULL)
 238                   return (-2);
 239 
 240         memset(hkey->hk_ipad, 0, sizeof(hkey->hk_ipad));
 241         memset(hkey->hk_opad, 0, sizeof(hkey->hk_opad));
 242 
 243         /* if key is longer than HMAC_LEN bytes reset it to key=MD5(key) */
 244         if (keylen > HMAC_LEN) {

 245                 MD5Init(&ctx);
 246                 MD5Update(&ctx, key, keylen);
 247                 MD5Final(tk, &ctx);
 248                 memset((void *) &ctx, 0, sizeof(ctx));
 249                 key = tk;
 250                 local_keylen = MD5_LEN;
 251         }
 252         /* start out by storing key in pads */
 253         memcpy(hkey->hk_ipad, key, local_keylen);
 254         memcpy(hkey->hk_opad, key, local_keylen);
 255 
 256         /* XOR key with hk_ipad and opad values */
 257         for (i = 0; i < HMAC_LEN; i++) {
 258                 hkey->hk_ipad[i] ^= HMAC_IPAD;
 259                 hkey->hk_opad[i] ^= HMAC_OPAD;
 260         }
 261         dkey->dk_key_size = local_keylen;
 262         dkey->dk_KEY_struct = (void *) hkey;
 263         return (1);
 264 }
 265 
 266 
 267 /************************************************************************** 
 268  *  dst_hmac_md5_key_to_file_format
 269  *      Encodes an HMAC Key into the portable file format.
 270  *  Parameters 
 271  *      hkey      HMAC KEY structure 
 272  *      buff      output buffer
 273  *      buff_len  size of output buffer 
 274  *  Return
 275  *      0  Failure - null input hkey
 276  *     -1  Failure - not enough space in output area
 277  *      N  Success - Length of data returned in buff
 278  */
 279 
 280 static int
 281 dst_hmac_md5_key_to_file_format(const DST_KEY *dkey, char *buff,
 282                                 const int buff_len)
 283 {
 284         char *bp;
 285         int len, i, key_len;
 286         u_char key[HMAC_LEN];
 287         HMAC_Key *hkey;
 288 
 289         if (dkey == NULL || dkey->dk_KEY_struct == NULL) 
 290                 return (0);
 291         /*
 292          * Using snprintf() would be so much simpler here.
 293          */
 294         if (buff == NULL ||
 295             buff_len <= (int)(strlen(key_file_fmt_str) +
 296                               strlen(KEY_FILE_FORMAT) + 4))
 297                 return (-1);    /*%< no OR not enough space in output area */
 298         hkey = (HMAC_Key *) dkey->dk_KEY_struct;
 299         memset(buff, 0, buff_len);      /*%< just in case */
 300         /* write file header */
 301         sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_HMAC_MD5, "HMAC");
 302 
 303         bp = buff + strlen(buff);

 304 
 305         memset(key, 0, HMAC_LEN);
 306         for (i = 0; i < HMAC_LEN; i++)
 307                 key[i] = hkey->hk_ipad[i] ^ HMAC_IPAD;
 308         for (i = HMAC_LEN - 1; i >= 0; i--)
 309                 if (key[i] != 0)
 310                         break;
 311         key_len = i + 1;
 312 
 313         if (buff_len - (bp - buff) < 6)
 314                 return (-1);
 315         strcat(bp, "Key: ");
 316         bp += strlen("Key: ");

 317 
 318         len = b64_ntop(key, key_len, bp, buff_len - (bp - buff));
 319         if (len < 0) 
 320                 return (-1);
 321         bp += len;
 322         if (buff_len - (bp - buff) < 2)
 323                 return (-1);
 324         *(bp++) = '\n';
 325         *bp = '\0';

 326 
 327         return (bp - buff);
 328 }
 329 
 330 
 331 /************************************************************************** 
 332  * dst_hmac_md5_key_from_file_format
 333  *     Converts contents of a key file into an HMAC key. 
 334  * Parameters 
 335  *     hkey    structure to put key into 
 336  *     buff       buffer containing the encoded key 
 337  *     buff_len   the length of the buffer
 338  * Return
 339  *     n >= 0 Foot print of the key converted 
 340  *     n <  0 Error in conversion 
 341  */
 342 
 343 static int
 344 dst_hmac_md5_key_from_file_format(DST_KEY *dkey, const char *buff,
 345                               const int buff_len)
 346 {
 347         const char *p = buff, *eol;


 350                                  * this
 351                                  */
 352         u_char *tmp;
 353         int key_len, len;
 354 
 355         if (dkey == NULL)
 356                 return (-2);
 357         if (buff == NULL || buff_len < 0)
 358                 return (-1);
 359 
 360         memset(key, 0, sizeof(key));
 361 
 362         if (!dst_s_verify_str(&p, "Key: "))
 363                 return (-3);
 364 
 365         eol = strchr(p, '\n');
 366         if (eol == NULL)
 367                 return (-4);
 368         len = eol - p;
 369         tmp = malloc(len + 2);
 370         if (tmp == NULL)
 371                 return (-5);
 372         memcpy(tmp, p, len);
 373         *(tmp + len) = 0x0;
 374         key_len = b64_pton((char *)tmp, key, HMAC_LEN+1);       /*%< see above */
 375         SAFE_FREE2(tmp, len + 2);
 376 
 377         if (dst_buffer_to_hmac_md5(dkey, key, key_len) < 0) {
 378                 return (-6);
 379         }
 380         return (0);
 381 }
 382 
 383 /*%
 384  * dst_hmac_md5_to_dns_key() 
 385  *         function to extract hmac key from DST_KEY structure 
 386  * intput: 
 387  *      in_key:  HMAC-MD5 key 
 388  * output: 
 389  *      out_str: buffer to write ot
 390  *      out_len: size of output buffer 
 391  * returns:
 392  *      number of bytes written to output buffer 
 393  */
 394 static int
 395 dst_hmac_md5_to_dns_key(const DST_KEY *in_key, u_char *out_str,
 396                         const int out_len)
 397 {
 398 
 399         HMAC_Key *hkey;
 400         int i;
 401         
 402         if (in_key == NULL || in_key->dk_KEY_struct == NULL ||
 403             out_len <= in_key->dk_key_size || out_str == NULL)


 432 
 433 static void *
 434 dst_hmac_md5_free_key_structure(void *key)
 435 {
 436         HMAC_Key *hkey = key;
 437         SAFE_FREE(hkey);
 438         return (NULL);
 439 }
 440 
 441 
 442 /*************************************************************************** 
 443  * dst_hmac_md5_generate_key
 444  *     Creates a HMAC key of size size with a maximum size of 63 bytes
 445  *     generating a HMAC key larger than 63 bytes makes no sense as that key 
 446  *     is digested before use. 
 447  */
 448 
 449 static int
 450 dst_hmac_md5_generate_key(DST_KEY *key, const int nothing)
 451 {
 452         (void)key;
 453         (void)nothing;
















 454         return (-1);






 455 }
 456 
 457 /*%
 458  * dst_hmac_md5_init()  Function to answer set up function pointers for HMAC
 459  *         related functions 
 460  */
 461 int

 462 dst_hmac_md5_init()



 463 {
 464         if (dst_t_func[KEY_HMAC_MD5] != NULL)
 465                 return (1);
 466         dst_t_func[KEY_HMAC_MD5] = malloc(sizeof(struct dst_func));
 467         if (dst_t_func[KEY_HMAC_MD5] == NULL)
 468                 return (0);
 469         memset(dst_t_func[KEY_HMAC_MD5], 0, sizeof(struct dst_func));
 470         dst_t_func[KEY_HMAC_MD5]->sign = dst_hmac_md5_sign;
 471         dst_t_func[KEY_HMAC_MD5]->verify = dst_hmac_md5_verify;
 472         dst_t_func[KEY_HMAC_MD5]->compare = dst_hmac_md5_compare_keys;
 473         dst_t_func[KEY_HMAC_MD5]->generate = dst_hmac_md5_generate_key;
 474         dst_t_func[KEY_HMAC_MD5]->destroy = dst_hmac_md5_free_key_structure;
 475         dst_t_func[KEY_HMAC_MD5]->to_dns_key = dst_hmac_md5_to_dns_key;
 476         dst_t_func[KEY_HMAC_MD5]->from_dns_key = dst_buffer_to_hmac_md5;
 477         dst_t_func[KEY_HMAC_MD5]->to_file_fmt = dst_hmac_md5_key_to_file_format;
 478         dst_t_func[KEY_HMAC_MD5]->from_file_fmt = dst_hmac_md5_key_from_file_format;
 479         return (1);
 480 }
 481 
 482 #else 
 483 #define dst_hmac_md5_init       __dst_hmac_md5_init
 484 
 485 int
 486 dst_hmac_md5_init(){
 487         return (0);
 488 }
 489 #endif
 490 
 491 /*! \file */