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

1.1     ! misho       1: #ifdef HMAC_MD5
        !             2: #ifndef LINT
        !             3: static const char rcsid[] = "$Header: /proj/cvs/prod/DHCP/dst/hmac_link.c,v 1.3 2007-12-06 00:50:22 dhankins Exp $";
        !             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>