1290001Sglebius/* 2290001Sglebius * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") 3290001Sglebius * Copyright (C) 2000, 2001 Internet Software Consortium. 4290001Sglebius * 5290001Sglebius * Permission to use, copy, modify, and/or distribute this software for any 6290001Sglebius * purpose with or without fee is hereby granted, provided that the above 7290001Sglebius * copyright notice and this permission notice appear in all copies. 8290001Sglebius * 9290001Sglebius * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10290001Sglebius * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11290001Sglebius * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12290001Sglebius * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13290001Sglebius * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14290001Sglebius * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15290001Sglebius * PERFORMANCE OF THIS SOFTWARE. 16290001Sglebius */ 17290001Sglebius 18290001Sglebius/* $Id: hmacmd5.c,v 1.16 2009/02/06 23:47:42 tbox Exp $ */ 19290001Sglebius 20290001Sglebius/*! \file 21290001Sglebius * This code implements the HMAC-MD5 keyed hash algorithm 22290001Sglebius * described in RFC2104. 23290001Sglebius */ 24290001Sglebius 25290001Sglebius#include "config.h" 26290001Sglebius 27290001Sglebius#include <isc/assertions.h> 28290001Sglebius#include <isc/hmacmd5.h> 29290001Sglebius#include <isc/md5.h> 30290001Sglebius#include <isc/platform.h> 31290001Sglebius#include <isc/string.h> 32290001Sglebius#include <isc/types.h> 33290001Sglebius#include <isc/util.h> 34290001Sglebius 35290001Sglebius#ifdef ISC_PLATFORM_OPENSSLHASH 36290001Sglebius 37290001Sglebiusvoid 38290001Sglebiusisc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key, 39290001Sglebius unsigned int len) 40290001Sglebius{ 41290001Sglebius HMAC_Init(ctx, (const void *) key, (int) len, EVP_md5()); 42290001Sglebius} 43290001Sglebius 44290001Sglebiusvoid 45290001Sglebiusisc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) { 46290001Sglebius HMAC_CTX_cleanup(ctx); 47290001Sglebius} 48290001Sglebius 49290001Sglebiusvoid 50290001Sglebiusisc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf, 51290001Sglebius unsigned int len) 52290001Sglebius{ 53290001Sglebius HMAC_Update(ctx, buf, (int) len); 54290001Sglebius} 55290001Sglebius 56290001Sglebiusvoid 57290001Sglebiusisc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) { 58290001Sglebius HMAC_Final(ctx, digest, NULL); 59290001Sglebius HMAC_CTX_cleanup(ctx); 60290001Sglebius} 61290001Sglebius 62290001Sglebius#else 63290001Sglebius 64290001Sglebius#define PADLEN 64 65290001Sglebius#define IPAD 0x36 66290001Sglebius#define OPAD 0x5C 67290001Sglebius 68290001Sglebius/*! 69290001Sglebius * Start HMAC-MD5 process. Initialize an md5 context and digest the key. 70290001Sglebius */ 71290001Sglebiusvoid 72290001Sglebiusisc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key, 73290001Sglebius unsigned int len) 74290001Sglebius{ 75290001Sglebius unsigned char ipad[PADLEN]; 76290001Sglebius int i; 77290001Sglebius 78290001Sglebius memset(ctx->key, 0, sizeof(ctx->key)); 79290001Sglebius if (len > sizeof(ctx->key)) { 80290001Sglebius isc_md5_t md5ctx; 81290001Sglebius isc_md5_init(&md5ctx); 82290001Sglebius isc_md5_update(&md5ctx, key, len); 83290001Sglebius isc_md5_final(&md5ctx, ctx->key); 84290001Sglebius } else 85290001Sglebius memcpy(ctx->key, key, len); 86290001Sglebius 87290001Sglebius isc_md5_init(&ctx->md5ctx); 88290001Sglebius memset(ipad, IPAD, sizeof(ipad)); 89290001Sglebius for (i = 0; i < PADLEN; i++) 90290001Sglebius ipad[i] ^= ctx->key[i]; 91290001Sglebius isc_md5_update(&ctx->md5ctx, ipad, sizeof(ipad)); 92290001Sglebius} 93290001Sglebius 94290001Sglebiusvoid 95290001Sglebiusisc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) { 96290001Sglebius isc_md5_invalidate(&ctx->md5ctx); 97290001Sglebius memset(ctx->key, 0, sizeof(ctx->key)); 98290001Sglebius} 99290001Sglebius 100290001Sglebius/*! 101290001Sglebius * Update context to reflect the concatenation of another buffer full 102290001Sglebius * of bytes. 103290001Sglebius */ 104290001Sglebiusvoid 105290001Sglebiusisc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf, 106290001Sglebius unsigned int len) 107290001Sglebius{ 108290001Sglebius isc_md5_update(&ctx->md5ctx, buf, len); 109290001Sglebius} 110290001Sglebius 111290001Sglebius/*! 112290001Sglebius * Compute signature - finalize MD5 operation and reapply MD5. 113290001Sglebius */ 114290001Sglebiusvoid 115290001Sglebiusisc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) { 116290001Sglebius unsigned char opad[PADLEN]; 117290001Sglebius int i; 118290001Sglebius 119290001Sglebius isc_md5_final(&ctx->md5ctx, digest); 120290001Sglebius 121290001Sglebius memset(opad, OPAD, sizeof(opad)); 122290001Sglebius for (i = 0; i < PADLEN; i++) 123290001Sglebius opad[i] ^= ctx->key[i]; 124290001Sglebius 125290001Sglebius isc_md5_init(&ctx->md5ctx); 126290001Sglebius isc_md5_update(&ctx->md5ctx, opad, sizeof(opad)); 127290001Sglebius isc_md5_update(&ctx->md5ctx, digest, ISC_MD5_DIGESTLENGTH); 128290001Sglebius isc_md5_final(&ctx->md5ctx, digest); 129290001Sglebius isc_hmacmd5_invalidate(ctx); 130290001Sglebius} 131290001Sglebius#endif /* !ISC_PLATFORM_OPENSSLHASH */ 132290001Sglebius 133290001Sglebius/*! 134290001Sglebius * Verify signature - finalize MD5 operation and reapply MD5, then 135290001Sglebius * compare to the supplied digest. 136290001Sglebius */ 137290001Sglebiusisc_boolean_t 138290001Sglebiusisc_hmacmd5_verify(isc_hmacmd5_t *ctx, unsigned char *digest) { 139290001Sglebius return (isc_hmacmd5_verify2(ctx, digest, ISC_MD5_DIGESTLENGTH)); 140290001Sglebius} 141290001Sglebius 142290001Sglebiusisc_boolean_t 143290001Sglebiusisc_hmacmd5_verify2(isc_hmacmd5_t *ctx, unsigned char *digest, size_t len) { 144290001Sglebius unsigned char newdigest[ISC_MD5_DIGESTLENGTH]; 145290001Sglebius 146290001Sglebius REQUIRE(len <= ISC_MD5_DIGESTLENGTH); 147290001Sglebius isc_hmacmd5_sign(ctx, newdigest); 148298770Sdelphij return (ISC_TF(isc_tsmemcmp(digest, newdigest, len) == 0)); 149290001Sglebius} 150