/*-
 * See the file LICENSE for redistribution information.
 *
 * Copyright (c) 1996-2001
 *      Sleepycat Software.  All rights reserved.
 */
/*
 * Some parts of this code originally written by Adam Stubblefield
 * - astubble@rice.edu
 */
#ifndef lint
static const char revid[] = "$Id: hmac.c,v 1.2 2002/01/08 18:55:22 sue Exp $";
#endif /* not lint */


#include "db_config.h"

#include "db_int.h"
#include "crypto.h"
#include "crypto_ext.h"

#define OUTPUT_SIZE	20
#define BLOCK_SIZE	64

static void __db_hmac __P((u_int8_t *, u_int8_t *, size_t, u_int8_t *));

/*
 * __db_hmac --
 *	Do a hashed MAC.
 */
static void
__db_hmac(k, data, data_len, mac)
	u_int8_t *k, *data, *mac;
	size_t data_len;
{
	SHA1_CTX ctx;
	u_int8_t key[BLOCK_SIZE];
	u_int8_t ipad[BLOCK_SIZE];
	u_int8_t opad[BLOCK_SIZE];
	u_int8_t tmp[OUTPUT_SIZE]; 
	int i;

	memset(key, 0x00, BLOCK_SIZE);
	memset(ipad, 0x36, BLOCK_SIZE);
	memset(opad, 0x5C, BLOCK_SIZE);

	memcpy(key, k, OUTPUT_SIZE);

	for(i = 0; i < BLOCK_SIZE; i++) {
		ipad[i] ^= key[i];
		opad[i] ^= key[i];
	}

	__db_SHA1Init(&ctx);
	__db_SHA1Update(&ctx, ipad, BLOCK_SIZE);
	__db_SHA1Update(&ctx, data, data_len);
	__db_SHA1Final(tmp, &ctx);
	__db_SHA1Init(&ctx);
	__db_SHA1Update(&ctx, opad, BLOCK_SIZE);
	__db_SHA1Update(&ctx, tmp, OUTPUT_SIZE);
	__db_SHA1Final(mac, &ctx);
	return;
} 

/*
 * __db_mac --
 *	Create a MAC/SHA1 checksum.
 *
 * PUBLIC: void __db_mac __P((u_int8_t *, size_t, u_int8_t *, u_int8_t *));
 */
void
__db_mac(data, data_len, mac_key, store)
	u_int8_t *data;
	size_t data_len;
	u_int8_t *mac_key;
	u_int8_t *store;
{
	SHA1_CTX ctx;

	/*
	 * Store better be 20 bytes
	 */
	if (mac_key == NULL) {
		/* Just a hash, no MAC */
		__db_SHA1Init(&ctx);
		__db_SHA1Update(&ctx, data, data_len);
		__db_SHA1Final(store, &ctx);
	} else
		__db_hmac(mac_key, data, data_len, store);
	return;
}
