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