1258945Sroberto/* 2280849Scy * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") 3258945Sroberto * Copyright (C) 2000, 2001 Internet Software Consortium. 4258945Sroberto * 5258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any 6258945Sroberto * purpose with or without fee is hereby granted, provided that the above 7258945Sroberto * copyright notice and this permission notice appear in all copies. 8258945Sroberto * 9258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11258945Sroberto * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15258945Sroberto * PERFORMANCE OF THIS SOFTWARE. 16258945Sroberto */ 17258945Sroberto 18280849Scy/* $Id: hmacmd5.c,v 1.16 2009/02/06 23:47:42 tbox Exp $ */ 19258945Sroberto 20258945Sroberto/*! \file 21258945Sroberto * This code implements the HMAC-MD5 keyed hash algorithm 22258945Sroberto * described in RFC2104. 23258945Sroberto */ 24258945Sroberto 25258945Sroberto#include "config.h" 26258945Sroberto 27258945Sroberto#include <isc/assertions.h> 28258945Sroberto#include <isc/hmacmd5.h> 29258945Sroberto#include <isc/md5.h> 30280849Scy#include <isc/platform.h> 31258945Sroberto#include <isc/string.h> 32258945Sroberto#include <isc/types.h> 33258945Sroberto#include <isc/util.h> 34258945Sroberto 35280849Scy#ifdef ISC_PLATFORM_OPENSSLHASH 36280849Scy 37280849Scyvoid 38280849Scyisc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key, 39280849Scy unsigned int len) 40280849Scy{ 41280849Scy HMAC_Init(ctx, (const void *) key, (int) len, EVP_md5()); 42280849Scy} 43280849Scy 44280849Scyvoid 45280849Scyisc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) { 46280849Scy HMAC_CTX_cleanup(ctx); 47280849Scy} 48280849Scy 49280849Scyvoid 50280849Scyisc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf, 51280849Scy unsigned int len) 52280849Scy{ 53280849Scy HMAC_Update(ctx, buf, (int) len); 54280849Scy} 55280849Scy 56280849Scyvoid 57280849Scyisc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) { 58280849Scy HMAC_Final(ctx, digest, NULL); 59280849Scy HMAC_CTX_cleanup(ctx); 60280849Scy} 61280849Scy 62280849Scy#else 63280849Scy 64258945Sroberto#define PADLEN 64 65258945Sroberto#define IPAD 0x36 66258945Sroberto#define OPAD 0x5C 67258945Sroberto 68258945Sroberto/*! 69258945Sroberto * Start HMAC-MD5 process. Initialize an md5 context and digest the key. 70258945Sroberto */ 71258945Srobertovoid 72258945Srobertoisc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key, 73258945Sroberto unsigned int len) 74258945Sroberto{ 75258945Sroberto unsigned char ipad[PADLEN]; 76258945Sroberto int i; 77258945Sroberto 78258945Sroberto memset(ctx->key, 0, sizeof(ctx->key)); 79258945Sroberto if (len > sizeof(ctx->key)) { 80258945Sroberto isc_md5_t md5ctx; 81258945Sroberto isc_md5_init(&md5ctx); 82258945Sroberto isc_md5_update(&md5ctx, key, len); 83258945Sroberto isc_md5_final(&md5ctx, ctx->key); 84258945Sroberto } else 85258945Sroberto memcpy(ctx->key, key, len); 86258945Sroberto 87258945Sroberto isc_md5_init(&ctx->md5ctx); 88258945Sroberto memset(ipad, IPAD, sizeof(ipad)); 89258945Sroberto for (i = 0; i < PADLEN; i++) 90258945Sroberto ipad[i] ^= ctx->key[i]; 91258945Sroberto isc_md5_update(&ctx->md5ctx, ipad, sizeof(ipad)); 92258945Sroberto} 93258945Sroberto 94258945Srobertovoid 95258945Srobertoisc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) { 96258945Sroberto isc_md5_invalidate(&ctx->md5ctx); 97258945Sroberto memset(ctx->key, 0, sizeof(ctx->key)); 98258945Sroberto} 99258945Sroberto 100258945Sroberto/*! 101258945Sroberto * Update context to reflect the concatenation of another buffer full 102258945Sroberto * of bytes. 103258945Sroberto */ 104258945Srobertovoid 105258945Srobertoisc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf, 106258945Sroberto unsigned int len) 107258945Sroberto{ 108258945Sroberto isc_md5_update(&ctx->md5ctx, buf, len); 109258945Sroberto} 110258945Sroberto 111258945Sroberto/*! 112258945Sroberto * Compute signature - finalize MD5 operation and reapply MD5. 113258945Sroberto */ 114258945Srobertovoid 115258945Srobertoisc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) { 116258945Sroberto unsigned char opad[PADLEN]; 117258945Sroberto int i; 118258945Sroberto 119258945Sroberto isc_md5_final(&ctx->md5ctx, digest); 120258945Sroberto 121258945Sroberto memset(opad, OPAD, sizeof(opad)); 122258945Sroberto for (i = 0; i < PADLEN; i++) 123258945Sroberto opad[i] ^= ctx->key[i]; 124258945Sroberto 125258945Sroberto isc_md5_init(&ctx->md5ctx); 126258945Sroberto isc_md5_update(&ctx->md5ctx, opad, sizeof(opad)); 127258945Sroberto isc_md5_update(&ctx->md5ctx, digest, ISC_MD5_DIGESTLENGTH); 128258945Sroberto isc_md5_final(&ctx->md5ctx, digest); 129258945Sroberto isc_hmacmd5_invalidate(ctx); 130258945Sroberto} 131280849Scy#endif /* !ISC_PLATFORM_OPENSSLHASH */ 132258945Sroberto 133258945Sroberto/*! 134258945Sroberto * Verify signature - finalize MD5 operation and reapply MD5, then 135258945Sroberto * compare to the supplied digest. 136258945Sroberto */ 137258945Srobertoisc_boolean_t 138258945Srobertoisc_hmacmd5_verify(isc_hmacmd5_t *ctx, unsigned char *digest) { 139258945Sroberto return (isc_hmacmd5_verify2(ctx, digest, ISC_MD5_DIGESTLENGTH)); 140258945Sroberto} 141258945Sroberto 142258945Srobertoisc_boolean_t 143258945Srobertoisc_hmacmd5_verify2(isc_hmacmd5_t *ctx, unsigned char *digest, size_t len) { 144258945Sroberto unsigned char newdigest[ISC_MD5_DIGESTLENGTH]; 145258945Sroberto 146258945Sroberto REQUIRE(len <= ISC_MD5_DIGESTLENGTH); 147258945Sroberto isc_hmacmd5_sign(ctx, newdigest); 148298699Sdelphij return (ISC_TF(isc_tsmemcmp(digest, newdigest, len) == 0)); 149258945Sroberto} 150