Update to new version 0.8.16 from BRCM

Sync with main tree commit b8349523e460493fa0b4de36c689595109e45e91
Author: Neeraj Kumar Garg <neerajkg@broadcom.com>
Date:   Tue Dec 27 23:21:45 2011 +0200
    P2P: Reject p2p_group_add if forced frequency is not acceptable

Change-Id: Icb4541a371b05c270e80440d7a7fdea7f33ff61e
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/crypto/crypto_internal.c b/src/crypto/crypto_internal.c
index 8fdba65..9362fe1 100644
--- a/src/crypto/crypto_internal.c
+++ b/src/crypto/crypto_internal.c
@@ -1,6 +1,6 @@
 /*
  * 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
@@ -16,6 +16,7 @@
 
 #include "common.h"
 #include "crypto.h"
+#include "sha256_i.h"
 #include "sha1_i.h"
 #include "md5_i.h"
 
@@ -24,6 +25,9 @@
 	union {
 		struct MD5Context md5;
 		struct SHA1Context sha1;
+#ifdef CONFIG_SHA256
+		struct sha256_state sha256;
+#endif /* CONFIG_SHA256 */
 	} u;
 	u8 key[64];
 	size_t key_len;
@@ -35,7 +39,7 @@
 {
 	struct crypto_hash *ctx;
 	u8 k_pad[64];
-	u8 tk[20];
+	u8 tk[32];
 	size_t i;
 
 	ctx = os_zalloc(sizeof(*ctx));
@@ -51,6 +55,11 @@
 	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 */
 	case CRYPTO_HASH_ALG_HMAC_MD5:
 		if (key_len > sizeof(k_pad)) {
 			MD5Init(&ctx->u.md5);
@@ -63,7 +72,8 @@
 		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);
@@ -81,12 +91,34 @@
 		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;
@@ -110,6 +142,14 @@
 	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 */
+	default:
+		break;
 	}
 }
 
@@ -146,6 +186,17 @@
 		*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 */
 	case CRYPTO_HASH_ALG_HMAC_MD5:
 		if (*len < 16) {
 			*len = 16;
@@ -186,6 +237,31 @@
 		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);