1258945Sroberto/*
2258945Sroberto * Crypto wrapper for internal crypto implementation
3258945Sroberto * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
4258945Sroberto *
5258945Sroberto * This program is free software; you can redistribute it and/or modify
6258945Sroberto * it under the terms of the GNU General Public License version 2 as
7258945Sroberto * published by the Free Software Foundation.
8258945Sroberto *
9258945Sroberto * Alternatively, this software may be distributed under the terms of BSD
10258945Sroberto * license.
11258945Sroberto *
12258945Sroberto * See README and COPYING for more details.
13258945Sroberto */
14258945Sroberto
15258945Sroberto#include "includes.h"
16258945Sroberto
17258945Sroberto#include "common.h"
18258945Sroberto#include "crypto.h"
19258945Sroberto#include "sha1_i.h"
20258945Sroberto#include "md5_i.h"
21258945Sroberto
22258945Srobertostruct crypto_hash {
23258945Sroberto	enum crypto_hash_alg alg;
24258945Sroberto	union {
25258945Sroberto		struct MD5Context md5;
26258945Sroberto		struct SHA1Context sha1;
27258945Sroberto	} u;
28258945Sroberto	u8 key[64];
29258945Sroberto	size_t key_len;
30258945Sroberto};
31258945Sroberto
32258945Sroberto
33258945Srobertostruct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
34258945Sroberto				      size_t key_len)
35258945Sroberto{
36258945Sroberto	struct crypto_hash *ctx;
37258945Sroberto	u8 k_pad[64];
38258945Sroberto	u8 tk[20];
39330567Sgordon	size_t i;
40258945Sroberto
41258945Sroberto	ctx = os_zalloc(sizeof(*ctx));
42258945Sroberto	if (ctx == NULL)
43258945Sroberto		return NULL;
44258945Sroberto
45258945Sroberto	ctx->alg = alg;
46258945Sroberto
47258945Sroberto	switch (alg) {
48258945Sroberto	case CRYPTO_HASH_ALG_MD5:
49258945Sroberto		MD5Init(&ctx->u.md5);
50258945Sroberto		break;
51258945Sroberto	case CRYPTO_HASH_ALG_SHA1:
52258945Sroberto		SHA1Init(&ctx->u.sha1);
53258945Sroberto		break;
54258945Sroberto	case CRYPTO_HASH_ALG_HMAC_MD5:
55258945Sroberto		if (key_len > sizeof(k_pad)) {
56258945Sroberto			MD5Init(&ctx->u.md5);
57258945Sroberto			MD5Update(&ctx->u.md5, key, key_len);
58258945Sroberto			MD5Final(tk, &ctx->u.md5);
59258945Sroberto			key = tk;
60258945Sroberto			key_len = 16;
61258945Sroberto		}
62258945Sroberto		os_memcpy(ctx->key, key, key_len);
63258945Sroberto		ctx->key_len = key_len;
64258945Sroberto
65258945Sroberto		os_memcpy(k_pad, key, key_len);
66258945Sroberto		os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
67258945Sroberto		for (i = 0; i < sizeof(k_pad); i++)
68258945Sroberto			k_pad[i] ^= 0x36;
69280849Scy		MD5Init(&ctx->u.md5);
70258945Sroberto		MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
71280849Scy		break;
72280849Scy	case CRYPTO_HASH_ALG_HMAC_SHA1:
73280849Scy		if (key_len > sizeof(k_pad)) {
74280849Scy			SHA1Init(&ctx->u.sha1);
75280849Scy			SHA1Update(&ctx->u.sha1, key, key_len);
76258945Sroberto			SHA1Final(tk, &ctx->u.sha1);
77258945Sroberto			key = tk;
78258945Sroberto			key_len = 20;
79258945Sroberto		}
80258945Sroberto		os_memcpy(ctx->key, key, key_len);
81258945Sroberto		ctx->key_len = key_len;
82258945Sroberto
83258945Sroberto		os_memcpy(k_pad, key, key_len);
84258945Sroberto		os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
85258945Sroberto		for (i = 0; i < sizeof(k_pad); i++)
86280849Scy			k_pad[i] ^= 0x36;
87280849Scy		SHA1Init(&ctx->u.sha1);
88280849Scy		SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
89280849Scy		break;
90258945Sroberto	default:
91280849Scy		os_free(ctx);
92258945Sroberto		return NULL;
93258945Sroberto	}
94258945Sroberto
95258945Sroberto	return ctx;
96258945Sroberto}
97258945Sroberto
98280849Scy
99280849Scyvoid crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
100280849Scy{
101280849Scy	if (ctx == NULL)
102280849Scy		return;
103258945Sroberto
104280849Scy	switch (ctx->alg) {
105280849Scy	case CRYPTO_HASH_ALG_MD5:
106280849Scy	case CRYPTO_HASH_ALG_HMAC_MD5:
107280849Scy		MD5Update(&ctx->u.md5, data, len);
108280849Scy		break;
109280849Scy	case CRYPTO_HASH_ALG_SHA1:
110280849Scy	case CRYPTO_HASH_ALG_HMAC_SHA1:
111280849Scy		SHA1Update(&ctx->u.sha1, data, len);
112280849Scy		break;
113280849Scy	}
114280849Scy}
115280849Scy
116280849Scy
117280849Scyint crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
118280849Scy{
119280849Scy	u8 k_pad[64];
120280849Scy	size_t i;
121280849Scy
122280849Scy	if (ctx == NULL)
123280849Scy		return -2;
124280849Scy
125280849Scy	if (mac == NULL || len == NULL) {
126280849Scy		os_free(ctx);
127280849Scy		return 0;
128280849Scy	}
129280849Scy
130285612Sdelphij	switch (ctx->alg) {
131285612Sdelphij	case CRYPTO_HASH_ALG_MD5:
132258945Sroberto		if (*len < 16) {
133258945Sroberto			*len = 16;
134280849Scy			os_free(ctx);
135280849Scy			return -1;
136258945Sroberto		}
137258945Sroberto		*len = 16;
138280849Scy		MD5Final(mac, &ctx->u.md5);
139280849Scy		break;
140280849Scy	case CRYPTO_HASH_ALG_SHA1:
141280849Scy		if (*len < 20) {
142280849Scy			*len = 20;
143280849Scy			os_free(ctx);
144280849Scy			return -1;
145280849Scy		}
146280849Scy		*len = 20;
147280849Scy		SHA1Final(mac, &ctx->u.sha1);
148280849Scy		break;
149280849Scy	case CRYPTO_HASH_ALG_HMAC_MD5:
150280849Scy		if (*len < 16) {
151280849Scy			*len = 16;
152280849Scy			os_free(ctx);
153280849Scy			return -1;
154280849Scy		}
155280849Scy		*len = 16;
156280849Scy
157258945Sroberto		MD5Final(mac, &ctx->u.md5);
158258945Sroberto
159258945Sroberto		os_memcpy(k_pad, ctx->key, ctx->key_len);
160258945Sroberto		os_memset(k_pad + ctx->key_len, 0,
161280849Scy			  sizeof(k_pad) - ctx->key_len);
162258945Sroberto		for (i = 0; i < sizeof(k_pad); i++)
163258945Sroberto			k_pad[i] ^= 0x5c;
164258945Sroberto		MD5Init(&ctx->u.md5);
165258945Sroberto		MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
166280849Scy		MD5Update(&ctx->u.md5, mac, 16);
167258945Sroberto		MD5Final(mac, &ctx->u.md5);
168280849Scy		break;
169280849Scy	case CRYPTO_HASH_ALG_HMAC_SHA1:
170258945Sroberto		if (*len < 20) {
171280849Scy			*len = 20;
172280849Scy			os_free(ctx);
173280849Scy			return -1;
174280849Scy		}
175280849Scy		*len = 20;
176280849Scy
177280849Scy		SHA1Final(mac, &ctx->u.sha1);
178280849Scy
179330567Sgordon		os_memcpy(k_pad, ctx->key, ctx->key_len);
180330567Sgordon		os_memset(k_pad + ctx->key_len, 0,
181258945Sroberto			  sizeof(k_pad) - ctx->key_len);
182258945Sroberto		for (i = 0; i < sizeof(k_pad); i++)
183258945Sroberto			k_pad[i] ^= 0x5c;
184330567Sgordon		SHA1Init(&ctx->u.sha1);
185330567Sgordon		SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
186258945Sroberto		SHA1Update(&ctx->u.sha1, mac, 20);
187330567Sgordon		SHA1Final(mac, &ctx->u.sha1);
188330567Sgordon		break;
189330567Sgordon	}
190330567Sgordon
191280849Scy	os_free(ctx);
192258945Sroberto
193280849Scy	return 0;
194280849Scy}
195280849Scy
196280849Scy
197330567Sgordonint crypto_global_init(void)
198280849Scy{
199280849Scy	return 0;
200280849Scy}
201330567Sgordon
202280849Scy
203330567Sgordonvoid crypto_global_deinit(void)
204330567Sgordon{
205280849Scy}
206330567Sgordon