wpa_supplicant: Initial Revision 0.8.X

Based on:
commit 0725cc7b7efc434910e89865c42eda7ce61bbf08
Author: Jouni Malinen <j@w1.fi>
Date:   Thu Apr 21 20:41:01 2011 +0300

    Enable CONFIG_DRIVER_NL80211=y in the default configuration

    nl80211 should be preferred over WEXT with any recent Linux
    kernel version.

Change-Id: I26aec5afbbd4f4a1f5fd900912545b6f5050de64
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/crypto/crypto_internal.c b/src/crypto/crypto_internal.c
new file mode 100644
index 0000000..8fdba65
--- /dev/null
+++ b/src/crypto/crypto_internal.c
@@ -0,0 +1,205 @@
+/*
+ * Crypto wrapper for internal crypto implementation
+ * Copyright (c) 2006-2009, 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.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "crypto.h"
+#include "sha1_i.h"
+#include "md5_i.h"
+
+struct crypto_hash {
+	enum crypto_hash_alg alg;
+	union {
+		struct MD5Context md5;
+		struct SHA1Context sha1;
+	} u;
+	u8 key[64];
+	size_t key_len;
+};
+
+
+struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
+				      size_t key_len)
+{
+	struct crypto_hash *ctx;
+	u8 k_pad[64];
+	u8 tk[20];
+	size_t i;
+
+	ctx = os_zalloc(sizeof(*ctx));
+	if (ctx == NULL)
+		return NULL;
+
+	ctx->alg = alg;
+
+	switch (alg) {
+	case CRYPTO_HASH_ALG_MD5:
+		MD5Init(&ctx->u.md5);
+		break;
+	case CRYPTO_HASH_ALG_SHA1:
+		SHA1Init(&ctx->u.sha1);
+		break;
+	case CRYPTO_HASH_ALG_HMAC_MD5:
+		if (key_len > sizeof(k_pad)) {
+			MD5Init(&ctx->u.md5);
+			MD5Update(&ctx->u.md5, key, key_len);
+			MD5Final(tk, &ctx->u.md5);
+			key = tk;
+			key_len = 16;
+		}
+		os_memcpy(ctx->key, key, key_len);
+		ctx->key_len = key_len;
+
+		os_memcpy(k_pad, key, key_len);
+		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);
+		MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
+		break;
+	case CRYPTO_HASH_ALG_HMAC_SHA1:
+		if (key_len > sizeof(k_pad)) {
+			SHA1Init(&ctx->u.sha1);
+			SHA1Update(&ctx->u.sha1, key, key_len);
+			SHA1Final(tk, &ctx->u.sha1);
+			key = tk;
+			key_len = 20;
+		}
+		os_memcpy(ctx->key, key, key_len);
+		ctx->key_len = key_len;
+
+		os_memcpy(k_pad, key, key_len);
+		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;
+	default:
+		os_free(ctx);
+		return NULL;
+	}
+
+	return ctx;
+}
+
+
+void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
+{
+	if (ctx == NULL)
+		return;
+
+	switch (ctx->alg) {
+	case CRYPTO_HASH_ALG_MD5:
+	case CRYPTO_HASH_ALG_HMAC_MD5:
+		MD5Update(&ctx->u.md5, data, len);
+		break;
+	case CRYPTO_HASH_ALG_SHA1:
+	case CRYPTO_HASH_ALG_HMAC_SHA1:
+		SHA1Update(&ctx->u.sha1, data, len);
+		break;
+	}
+}
+
+
+int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
+{
+	u8 k_pad[64];
+	size_t i;
+
+	if (ctx == NULL)
+		return -2;
+
+	if (mac == NULL || len == NULL) {
+		os_free(ctx);
+		return 0;
+	}
+
+	switch (ctx->alg) {
+	case CRYPTO_HASH_ALG_MD5:
+		if (*len < 16) {
+			*len = 16;
+			os_free(ctx);
+			return -1;
+		}
+		*len = 16;
+		MD5Final(mac, &ctx->u.md5);
+		break;
+	case CRYPTO_HASH_ALG_SHA1:
+		if (*len < 20) {
+			*len = 20;
+			os_free(ctx);
+			return -1;
+		}
+		*len = 20;
+		SHA1Final(mac, &ctx->u.sha1);
+		break;
+	case CRYPTO_HASH_ALG_HMAC_MD5:
+		if (*len < 16) {
+			*len = 16;
+			os_free(ctx);
+			return -1;
+		}
+		*len = 16;
+
+		MD5Final(mac, &ctx->u.md5);
+
+		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;
+		MD5Init(&ctx->u.md5);
+		MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
+		MD5Update(&ctx->u.md5, mac, 16);
+		MD5Final(mac, &ctx->u.md5);
+		break;
+	case CRYPTO_HASH_ALG_HMAC_SHA1:
+		if (*len < 20) {
+			*len = 20;
+			os_free(ctx);
+			return -1;
+		}
+		*len = 20;
+
+		SHA1Final(mac, &ctx->u.sha1);
+
+		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;
+		SHA1Init(&ctx->u.sha1);
+		SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
+		SHA1Update(&ctx->u.sha1, mac, 20);
+		SHA1Final(mac, &ctx->u.sha1);
+		break;
+	}
+
+	os_free(ctx);
+
+	return 0;
+}
+
+
+int crypto_global_init(void)
+{
+	return 0;
+}
+
+
+void crypto_global_deinit(void)
+{
+}