hmacmd5.c revision 298699
1/* 2 * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 2000, 2001 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or 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.16 2009/02/06 23:47:42 tbox 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/platform.h> 31#include <isc/string.h> 32#include <isc/types.h> 33#include <isc/util.h> 34 35#ifdef ISC_PLATFORM_OPENSSLHASH 36 37void 38isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key, 39 unsigned int len) 40{ 41 HMAC_Init(ctx, (const void *) key, (int) len, EVP_md5()); 42} 43 44void 45isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) { 46 HMAC_CTX_cleanup(ctx); 47} 48 49void 50isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf, 51 unsigned int len) 52{ 53 HMAC_Update(ctx, buf, (int) len); 54} 55 56void 57isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) { 58 HMAC_Final(ctx, digest, NULL); 59 HMAC_CTX_cleanup(ctx); 60} 61 62#else 63 64#define PADLEN 64 65#define IPAD 0x36 66#define OPAD 0x5C 67 68/*! 69 * Start HMAC-MD5 process. Initialize an md5 context and digest the key. 70 */ 71void 72isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key, 73 unsigned int len) 74{ 75 unsigned char ipad[PADLEN]; 76 int i; 77 78 memset(ctx->key, 0, sizeof(ctx->key)); 79 if (len > sizeof(ctx->key)) { 80 isc_md5_t md5ctx; 81 isc_md5_init(&md5ctx); 82 isc_md5_update(&md5ctx, key, len); 83 isc_md5_final(&md5ctx, ctx->key); 84 } else 85 memcpy(ctx->key, key, len); 86 87 isc_md5_init(&ctx->md5ctx); 88 memset(ipad, IPAD, sizeof(ipad)); 89 for (i = 0; i < PADLEN; i++) 90 ipad[i] ^= ctx->key[i]; 91 isc_md5_update(&ctx->md5ctx, ipad, sizeof(ipad)); 92} 93 94void 95isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) { 96 isc_md5_invalidate(&ctx->md5ctx); 97 memset(ctx->key, 0, sizeof(ctx->key)); 98} 99 100/*! 101 * Update context to reflect the concatenation of another buffer full 102 * of bytes. 103 */ 104void 105isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf, 106 unsigned int len) 107{ 108 isc_md5_update(&ctx->md5ctx, buf, len); 109} 110 111/*! 112 * Compute signature - finalize MD5 operation and reapply MD5. 113 */ 114void 115isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) { 116 unsigned char opad[PADLEN]; 117 int i; 118 119 isc_md5_final(&ctx->md5ctx, digest); 120 121 memset(opad, OPAD, sizeof(opad)); 122 for (i = 0; i < PADLEN; i++) 123 opad[i] ^= ctx->key[i]; 124 125 isc_md5_init(&ctx->md5ctx); 126 isc_md5_update(&ctx->md5ctx, opad, sizeof(opad)); 127 isc_md5_update(&ctx->md5ctx, digest, ISC_MD5_DIGESTLENGTH); 128 isc_md5_final(&ctx->md5ctx, digest); 129 isc_hmacmd5_invalidate(ctx); 130} 131#endif /* !ISC_PLATFORM_OPENSSLHASH */ 132 133/*! 134 * Verify signature - finalize MD5 operation and reapply MD5, then 135 * compare to the supplied digest. 136 */ 137isc_boolean_t 138isc_hmacmd5_verify(isc_hmacmd5_t *ctx, unsigned char *digest) { 139 return (isc_hmacmd5_verify2(ctx, digest, ISC_MD5_DIGESTLENGTH)); 140} 141 142isc_boolean_t 143isc_hmacmd5_verify2(isc_hmacmd5_t *ctx, unsigned char *digest, size_t len) { 144 unsigned char newdigest[ISC_MD5_DIGESTLENGTH]; 145 146 REQUIRE(len <= ISC_MD5_DIGESTLENGTH); 147 isc_hmacmd5_sign(ctx, newdigest); 148 return (ISC_TF(isc_tsmemcmp(digest, newdigest, len) == 0)); 149} 150