16d49e1aeSJan Lentfer /*
23ff40c12SJohn Marino * Crypto wrapper for internal crypto implementation
33ff40c12SJohn Marino * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
46d49e1aeSJan Lentfer *
53ff40c12SJohn Marino * This software may be distributed under the terms of the BSD license.
63ff40c12SJohn Marino * See README for more details.
76d49e1aeSJan Lentfer */
86d49e1aeSJan Lentfer
96d49e1aeSJan Lentfer #include "includes.h"
106d49e1aeSJan Lentfer
116d49e1aeSJan Lentfer #include "common.h"
126d49e1aeSJan Lentfer #include "crypto.h"
133ff40c12SJohn Marino #include "sha256_i.h"
14*a1157835SDaniel Fojt #include "sha384_i.h"
15*a1157835SDaniel Fojt #include "sha512_i.h"
163ff40c12SJohn Marino #include "sha1_i.h"
173ff40c12SJohn Marino #include "md5_i.h"
186d49e1aeSJan Lentfer
196d49e1aeSJan Lentfer struct crypto_hash {
206d49e1aeSJan Lentfer enum crypto_hash_alg alg;
216d49e1aeSJan Lentfer union {
226d49e1aeSJan Lentfer struct MD5Context md5;
236d49e1aeSJan Lentfer struct SHA1Context sha1;
243ff40c12SJohn Marino #ifdef CONFIG_SHA256
253ff40c12SJohn Marino struct sha256_state sha256;
263ff40c12SJohn Marino #endif /* CONFIG_SHA256 */
27*a1157835SDaniel Fojt #ifdef CONFIG_INTERNAL_SHA384
28*a1157835SDaniel Fojt struct sha384_state sha384;
29*a1157835SDaniel Fojt #endif /* CONFIG_INTERNAL_SHA384 */
30*a1157835SDaniel Fojt #ifdef CONFIG_INTERNAL_SHA512
31*a1157835SDaniel Fojt struct sha512_state sha512;
32*a1157835SDaniel Fojt #endif /* CONFIG_INTERNAL_SHA512 */
336d49e1aeSJan Lentfer } u;
346d49e1aeSJan Lentfer u8 key[64];
356d49e1aeSJan Lentfer size_t key_len;
366d49e1aeSJan Lentfer };
376d49e1aeSJan Lentfer
386d49e1aeSJan Lentfer
crypto_hash_init(enum crypto_hash_alg alg,const u8 * key,size_t key_len)396d49e1aeSJan Lentfer struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
406d49e1aeSJan Lentfer size_t key_len)
416d49e1aeSJan Lentfer {
426d49e1aeSJan Lentfer struct crypto_hash *ctx;
436d49e1aeSJan Lentfer u8 k_pad[64];
443ff40c12SJohn Marino u8 tk[32];
456d49e1aeSJan Lentfer size_t i;
466d49e1aeSJan Lentfer
476d49e1aeSJan Lentfer ctx = os_zalloc(sizeof(*ctx));
486d49e1aeSJan Lentfer if (ctx == NULL)
496d49e1aeSJan Lentfer return NULL;
506d49e1aeSJan Lentfer
516d49e1aeSJan Lentfer ctx->alg = alg;
526d49e1aeSJan Lentfer
536d49e1aeSJan Lentfer switch (alg) {
546d49e1aeSJan Lentfer case CRYPTO_HASH_ALG_MD5:
556d49e1aeSJan Lentfer MD5Init(&ctx->u.md5);
566d49e1aeSJan Lentfer break;
576d49e1aeSJan Lentfer case CRYPTO_HASH_ALG_SHA1:
586d49e1aeSJan Lentfer SHA1Init(&ctx->u.sha1);
596d49e1aeSJan Lentfer break;
603ff40c12SJohn Marino #ifdef CONFIG_SHA256
613ff40c12SJohn Marino case CRYPTO_HASH_ALG_SHA256:
623ff40c12SJohn Marino sha256_init(&ctx->u.sha256);
633ff40c12SJohn Marino break;
643ff40c12SJohn Marino #endif /* CONFIG_SHA256 */
65*a1157835SDaniel Fojt #ifdef CONFIG_INTERNAL_SHA384
66*a1157835SDaniel Fojt case CRYPTO_HASH_ALG_SHA384:
67*a1157835SDaniel Fojt sha384_init(&ctx->u.sha384);
68*a1157835SDaniel Fojt break;
69*a1157835SDaniel Fojt #endif /* CONFIG_INTERNAL_SHA384 */
70*a1157835SDaniel Fojt #ifdef CONFIG_INTERNAL_SHA512
71*a1157835SDaniel Fojt case CRYPTO_HASH_ALG_SHA512:
72*a1157835SDaniel Fojt sha512_init(&ctx->u.sha512);
73*a1157835SDaniel Fojt break;
74*a1157835SDaniel Fojt #endif /* CONFIG_INTERNAL_SHA512 */
756d49e1aeSJan Lentfer case CRYPTO_HASH_ALG_HMAC_MD5:
766d49e1aeSJan Lentfer if (key_len > sizeof(k_pad)) {
776d49e1aeSJan Lentfer MD5Init(&ctx->u.md5);
786d49e1aeSJan Lentfer MD5Update(&ctx->u.md5, key, key_len);
796d49e1aeSJan Lentfer MD5Final(tk, &ctx->u.md5);
806d49e1aeSJan Lentfer key = tk;
816d49e1aeSJan Lentfer key_len = 16;
826d49e1aeSJan Lentfer }
836d49e1aeSJan Lentfer os_memcpy(ctx->key, key, key_len);
846d49e1aeSJan Lentfer ctx->key_len = key_len;
856d49e1aeSJan Lentfer
866d49e1aeSJan Lentfer os_memcpy(k_pad, key, key_len);
873ff40c12SJohn Marino if (key_len < sizeof(k_pad))
886d49e1aeSJan Lentfer os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
896d49e1aeSJan Lentfer for (i = 0; i < sizeof(k_pad); i++)
906d49e1aeSJan Lentfer k_pad[i] ^= 0x36;
916d49e1aeSJan Lentfer MD5Init(&ctx->u.md5);
926d49e1aeSJan Lentfer MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
936d49e1aeSJan Lentfer break;
946d49e1aeSJan Lentfer case CRYPTO_HASH_ALG_HMAC_SHA1:
956d49e1aeSJan Lentfer if (key_len > sizeof(k_pad)) {
966d49e1aeSJan Lentfer SHA1Init(&ctx->u.sha1);
976d49e1aeSJan Lentfer SHA1Update(&ctx->u.sha1, key, key_len);
986d49e1aeSJan Lentfer SHA1Final(tk, &ctx->u.sha1);
996d49e1aeSJan Lentfer key = tk;
1006d49e1aeSJan Lentfer key_len = 20;
1016d49e1aeSJan Lentfer }
1026d49e1aeSJan Lentfer os_memcpy(ctx->key, key, key_len);
1036d49e1aeSJan Lentfer ctx->key_len = key_len;
1046d49e1aeSJan Lentfer
1056d49e1aeSJan Lentfer os_memcpy(k_pad, key, key_len);
1063ff40c12SJohn Marino if (key_len < sizeof(k_pad))
1076d49e1aeSJan Lentfer os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
1086d49e1aeSJan Lentfer for (i = 0; i < sizeof(k_pad); i++)
1096d49e1aeSJan Lentfer k_pad[i] ^= 0x36;
1106d49e1aeSJan Lentfer SHA1Init(&ctx->u.sha1);
1116d49e1aeSJan Lentfer SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
1126d49e1aeSJan Lentfer break;
1133ff40c12SJohn Marino #ifdef CONFIG_SHA256
1143ff40c12SJohn Marino case CRYPTO_HASH_ALG_HMAC_SHA256:
1153ff40c12SJohn Marino if (key_len > sizeof(k_pad)) {
1163ff40c12SJohn Marino sha256_init(&ctx->u.sha256);
1173ff40c12SJohn Marino sha256_process(&ctx->u.sha256, key, key_len);
1183ff40c12SJohn Marino sha256_done(&ctx->u.sha256, tk);
1193ff40c12SJohn Marino key = tk;
1203ff40c12SJohn Marino key_len = 32;
1213ff40c12SJohn Marino }
1223ff40c12SJohn Marino os_memcpy(ctx->key, key, key_len);
1233ff40c12SJohn Marino ctx->key_len = key_len;
1243ff40c12SJohn Marino
1253ff40c12SJohn Marino os_memcpy(k_pad, key, key_len);
1263ff40c12SJohn Marino if (key_len < sizeof(k_pad))
1273ff40c12SJohn Marino os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
1283ff40c12SJohn Marino for (i = 0; i < sizeof(k_pad); i++)
1293ff40c12SJohn Marino k_pad[i] ^= 0x36;
1303ff40c12SJohn Marino sha256_init(&ctx->u.sha256);
1313ff40c12SJohn Marino sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
1323ff40c12SJohn Marino break;
1333ff40c12SJohn Marino #endif /* CONFIG_SHA256 */
1346d49e1aeSJan Lentfer default:
1356d49e1aeSJan Lentfer os_free(ctx);
1366d49e1aeSJan Lentfer return NULL;
1376d49e1aeSJan Lentfer }
1386d49e1aeSJan Lentfer
1396d49e1aeSJan Lentfer return ctx;
1406d49e1aeSJan Lentfer }
1416d49e1aeSJan Lentfer
1426d49e1aeSJan Lentfer
crypto_hash_update(struct crypto_hash * ctx,const u8 * data,size_t len)1436d49e1aeSJan Lentfer void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
1446d49e1aeSJan Lentfer {
1456d49e1aeSJan Lentfer if (ctx == NULL)
1466d49e1aeSJan Lentfer return;
1476d49e1aeSJan Lentfer
1486d49e1aeSJan Lentfer switch (ctx->alg) {
1496d49e1aeSJan Lentfer case CRYPTO_HASH_ALG_MD5:
1506d49e1aeSJan Lentfer case CRYPTO_HASH_ALG_HMAC_MD5:
1516d49e1aeSJan Lentfer MD5Update(&ctx->u.md5, data, len);
1526d49e1aeSJan Lentfer break;
1536d49e1aeSJan Lentfer case CRYPTO_HASH_ALG_SHA1:
1546d49e1aeSJan Lentfer case CRYPTO_HASH_ALG_HMAC_SHA1:
1556d49e1aeSJan Lentfer SHA1Update(&ctx->u.sha1, data, len);
1566d49e1aeSJan Lentfer break;
1573ff40c12SJohn Marino #ifdef CONFIG_SHA256
1583ff40c12SJohn Marino case CRYPTO_HASH_ALG_SHA256:
1593ff40c12SJohn Marino case CRYPTO_HASH_ALG_HMAC_SHA256:
1603ff40c12SJohn Marino sha256_process(&ctx->u.sha256, data, len);
1613ff40c12SJohn Marino break;
1623ff40c12SJohn Marino #endif /* CONFIG_SHA256 */
163*a1157835SDaniel Fojt #ifdef CONFIG_INTERNAL_SHA384
164*a1157835SDaniel Fojt case CRYPTO_HASH_ALG_SHA384:
165*a1157835SDaniel Fojt sha384_process(&ctx->u.sha384, data, len);
166*a1157835SDaniel Fojt break;
167*a1157835SDaniel Fojt #endif /* CONFIG_INTERNAL_SHA384 */
168*a1157835SDaniel Fojt #ifdef CONFIG_INTERNAL_SHA512
169*a1157835SDaniel Fojt case CRYPTO_HASH_ALG_SHA512:
170*a1157835SDaniel Fojt sha512_process(&ctx->u.sha512, data, len);
171*a1157835SDaniel Fojt break;
172*a1157835SDaniel Fojt #endif /* CONFIG_INTERNAL_SHA512 */
1733ff40c12SJohn Marino default:
1743ff40c12SJohn Marino break;
1756d49e1aeSJan Lentfer }
1766d49e1aeSJan Lentfer }
1776d49e1aeSJan Lentfer
1786d49e1aeSJan Lentfer
crypto_hash_finish(struct crypto_hash * ctx,u8 * mac,size_t * len)1796d49e1aeSJan Lentfer int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
1806d49e1aeSJan Lentfer {
1816d49e1aeSJan Lentfer u8 k_pad[64];
1826d49e1aeSJan Lentfer size_t i;
1836d49e1aeSJan Lentfer
1846d49e1aeSJan Lentfer if (ctx == NULL)
1856d49e1aeSJan Lentfer return -2;
1866d49e1aeSJan Lentfer
1876d49e1aeSJan Lentfer if (mac == NULL || len == NULL) {
1886d49e1aeSJan Lentfer os_free(ctx);
1896d49e1aeSJan Lentfer return 0;
1906d49e1aeSJan Lentfer }
1916d49e1aeSJan Lentfer
1926d49e1aeSJan Lentfer switch (ctx->alg) {
1936d49e1aeSJan Lentfer case CRYPTO_HASH_ALG_MD5:
1946d49e1aeSJan Lentfer if (*len < 16) {
1956d49e1aeSJan Lentfer *len = 16;
1966d49e1aeSJan Lentfer os_free(ctx);
1976d49e1aeSJan Lentfer return -1;
1986d49e1aeSJan Lentfer }
1996d49e1aeSJan Lentfer *len = 16;
2006d49e1aeSJan Lentfer MD5Final(mac, &ctx->u.md5);
2016d49e1aeSJan Lentfer break;
2026d49e1aeSJan Lentfer case CRYPTO_HASH_ALG_SHA1:
2036d49e1aeSJan Lentfer if (*len < 20) {
2046d49e1aeSJan Lentfer *len = 20;
2056d49e1aeSJan Lentfer os_free(ctx);
2066d49e1aeSJan Lentfer return -1;
2076d49e1aeSJan Lentfer }
2086d49e1aeSJan Lentfer *len = 20;
2096d49e1aeSJan Lentfer SHA1Final(mac, &ctx->u.sha1);
2106d49e1aeSJan Lentfer break;
2113ff40c12SJohn Marino #ifdef CONFIG_SHA256
2123ff40c12SJohn Marino case CRYPTO_HASH_ALG_SHA256:
2133ff40c12SJohn Marino if (*len < 32) {
2143ff40c12SJohn Marino *len = 32;
2153ff40c12SJohn Marino os_free(ctx);
2163ff40c12SJohn Marino return -1;
2173ff40c12SJohn Marino }
2183ff40c12SJohn Marino *len = 32;
2193ff40c12SJohn Marino sha256_done(&ctx->u.sha256, mac);
2203ff40c12SJohn Marino break;
2213ff40c12SJohn Marino #endif /* CONFIG_SHA256 */
222*a1157835SDaniel Fojt #ifdef CONFIG_INTERNAL_SHA384
223*a1157835SDaniel Fojt case CRYPTO_HASH_ALG_SHA384:
224*a1157835SDaniel Fojt if (*len < 48) {
225*a1157835SDaniel Fojt *len = 48;
226*a1157835SDaniel Fojt os_free(ctx);
227*a1157835SDaniel Fojt return -1;
228*a1157835SDaniel Fojt }
229*a1157835SDaniel Fojt *len = 48;
230*a1157835SDaniel Fojt sha384_done(&ctx->u.sha384, mac);
231*a1157835SDaniel Fojt break;
232*a1157835SDaniel Fojt #endif /* CONFIG_INTERNAL_SHA384 */
233*a1157835SDaniel Fojt #ifdef CONFIG_INTERNAL_SHA512
234*a1157835SDaniel Fojt case CRYPTO_HASH_ALG_SHA512:
235*a1157835SDaniel Fojt if (*len < 64) {
236*a1157835SDaniel Fojt *len = 64;
237*a1157835SDaniel Fojt os_free(ctx);
238*a1157835SDaniel Fojt return -1;
239*a1157835SDaniel Fojt }
240*a1157835SDaniel Fojt *len = 64;
241*a1157835SDaniel Fojt sha512_done(&ctx->u.sha512, mac);
242*a1157835SDaniel Fojt break;
243*a1157835SDaniel Fojt #endif /* CONFIG_INTERNAL_SHA512 */
2446d49e1aeSJan Lentfer case CRYPTO_HASH_ALG_HMAC_MD5:
2456d49e1aeSJan Lentfer if (*len < 16) {
2466d49e1aeSJan Lentfer *len = 16;
2476d49e1aeSJan Lentfer os_free(ctx);
2486d49e1aeSJan Lentfer return -1;
2496d49e1aeSJan Lentfer }
2506d49e1aeSJan Lentfer *len = 16;
2516d49e1aeSJan Lentfer
2526d49e1aeSJan Lentfer MD5Final(mac, &ctx->u.md5);
2536d49e1aeSJan Lentfer
2546d49e1aeSJan Lentfer os_memcpy(k_pad, ctx->key, ctx->key_len);
2556d49e1aeSJan Lentfer os_memset(k_pad + ctx->key_len, 0,
2566d49e1aeSJan Lentfer sizeof(k_pad) - ctx->key_len);
2576d49e1aeSJan Lentfer for (i = 0; i < sizeof(k_pad); i++)
2586d49e1aeSJan Lentfer k_pad[i] ^= 0x5c;
2596d49e1aeSJan Lentfer MD5Init(&ctx->u.md5);
2606d49e1aeSJan Lentfer MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
2616d49e1aeSJan Lentfer MD5Update(&ctx->u.md5, mac, 16);
2626d49e1aeSJan Lentfer MD5Final(mac, &ctx->u.md5);
2636d49e1aeSJan Lentfer break;
2646d49e1aeSJan Lentfer case CRYPTO_HASH_ALG_HMAC_SHA1:
2656d49e1aeSJan Lentfer if (*len < 20) {
2666d49e1aeSJan Lentfer *len = 20;
2676d49e1aeSJan Lentfer os_free(ctx);
2686d49e1aeSJan Lentfer return -1;
2696d49e1aeSJan Lentfer }
2706d49e1aeSJan Lentfer *len = 20;
2716d49e1aeSJan Lentfer
2726d49e1aeSJan Lentfer SHA1Final(mac, &ctx->u.sha1);
2736d49e1aeSJan Lentfer
2746d49e1aeSJan Lentfer os_memcpy(k_pad, ctx->key, ctx->key_len);
2756d49e1aeSJan Lentfer os_memset(k_pad + ctx->key_len, 0,
2766d49e1aeSJan Lentfer sizeof(k_pad) - ctx->key_len);
2776d49e1aeSJan Lentfer for (i = 0; i < sizeof(k_pad); i++)
2786d49e1aeSJan Lentfer k_pad[i] ^= 0x5c;
2796d49e1aeSJan Lentfer SHA1Init(&ctx->u.sha1);
2806d49e1aeSJan Lentfer SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
2816d49e1aeSJan Lentfer SHA1Update(&ctx->u.sha1, mac, 20);
2826d49e1aeSJan Lentfer SHA1Final(mac, &ctx->u.sha1);
2836d49e1aeSJan Lentfer break;
2843ff40c12SJohn Marino #ifdef CONFIG_SHA256
2853ff40c12SJohn Marino case CRYPTO_HASH_ALG_HMAC_SHA256:
2863ff40c12SJohn Marino if (*len < 32) {
2873ff40c12SJohn Marino *len = 32;
2886d49e1aeSJan Lentfer os_free(ctx);
2893ff40c12SJohn Marino return -1;
2906d49e1aeSJan Lentfer }
2913ff40c12SJohn Marino *len = 32;
2926d49e1aeSJan Lentfer
2933ff40c12SJohn Marino sha256_done(&ctx->u.sha256, mac);
2946d49e1aeSJan Lentfer
2953ff40c12SJohn Marino os_memcpy(k_pad, ctx->key, ctx->key_len);
2963ff40c12SJohn Marino os_memset(k_pad + ctx->key_len, 0,
2973ff40c12SJohn Marino sizeof(k_pad) - ctx->key_len);
2983ff40c12SJohn Marino for (i = 0; i < sizeof(k_pad); i++)
2993ff40c12SJohn Marino k_pad[i] ^= 0x5c;
3003ff40c12SJohn Marino sha256_init(&ctx->u.sha256);
3013ff40c12SJohn Marino sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
3023ff40c12SJohn Marino sha256_process(&ctx->u.sha256, mac, 32);
3033ff40c12SJohn Marino sha256_done(&ctx->u.sha256, mac);
3046d49e1aeSJan Lentfer break;
3053ff40c12SJohn Marino #endif /* CONFIG_SHA256 */
3066d49e1aeSJan Lentfer default:
3076d49e1aeSJan Lentfer os_free(ctx);
3086d49e1aeSJan Lentfer return -1;
3096d49e1aeSJan Lentfer }
3106d49e1aeSJan Lentfer
3116d49e1aeSJan Lentfer os_free(ctx);
3126d49e1aeSJan Lentfer
313*a1157835SDaniel Fojt if (TEST_FAIL())
314*a1157835SDaniel Fojt return -1;
315*a1157835SDaniel Fojt
3166d49e1aeSJan Lentfer return 0;
3176d49e1aeSJan Lentfer }
3186d49e1aeSJan Lentfer
3196d49e1aeSJan Lentfer
crypto_global_init(void)3206d49e1aeSJan Lentfer int crypto_global_init(void)
3216d49e1aeSJan Lentfer {
3226d49e1aeSJan Lentfer return 0;
3236d49e1aeSJan Lentfer }
3246d49e1aeSJan Lentfer
3256d49e1aeSJan Lentfer
crypto_global_deinit(void)3266d49e1aeSJan Lentfer void crypto_global_deinit(void)
3276d49e1aeSJan Lentfer {
3286d49e1aeSJan Lentfer }
329