#include "config.h"
#include <isc/assertions.h>
#include <isc/hmacmd5.h>
#include <isc/md5.h>
#include <isc/string.h>
#include <isc/types.h>
#include <isc/util.h>
#define PADLEN 64
#define IPAD 0x36
#define OPAD 0x5C
void
isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
unsigned int len)
{
unsigned char ipad[PADLEN];
int i;
memset(ctx->key, 0, sizeof(ctx->key));
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);
memset(ipad, IPAD, sizeof(ipad));
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);
memset(ctx->key, 0, sizeof(ctx->key));
}
void
isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
unsigned int len)
{
isc_md5_update(&ctx->md5ctx, buf, len);
}
void
isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
unsigned char opad[PADLEN];
int i;
isc_md5_final(&ctx->md5ctx, digest);
memset(opad, OPAD, sizeof(opad));
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);
}
isc_boolean_t
isc_hmacmd5_verify(isc_hmacmd5_t *ctx, unsigned char *digest) {
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) {
unsigned char newdigest[ISC_MD5_DIGESTLENGTH];
REQUIRE(len <= ISC_MD5_DIGESTLENGTH);
isc_hmacmd5_sign(ctx, newdigest);
return (ISC_TF(memcmp(digest, newdigest, len) == 0));
}