Annotation of embedaddon/dhcp/dst/hmac_link.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>