/*
* Crypto wrapper for internal crypto implementation
- * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "crypto.h"
+#include "sha256_i.h"
+#include "sha384_i.h"
+#include "sha512_i.h"
#include "sha1_i.h"
#include "md5_i.h"
union {
struct MD5Context md5;
struct SHA1Context sha1;
+#ifdef CONFIG_SHA256
+ struct sha256_state sha256;
+#endif /* CONFIG_SHA256 */
+#ifdef CONFIG_INTERNAL_SHA384
+ struct sha384_state sha384;
+#endif /* CONFIG_INTERNAL_SHA384 */
+#ifdef CONFIG_INTERNAL_SHA512
+ struct sha512_state sha512;
+#endif /* CONFIG_INTERNAL_SHA512 */
} u;
u8 key[64];
size_t key_len;
{
struct crypto_hash *ctx;
u8 k_pad[64];
- u8 tk[20];
+ u8 tk[32];
size_t i;
ctx = os_zalloc(sizeof(*ctx));
case CRYPTO_HASH_ALG_SHA1:
SHA1Init(&ctx->u.sha1);
break;
+#ifdef CONFIG_SHA256
+ case CRYPTO_HASH_ALG_SHA256:
+ sha256_init(&ctx->u.sha256);
+ break;
+#endif /* CONFIG_SHA256 */
+#ifdef CONFIG_INTERNAL_SHA384
+ case CRYPTO_HASH_ALG_SHA384:
+ sha384_init(&ctx->u.sha384);
+ break;
+#endif /* CONFIG_INTERNAL_SHA384 */
+#ifdef CONFIG_INTERNAL_SHA512
+ case CRYPTO_HASH_ALG_SHA512:
+ sha512_init(&ctx->u.sha512);
+ break;
+#endif /* CONFIG_INTERNAL_SHA512 */
case CRYPTO_HASH_ALG_HMAC_MD5:
if (key_len > sizeof(k_pad)) {
MD5Init(&ctx->u.md5);
ctx->key_len = key_len;
os_memcpy(k_pad, key, key_len);
- os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
+ if (key_len < sizeof(k_pad))
+ os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
for (i = 0; i < sizeof(k_pad); i++)
k_pad[i] ^= 0x36;
MD5Init(&ctx->u.md5);
ctx->key_len = key_len;
os_memcpy(k_pad, key, key_len);
- os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
+ if (key_len < sizeof(k_pad))
+ os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
for (i = 0; i < sizeof(k_pad); i++)
k_pad[i] ^= 0x36;
SHA1Init(&ctx->u.sha1);
SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
break;
+#ifdef CONFIG_SHA256
+ case CRYPTO_HASH_ALG_HMAC_SHA256:
+ if (key_len > sizeof(k_pad)) {
+ sha256_init(&ctx->u.sha256);
+ sha256_process(&ctx->u.sha256, key, key_len);
+ sha256_done(&ctx->u.sha256, tk);
+ key = tk;
+ key_len = 32;
+ }
+ os_memcpy(ctx->key, key, key_len);
+ ctx->key_len = key_len;
+
+ os_memcpy(k_pad, key, key_len);
+ if (key_len < sizeof(k_pad))
+ os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
+ for (i = 0; i < sizeof(k_pad); i++)
+ k_pad[i] ^= 0x36;
+ sha256_init(&ctx->u.sha256);
+ sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
+ break;
+#endif /* CONFIG_SHA256 */
default:
os_free(ctx);
return NULL;
case CRYPTO_HASH_ALG_HMAC_SHA1:
SHA1Update(&ctx->u.sha1, data, len);
break;
+#ifdef CONFIG_SHA256
+ case CRYPTO_HASH_ALG_SHA256:
+ case CRYPTO_HASH_ALG_HMAC_SHA256:
+ sha256_process(&ctx->u.sha256, data, len);
+ break;
+#endif /* CONFIG_SHA256 */
+#ifdef CONFIG_INTERNAL_SHA384
+ case CRYPTO_HASH_ALG_SHA384:
+ sha384_process(&ctx->u.sha384, data, len);
+ break;
+#endif /* CONFIG_INTERNAL_SHA384 */
+#ifdef CONFIG_INTERNAL_SHA512
+ case CRYPTO_HASH_ALG_SHA512:
+ sha512_process(&ctx->u.sha512, data, len);
+ break;
+#endif /* CONFIG_INTERNAL_SHA512 */
+ default:
+ break;
}
}
*len = 20;
SHA1Final(mac, &ctx->u.sha1);
break;
+#ifdef CONFIG_SHA256
+ case CRYPTO_HASH_ALG_SHA256:
+ if (*len < 32) {
+ *len = 32;
+ os_free(ctx);
+ return -1;
+ }
+ *len = 32;
+ sha256_done(&ctx->u.sha256, mac);
+ break;
+#endif /* CONFIG_SHA256 */
+#ifdef CONFIG_INTERNAL_SHA384
+ case CRYPTO_HASH_ALG_SHA384:
+ if (*len < 48) {
+ *len = 48;
+ os_free(ctx);
+ return -1;
+ }
+ *len = 48;
+ sha384_done(&ctx->u.sha384, mac);
+ break;
+#endif /* CONFIG_INTERNAL_SHA384 */
+#ifdef CONFIG_INTERNAL_SHA512
+ case CRYPTO_HASH_ALG_SHA512:
+ if (*len < 64) {
+ *len = 64;
+ os_free(ctx);
+ return -1;
+ }
+ *len = 64;
+ sha512_done(&ctx->u.sha512, mac);
+ break;
+#endif /* CONFIG_INTERNAL_SHA512 */
case CRYPTO_HASH_ALG_HMAC_MD5:
if (*len < 16) {
*len = 16;
SHA1Update(&ctx->u.sha1, mac, 20);
SHA1Final(mac, &ctx->u.sha1);
break;
+#ifdef CONFIG_SHA256
+ case CRYPTO_HASH_ALG_HMAC_SHA256:
+ if (*len < 32) {
+ *len = 32;
+ os_free(ctx);
+ return -1;
+ }
+ *len = 32;
+
+ sha256_done(&ctx->u.sha256, mac);
+
+ os_memcpy(k_pad, ctx->key, ctx->key_len);
+ os_memset(k_pad + ctx->key_len, 0,
+ sizeof(k_pad) - ctx->key_len);
+ for (i = 0; i < sizeof(k_pad); i++)
+ k_pad[i] ^= 0x5c;
+ sha256_init(&ctx->u.sha256);
+ sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
+ sha256_process(&ctx->u.sha256, mac, 32);
+ sha256_done(&ctx->u.sha256, mac);
+ break;
+#endif /* CONFIG_SHA256 */
+ default:
+ os_free(ctx);
+ return -1;
}
os_free(ctx);