summaryrefslogtreecommitdiff
path: root/ext/Digest/SHA/src/hmac.c
blob: 4fd7610de0a3f5eeb98068b3d7096527cbb8d2f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*
 * hmac.c: routines to compute HMAC-SHA-1/224/256/384/512 digests
 *
 * Ref: FIPS PUB 198 The Keyed-Hash Message Authentication Code
 *
 * Copyright (C) 2003-2006 Mark Shelor, All Rights Reserved
 *
 * Version: 5.43
 * Sat Aug  5 02:36:18 MST 2006
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hmac.h"
#include "sha.h"

/* hmacopen: creates a new HMAC-SHA digest object */
HMAC *hmacopen(int alg, unsigned char *key, unsigned int keylen)
{
	unsigned int i;
	HMAC *h;

	SHA_newz(0, h, 1, HMAC);
	if (h == NULL)
		return(NULL);
	if ((h->isha = shaopen(alg)) == NULL) {
		SHA_free(h);
		return(NULL);
	}
	if ((h->osha = shaopen(alg)) == NULL) {
		shaclose(h->isha);
		SHA_free(h);
		return(NULL);
	}
	if (keylen <= h->osha->blocksize / 8)
		memcpy(h->key, key, keylen);
	else {
		if ((h->ksha = shaopen(alg)) == NULL) {
			shaclose(h->isha);
			shaclose(h->osha);
			SHA_free(h);
			return(NULL);
		}
		shawrite(key, keylen * 8, h->ksha);
		shafinish(h->ksha);
		memcpy(h->key, shadigest(h->ksha), h->ksha->digestlen);
		shaclose(h->ksha);
	}
	for (i = 0; i < h->osha->blocksize / 8; i++)
		h->key[i] ^= 0x5c;
	shawrite(h->key, h->osha->blocksize, h->osha);
	for (i = 0; i < h->isha->blocksize / 8; i++)
		h->key[i] ^= (0x5c ^ 0x36);
	shawrite(h->key, h->isha->blocksize, h->isha);
	memset(h->key, 0, sizeof(h->key));
	return(h);
}

/* hmacwrite: triggers a state update using data in bitstr/bitcnt */
unsigned long hmacwrite(unsigned char *bitstr, unsigned long bitcnt, HMAC *h)
{
	return(shawrite(bitstr, bitcnt, h->isha));
}

/* hmacfinish: computes final digest state */
void hmacfinish(HMAC *h)
{
	shafinish(h->isha);
	shawrite(shadigest(h->isha), h->isha->digestlen * 8, h->osha);
	shaclose(h->isha);
	shafinish(h->osha);
}

/* hmacdigest: returns pointer to digest (binary) */
unsigned char *hmacdigest(HMAC *h)
{
	return(shadigest(h->osha));
}

/* hmachex: returns pointer to digest (hexadecimal) */
char *hmachex(HMAC *h)
{
	return(shahex(h->osha));
}

/* hmacbase64: returns pointer to digest (Base 64) */
char *hmacbase64(HMAC *h)
{
	return(shabase64(h->osha));
}

/* hmacclose: de-allocates digest object */
int hmacclose(HMAC *h)
{
	shaclose(h->osha);
	memset(h, 0, sizeof(HMAC));
	SHA_free(h);
	return(0);
}