hmacmd5.c revision 170222
1/* 2 * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 2000, 2001 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: hmacmd5.c,v 1.7.18.5 2006/02/26 22:30:56 marka Exp $ */ 19 20/*! \file 21 * This code implements the HMAC-MD5 keyed hash algorithm 22 * described in RFC2104. 23 */ 24 25#include "config.h" 26 27#include <isc/assertions.h> 28#include <isc/hmacmd5.h> 29#include <isc/md5.h> 30#include <isc/string.h> 31#include <isc/types.h> 32#include <isc/util.h> 33 34#define PADLEN 64 35#define IPAD 0x36 36#define OPAD 0x5C 37 38/*! 39 * Start HMAC-MD5 process. Initialize an md5 context and digest the key. 40 */ 41void 42isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key, 43 unsigned int len) 44{ 45 unsigned char ipad[PADLEN]; 46 int i; 47 48 memset(ctx->key, 0, sizeof(ctx->key)); 49 if (len > sizeof(ctx->key)) { 50 isc_md5_t md5ctx; 51 isc_md5_init(&md5ctx); 52 isc_md5_update(&md5ctx, key, len); 53 isc_md5_final(&md5ctx, ctx->key); 54 } else 55 memcpy(ctx->key, key, len); 56 57 isc_md5_init(&ctx->md5ctx); 58 memset(ipad, IPAD, sizeof(ipad)); 59 for (i = 0; i < PADLEN; i++) 60 ipad[i] ^= ctx->key[i]; 61 isc_md5_update(&ctx->md5ctx, ipad, sizeof(ipad)); 62} 63 64void 65isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) { 66 isc_md5_invalidate(&ctx->md5ctx); 67 memset(ctx->key, 0, sizeof(ctx->key)); 68} 69 70/*! 71 * Update context to reflect the concatenation of another buffer full 72 * of bytes. 73 */ 74void 75isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf, 76 unsigned int len) 77{ 78 isc_md5_update(&ctx->md5ctx, buf, len); 79} 80 81/*! 82 * Compute signature - finalize MD5 operation and reapply MD5. 83 */ 84void 85isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) { 86 unsigned char opad[PADLEN]; 87 int i; 88 89 isc_md5_final(&ctx->md5ctx, digest); 90 91 memset(opad, OPAD, sizeof(opad)); 92 for (i = 0; i < PADLEN; i++) 93 opad[i] ^= ctx->key[i]; 94 95 isc_md5_init(&ctx->md5ctx); 96 isc_md5_update(&ctx->md5ctx, opad, sizeof(opad)); 97 isc_md5_update(&ctx->md5ctx, digest, ISC_MD5_DIGESTLENGTH); 98 isc_md5_final(&ctx->md5ctx, digest); 99 isc_hmacmd5_invalidate(ctx); 100} 101 102/*! 103 * Verify signature - finalize MD5 operation and reapply MD5, then 104 * compare to the supplied digest. 105 */ 106isc_boolean_t 107isc_hmacmd5_verify(isc_hmacmd5_t *ctx, unsigned char *digest) { 108 return (isc_hmacmd5_verify2(ctx, digest, ISC_MD5_DIGESTLENGTH)); 109} 110 111isc_boolean_t 112isc_hmacmd5_verify2(isc_hmacmd5_t *ctx, unsigned char *digest, size_t len) { 113 unsigned char newdigest[ISC_MD5_DIGESTLENGTH]; 114 115 REQUIRE(len <= ISC_MD5_DIGESTLENGTH); 116 isc_hmacmd5_sign(ctx, newdigest); 117 return (ISC_TF(memcmp(digest, newdigest, len) == 0)); 118} 119