hash.c revision 67112
156918Sru/*-
256918Sru * Copyright (c) 2000 Mark R V Murray
353451Speter * All rights reserved.
456918Sru *
553475Sobrien * Redistribution and use in source and binary forms, with or without
653475Sobrien * modification, are permitted provided that the following conditions
756918Sru * are met:
856918Sru * 1. Redistributions of source code must retain the above copyright
956918Sru *    notice, this list of conditions and the following disclaimer
1056918Sru *    in this position and unchanged.
1153475Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1256918Sru *    notice, this list of conditions and the following disclaimer in the
1356918Sru *    documentation and/or other materials provided with the distribution.
1456918Sru *
1556918Sru * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1653451Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1756918Sru * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1856918Sru * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1956918Sru * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2056918Sru * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2153451Speter * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2253475Sobrien * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2353475Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2453475Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2553475Sobrien *
2653451Speter * $FreeBSD: head/sys/dev/random/hash.c 67112 2000-10-14 10:59:56Z markm $
2753451Speter */
2853475Sobrien
2953475Sobrien#include <sys/param.h>
3053475Sobrien#include <sys/systm.h>
3153475Sobrien#include <sys/queue.h>
3253451Speter#include <sys/libkern.h>
3353451Speter#include <sys/random.h>
3453475Sobrien#include <sys/time.h>
3553475Sobrien#include <sys/types.h>
3653475Sobrien#include <crypto/blowfish/blowfish.h>
3753451Speter
3853451Speter#include <dev/random/hash.h>
3953475Sobrien
4053475Sobrien/* initialise the hash by copying in some supplied data */
4153451Spetervoid
4253475Sobrienyarrow_hash_init(struct yarrowhash *context, void *data, size_t size)
4353475Sobrien{
4453475Sobrien	size_t count;
4553475Sobrien
4653475Sobrien	count = size > KEYSIZE ? KEYSIZE : size;
4753475Sobrien	memset(context->hash, 0xff, KEYSIZE);
4853475Sobrien	memcpy(context->hash, data, count);
4953451Speter}
5053451Speter
5153475Sobrien/* Do a Davies-Meyer hash using a block cipher.
5253475Sobrien * H_0 = I
5353475Sobrien * H_i = E_M_i(H_i-1) ^ H_i-1
5453475Sobrien */
5553451Spetervoid
5653451Speteryarrow_hash_iterate(struct yarrowhash *context, void *data, size_t size)
5753451Speter{
5853451Speter	u_char keybuffer[KEYSIZE], temp[KEYSIZE];
5953451Speter	size_t count;
6053451Speter	int iteration, last, i;
6153451Speter
6253451Speter	iteration = 0;
6353475Sobrien	last = 0;
6453451Speter	for (;;) {
6553451Speter		if (size <= KEYSIZE)
6653451Speter			last = 1;
6753451Speter		count = size > KEYSIZE ? KEYSIZE : size;
6853451Speter		memcpy(keybuffer, &((u_char *)data)[iteration], count);
6953451Speter		memset(&keybuffer[KEYSIZE - count], 0xff, count);
7053451Speter		BF_set_key(&context->hashkey, count,
7153451Speter			&((u_char *)data)[iteration]);
7253451Speter		BF_cbc_encrypt(context->hash, temp, KEYSIZE, &context->hashkey,
7353451Speter			context->ivec, BF_ENCRYPT);
7453451Speter		for (i = 0; i < KEYSIZE; i++)
7553451Speter			context->hash[i] ^= temp[i];
7653451Speter		if (last)
7753451Speter			break;
7853475Sobrien		iteration += KEYSIZE;
7953475Sobrien		size -= KEYSIZE;
8053475Sobrien	}
8156918Sru}
8256918Sru
8356918Sru/* Conclude by returning a pointer to the data */
8453475Sobrienvoid
8553475Sobrienyarrow_hash_finish(struct yarrowhash *context, void *buf)
8653475Sobrien{
8753475Sobrien	memcpy(buf, context->hash, sizeof(context->hash));
8853475Sobrien}
8953475Sobrien
9053475Sobrien/* Initialise the encryption routine by setting up the key schedule */
9153475Sobrienvoid
9253475Sobrienyarrow_encrypt_init(struct yarrowkey *context, void *data, size_t size)
9353475Sobrien{
9453475Sobrien	size_t count;
9553475Sobrien
9653475Sobrien	count = size > KEYSIZE ? KEYSIZE : size;
9753475Sobrien	BF_set_key(&context->key, size, data);
9853475Sobrien}
9953475Sobrien
10053475Sobrien/* Encrypt the supplied data using the key schedule preset in the context */
10153475Sobrienvoid
10253451Speteryarrow_encrypt(struct yarrowkey *context, void *d_in, void *d_out, size_t size)
10353451Speter{
10453451Speter	size_t count;
10553451Speter	int iteration, last;
10653451Speter
10753451Speter	last = 0;
10853451Speter	for (iteration = 0;; iteration += KEYSIZE) {
10953451Speter		if (size <= KEYSIZE)
11053451Speter			last = 1;
11153451Speter		count = size > KEYSIZE ? KEYSIZE : size;
11253451Speter		BF_cbc_encrypt(&((u_char *)d_in)[iteration],
11353475Sobrien			&((u_char *)d_out)[iteration], count, &context->key,
11453451Speter			context->ivec, BF_ENCRYPT);
11553451Speter		if (last)
11653451Speter			break;
11753475Sobrien		size -= KEYSIZE;
11853451Speter	}
11953451Speter}
12053451Speter