hmacmd5.c 3.78 KB
Newer Older
1
/*
Automatic Updater's avatar
Automatic Updater committed
2
 * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
Brian Wellington's avatar
Brian Wellington committed
3
 * Copyright (C) 2000, 2001  Internet Software Consortium.
4
 *
Automatic Updater's avatar
Automatic Updater committed
5
 * Permission to use, copy, modify, and/or distribute this software for any
6 7
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
8
 *
Mark Andrews's avatar
Mark Andrews committed
9 10 11 12 13 14 15
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
16 17
 */

Automatic Updater's avatar
Automatic Updater committed
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 26 27 28 29
 */

#include "config.h"

#include <isc/assertions.h>
#include <isc/hmacmd5.h>
#include <isc/md5.h>
Francis Dupont's avatar
Francis Dupont committed
30
#include <isc/platform.h>
Evan Hunt's avatar
Evan Hunt committed
31
#include <isc/safe.h>
32
#include <isc/string.h>
33 34 35
#include <isc/types.h>
#include <isc/util.h>

Francis Dupont's avatar
Francis Dupont committed
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
#ifdef ISC_PLATFORM_OPENSSLHASH

void
isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
		 unsigned int len)
{
	HMAC_Init(ctx, (const void *) key, (int) len, EVP_md5());
}

void
isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) {
	HMAC_CTX_cleanup(ctx);
}

void
isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
		   unsigned int len)
{
	HMAC_Update(ctx, buf, (int) len);
}

void
isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
	HMAC_Final(ctx, digest, NULL);
	HMAC_CTX_cleanup(ctx);
}

#else

65 66 67 68
#define PADLEN 64
#define IPAD 0x36
#define OPAD 0x5C

69
/*!
70 71 72 73 74 75 76 77 78
 * Start HMAC-MD5 process.  Initialize an md5 context and digest the key.
 */
void
isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
		 unsigned int len)
{
	unsigned char ipad[PADLEN];
	int i;

Andreas Gustafsson's avatar
Andreas Gustafsson committed
79
	memset(ctx->key, 0, sizeof(ctx->key));
80 81 82 83 84 85 86 87 88
	if (len > sizeof(ctx->key)) {
		isc_md5_t md5ctx;
		isc_md5_init(&md5ctx);
		isc_md5_update(&md5ctx, key, len);
		isc_md5_final(&md5ctx, ctx->key);
	} else
		memcpy(ctx->key, key, len);

	isc_md5_init(&ctx->md5ctx);
Andreas Gustafsson's avatar
Andreas Gustafsson committed
89
	memset(ipad, IPAD, sizeof(ipad));
90 91 92 93 94 95 96 97
	for (i = 0; i < PADLEN; i++)
		ipad[i] ^= ctx->key[i];
	isc_md5_update(&ctx->md5ctx, ipad, sizeof(ipad));
}

void
isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) {
	isc_md5_invalidate(&ctx->md5ctx);
Andreas Gustafsson's avatar
Andreas Gustafsson committed
98
	memset(ctx->key, 0, sizeof(ctx->key));
99 100
}

101
/*!
102 103 104 105 106 107 108 109 110 111
 * Update context to reflect the concatenation of another buffer full
 * of bytes.
 */
void
isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
		   unsigned int len)
{
	isc_md5_update(&ctx->md5ctx, buf, len);
}

112
/*!
113 114 115 116 117 118 119 120 121
 * Compute signature - finalize MD5 operation and reapply MD5.
 */
void
isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
	unsigned char opad[PADLEN];
	int i;

	isc_md5_final(&ctx->md5ctx, digest);

Andreas Gustafsson's avatar
Andreas Gustafsson committed
122
	memset(opad, OPAD, sizeof(opad));
123 124 125 126 127 128 129 130 131
	for (i = 0; i < PADLEN; i++)
		opad[i] ^= ctx->key[i];

	isc_md5_init(&ctx->md5ctx);
	isc_md5_update(&ctx->md5ctx, opad, sizeof(opad));
	isc_md5_update(&ctx->md5ctx, digest, ISC_MD5_DIGESTLENGTH);
	isc_md5_final(&ctx->md5ctx, digest);
	isc_hmacmd5_invalidate(ctx);
}
Francis Dupont's avatar
Francis Dupont committed
132
#endif /* !ISC_PLATFORM_OPENSSLHASH */
133

134
/*!
135 136 137 138 139
 * Verify signature - finalize MD5 operation and reapply MD5, then
 * compare to the supplied digest.
 */
isc_boolean_t
isc_hmacmd5_verify(isc_hmacmd5_t *ctx, unsigned char *digest) {
140 141 142 143 144
	return (isc_hmacmd5_verify2(ctx, digest, ISC_MD5_DIGESTLENGTH));
}

isc_boolean_t
isc_hmacmd5_verify2(isc_hmacmd5_t *ctx, unsigned char *digest, size_t len) {
145 146
	unsigned char newdigest[ISC_MD5_DIGESTLENGTH];

147
	REQUIRE(len <= ISC_MD5_DIGESTLENGTH);
148
	isc_hmacmd5_sign(ctx, newdigest);
Evan Hunt's avatar
Evan Hunt committed
149
	return (isc_safe_memcmp(digest, newdigest, len));
150
}