]> granicus.if.org Git - esp-idf/commitdiff
wpa_supplicant: replace pre-built crypto library with source code
authorIvan Grokhotkov <ivan@espressif.com>
Fri, 4 Nov 2016 06:12:21 +0000 (14:12 +0800)
committerIvan Grokhotkov <ivan@espressif.com>
Fri, 4 Nov 2016 06:58:47 +0000 (14:58 +0800)
92 files changed:
components/esp32/component.mk
components/wpa_supplicant/COPYING [new file with mode: 0644]
components/wpa_supplicant/component.mk [new file with mode: 0644]
components/wpa_supplicant/include/crypto/aes.h [new file with mode: 0644]
components/wpa_supplicant/include/crypto/aes_i.h [new file with mode: 0644]
components/wpa_supplicant/include/crypto/aes_wrap.h [new file with mode: 0644]
components/wpa_supplicant/include/crypto/base64.h [new file with mode: 0644]
components/wpa_supplicant/include/crypto/common.h [new file with mode: 0644]
components/wpa_supplicant/include/crypto/crypto.h [new file with mode: 0644]
components/wpa_supplicant/include/crypto/dh_group5.h [new file with mode: 0644]
components/wpa_supplicant/include/crypto/dh_groups.h [new file with mode: 0644]
components/wpa_supplicant/include/crypto/includes.h [new file with mode: 0644]
components/wpa_supplicant/include/crypto/md5.h [new file with mode: 0644]
components/wpa_supplicant/include/crypto/md5_i.h [new file with mode: 0644]
components/wpa_supplicant/include/crypto/random.h [new file with mode: 0644]
components/wpa_supplicant/include/crypto/sha1.h [new file with mode: 0644]
components/wpa_supplicant/include/crypto/sha1_i.h [new file with mode: 0644]
components/wpa_supplicant/include/crypto/sha256.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/ap_config.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/common.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/defs.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/eapol_common.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/hostapd.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/ieee80211_crypto.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/ieee802_11_defs.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/ieee802_1x.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/includes.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/list.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/sta_info.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/state_machine.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/wpa.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/wpa_auth.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/wpa_auth_i.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/wpa_auth_ie.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/wpa_common.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/wpa_debug.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/wpa_i.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/wpa_ie.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/wpabuf.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa/wpas_glue.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/eap_peer/eap.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/eap_peer/eap_common.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/eap_peer/eap_config.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/eap_peer/eap_defs.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/eap_peer/eap_i.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/eap_peer/eap_tls.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/eap_peer/eap_tls_common.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/tls/asn1.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/tls/bignum.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/tls/libtommath.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/tls/pkcs1.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/tls/pkcs5.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/tls/pkcs8.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/tls/rsa.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/tls/tls.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/tls/tlsv1_client.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/tls/tlsv1_client_i.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/tls/tlsv1_common.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/tls/tlsv1_cred.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/tls/tlsv1_record.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/tls/tlsv1_server.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/tls/tlsv1_server_i.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/tls/x509v3.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/utils/base64.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/utils/ext_password.h [new file with mode: 0644]
components/wpa_supplicant/include/wpa2/utils/ext_password_i.h [new file with mode: 0644]
components/wpa_supplicant/port/include/byteswap.h [new file with mode: 0644]
components/wpa_supplicant/port/include/endian.h [new file with mode: 0644]
components/wpa_supplicant/port/include/os.h [new file with mode: 0644]
components/wpa_supplicant/src/crypto/aes-cbc.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/aes-internal-dec.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/aes-internal-enc.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/aes-internal.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/aes-unwrap.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/aes-wrap.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/bignum.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/bignum.h [new file with mode: 0644]
components/wpa_supplicant/src/crypto/crypto_internal-cipher.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/crypto_internal-modexp.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/crypto_internal-rsa.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/crypto_internal.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/dh_group5.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/dh_groups.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/libtommath.h [new file with mode: 0644]
components/wpa_supplicant/src/crypto/md5-internal.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/md5.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/rc4.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/sha1-internal.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/sha1-pbkdf2.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/sha1.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/sha256-internal.c [new file with mode: 0644]
components/wpa_supplicant/src/crypto/sha256.c [new file with mode: 0644]

index 788f8801270ce9c09018cdd6144deace4bc078b9..e91020c3e6943d65a6adf6e7d8fcd33d6896d5b9 100644 (file)
@@ -10,7 +10,7 @@
 
 COMPONENT_SRCDIRS := . hwcrypto
 
-LIBS := crypto core net80211 phy rtc pp wpa smartconfig
+LIBS := core net80211 phy rtc pp wpa smartconfig
 
 LINKER_SCRIPTS += -T esp32_out.ld -T esp32.common.ld -T esp32.rom.ld -T esp32.peripherals.ld
 
diff --git a/components/wpa_supplicant/COPYING b/components/wpa_supplicant/COPYING
new file mode 100644 (file)
index 0000000..7efce0d
--- /dev/null
@@ -0,0 +1,22 @@
+wpa_supplicant and hostapd
+--------------------------
+
+Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi> and contributors
+All Rights Reserved.
+
+
+See the README file for the current license terms.
+
+This software was previously distributed under BSD/GPL v2 dual license
+terms that allowed either of those license alternatives to be
+selected. As of February 11, 2012, the project has chosen to use only
+the BSD license option for future distribution. As such, the GPL v2
+license option is no longer used. It should be noted that the BSD
+license option (the one with advertisement clause removed) is compatible
+with GPL and as such, does not prevent use of this software in projects
+that use GPL.
+
+Some of the files may still include pointers to GPL version 2 license
+terms. However, such copyright and license notifications are maintained
+only for attribution purposes and any distribution of this software
+after February 11, 2012 is no longer under the GPL v2 option.
diff --git a/components/wpa_supplicant/component.mk b/components/wpa_supplicant/component.mk
new file mode 100644 (file)
index 0000000..6e5d7e0
--- /dev/null
@@ -0,0 +1,6 @@
+COMPONENT_ADD_INCLUDEDIRS := include port/include
+COMPONENT_SRCDIRS := src/crypto
+
+CFLAGS += -DEMBEDDED_SUPP -D__ets__
+
+include $(IDF_PATH)/make/component_common.mk
diff --git a/components/wpa_supplicant/include/crypto/aes.h b/components/wpa_supplicant/include/crypto/aes.h
new file mode 100644 (file)
index 0000000..ba384a9
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * AES functions
+ * Copyright (c) 2003-2006, 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.
+ */
+
+#ifndef AES_H
+#define AES_H
+
+#define AES_BLOCK_SIZE 16
+
+void * aes_encrypt_init(const u8 *key, size_t len);
+void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt);
+void aes_encrypt_deinit(void *ctx);
+void * aes_decrypt_init(const u8 *key, size_t len);
+void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain);
+void aes_decrypt_deinit(void *ctx);
+
+#endif /* AES_H */
diff --git a/components/wpa_supplicant/include/crypto/aes_i.h b/components/wpa_supplicant/include/crypto/aes_i.h
new file mode 100644 (file)
index 0000000..1063422
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * AES (Rijndael) cipher
+ * Copyright (c) 2003-2005, 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.
+ */
+
+#ifndef AES_I_H
+#define AES_I_H
+
+#include "aes.h"
+
+/* #define FULL_UNROLL */
+#define AES_SMALL_TABLES
+
+extern const u32 Te0[256];
+extern const u32 Te1[256];
+extern const u32 Te2[256];
+extern const u32 Te3[256];
+extern const u32 Te4[256];
+extern const u32 Td0[256];
+extern const u32 Td1[256];
+extern const u32 Td2[256];
+extern const u32 Td3[256];
+extern const u32 Td4[256];
+extern const u32 rcon[10];
+extern const u8 Td4s[256];
+extern const u8 rcons[10];
+
+#ifndef AES_SMALL_TABLES
+
+#define RCON(i) rcon[(i)]
+
+#define TE0(i) Te0[((i) >> 24) & 0xff]
+#define TE1(i) Te1[((i) >> 16) & 0xff]
+#define TE2(i) Te2[((i) >> 8) & 0xff]
+#define TE3(i) Te3[(i) & 0xff]
+#define TE41(i) (Te4[((i) >> 24) & 0xff] & 0xff000000)
+#define TE42(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000)
+#define TE43(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00)
+#define TE44(i) (Te4[(i) & 0xff] & 0x000000ff)
+#define TE421(i) (Te4[((i) >> 16) & 0xff] & 0xff000000)
+#define TE432(i) (Te4[((i) >> 8) & 0xff] & 0x00ff0000)
+#define TE443(i) (Te4[(i) & 0xff] & 0x0000ff00)
+#define TE414(i) (Te4[((i) >> 24) & 0xff] & 0x000000ff)
+#define TE411(i) (Te4[((i) >> 24) & 0xff] & 0xff000000)
+#define TE422(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000)
+#define TE433(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00)
+#define TE444(i) (Te4[(i) & 0xff] & 0x000000ff)
+#define TE4(i) (Te4[(i)] & 0x000000ff)
+
+#define TD0(i) Td0[((i) >> 24) & 0xff]
+#define TD1(i) Td1[((i) >> 16) & 0xff]
+#define TD2(i) Td2[((i) >> 8) & 0xff]
+#define TD3(i) Td3[(i) & 0xff]
+#define TD41(i) (Td4[((i) >> 24) & 0xff] & 0xff000000)
+#define TD42(i) (Td4[((i) >> 16) & 0xff] & 0x00ff0000)
+#define TD43(i) (Td4[((i) >> 8) & 0xff] & 0x0000ff00)
+#define TD44(i) (Td4[(i) & 0xff] & 0x000000ff)
+#define TD0_(i) Td0[(i) & 0xff]
+#define TD1_(i) Td1[(i) & 0xff]
+#define TD2_(i) Td2[(i) & 0xff]
+#define TD3_(i) Td3[(i) & 0xff]
+
+#else /* AES_SMALL_TABLES */
+
+#define RCON(i) (rcons[(i)] << 24)
+
+static inline u32 rotr(u32 val, int bits)
+{
+       return (val >> bits) | (val << (32 - bits));
+}
+
+#define TE0(i) Te0[((i) >> 24) & 0xff]
+#define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8)
+#define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16)
+#define TE3(i) rotr(Te0[(i) & 0xff], 24)
+#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000)
+#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000)
+#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00)
+#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff)
+#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000)
+#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000)
+#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00)
+#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff)
+#define TE411(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000)
+#define TE422(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000)
+#define TE433(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00)
+#define TE444(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff)
+#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff)
+
+#define TD0(i) Td0[((i) >> 24) & 0xff]
+#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8)
+#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16)
+#define TD3(i) rotr(Td0[(i) & 0xff], 24)
+#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24)
+#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16)
+#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8)
+#define TD44(i) (Td4s[(i) & 0xff])
+#define TD0_(i) Td0[(i) & 0xff]
+#define TD1_(i) rotr(Td0[(i) & 0xff], 8)
+#define TD2_(i) rotr(Td0[(i) & 0xff], 16)
+#define TD3_(i) rotr(Td0[(i) & 0xff], 24)
+
+#endif /* AES_SMALL_TABLES */
+
+#ifdef _MSC_VER
+#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
+#define GETU32(p) SWAP(*((u32 *)(p)))
+#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
+#else
+#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \
+((u32)(pt)[2] <<  8) ^ ((u32)(pt)[3]))
+#define PUTU32(ct, st) { \
+(ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \
+(ct)[2] = (u8)((st) >>  8); (ct)[3] = (u8)(st); }
+#endif
+
+#define AES_PRIV_SIZE (4 * 4 * 15 + 4)
+#define AES_PRIV_NR_POS (4 * 15)
+
+int rijndaelKeySetupEnc(u32 rk[], const u8 cipherKey[], int keyBits);
+
+#endif /* AES_I_H */
diff --git a/components/wpa_supplicant/include/crypto/aes_wrap.h b/components/wpa_supplicant/include/crypto/aes_wrap.h
new file mode 100644 (file)
index 0000000..4b1c7b0
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * AES-based functions
+ *
+ * - AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * - One-Key CBC MAC (OMAC1) hash with AES-128
+ * - AES-128 CTR mode encryption
+ * - AES-128 EAX mode encryption/decryption
+ * - AES-128 CBC
+ *
+ * Copyright (c) 2003-2007, 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.
+ */
+
+#ifndef AES_WRAP_H
+#define AES_WRAP_H
+
+int __must_check aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher);
+int __must_check aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain);
+int __must_check omac1_aes_128_vector(const u8 *key, size_t num_elem,
+                                     const u8 *addr[], const size_t *len,
+                                     u8 *mac);
+int __must_check omac1_aes_128(const u8 *key, const u8 *data, size_t data_len,
+                              u8 *mac);
+int __must_check aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out);
+int __must_check aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
+                                    u8 *data, size_t data_len);
+int __must_check aes_128_eax_encrypt(const u8 *key,
+                                    const u8 *nonce, size_t nonce_len,
+                                    const u8 *hdr, size_t hdr_len,
+                                    u8 *data, size_t data_len, u8 *tag);
+int __must_check aes_128_eax_decrypt(const u8 *key,
+                                    const u8 *nonce, size_t nonce_len,
+                                    const u8 *hdr, size_t hdr_len,
+                                    u8 *data, size_t data_len, const u8 *tag);
+int __must_check aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data,
+                                    size_t data_len);
+int __must_check aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data,
+                                    size_t data_len);
+
+#endif /* AES_WRAP_H */
diff --git a/components/wpa_supplicant/include/crypto/base64.h b/components/wpa_supplicant/include/crypto/base64.h
new file mode 100644 (file)
index 0000000..b87a168
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Base64 encoding/decoding (RFC1341)
+ * Copyright (c) 2005, 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.
+ */
+
+#ifndef BASE64_H
+#define BASE64_H
+
+unsigned char * base64_encode(const unsigned char *src, size_t len,
+                             size_t *out_len);
+unsigned char * base64_decode(const unsigned char *src, size_t len,
+                             size_t *out_len);
+
+#endif /* BASE64_H */
diff --git a/components/wpa_supplicant/include/crypto/common.h b/components/wpa_supplicant/include/crypto/common.h
new file mode 100644 (file)
index 0000000..319b861
--- /dev/null
@@ -0,0 +1,481 @@
+/*
+ * wpa_supplicant/hostapd / common helper functions, etc.
+ * Copyright (c) 2002-2007, 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.
+ */
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#include "os.h"
+
+#if defined(__XTENSA__)
+#include <machine/endian.h>
+#define __BYTE_ORDER     BYTE_ORDER
+#define __LITTLE_ENDIAN  LITTLE_ENDIAN
+#define __BIG_ENDIAN     BIG_ENDIAN
+#endif /*__XTENSA__*/
+
+#if defined(__linux__) || defined(__GLIBC__)
+#include <endian.h>
+#include <byteswap.h>
+#endif /* __linux__ */
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \
+    defined(__OpenBSD__)
+#include <sys/types.h>
+#include <sys/endian.h>
+#define __BYTE_ORDER   _BYTE_ORDER
+#define        __LITTLE_ENDIAN _LITTLE_ENDIAN
+#define        __BIG_ENDIAN    _BIG_ENDIAN
+#ifdef __OpenBSD__
+#define bswap_16 swap16
+#define bswap_32 swap32
+#define bswap_64 swap64
+#else /* __OpenBSD__ */
+#define bswap_16 bswap16
+#define bswap_32 bswap32
+#define bswap_64 bswap64
+#endif /* __OpenBSD__ */
+#endif /* defined(__FreeBSD__) || defined(__NetBSD__) ||
+       * defined(__DragonFly__) || defined(__OpenBSD__) */
+
+#ifdef __APPLE__
+#include <sys/types.h>
+#include <machine/endian.h>
+#define __BYTE_ORDER   _BYTE_ORDER
+#define __LITTLE_ENDIAN        _LITTLE_ENDIAN
+#define __BIG_ENDIAN   _BIG_ENDIAN
+static inline unsigned short bswap_16(unsigned short v)
+{
+       return ((v & 0xff) << 8) | (v >> 8);
+}
+
+static inline unsigned int bswap_32(unsigned int v)
+{
+       return ((v & 0xff) << 24) | ((v & 0xff00) << 8) |
+               ((v & 0xff0000) >> 8) | (v >> 24);
+}
+#endif /* __APPLE__ */
+
+#ifdef CONFIG_TI_COMPILER
+#define __BIG_ENDIAN 4321
+#define __LITTLE_ENDIAN 1234
+#ifdef __big_endian__
+#define __BYTE_ORDER __BIG_ENDIAN
+#else
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
+#endif /* CONFIG_TI_COMPILER */
+
+#ifdef __SYMBIAN32__
+#define __BIG_ENDIAN 4321
+#define __LITTLE_ENDIAN 1234
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#endif /* __SYMBIAN32__ */
+
+#ifdef CONFIG_NATIVE_WINDOWS
+#include <winsock.h>
+
+typedef int socklen_t;
+
+#ifndef MSG_DONTWAIT
+#define MSG_DONTWAIT 0 /* not supported */
+#endif
+
+#endif /* CONFIG_NATIVE_WINDOWS */
+
+#ifdef _MSC_VER
+#define inline __inline
+
+#undef vsnprintf
+#define vsnprintf _vsnprintf
+#undef close
+#define close closesocket
+#endif /* _MSC_VER */
+
+
+/* Define platform specific integer types */
+
+#ifdef _MSC_VER
+typedef UINT64 u64;
+typedef UINT32 u32;
+typedef UINT16 u16;
+typedef UINT8 u8;
+typedef INT64 s64;
+typedef INT32 s32;
+typedef INT16 s16;
+typedef INT8 s8;
+#define WPA_TYPES_DEFINED
+#endif /* _MSC_VER */
+
+#ifdef __vxworks
+typedef unsigned long long u64;
+typedef UINT32 u32;
+typedef UINT16 u16;
+typedef UINT8 u8;
+typedef long long s64;
+typedef INT32 s32;
+typedef INT16 s16;
+typedef INT8 s8;
+#define WPA_TYPES_DEFINED
+#endif /* __vxworks */
+
+#ifdef CONFIG_TI_COMPILER
+#ifdef _LLONG_AVAILABLE
+typedef unsigned long long u64;
+#else
+/*
+ * TODO: 64-bit variable not available. Using long as a workaround to test the
+ * build, but this will likely not work for all operations.
+ */
+typedef unsigned long u64;
+#endif
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+#define WPA_TYPES_DEFINED
+#endif /* CONFIG_TI_COMPILER */
+
+#ifdef __SYMBIAN32__
+#define __REMOVE_PLATSEC_DIAGNOSTICS__
+#include <e32def.h>
+typedef TUint64 u64;
+typedef TUint32 u32;
+typedef TUint16 u16;
+typedef TUint8 u8;
+#define WPA_TYPES_DEFINED
+#endif /* __SYMBIAN32__ */
+
+#ifndef WPA_TYPES_DEFINED
+#ifdef CONFIG_USE_INTTYPES_H
+#include <inttypes.h>
+#else
+#include <stdint.h>
+#endif
+
+typedef uint64_t u64;
+typedef uint32_t u32;
+typedef uint16_t u16;
+typedef uint8_t u8;
+typedef int64_t s64;
+typedef int32_t s32;
+typedef int16_t s16;
+typedef int8_t s8;
+#define WPA_TYPES_DEFINED
+#endif /* !WPA_TYPES_DEFINED */
+
+
+/* Define platform specific byte swapping macros */
+
+#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
+
+static inline unsigned short wpa_swap_16(unsigned short v)
+{
+       return ((v & 0xff) << 8) | (v >> 8);
+}
+
+static inline unsigned int wpa_swap_32(unsigned int v)
+{
+       return ((v & 0xff) << 24) | ((v & 0xff00) << 8) |
+               ((v & 0xff0000) >> 8) | (v >> 24);
+}
+
+#define le_to_host16(n) (n)
+#define host_to_le16(n) (n)
+#define be_to_host16(n) wpa_swap_16(n)
+#define host_to_be16(n) wpa_swap_16(n)
+#define le_to_host32(n) (n)
+#define be_to_host32(n) wpa_swap_32(n)
+#define host_to_be32(n) wpa_swap_32(n)
+
+#define WPA_BYTE_SWAP_DEFINED
+
+#endif /* __CYGWIN__ || CONFIG_NATIVE_WINDOWS */
+
+
+#ifndef WPA_BYTE_SWAP_DEFINED
+
+#ifndef __BYTE_ORDER
+#ifndef __LITTLE_ENDIAN
+#ifndef __BIG_ENDIAN
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#if defined(sparc)
+#define __BYTE_ORDER __BIG_ENDIAN
+#endif
+#endif /* __BIG_ENDIAN */
+#endif /* __LITTLE_ENDIAN */
+#endif /* __BYTE_ORDER */
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define le_to_host16(n) ((__force u16) (le16) (n))
+#define host_to_le16(n) ((__force le16) (u16) (n))
+#define be_to_host16(n) bswap_16((__force u16) (be16) (n))
+#define host_to_be16(n) ((__force be16) bswap_16((n)))
+#define le_to_host32(n) ((__force u32) (le32) (n))
+#define host_to_le32(n) ((__force le32) (u32) (n))
+#define be_to_host32(n) bswap_32((__force u32) (be32) (n))
+#define host_to_be32(n) ((__force be32) bswap_32((n)))
+#define le_to_host64(n) ((__force u64) (le64) (n))
+#define host_to_le64(n) ((__force le64) (u64) (n))
+#define be_to_host64(n) bswap_64((__force u64) (be64) (n))
+#define host_to_be64(n) ((__force be64) bswap_64((n)))
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define le_to_host16(n) bswap_16(n)
+#define host_to_le16(n) bswap_16(n)
+#define be_to_host16(n) (n)
+#define host_to_be16(n) (n)
+#define le_to_host32(n) bswap_32(n)
+#define be_to_host32(n) (n)
+#define host_to_be32(n) (n)
+#define le_to_host64(n) bswap_64(n)
+#define host_to_le64(n) bswap_64(n)
+#define be_to_host64(n) (n)
+#define host_to_be64(n) (n)
+#ifndef WORDS_BIGENDIAN
+#define WORDS_BIGENDIAN
+#endif
+#else
+#error Could not determine CPU byte order
+#endif
+
+#define WPA_BYTE_SWAP_DEFINED
+#endif /* !WPA_BYTE_SWAP_DEFINED */
+
+
+/* Macros for handling unaligned memory accesses */
+
+#define WPA_GET_BE16(a) ((u16) (((a)[0] << 8) | (a)[1]))
+#define WPA_PUT_BE16(a, val)                   \
+       do {                                    \
+               (a)[0] = ((u16) (val)) >> 8;    \
+               (a)[1] = ((u16) (val)) & 0xff;  \
+       } while (0)
+
+#define WPA_GET_LE16(a) ((u16) (((a)[1] << 8) | (a)[0]))
+#define WPA_PUT_LE16(a, val)                   \
+       do {                                    \
+               (a)[1] = ((u16) (val)) >> 8;    \
+               (a)[0] = ((u16) (val)) & 0xff;  \
+       } while (0)
+
+#define WPA_GET_BE24(a) ((((u32) (a)[0]) << 16) | (((u32) (a)[1]) << 8) | \
+                        ((u32) (a)[2]))
+#define WPA_PUT_BE24(a, val)                                   \
+       do {                                                    \
+               (a)[0] = (u8) ((((u32) (val)) >> 16) & 0xff);   \
+               (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff);    \
+               (a)[2] = (u8) (((u32) (val)) & 0xff);           \
+       } while (0)
+
+#define WPA_GET_BE32(a) ((((u32) (a)[0]) << 24) | (((u32) (a)[1]) << 16) | \
+                        (((u32) (a)[2]) << 8) | ((u32) (a)[3]))
+#define WPA_PUT_BE32(a, val)                                   \
+       do {                                                    \
+               (a)[0] = (u8) ((((u32) (val)) >> 24) & 0xff);   \
+               (a)[1] = (u8) ((((u32) (val)) >> 16) & 0xff);   \
+               (a)[2] = (u8) ((((u32) (val)) >> 8) & 0xff);    \
+               (a)[3] = (u8) (((u32) (val)) & 0xff);           \
+       } while (0)
+
+#define WPA_GET_LE32(a) ((((u32) (a)[3]) << 24) | (((u32) (a)[2]) << 16) | \
+                        (((u32) (a)[1]) << 8) | ((u32) (a)[0]))
+#define WPA_PUT_LE32(a, val)                                   \
+       do {                                                    \
+               (a)[3] = (u8) ((((u32) (val)) >> 24) & 0xff);   \
+               (a)[2] = (u8) ((((u32) (val)) >> 16) & 0xff);   \
+               (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff);    \
+               (a)[0] = (u8) (((u32) (val)) & 0xff);           \
+       } while (0)
+
+#define WPA_GET_BE64(a) ((((u64) (a)[0]) << 56) | (((u64) (a)[1]) << 48) | \
+                        (((u64) (a)[2]) << 40) | (((u64) (a)[3]) << 32) | \
+                        (((u64) (a)[4]) << 24) | (((u64) (a)[5]) << 16) | \
+                        (((u64) (a)[6]) << 8) | ((u64) (a)[7]))
+#define WPA_PUT_BE64(a, val)                           \
+       do {                                            \
+               (a)[0] = (u8) (((u64) (val)) >> 56);    \
+               (a)[1] = (u8) (((u64) (val)) >> 48);    \
+               (a)[2] = (u8) (((u64) (val)) >> 40);    \
+               (a)[3] = (u8) (((u64) (val)) >> 32);    \
+               (a)[4] = (u8) (((u64) (val)) >> 24);    \
+               (a)[5] = (u8) (((u64) (val)) >> 16);    \
+               (a)[6] = (u8) (((u64) (val)) >> 8);     \
+               (a)[7] = (u8) (((u64) (val)) & 0xff);   \
+       } while (0)
+
+#define WPA_GET_LE64(a) ((((u64) (a)[7]) << 56) | (((u64) (a)[6]) << 48) | \
+                        (((u64) (a)[5]) << 40) | (((u64) (a)[4]) << 32) | \
+                        (((u64) (a)[3]) << 24) | (((u64) (a)[2]) << 16) | \
+                        (((u64) (a)[1]) << 8) | ((u64) (a)[0]))
+
+
+#ifndef ETH_ALEN
+#define ETH_ALEN 6
+#endif
+#ifndef IFNAMSIZ
+#define IFNAMSIZ 16
+#endif
+#ifndef ETH_P_ALL
+#define ETH_P_ALL 0x0003
+#endif
+#ifndef ETH_P_PAE
+#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
+#endif /* ETH_P_PAE */
+#ifndef ETH_P_EAPOL
+#define ETH_P_EAPOL ETH_P_PAE
+#endif /* ETH_P_EAPOL */
+#ifndef ETH_P_RSN_PREAUTH
+#define ETH_P_RSN_PREAUTH 0x88c7
+#endif /* ETH_P_RSN_PREAUTH */
+#ifndef ETH_P_RRB
+#define ETH_P_RRB 0x890D
+#endif /* ETH_P_RRB */
+
+
+#ifdef __GNUC__
+#define PRINTF_FORMAT(a,b) __attribute__ ((format (printf, (a), (b))))
+#define STRUCT_PACKED __attribute__ ((packed))
+#else
+#define PRINTF_FORMAT(a,b)
+#define STRUCT_PACKED
+#endif
+
+#ifdef CONFIG_ANSI_C_EXTRA
+
+#if !defined(_MSC_VER) || _MSC_VER < 1400
+/* snprintf - used in number of places; sprintf() is _not_ a good replacement
+ * due to possible buffer overflow; see, e.g.,
+ * http://www.ijs.si/software/snprintf/ for portable implementation of
+ * snprintf. */
+int snprintf(char *str, size_t size, const char *format, ...);
+
+/* vsnprintf - only used for wpa_msg() in wpa_supplicant.c */
+int vsnprintf(char *str, size_t size, const char *format, va_list ap);
+#endif /* !defined(_MSC_VER) || _MSC_VER < 1400 */
+
+/* getopt - only used in main.c */
+int getopt(int argc, char *const argv[], const char *optstring);
+extern char *optarg;
+extern int optind;
+
+#ifndef CONFIG_NO_SOCKLEN_T_TYPEDEF
+#ifndef __socklen_t_defined
+typedef int socklen_t;
+#endif
+#endif
+
+/* inline - define as __inline or just define it to be empty, if needed */
+#ifdef CONFIG_NO_INLINE
+#define inline
+#else
+#define inline __inline
+#endif
+
+#ifndef __func__
+#define __func__ "__func__ not defined"
+#endif
+
+#ifndef bswap_16
+#define bswap_16(a) ((((u16) (a) << 8) & 0xff00) | (((u16) (a) >> 8) & 0xff))
+#endif
+
+#ifndef bswap_32
+#define bswap_32(a) ((((u32) (a) << 24) & 0xff000000) | \
+                    (((u32) (a) << 8) & 0xff0000) | \
+                    (((u32) (a) >> 8) & 0xff00) | \
+                    (((u32) (a) >> 24) & 0xff))
+#endif
+
+#ifndef MSG_DONTWAIT
+#define MSG_DONTWAIT 0
+#endif
+
+#ifdef _WIN32_WCE
+void perror(const char *s);
+#endif /* _WIN32_WCE */
+
+#endif /* CONFIG_ANSI_C_EXTRA */
+
+#ifndef MAC2STR
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+#endif
+
+#ifndef BIT
+#define BIT(x) (1 << (x))
+#endif
+
+/*
+ * Definitions for sparse validation
+ * (http://kernel.org/pub/linux/kernel/people/josh/sparse/)
+ */
+#ifdef __CHECKER__
+#define __force __attribute__((force))
+#define __bitwise __attribute__((bitwise))
+#else
+#define __force
+#define __bitwise
+#endif
+
+typedef u16 __bitwise be16;
+typedef u16 __bitwise le16;
+typedef u32 __bitwise be32;
+typedef u32 __bitwise le32;
+typedef u64 __bitwise be64;
+typedef u64 __bitwise le64;
+
+#ifndef __must_check
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+#define __must_check __attribute__((__warn_unused_result__))
+#else
+#define __must_check
+#endif /* __GNUC__ */
+#endif /* __must_check */
+
+int hwaddr_aton(const char *txt, u8 *addr);
+int hwaddr_aton2(const char *txt, u8 *addr);
+int hexstr2bin(const char *hex, u8 *buf, size_t len);
+void inc_byte_array(u8 *counter, size_t len);
+void wpa_get_ntp_timestamp(u8 *buf);
+int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len);
+int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
+                              size_t len);
+
+#ifdef CONFIG_NATIVE_WINDOWS
+void wpa_unicode2ascii_inplace(TCHAR *str);
+TCHAR * wpa_strdup_tchar(const char *str);
+#else /* CONFIG_NATIVE_WINDOWS */
+#define wpa_unicode2ascii_inplace(s) do { } while (0)
+#define wpa_strdup_tchar(s) strdup((s))
+#endif /* CONFIG_NATIVE_WINDOWS */
+
+const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len);
+
+static inline int is_zero_ether_addr(const u8 *a)
+{
+       return !(a[0] | a[1] | a[2] | a[3] | a[4] | a[5]);
+}
+
+/*
+ * gcc 4.4 ends up generating strict-aliasing warnings about some very common
+ * networking socket uses that do not really result in a real problem and
+ * cannot be easily avoided with union-based type-punning due to struct
+ * definitions including another struct in system header files. To avoid having
+ * to fully disable strict-aliasing warnings, provide a mechanism to hide the
+ * typecast from aliasing for now. A cleaner solution will hopefully be found
+ * in the future to handle these cases.
+ */
+void * __hide_aliasing_typecast(void *foo);
+#define aliasing_hide_typecast(a,t) (t *) __hide_aliasing_typecast((a))
+
+#endif /* COMMON_H */
diff --git a/components/wpa_supplicant/include/crypto/crypto.h b/components/wpa_supplicant/include/crypto/crypto.h
new file mode 100644 (file)
index 0000000..f0b9f22
--- /dev/null
@@ -0,0 +1,471 @@
+/*
+ * WPA Supplicant / wrapper functions for crypto libraries
+ * Copyright (c) 2004-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.
+ *
+ * This file defines the cryptographic functions that need to be implemented
+ * for wpa_supplicant and hostapd. When TLS is not used, internal
+ * implementation of MD5, SHA1, and AES is used and no external libraries are
+ * required. When TLS is enabled (e.g., by enabling EAP-TLS or EAP-PEAP), the
+ * crypto library used by the TLS implementation is expected to be used for
+ * non-TLS needs, too, in order to save space by not implementing these
+ * functions twice.
+ *
+ * Wrapper code for using each crypto library is in its own file (crypto*.c)
+ * and one of these files is build and linked in to provide the functions
+ * defined here.
+ */
+
+#ifndef CRYPTO_H
+#define CRYPTO_H
+
+/**
+ * md4_vector - MD4 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 on failure
+ */
+int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
+
+/**
+ * md5_vector - MD5 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 on failure
+ */
+int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
+
+#ifdef CONFIG_FIPS
+/**
+ * md5_vector_non_fips_allow - MD5 hash for data vector (non-FIPS use allowed)
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 on failure
+ */
+int md5_vector_non_fips_allow(size_t num_elem, const u8 *addr[],
+                             const size_t *len, u8 *mac);
+#else /* CONFIG_FIPS */
+#define md5_vector_non_fips_allow md5_vector
+#endif /* CONFIG_FIPS */
+
+
+/**
+ * sha1_vector - SHA-1 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 on failure
+ */
+int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len,
+               u8 *mac);
+
+/**
+ * fips186_2-prf - NIST FIPS Publication 186-2 change notice 1 PRF
+ * @seed: Seed/key for the PRF
+ * @seed_len: Seed length in bytes
+ * @x: Buffer for PRF output
+ * @xlen: Output length in bytes
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function implements random number generation specified in NIST FIPS
+ * Publication 186-2 for EAP-SIM. This PRF uses a function that is similar to
+ * SHA-1, but has different message padding.
+ */
+int __must_check fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x,
+                              size_t xlen);
+
+/**
+ * sha256_vector - SHA256 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 on failure
+ */
+int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
+                 u8 *mac);
+
+/**
+ * des_encrypt - Encrypt one block with DES
+ * @clear: 8 octets (in)
+ * @key: 7 octets (in) (no parity bits included)
+ * @cypher: 8 octets (out)
+ */
+void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher);
+
+/**
+ * aes_encrypt_init - Initialize AES for encryption
+ * @key: Encryption key
+ * @len: Key length in bytes (usually 16, i.e., 128 bits)
+ * Returns: Pointer to context data or %NULL on failure
+ */
+void * aes_encrypt_init(const u8 *key, size_t len);
+
+/**
+ * aes_encrypt - Encrypt one AES block
+ * @ctx: Context pointer from aes_encrypt_init()
+ * @plain: Plaintext data to be encrypted (16 bytes)
+ * @crypt: Buffer for the encrypted data (16 bytes)
+ */
+void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt);
+
+/**
+ * aes_encrypt_deinit - Deinitialize AES encryption
+ * @ctx: Context pointer from aes_encrypt_init()
+ */
+void aes_encrypt_deinit(void *ctx);
+
+/**
+ * aes_decrypt_init - Initialize AES for decryption
+ * @key: Decryption key
+ * @len: Key length in bytes (usually 16, i.e., 128 bits)
+ * Returns: Pointer to context data or %NULL on failure
+ */
+void * aes_decrypt_init(const u8 *key, size_t len);
+
+/**
+ * aes_decrypt - Decrypt one AES block
+ * @ctx: Context pointer from aes_encrypt_init()
+ * @crypt: Encrypted data (16 bytes)
+ * @plain: Buffer for the decrypted data (16 bytes)
+ */
+void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain);
+
+/**
+ * aes_decrypt_deinit - Deinitialize AES decryption
+ * @ctx: Context pointer from aes_encrypt_init()
+ */
+void aes_decrypt_deinit(void *ctx);
+
+
+enum crypto_hash_alg {
+        CRYPTO_HASH_ALG_MD5, CRYPTO_HASH_ALG_SHA1,
+        CRYPTO_HASH_ALG_HMAC_MD5, CRYPTO_HASH_ALG_HMAC_SHA1,
+        CRYPTO_HASH_ALG_SHA256, CRYPTO_HASH_ALG_HMAC_SHA256
+};
+
+
+struct crypto_hash;
+
+/**
+ * crypto_hash_init - Initialize hash/HMAC function
+ * @alg: Hash algorithm
+ * @key: Key for keyed hash (e.g., HMAC) or %NULL if not needed
+ * @key_len: Length of the key in bytes
+ * Returns: Pointer to hash context to use with other hash functions or %NULL
+ * on failure
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
+                                     size_t key_len);
+
+/**
+ * crypto_hash_update - Add data to hash calculation
+ * @ctx: Context pointer from crypto_hash_init()
+ * @data: Data buffer to add
+ * @len: Length of the buffer
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len);
+
+/**
+ * crypto_hash_finish - Complete hash calculation
+ * @ctx: Context pointer from crypto_hash_init()
+ * @hash: Buffer for hash value or %NULL if caller is just freeing the hash
+ * context
+ * @len: Pointer to length of the buffer or %NULL if caller is just freeing the
+ * hash context; on return, this is set to the actual length of the hash value
+ * Returns: 0 on success, -1 if buffer is too small (len set to needed length),
+ * or -2 on other failures (including failed crypto_hash_update() operations)
+ *
+ * This function calculates the hash value and frees the context buffer that
+ * was used for hash calculation.
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+int crypto_hash_finish(struct crypto_hash *ctx, u8 *hash, size_t *len);
+
+
+enum crypto_cipher_alg {
+       CRYPTO_CIPHER_NULL = 0, CRYPTO_CIPHER_ALG_AES, CRYPTO_CIPHER_ALG_3DES,
+       CRYPTO_CIPHER_ALG_DES, CRYPTO_CIPHER_ALG_RC2, CRYPTO_CIPHER_ALG_RC4
+};
+
+struct crypto_cipher;
+
+/**
+ * crypto_cipher_init - Initialize block/stream cipher function
+ * @alg: Cipher algorithm
+ * @iv: Initialization vector for block ciphers or %NULL for stream ciphers
+ * @key: Cipher key
+ * @key_len: Length of key in bytes
+ * Returns: Pointer to cipher context to use with other cipher functions or
+ * %NULL on failure
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
+                                         const u8 *iv, const u8 *key,
+                                         size_t key_len);
+
+/**
+ * crypto_cipher_encrypt - Cipher encrypt
+ * @ctx: Context pointer from crypto_cipher_init()
+ * @plain: Plaintext to cipher
+ * @crypt: Resulting ciphertext
+ * @len: Length of the plaintext
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+int __must_check crypto_cipher_encrypt(struct crypto_cipher *ctx,
+                                      const u8 *plain, u8 *crypt, size_t len);
+
+/**
+ * crypto_cipher_decrypt - Cipher decrypt
+ * @ctx: Context pointer from crypto_cipher_init()
+ * @crypt: Ciphertext to decrypt
+ * @plain: Resulting plaintext
+ * @len: Length of the cipher text
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+int __must_check crypto_cipher_decrypt(struct crypto_cipher *ctx,
+                                      const u8 *crypt, u8 *plain, size_t len);
+
+/**
+ * crypto_cipher_decrypt - Free cipher context
+ * @ctx: Context pointer from crypto_cipher_init()
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+void crypto_cipher_deinit(struct crypto_cipher *ctx);
+
+
+struct crypto_public_key;
+struct crypto_private_key;
+
+/**
+ * crypto_public_key_import - Import an RSA public key
+ * @key: Key buffer (DER encoded RSA public key)
+ * @len: Key buffer length in bytes
+ * Returns: Pointer to the public key or %NULL on failure
+ *
+ * This function can just return %NULL if the crypto library supports X.509
+ * parsing. In that case, crypto_public_key_from_cert() is used to import the
+ * public key from a certificate.
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len);
+
+/**
+ * crypto_private_key_import - Import an RSA private key
+ * @key: Key buffer (DER encoded RSA private key)
+ * @len: Key buffer length in bytes
+ * @passwd: Key encryption password or %NULL if key is not encrypted
+ * Returns: Pointer to the private key or %NULL on failure
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+struct crypto_private_key * crypto_private_key_import(const u8 *key,
+                                                     size_t len,
+                                                     const char *passwd);
+
+/**
+ * crypto_public_key_from_cert - Import an RSA public key from a certificate
+ * @buf: DER encoded X.509 certificate
+ * @len: Certificate buffer length in bytes
+ * Returns: Pointer to public key or %NULL on failure
+ *
+ * This function can just return %NULL if the crypto library does not support
+ * X.509 parsing. In that case, internal code will be used to parse the
+ * certificate and public key is imported using crypto_public_key_import().
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
+                                                      size_t len);
+
+/**
+ * crypto_public_key_encrypt_pkcs1_v15 - Public key encryption (PKCS #1 v1.5)
+ * @key: Public key
+ * @in: Plaintext buffer
+ * @inlen: Length of plaintext buffer in bytes
+ * @out: Output buffer for encrypted data
+ * @outlen: Length of output buffer in bytes; set to used length on success
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+int __must_check crypto_public_key_encrypt_pkcs1_v15(
+       struct crypto_public_key *key, const u8 *in, size_t inlen,
+       u8 *out, size_t *outlen);
+
+/**
+ * crypto_private_key_decrypt_pkcs1_v15 - Private key decryption (PKCS #1 v1.5)
+ * @key: Private key
+ * @in: Encrypted buffer
+ * @inlen: Length of encrypted buffer in bytes
+ * @out: Output buffer for encrypted data
+ * @outlen: Length of output buffer in bytes; set to used length on success
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+int __must_check crypto_private_key_decrypt_pkcs1_v15(
+       struct crypto_private_key *key, const u8 *in, size_t inlen,
+       u8 *out, size_t *outlen);
+
+/**
+ * crypto_private_key_sign_pkcs1 - Sign with private key (PKCS #1)
+ * @key: Private key from crypto_private_key_import()
+ * @in: Plaintext buffer
+ * @inlen: Length of plaintext buffer in bytes
+ * @out: Output buffer for encrypted (signed) data
+ * @outlen: Length of output buffer in bytes; set to used length on success
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+int __must_check crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
+                                              const u8 *in, size_t inlen,
+                                              u8 *out, size_t *outlen);
+
+/**
+ * crypto_public_key_free - Free public key
+ * @key: Public key
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+void crypto_public_key_free(struct crypto_public_key *key);
+
+/**
+ * crypto_private_key_free - Free private key
+ * @key: Private key from crypto_private_key_import()
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+void crypto_private_key_free(struct crypto_private_key *key);
+
+/**
+ * crypto_public_key_decrypt_pkcs1 - Decrypt PKCS #1 signature
+ * @key: Public key
+ * @crypt: Encrypted signature data (using the private key)
+ * @crypt_len: Encrypted signature data length
+ * @plain: Buffer for plaintext (at least crypt_len bytes)
+ * @plain_len: Plaintext length (max buffer size on input, real len on output);
+ * Returns: 0 on success, -1 on failure
+ */
+int __must_check crypto_public_key_decrypt_pkcs1(
+       struct crypto_public_key *key, const u8 *crypt, size_t crypt_len,
+       u8 *plain, size_t *plain_len);
+
+/**
+ * crypto_global_init - Initialize crypto wrapper
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+int __must_check crypto_global_init(void);
+
+/**
+ * crypto_global_deinit - Deinitialize crypto wrapper
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+void crypto_global_deinit(void);
+
+/**
+ * crypto_mod_exp - Modular exponentiation of large integers
+ * @base: Base integer (big endian byte array)
+ * @base_len: Length of base integer in bytes
+ * @power: Power integer (big endian byte array)
+ * @power_len: Length of power integer in bytes
+ * @modulus: Modulus integer (big endian byte array)
+ * @modulus_len: Length of modulus integer in bytes
+ * @result: Buffer for the result
+ * @result_len: Result length (max buffer size on input, real len on output)
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function calculates result = base ^ power mod modulus. modules_len is
+ * used as the maximum size of modulus buffer. It is set to the used size on
+ * success.
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+int __must_check crypto_mod_exp(const u8 *base, size_t base_len,
+                               const u8 *power, size_t power_len,
+                               const u8 *modulus, size_t modulus_len,
+                               u8 *result, size_t *result_len);
+
+/**
+ * rc4_skip - XOR RC4 stream to given data with skip-stream-start
+ * @key: RC4 key
+ * @keylen: RC4 key length
+ * @skip: number of bytes to skip from the beginning of the RC4 stream
+ * @data: data to be XOR'ed with RC4 stream
+ * @data_len: buf length
+ * Returns: 0 on success, -1 on failure
+ *
+ * Generate RC4 pseudo random stream for the given key, skip beginning of the
+ * stream, and XOR the end result with the data buffer to perform RC4
+ * encryption/decryption.
+ */
+int rc4_skip(const u8 *key, size_t keylen, size_t skip,
+            u8 *data, size_t data_len);
+
+#endif /* CRYPTO_H */
diff --git a/components/wpa_supplicant/include/crypto/dh_group5.h b/components/wpa_supplicant/include/crypto/dh_group5.h
new file mode 100644 (file)
index 0000000..595f111
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Diffie-Hellman group 5 operations
+ * Copyright (c) 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.
+ */
+
+#ifndef DH_GROUP5_H
+#define DH_GROUP5_H
+
+void * dh5_init(struct wpabuf **priv, struct wpabuf **publ);
+struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
+                                 const struct wpabuf *own_private);
+void dh5_free(void *ctx);
+
+#endif /* DH_GROUP5_H */
diff --git a/components/wpa_supplicant/include/crypto/dh_groups.h b/components/wpa_supplicant/include/crypto/dh_groups.h
new file mode 100644 (file)
index 0000000..5c61539
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Diffie-Hellman groups
+ * Copyright (c) 2007, 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.
+ */
+
+#ifndef DH_GROUPS_H
+#define DH_GROUPS_H
+
+struct dh_group {
+       int id;
+       const u8 *generator;
+       size_t generator_len;
+       const u8 *prime;
+       size_t prime_len;
+};
+
+const struct dh_group * dh_groups_get(int id);
+struct wpabuf * dh_init(const struct dh_group *dh, struct wpabuf **priv);
+struct wpabuf * dh_derive_shared(const struct wpabuf *peer_public,
+                                const struct wpabuf *own_private,
+                                const struct dh_group *dh);
+
+#endif /* DH_GROUPS_H */
diff --git a/components/wpa_supplicant/include/crypto/includes.h b/components/wpa_supplicant/include/crypto/includes.h
new file mode 100644 (file)
index 0000000..dbc6575
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * wpa_supplicant/hostapd - Default include files
+ * Copyright (c) 2005-2006, 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 header file is included into all C files so that commonly used header
+ * files can be selected with OS specific ifdef blocks in one place instead of
+ * having to have OS/C library specific selection in many files.
+ */
+
+#ifndef INCLUDES_H
+#define INCLUDES_H
+
+/* Include possible build time configuration before including anything else */
+//#include "build_config.h"  //don't need anymore
+#ifndef __ets__
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#ifndef _WIN32_WCE
+#ifndef CONFIG_TI_COMPILER
+#include <signal.h>
+#include <sys/types.h>
+#endif /* CONFIG_TI_COMPILER */
+#include <errno.h>
+#endif /* _WIN32_WCE */
+#include <ctype.h>
+#include <time.h>
+
+#ifndef CONFIG_TI_COMPILER
+#ifndef _MSC_VER
+#include <unistd.h>
+#endif /* _MSC_VER */
+#endif /* CONFIG_TI_COMPILER */
+
+#ifndef CONFIG_NATIVE_WINDOWS
+#ifndef CONFIG_TI_COMPILER
+//#include <sys/socket.h>
+//#include <netinet/in.h>
+//#include <arpa/inet.h>
+#ifndef __vxworks
+#ifndef __SYMBIAN32__
+//#include <sys/uio.h>
+#endif /* __SYMBIAN32__ */
+#include <sys/time.h>
+#endif /* __vxworks */
+#endif /* CONFIG_TI_COMPILER */
+#endif /* CONFIG_NATIVE_WINDOWS */
+
+#else
+
+#include "rom/ets_sys.h"
+
+#endif /* !__ets__ */
+
+#endif /* INCLUDES_H */
diff --git a/components/wpa_supplicant/include/crypto/md5.h b/components/wpa_supplicant/include/crypto/md5.h
new file mode 100644 (file)
index 0000000..8952590
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * MD5 hash implementation and interface functions
+ * Copyright (c) 2003-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.
+ */
+
+#ifndef MD5_H
+#define MD5_H
+
+#define MD5_MAC_LEN 16
+
+int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
+                   const u8 *addr[], const size_t *len, u8 *mac);
+int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
+            u8 *mac);
+#ifdef CONFIG_FIPS
+int hmac_md5_vector_non_fips_allow(const u8 *key, size_t key_len,
+                                  size_t num_elem, const u8 *addr[],
+                                  const size_t *len, u8 *mac);
+int hmac_md5_non_fips_allow(const u8 *key, size_t key_len, const u8 *data,
+                           size_t data_len, u8 *mac);
+#else /* CONFIG_FIPS */
+#define hmac_md5_vector_non_fips_allow hmac_md5_vector
+#define hmac_md5_non_fips_allow hmac_md5
+#endif /* CONFIG_FIPS */
+
+#endif /* MD5_H */
diff --git a/components/wpa_supplicant/include/crypto/md5_i.h b/components/wpa_supplicant/include/crypto/md5_i.h
new file mode 100644 (file)
index 0000000..b7f6596
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * MD5 internal definitions
+ * Copyright (c) 2003-2005, 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.
+ */
+
+#ifndef MD5_I_H
+#define MD5_I_H
+
+struct MD5Context {
+       u32 buf[4];
+       u32 bits[2];
+       u8 in[64];
+};
+
+void MD5Init(struct MD5Context *context);
+void MD5Update(struct MD5Context *context, unsigned char const *buf,
+              unsigned len);
+void MD5Final(unsigned char digest[16], struct MD5Context *context);
+
+#endif /* MD5_I_H */
diff --git a/components/wpa_supplicant/include/crypto/random.h b/components/wpa_supplicant/include/crypto/random.h
new file mode 100644 (file)
index 0000000..cbfa877
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Random number generator
+ * Copyright (c) 2010-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.
+ */
+
+#ifndef RANDOM_H
+#define RANDOM_H
+
+#define CONFIG_NO_RANDOM_POOL
+
+#ifdef CONFIG_NO_RANDOM_POOL
+#define random_init(e) do { } while (0)
+#define random_deinit() do { } while (0)
+#define random_add_randomness(b, l) do { } while (0)
+#define random_get_bytes(b, l) os_get_random((b), (l))
+#define random_pool_ready() 1
+#define random_mark_pool_ready() do { } while (0)
+#else /* CONFIG_NO_RANDOM_POOL */
+void random_init(const char *entropy_file);
+void random_deinit(void);
+void random_add_randomness(const void *buf, size_t len);
+int random_get_bytes(void *buf, size_t len);
+#endif /* CONFIG_NO_RANDOM_POOL */
+
+#endif /* RANDOM_H */
diff --git a/components/wpa_supplicant/include/crypto/sha1.h b/components/wpa_supplicant/include/crypto/sha1.h
new file mode 100644 (file)
index 0000000..b3d186b
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * SHA1 hash implementation and interface functions
+ * Copyright (c) 2003-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.
+ */
+
+#ifndef SHA1_H
+#define SHA1_H
+
+#define SHA1_MAC_LEN 20
+
+int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
+                    const u8 *addr[], const size_t *len, u8 *mac);
+int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
+              u8 *mac);
+int sha1_prf(const u8 *key, size_t key_len, const char *label,
+            const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
+int sha1_t_prf(const u8 *key, size_t key_len, const char *label,
+              const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len);
+//int __must_check tls_prf(const u8 *secret, size_t secret_len,
+//                      const char *label, const u8 *seed, size_t seed_len,
+//                      u8 *out, size_t outlen);
+int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
+               int iterations, u8 *buf, size_t buflen);
+#endif /* SHA1_H */
diff --git a/components/wpa_supplicant/include/crypto/sha1_i.h b/components/wpa_supplicant/include/crypto/sha1_i.h
new file mode 100644 (file)
index 0000000..ec2f82f
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * SHA1 internal definitions
+ * Copyright (c) 2003-2005, 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.
+ */
+
+#ifndef SHA1_I_H
+#define SHA1_I_H
+
+struct SHA1Context {
+       u32 state[5];
+       u32 count[2];
+       unsigned char buffer[64];
+};
+
+void SHA1Init(struct SHA1Context *context);
+void SHA1Update(struct SHA1Context *context, const void *data, u32 len);
+void SHA1Final(unsigned char digest[20], struct SHA1Context *context);
+void SHA1Transform(u32 state[5], const unsigned char buffer[64]);
+
+#endif /* SHA1_I_H */
diff --git a/components/wpa_supplicant/include/crypto/sha256.h b/components/wpa_supplicant/include/crypto/sha256.h
new file mode 100644 (file)
index 0000000..dc597f0
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * SHA256 hash implementation and interface functions
+ * Copyright (c) 2003-2006, 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.
+ */
+
+#ifndef SHA256_H
+#define SHA256_H
+
+#define SHA256_MAC_LEN 32
+
+void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
+                     const u8 *addr[], const size_t *len, u8 *mac);
+void hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
+                size_t data_len, u8 *mac);
+void sha256_prf(const u8 *key, size_t key_len, const char *label,
+             const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
+
+#endif /* SHA256_H */
diff --git a/components/wpa_supplicant/include/wpa/ap_config.h b/components/wpa_supplicant/include/wpa/ap_config.h
new file mode 100644 (file)
index 0000000..761becb
--- /dev/null
@@ -0,0 +1,544 @@
+/*
+ * hostapd / Configuration definitions and helpers functions
+ * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef HOSTAPD_CONFIG_H
+#define HOSTAPD_CONFIG_H
+
+#include "wpa/defs.h"
+//#include "ip_addr.h"
+#include "wpa/wpa_common.h"
+//#include "common/ieee802_11_common.h"
+//#include "wps/wps.h"
+
+#define MAX_STA_COUNT 4
+#define MAX_VLAN_ID 4094
+
+typedef u8 macaddr[ETH_ALEN];
+
+struct mac_acl_entry {
+       macaddr addr;
+       int vlan_id;
+};
+
+struct hostapd_radius_servers;
+struct ft_remote_r0kh;
+struct ft_remote_r1kh;
+
+#define HOSTAPD_MAX_SSID_LEN 32
+
+#define NUM_WEP_KEYS 4
+struct hostapd_wep_keys {
+       u8 idx;
+       u8 *key[NUM_WEP_KEYS];
+       size_t len[NUM_WEP_KEYS];
+       int keys_set;
+       size_t default_len; /* key length used for dynamic key generation */
+};
+
+typedef enum hostap_security_policy {
+       SECURITY_PLAINTEXT = 0,
+       SECURITY_STATIC_WEP = 1,
+       SECURITY_IEEE_802_1X = 2,
+       SECURITY_WPA_PSK = 3,
+       SECURITY_WPA = 4
+} secpolicy;
+
+struct hostapd_ssid {
+       u8 ssid[HOSTAPD_MAX_SSID_LEN];
+       size_t ssid_len;
+       unsigned int ssid_set:1;
+       unsigned int utf8_ssid:1;
+
+//     char vlan[IFNAMSIZ + 1];
+//     secpolicy security_policy;
+
+       struct hostapd_wpa_psk *wpa_psk;
+       char *wpa_passphrase;
+//     char *wpa_psk_file;
+
+       struct hostapd_wep_keys wep;
+
+#if 0
+#define DYNAMIC_VLAN_DISABLED 0
+#define DYNAMIC_VLAN_OPTIONAL 1
+#define DYNAMIC_VLAN_REQUIRED 2
+       int dynamic_vlan;
+#define DYNAMIC_VLAN_NAMING_WITHOUT_DEVICE 0
+#define DYNAMIC_VLAN_NAMING_WITH_DEVICE 1
+#define DYNAMIC_VLAN_NAMING_END 2
+       int vlan_naming;
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
+       char *vlan_tagged_interface;
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
+       struct hostapd_wep_keys **dyn_vlan_keys;
+       size_t max_dyn_vlan_keys;
+#endif
+};
+
+#if 0
+#define VLAN_ID_WILDCARD -1
+
+struct hostapd_vlan {
+       struct hostapd_vlan *next;
+       int vlan_id; /* VLAN ID or -1 (VLAN_ID_WILDCARD) for wildcard entry */
+       char ifname[IFNAMSIZ + 1];
+       int dynamic_vlan;
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
+
+#define DVLAN_CLEAN_BR         0x1
+#define DVLAN_CLEAN_VLAN       0x2
+#define DVLAN_CLEAN_VLAN_PORT  0x4
+#define DVLAN_CLEAN_WLAN_PORT  0x8
+       int clean;
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
+};
+#endif
+
+#define PMK_LEN 32
+struct hostapd_sta_wpa_psk_short {
+       struct hostapd_sta_wpa_psk_short *next;
+       u8 psk[PMK_LEN];
+};
+
+struct hostapd_wpa_psk {
+       struct hostapd_wpa_psk *next;
+       int group;
+       u8 psk[PMK_LEN];
+       u8 addr[ETH_ALEN];
+};
+
+#if 0
+struct hostapd_eap_user {
+       struct hostapd_eap_user *next;
+       u8 *identity;
+       size_t identity_len;
+       struct {
+               int vendor;
+               u32 method;
+       } methods[EAP_MAX_METHODS];
+       u8 *password;
+       size_t password_len;
+       int phase2;
+       int force_version;
+       unsigned int wildcard_prefix:1;
+       unsigned int password_hash:1; /* whether password is hashed with
+                                      * nt_password_hash() */
+       int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */
+};
+
+struct hostapd_radius_attr {
+       u8 type;
+       struct wpabuf *val;
+       struct hostapd_radius_attr *next;
+};
+
+
+#define NUM_TX_QUEUES 4
+
+struct hostapd_tx_queue_params {
+       int aifs;
+       int cwmin;
+       int cwmax;
+       int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */
+};
+
+
+#define MAX_ROAMING_CONSORTIUM_LEN 15
+
+struct hostapd_roaming_consortium {
+       u8 len;
+       u8 oi[MAX_ROAMING_CONSORTIUM_LEN];
+};
+
+struct hostapd_lang_string {
+       u8 lang[3];
+       u8 name_len;
+       u8 name[252];
+};
+
+#define MAX_NAI_REALMS 10
+#define MAX_NAI_REALMLEN 255
+#define MAX_NAI_EAP_METHODS 5
+#define MAX_NAI_AUTH_TYPES 4
+struct hostapd_nai_realm_data {
+       u8 encoding;
+       char realm_buf[MAX_NAI_REALMLEN + 1];
+       char *realm[MAX_NAI_REALMS];
+       u8 eap_method_count;
+       struct hostapd_nai_realm_eap {
+               u8 eap_method;
+               u8 num_auths;
+               u8 auth_id[MAX_NAI_AUTH_TYPES];
+               u8 auth_val[MAX_NAI_AUTH_TYPES];
+       } eap_method[MAX_NAI_EAP_METHODS];
+};
+#endif
+
+/**
+ * struct hostapd_bss_config - Per-BSS configuration
+ */
+struct hostapd_bss_config {
+//     char iface[IFNAMSIZ + 1];
+//     char bridge[IFNAMSIZ + 1];
+//     char wds_bridge[IFNAMSIZ + 1];
+
+//     enum hostapd_logger_level logger_syslog_level, logger_stdout_level;
+
+//     unsigned int logger_syslog; /* module bitfield */
+//     unsigned int logger_stdout; /* module bitfield */
+
+//     char *dump_log_name; /* file name for state dump (SIGUSR1) */
+
+       int max_num_sta; /* maximum number of STAs in station table */
+
+       int dtim_period;
+
+       int ieee802_1x; /* use IEEE 802.1X */
+       int eapol_version;
+//     int eap_server; /* Use internal EAP server instead of external
+//                      * RADIUS server */
+//     struct hostapd_eap_user *eap_user;
+//     char *eap_user_sqlite;
+//     char *eap_sim_db;
+//     struct hostapd_ip_addr own_ip_addr;
+//     char *nas_identifier;
+//     struct hostapd_radius_servers *radius;
+//     int acct_interim_interval;
+//     int radius_request_cui;
+//     struct hostapd_radius_attr *radius_auth_req_attr;
+//     struct hostapd_radius_attr *radius_acct_req_attr;
+//     int radius_das_port;
+//     unsigned int radius_das_time_window;
+//     int radius_das_require_event_timestamp;
+//     struct hostapd_ip_addr radius_das_client_addr;
+//     u8 *radius_das_shared_secret;
+//     size_t radius_das_shared_secret_len;
+
+       struct hostapd_ssid ssid;
+
+//     char *eap_req_id_text; /* optional displayable message sent with
+//                             * EAP Request-Identity */
+//     size_t eap_req_id_text_len;
+//     int eapol_key_index_workaround;
+
+//     size_t default_wep_key_len;
+//     int individual_wep_key_len;
+       int wep_rekeying_period;
+       int broadcast_key_idx_min, broadcast_key_idx_max;
+//     int eap_reauth_period;
+
+//     int ieee802_11f; /* use IEEE 802.11f (IAPP) */
+//     char iapp_iface[IFNAMSIZ + 1]; /* interface used with IAPP broadcast
+//                                     * frames */
+
+       enum {
+               ACCEPT_UNLESS_DENIED = 0,
+               DENY_UNLESS_ACCEPTED = 1,
+               USE_EXTERNAL_RADIUS_AUTH = 2
+       } macaddr_acl;
+//     struct mac_acl_entry *accept_mac;
+//     int num_accept_mac;
+//     struct mac_acl_entry *deny_mac;
+//     int num_deny_mac;
+//     int wds_sta;
+//     int isolate;
+
+       int auth_algs; /* bitfield of allowed IEEE 802.11 authentication
+                       * algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
+
+       int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */
+       int wpa_key_mgmt;
+#ifdef CONFIG_IEEE80211W
+       enum mfp_options ieee80211w;
+       /* dot11AssociationSAQueryMaximumTimeout (in TUs) */
+       unsigned int assoc_sa_query_max_timeout;
+       /* dot11AssociationSAQueryRetryTimeout (in TUs) */
+       int assoc_sa_query_retry_timeout;
+#endif /* CONFIG_IEEE80211W */
+       enum {
+               PSK_RADIUS_IGNORED = 0,
+               PSK_RADIUS_ACCEPTED = 1,
+               PSK_RADIUS_REQUIRED = 2
+       } wpa_psk_radius;
+       int wpa_pairwise;
+       int wpa_group;
+       int wpa_group_rekey;
+       int wpa_strict_rekey;
+       int wpa_gmk_rekey;
+       int wpa_ptk_rekey;
+       int rsn_pairwise;
+       int rsn_preauth;
+       char *rsn_preauth_interfaces;
+       int peerkey;
+
+#ifdef CONFIG_IEEE80211R
+       /* IEEE 802.11r - Fast BSS Transition */
+       u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
+       u8 r1_key_holder[FT_R1KH_ID_LEN];
+       u32 r0_key_lifetime;
+       u32 reassociation_deadline;
+       struct ft_remote_r0kh *r0kh_list;
+       struct ft_remote_r1kh *r1kh_list;
+       int pmk_r1_push;
+       int ft_over_ds;
+#endif /* CONFIG_IEEE80211R */
+
+//     char *ctrl_interface; /* directory for UNIX domain sockets */
+#ifndef CONFIG_NATIVE_WINDOWS
+//     gid_t ctrl_interface_gid;
+#endif /* CONFIG_NATIVE_WINDOWS */
+//     int ctrl_interface_gid_set;
+
+//     char *ca_cert;
+//     char *server_cert;
+//     char *private_key;
+//     char *private_key_passwd;
+//     int check_crl;
+//     char *dh_file;
+//     u8 *pac_opaque_encr_key;
+//     u8 *eap_fast_a_id;
+//     size_t eap_fast_a_id_len;
+//     char *eap_fast_a_id_info;
+//     int eap_fast_prov;
+//     int pac_key_lifetime;
+//     int pac_key_refresh_time;
+//     int eap_sim_aka_result_ind;
+//     int tnc;
+//     int fragment_size;
+//     u16 pwd_group;
+
+//     char *radius_server_clients;
+//     int radius_server_auth_port;
+//     int radius_server_ipv6;
+
+//     char *test_socket; /* UNIX domain socket path for driver_test */
+
+//     int use_pae_group_addr; /* Whether to send EAPOL frames to PAE group
+//                              * address instead of individual address
+//                              * (for driver_wired.c).
+//                              */
+
+       int ap_max_inactivity;
+       int ignore_broadcast_ssid;
+
+       int wmm_enabled;
+       int wmm_uapsd;
+
+//     struct hostapd_vlan *vlan, *vlan_tail;
+
+       macaddr bssid;
+
+       /*
+        * Maximum listen interval that STAs can use when associating with this
+        * BSS. If a STA tries to use larger value, the association will be
+        * denied with status code 51.
+        */
+       u16 max_listen_interval;
+
+//     int disable_pmksa_caching;
+//     int okc; /* Opportunistic Key Caching */
+
+//     int wps_state;
+#ifdef CONFIG_WPS
+       int ap_setup_locked;
+       u8 uuid[16];
+       char *wps_pin_requests;
+       char *device_name;
+       char *manufacturer;
+       char *model_name;
+       char *model_number;
+       char *serial_number;
+       u8 device_type[WPS_DEV_TYPE_LEN];
+       char *config_methods;
+       u8 os_version[4];
+       char *ap_pin;
+       int skip_cred_build;
+       u8 *extra_cred;
+       size_t extra_cred_len;
+       int wps_cred_processing;
+       u8 *ap_settings;
+       size_t ap_settings_len;
+       char *upnp_iface;
+       char *friendly_name;
+       char *manufacturer_url;
+       char *model_description;
+       char *model_url;
+       char *upc;
+       struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
+       int wps_nfc_dev_pw_id;
+       struct wpabuf *wps_nfc_dh_pubkey;
+       struct wpabuf *wps_nfc_dh_privkey;
+       struct wpabuf *wps_nfc_dev_pw;
+#endif /* CONFIG_WPS */
+//     int pbc_in_m1;
+
+#define P2P_ENABLED BIT(0)
+#define P2P_GROUP_OWNER BIT(1)
+#define P2P_GROUP_FORMATION BIT(2)
+#define P2P_MANAGE BIT(3)
+#define P2P_ALLOW_CROSS_CONNECTION BIT(4)
+//     int p2p;
+
+//     int disassoc_low_ack;
+//     int skip_inactivity_poll;
+
+#define TDLS_PROHIBIT BIT(0)
+#define TDLS_PROHIBIT_CHAN_SWITCH BIT(1)
+//     int tdls;
+//     int disable_11n;
+//     int disable_11ac;
+
+       /* IEEE 802.11v */
+//     int time_advertisement;
+//     char *time_zone;
+//     int wnm_sleep_mode;
+//     int bss_transition;
+
+       /* IEEE 802.11u - Interworking */
+//     int interworking;
+//     int access_network_type;
+//     int internet;
+//     int asra;
+//     int esr;
+//     int uesa;
+//     int venue_info_set;
+//     u8 venue_group;
+//     u8 venue_type;
+//     u8 hessid[ETH_ALEN];
+
+       /* IEEE 802.11u - Roaming Consortium list */
+//     unsigned int roaming_consortium_count;
+//     struct hostapd_roaming_consortium *roaming_consortium;
+
+       /* IEEE 802.11u - Venue Name duples */
+//     unsigned int venue_name_count;
+//     struct hostapd_lang_string *venue_name;
+
+       /* IEEE 802.11u - Network Authentication Type */
+//     u8 *network_auth_type;
+//     size_t network_auth_type_len;
+
+       /* IEEE 802.11u - IP Address Type Availability */
+//     u8 ipaddr_type_availability;
+//     u8 ipaddr_type_configured;
+
+       /* IEEE 802.11u - 3GPP Cellular Network */
+//     u8 *anqp_3gpp_cell_net;
+//     size_t anqp_3gpp_cell_net_len;
+
+       /* IEEE 802.11u - Domain Name */
+//     u8 *domain_name;
+//     size_t domain_name_len;
+
+//     unsigned int nai_realm_count;
+//     struct hostapd_nai_realm_data *nai_realm_data;
+
+//     u16 gas_comeback_delay;
+//     int gas_frag_limit;
+
+#ifdef CONFIG_HS20
+       int hs20;
+       int disable_dgaf;
+       unsigned int hs20_oper_friendly_name_count;
+       struct hostapd_lang_string *hs20_oper_friendly_name;
+       u8 *hs20_wan_metrics;
+       u8 *hs20_connection_capability;
+       size_t hs20_connection_capability_len;
+       u8 *hs20_operating_class;
+       u8 hs20_operating_class_len;
+#endif /* CONFIG_HS20 */
+
+//     u8 wps_rf_bands; /* RF bands for WPS (WPS_RF_*) */
+
+#ifdef CONFIG_RADIUS_TEST
+       char *dump_msk_file;
+#endif /* CONFIG_RADIUS_TEST */
+
+//     struct wpabuf *vendor_elements;
+};
+
+
+/**
+ * struct hostapd_config - Per-radio interface configuration
+ */
+struct hostapd_config {
+       struct hostapd_bss_config *bss, *last_bss;
+       size_t num_bss;
+
+       u16 beacon_int;
+       int rts_threshold;
+       int fragm_threshold;
+       u8 send_probe_response;
+       u8 channel;
+       enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
+       enum {
+               LONG_PREAMBLE = 0,
+               SHORT_PREAMBLE = 1
+       } preamble;
+
+       int *supported_rates;
+       int *basic_rates;
+
+       const struct wpa_driver_ops *driver;
+
+       int ap_table_max_size;
+       int ap_table_expiration_time;
+
+       char country[3]; /* first two octets: country code as described in
+                         * ISO/IEC 3166-1. Third octet:
+                         * ' ' (ascii 32): all environments
+                         * 'O': Outdoor environemnt only
+                         * 'I': Indoor environment only
+                         */
+
+       int ieee80211d;
+
+//     struct hostapd_tx_queue_params tx_queue[NUM_TX_QUEUES];
+
+       /*
+        * WMM AC parameters, in same order as 802.1D, i.e.
+        * 0 = BE (best effort)
+        * 1 = BK (background)
+        * 2 = VI (video)
+        * 3 = VO (voice)
+        */
+//     struct hostapd_wmm_ac_params wmm_ac_params[4];
+
+       int ht_op_mode_fixed;
+       u16 ht_capab;
+       int ieee80211n;
+       int secondary_channel;
+       int require_ht;
+       u32 vht_capab;
+       int ieee80211ac;
+       int require_vht;
+       u8 vht_oper_chwidth;
+       u8 vht_oper_centr_freq_seg0_idx;
+       u8 vht_oper_centr_freq_seg1_idx;
+};
+
+
+int hostapd_mac_comp(const void *a, const void *b);
+int hostapd_mac_comp_empty(const void *a);
+struct hostapd_config * hostapd_config_defaults(void);
+void hostapd_config_defaults_bss(struct hostapd_bss_config *bss);
+void hostapd_config_free(struct hostapd_config *conf);
+int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
+                         const u8 *addr, int *vlan_id);
+int hostapd_rate_found(int *list, int rate);
+int hostapd_wep_key_cmp(struct hostapd_wep_keys *a,
+                       struct hostapd_wep_keys *b);
+const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
+                          const u8 *addr, const u8 *prev_psk);
+int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf);
+//const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan,
+//                                     int vlan_id);
+//struct hostapd_radius_attr *
+//hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type);
+
+#endif /* HOSTAPD_CONFIG_H */
diff --git a/components/wpa_supplicant/include/wpa/common.h b/components/wpa_supplicant/include/wpa/common.h
new file mode 100644 (file)
index 0000000..ca80c23
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * wpa_supplicant/hostapd / common helper functions, etc.
+ * Copyright (c) 2002-2007, 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.
+ */
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#if defined(__ets__)
+#endif /* ets */
+#include "os.h"
+
+#if defined(__XTENSA__)
+#include <machine/endian.h>
+#define __BYTE_ORDER     BYTE_ORDER
+#define __LITTLE_ENDIAN  LITTLE_ENDIAN
+#define __BIG_ENDIAN     BIG_ENDIAN
+#endif /*__XTENSA__*/
+
+#if defined(__linux__) || defined(__GLIBC__) || defined(__ets__)
+#include <endian.h>
+#include <byteswap.h>
+#endif /* __linux__ */
+
+/* Define platform specific byte swapping macros */
+
+#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
+
+static inline unsigned short wpa_swap_16(unsigned short v)
+{
+       return ((v & 0xff) << 8) | (v >> 8);
+}
+
+static inline unsigned int wpa_swap_32(unsigned int v)
+{
+       return ((v & 0xff) << 24) | ((v & 0xff00) << 8) |
+               ((v & 0xff0000) >> 8) | (v >> 24);
+}
+
+#define le_to_host16(n) (n)
+#define host_to_le16(n) (n)
+#define be_to_host16(n) wpa_swap_16(n)
+#define host_to_be16(n) wpa_swap_16(n)
+#define le_to_host32(n) (n)
+#define be_to_host32(n) wpa_swap_32(n)
+#define host_to_be32(n) wpa_swap_32(n)
+
+#define WPA_BYTE_SWAP_DEFINED
+
+#endif /* __CYGWIN__ || CONFIG_NATIVE_WINDOWS */
+
+
+#ifndef WPA_BYTE_SWAP_DEFINED
+
+#ifndef __BYTE_ORDER
+#ifndef __LITTLE_ENDIAN
+#ifndef __BIG_ENDIAN
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#if defined(sparc)
+#define __BYTE_ORDER __BIG_ENDIAN
+#endif
+#endif /* __BIG_ENDIAN */
+#endif /* __LITTLE_ENDIAN */
+#endif /* __BYTE_ORDER */
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define le_to_host16(n) ((__force u16) (le16) (n))
+#define host_to_le16(n) ((__force le16) (u16) (n))
+#define be_to_host16(n) __bswap_16((__force u16) (be16) (n))
+#define host_to_be16(n) ((__force be16) __bswap_16((n)))
+#define le_to_host32(n) ((__force u32) (le32) (n))
+#define host_to_le32(n) ((__force le32) (u32) (n))
+#define be_to_host32(n) __bswap_32((__force u32) (be32) (n))
+#define host_to_be32(n) ((__force be32) __bswap_32((n)))
+#define le_to_host64(n) ((__force u64) (le64) (n))
+#define host_to_le64(n) ((__force le64) (u64) (n))
+#define be_to_host64(n) __bswap_64((__force u64) (be64) (n))
+#define host_to_be64(n) ((__force be64) bswap_64((n)))
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define le_to_host16(n) __bswap_16(n)
+#define host_to_le16(n) __bswap_16(n)
+#define be_to_host16(n) (n)
+#define host_to_be16(n) (n)
+#define le_to_host32(n) __bswap_32(n)
+#define be_to_host32(n) (n)
+#define host_to_be32(n) (n)
+#define le_to_host64(n) __bswap_64(n)
+#define host_to_le64(n) __bswap_64(n)
+#define be_to_host64(n) (n)
+#define host_to_be64(n) (n)
+#ifndef WORDS_BIGENDIAN
+#define WORDS_BIGENDIAN
+#endif
+#else
+#error Could not determine CPU byte order
+#endif
+
+#define WPA_BYTE_SWAP_DEFINED
+#endif /* !WPA_BYTE_SWAP_DEFINED */
+
+
+/* Macros for handling unaligned memory accesses */
+
+#define WPA_GET_BE16(a) ((u16) (((a)[0] << 8) | (a)[1]))
+#define WPA_PUT_BE16(a, val)                   \
+       do {                                    \
+               (a)[0] = ((u16) (val)) >> 8;    \
+               (a)[1] = ((u16) (val)) & 0xff;  \
+       } while (0)
+
+#define WPA_GET_LE16(a) ((u16) (((a)[1] << 8) | (a)[0]))
+#define WPA_PUT_LE16(a, val)                   \
+       do {                                    \
+               (a)[1] = ((u16) (val)) >> 8;    \
+               (a)[0] = ((u16) (val)) & 0xff;  \
+       } while (0)
+
+#define WPA_GET_BE24(a) ((((u32) (a)[0]) << 16) | (((u32) (a)[1]) << 8) | \
+                        ((u32) (a)[2]))
+#define WPA_PUT_BE24(a, val)                                   \
+       do {                                                    \
+               (a)[0] = (u8) ((((u32) (val)) >> 16) & 0xff);   \
+               (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff);    \
+               (a)[2] = (u8) (((u32) (val)) & 0xff);           \
+       } while (0)
+
+#define WPA_GET_BE32(a) ((((u32) (a)[0]) << 24) | (((u32) (a)[1]) << 16) | \
+                        (((u32) (a)[2]) << 8) | ((u32) (a)[3]))
+#define WPA_PUT_BE32(a, val)                                   \
+       do {                                                    \
+               (a)[0] = (u8) ((((u32) (val)) >> 24) & 0xff);   \
+               (a)[1] = (u8) ((((u32) (val)) >> 16) & 0xff);   \
+               (a)[2] = (u8) ((((u32) (val)) >> 8) & 0xff);    \
+               (a)[3] = (u8) (((u32) (val)) & 0xff);           \
+       } while (0)
+
+#define WPA_GET_LE32(a) ((((u32) (a)[3]) << 24) | (((u32) (a)[2]) << 16) | \
+                        (((u32) (a)[1]) << 8) | ((u32) (a)[0]))
+#define WPA_PUT_LE32(a, val)                                   \
+       do {                                                    \
+               (a)[3] = (u8) ((((u32) (val)) >> 24) & 0xff);   \
+               (a)[2] = (u8) ((((u32) (val)) >> 16) & 0xff);   \
+               (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff);    \
+               (a)[0] = (u8) (((u32) (val)) & 0xff);           \
+       } while (0)
+
+#define WPA_GET_BE64(a) ((((u64) (a)[0]) << 56) | (((u64) (a)[1]) << 48) | \
+                        (((u64) (a)[2]) << 40) | (((u64) (a)[3]) << 32) | \
+                        (((u64) (a)[4]) << 24) | (((u64) (a)[5]) << 16) | \
+                        (((u64) (a)[6]) << 8) | ((u64) (a)[7]))
+#define WPA_PUT_BE64(a, val)                           \
+       do {                                            \
+               (a)[0] = (u8) (((u64) (val)) >> 56);    \
+               (a)[1] = (u8) (((u64) (val)) >> 48);    \
+               (a)[2] = (u8) (((u64) (val)) >> 40);    \
+               (a)[3] = (u8) (((u64) (val)) >> 32);    \
+               (a)[4] = (u8) (((u64) (val)) >> 24);    \
+               (a)[5] = (u8) (((u64) (val)) >> 16);    \
+               (a)[6] = (u8) (((u64) (val)) >> 8);     \
+               (a)[7] = (u8) (((u64) (val)) & 0xff);   \
+       } while (0)
+
+#define WPA_GET_LE64(a) ((((u64) (a)[7]) << 56) | (((u64) (a)[6]) << 48) | \
+                        (((u64) (a)[5]) << 40) | (((u64) (a)[4]) << 32) | \
+                        (((u64) (a)[3]) << 24) | (((u64) (a)[2]) << 16) | \
+                        (((u64) (a)[1]) << 8) | ((u64) (a)[0]))
+
+
+#ifndef ETH_ALEN
+#define ETH_ALEN 6
+#endif
+//#ifndef IFNAMSIZ
+//#define IFNAMSIZ 16
+//#endif
+#ifndef ETH_P_ALL
+#define ETH_P_ALL 0x0003
+#endif
+#ifndef ETH_P_PAE
+#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
+#endif /* ETH_P_PAE */
+#ifndef ETH_P_EAPOL
+#define ETH_P_EAPOL ETH_P_PAE
+#endif /* ETH_P_EAPOL */
+#ifndef ETH_P_RSN_PREAUTH
+#define ETH_P_RSN_PREAUTH 0x88c7
+#endif /* ETH_P_RSN_PREAUTH */
+#ifndef ETH_P_RRB
+#define ETH_P_RRB 0x890D
+#endif /* ETH_P_RRB */
+
+
+#ifdef __GNUC__
+#define PRINTF_FORMAT(a,b) __attribute__ ((format (printf, (a), (b))))
+#define STRUCT_PACKED __attribute__ ((packed))
+#else
+#define PRINTF_FORMAT(a,b)
+#define STRUCT_PACKED
+#endif
+
+#ifdef CONFIG_ANSI_C_EXTRA
+
+/* inline - define as __inline or just define it to be empty, if needed */
+#ifdef CONFIG_NO_INLINE
+#define inline
+#else
+#define inline __inline
+#endif
+
+#ifndef __func__
+#define __func__ "__func__ not defined"
+#endif
+
+#ifndef bswap_16
+#define bswap_16(a) ((((u16) (a) << 8) & 0xff00) | (((u16) (a) >> 8) & 0xff))
+#endif
+
+#ifndef bswap_32
+#define bswap_32(a) ((((u32) (a) << 24) & 0xff000000) | \
+                    (((u32) (a) << 8) & 0xff0000) | \
+                    (((u32) (a) >> 8) & 0xff00) | \
+                    (((u32) (a) >> 24) & 0xff))
+#endif
+
+#ifndef MSG_DONTWAIT
+#define MSG_DONTWAIT 0
+#endif
+
+#ifdef _WIN32_WCE
+void perror(const char *s);
+#endif /* _WIN32_WCE */
+
+#endif /* CONFIG_ANSI_C_EXTRA */
+
+#ifndef MAC2STR
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+#endif
+
+#ifndef BIT
+#define BIT(x) (1 << (x))
+#endif
+
+/*
+ * Definitions for sparse validation
+ * (http://kernel.org/pub/linux/kernel/people/josh/sparse/)
+ */
+#ifdef __CHECKER__
+#define __force __attribute__((force))
+#define __bitwise __attribute__((bitwise))
+#else
+#define __force
+#define __bitwise
+#endif
+
+typedef u16 __bitwise be16;
+typedef u16 __bitwise le16;
+typedef u32 __bitwise be32;
+typedef u32 __bitwise le32;
+typedef u64 __bitwise be64;
+typedef u64 __bitwise le64;
+
+#ifndef __must_check
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+#define __must_check __attribute__((__warn_unused_result__))
+#else
+#define __must_check
+#endif /* __GNUC__ */
+#endif /* __must_check */
+
+int hwaddr_aton(const char *txt, u8 *addr);
+int hwaddr_aton2(const char *txt, u8 *addr);
+int hexstr2bin(const char *hex, u8 *buf, size_t len);
+void inc_byte_array(u8 *counter, size_t len);
+void wpa_get_ntp_timestamp(u8 *buf);
+int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len);
+int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
+                              size_t len);
+
+#ifdef CONFIG_NATIVE_WINDOWS
+void wpa_unicode2ascii_inplace(TCHAR *str);
+TCHAR * wpa_strdup_tchar(const char *str);
+#else /* CONFIG_NATIVE_WINDOWS */
+#define wpa_unicode2ascii_inplace(s) do { } while (0)
+#define wpa_strdup_tchar(s) strdup((s))
+#endif /* CONFIG_NATIVE_WINDOWS */
+
+const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len);
+char * wpa_config_parse_string(const char *value, size_t *len);
+
+static inline int is_zero_ether_addr(const u8 *a)
+{
+       return !(a[0] | a[1] | a[2] | a[3] | a[4] | a[5]);
+}
+
+extern const struct eth_addr ethbroadcast;
+#define broadcast_ether_addr &ethbroadcast
+
+#include "wpabuf.h"
+#include "wpa_debug.h"
+
+
+/*
+ * gcc 4.4 ends up generating strict-aliasing warnings about some very common
+ * networking socket uses that do not really result in a real problem and
+ * cannot be easily avoided with union-based type-punning due to struct
+ * definitions including another struct in system header files. To avoid having
+ * to fully disable strict-aliasing warnings, provide a mechanism to hide the
+ * typecast from aliasing for now. A cleaner solution will hopefully be found
+ * in the future to handle these cases.
+ */
+void * __hide_aliasing_typecast(void *foo);
+#define aliasing_hide_typecast(a,t) (t *) __hide_aliasing_typecast((a))
+
+#endif /* COMMON_H */
diff --git a/components/wpa_supplicant/include/wpa/defs.h b/components/wpa_supplicant/include/wpa/defs.h
new file mode 100644 (file)
index 0000000..f019cee
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * WPA Supplicant - Common definitions
+ * Copyright (c) 2004-2008, 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.
+ */
+
+#ifndef DEFS_H
+#define DEFS_H
+
+#ifdef FALSE
+#undef FALSE
+#endif
+#ifdef TRUE
+#undef TRUE
+#endif
+typedef enum { FALSE = 0, TRUE = 1 } Boolean;
+
+/*
+#define WPA_CIPHER_NONE BIT(0)
+#define WPA_CIPHER_WEP40 BIT(1)
+#define WPA_CIPHER_WEP104 BIT(2)
+#define WPA_CIPHER_TKIP BIT(3)
+#define WPA_CIPHER_CCMP BIT(4)
+#ifdef CONFIG_IEEE80211W
+#define WPA_CIPHER_AES_128_CMAC BIT(5)
+#endif 
+*/
+
+/*
+ * NB: these values are ordered carefully; there are lots of
+ * of implications in any reordering.  Beware that 4 is used
+ * only to indicate h/w TKIP MIC support in driver capabilities;
+ * there is no separate cipher support (it's rolled into the
+ * TKIP cipher support).
+ */
+#define        IEEE80211_CIPHER_NONE           0       /* pseudo value */
+#define        IEEE80211_CIPHER_TKIP           1
+#define        IEEE80211_CIPHER_AES_OCB        2
+#define        IEEE80211_CIPHER_AES_CCM        3
+#define        IEEE80211_CIPHER_TKIPMIC        4       /* TKIP MIC capability */
+#define        IEEE80211_CIPHER_CKIP           5
+#define        IEEE80211_CIPHER_WEP            6
+#define        IEEE80211_CIPHER_WEP40          7
+#define        IEEE80211_CIPHER_WEP104         8
+
+
+#define        IEEE80211_CIPHER_MAX            (IEEE80211_CIPHER_NONE+2)
+
+/* capability bits in ic_cryptocaps/iv_cryptocaps */
+#define        IEEE80211_CRYPTO_NONE           (1<<IEEE80211_CIPHER_NONE)
+#define        IEEE80211_CRYPTO_WEP            (1<<IEEE80211_CIPHER_WEP)
+#define        IEEE80211_CRYPTO_WEP40          (1<<IEEE80211_CIPHER_WEP40)
+#define        IEEE80211_CRYPTO_WEP104 (1<<IEEE80211_CIPHER_WEP104)
+#define        IEEE80211_CRYPTO_TKIP           (1<<IEEE80211_CIPHER_TKIP)
+#define        IEEE80211_CRYPTO_AES_OCB        (1<<IEEE80211_CIPHER_AES_OCB)
+#define        IEEE80211_CRYPTO_AES_CCM        (1<<IEEE80211_CIPHER_AES_CCM)
+#define        IEEE80211_CRYPTO_TKIPMIC        (1<<IEEE80211_CIPHER_TKIPMIC)
+#define        IEEE80211_CRYPTO_CKIP           (1<<IEEE80211_CIPHER_CKIP)
+
+#define WPA_CIPHER_NONE                     IEEE80211_CRYPTO_NONE
+#define WPA_CIPHER_WEP40                    IEEE80211_CRYPTO_WEP40
+#define WPA_CIPHER_WEP104                  IEEE80211_CRYPTO_WEP104
+#define WPA_CIPHER_TKIP                       IEEE80211_CRYPTO_TKIP
+#define WPA_CIPHER_CCMP                     IEEE80211_CRYPTO_AES_CCM
+#ifdef CONFIG_IEEE80211W
+#define WPA_CIPHER_AES_128_CMAC    IEEE80211_CRYPTO_AES_OCB
+#endif /* CONFIG_IEEE80211W */
+#define WPA_CIPHER_GCMP BIT(6)
+
+#define WPA_KEY_MGMT_IEEE8021X BIT(0)
+#define WPA_KEY_MGMT_PSK BIT(1)
+#define WPA_KEY_MGMT_NONE BIT(2)
+#define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3)
+#define WPA_KEY_MGMT_WPA_NONE BIT(4)
+#define WPA_KEY_MGMT_FT_IEEE8021X BIT(5)
+#define WPA_KEY_MGMT_FT_PSK BIT(6)
+#define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7)
+#define WPA_KEY_MGMT_PSK_SHA256 BIT(8)
+#define WPA_KEY_MGMT_WPS BIT(9)
+#define WPA_KEY_MGMT_CCKM BIT(14)
+
+static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
+{
+       return !!(akm & (WPA_KEY_MGMT_IEEE8021X |
+                        WPA_KEY_MGMT_FT_IEEE8021X |
+                        WPA_KEY_MGMT_CCKM |
+                        WPA_KEY_MGMT_IEEE8021X_SHA256));
+}
+
+static inline int wpa_key_mgmt_wpa_psk(int akm)
+{
+       return akm == WPA_KEY_MGMT_PSK ||
+               akm == WPA_KEY_MGMT_FT_PSK ||
+               akm == WPA_KEY_MGMT_PSK_SHA256;
+}
+
+static inline int wpa_key_mgmt_ft(int akm)
+{
+       return akm == WPA_KEY_MGMT_FT_PSK ||
+               akm == WPA_KEY_MGMT_FT_IEEE8021X;
+}
+
+static inline int wpa_key_mgmt_sha256(int akm)
+{
+       return akm == WPA_KEY_MGMT_PSK_SHA256 ||
+               akm == WPA_KEY_MGMT_IEEE8021X_SHA256;
+}
+
+
+#define WPA_PROTO_WPA BIT(0)
+#define WPA_PROTO_RSN BIT(1)
+
+#define WPA_AUTH_ALG_OPEN BIT(0)
+#define WPA_AUTH_ALG_SHARED BIT(1)
+#define WPA_AUTH_ALG_LEAP BIT(2)
+#define WPA_AUTH_ALG_FT BIT(3)
+
+
+enum ieee80211_key_alg {
+       ALG_WEP,
+       ALG_TKIP,
+       ALG_CCMP,
+       ALG_AES_CMAC,
+};
+
+enum wpa_alg {
+       WPA_ALG_NONE =0,
+       WPA_ALG_WEP40 = 1,
+       WPA_ALG_TKIP = 2,
+       WPA_ALG_CCMP = 3,
+       WPA_ALG_WAPI = 4,
+       WPA_ALG_WEP104 = 5,
+       WPA_ALG_WEP,
+       WPA_ALG_IGTK,
+       WPA_ALG_PMK,
+       WPA_ALG_GCMP
+};
+
+/**
+ * enum wpa_cipher - Cipher suites
+ */
+enum wpa_cipher {
+       CIPHER_NONE,
+       CIPHER_WEP40,
+       CIPHER_TKIP,
+       CIPHER_CCMP,
+       CIPHER_WEP104
+};
+
+/**
+ * enum wpa_key_mgmt - Key management suites
+ */
+enum wpa_key_mgmt {
+       KEY_MGMT_802_1X,
+       KEY_MGMT_PSK,
+       KEY_MGMT_NONE,
+       KEY_MGMT_802_1X_NO_WPA,
+       KEY_MGMT_WPA_NONE,
+       KEY_MGMT_FT_802_1X,
+       KEY_MGMT_FT_PSK,
+       KEY_MGMT_802_1X_SHA256,
+       KEY_MGMT_PSK_SHA256,
+       KEY_MGMT_WPS
+};
+
+/**
+ * enum wpa_states - wpa_supplicant state
+ *
+ * These enumeration values are used to indicate the current wpa_supplicant
+ * state (wpa_s->wpa_state). The current state can be retrieved with
+ * wpa_supplicant_get_state() function and the state can be changed by calling
+ * wpa_supplicant_set_state(). In WPA state machine (wpa.c and preauth.c), the
+ * wrapper functions wpa_sm_get_state() and wpa_sm_set_state() should be used
+ * to access the state variable.
+ */
+enum wpa_states {
+       /**
+        * WPA_DISCONNECTED - Disconnected state
+        *
+        * This state indicates that client is not associated, but is likely to
+        * start looking for an access point. This state is entered when a
+        * connection is lost.
+        */
+       WPA_DISCONNECTED,
+
+       /**
+        * WPA_INACTIVE - Inactive state (wpa_supplicant disabled)
+        *
+        * This state is entered if there are no enabled networks in the
+        * configuration. wpa_supplicant is not trying to associate with a new
+        * network and external interaction (e.g., ctrl_iface call to add or
+        * enable a network) is needed to start association.
+        */
+       WPA_INACTIVE,
+
+       /**
+        * WPA_SCANNING - Scanning for a network
+        *
+        * This state is entered when wpa_supplicant starts scanning for a
+        * network.
+        */
+       WPA_SCANNING,
+
+       /**
+        * WPA_AUTHENTICATING - Trying to authenticate with a BSS/SSID
+        *
+        * This state is entered when wpa_supplicant has found a suitable BSS
+        * to authenticate with and the driver is configured to try to
+        * authenticate with this BSS. This state is used only with drivers
+        * that use wpa_supplicant as the SME.
+        */
+       WPA_AUTHENTICATING,
+
+       /**
+        * WPA_ASSOCIATING - Trying to associate with a BSS/SSID
+        *
+        * This state is entered when wpa_supplicant has found a suitable BSS
+        * to associate with and the driver is configured to try to associate
+        * with this BSS in ap_scan=1 mode. When using ap_scan=2 mode, this
+        * state is entered when the driver is configured to try to associate
+        * with a network using the configured SSID and security policy.
+        */
+       WPA_ASSOCIATING,
+
+       /**
+        * WPA_ASSOCIATED - Association completed
+        *
+        * This state is entered when the driver reports that association has
+        * been successfully completed with an AP. If IEEE 802.1X is used
+        * (with or without WPA/WPA2), wpa_supplicant remains in this state
+        * until the IEEE 802.1X/EAPOL authentication has been completed.
+        */
+       WPA_ASSOCIATED,
+
+       /**
+        * WPA_4WAY_HANDSHAKE - WPA 4-Way Key Handshake in progress
+        *
+        * This state is entered when WPA/WPA2 4-Way Handshake is started. In
+        * case of WPA-PSK, this happens when receiving the first EAPOL-Key
+        * frame after association. In case of WPA-EAP, this state is entered
+        * when the IEEE 802.1X/EAPOL authentication has been completed.
+        */
+       WPA_FIRST_HALF_4WAY_HANDSHAKE,
+
+       WPA_LAST_HALF_4WAY_HANDSHAKE,
+
+       /**
+        * WPA_GROUP_HANDSHAKE - WPA Group Key Handshake in progress
+        *
+        * This state is entered when 4-Way Key Handshake has been completed
+        * (i.e., when the supplicant sends out message 4/4) and when Group
+        * Key rekeying is started by the AP (i.e., when supplicant receives
+        * message 1/2).
+        */
+       WPA_GROUP_HANDSHAKE,
+
+       /**
+        * WPA_COMPLETED - All authentication completed
+        *
+        * This state is entered when the full authentication process is
+        * completed. In case of WPA2, this happens when the 4-Way Handshake is
+        * successfully completed. With WPA, this state is entered after the
+        * Group Key Handshake; with IEEE 802.1X (non-WPA) connection is
+        * completed after dynamic keys are received (or if not used, after
+        * the EAP authentication has been completed). With static WEP keys and
+        * plaintext connections, this state is entered when an association
+        * has been completed.
+        *
+        * This state indicates that the supplicant has completed its
+        * processing for the association phase and that data connection is
+        * fully configured.
+        */
+       WPA_COMPLETED,
+
+       WPA_MIC_FAILURE,                         // first mic_error event occur
+
+       WPA_TKIP_COUNTERMEASURES  //in countermeasure period that stop connect with ap in 60 sec
+};
+
+#define MLME_SETPROTECTION_PROTECT_TYPE_NONE 0
+#define MLME_SETPROTECTION_PROTECT_TYPE_RX 1
+#define MLME_SETPROTECTION_PROTECT_TYPE_TX 2
+#define MLME_SETPROTECTION_PROTECT_TYPE_RX_TX 3
+
+#define MLME_SETPROTECTION_KEY_TYPE_GROUP 0
+#define MLME_SETPROTECTION_KEY_TYPE_PAIRWISE 1
+
+/**
+ * enum hostapd_hw_mode - Hardware mode
+ */
+enum hostapd_hw_mode {
+       HOSTAPD_MODE_IEEE80211B,
+       HOSTAPD_MODE_IEEE80211G,
+       HOSTAPD_MODE_IEEE80211A,
+       HOSTAPD_MODE_IEEE80211AD,
+       NUM_HOSTAPD_MODES
+};
+
+#endif /* DEFS_H */
diff --git a/components/wpa_supplicant/include/wpa/eapol_common.h b/components/wpa_supplicant/include/wpa/eapol_common.h
new file mode 100644 (file)
index 0000000..6a40ac3
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * EAPOL definitions shared between hostapd and wpa_supplicant
+ * Copyright (c) 2002-2007, 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.
+ */
+
+#ifndef EAPOL_COMMON_H
+#define EAPOL_COMMON_H
+
+/* IEEE Std 802.1X-2004 */
+
+struct ieee802_1x_hdr {
+       u8 version;
+       u8 type;
+       be16 length;
+       /* followed by length octets of data */
+} STRUCT_PACKED;
+
+
+#define EAPOL_VERSION 2
+
+enum { IEEE802_1X_TYPE_EAP_PACKET = 0,
+       IEEE802_1X_TYPE_EAPOL_START = 1,
+       IEEE802_1X_TYPE_EAPOL_LOGOFF = 2,
+       IEEE802_1X_TYPE_EAPOL_KEY = 3,
+       IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT = 4
+};
+
+enum { EAPOL_KEY_TYPE_RC4 = 1, EAPOL_KEY_TYPE_RSN = 2,
+       EAPOL_KEY_TYPE_WPA = 254 };
+
+#define IEEE8021X_REPLAY_COUNTER_LEN 8
+#define IEEE8021X_KEY_SIGN_LEN 16
+#define IEEE8021X_KEY_IV_LEN 16
+
+#define IEEE8021X_KEY_INDEX_FLAG 0x80
+#define IEEE8021X_KEY_INDEX_MASK 0x03
+
+struct ieee802_1x_eapol_key {
+       u8 type;
+       /* Note: key_length is unaligned */
+       u8 key_length[2];
+       /* does not repeat within the life of the keying material used to
+        * encrypt the Key field; 64-bit NTP timestamp MAY be used here */
+       u8 replay_counter[IEEE8021X_REPLAY_COUNTER_LEN];
+       u8 key_iv[IEEE8021X_KEY_IV_LEN]; /* cryptographically random number */
+       u8 key_index; /* key flag in the most significant bit:
+                      * 0 = broadcast (default key),
+                      * 1 = unicast (key mapping key); key index is in the
+                      * 7 least significant bits */
+       /* HMAC-MD5 message integrity check computed with MS-MPPE-Send-Key as
+        * the key */
+       u8 key_signature[IEEE8021X_KEY_SIGN_LEN];
+
+       /* followed by key: if packet body length = 44 + key length, then the
+        * key field (of key_length bytes) contains the key in encrypted form;
+        * if packet body length = 44, key field is absent and key_length
+        * represents the number of least significant octets from
+        * MS-MPPE-Send-Key attribute to be used as the keying material;
+        * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */
+} STRUCT_PACKED;
+
+#endif /* EAPOL_COMMON_H */
diff --git a/components/wpa_supplicant/include/wpa/hostapd.h b/components/wpa_supplicant/include/wpa/hostapd.h
new file mode 100644 (file)
index 0000000..1d52659
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+ * hostapd / Initialization and configuration
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef HOSTAPD_H
+#define HOSTAPD_H
+
+#include "wpa/defs.h"
+#include "wpa/ap_config.h"
+
+struct wpa_driver_ops;
+struct wpa_ctrl_dst;
+struct radius_server_data;
+struct upnp_wps_device_sm;
+struct hostapd_data;
+struct sta_info;
+struct hostap_sta_driver_data;
+struct ieee80211_ht_capabilities;
+struct full_dynamic_vlan;
+enum wps_event;
+union wps_event_data;
+
+struct hostapd_iface;
+
+struct hapd_interfaces {
+       int (*reload_config)(struct hostapd_iface *iface);
+       struct hostapd_config * (*config_read_cb)(const char *config_fname);
+       int (*ctrl_iface_init)(struct hostapd_data *hapd);
+       void (*ctrl_iface_deinit)(struct hostapd_data *hapd);
+       int (*for_each_interface)(struct hapd_interfaces *interfaces,
+                                 int (*cb)(struct hostapd_iface *iface,
+                                           void *ctx), void *ctx);
+       int (*driver_init)(struct hostapd_iface *iface);
+
+       size_t count;
+       int global_ctrl_sock;
+       char *global_iface_path;
+       char *global_iface_name;
+       struct hostapd_iface **iface;
+};
+
+
+struct hostapd_probereq_cb {
+       int (*cb)(void *ctx, const u8 *sa, const u8 *da, const u8 *bssid,
+                 const u8 *ie, size_t ie_len, int ssi_signal);
+       void *ctx;
+};
+
+#define HOSTAPD_RATE_BASIC 0x00000001
+
+struct hostapd_rate_data {
+       int rate; /* rate in 100 kbps */
+       int flags; /* HOSTAPD_RATE_ flags */
+};
+
+struct hostapd_frame_info {
+       u32 channel;
+       u32 datarate;
+       int ssi_signal; /* dBm */
+};
+
+
+/**
+ * struct hostapd_data - hostapd per-BSS data structure
+ */
+struct hostapd_data {
+//     struct hostapd_iface *iface;
+       struct hostapd_config *iconf;
+       struct hostapd_bss_config *conf;
+       int interface_added; /* virtual interface added for this BSS */
+
+       u8 own_addr[ETH_ALEN];
+
+       int num_sta; /* number of entries in sta_list */
+//     struct sta_info *sta_list; /* STA info list head */
+//#define STA_HASH_SIZE 256
+//#define STA_HASH(sta) (sta[5])
+//     struct sta_info *sta_hash[STA_HASH_SIZE];
+
+//     /*
+//      * Bitfield for indicating which AIDs are allocated. Only AID values
+//      * 1-2007 are used and as such, the bit at index 0 corresponds to AID
+//      * 1.
+//      */
+//#define AID_WORDS ((2008 + 31) / 32)
+//     u32 sta_aid[AID_WORDS];
+
+//     const struct wpa_driver_ops *driver;
+//     void *drv_priv;
+
+//     void (*new_assoc_sta_cb)(struct hostapd_data *hapd,
+//                              struct sta_info *sta, int reassoc);
+
+//     void *msg_ctx; /* ctx for wpa_msg() calls */
+//     void *msg_ctx_parent; /* parent interface ctx for wpa_msg() calls */
+
+//     struct radius_client_data *radius;
+//     u32 acct_session_id_hi, acct_session_id_lo;
+//     struct radius_das_data *radius_das;
+
+//     struct iapp_data *iapp;
+
+//     struct hostapd_cached_radius_acl *acl_cache;
+//     struct hostapd_acl_query_data *acl_queries;
+
+       struct wpa_authenticator *wpa_auth;
+//     struct eapol_authenticator *eapol_auth;
+
+//     struct rsn_preauth_interface *preauth_iface;
+//     time_t michael_mic_failure;
+//     int michael_mic_failures;
+//     int tkip_countermeasures;
+
+//     int ctrl_sock;
+//     struct wpa_ctrl_dst *ctrl_dst;
+
+//     void *ssl_ctx;
+//     void *eap_sim_db_priv;
+//     struct radius_server_data *radius_srv;
+
+//     int parameter_set_count;
+
+       /* Time Advertisement */
+//     u8 time_update_counter;
+//     struct wpabuf *time_adv;
+
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
+       struct full_dynamic_vlan *full_dynamic_vlan;
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
+
+//     struct l2_packet_data *l2;
+//     struct wps_context *wps;
+
+//     int beacon_set_done;
+//     struct wpabuf *wps_beacon_ie;
+//     struct wpabuf *wps_probe_resp_ie;
+#ifdef CONFIG_WPS
+       unsigned int ap_pin_failures;
+       unsigned int ap_pin_failures_consecutive;
+       struct upnp_wps_device_sm *wps_upnp;
+       unsigned int ap_pin_lockout_time;
+#endif /* CONFIG_WPS */
+
+//     struct hostapd_probereq_cb *probereq_cb;
+//     size_t num_probereq_cb;
+
+//     void (*public_action_cb)(void *ctx, const u8 *buf, size_t len,
+//                              int freq);
+//     void *public_action_cb_ctx;
+
+//     int (*vendor_action_cb)(void *ctx, const u8 *buf, size_t len,
+//                             int freq);
+//     void *vendor_action_cb_ctx;
+
+//     void (*wps_reg_success_cb)(void *ctx, const u8 *mac_addr,
+//                                const u8 *uuid_e);
+//     void *wps_reg_success_cb_ctx;
+
+//     void (*wps_event_cb)(void *ctx, enum wps_event event,
+//                          union wps_event_data *data);
+//     void *wps_event_cb_ctx;
+
+//     void (*sta_authorized_cb)(void *ctx, const u8 *mac_addr,
+//                               int authorized, const u8 *p2p_dev_addr);
+//     void *sta_authorized_cb_ctx;
+
+//     void (*setup_complete_cb)(void *ctx);
+//     void *setup_complete_cb_ctx;
+
+#ifdef CONFIG_P2P
+       struct p2p_data *p2p;
+       struct p2p_group *p2p_group;
+       struct wpabuf *p2p_beacon_ie;
+       struct wpabuf *p2p_probe_resp_ie;
+
+       /* Number of non-P2P association stations */
+       int num_sta_no_p2p;
+
+       /* Periodic NoA (used only when no non-P2P clients in the group) */
+       int noa_enabled;
+       int noa_start;
+       int noa_duration;
+#endif /* CONFIG_P2P */
+#ifdef CONFIG_INTERWORKING
+       size_t gas_frag_limit;
+#endif /* CONFIG_INTERWORKING */
+
+#ifdef CONFIG_SQLITE
+       struct hostapd_eap_user tmp_eap_user;
+#endif /* CONFIG_SQLITE */
+};
+
+#if 0
+/**
+ * struct hostapd_iface - hostapd per-interface data structure
+ */
+struct hostapd_iface {
+       struct hapd_interfaces *interfaces;
+       void *owner;
+       char *config_fname;
+       struct hostapd_config *conf;
+
+       size_t num_bss;
+       struct hostapd_data **bss;
+
+       int num_ap; /* number of entries in ap_list */
+       struct ap_info *ap_list; /* AP info list head */
+       struct ap_info *ap_hash[STA_HASH_SIZE];
+       struct ap_info *ap_iter_list;
+
+       unsigned int drv_flags;
+
+       /*
+        * A bitmap of supported protocols for probe response offload. See
+        * struct wpa_driver_capa in driver.h
+        */
+       unsigned int probe_resp_offloads;
+
+       struct hostapd_hw_modes *hw_features;
+       int num_hw_features;
+       struct hostapd_hw_modes *current_mode;
+       /* Rates that are currently used (i.e., filtered copy of
+        * current_mode->channels */
+       int num_rates;
+       struct hostapd_rate_data *current_rates;
+       int *basic_rates;
+       int freq;
+
+       u16 hw_flags;
+
+       /* Number of associated Non-ERP stations (i.e., stations using 802.11b
+        * in 802.11g BSS) */
+       int num_sta_non_erp;
+
+       /* Number of associated stations that do not support Short Slot Time */
+       int num_sta_no_short_slot_time;
+
+       /* Number of associated stations that do not support Short Preamble */
+       int num_sta_no_short_preamble;
+
+       int olbc; /* Overlapping Legacy BSS Condition */
+
+       /* Number of HT associated stations that do not support greenfield */
+       int num_sta_ht_no_gf;
+
+       /* Number of associated non-HT stations */
+       int num_sta_no_ht;
+
+       /* Number of HT associated stations 20 MHz */
+       int num_sta_ht_20mhz;
+
+       /* Overlapping BSS information */
+       int olbc_ht;
+
+       u16 ht_op_mode;
+       void (*scan_cb)(struct hostapd_iface *iface);
+};
+#endif
+
+#if 0
+/* hostapd.c */
+int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
+                              int (*cb)(struct hostapd_iface *iface,
+                                        void *ctx), void *ctx);
+int hostapd_reload_config(struct hostapd_iface *iface);
+struct hostapd_data *
+hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
+                      struct hostapd_config *conf,
+                      struct hostapd_bss_config *bss);
+int hostapd_setup_interface(struct hostapd_iface *iface);
+int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err);
+void hostapd_interface_deinit(struct hostapd_iface *iface);
+void hostapd_interface_free(struct hostapd_iface *iface);
+void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
+                          int reassoc);
+void hostapd_interface_deinit_free(struct hostapd_iface *iface);
+int hostapd_enable_iface(struct hostapd_iface *hapd_iface);
+int hostapd_reload_iface(struct hostapd_iface *hapd_iface);
+int hostapd_disable_iface(struct hostapd_iface *hapd_iface);
+int hostapd_add_iface(struct hapd_interfaces *ifaces, char *buf);
+int hostapd_remove_iface(struct hapd_interfaces *ifaces, char *buf);
+
+/* utils.c */
+int hostapd_register_probereq_cb(struct hostapd_data *hapd,
+                                int (*cb)(void *ctx, const u8 *sa,
+                                          const u8 *da, const u8 *bssid,
+                                          const u8 *ie, size_t ie_len,
+                                          int ssi_signal),
+                                void *ctx);
+void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr);
+
+/* drv_callbacks.c (TODO: move to somewhere else?) */
+int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
+                       const u8 *ie, size_t ielen, int reassoc);
+void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
+void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr);
+int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
+                        const u8 *bssid, const u8 *ie, size_t ie_len,
+                        int ssi_signal);
+void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
+                            int offset);
+
+const struct hostapd_eap_user *
+hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
+                    size_t identity_len, int phase2);
+#endif
+
+#endif /* HOSTAPD_H */
diff --git a/components/wpa_supplicant/include/wpa/ieee80211_crypto.h b/components/wpa_supplicant/include/wpa/ieee80211_crypto.h
new file mode 100644 (file)
index 0000000..be0fb9a
--- /dev/null
@@ -0,0 +1,226 @@
+/*-
+ * Copyright (c) 2001 Atsushi Onoe
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * copyright (c) 2010-2011  Espressif System
+ */
+#ifndef _NET80211_IEEE80211_CRYPTO_H_
+#define _NET80211_IEEE80211_CRYPTO_H_
+
+//#include "pp/esf_buf.h"
+
+/*
+ * 802.11 protocol crypto-related definitions.
+ */
+#define        IEEE80211_KEYBUF_SIZE   16
+#define        IEEE80211_MICBUF_SIZE   (8+8)   /* space for both tx+rx keys */
+
+/*
+ * Old WEP-style key.  Deprecated.
+ */
+
+#if 0
+struct ieee80211_rsnparms {
+       uint8_t         rsn_mcastcipher;        /* mcast/group cipher */
+       uint8_t         rsn_mcastkeylen;        /* mcast key length */
+       uint8_t         rsn_ucastcipher;        /* selected unicast cipher */
+       uint8_t         rsn_ucastkeylen;        /* unicast key length */
+       uint8_t         rsn_keymgmt;            /* selected key mgmt algo */
+       uint16_t        rsn_caps;               /* capabilities */
+};
+#endif //0000
+
+/*
+ * Template for a supported cipher.  Ciphers register with the
+ * crypto code and are typically loaded as separate modules
+ * (the null cipher is always present).
+ * XXX may need refcnts
+ */
+
+/*
+ * Crypto key state.  There is sufficient room for all supported
+ * ciphers (see below).  The underlying ciphers are handled
+ * separately through loadable cipher modules that register with
+ * the generic crypto support.  A key has a reference to an instance
+ * of the cipher; any per-key state is hung off wk_private by the
+ * cipher when it is attached.  Ciphers are automatically called
+ * to detach and cleanup any such state when the key is deleted.
+ *
+ * The generic crypto support handles encap/decap of cipher-related
+ * frame contents for both hardware- and software-based implementations.
+ * A key requiring software crypto support is automatically flagged and
+ * the cipher is expected to honor this and do the necessary work.
+ * Ciphers such as TKIP may also support mixed hardware/software
+ * encrypt/decrypt and MIC processing.
+ */
+typedef uint16_t ieee80211_keyix;      /* h/w key index */
+
+struct ieee80211_key {
+       uint8_t         wk_keylen;      /* key length in bytes */
+       uint8_t         wk_pad;
+       uint16_t        wk_flags;
+#define        IEEE80211_KEY_XMIT      0x0001  /* key used for xmit */
+#define        IEEE80211_KEY_RECV      0x0002  /* key used for recv */
+#define        IEEE80211_KEY_GROUP     0x0004  /* key used for WPA group operation */
+#define        IEEE80211_KEY_SWENCRYPT 0x0010  /* host-based encrypt */
+#define        IEEE80211_KEY_SWDECRYPT 0x0020  /* host-based decrypt */
+#define        IEEE80211_KEY_SWENMIC   0x0040  /* host-based enmic */
+#define        IEEE80211_KEY_SWDEMIC   0x0080  /* host-based demic */
+#define        IEEE80211_KEY_DEVKEY    0x0100  /* device key request completed */
+#define        IEEE80211_KEY_CIPHER0   0x1000  /* cipher-specific action 0 */
+#define        IEEE80211_KEY_CIPHER1   0x2000  /* cipher-specific action 1 */
+#define IEEE80211_KEY_EMPTY     0x0000
+       ieee80211_keyix wk_keyix;       /* h/w key index */
+       ieee80211_keyix wk_rxkeyix;     /* optional h/w rx key index */
+       uint8_t         wk_key[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE];
+#define        wk_txmic        wk_key+IEEE80211_KEYBUF_SIZE+0  /* XXX can't () right */
+#define        wk_rxmic        wk_key+IEEE80211_KEYBUF_SIZE+8  /* XXX can't () right */
+                                       /* key receive sequence counter */
+       uint64_t        wk_keyrsc[IEEE80211_TID_SIZE];
+       uint64_t        wk_keytsc;      /* key transmit sequence counter */
+       const struct ieee80211_cipher *wk_cipher;
+       //void          *wk_private;    /* private cipher state */
+       //uint8_t               wk_macaddr[IEEE80211_ADDR_LEN]; //JLU: no need ...
+};
+#define        IEEE80211_KEY_COMMON            /* common flags passed in by apps */\
+       (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV | IEEE80211_KEY_GROUP)
+#define        IEEE80211_KEY_DEVICE            /* flags owned by device driver */\
+       (IEEE80211_KEY_DEVKEY|IEEE80211_KEY_CIPHER0|IEEE80211_KEY_CIPHER1)
+
+#define        IEEE80211_KEY_SWCRYPT \
+       (IEEE80211_KEY_SWENCRYPT | IEEE80211_KEY_SWDECRYPT)
+#define        IEEE80211_KEY_SWMIC     (IEEE80211_KEY_SWENMIC | IEEE80211_KEY_SWDEMIC)
+
+//#define      IEEE80211_KEYIX_NONE    ((ieee80211_keyix) -1)
+
+/*
+ * NB: these values are ordered carefully; there are lots of
+ * of implications in any reordering.  Beware that 4 is used
+ * only to indicate h/w TKIP MIC support in driver capabilities;
+ * there is no separate cipher support (it's rolled into the
+ * TKIP cipher support).
+ */
+#define        IEEE80211_CIPHER_NONE           0       /* pseudo value */
+#define        IEEE80211_CIPHER_TKIP           1
+#define        IEEE80211_CIPHER_AES_OCB        2
+#define        IEEE80211_CIPHER_AES_CCM        3
+#define        IEEE80211_CIPHER_TKIPMIC        4       /* TKIP MIC capability */
+#define        IEEE80211_CIPHER_CKIP           5
+#define        IEEE80211_CIPHER_WEP            6
+#define        IEEE80211_CIPHER_WEP40          7
+#define        IEEE80211_CIPHER_WEP104         8
+
+
+#define        IEEE80211_CIPHER_MAX            (IEEE80211_CIPHER_NONE+2)
+
+/* capability bits in ic_cryptocaps/iv_cryptocaps */
+#define        IEEE80211_CRYPTO_NONE           (1<<IEEE80211_CIPHER_NONE)
+#define        IEEE80211_CRYPTO_WEP            (1<<IEEE80211_CIPHER_WEP)
+#define        IEEE80211_CRYPTO_WEP40          (1<<IEEE80211_CIPHER_WEP40)
+#define        IEEE80211_CRYPTO_WEP104 (1<<IEEE80211_CIPHER_WEP104)
+#define        IEEE80211_CRYPTO_TKIP           (1<<IEEE80211_CIPHER_TKIP)
+#define        IEEE80211_CRYPTO_AES_OCB        (1<<IEEE80211_CIPHER_AES_OCB)
+#define        IEEE80211_CRYPTO_AES_CCM        (1<<IEEE80211_CIPHER_AES_CCM)
+#define        IEEE80211_CRYPTO_TKIPMIC        (1<<IEEE80211_CIPHER_TKIPMIC)
+#define        IEEE80211_CRYPTO_CKIP           (1<<IEEE80211_CIPHER_CKIP)
+
+struct ieee80211_cipher {
+       u_int   ic_cipher;              /* IEEE80211_CIPHER_* */
+       u_int   ic_header;              /* size of privacy header (bytes) */
+       u_int   ic_trailer;             /* size of privacy trailer (bytes) */
+       u_int   ic_miclen;              /* size of mic trailer (bytes) */
+//     int     (*ic_setkey)(struct ieee80211_key *);
+       int     (*ic_encap)(struct ieee80211_key *, esf_buf_t *, uint8_t);
+       int     (*ic_decap)(struct ieee80211_key *, esf_buf_t *, int);
+#ifdef EAGLE_SW_MIC
+       int     (*ic_enmic)(struct ieee80211_key *, esf_buf_t *, int);
+       int     (*ic_demic)(struct ieee80211_key *, esf_buf_t *, int);
+#endif /* EAGLE_SW_CRYPTO */
+};
+
+struct ieee80211com;
+struct ieee80211_conn;
+
+#define        IEEE80211_KEY_UNDEFINED(k) \
+       ((k)->wk_cipher == &ieee80211_cipher_none)
+
+struct ieee80211_key *ieee80211_crypto_encap(struct ieee80211_conn *,
+               esf_buf *);
+
+struct ieee80211_key *ieee80211_crypto_decap(struct ieee80211_conn *,
+               esf_buf *, int);
+
+#if 0 //H/W MIC
+/*
+ * Check and remove any MIC.
+ */
+static INLINE int
+ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k,
+       esf_buf *m, int force)
+{
+       const struct ieee80211_cipher *cip = k->wk_cipher;
+       return (cip->ic_miclen > 0 ? cip->ic_demic(k, m, force) : 1);
+}
+
+/*
+ * Add any MIC.
+ */
+static INLINE int
+ieee80211_crypto_enmic(struct ieee80211vap *vap,
+       struct ieee80211_key *k, esf_buf *m, int force)
+{
+       const struct ieee80211_cipher *cip = k->wk_cipher;
+       return (cip->ic_miclen > 0 ? cip->ic_enmic(k, m, force) : 1);
+}
+#endif //0000
+
+/* 
+ * Setup crypto support for a device/shared instance.
+ */
+void ieee80211_crypto_attach(struct ieee80211com *ic);
+
+/* 
+ * Reset key state to an unused state.  The crypto
+ * key allocation mechanism insures other state (e.g.
+ * key data) is properly setup before a key is used.
+ */
+static inline void
+ieee80211_crypto_resetkey(struct ieee80211_key *k)
+{
+       k->wk_cipher = NULL;
+       k->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV;
+}
+
+/*
+ * Crypt-related notification methods.
+ */
+//void ieee80211_notify_replay_failure(const struct ieee80211_frame *, const struct ieee80211_key *,
+//             uint64_t rsc, int tid);
+//void ieee80211_notify_michael_failure(const struct ieee80211_frame *, u_int keyix);
+
+#endif /* _NET80211_IEEE80211_CRYPTO_H_ */
diff --git a/components/wpa_supplicant/include/wpa/ieee802_11_defs.h b/components/wpa_supplicant/include/wpa/ieee802_11_defs.h
new file mode 100644 (file)
index 0000000..4881e39
--- /dev/null
@@ -0,0 +1,607 @@
+/*
+ * IEEE 802.11 Frame type definitions
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2007-2008 Intel Corporation
+ *
+ * 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.
+ */
+
+#ifndef IEEE802_11_DEFS_H
+#define IEEE802_11_DEFS_H
+
+/* IEEE 802.11 defines */
+
+#define WLAN_FC_PVER           0x0003
+#define WLAN_FC_TODS           0x0100
+#define WLAN_FC_FROMDS         0x0200
+#define WLAN_FC_MOREFRAG       0x0400
+#define WLAN_FC_RETRY          0x0800
+#define WLAN_FC_PWRMGT         0x1000
+#define WLAN_FC_MOREDATA       0x2000
+#define WLAN_FC_ISWEP          0x4000
+#define WLAN_FC_ORDER          0x8000
+
+#define WLAN_FC_GET_TYPE(fc)   (((fc) & 0x000c) >> 2)
+#define WLAN_FC_GET_STYPE(fc)  (((fc) & 0x00f0) >> 4)
+
+#define WLAN_GET_SEQ_FRAG(seq) ((seq) & (BIT(3) | BIT(2) | BIT(1) | BIT(0)))
+#define WLAN_GET_SEQ_SEQ(seq) \
+       (((seq) & (~(BIT(3) | BIT(2) | BIT(1) | BIT(0)))) >> 4)
+
+#define WLAN_FC_TYPE_MGMT              0
+#define WLAN_FC_TYPE_CTRL              1
+#define WLAN_FC_TYPE_DATA              2
+
+/* management */
+#define WLAN_FC_STYPE_ASSOC_REQ                0
+#define WLAN_FC_STYPE_ASSOC_RESP       1
+#define WLAN_FC_STYPE_REASSOC_REQ      2
+#define WLAN_FC_STYPE_REASSOC_RESP     3
+#define WLAN_FC_STYPE_PROBE_REQ                4
+#define WLAN_FC_STYPE_PROBE_RESP       5
+#define WLAN_FC_STYPE_BEACON           8
+#define WLAN_FC_STYPE_ATIM             9
+#define WLAN_FC_STYPE_DISASSOC         10
+#define WLAN_FC_STYPE_AUTH             11
+#define WLAN_FC_STYPE_DEAUTH           12
+#define WLAN_FC_STYPE_ACTION           13
+
+/* control */
+#define WLAN_FC_STYPE_PSPOLL           10
+#define WLAN_FC_STYPE_RTS              11
+#define WLAN_FC_STYPE_CTS              12
+#define WLAN_FC_STYPE_ACK              13
+#define WLAN_FC_STYPE_CFEND            14
+#define WLAN_FC_STYPE_CFENDACK         15
+
+/* data */
+#define WLAN_FC_STYPE_DATA             0
+#define WLAN_FC_STYPE_DATA_CFACK       1
+#define WLAN_FC_STYPE_DATA_CFPOLL      2
+#define WLAN_FC_STYPE_DATA_CFACKPOLL   3
+#define WLAN_FC_STYPE_NULLFUNC         4
+#define WLAN_FC_STYPE_CFACK            5
+#define WLAN_FC_STYPE_CFPOLL           6
+#define WLAN_FC_STYPE_CFACKPOLL                7
+#define WLAN_FC_STYPE_QOS_DATA         8
+
+/* Authentication algorithms */
+#define WLAN_AUTH_OPEN                 0
+#define WLAN_AUTH_SHARED_KEY           1
+#define WLAN_AUTH_FT                   2
+#define WLAN_AUTH_LEAP                 128
+
+#define WLAN_AUTH_CHALLENGE_LEN 128
+
+#define WLAN_CAPABILITY_ESS BIT(0)
+#define WLAN_CAPABILITY_IBSS BIT(1)
+#define WLAN_CAPABILITY_CF_POLLABLE BIT(2)
+#define WLAN_CAPABILITY_CF_POLL_REQUEST BIT(3)
+#define WLAN_CAPABILITY_PRIVACY BIT(4)
+#define WLAN_CAPABILITY_SHORT_PREAMBLE BIT(5)
+#define WLAN_CAPABILITY_PBCC BIT(6)
+#define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7)
+#define WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8)
+#define WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10)
+#define WLAN_CAPABILITY_DSSS_OFDM BIT(13)
+
+/* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */
+#define WLAN_STATUS_SUCCESS 0
+#define WLAN_STATUS_UNSPECIFIED_FAILURE 1
+#define WLAN_STATUS_CAPS_UNSUPPORTED 10
+#define WLAN_STATUS_REASSOC_NO_ASSOC 11
+#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12
+#define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13
+#define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14
+#define WLAN_STATUS_CHALLENGE_FAIL 15
+#define WLAN_STATUS_AUTH_TIMEOUT 16
+#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17
+#define WLAN_STATUS_ASSOC_DENIED_RATES 18
+/* IEEE 802.11b */
+#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19
+#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20
+#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21
+/* IEEE 802.11h */
+#define WLAN_STATUS_SPEC_MGMT_REQUIRED 22
+#define WLAN_STATUS_PWR_CAPABILITY_NOT_VALID 23
+#define WLAN_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24
+/* IEEE 802.11g */
+#define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25
+#define WLAN_STATUS_ASSOC_DENIED_NO_ER_PBCC 26
+#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 27
+#define WLAN_STATUS_R0KH_UNREACHABLE 28
+/* IEEE 802.11w */
+#define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30
+#define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31
+#define WLAN_STATUS_UNSPECIFIED_QOS_FAILURE 32
+#define WLAN_STATUS_REQUEST_DECLINED 37
+#define WLAN_STATUS_INVALID_PARAMETERS 38
+/* IEEE 802.11i */
+#define WLAN_STATUS_INVALID_IE 40
+#define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41
+#define WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID 42
+#define WLAN_STATUS_AKMP_NOT_VALID 43
+#define WLAN_STATUS_UNSUPPORTED_RSN_IE_VERSION 44
+#define WLAN_STATUS_INVALID_RSN_IE_CAPAB 45
+#define WLAN_STATUS_CIPHER_REJECTED_PER_POLICY 46
+#define WLAN_STATUS_TS_NOT_CREATED 47
+#define WLAN_STATUS_DIRECT_LINK_NOT_ALLOWED 48
+#define WLAN_STATUS_DEST_STA_NOT_PRESENT 49
+#define WLAN_STATUS_DEST_STA_NOT_QOS_STA 50
+#define WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE 51
+/* IEEE 802.11r */
+#define WLAN_STATUS_INVALID_FT_ACTION_FRAME_COUNT 52
+#define WLAN_STATUS_INVALID_PMKID 53
+#define WLAN_STATUS_INVALID_MDIE 54
+#define WLAN_STATUS_INVALID_FTIE 55
+
+/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */
+#define WLAN_REASON_UNSPECIFIED 1
+#define WLAN_REASON_PREV_AUTH_NOT_VALID 2
+#define WLAN_REASON_DEAUTH_LEAVING 3
+#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4
+#define WLAN_REASON_DISASSOC_AP_BUSY 5
+#define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6
+#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7
+#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8
+#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9
+/* IEEE 802.11h */
+#define WLAN_REASON_PWR_CAPABILITY_NOT_VALID 10
+#define WLAN_REASON_SUPPORTED_CHANNEL_NOT_VALID 11
+/* IEEE 802.11i */
+#define WLAN_REASON_INVALID_IE 13
+#define WLAN_REASON_MICHAEL_MIC_FAILURE 14
+#define WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT 15
+#define WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT 16
+#define WLAN_REASON_IE_IN_4WAY_DIFFERS 17
+#define WLAN_REASON_GROUP_CIPHER_NOT_VALID 18
+#define WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID 19
+#define WLAN_REASON_AKMP_NOT_VALID 20
+#define WLAN_REASON_UNSUPPORTED_RSN_IE_VERSION 21
+#define WLAN_REASON_INVALID_RSN_IE_CAPAB 22
+#define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23
+#define WLAN_REASON_CIPHER_SUITE_REJECTED 24
+
+
+/* Information Element IDs */
+#define WLAN_EID_SSID 0
+#define WLAN_EID_SUPP_RATES 1
+#define WLAN_EID_FH_PARAMS 2
+#define WLAN_EID_DS_PARAMS 3
+#define WLAN_EID_CF_PARAMS 4
+#define WLAN_EID_TIM 5
+#define WLAN_EID_IBSS_PARAMS 6
+#define WLAN_EID_COUNTRY 7
+#define WLAN_EID_CHALLENGE 16
+/* EIDs defined by IEEE 802.11h - START */
+#define WLAN_EID_PWR_CONSTRAINT 32
+#define WLAN_EID_PWR_CAPABILITY 33
+#define WLAN_EID_TPC_REQUEST 34
+#define WLAN_EID_TPC_REPORT 35
+#define WLAN_EID_SUPPORTED_CHANNELS 36
+#define WLAN_EID_CHANNEL_SWITCH 37
+#define WLAN_EID_MEASURE_REQUEST 38
+#define WLAN_EID_MEASURE_REPORT 39
+#define WLAN_EID_QUITE 40
+#define WLAN_EID_IBSS_DFS 41
+/* EIDs defined by IEEE 802.11h - END */
+#define WLAN_EID_ERP_INFO 42
+#define WLAN_EID_HT_CAP 45
+#define WLAN_EID_RSN 48
+#define WLAN_EID_EXT_SUPP_RATES 50
+#define WLAN_EID_MOBILITY_DOMAIN 54
+#define WLAN_EID_FAST_BSS_TRANSITION 55
+#define WLAN_EID_TIMEOUT_INTERVAL 56
+#define WLAN_EID_RIC_DATA 57
+#define WLAN_EID_HT_OPERATION 61
+#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
+#define WLAN_EID_20_40_BSS_COEXISTENCE 72
+#define WLAN_EID_20_40_BSS_INTOLERANT 73
+#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74
+#define WLAN_EID_MMIE 76
+#define WLAN_EID_VENDOR_SPECIFIC 221
+
+
+/* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */
+#define WLAN_ACTION_SPECTRUM_MGMT 0
+#define WLAN_ACTION_QOS 1
+#define WLAN_ACTION_DLS 2
+#define WLAN_ACTION_BLOCK_ACK 3
+#define WLAN_ACTION_PUBLIC 4
+#define WLAN_ACTION_RADIO_MEASUREMENT 5
+#define WLAN_ACTION_FT 6
+#define WLAN_ACTION_HT 7
+#define WLAN_ACTION_SA_QUERY 8
+#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */
+
+/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */
+#define WLAN_SA_QUERY_REQUEST 0
+#define WLAN_SA_QUERY_RESPONSE 1
+
+#define WLAN_SA_QUERY_TR_ID_LEN 2
+
+/* Timeout Interval Type */
+#define WLAN_TIMEOUT_REASSOC_DEADLINE 1
+#define WLAN_TIMEOUT_KEY_LIFETIME 2
+#define WLAN_TIMEOUT_ASSOC_COMEBACK 3
+
+
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
+struct ieee80211_hdr {
+       le16 frame_control;
+       le16 duration_id;
+       u8 addr1[6];
+       u8 addr2[6];
+       u8 addr3[6];
+       le16 seq_ctrl;
+       /* followed by 'u8 addr4[6];' if ToDS and FromDS is set in data frame
+        */
+} STRUCT_PACKED;
+
+#define IEEE80211_DA_FROMDS addr1
+#define IEEE80211_BSSID_FROMDS addr2
+#define IEEE80211_SA_FROMDS addr3
+
+#define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr))
+
+#define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4))
+
+struct ieee80211_mgmt {
+       le16 frame_control;
+       le16 duration;
+       u8 da[6];
+       u8 sa[6];
+       u8 bssid[6];
+       le16 seq_ctrl;
+       union {
+               struct {
+                       le16 auth_alg;
+                       le16 auth_transaction;
+                       le16 status_code;
+                       /* possibly followed by Challenge text */
+                       u8 variable[0];
+               } STRUCT_PACKED auth;
+               struct {
+                       le16 reason_code;
+               } STRUCT_PACKED deauth;
+               struct {
+                       le16 capab_info;
+                       le16 listen_interval;
+                       /* followed by SSID and Supported rates */
+                       u8 variable[0];
+               } STRUCT_PACKED assoc_req;
+               struct {
+                       le16 capab_info;
+                       le16 status_code;
+                       le16 aid;
+                       /* followed by Supported rates */
+                       u8 variable[0];
+               } STRUCT_PACKED assoc_resp, reassoc_resp;
+               struct {
+                       le16 capab_info;
+                       le16 listen_interval;
+                       u8 current_ap[6];
+                       /* followed by SSID and Supported rates */
+                       u8 variable[0];
+               } STRUCT_PACKED reassoc_req;
+               struct {
+                       le16 reason_code;
+               } STRUCT_PACKED disassoc;
+               struct {
+                       u8 timestamp[8];
+                       le16 beacon_int;
+                       le16 capab_info;
+                       /* followed by some of SSID, Supported rates,
+                        * FH Params, DS Params, CF Params, IBSS Params, TIM */
+                       u8 variable[0];
+               } STRUCT_PACKED beacon;
+               struct {
+                       /* only variable items: SSID, Supported rates */
+                       u8 variable[0];
+               } STRUCT_PACKED probe_req;
+               struct {
+                       u8 timestamp[8];
+                       le16 beacon_int;
+                       le16 capab_info;
+                       /* followed by some of SSID, Supported rates,
+                        * FH Params, DS Params, CF Params, IBSS Params */
+                       u8 variable[0];
+               } STRUCT_PACKED probe_resp;
+               struct {
+                       u8 category;
+                       union {
+                               struct {
+                                       u8 action_code;
+                                       u8 dialog_token;
+                                       u8 status_code;
+                                       u8 variable[0];
+                               } STRUCT_PACKED wmm_action;
+                               struct{
+                                       u8 action_code;
+                                       u8 element_id;
+                                       u8 length;
+                                       u8 switch_mode;
+                                       u8 new_chan;
+                                       u8 switch_count;
+                               } STRUCT_PACKED chan_switch;
+                               struct {
+                                       u8 action;
+                                       u8 sta_addr[ETH_ALEN];
+                                       u8 target_ap_addr[ETH_ALEN];
+                                       u8 variable[0]; /* FT Request */
+                               } STRUCT_PACKED ft_action_req;
+                               struct {
+                                       u8 action;
+                                       u8 sta_addr[ETH_ALEN];
+                                       u8 target_ap_addr[ETH_ALEN];
+                                       le16 status_code;
+                                       u8 variable[0]; /* FT Request */
+                               } STRUCT_PACKED ft_action_resp;
+                               struct {
+                                       u8 action;
+                                       u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
+                               } STRUCT_PACKED sa_query_req;
+                               struct {
+                                       u8 action; /* */
+                                       u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
+                               } STRUCT_PACKED sa_query_resp;
+                       } u;
+               } STRUCT_PACKED action;
+       } u;
+} STRUCT_PACKED;
+
+
+struct ieee80211_ht_capabilities {
+       le16 ht_capabilities_info;
+       u8 a_mpdu_params;
+       u8 supported_mcs_set[16];
+       le16 ht_extended_capabilities;
+       le32 tx_bf_capability_info;
+       u8 asel_capabilities;
+} STRUCT_PACKED;
+
+
+struct ieee80211_ht_operation {
+       u8 control_chan;
+       u8 ht_param;
+       le16 operation_mode;
+       le16 stbc_param;
+       u8 basic_set[16];
+} STRUCT_PACKED;
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
+
+#define ERP_INFO_NON_ERP_PRESENT BIT(0)
+#define ERP_INFO_USE_PROTECTION BIT(1)
+#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2)
+
+
+#define HT_CAP_INFO_LDPC_CODING_CAP            ((u16) BIT(0))
+#define HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET     ((u16) BIT(1))
+#define HT_CAP_INFO_SMPS_MASK                  ((u16) (BIT(2) | BIT(3)))
+#define HT_CAP_INFO_SMPS_STATIC                        ((u16) 0)
+#define HT_CAP_INFO_SMPS_DYNAMIC               ((u16) BIT(2))
+#define HT_CAP_INFO_SMPS_DISABLED              ((u16) (BIT(2) | BIT(3)))
+#define HT_CAP_INFO_GREEN_FIELD                        ((u16) BIT(4))
+#define HT_CAP_INFO_SHORT_GI20MHZ              ((u16) BIT(5))
+#define HT_CAP_INFO_SHORT_GI40MHZ              ((u16) BIT(6))
+#define HT_CAP_INFO_TX_STBC                    ((u16) BIT(7))
+#define HT_CAP_INFO_RX_STBC_MASK               ((u16) (BIT(8) | BIT(9)))
+#define HT_CAP_INFO_RX_STBC_1                  ((u16) BIT(8))
+#define HT_CAP_INFO_RX_STBC_12                 ((u16) BIT(9))
+#define HT_CAP_INFO_RX_STBC_123                        ((u16) (BIT(8) | BIT(9)))
+#define HT_CAP_INFO_DELAYED_BA                 ((u16) BIT(10))
+#define HT_CAP_INFO_MAX_AMSDU_SIZE             ((u16) BIT(11))
+#define HT_CAP_INFO_DSSS_CCK40MHZ              ((u16) BIT(12))
+#define HT_CAP_INFO_PSMP_SUPP                  ((u16) BIT(13))
+#define HT_CAP_INFO_40MHZ_INTOLERANT           ((u16) BIT(14))
+#define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT  ((u16) BIT(15))
+
+
+#define EXT_HT_CAP_INFO_PCO                    ((u16) BIT(0))
+#define EXT_HT_CAP_INFO_TRANS_TIME_OFFSET      1
+#define EXT_HT_CAP_INFO_MCS_FEEDBACK_OFFSET    8
+#define EXT_HT_CAP_INFO_HTC_SUPPORTED          ((u16) BIT(10))
+#define EXT_HT_CAP_INFO_RD_RESPONDER           ((u16) BIT(11))
+
+
+#define TX_BEAMFORM_CAP_TXBF_CAP ((u32) BIT(0))
+#define TX_BEAMFORM_CAP_RX_STAGGERED_SOUNDING_CAP ((u32) BIT(1))
+#define TX_BEAMFORM_CAP_TX_STAGGERED_SOUNDING_CAP ((u32) BIT(2))
+#define TX_BEAMFORM_CAP_RX_ZLF_CAP ((u32) BIT(3))
+#define TX_BEAMFORM_CAP_TX_ZLF_CAP ((u32) BIT(4))
+#define TX_BEAMFORM_CAP_IMPLICIT_ZLF_CAP ((u32) BIT(5))
+#define TX_BEAMFORM_CAP_CALIB_OFFSET 6
+#define TX_BEAMFORM_CAP_EXPLICIT_CSI_TXBF_CAP ((u32) BIT(8))
+#define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_CAP ((u32) BIT(9))
+#define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_CAP ((u32) BIT(10))
+#define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_OFFSET 11
+#define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_FEEDBACK_OFFSET 13
+#define TX_BEAMFORM_CAP_EXPLICIT_COMPRESSED_STEERING_MATRIX_FEEDBACK_OFFSET 15
+#define TX_BEAMFORM_CAP_MINIMAL_GROUPING_OFFSET 17
+#define TX_BEAMFORM_CAP_CSI_NUM_BEAMFORMER_ANT_OFFSET 19
+#define TX_BEAMFORM_CAP_UNCOMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 21
+#define TX_BEAMFORM_CAP_COMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 23
+#define TX_BEAMFORM_CAP_SCI_MAX_OF_ROWS_BEANFORMER_SUPPORTED_OFFSET 25
+
+
+#define ASEL_CAPABILITY_ASEL_CAPABLE ((u8) BIT(0))
+#define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(1))
+#define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(2))
+#define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_CAP ((u8) BIT(3))
+#define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_CAP ((u8) BIT(4))
+#define ASEL_CAPABILITY_RX_AS_CAP ((u8) BIT(5))
+#define ASEL_CAPABILITY_TX_SOUND_PPDUS_CAP ((u8) BIT(6))
+
+#define HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK       ((u8) BIT(0) | BIT(1))
+#define HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE          ((u8) BIT(0))
+#define HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW          ((u8) BIT(0) | BIT(1))
+#define HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH          ((u8) BIT(2))
+#define HT_INFO_HT_PARAM_RIFS_MODE                     ((u8) BIT(3))
+#define HT_INFO_HT_PARAM_CTRL_ACCESS_ONLY              ((u8) BIT(4))
+#define HT_INFO_HT_PARAM_SRV_INTERVAL_GRANULARITY      ((u8) BIT(5))
+
+
+#define OP_MODE_PURE                    0
+#define OP_MODE_MAY_BE_LEGACY_STAS      1
+#define OP_MODE_20MHZ_HT_STA_ASSOCED    2
+#define OP_MODE_MIXED                   3
+
+#define HT_INFO_OPERATION_MODE_OP_MODE_MASK    \
+               ((le16) (0x0001 | 0x0002))
+#define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET          0
+#define HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT     ((u8) BIT(2))
+#define HT_INFO_OPERATION_MODE_TRANSMIT_BURST_LIMIT    ((u8) BIT(3))
+#define HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT      ((u8) BIT(4))
+
+#define HT_INFO_STBC_PARAM_DUAL_BEACON                 ((u16) BIT(6))
+#define HT_INFO_STBC_PARAM_DUAL_STBC_PROTECT           ((u16) BIT(7))
+#define HT_INFO_STBC_PARAM_SECONDARY_BCN               ((u16) BIT(8))
+#define HT_INFO_STBC_PARAM_LSIG_TXOP_PROTECT_ALLOWED   ((u16) BIT(9))
+#define HT_INFO_STBC_PARAM_PCO_ACTIVE                  ((u16) BIT(10))
+#define HT_INFO_STBC_PARAM_PCO_PHASE                   ((u16) BIT(11))
+
+
+#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs)
+                               * 00:50:F2 */
+#define WPA_IE_VENDOR_TYPE 0x0050f201
+#define WPS_IE_VENDOR_TYPE 0x0050f204
+
+#define WMM_OUI_TYPE 2
+#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
+#define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1
+#define WMM_OUI_SUBTYPE_TSPEC_ELEMENT 2
+#define WMM_VERSION 1
+
+#define WMM_ACTION_CODE_ADDTS_REQ 0
+#define WMM_ACTION_CODE_ADDTS_RESP 1
+#define WMM_ACTION_CODE_DELTS 2
+
+#define WMM_ADDTS_STATUS_ADMISSION_ACCEPTED 0
+#define WMM_ADDTS_STATUS_INVALID_PARAMETERS 1
+/* 2 - Reserved */
+#define WMM_ADDTS_STATUS_REFUSED 3
+/* 4-255 - Reserved */
+
+/* WMM TSPEC Direction Field Values */
+#define WMM_TSPEC_DIRECTION_UPLINK 0
+#define WMM_TSPEC_DIRECTION_DOWNLINK 1
+/* 2 - Reserved */
+#define WMM_TSPEC_DIRECTION_BI_DIRECTIONAL 3
+
+/*
+ * WMM Information Element (used in (Re)Association Request frames; may also be
+ * used in Beacon frames)
+ */
+struct wmm_information_element {
+       /* Element ID: 221 (0xdd); Length: 7 */
+       /* required fields for WMM version 1 */
+       u8 oui[3]; /* 00:50:f2 */
+       u8 oui_type; /* 2 */
+       u8 oui_subtype; /* 0 */
+       u8 version; /* 1 for WMM version 1.0 */
+       u8 qos_info; /* AP/STA specific QoS info */
+
+} STRUCT_PACKED;
+
+#define WMM_AC_AIFSN_MASK 0x0f
+#define WMM_AC_AIFNS_SHIFT 0
+#define WMM_AC_ACM 0x10
+#define WMM_AC_ACI_MASK 0x60
+#define WMM_AC_ACI_SHIFT 5
+
+#define WMM_AC_ECWMIN_MASK 0x0f
+#define WMM_AC_ECWMIN_SHIFT 0
+#define WMM_AC_ECWMAX_MASK 0xf0
+#define WMM_AC_ECWMAX_SHIFT 4
+
+struct wmm_ac_parameter {
+       u8 aci_aifsn; /* AIFSN, ACM, ACI */
+       u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */
+       le16 txop_limit;
+}  STRUCT_PACKED;
+
+/*
+ * WMM Parameter Element (used in Beacon, Probe Response, and (Re)Association
+ * Response frmaes)
+ */
+struct wmm_parameter_element {
+       /* Element ID: 221 (0xdd); Length: 24 */
+       /* required fields for WMM version 1 */
+       u8 oui[3]; /* 00:50:f2 */
+       u8 oui_type; /* 2 */
+       u8 oui_subtype; /* 1 */
+       u8 version; /* 1 for WMM version 1.0 */
+       u8 qos_info; /* AP/STA specif QoS info */
+       u8 reserved; /* 0 */
+       struct wmm_ac_parameter ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */
+
+} STRUCT_PACKED;
+
+/* WMM TSPEC Element */
+struct wmm_tspec_element {
+       u8 eid; /* 221 = 0xdd */
+       u8 length; /* 6 + 55 = 61 */
+       u8 oui[3]; /* 00:50:f2 */
+       u8 oui_type; /* 2 */
+       u8 oui_subtype; /* 2 */
+       u8 version; /* 1 */
+       /* WMM TSPEC body (55 octets): */
+       u8 ts_info[3];
+       le16 nominal_msdu_size;
+       le16 maximum_msdu_size;
+       le32 minimum_service_interval;
+       le32 maximum_service_interval;
+       le32 inactivity_interval;
+       le32 suspension_interval;
+       le32 service_start_time;
+       le32 minimum_data_rate;
+       le32 mean_data_rate;
+       le32 peak_data_rate;
+       le32 maximum_burst_size;
+       le32 delay_bound;
+       le32 minimum_phy_rate;
+       le16 surplus_bandwidth_allowance;
+       le16 medium_time;
+} STRUCT_PACKED;
+
+
+/* Access Categories / ACI to AC coding */
+enum {
+       WMM_AC_BE = 0 /* Best Effort */,
+       WMM_AC_BK = 1 /* Background */,
+       WMM_AC_VI = 2 /* Video */,
+       WMM_AC_VO = 3 /* Voice */
+};
+
+
+#define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */
+
+#define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */
+
+/* cipher suite selectors */
+#define WLAN_CIPHER_SUITE_USE_GROUP    0x000FAC00
+#define WLAN_CIPHER_SUITE_WEP40                0x000FAC01
+#define WLAN_CIPHER_SUITE_TKIP         0x000FAC02
+/* reserved:                           0x000FAC03 */
+#define WLAN_CIPHER_SUITE_CCMP         0x000FAC04
+#define WLAN_CIPHER_SUITE_WEP104       0x000FAC05
+#define WLAN_CIPHER_SUITE_AES_CMAC     0x000FAC06
+
+/* AKM suite selectors */
+#define WLAN_AKM_SUITE_8021X           0x000FAC01
+#define WLAN_AKM_SUITE_PSK             0x000FAC02
+
+#endif /* IEEE802_11_DEFS_H */
diff --git a/components/wpa_supplicant/include/wpa/ieee802_1x.h b/components/wpa_supplicant/include/wpa/ieee802_1x.h
new file mode 100644 (file)
index 0000000..e10ff7b
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * hostapd / IEEE 802.1X-2004 Authenticator
+ * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef IEEE802_1X_H
+#define IEEE802_1X_H
+
+struct hostapd_data;
+struct sta_info;
+struct eapol_state_machine;
+struct hostapd_config;
+struct hostapd_bss_config;
+struct hostapd_radius_attr;
+struct radius_msg;
+
+
+void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
+                       size_t len);
+
+#if 0
+void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta);
+void ieee802_1x_free_station(struct sta_info *sta);
+
+void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta);
+void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta);
+void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,
+                                  struct sta_info *sta, int authorized);
+void ieee802_1x_dump_state(FILE *f, const char *prefix, struct sta_info *sta);
+int ieee802_1x_init(struct hostapd_data *hapd);
+void ieee802_1x_deinit(struct hostapd_data *hapd);
+int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
+                        const u8 *buf, size_t len, int ack);
+int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
+                              const u8 *data, int len, int ack);
+u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len);
+u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
+                                int idx);
+struct wpabuf * ieee802_1x_get_radius_cui(struct eapol_state_machine *sm);
+const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len);
+void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm,
+                                   int enabled);
+void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm,
+                                 int valid);
+void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth);
+int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen);
+int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
+                          char *buf, size_t buflen);
+void hostapd_get_ntp_timestamp(u8 *buf);
+char *eap_type_text(u8 type);
+
+const char *radius_mode_txt(struct hostapd_data *hapd);
+int radius_sta_rate(struct hostapd_data *hapd, struct sta_info *sta);
+
+int add_common_radius_attr(struct hostapd_data *hapd,
+                          struct hostapd_radius_attr *req_attr,
+                          struct sta_info *sta,
+                          struct radius_msg *msg);
+#endif
+
+#endif /* IEEE802_1X_H */
diff --git a/components/wpa_supplicant/include/wpa/includes.h b/components/wpa_supplicant/include/wpa/includes.h
new file mode 100644 (file)
index 0000000..993bc49
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * wpa_supplicant/hostapd - Default include files
+ * Copyright (c) 2005-2006, 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 header file is included into all C files so that commonly used header
+ * files can be selected with OS specific ifdef blocks in one place instead of
+ * having to have OS/C library specific selection in many files.
+ */
+
+#ifndef INCLUDES_H
+#define INCLUDES_H
+
+/* Include possible build time configuration before including anything else */
+//#include "build_config.h"  //don't need anymore
+
+//#include <stdlib.h>
+//#include <stdio.h>
+//#include <string.h>
+//#include <ctype.h>
+//#include <time.h>
+
+#endif /* INCLUDES_H */
diff --git a/components/wpa_supplicant/include/wpa/list.h b/components/wpa_supplicant/include/wpa/list.h
new file mode 100644 (file)
index 0000000..c8dccee
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Doubly-linked list
+ * Copyright (c) 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.
+ */
+
+#ifndef LIST_H
+#define LIST_H
+
+/**
+ * struct dl_list - Doubly-linked list
+ */
+struct dl_list {
+       struct dl_list *next;
+       struct dl_list *prev;
+};
+
+static inline void dl_list_init(struct dl_list *list)
+{
+       list->next = list;
+       list->prev = list;
+}
+
+static inline void dl_list_add(struct dl_list *list, struct dl_list *item)
+{
+       item->next = list->next;
+       item->prev = list;
+       list->next->prev = item;
+       list->next = item;
+}
+
+static inline void dl_list_add_tail(struct dl_list *list, struct dl_list *item)
+{
+       dl_list_add(list->prev, item);
+}
+
+static inline void dl_list_del(struct dl_list *item)
+{
+       item->next->prev = item->prev;
+       item->prev->next = item->next;
+       item->next = NULL;
+       item->prev = NULL;
+}
+
+static inline int dl_list_empty(struct dl_list *list)
+{
+       return list->next == list;
+}
+
+static inline unsigned int dl_list_len(struct dl_list *list)
+{
+       struct dl_list *item;
+       int count = 0;
+       for (item = list->next; item != list; item = item->next)
+               count++;
+       return count;
+}
+
+#ifndef offsetof
+#define offsetof(type, member) ((long) &((type *) 0)->member)
+#endif
+
+#define dl_list_entry(item, type, member) \
+       ((type *) ((char *) item - offsetof(type, member)))
+
+#define dl_list_first(list, type, member) \
+       (dl_list_empty((list)) ? NULL : \
+        dl_list_entry((list)->next, type, member))
+
+#define dl_list_last(list, type, member) \
+       (dl_list_empty((list)) ? NULL : \
+        dl_list_entry((list)->prev, type, member))
+
+#define dl_list_for_each(item, list, type, member) \
+       for (item = dl_list_entry((list)->next, type, member); \
+            &item->member != (list); \
+            item = dl_list_entry(item->member.next, type, member))
+
+#define dl_list_for_each_safe(item, n, list, type, member) \
+       for (item = dl_list_entry((list)->next, type, member), \
+                    n = dl_list_entry(item->member.next, type, member); \
+            &item->member != (list); \
+            item = n, n = dl_list_entry(n->member.next, type, member))
+
+#define dl_list_for_each_reverse(item, list, type, member) \
+       for (item = dl_list_entry((list)->prev, type, member); \
+            &item->member != (list); \
+            item = dl_list_entry(item->member.prev, type, member))
+
+#define DEFINE_DL_LIST(name) \
+       struct dl_list name = { &(name), &(name) }
+
+#endif /* LIST_H */
diff --git a/components/wpa_supplicant/include/wpa/sta_info.h b/components/wpa_supplicant/include/wpa/sta_info.h
new file mode 100644 (file)
index 0000000..44874a2
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * hostapd / Station table
+ * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef STA_INFO_H
+#define STA_INFO_H
+
+/* STA flags */
+#define WLAN_STA_AUTH BIT(0)
+#define WLAN_STA_ASSOC BIT(1)
+#define WLAN_STA_PS BIT(2)
+#define WLAN_STA_TIM BIT(3)
+#define WLAN_STA_PERM BIT(4)
+#define WLAN_STA_AUTHORIZED BIT(5)
+#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */
+#define WLAN_STA_SHORT_PREAMBLE BIT(7)
+#define WLAN_STA_PREAUTH BIT(8)
+#define WLAN_STA_WMM BIT(9)
+#define WLAN_STA_MFP BIT(10)
+#define WLAN_STA_HT BIT(11)
+#define WLAN_STA_WPS BIT(12)
+#define WLAN_STA_MAYBE_WPS BIT(13)
+#define WLAN_STA_WDS BIT(14)
+#define WLAN_STA_ASSOC_REQ_OK BIT(15)
+#define WLAN_STA_WPS2 BIT(16)
+#define WLAN_STA_GAS BIT(17)
+#define WLAN_STA_VHT BIT(18)
+#define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
+#define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
+#define WLAN_STA_NONERP BIT(31)
+
+/* Maximum number of supported rates (from both Supported Rates and Extended
+ * Supported Rates IEs). */
+#define WLAN_SUPP_RATES_MAX 32
+
+
+struct sta_info {
+       struct sta_info *next; /* next entry in sta list */
+       struct sta_info *hnext; /* next entry in hash table list */
+       u8 addr[6];
+       u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */
+       u32 flags; /* Bitfield of WLAN_STA_* */
+       u16 capability;
+       u16 listen_interval; /* or beacon_int for APs */
+       u8 supported_rates[WLAN_SUPP_RATES_MAX];
+       int supported_rates_len;
+//     u8 qosinfo; /* Valid when WLAN_STA_WMM is set */
+
+//     unsigned int nonerp_set:1;
+//     unsigned int no_short_slot_time_set:1;
+//     unsigned int no_short_preamble_set:1;
+//     unsigned int no_ht_gf_set:1;
+//     unsigned int no_ht_set:1;
+//     unsigned int ht_20mhz_set:1;
+//     unsigned int no_p2p_set:1;
+
+       u16 auth_alg;
+//     u8 previous_ap[6];
+
+       enum {
+               STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH, STA_REMOVE
+       } timeout_next;
+
+//     u16 deauth_reason;
+//     u16 disassoc_reason;
+
+       /* IEEE 802.1X related data */
+//     struct eapol_state_machine *eapol_sm;
+
+       /* IEEE 802.11f (IAPP) related data */
+//     struct ieee80211_mgmt *last_assoc_req;
+
+//     u32 acct_session_id_hi;
+//     u32 acct_session_id_lo;
+//     time_t acct_session_start;
+//     int acct_session_started;
+//     int acct_terminate_cause; /* Acct-Terminate-Cause */
+//     int acct_interim_interval; /* Acct-Interim-Interval */
+
+//     unsigned long last_rx_bytes;
+//     unsigned long last_tx_bytes;
+//     u32 acct_input_gigawords; /* Acct-Input-Gigawords */
+//     u32 acct_output_gigawords; /* Acct-Output-Gigawords */
+
+//     u8 *challenge; /* IEEE 802.11 Shared Key Authentication Challenge */
+
+       struct wpa_state_machine *wpa_sm;
+//     struct rsn_preauth_interface *preauth_iface;
+
+       struct hostapd_ssid *ssid; /* SSID selection based on (Re)AssocReq */
+//     struct hostapd_ssid *ssid_probe; /* SSID selection based on ProbeReq */
+
+//     int vlan_id;
+        /* PSKs from RADIUS authentication server */
+//     struct hostapd_sta_wpa_psk_short *psk;
+
+//     char *identity; /* User-Name from RADIUS */
+//     char *radius_cui; /* Chargeable-User-Identity from RADIUS */
+
+//     struct ieee80211_ht_capabilities *ht_capabilities;
+//     struct ieee80211_vht_capabilities *vht_capabilities;
+
+#ifdef CONFIG_IEEE80211W
+       int sa_query_count; /* number of pending SA Query requests;
+                            * 0 = no SA Query in progress */
+       int sa_query_timed_out;
+       u8 *sa_query_trans_id; /* buffer of WLAN_SA_QUERY_TR_ID_LEN *
+                               * sa_query_count octets of pending SA Query
+                               * transaction identifiers */
+       struct os_time sa_query_start;
+#endif /* CONFIG_IEEE80211W */
+
+#ifdef CONFIG_INTERWORKING
+#define GAS_DIALOG_MAX 8 /* Max concurrent dialog number */
+       struct gas_dialog_info *gas_dialog;
+       u8 gas_dialog_next;
+#endif /* CONFIG_INTERWORKING */
+
+//     struct wpabuf *wps_ie; /* WPS IE from (Re)Association Request */
+//     struct wpabuf *p2p_ie; /* P2P IE from (Re)Association Request */
+//     struct wpabuf *hs20_ie; /* HS 2.0 IE from (Re)Association Request */
+
+//     struct os_time connected_time;
+
+#ifdef CONFIG_SAE
+       enum { SAE_INIT, SAE_COMMIT, SAE_CONFIRM } sae_state;
+       u16 sae_send_confirm;
+#endif /* CONFIG_SAE */
+};
+
+
+/* Default value for maximum station inactivity. After AP_MAX_INACTIVITY has
+ * passed since last received frame from the station, a nullfunc data frame is
+ * sent to the station. If this frame is not acknowledged and no other frames
+ * have been received, the station will be disassociated after
+ * AP_DISASSOC_DELAY seconds. Similarly, the station will be deauthenticated
+ * after AP_DEAUTH_DELAY seconds has passed after disassociation. */
+#define AP_MAX_INACTIVITY (5 * 60)
+#define AP_DISASSOC_DELAY (1)
+#define AP_DEAUTH_DELAY (1)
+/* Number of seconds to keep STA entry with Authenticated flag after it has
+ * been disassociated. */
+#define AP_MAX_INACTIVITY_AFTER_DISASSOC (1 * 30)
+/* Number of seconds to keep STA entry after it has been deauthenticated. */
+#define AP_MAX_INACTIVITY_AFTER_DEAUTH (1 * 5)
+
+
+struct hostapd_data;
+
+int ap_for_each_sta(struct hostapd_data *hapd,
+                   int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
+                             void *ctx),
+                   void *ctx);
+struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta);
+void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta);
+void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
+void hostapd_free_stas(struct hostapd_data *hapd);
+void ap_handle_timer(void *eloop_ctx, void *timeout_ctx);
+void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
+                           u32 session_timeout);
+void ap_sta_no_session_timeout(struct hostapd_data *hapd,
+                              struct sta_info *sta);
+struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr);
+void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
+                        u16 reason);
+void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
+                          u16 reason);
+#ifdef CONFIG_WPS
+int ap_sta_wps_cancel(struct hostapd_data *hapd,
+                     struct sta_info *sta, void *ctx);
+#endif /* CONFIG_WPS */
+int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
+                    int old_vlanid);
+void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
+void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
+int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta);
+void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
+                      const u8 *addr, u16 reason);
+
+void ap_sta_set_authorized(struct hostapd_data *hapd,
+                          struct sta_info *sta, int authorized);
+static inline int ap_sta_is_authorized(struct sta_info *sta)
+{
+       return sta->flags & WLAN_STA_AUTHORIZED;
+}
+
+void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta);
+void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta);
+
+#endif /* STA_INFO_H */
diff --git a/components/wpa_supplicant/include/wpa/state_machine.h b/components/wpa_supplicant/include/wpa/state_machine.h
new file mode 100644 (file)
index 0000000..ce8c51e
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * wpa_supplicant/hostapd - State machine definitions
+ * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ *
+ * This file includes a set of pre-processor macros that can be used to
+ * implement a state machine. In addition to including this header file, each
+ * file implementing a state machine must define STATE_MACHINE_DATA to be the
+ * data structure including state variables (enum machine_state,
+ * Boolean changed), and STATE_MACHINE_DEBUG_PREFIX to be a string that is used
+ * as a prefix for all debug messages. If SM_ENTRY_MA macro is used to define
+ * a group of state machines with shared data structure, STATE_MACHINE_ADDR
+ * needs to be defined to point to the MAC address used in debug output.
+ * SM_ENTRY_M macro can be used to define similar group of state machines
+ * without this additional debug info.
+ */
+
+#ifndef STATE_MACHINE_H
+#define STATE_MACHINE_H
+
+/**
+ * SM_STATE - Declaration of a state machine function
+ * @machine: State machine name
+ * @state: State machine state
+ *
+ * This macro is used to declare a state machine function. It is used in place
+ * of a C function definition to declare functions to be run when the state is
+ * entered by calling SM_ENTER or SM_ENTER_GLOBAL.
+ */
+#define SM_STATE(machine, state) \
+static void ICACHE_FLASH_ATTR sm_ ## machine ## _ ## state ## _Enter(STATE_MACHINE_DATA *sm, \
+       int global)
+
+/**
+ * SM_ENTRY - State machine function entry point
+ * @machine: State machine name
+ * @state: State machine state
+ *
+ * This macro is used inside each state machine function declared with
+ * SM_STATE. SM_ENTRY should be in the beginning of the function body, but
+ * after declaration of possible local variables. This macro prints debug
+ * information about state transition and update the state machine state.
+ */
+#define SM_ENTRY(machine, state) \
+if (!global || sm->machine ## _state != machine ## _ ## state) { \
+       sm->changed = TRUE; \
+       wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " #machine \
+                  " entering state " #state); \
+} \
+sm->machine ## _state = machine ## _ ## state;
+
+/**
+ * SM_ENTRY_M - State machine function entry point for state machine group
+ * @machine: State machine name
+ * @_state: State machine state
+ * @data: State variable prefix (full variable: prefix_state)
+ *
+ * This macro is like SM_ENTRY, but for state machine groups that use a shared
+ * data structure for more than one state machine. Both machine and prefix
+ * parameters are set to "sub-state machine" name. prefix is used to allow more
+ * than one state variable to be stored in the same data structure.
+ */
+#define SM_ENTRY_M(machine, _state, data) \
+if (!global || sm->data ## _ ## state != machine ## _ ## _state) { \
+       sm->changed = TRUE; \
+       wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " \
+                  #machine " entering state " #_state); \
+} \
+sm->data ## _ ## state = machine ## _ ## _state;
+
+/**
+ * SM_ENTRY_MA - State machine function entry point for state machine group
+ * @machine: State machine name
+ * @_state: State machine state
+ * @data: State variable prefix (full variable: prefix_state)
+ *
+ * This macro is like SM_ENTRY_M, but a MAC address is included in debug
+ * output. STATE_MACHINE_ADDR has to be defined to point to the MAC address to
+ * be included in debug.
+ */
+#define SM_ENTRY_MA(machine, _state, data) \
+if (!global || sm->data ## _ ## state != machine ## _ ## _state) { \
+       sm->changed = TRUE; \
+       wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " MACSTR " " \
+                  #machine " entering state " #_state"\n", \
+                  MAC2STR(STATE_MACHINE_ADDR)); \
+} \
+sm->data ## _ ## state = machine ## _ ## _state;
+
+/**
+ * SM_ENTER - Enter a new state machine state
+ * @machine: State machine name
+ * @state: State machine state
+ *
+ * This macro expands to a function call to a state machine function defined
+ * with SM_STATE macro. SM_ENTER is used in a state machine step function to
+ * move the state machine to a new state.
+ */
+#define SM_ENTER(machine, state) \
+sm_ ## machine ## _ ## state ## _Enter(sm, 0)
+
+/**
+ * SM_ENTER_GLOBAL - Enter a new state machine state based on global rule
+ * @machine: State machine name
+ * @state: State machine state
+ *
+ * This macro is like SM_ENTER, but this is used when entering a new state
+ * based on a global (not specific to any particular state) rule. A separate
+ * macro is used to avoid unwanted debug message floods when the same global
+ * rule is forcing a state machine to remain in on state.
+ */
+#define SM_ENTER_GLOBAL(machine, state) \
+sm_ ## machine ## _ ## state ## _Enter(sm, 1)
+
+/**
+ * SM_STEP - Declaration of a state machine step function
+ * @machine: State machine name
+ *
+ * This macro is used to declare a state machine step function. It is used in
+ * place of a C function definition to declare a function that is used to move
+ * state machine to a new state based on state variables. This function uses
+ * SM_ENTER and SM_ENTER_GLOBAL macros to enter new state.
+ */
+#define SM_STEP(machine) \
+static void ICACHE_FLASH_ATTR sm_ ## machine ## _Step(STATE_MACHINE_DATA *sm)
+
+/**
+ * SM_STEP_RUN - Call the state machine step function
+ * @machine: State machine name
+ *
+ * This macro expands to a function call to a state machine step function
+ * defined with SM_STEP macro.
+ */
+#define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm)
+
+#endif /* STATE_MACHINE_H */
diff --git a/components/wpa_supplicant/include/wpa/wpa.h b/components/wpa_supplicant/include/wpa/wpa.h
new file mode 100644 (file)
index 0000000..2a1adfc
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * wpa_supplicant - WPA definitions
+ * Copyright (c) 2003-2007, 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.
+ */
+
+#ifndef WPA_H
+#define WPA_H
+
+#include "c_types.h"
+#include "os_type.h"
+#include "common.h"
+#include "ets_sys.h"
+#include "wpa/defs.h"
+#include "wpa/wpa_common.h"
+
+//#include "net80211/ieee80211_var.h"
+//#include "net80211/ieee80211_node.h"
+
+#define WPA_SM_STATE(_sm) ((_sm)->wpa_state)
+
+struct wpa_sm;
+
+int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len);
+
+#define WPA_ASSERT  ASSERT
+
+struct install_key {
+    int mic_errors_seen; /* Michael MIC errors with the current PTK */
+    int keys_cleared;
+    enum wpa_alg alg;
+    u8 addr[ETH_ALEN];
+    int key_idx;
+    int set_tx;
+    u8 seq[10];
+    u8 key[32];
+};
+
+/**
+ * struct wpa_sm - Internal WPA state machine data
+ */
+struct wpa_sm {
+    u8 pmk[PMK_LEN];
+    size_t pmk_len;
+
+//    char *passphrase;  //wlan password
+//    u8 *ssid;               //wlan network name
+//    size_t ssid_len;
+
+    struct wpa_ptk ptk, tptk;
+    int ptk_set, tptk_set;
+    u8 snonce[WPA_NONCE_LEN];
+    u8 anonce[WPA_NONCE_LEN]; /* ANonce from the last 1/4 msg */
+    int renew_snonce;
+    u8 rx_replay_counter[WPA_REPLAY_COUNTER_LEN];
+    int rx_replay_counter_set;
+    u8 request_counter[WPA_REPLAY_COUNTER_LEN];
+
+//    void *network_ctx;
+
+    unsigned int pairwise_cipher;
+    unsigned int group_cipher;
+    unsigned int key_mgmt;
+    unsigned int mgmt_group_cipher;
+
+    int rsn_enabled; /* Whether RSN is enabled in configuration */
+
+    int countermeasures; /*TKIP countermeasures state flag, 1:in countermeasures state*/
+    os_timer_t  cm_timer;
+
+    u8 *assoc_wpa_ie; /* Own WPA/RSN IE from (Re)AssocReq */
+    size_t assoc_wpa_ie_len;
+
+    u8 eapol_version;
+
+    int wpa_ptk_rekey;
+    u8 own_addr[ETH_ALEN];
+
+    u8 bssid[ETH_ALEN];
+
+    unsigned int proto;
+    enum wpa_states wpa_state;
+
+    u8 *ap_wpa_ie, *ap_rsn_ie;
+    size_t ap_wpa_ie_len, ap_rsn_ie_len;
+
+    struct install_key install_ptk;
+    struct install_key install_gtk;
+    int  key_entry_valid;   //present current avaliable entry for bssid, for pairkey:0,5,10,15,20, gtk: pairkey_no+i (i:1~4)
+       
+//    char *msg;   //send eapol msg buff
+//    size_t msg_len;  //msg length:6 + sizeof(eth) + data_len
+
+//    struct netif *ifp;
+    struct pbuf *pb;
+
+    void (* sendto) (struct pbuf *pb);
+    void (*config_assoc_ie) (uint8 proto, u8 *assoc_buf, u32 assoc_wpa_ie_len);
+    void (*install_ppkey) (enum wpa_alg alg, uint8 *addr, int key_idx, int set_tx,
+               uint8 *seq, size_t seq_len, uint8 *key, size_t key_len, int key_entry_valid);
+    void (*wpa_deauthenticate)(uint8 reason_code);
+    void (*wpa_neg_complete)();
+    struct wpa_gtk_data gd; //used for calllback save param
+    uint16 key_info;   //used for txcallback param    
+};
+
+struct l2_ethhdr {
+    u8 h_dest[ETH_ALEN];
+    u8 h_source[ETH_ALEN];
+    be16 h_proto;
+} STRUCT_PACKED;
+
+/**
+ * set_key - Configure encryption key
+ * @ifname: Interface name (for multi-SSID/VLAN support)
+ * @priv: private driver interface data
+ * @alg: encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP,
+ *     %WPA_ALG_TKIP, %WPA_ALG_CCMP, %WPA_ALG_IGTK, %WPA_ALG_PMK);
+ *     %WPA_ALG_NONE clears the key.
+ * @addr: address of the peer STA or ff:ff:ff:ff:ff:ff for
+ *     broadcast/default keys
+ * @key_idx: key index (0..3), usually 0 for unicast keys; 0..4095 for
+ *     IGTK
+ * @set_tx: configure this key as the default Tx key (only used when
+ *     driver does not support separate unicast/individual key
+ * @seq: sequence number/packet number, seq_len octets, the next
+ *     packet number to be used for in replay protection; configured
+ *     for Rx keys (in most cases, this is only used with broadcast
+ *     keys and set to zero for unicast keys)
+ * @seq_len: length of the seq, depends on the algorithm:
+ *     TKIP: 6 octets, CCMP: 6 octets, IGTK: 6 octets
+ * @key: key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key,
+ *     8-byte Rx Mic Key
+ * @key_len: length of the key buffer in octets (WEP: 5 or 13,
+ *     TKIP: 32, CCMP: 16, IGTK: 16)
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ * Configure the given key for the kernel driver. If the driver
+ * supports separate individual keys (4 default keys + 1 individual),
+ * addr can be used to determine whether the key is default or
+ * individual. If only 4 keys are supported, the default key with key
+ * index 0 is used as the individual key. STA must be configured to use
+ * it as the default Tx key (set_tx is set) and accept Rx for all the
+ * key indexes. In most cases, WPA uses only key indexes 1 and 2 for
+ * broadcast keys, so key index 0 is available for this kind of
+ * configuration.
+ *
+ * Please note that TKIP keys include separate TX and RX MIC keys and
+ * some drivers may expect them in different order than wpa_supplicant
+ * is using. If the TX/RX keys are swapped, all TKIP encrypted packets
+ * will tricker Michael MIC errors. This can be fixed by changing the
+ * order of MIC keys by swapping te bytes 16..23 and 24..31 of the key
+ * in driver_*.c set_key() implementation, see driver_ndis.c for an
+ * example on how this can be done.
+ */
+
+
+/**
+ * send_eapol - Optional function for sending EAPOL packets
+ * @priv: private driver interface data
+ * @dest: Destination MAC address
+ * @proto: Ethertype
+ * @data: EAPOL packet starting with IEEE 802.1X header
+ * @data_len: Size of the EAPOL packet
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ * This optional function can be used to override l2_packet operations
+ * with driver specific functionality. If this function pointer is set,
+ * l2_packet module is not used at all and the driver interface code is
+ * responsible for receiving and sending all EAPOL packets. The
+ * received EAPOL packets are sent to core code with EVENT_EAPOL_RX
+ * event. The driver interface is required to implement get_mac_addr()
+ * handler if send_eapol() is used.
+ */
+
+#define KEYENTRY_TABLE_MAP(key_entry_valid)  ((key_entry_valid)%5) 
+
+void pp_michael_mic_failure(uint16 isunicast);
+
+void wpa_sm_set_state(enum wpa_states state);
+
+#endif /* WPA_H */
+
diff --git a/components/wpa_supplicant/include/wpa/wpa_auth.h b/components/wpa_supplicant/include/wpa/wpa_auth.h
new file mode 100644 (file)
index 0000000..c729923
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * hostapd - IEEE 802.11i-2004 / WPA Authenticator
+ * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_AUTH_H
+#define WPA_AUTH_H
+
+#include "wpa/defs.h"
+#include "wpa/eapol_common.h"
+#include "wpa/wpa_common.h"
+
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
+/* IEEE Std 802.11r-2008, 11A.10.3 - Remote request/response frame definition
+ */
+struct ft_rrb_frame {
+       u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
+       u8 packet_type; /* FT_PACKET_REQUEST/FT_PACKET_RESPONSE */
+       le16 action_length; /* little endian length of action_frame */
+       u8 ap_address[ETH_ALEN];
+       /*
+        * Followed by action_length bytes of FT Action frame (from Category
+        * field to the end of Action Frame body.
+        */
+} STRUCT_PACKED;
+
+#define RSN_REMOTE_FRAME_TYPE_FT_RRB 1
+
+#define FT_PACKET_REQUEST 0
+#define FT_PACKET_RESPONSE 1
+/* Vendor-specific types for R0KH-R1KH protocol; not defined in 802.11r */
+#define FT_PACKET_R0KH_R1KH_PULL 200
+#define FT_PACKET_R0KH_R1KH_RESP 201
+#define FT_PACKET_R0KH_R1KH_PUSH 202
+
+#define FT_R0KH_R1KH_PULL_DATA_LEN 44
+#define FT_R0KH_R1KH_RESP_DATA_LEN 76
+#define FT_R0KH_R1KH_PUSH_DATA_LEN 88
+
+struct ft_r0kh_r1kh_pull_frame {
+       u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
+       u8 packet_type; /* FT_PACKET_R0KH_R1KH_PULL */
+       le16 data_length; /* little endian length of data (44) */
+       u8 ap_address[ETH_ALEN];
+
+       u8 nonce[16];
+       u8 pmk_r0_name[WPA_PMK_NAME_LEN];
+       u8 r1kh_id[FT_R1KH_ID_LEN];
+       u8 s1kh_id[ETH_ALEN];
+       u8 pad[4]; /* 8-octet boundary for AES key wrap */
+       u8 key_wrap_extra[8];
+} STRUCT_PACKED;
+
+struct ft_r0kh_r1kh_resp_frame {
+       u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
+       u8 packet_type; /* FT_PACKET_R0KH_R1KH_RESP */
+       le16 data_length; /* little endian length of data (76) */
+       u8 ap_address[ETH_ALEN];
+
+       u8 nonce[16]; /* copied from pull */
+       u8 r1kh_id[FT_R1KH_ID_LEN]; /* copied from pull */
+       u8 s1kh_id[ETH_ALEN]; /* copied from pull */
+       u8 pmk_r1[PMK_LEN];
+       u8 pmk_r1_name[WPA_PMK_NAME_LEN];
+       le16 pairwise;
+       u8 pad[2]; /* 8-octet boundary for AES key wrap */
+       u8 key_wrap_extra[8];
+} STRUCT_PACKED;
+
+struct ft_r0kh_r1kh_push_frame {
+       u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
+       u8 packet_type; /* FT_PACKET_R0KH_R1KH_PUSH */
+       le16 data_length; /* little endian length of data (88) */
+       u8 ap_address[ETH_ALEN];
+
+       /* Encrypted with AES key-wrap */
+       u8 timestamp[4]; /* current time in seconds since unix epoch, little
+                         * endian */
+       u8 r1kh_id[FT_R1KH_ID_LEN];
+       u8 s1kh_id[ETH_ALEN];
+       u8 pmk_r0_name[WPA_PMK_NAME_LEN];
+       u8 pmk_r1[PMK_LEN];
+       u8 pmk_r1_name[WPA_PMK_NAME_LEN];
+       le16 pairwise;
+       u8 pad[6]; /* 8-octet boundary for AES key wrap */
+       u8 key_wrap_extra[8];
+} STRUCT_PACKED;
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
+
+
+/* per STA state machine data */
+
+struct wpa_authenticator;
+struct wpa_state_machine;
+struct rsn_pmksa_cache_entry;
+struct eapol_state_machine;
+
+
+struct ft_remote_r0kh {
+       struct ft_remote_r0kh *next;
+       u8 addr[ETH_ALEN];
+       u8 id[FT_R0KH_ID_MAX_LEN];
+       size_t id_len;
+       u8 key[16];
+};
+
+
+struct ft_remote_r1kh {
+       struct ft_remote_r1kh *next;
+       u8 addr[ETH_ALEN];
+       u8 id[FT_R1KH_ID_LEN];
+       u8 key[16];
+};
+
+
+struct wpa_auth_config {
+       int wpa;
+       int wpa_key_mgmt;
+       int wpa_pairwise;
+       int wpa_group;
+       int wpa_group_rekey;
+       int wpa_strict_rekey;
+       int wpa_gmk_rekey;
+       int wpa_ptk_rekey;
+       int rsn_pairwise;
+       int rsn_preauth;
+       int eapol_version;
+       int peerkey;
+       int wmm_enabled;
+       int wmm_uapsd;
+       int disable_pmksa_caching;
+       int okc;
+       int tx_status;
+#ifdef CONFIG_IEEE80211W
+       enum mfp_options ieee80211w;
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_IEEE80211R
+#define SSID_LEN 32
+       u8 ssid[SSID_LEN];
+       size_t ssid_len;
+       u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
+       u8 r0_key_holder[FT_R0KH_ID_MAX_LEN];
+       size_t r0_key_holder_len;
+       u8 r1_key_holder[FT_R1KH_ID_LEN];
+       u32 r0_key_lifetime;
+       u32 reassociation_deadline;
+       struct ft_remote_r0kh *r0kh_list;
+       struct ft_remote_r1kh *r1kh_list;
+       int pmk_r1_push;
+       int ft_over_ds;
+#endif /* CONFIG_IEEE80211R */
+       int disable_gtk;
+       int ap_mlme;
+};
+
+typedef enum {
+       LOGGER_DEBUG, LOGGER_INFO, LOGGER_WARNING
+} logger_level;
+
+typedef enum {
+       WPA_EAPOL_portEnabled, WPA_EAPOL_portValid, WPA_EAPOL_authorized,
+       WPA_EAPOL_portControl_Auto, WPA_EAPOL_keyRun, WPA_EAPOL_keyAvailable,
+       WPA_EAPOL_keyDone, WPA_EAPOL_inc_EapolFramesTx
+} wpa_eapol_variable;
+
+struct wpa_auth_callbacks {
+       void *ctx;
+       void (*logger)(void *ctx, const u8 *addr, logger_level level,
+                      const char *txt);
+       void (*disconnect)(void *ctx, const u8 *addr, u16 reason);
+       int (*mic_failure_report)(void *ctx, const u8 *addr);
+       void (*set_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var,
+                         int value);
+       int (*get_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var);
+       const u8 * (*get_psk)(void *ctx, const u8 *addr, const u8 *prev_psk);
+       int (*get_msk)(void *ctx, const u8 *addr, u8 *msk, size_t *len);
+       int (*set_key)(void *ctx, int vlan_id, enum wpa_alg alg,
+                      const u8 *addr, int idx, u8 *key, size_t key_len);
+       int (*get_seqnum)(void *ctx, const u8 *addr, int idx, u8 *seq);
+       int (*send_eapol)(void *ctx, const u8 *addr, const u8 *data,
+                         size_t data_len, int encrypt);
+       int (*for_each_sta)(void *ctx, int (*cb)(struct wpa_state_machine *sm,
+                                                void *ctx), void *cb_ctx);
+       int (*for_each_auth)(void *ctx, int (*cb)(struct wpa_authenticator *a,
+                                                 void *ctx), void *cb_ctx);
+       int (*send_ether)(void *ctx, const u8 *dst, u16 proto, const u8 *data,
+                         size_t data_len);
+#ifdef CONFIG_IEEE80211R
+       struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr);
+       int (*send_ft_action)(void *ctx, const u8 *dst,
+                             const u8 *data, size_t data_len);
+       int (*add_tspec)(void *ctx, const u8 *sta_addr, u8 *tspec_ie,
+                         size_t tspec_ielen);
+#endif /* CONFIG_IEEE80211R */
+};
+
+struct wpa_authenticator * wpa_init(const u8 *addr,
+                                   struct wpa_auth_config *conf,
+                                   struct wpa_auth_callbacks *cb);
+int wpa_init_keys(struct wpa_authenticator *wpa_auth);
+void wpa_deinit(struct wpa_authenticator *wpa_auth);
+int wpa_reconfig(struct wpa_authenticator *wpa_auth,
+                struct wpa_auth_config *conf);
+
+enum {
+       WPA_IE_OK, WPA_INVALID_IE, WPA_INVALID_GROUP, WPA_INVALID_PAIRWISE,
+       WPA_INVALID_AKMP, WPA_NOT_ENABLED, WPA_ALLOC_FAIL,
+       WPA_MGMT_FRAME_PROTECTION_VIOLATION, WPA_INVALID_MGMT_GROUP_CIPHER,
+       WPA_INVALID_MDIE, WPA_INVALID_PROTO
+};
+       
+int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
+                       struct wpa_state_machine *sm,
+                       const u8 *wpa_ie, size_t wpa_ie_len/*,
+                       const u8 *mdie, size_t mdie_len*/);
+int wpa_auth_uses_mfp(struct wpa_state_machine *sm);
+struct wpa_state_machine *
+wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr);
+int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
+                           struct wpa_state_machine *sm);
+void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm);
+void wpa_auth_sta_deinit(struct wpa_state_machine *sm);
+void wpa_receive(struct wpa_authenticator *wpa_auth,
+                struct wpa_state_machine *sm,
+                u8 *data, size_t data_len);
+typedef enum {
+       WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH,
+       WPA_REAUTH_EAPOL, WPA_ASSOC_FT
+} wpa_event;
+void wpa_remove_ptk(struct wpa_state_machine *sm);
+int wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event);
+void wpa_auth_sm_notify(struct wpa_state_machine *sm);
+void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth);
+int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen);
+int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen);
+void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth);
+int wpa_auth_pairwise_set(struct wpa_state_machine *sm);
+int wpa_auth_get_pairwise(struct wpa_state_machine *sm);
+int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm);
+int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm);
+int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
+                            struct rsn_pmksa_cache_entry *entry);
+struct rsn_pmksa_cache_entry *
+wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm);
+void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm);
+const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth,
+                              size_t *len);
+int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
+                      int session_timeout, struct eapol_state_machine *eapol);
+int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
+                              const u8 *pmk, size_t len, const u8 *sta_addr,
+                              int session_timeout,
+                              struct eapol_state_machine *eapol);
+int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id);
+void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
+                                 struct wpa_state_machine *sm, int ack);
+
+#ifdef CONFIG_IEEE80211R
+u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
+                                size_t max_len, int auth_alg,
+                                const u8 *req_ies, size_t req_ies_len);
+void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
+                        u16 auth_transaction, const u8 *ies, size_t ies_len,
+                        void (*cb)(void *ctx, const u8 *dst, const u8 *bssid,
+                                   u16 auth_transaction, u16 resp,
+                                   const u8 *ies, size_t ies_len),
+                        void *ctx);
+u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
+                           size_t ies_len);
+int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len);
+int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
+                 const u8 *data, size_t data_len);
+void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr);
+#endif /* CONFIG_IEEE80211R */
+
+void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm);
+void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag);
+int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos);
+int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos);
+
+int wpa_auth_uses_sae(struct wpa_state_machine *sm);
+
+#endif /* WPA_AUTH_H */
diff --git a/components/wpa_supplicant/include/wpa/wpa_auth_i.h b/components/wpa_supplicant/include/wpa/wpa_auth_i.h
new file mode 100644 (file)
index 0000000..53ad8ea
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * hostapd - IEEE 802.11i-2004 / WPA Authenticator: Internal definitions
+ * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_AUTH_I_H
+#define WPA_AUTH_I_H
+
+/* max(dot11RSNAConfigGroupUpdateCount,dot11RSNAConfigPairwiseUpdateCount) */
+#define RSNA_MAX_EAPOL_RETRIES 4
+
+struct wpa_group;
+
+struct wpa_stsl_negotiation {
+       struct wpa_stsl_negotiation *next;
+       u8 initiator[ETH_ALEN];
+       u8 peer[ETH_ALEN];
+};
+
+
+struct wpa_state_machine {
+       struct wpa_authenticator *wpa_auth;
+       struct wpa_group *group;
+
+       u8 addr[ETH_ALEN];
+
+       enum {
+               WPA_PTK_INITIALIZE, WPA_PTK_DISCONNECT, WPA_PTK_DISCONNECTED,
+               WPA_PTK_AUTHENTICATION, WPA_PTK_AUTHENTICATION2,
+               WPA_PTK_INITPMK, WPA_PTK_INITPSK, WPA_PTK_PTKSTART,
+               WPA_PTK_PTKCALCNEGOTIATING, WPA_PTK_PTKCALCNEGOTIATING2,
+               WPA_PTK_PTKINITNEGOTIATING, WPA_PTK_PTKINITDONE
+       } wpa_ptk_state;
+
+       enum {
+               WPA_PTK_GROUP_IDLE = 0,
+               WPA_PTK_GROUP_REKEYNEGOTIATING,
+               WPA_PTK_GROUP_REKEYESTABLISHED,
+               WPA_PTK_GROUP_KEYERROR
+       } wpa_ptk_group_state;
+
+       Boolean Init;
+       Boolean DeauthenticationRequest;
+       Boolean AuthenticationRequest;
+       Boolean ReAuthenticationRequest;
+       Boolean Disconnect;
+       int TimeoutCtr;
+       int GTimeoutCtr;
+       Boolean TimeoutEvt;
+       Boolean EAPOLKeyReceived;
+       Boolean EAPOLKeyPairwise;
+       Boolean EAPOLKeyRequest;
+       Boolean MICVerified;
+       Boolean GUpdateStationKeys;
+       u8 ANonce[WPA_NONCE_LEN];
+       u8 SNonce[WPA_NONCE_LEN];
+       u8 PMK[PMK_LEN];
+       struct wpa_ptk PTK;
+       Boolean PTK_valid;
+       Boolean pairwise_set;
+       int keycount;
+       Boolean Pair;
+       struct wpa_key_replay_counter {
+               u8 counter[WPA_REPLAY_COUNTER_LEN];
+               Boolean valid;
+       } key_replay[RSNA_MAX_EAPOL_RETRIES],
+               prev_key_replay[RSNA_MAX_EAPOL_RETRIES];
+       Boolean PInitAKeys; /* WPA only, not in IEEE 802.11i */
+       Boolean PTKRequest; /* not in IEEE 802.11i state machine */
+       Boolean has_GTK;
+       Boolean PtkGroupInit; /* init request for PTK Group state machine */
+
+       u8 *last_rx_eapol_key; /* starting from IEEE 802.1X header */
+       size_t last_rx_eapol_key_len;
+
+       unsigned int changed:1;
+       unsigned int in_step_loop:1;
+       unsigned int pending_deinit:1;
+       unsigned int started:1;
+       unsigned int mgmt_frame_prot:1;
+       unsigned int rx_eapol_key_secure:1;
+       unsigned int update_snonce:1;
+#ifdef CONFIG_IEEE80211R
+       unsigned int ft_completed:1;
+       unsigned int pmk_r1_name_valid:1;
+#endif /* CONFIG_IEEE80211R */
+       unsigned int is_wnmsleep:1;
+
+       u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN];
+       int req_replay_counter_used;
+
+       u8 *wpa_ie;
+       size_t wpa_ie_len;
+
+       enum {
+               WPA_VERSION_NO_WPA = 0 /* WPA not used */,
+               WPA_VERSION_WPA = 1 /* WPA / IEEE 802.11i/D3.0 */,
+               WPA_VERSION_WPA2 = 2 /* WPA2 / IEEE 802.11i */
+       } wpa;
+       int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */
+       int wpa_key_mgmt; /* the selected WPA_KEY_MGMT_* */
+//     struct rsn_pmksa_cache_entry *pmksa;
+
+//     u32 dot11RSNAStatsTKIPLocalMICFailures;
+//     u32 dot11RSNAStatsTKIPRemoteMICFailures;
+
+#ifdef CONFIG_IEEE80211R
+       u8 xxkey[PMK_LEN]; /* PSK or the second 256 bits of MSK */
+       size_t xxkey_len;
+       u8 pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name derived from FT Auth
+                                          * Request */
+       u8 r0kh_id[FT_R0KH_ID_MAX_LEN]; /* R0KH-ID from FT Auth Request */
+       size_t r0kh_id_len;
+       u8 sup_pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name from EAPOL-Key
+                                              * message 2/4 */
+       u8 *assoc_resp_ftie;
+#endif /* CONFIG_IEEE80211R */
+
+       int pending_1_of_4_timeout;
+};
+
+
+/* per group key state machine data */
+struct wpa_group {
+       struct wpa_group *next;
+       int vlan_id;
+
+       Boolean GInit;
+       int GKeyDoneStations;
+       Boolean GTKReKey;
+       int GTK_len;
+       int GN, GM;
+       Boolean GTKAuthenticator;
+       u8 Counter[WPA_NONCE_LEN];
+
+       enum {
+               WPA_GROUP_GTK_INIT = 0,
+               WPA_GROUP_SETKEYS, WPA_GROUP_SETKEYSDONE
+       } wpa_group_state;
+
+       u8 GMK[WPA_GMK_LEN];
+       u8 GTK[2][WPA_GTK_MAX_LEN];
+       u8 GNonce[WPA_NONCE_LEN];
+       Boolean changed;
+       Boolean first_sta_seen;
+       Boolean reject_4way_hs_for_entropy;
+#ifdef CONFIG_IEEE80211W
+       u8 IGTK[2][WPA_IGTK_LEN];
+       int GN_igtk, GM_igtk;
+#endif /* CONFIG_IEEE80211W */
+};
+
+
+struct wpa_ft_pmk_cache;
+
+/* per authenticator data */
+struct wpa_authenticator {
+       struct wpa_group *group;
+
+//     unsigned int dot11RSNAStatsTKIPRemoteMICFailures;
+//     u32 dot11RSNAAuthenticationSuiteSelected;
+//     u32 dot11RSNAPairwiseCipherSelected;
+//     u32 dot11RSNAGroupCipherSelected;
+//     u8 dot11RSNAPMKIDUsed[PMKID_LEN];
+//     u32 dot11RSNAAuthenticationSuiteRequested; /* FIX: update */
+//     u32 dot11RSNAPairwiseCipherRequested; /* FIX: update */
+//     u32 dot11RSNAGroupCipherRequested; /* FIX: update */
+//     unsigned int dot11RSNATKIPCounterMeasuresInvoked;
+//     unsigned int dot11RSNA4WayHandshakeFailures;
+
+//     struct wpa_stsl_negotiation *stsl_negotiations;
+
+       struct wpa_auth_config conf;
+//     struct wpa_auth_callbacks cb;
+
+       u8 *wpa_ie;
+       size_t wpa_ie_len;
+
+       u8 addr[ETH_ALEN];
+
+//     struct rsn_pmksa_cache *pmksa;
+//     struct wpa_ft_pmk_cache *ft_pmk_cache;
+};
+
+
+int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
+                    const u8 *pmkid);
+#if 0
+void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
+                    logger_level level, const char *txt);
+void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr,
+                     logger_level level, const char *fmt, ...);
+#endif
+void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
+                     struct wpa_state_machine *sm, int key_info,
+                     const u8 *key_rsc, const u8 *nonce,
+                     const u8 *kde, size_t kde_len,
+                     int keyidx, int encr, int force_version);
+int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth,
+                         int (*cb)(struct wpa_state_machine *sm, void *ctx),
+                         void *cb_ctx);
+int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth,
+                          int (*cb)(struct wpa_authenticator *a, void *ctx),
+                          void *cb_ctx);
+
+#ifdef CONFIG_PEERKEY
+int wpa_stsl_remove(struct wpa_authenticator *wpa_auth,
+                   struct wpa_stsl_negotiation *neg);
+void wpa_smk_error(struct wpa_authenticator *wpa_auth,
+                  struct wpa_state_machine *sm, struct wpa_eapol_key *key);
+void wpa_smk_m1(struct wpa_authenticator *wpa_auth,
+               struct wpa_state_machine *sm, struct wpa_eapol_key *key);
+void wpa_smk_m3(struct wpa_authenticator *wpa_auth,
+               struct wpa_state_machine *sm, struct wpa_eapol_key *key);
+#endif /* CONFIG_PEERKEY */
+
+#ifdef CONFIG_IEEE80211R
+int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len);
+int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id,
+                  size_t r0kh_id_len,
+                  const u8 *anonce, const u8 *snonce,
+                  u8 *buf, size_t len, const u8 *subelem,
+                  size_t subelem_len);
+int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,
+                          struct wpa_ptk *ptk, size_t ptk_len);
+struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void);
+void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache);
+void wpa_ft_install_ptk(struct wpa_state_machine *sm);
+#endif /* CONFIG_IEEE80211R */
+
+#endif /* WPA_AUTH_I_H */
diff --git a/components/wpa_supplicant/include/wpa/wpa_auth_ie.h b/components/wpa_supplicant/include/wpa/wpa_auth_ie.h
new file mode 100644 (file)
index 0000000..4999139
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * hostapd - WPA/RSN IE and KDE definitions
+ * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_AUTH_IE_H
+#define WPA_AUTH_IE_H
+
+struct wpa_eapol_ie_parse {
+       const u8 *wpa_ie;
+       size_t wpa_ie_len;
+       const u8 *rsn_ie;
+       size_t rsn_ie_len;
+       const u8 *pmkid;
+       const u8 *gtk;
+       size_t gtk_len;
+       const u8 *mac_addr;
+       size_t mac_addr_len;
+#ifdef CONFIG_PEERKEY
+       const u8 *smk;
+       size_t smk_len;
+       const u8 *nonce;
+       size_t nonce_len;
+       const u8 *lifetime;
+       size_t lifetime_len;
+       const u8 *error;
+       size_t error_len;
+#endif /* CONFIG_PEERKEY */
+#ifdef CONFIG_IEEE80211W
+       const u8 *igtk;
+       size_t igtk_len;
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_IEEE80211R
+       const u8 *mdie;
+       size_t mdie_len;
+       const u8 *ftie;
+       size_t ftie_len;
+#endif /* CONFIG_IEEE80211R */
+};
+
+int wpa_parse_kde_ies(const u8 *buf, size_t len,
+                     struct wpa_eapol_ie_parse *ie);
+u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len,
+                const u8 *data2, size_t data2_len);
+int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth);
+
+#endif /* WPA_AUTH_IE_H */
diff --git a/components/wpa_supplicant/include/wpa/wpa_common.h b/components/wpa_supplicant/include/wpa/wpa_common.h
new file mode 100644 (file)
index 0000000..480cf0e
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ * WPA definitions shared between hostapd and wpa_supplicant
+ * Copyright (c) 2002-2008, 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 "os.h"
+#ifndef WPA_COMMON_H
+#define WPA_COMMON_H
+
+#define WPA_MAX_SSID_LEN 32
+
+/* IEEE 802.11i */
+#define PMKID_LEN 16
+#define PMK_LEN 32
+#define WPA_REPLAY_COUNTER_LEN 8
+#define WPA_NONCE_LEN 32
+#define WPA_KEY_RSC_LEN 8
+#define WPA_GMK_LEN 32
+#define WPA_GTK_MAX_LEN 32
+
+#define WPA_SELECTOR_LEN 4
+#define WPA_VERSION 1
+#define RSN_SELECTOR_LEN 4
+#define RSN_VERSION 1
+
+#define RSN_SELECTOR(a, b, c, d) \
+       ((((u32) (a)) << 24) | (((u32) (b)) << 16) | (((u32) (c)) << 8) | \
+        (u32) (d))
+
+#define WPA_AUTH_KEY_MGMT_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0)
+#define WPA_AUTH_KEY_MGMT_UNSPEC_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
+#define WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 2)
+#define WPA_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0)
+#define WPA_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
+#define WPA_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x50, 0xf2, 2)
+#if 0
+#define WPA_CIPHER_SUITE_WRAP RSN_SELECTOR(0x00, 0x50, 0xf2, 3)
+#endif
+#define WPA_CIPHER_SUITE_CCMP RSN_SELECTOR(0x00, 0x50, 0xf2, 4)
+#define WPA_CIPHER_SUITE_WEP104 RSN_SELECTOR(0x00, 0x50, 0xf2, 5)
+
+
+#define RSN_AUTH_KEY_MGMT_UNSPEC_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 1)
+#define RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 2)
+#ifdef CONFIG_IEEE80211R
+#define RSN_AUTH_KEY_MGMT_FT_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 3)
+#define RSN_AUTH_KEY_MGMT_FT_PSK RSN_SELECTOR(0x00, 0x0f, 0xac, 4)
+#endif /* CONFIG_IEEE80211R */
+#define RSN_AUTH_KEY_MGMT_802_1X_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 5)
+#define RSN_AUTH_KEY_MGMT_PSK_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
+
+#define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0)
+#define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1)
+#define RSN_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x0f, 0xac, 2)
+#if 0
+#define RSN_CIPHER_SUITE_WRAP RSN_SELECTOR(0x00, 0x0f, 0xac, 3)
+#endif
+#define RSN_CIPHER_SUITE_CCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 4)
+#define RSN_CIPHER_SUITE_WEP104 RSN_SELECTOR(0x00, 0x0f, 0xac, 5)
+#ifdef CONFIG_IEEE80211W
+#define RSN_CIPHER_SUITE_AES_128_CMAC RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
+#endif /* CONFIG_IEEE80211W */
+#define RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
+#define RSN_CIPHER_SUITE_GCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 8)
+
+/* EAPOL-Key Key Data Encapsulation
+ * GroupKey and PeerKey require encryption, otherwise, encryption is optional.
+ */
+#define RSN_KEY_DATA_GROUPKEY RSN_SELECTOR(0x00, 0x0f, 0xac, 1)
+#if 0
+#define RSN_KEY_DATA_STAKEY RSN_SELECTOR(0x00, 0x0f, 0xac, 2)
+#endif
+#define RSN_KEY_DATA_MAC_ADDR RSN_SELECTOR(0x00, 0x0f, 0xac, 3)
+#define RSN_KEY_DATA_PMKID RSN_SELECTOR(0x00, 0x0f, 0xac, 4)
+#ifdef CONFIG_PEERKEY
+#define RSN_KEY_DATA_SMK RSN_SELECTOR(0x00, 0x0f, 0xac, 5)
+#define RSN_KEY_DATA_NONCE RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
+#define RSN_KEY_DATA_LIFETIME RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
+#define RSN_KEY_DATA_ERROR RSN_SELECTOR(0x00, 0x0f, 0xac, 8)
+#endif /* CONFIG_PEERKEY */
+#ifdef CONFIG_IEEE80211W
+#define RSN_KEY_DATA_IGTK RSN_SELECTOR(0x00, 0x0f, 0xac, 9)
+#endif /* CONFIG_IEEE80211W */
+
+#define WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
+
+#define RSN_SELECTOR_PUT(a, val) WPA_PUT_BE32((u8 *) (a), (val))
+#define RSN_SELECTOR_GET(a) WPA_GET_BE32((const u8 *) (a))
+
+#define RSN_NUM_REPLAY_COUNTERS_1 0
+#define RSN_NUM_REPLAY_COUNTERS_2 1
+#define RSN_NUM_REPLAY_COUNTERS_4 2
+#define RSN_NUM_REPLAY_COUNTERS_16 3
+
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
+#ifdef CONFIG_IEEE80211W
+#define WPA_IGTK_LEN 16
+#endif /* CONFIG_IEEE80211W */
+
+
+/* IEEE 802.11, 7.3.2.25.3 RSN Capabilities */
+#define WPA_CAPABILITY_PREAUTH BIT(0)
+#define WPA_CAPABILITY_NO_PAIRWISE BIT(1)
+/* B2-B3: PTKSA Replay Counter */
+/* B4-B5: GTKSA Replay Counter */
+#define WPA_CAPABILITY_MFPR BIT(6)
+#define WPA_CAPABILITY_MFPC BIT(7)
+#define WPA_CAPABILITY_PEERKEY_ENABLED BIT(9)
+
+
+/* IEEE 802.11r */
+#define MOBILITY_DOMAIN_ID_LEN 2
+#define FT_R0KH_ID_MAX_LEN 48
+#define FT_R1KH_ID_LEN 6
+#define WPA_PMK_NAME_LEN 16
+
+
+/* IEEE 802.11, 8.5.2 EAPOL-Key frames */
+#define WPA_KEY_INFO_TYPE_MASK ((u16) (BIT(0) | BIT(1) | BIT(2)))
+#define WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 BIT(0)
+#define WPA_KEY_INFO_TYPE_HMAC_SHA1_AES BIT(1)
+#define WPA_KEY_INFO_TYPE_AES_128_CMAC 3
+#define WPA_KEY_INFO_KEY_TYPE BIT(3) /* 1 = Pairwise, 0 = Group key */
+/* bit4..5 is used in WPA, but is reserved in IEEE 802.11i/RSN */
+#define WPA_KEY_INFO_KEY_INDEX_MASK (BIT(4) | BIT(5))
+#define WPA_KEY_INFO_KEY_INDEX_SHIFT 4
+#define WPA_KEY_INFO_INSTALL BIT(6) /* pairwise */
+#define WPA_KEY_INFO_TXRX BIT(6) /* group */
+#define WPA_KEY_INFO_ACK BIT(7)
+#define WPA_KEY_INFO_MIC BIT(8)
+#define WPA_KEY_INFO_SECURE BIT(9)
+#define WPA_KEY_INFO_ERROR BIT(10)
+#define WPA_KEY_INFO_REQUEST BIT(11)
+#define WPA_KEY_INFO_ENCR_KEY_DATA BIT(12) /* IEEE 802.11i/RSN only */
+#define WPA_KEY_INFO_SMK_MESSAGE BIT(13)
+
+
+struct wpa_eapol_key {
+       u8 type;
+       /* Note: key_info, key_length, and key_data_length are unaligned */
+       u8 key_info[2]; /* big endian */
+       u8 key_length[2]; /* big endian */
+       u8 replay_counter[WPA_REPLAY_COUNTER_LEN];
+       u8 key_nonce[WPA_NONCE_LEN];
+       u8 key_iv[16];
+       u8 key_rsc[WPA_KEY_RSC_LEN];
+       u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */
+       u8 key_mic[16];
+       u8 key_data_length[2]; /* big endian */
+       /* followed by key_data_length bytes of key_data */
+} STRUCT_PACKED;
+
+/**
+ * struct wpa_ptk - WPA Pairwise Transient Key
+ * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
+ */
+struct wpa_ptk {
+       u8 kck[16]; /* EAPOL-Key Key Confirmation Key (KCK) */
+       u8 kek[16]; /* EAPOL-Key Key Encryption Key (KEK) */
+       u8 tk1[16]; /* Temporal Key 1 (TK1) */
+       union {
+               u8 tk2[16]; /* Temporal Key 2 (TK2) */
+               struct {
+                       u8 tx_mic_key[8];
+                       u8 rx_mic_key[8];
+               } auth;
+       } u;
+} STRUCT_PACKED;
+
+struct wpa_gtk_data {
+       enum wpa_alg alg;
+       int tx, key_rsc_len, keyidx;
+       u8 gtk[32];
+       int gtk_len;
+};
+
+
+/* WPA IE version 1
+ * 00-50-f2:1 (OUI:OUI type)
+ * 0x01 0x00 (version; little endian)
+ * (all following fields are optional:)
+ * Group Suite Selector (4 octets) (default: TKIP)
+ * Pairwise Suite Count (2 octets, little endian) (default: 1)
+ * Pairwise Suite List (4 * n octets) (default: TKIP)
+ * Authenticated Key Management Suite Count (2 octets, little endian)
+ *    (default: 1)
+ * Authenticated Key Management Suite List (4 * n octets)
+ *    (default: unspec 802.1X)
+ * WPA Capabilities (2 octets, little endian) (default: 0)
+ */
+
+struct wpa_ie_hdr {
+       u8 elem_id;
+       u8 len;
+       u8 oui[4]; /* 24-bit OUI followed by 8-bit OUI type */
+       u8 version[2]; /* little endian */
+} STRUCT_PACKED;
+
+
+/* 1/4: PMKID
+ * 2/4: RSN IE
+ * 3/4: one or two RSN IEs + GTK IE (encrypted)
+ * 4/4: empty
+ * 1/2: GTK IE (encrypted)
+ * 2/2: empty
+ */
+
+/* RSN IE version 1
+ * 0x01 0x00 (version; little endian)
+ * (all following fields are optional:)
+ * Group Suite Selector (4 octets) (default: CCMP)
+ * Pairwise Suite Count (2 octets, little endian) (default: 1)
+ * Pairwise Suite List (4 * n octets) (default: CCMP)
+ * Authenticated Key Management Suite Count (2 octets, little endian)
+ *    (default: 1)
+ * Authenticated Key Management Suite List (4 * n octets)
+ *    (default: unspec 802.1X)
+ * RSN Capabilities (2 octets, little endian) (default: 0)
+ * PMKID Count (2 octets) (default: 0)
+ * PMKID List (16 * n octets)
+ * Management Group Cipher Suite (4 octets) (default: AES-128-CMAC)
+ */
+
+struct rsn_ie_hdr {
+       u8 elem_id; /* WLAN_EID_RSN */
+       u8 len;
+       u8 version[2]; /* little endian */
+} STRUCT_PACKED;
+
+
+#ifdef CONFIG_PEERKEY
+enum {
+       STK_MUI_4WAY_STA_AP = 1,
+       STK_MUI_4WAY_STAT_STA = 2,
+       STK_MUI_GTK = 3,
+       STK_MUI_SMK = 4
+};
+
+enum {
+       STK_ERR_STA_NR = 1,
+       STK_ERR_STA_NRSN = 2,
+       STK_ERR_CPHR_NS = 3,
+       STK_ERR_NO_STSL = 4
+};
+#endif /* CONFIG_PEERKEY */
+
+struct rsn_error_kde {
+       be16 mui;
+       be16 error_type;
+} STRUCT_PACKED;
+
+#ifdef CONFIG_IEEE80211W
+struct wpa_igtk_kde {
+       u8 keyid[2];
+       u8 pn[6];
+       u8 igtk[WPA_IGTK_LEN];
+} STRUCT_PACKED;
+#endif /* CONFIG_IEEE80211W */
+
+#ifdef CONFIG_IEEE80211R
+struct rsn_mdie {
+       u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
+       u8 ft_capab;
+} STRUCT_PACKED;
+
+#define RSN_FT_CAPAB_FT_OVER_DS BIT(0)
+#define RSN_FT_CAPAB_FT_RESOURCE_REQ_SUPP BIT(1)
+
+struct rsn_ftie {
+       u8 mic_control[2];
+       u8 mic[16];
+       u8 anonce[WPA_NONCE_LEN];
+       u8 snonce[WPA_NONCE_LEN];
+       /* followed by optional parameters */
+} STRUCT_PACKED;
+
+#define FTIE_SUBELEM_R1KH_ID 1
+#define FTIE_SUBELEM_GTK 2
+#define FTIE_SUBELEM_R0KH_ID 3
+#define FTIE_SUBELEM_IGTK 4
+
+struct rsn_rdie {
+       u8 id;
+       u8 descr_count;
+       le16 status_code;
+} STRUCT_PACKED;
+
+#endif /* CONFIG_IEEE80211R */
+
+struct wpa_ie_data {
+       int proto;
+       int pairwise_cipher;
+       int group_cipher;
+       int key_mgmt;
+       int capabilities;
+       size_t num_pmkid;
+       const u8 *pmkid;
+       int mgmt_group_cipher;
+};
+
+const char * wpa_cipher_txt(int cipher);
+
+int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
+                        struct wpa_ie_data *data);
+
+int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
+                     u8 *mic);
+int wpa_compare_rsn_ie(int ft_initial_assoc,
+                      const u8 *ie1, size_t ie1len,
+                      const u8 *ie2, size_t ie2len);
+
+void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
+                   const u8 *addr1, const u8 *addr2,
+                   const u8 *nonce1, const u8 *nonce2,
+                   u8 *ptk, size_t ptk_len, int use_sha256);
+
+void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
+              u8 *pmkid, int use_sha256);
+
+#endif /* WPA_COMMON_H */
diff --git a/components/wpa_supplicant/include/wpa/wpa_debug.h b/components/wpa_supplicant/include/wpa/wpa_debug.h
new file mode 100644 (file)
index 0000000..b78a657
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * wpa_supplicant/hostapd / Debug prints
+ * Copyright (c) 2002-2007, 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.
+ */
+
+#ifndef WPA_DEBUG_H
+#define WPA_DEBUG_H
+
+
+enum { MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR };
+
+/** EAP authentication completed successfully */
+#define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS "
+
+int wpa_debug_open_file(const char *path);
+void wpa_debug_close_file(void);
+
+/**
+ * wpa_debug_printf_timestamp - Print timestamp for debug output
+ *
+ * This function prints a timestamp in seconds_from_1970.microsoconds
+ * format if debug output has been configured to include timestamps in debug
+ * messages.
+ */
+void wpa_debug_print_timestamp(void);
+
+/**
+ * wpa_printf - conditional printf
+ * @level: priority level (MSG_*) of the message
+ * @fmt: printf format string, followed by optional arguments
+ *
+ * This function is used to print conditional debugging and error messages. The
+ * output may be directed to stdout, stderr, and/or syslog based on
+ * configuration.
+ *
+ * Note: New line '\n' is added to the end of the text when printing to stdout.
+ */
+//#define  DEBUG_PRINT
+//#define   MSG_PRINT
+
+/**
+ * wpa_hexdump - conditional hex dump
+ * @level: priority level (MSG_*) of the message
+ * @title: title of for the message
+ * @buf: data buffer to be dumped
+ * @len: length of the buf
+ *
+ * This function is used to print conditional debugging and error messages. The
+ * output may be directed to stdout, stderr, and/or syslog based on
+ * configuration. The contents of buf is printed out has hex dump.
+ */
+#ifdef DEBUG_PRINT
+#define wpa_printf(level,fmt, args...) ets_printf(fmt,## args)
+
+static inline void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len)
+{
+
+}
+
+static inline void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf, size_t len)
+{
+}
+
+
+void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len);
+
+static inline void wpa_hexdump_buf(int level, const char *title,
+                                  const struct wpabuf *buf)
+{
+       wpa_hexdump(level, title, wpabuf_head(buf), wpabuf_len(buf));
+}
+
+/**
+ * wpa_hexdump_key - conditional hex dump, hide keys
+ * @level: priority level (MSG_*) of the message
+ * @title: title of for the message
+ * @buf: data buffer to be dumped
+ * @len: length of the buf
+ *
+ * This function is used to print conditional debugging and error messages. The
+ * output may be directed to stdout, stderr, and/or syslog based on
+ * configuration. The contents of buf is printed out has hex dump. This works
+ * like wpa_hexdump(), but by default, does not include secret keys (passwords,
+ * etc.) in debug output.
+ */
+void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len);
+
+
+static inline void wpa_hexdump_buf_key(int level, const char *title,
+                                      const struct wpabuf *buf)
+{
+       wpa_hexdump_key(level, title, wpabuf_head(buf), wpabuf_len(buf));
+}
+
+/**
+ * wpa_hexdump_ascii - conditional hex dump
+ * @level: priority level (MSG_*) of the message
+ * @title: title of for the message
+ * @buf: data buffer to be dumped
+ * @len: length of the buf
+ *
+ * This function is used to print conditional debugging and error messages. The
+ * output may be directed to stdout, stderr, and/or syslog based on
+ * configuration. The contents of buf is printed out has hex dump with both
+ * the hex numbers and ASCII characters (for printable range) are shown. 16
+ * bytes per line will be shown.
+ */
+void wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
+                      size_t len);
+
+/**
+ * wpa_hexdump_ascii_key - conditional hex dump, hide keys
+ * @level: priority level (MSG_*) of the message
+ * @title: title of for the message
+ * @buf: data buffer to be dumped
+ * @len: length of the buf
+ *
+ * This function is used to print conditional debugging and error messages. The
+ * output may be directed to stdout, stderr, and/or syslog based on
+ * configuration. The contents of buf is printed out has hex dump with both
+ * the hex numbers and ASCII characters (for printable range) are shown. 16
+ * bytes per line will be shown. This works like wpa_hexdump_ascii(), but by
+ * default, does not include secret keys (passwords, etc.) in debug output.
+ */
+void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
+                          size_t len);
+#else
+#define wpa_printf(level,fmt, args...)
+#define wpa_hexdump(...)
+#define wpa_hexdump_buf(...)
+#define wpa_hexdump_key(...)
+#define wpa_hexdump_buf_key(...)
+#define wpa_hexdump_ascii(...)
+#define wpa_hexdump_ascii_key(...)
+#endif
+
+#define wpa_auth_logger
+#define wpa_auth_vlogger
+
+/**
+ * wpa_msg - Conditional printf for default target and ctrl_iface monitors
+ * @ctx: Pointer to context data; this is the ctx variable registered
+ *     with struct wpa_driver_ops::init()
+ * @level: priority level (MSG_*) of the message
+ * @fmt: printf format string, followed by optional arguments
+ *
+ * This function is used to print conditional debugging and error messages. The
+ * output may be directed to stdout, stderr, and/or syslog based on
+ * configuration. This function is like wpa_printf(), but it also sends the
+ * same message to all attached ctrl_iface monitors.
+ *
+ * Note: New line '\n' is added to the end of the text when printing to stdout.
+ */
+void wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4);
+
+/**
+ * wpa_msg_ctrl - Conditional printf for ctrl_iface monitors
+ * @ctx: Pointer to context data; this is the ctx variable registered
+ *     with struct wpa_driver_ops::init()
+ * @level: priority level (MSG_*) of the message
+ * @fmt: printf format string, followed by optional arguments
+ *
+ * This function is used to print conditional debugging and error messages.
+ * This function is like wpa_msg(), but it sends the output only to the
+ * attached ctrl_iface monitors. In other words, it can be used for frequent
+ * events that do not need to be sent to syslog.
+ */
+void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
+PRINTF_FORMAT(3, 4);
+
+typedef void (*wpa_msg_cb_func)(void *ctx, int level, const char *txt,
+                               size_t len);
+
+typedef void (*eloop_timeout_handler)(void *eloop_data, void *user_ctx);
+
+int eloop_cancel_timeout(eloop_timeout_handler handler,
+                        void *eloop_data, void *user_data);
+
+int eloop_register_timeout(unsigned int secs, unsigned int usecs,
+                          eloop_timeout_handler handler,
+                          void *eloop_data, void *user_data);
+
+
+#endif /* WPA_DEBUG_H */
diff --git a/components/wpa_supplicant/include/wpa/wpa_i.h b/components/wpa_supplicant/include/wpa/wpa_i.h
new file mode 100644 (file)
index 0000000..a43c33d
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Internal WPA/RSN supplicant state machine definitions
+ * Copyright (c) 2004-2010, 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.
+ */
+
+#ifndef WPA_I_H
+#define WPA_I_H
+
+/**
+ * set_key - Configure encryption key
+ * @ifname: Interface name (for multi-SSID/VLAN support)
+ * @priv: private driver interface data
+ * @alg: encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP,
+ *     %WPA_ALG_TKIP, %WPA_ALG_CCMP, %WPA_ALG_IGTK, %WPA_ALG_PMK);
+ *     %WPA_ALG_NONE clears the key.
+ * @addr: address of the peer STA or ff:ff:ff:ff:ff:ff for
+ *     broadcast/default keys
+ * @key_idx: key index (0..3), usually 0 for unicast keys; 0..4095 for
+ *     IGTK
+ * @set_tx: configure this key as the default Tx key (only used when
+ *     driver does not support separate unicast/individual key
+ * @seq: sequence number/packet number, seq_len octets, the next
+ *     packet number to be used for in replay protection; configured
+ *     for Rx keys (in most cases, this is only used with broadcast
+ *     keys and set to zero for unicast keys)
+ * @seq_len: length of the seq, depends on the algorithm:
+ *     TKIP: 6 octets, CCMP: 6 octets, IGTK: 6 octets
+ * @key: key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key,
+ *     8-byte Rx Mic Key
+ * @key_len: length of the key buffer in octets (WEP: 5 or 13,
+ *     TKIP: 32, CCMP: 16, IGTK: 16)
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ * Configure the given key for the kernel driver. If the driver
+ * supports separate individual keys (4 default keys + 1 individual),
+ * addr can be used to determine whether the key is default or
+ * individual. If only 4 keys are supported, the default key with key
+ * index 0 is used as the individual key. STA must be configured to use
+ * it as the default Tx key (set_tx is set) and accept Rx for all the
+ * key indexes. In most cases, WPA uses only key indexes 1 and 2 for
+ * broadcast keys, so key index 0 is available for this kind of
+ * configuration.
+ *
+ * Please note that TKIP keys include separate TX and RX MIC keys and
+ * some drivers may expect them in different order than wpa_supplicant
+ * is using. If the TX/RX keys are swapped, all TKIP encrypted packets
+ * will tricker Michael MIC errors. This can be fixed by changing the
+ * order of MIC keys by swapping te bytes 16..23 and 24..31 of the key
+ * in driver_*.c set_key() implementation, see driver_ndis.c for an
+ * example on how this can be done.
+ */
+
+typedef void (* WPA_SEND_FUNC)(struct pbuf *pb);
+
+typedef void (* WPA_SET_ASSOC_IE)(uint8 proto, u8 *assoc_buf, u32 assoc_wpa_ie_len);
+
+typedef void (*WPA_INSTALL_KEY) (enum wpa_alg alg, uint8 *addr, int key_idx, int set_tx,
+               uint8 *seq, size_t seq_len, uint8 *key, size_t key_len, int key_entry_valid);
+
+typedef void (*WPA_DEAUTH)(uint8 reason_code);
+
+typedef void (*WPA_NEG_COMPLETE)();
+
+void wpa_register(char * payload, WPA_SEND_FUNC snd_func, \
+                                                      WPA_SET_ASSOC_IE set_assoc_ie_func, \
+                                                      WPA_INSTALL_KEY ppinstallkey, \
+                                                      WPA_DEAUTH wpa_deauth, \
+                                                      WPA_NEG_COMPLETE wpa_neg_complete);
+
+#include "pp/esf_buf.h"
+void eapol_txcb(esf_buf_t *eb);
+
+void wpa_set_profile(uint32 wpa_proto);
+
+void wpa_set_bss(char *macddr, char * bssid, uint8 pairwise_cipher, uint8 group_cipher, char *passphrase, u8 *ssid, size_t ssid_len);
+
+int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len);
+#endif /* WPA_I_H */
+
diff --git a/components/wpa_supplicant/include/wpa/wpa_ie.h b/components/wpa_supplicant/include/wpa/wpa_ie.h
new file mode 100644 (file)
index 0000000..94518d8
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * wpa_supplicant - WPA/RSN IE and KDE definitions
+ * Copyright (c) 2004-2007, 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.
+ */
+
+#ifndef WPA_IE_H
+#define WPA_IE_H
+
+struct wpa_eapol_ie_parse {
+       const u8 *wpa_ie;
+       size_t wpa_ie_len;
+       const u8 *rsn_ie;
+       size_t rsn_ie_len;
+       const u8 *pmkid;
+       const u8 *gtk;
+       size_t gtk_len;
+       const u8 *mac_addr;
+       size_t mac_addr_len;
+#ifdef CONFIG_PEERKEY
+       const u8 *smk;
+       size_t smk_len;
+       const u8 *nonce;
+       size_t nonce_len;
+       const u8 *lifetime;
+       size_t lifetime_len;
+       const u8 *error;
+       size_t error_len;
+#endif /* CONFIG_PEERKEY */
+#ifdef CONFIG_IEEE80211W
+       const u8 *igtk;
+       size_t igtk_len;
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_IEEE80211R
+       const u8 *mdie;
+       size_t mdie_len;
+       const u8 *ftie;
+       size_t ftie_len;
+       const u8 *reassoc_deadline;
+       const u8 *key_lifetime;
+#endif /* CONFIG_IEEE80211R */
+};
+
+int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
+                            struct wpa_eapol_ie_parse *ie);
+int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len);
+
+#endif /* WPA_IE_H */
diff --git a/components/wpa_supplicant/include/wpa/wpabuf.h b/components/wpa_supplicant/include/wpa/wpabuf.h
new file mode 100644 (file)
index 0000000..cccfcc8
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Dynamic data buffer
+ * Copyright (c) 2007-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.
+ */
+
+#ifndef WPABUF_H
+#define WPABUF_H
+
+/*
+ * Internal data structure for wpabuf. Please do not touch this directly from
+ * elsewhere. This is only defined in header file to allow inline functions
+ * from this file to access data.
+ */
+struct wpabuf {
+       size_t size; /* total size of the allocated buffer */
+       size_t used; /* length of data in the buffer */
+       u8 *ext_data; /* pointer to external data; NULL if data follows
+                      * struct wpabuf */
+       /* optionally followed by the allocated buffer */
+};
+
+
+int wpabuf_resize(struct wpabuf **buf, size_t add_len);
+struct wpabuf * wpabuf_alloc(size_t len);
+struct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len);
+struct wpabuf * wpabuf_alloc_copy(const void *data, size_t len);
+struct wpabuf * wpabuf_dup(const struct wpabuf *src);
+void wpabuf_free(struct wpabuf *buf);
+void * wpabuf_put(struct wpabuf *buf, size_t len);
+struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b);
+struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len);
+void wpabuf_printf(struct wpabuf *buf, char *fmt, ...) PRINTF_FORMAT(2, 3);
+
+
+/**
+ * wpabuf_size - Get the currently allocated size of a wpabuf buffer
+ * @buf: wpabuf buffer
+ * Returns: Currently allocated size of the buffer
+ */
+static inline size_t wpabuf_size(const struct wpabuf *buf)
+{
+       return buf->size;
+}
+
+/**
+ * wpabuf_len - Get the current length of a wpabuf buffer data
+ * @buf: wpabuf buffer
+ * Returns: Currently used length of the buffer
+ */
+static inline size_t wpabuf_len(const struct wpabuf *buf)
+{
+       return buf->used;
+}
+
+/**
+ * wpabuf_tailroom - Get size of available tail room in the end of the buffer
+ * @buf: wpabuf buffer
+ * Returns: Tail room (in bytes) of available space in the end of the buffer
+ */
+static inline size_t wpabuf_tailroom(const struct wpabuf *buf)
+{
+       return buf->size - buf->used;
+}
+
+/**
+ * wpabuf_head - Get pointer to the head of the buffer data
+ * @buf: wpabuf buffer
+ * Returns: Pointer to the head of the buffer data
+ */
+static inline const void * wpabuf_head(const struct wpabuf *buf)
+{
+       if (buf->ext_data)
+               return buf->ext_data;
+       return buf + 1;
+}
+
+static inline const u8 * wpabuf_head_u8(const struct wpabuf *buf)
+{
+       return wpabuf_head(buf);
+}
+
+/**
+ * wpabuf_mhead - Get modifiable pointer to the head of the buffer data
+ * @buf: wpabuf buffer
+ * Returns: Pointer to the head of the buffer data
+ */
+static inline void * wpabuf_mhead(struct wpabuf *buf)
+{
+       if (buf->ext_data)
+               return buf->ext_data;
+       return buf + 1;
+}
+
+static inline u8 * wpabuf_mhead_u8(struct wpabuf *buf)
+{
+       return wpabuf_mhead(buf);
+}
+
+static inline void wpabuf_put_u8(struct wpabuf *buf, u8 data)
+{
+       u8 *pos = wpabuf_put(buf, 1);
+       *pos = data;
+}
+
+static inline void wpabuf_put_le16(struct wpabuf *buf, u16 data)
+{
+       u8 *pos = wpabuf_put(buf, 2);
+       WPA_PUT_LE16(pos, data);
+}
+
+static inline void wpabuf_put_le32(struct wpabuf *buf, u32 data)
+{
+       u8 *pos = wpabuf_put(buf, 4);
+       WPA_PUT_LE32(pos, data);
+}
+
+static inline void wpabuf_put_be16(struct wpabuf *buf, u16 data)
+{
+       u8 *pos = wpabuf_put(buf, 2);
+       WPA_PUT_BE16(pos, data);
+}
+
+static inline void wpabuf_put_be24(struct wpabuf *buf, u32 data)
+{
+       u8 *pos = wpabuf_put(buf, 3);
+       WPA_PUT_BE24(pos, data);
+}
+
+static inline void wpabuf_put_be32(struct wpabuf *buf, u32 data)
+{
+       u8 *pos = wpabuf_put(buf, 4);
+       WPA_PUT_BE32(pos, data);
+}
+
+static inline void wpabuf_put_data(struct wpabuf *buf, const void *data,
+                                  size_t len)
+{
+       if (data)
+               os_memcpy(wpabuf_put(buf, len), data, len);
+}
+
+static inline void wpabuf_put_buf(struct wpabuf *dst,
+                                 const struct wpabuf *src)
+{
+       wpabuf_put_data(dst, wpabuf_head(src), wpabuf_len(src));
+}
+
+static inline void wpabuf_set(struct wpabuf *buf, const void *data, size_t len)
+{
+       buf->ext_data = (u8 *) data;
+       buf->size = buf->used = len;
+}
+
+static inline void wpabuf_put_str(struct wpabuf *dst, const char *str)
+{
+       wpabuf_put_data(dst, str, os_strlen(str));
+}
+
+#endif /* WPABUF_H */
diff --git a/components/wpa_supplicant/include/wpa/wpas_glue.h b/components/wpa_supplicant/include/wpa/wpas_glue.h
new file mode 100644 (file)
index 0000000..7e254a2
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * WPA Supplicant - Glue code to setup EAPOL and RSN modules
+ * Copyright (c) 2003-2008, 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.
+ */
+
+#ifndef WPAS_GLUE_H
+#define WPAS_GLUE_H
+
+u8 * wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type,
+                                     const void *data, u16 data_len,
+                                     size_t *msg_len, void **data_pos);
+
+int wpa_sm_mlme_setprotection(struct wpa_sm *sm, const u8 *addr,
+                                           int protect_type, int key_type);
+
+void wpa_sm_deauthenticate(struct wpa_sm *sm, uint8 reason_code);
+
+void wpa_sm_disassociate(struct wpa_sm *sm, int reason_code);
+
+int wpa_sm_get_beacon_ie(struct wpa_sm *sm);
+
+#endif /* WPAS_GLUE_H */
diff --git a/components/wpa_supplicant/include/wpa2/eap_peer/eap.h b/components/wpa_supplicant/include/wpa2/eap_peer/eap.h
new file mode 100644 (file)
index 0000000..e2cd2dd
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * EAP peer state machine functions (RFC 4137)
+ * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef EAP_H
+#define EAP_H
+
+#include "wpa/defs.h"
+#include "eap/eap_defs.h"
+
+struct eap_sm;
+
+struct eap_method_type {
+       int vendor;
+       u32 method;
+};
+
+const u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len);
+
+#endif /* EAP_H */
diff --git a/components/wpa_supplicant/include/wpa2/eap_peer/eap_common.h b/components/wpa_supplicant/include/wpa2/eap_peer/eap_common.h
new file mode 100644 (file)
index 0000000..38c5710
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * EAP common peer/server definitions
+ * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef EAP_COMMON_H
+#define EAP_COMMON_H
+
+#include "wpa/wpabuf.h"
+
+int eap_hdr_len_valid(const struct wpabuf *msg, size_t min_payload);
+const u8 * eap_hdr_validate(int vendor, EapType eap_type,
+                           const struct wpabuf *msg, size_t *plen);
+struct wpabuf * eap_msg_alloc(int vendor, EapType type, size_t payload_len,
+                             u8 code, u8 identifier);
+void eap_update_len(struct wpabuf *msg);
+u8 eap_get_id(const struct wpabuf *msg);
+EapType eap_get_type(const struct wpabuf *msg);
+
+#endif /* EAP_COMMON_H */
diff --git a/components/wpa_supplicant/include/wpa2/eap_peer/eap_config.h b/components/wpa_supplicant/include/wpa2/eap_peer/eap_config.h
new file mode 100644 (file)
index 0000000..f35cbf4
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * EAP peer configuration data
+ * Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef EAP_CONFIG_H
+#define EAP_CONFIG_H
+
+/**
+ * struct eap_peer_config - EAP peer configuration/credentials
+ */
+struct eap_peer_config {
+       /**
+        * identity - EAP Identity
+        *
+        * This field is used to set the real user identity or NAI (for
+        * EAP-PSK/PAX/SAKE/GPSK).
+        */
+       u8 *identity;
+
+       /**
+        * identity_len - EAP Identity length
+        */
+       size_t identity_len;
+
+       /**
+        * password - Password string for EAP
+        *
+        * This field can include either the plaintext password (default
+        * option) or a NtPasswordHash (16-byte MD4 hash of the unicode
+        * presentation of the password) if flags field has
+        * EAP_CONFIG_FLAGS_PASSWORD_NTHASH bit set to 1. NtPasswordHash can
+        * only be used with authentication mechanism that use this hash as the
+        * starting point for operation: MSCHAP and MSCHAPv2 (EAP-MSCHAPv2,
+        * EAP-TTLS/MSCHAPv2, EAP-TTLS/MSCHAP, LEAP).
+        *
+        * In addition, this field is used to configure a pre-shared key for
+        * EAP-PSK/PAX/SAKE/GPSK. The length of the PSK must be 16 for EAP-PSK
+        * and EAP-PAX and 32 for EAP-SAKE. EAP-GPSK can use a variable length
+        * PSK.
+        */
+       u8 *password;
+
+       /**
+        * password_len - Length of password field
+        */
+       size_t password_len;
+
+       /**
+        * ca_cert - File path to CA certificate file (PEM/DER)
+        *
+        * This file can have one or more trusted CA certificates. If ca_cert
+        * and ca_path are not included, server certificate will not be
+        * verified. This is insecure and a trusted CA certificate should
+        * always be configured when using EAP-TLS/TTLS/PEAP. Full path to the
+        * file should be used since working directory may change when
+        * wpa_supplicant is run in the background.
+        *
+        * Alternatively, a named configuration blob can be used by setting
+        * this to blob://blob_name.
+        *
+        * Alternatively, this can be used to only perform matching of the
+        * server certificate (SHA-256 hash of the DER encoded X.509
+        * certificate). In this case, the possible CA certificates in the
+        * server certificate chain are ignored and only the server certificate
+        * is verified. This is configured with the following format:
+        * hash:://server/sha256/cert_hash_in_hex
+        * For example: "hash://server/sha256/
+        * 5a1bc1296205e6fdbe3979728efe3920798885c1c4590b5f90f43222d239ca6a"
+        *
+        * On Windows, trusted CA certificates can be loaded from the system
+        * certificate store by setting this to cert_store://name, e.g.,
+        * ca_cert="cert_store://CA" or ca_cert="cert_store://ROOT".
+        * Note that when running wpa_supplicant as an application, the user
+        * certificate store (My user account) is used, whereas computer store
+        * (Computer account) is used when running wpasvc as a service.
+        */
+       u8 *ca_cert;
+
+       /**
+        * ca_path - Directory path for CA certificate files (PEM)
+        *
+        * This path may contain multiple CA certificates in OpenSSL format.
+        * Common use for this is to point to system trusted CA list which is
+        * often installed into directory like /etc/ssl/certs. If configured,
+        * these certificates are added to the list of trusted CAs. ca_cert
+        * may also be included in that case, but it is not required.
+        */
+       u8 *ca_path;
+
+       /**
+        * client_cert - File path to client certificate file (PEM/DER)
+        *
+        * This field is used with EAP method that use TLS authentication.
+        * Usually, this is only configured for EAP-TLS, even though this could
+        * in theory be used with EAP-TTLS and EAP-PEAP, too. Full path to the
+        * file should be used since working directory may change when
+        * wpa_supplicant is run in the background.
+        *
+        * Alternatively, a named configuration blob can be used by setting
+        * this to blob://blob_name.
+        */
+       u8 *client_cert;
+
+       /**
+        * private_key - File path to client private key file (PEM/DER/PFX)
+        *
+        * When PKCS#12/PFX file (.p12/.pfx) is used, client_cert should be
+        * commented out. Both the private key and certificate will be read
+        * from the PKCS#12 file in this case. Full path to the file should be
+        * used since working directory may change when wpa_supplicant is run
+        * in the background.
+        *
+        * Windows certificate store can be used by leaving client_cert out and
+        * configuring private_key in one of the following formats:
+        *
+        * cert://substring_to_match
+        *
+        * hash://certificate_thumbprint_in_hex
+        *
+        * For example: private_key="hash://63093aa9c47f56ae88334c7b65a4"
+        *
+        * Note that when running wpa_supplicant as an application, the user
+        * certificate store (My user account) is used, whereas computer store
+        * (Computer account) is used when running wpasvc as a service.
+        *
+        * Alternatively, a named configuration blob can be used by setting
+        * this to blob://blob_name.
+        */
+       u8 *private_key;
+
+       /**
+        * private_key_passwd - Password for private key file
+        *
+        * If left out, this will be asked through control interface.
+        */
+       u8 *private_key_passwd;
+
+       char *phase1;
+
+       /**
+        * pin - PIN for USIM, GSM SIM, and smartcards
+        *
+        * This field is used to configure PIN for SIM and smartcards for
+        * EAP-SIM and EAP-AKA. In addition, this is used with EAP-TLS if a
+        * smartcard is used for private key operations.
+        *
+        * If left out, this will be asked through control interface.
+        */
+       char *pin;
+
+       /**
+        * fragment_size - Maximum EAP fragment size in bytes (default 1398)
+        *
+        * This value limits the fragment size for EAP methods that support
+        * fragmentation (e.g., EAP-TLS and EAP-PEAP). This value should be set
+        * small enough to make the EAP messages fit in MTU of the network
+        * interface used for EAPOL. The default value is suitable for most
+        * cases.
+        */
+       int fragment_size;
+
+#define EAP_CONFIG_FLAGS_PASSWORD_NTHASH BIT(0)
+#define EAP_CONFIG_FLAGS_EXT_PASSWORD BIT(1)
+       /**
+        * flags - Network configuration flags (bitfield)
+        *
+        * This variable is used for internal flags to describe further details
+        * for the network parameters.
+        * bit 0 = password is represented as a 16-byte NtPasswordHash value
+        *         instead of plaintext password
+        * bit 1 = password is stored in external storage; the value in the
+        *         password field is the name of that external entry
+        */
+       u32 flags;
+
+       /**
+        * ocsp - Whether to use/require OCSP to check server certificate
+        *
+        * 0 = do not use OCSP stapling (TLS certificate status extension)
+        * 1 = try to use OCSP stapling, but not require response
+        * 2 = require valid OCSP stapling response
+        */
+       int ocsp;
+};
+
+
+/**
+ * struct wpa_config_blob - Named configuration blob
+ *
+ * This data structure is used to provide storage for binary objects to store
+ * abstract information like certificates and private keys inlined with the
+ * configuration data.
+ */
+struct wpa_config_blob {
+       /**
+        * name - Blob name
+        */
+       char *name;
+
+       /**
+        * data - Pointer to binary data
+        */
+       u8 *data;
+
+       /**
+        * len - Length of binary data
+        */
+       size_t len;
+
+       /**
+        * next - Pointer to next blob in the configuration
+        */
+       struct wpa_config_blob *next;
+};
+
+#endif /* EAP_CONFIG_H */
diff --git a/components/wpa_supplicant/include/wpa2/eap_peer/eap_defs.h b/components/wpa_supplicant/include/wpa2/eap_peer/eap_defs.h
new file mode 100644 (file)
index 0000000..10995d3
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * EAP server/peer: Shared EAP definitions
+ * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef EAP_DEFS_H
+#define EAP_DEFS_H
+
+/* RFC 3748 - Extensible Authentication Protocol (EAP) */
+
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
+struct eap_hdr {
+       u8 code;
+       u8 identifier;
+       be16 length; /* including code and identifier; network byte order */
+       /* followed by length-4 octets of data */
+} STRUCT_PACKED;
+
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
+
+enum { EAP_CODE_REQUEST = 1, EAP_CODE_RESPONSE = 2, EAP_CODE_SUCCESS = 3,
+       EAP_CODE_FAILURE = 4 };
+
+/* EAP Request and Response data begins with one octet Type. Success and
+ * Failure do not have additional data. */
+
+/*
+ * EAP Method Types as allocated by IANA:
+ * http://www.iana.org/assignments/eap-numbers
+ */
+typedef enum {
+       EAP_TYPE_NONE = 0,
+       EAP_TYPE_IDENTITY = 1 /* RFC 3748 */,
+       EAP_TYPE_NOTIFICATION = 2 /* RFC 3748 */,
+       EAP_TYPE_NAK = 3 /* Response only, RFC 3748 */,
+       EAP_TYPE_MD5 = 4, /* RFC 3748 */
+       EAP_TYPE_OTP = 5 /* RFC 3748 */,
+       EAP_TYPE_GTC = 6, /* RFC 3748 */
+       EAP_TYPE_TLS = 13 /* RFC 2716 */,
+       EAP_TYPE_LEAP = 17 /* Cisco proprietary */,
+       EAP_TYPE_SIM = 18 /* RFC 4186 */,
+       EAP_TYPE_TTLS = 21 /* RFC 5281 */,
+       EAP_TYPE_AKA = 23 /* RFC 4187 */,
+       EAP_TYPE_PEAP = 25 /* draft-josefsson-pppext-eap-tls-eap-06.txt */,
+       EAP_TYPE_MSCHAPV2 = 26 /* draft-kamath-pppext-eap-mschapv2-00.txt */,
+       EAP_TYPE_TLV = 33 /* draft-josefsson-pppext-eap-tls-eap-07.txt */,
+       EAP_TYPE_TNC = 38 /* TNC IF-T v1.0-r3; note: tentative assignment;
+                          * type 38 has previously been allocated for
+                          * EAP-HTTP Digest, (funk.com) */,
+       EAP_TYPE_FAST = 43 /* RFC 4851 */,
+       EAP_TYPE_PAX = 46 /* RFC 4746 */,
+       EAP_TYPE_PSK = 47 /* RFC 4764 */,
+       EAP_TYPE_SAKE = 48 /* RFC 4763 */,
+       EAP_TYPE_IKEV2 = 49 /* RFC 5106 */,
+       EAP_TYPE_AKA_PRIME = 50 /* RFC 5448 */,
+       EAP_TYPE_GPSK = 51 /* RFC 5433 */,
+       EAP_TYPE_PWD = 52 /* RFC 5931 */,
+       EAP_TYPE_EKE = 53 /* RFC 6124 */,
+       EAP_TYPE_EXPANDED = 254 /* RFC 3748 */
+} EapType;
+
+
+/* SMI Network Management Private Enterprise Code for vendor specific types */
+enum {
+       EAP_VENDOR_IETF = 0,
+       EAP_VENDOR_MICROSOFT = 0x000137 /* Microsoft */,
+       EAP_VENDOR_WFA = 0x00372A /* Wi-Fi Alliance */,
+       EAP_VENDOR_HOSTAP = 39068 /* hostapd/wpa_supplicant project */
+};
+
+struct eap_expand {
+    u8 vendor_id[3];
+    be32 vendor_type;
+    u8 opcode;
+} STRUCT_PACKED;
+
+#define EAP_VENDOR_UNAUTH_TLS EAP_VENDOR_HOSTAP
+#define EAP_VENDOR_TYPE_UNAUTH_TLS 1
+
+#define EAP_MSK_LEN 64
+#define EAP_EMSK_LEN 64
+
+#endif /* EAP_DEFS_H */
diff --git a/components/wpa_supplicant/include/wpa2/eap_peer/eap_i.h b/components/wpa_supplicant/include/wpa2/eap_peer/eap_i.h
new file mode 100644 (file)
index 0000000..a4779d1
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * EAP peer state machines internal structures (RFC 4137)
+ * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef EAP_I_H
+#define EAP_I_H
+
+#include "wpa/wpabuf.h"
+#include "eap.h"
+#include "eap_common.h"
+#include "eap_config.h"
+
+/* RFC 4137 - EAP Peer state machine */
+
+typedef enum {
+       DECISION_FAIL, DECISION_COND_SUCC, DECISION_UNCOND_SUCC
+} EapDecision;
+
+typedef enum {
+       METHOD_NONE, METHOD_INIT, METHOD_CONT, METHOD_MAY_CONT, METHOD_DONE
+} EapMethodState;
+
+/**
+ * struct eap_method_ret - EAP return values from struct eap_method::process()
+ *
+ * These structure contains OUT variables for the interface between peer state
+ * machine and methods (RFC 4137, Sect. 4.2). eapRespData will be returned as
+ * the return value of struct eap_method::process() so it is not included in
+ * this structure.
+ */
+struct eap_method_ret {
+       /**
+        * ignore - Whether method decided to drop the current packed (OUT)
+        */
+       Boolean ignore;
+
+       /**
+        * methodState - Method-specific state (IN/OUT)
+        */
+       EapMethodState methodState;
+
+       /**
+        * decision - Authentication decision (OUT)
+        */
+       EapDecision decision;
+
+       /**
+        * allowNotifications - Whether method allows notifications (OUT)
+        */
+       Boolean allowNotifications;
+};
+
+#define CLIENT_CERT_NAME       "CLC"
+#define CA_CERT_NAME           "CAC"
+#define PRIVATE_KEY_NAME       "PVK"
+#define BLOB_NAME_LEN          3
+#define BLOB_NUM               2
+
+/**
+ * struct eap_sm - EAP state machine data
+ */
+struct eap_sm {
+       void *eap_method_priv;
+
+       void *ssl_ctx;
+
+       unsigned int workaround;
+/////////////////////////////////////////////////
+        struct pbuf *outbuf;
+       struct wpa_config_blob blob[BLOB_NUM];
+       struct eap_peer_config config;
+       u8 current_identifier;
+       u8 ownaddr[ETH_ALEN];
+#ifdef USE_WPA2_TASK
+#define SIG_WPA2_NUM 2
+       u8 wpa2_sig_cnt[SIG_WPA2_NUM];
+#endif
+       u8 finish_state;
+};
+
+struct eap_peer_config * eap_get_config(struct eap_sm *sm);
+const struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm, const char *name);
+
+#endif /* EAP_I_H */
diff --git a/components/wpa_supplicant/include/wpa2/eap_peer/eap_tls.h b/components/wpa_supplicant/include/wpa2/eap_peer/eap_tls.h
new file mode 100644 (file)
index 0000000..a8a386f
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions
+ * Copyright (c) 2004-2009, 2012, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef EAP_TLS_H
+#define EAP_TLS_H
+
+#include "eap_i.h"
+#include "eap_common.h" 
+#include "eap.h" 
+#include "wpa/wpabuf.h" 
+
+void * eap_tls_init(struct eap_sm *sm);
+void eap_tls_deinit(struct eap_sm *sm, void *priv);
+struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
+                                       struct eap_method_ret *ret,
+                                       const struct wpabuf *reqData);
+
+u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len);
+
+#endif /* EAP_TLS_H */
diff --git a/components/wpa_supplicant/include/wpa2/eap_peer/eap_tls_common.h b/components/wpa_supplicant/include/wpa2/eap_peer/eap_tls_common.h
new file mode 100644 (file)
index 0000000..1a5e0f8
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions
+ * Copyright (c) 2004-2009, 2012, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef EAP_TLS_COMMON_H
+#define EAP_TLS_COMMON_H
+
+/**
+ * struct eap_ssl_data - TLS data for EAP methods
+ */
+struct eap_ssl_data {
+       /**
+        * conn - TLS connection context data from tls_connection_init()
+        */
+       struct tls_connection *conn;
+
+       /**
+        * tls_out - TLS message to be sent out in fragments
+        */
+       struct wpabuf *tls_out;
+
+       /**
+        * tls_out_pos - The current position in the outgoing TLS message
+        */
+       size_t tls_out_pos;
+
+       /**
+        * tls_out_limit - Maximum fragment size for outgoing TLS messages
+        */
+       size_t tls_out_limit;
+
+       /**
+        * tls_in - Received TLS message buffer for re-assembly
+        */
+       struct wpabuf *tls_in;
+
+       /**
+        * tls_in_left - Number of remaining bytes in the incoming TLS message
+        */
+       size_t tls_in_left;
+
+       /**
+        * tls_in_total - Total number of bytes in the incoming TLS message
+        */
+       size_t tls_in_total;
+
+       /**
+        * phase2 - Whether this TLS connection is used in EAP phase 2 (tunnel)
+        */
+       int phase2;
+
+       /**
+        * include_tls_length - Whether the TLS length field is included even
+        * if the TLS data is not fragmented
+        */
+       int include_tls_length;
+
+       /**
+        * eap - EAP state machine allocated with eap_peer_sm_init()
+        */
+       struct eap_sm *eap;
+
+       /**
+        * ssl_ctx - TLS library context to use for the connection
+        */
+       void *ssl_ctx;
+
+       /**
+        * eap_type - EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST)
+        */
+       u8 eap_type;
+};
+
+
+/* EAP TLS Flags */
+#define EAP_TLS_FLAGS_LENGTH_INCLUDED 0x80
+#define EAP_TLS_FLAGS_MORE_FRAGMENTS 0x40
+#define EAP_TLS_FLAGS_START 0x20
+#define EAP_TLS_VERSION_MASK 0x07
+
+ /* could be up to 128 bytes, but only the first 64 bytes are used */
+#define EAP_TLS_KEY_LEN 64
+
+/* dummy type used as a flag for UNAUTH-TLS */
+#define EAP_UNAUTH_TLS_TYPE 255
+
+
+int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
+                         struct eap_peer_config *config, u8 eap_type);
+void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data);
+u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
+                            const char *label, size_t len);
+u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
+                                   struct eap_ssl_data *data, u8 eap_type,
+                                   size_t *len);
+int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
+                               EapType eap_type, int peap_version,
+                               u8 id, const u8 *in_data, size_t in_len,
+                               struct wpabuf **out_data);
+struct wpabuf * eap_peer_tls_build_ack(u8 id, EapType eap_type,
+                                      int peap_version);
+int eap_peer_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data);
+int eap_peer_tls_status(struct eap_sm *sm, struct eap_ssl_data *data,
+                       char *buf, size_t buflen, int verbose);
+const u8 * eap_peer_tls_process_init(struct eap_sm *sm,
+                                    struct eap_ssl_data *data,
+                                    EapType eap_type,
+                                    struct eap_method_ret *ret,
+                                    const struct wpabuf *reqData,
+                                    size_t *len, u8 *flags);
+void eap_peer_tls_reset_input(struct eap_ssl_data *data);
+void eap_peer_tls_reset_output(struct eap_ssl_data *data);
+int eap_peer_tls_decrypt(struct eap_sm *sm, struct eap_ssl_data *data,
+                        const struct wpabuf *in_data,
+                        struct wpabuf **in_decrypted);
+int eap_peer_tls_encrypt(struct eap_sm *sm, struct eap_ssl_data *data,
+                        EapType eap_type, int peap_version, u8 id,
+                        const struct wpabuf *in_data,
+                        struct wpabuf **out_data);
+int eap_peer_select_phase2_methods(struct eap_peer_config *config,
+                                  const char *prefix,
+                                  struct eap_method_type **types,
+                                  size_t *num_types);
+int eap_peer_tls_phase2_nak(struct eap_method_type *types, size_t num_types,
+                           struct eap_hdr *hdr, struct wpabuf **resp);
+
+#endif /* EAP_TLS_COMMON_H */
diff --git a/components/wpa_supplicant/include/wpa2/tls/asn1.h b/components/wpa_supplicant/include/wpa2/tls/asn1.h
new file mode 100644 (file)
index 0000000..6342c4c
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * ASN.1 DER parsing
+ * Copyright (c) 2006, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef ASN1_H
+#define ASN1_H
+
+#define ASN1_TAG_EOC           0x00 /* not used with DER */
+#define ASN1_TAG_BOOLEAN       0x01
+#define ASN1_TAG_INTEGER       0x02
+#define ASN1_TAG_BITSTRING     0x03
+#define ASN1_TAG_OCTETSTRING   0x04
+#define ASN1_TAG_NULL          0x05
+#define ASN1_TAG_OID           0x06
+#define ASN1_TAG_OBJECT_DESCRIPTOR     0x07 /* not yet parsed */
+#define ASN1_TAG_EXTERNAL      0x08 /* not yet parsed */
+#define ASN1_TAG_REAL          0x09 /* not yet parsed */
+#define ASN1_TAG_ENUMERATED    0x0A /* not yet parsed */
+#define ASN1_TAG_UTF8STRING    0x0C /* not yet parsed */
+#define ANS1_TAG_RELATIVE_OID  0x0D
+#define ASN1_TAG_SEQUENCE      0x10 /* shall be constructed */
+#define ASN1_TAG_SET           0x11
+#define ASN1_TAG_NUMERICSTRING 0x12 /* not yet parsed */
+#define ASN1_TAG_PRINTABLESTRING       0x13
+#define ASN1_TAG_TG1STRING     0x14 /* not yet parsed */
+#define ASN1_TAG_VIDEOTEXSTRING        0x15 /* not yet parsed */
+#define ASN1_TAG_IA5STRING     0x16
+#define ASN1_TAG_UTCTIME       0x17
+#define ASN1_TAG_GENERALIZEDTIME       0x18 /* not yet parsed */
+#define ASN1_TAG_GRAPHICSTRING 0x19 /* not yet parsed */
+#define ASN1_TAG_VISIBLESTRING 0x1A
+#define ASN1_TAG_GENERALSTRING 0x1B /* not yet parsed */
+#define ASN1_TAG_UNIVERSALSTRING       0x1C /* not yet parsed */
+#define ASN1_TAG_BMPSTRING     0x1D /* not yet parsed */
+
+#define ASN1_CLASS_UNIVERSAL           0
+#define ASN1_CLASS_APPLICATION         1
+#define ASN1_CLASS_CONTEXT_SPECIFIC    2
+#define ASN1_CLASS_PRIVATE             3
+
+
+struct asn1_hdr {
+       const u8 *payload;
+       u8 identifier, class, constructed;
+       unsigned int tag, length;
+};
+
+#define ASN1_MAX_OID_LEN 20
+struct asn1_oid {
+       unsigned long oid[ASN1_MAX_OID_LEN];
+       size_t len;
+};
+
+
+int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr);
+int asn1_parse_oid(const u8 *buf, size_t len, struct asn1_oid *oid);
+int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid,
+                const u8 **next);
+void asn1_oid_to_str(struct asn1_oid *oid, char *buf, size_t len);
+unsigned long asn1_bit_string_to_long(const u8 *buf, size_t len);
+
+#endif /* ASN1_H */
diff --git a/components/wpa_supplicant/include/wpa2/tls/bignum.h b/components/wpa_supplicant/include/wpa2/tls/bignum.h
new file mode 100644 (file)
index 0000000..f25e267
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Big number math
+ * Copyright (c) 2006, 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.
+ */
+
+#ifndef BIGNUM_H
+#define BIGNUM_H
+
+struct bignum;
+
+struct bignum * bignum_init(void);
+void bignum_deinit(struct bignum *n);
+size_t bignum_get_unsigned_bin_len(struct bignum *n);
+int bignum_get_unsigned_bin(const struct bignum *n, u8 *buf, size_t *len);
+int bignum_set_unsigned_bin(struct bignum *n, const u8 *buf, size_t len);
+int bignum_cmp(const struct bignum *a, const struct bignum *b);
+int bignum_cmp_d(const struct bignum *a, unsigned long b);
+int bignum_add(const struct bignum *a, const struct bignum *b,
+              struct bignum *c);
+int bignum_sub(const struct bignum *a, const struct bignum *b,
+              struct bignum *c);
+int bignum_mul(const struct bignum *a, const struct bignum *b,
+              struct bignum *c);
+int bignum_mulmod(const struct bignum *a, const struct bignum *b,
+                 const struct bignum *c, struct bignum *d);
+int bignum_exptmod(const struct bignum *a, const struct bignum *b,
+                  const struct bignum *c, struct bignum *d);
+
+#endif /* BIGNUM_H */
diff --git a/components/wpa_supplicant/include/wpa2/tls/libtommath.h b/components/wpa_supplicant/include/wpa2/tls/libtommath.h
new file mode 100644 (file)
index 0000000..c0409b5
--- /dev/null
@@ -0,0 +1,3443 @@
+/*
+ * Minimal code for RSA support from LibTomMath 0.41
+ * http://libtom.org/
+ * http://libtom.org/files/ltm-0.41.tar.bz2
+ * This library was released in public domain by Tom St Denis.
+ *
+ * The combination in this file may not use all of the optimized algorithms
+ * from LibTomMath and may be considerable slower than the LibTomMath with its
+ * default settings. The main purpose of having this version here is to make it
+ * easier to build bignum.c wrapper without having to install and build an
+ * external library.
+ *
+ * If CONFIG_INTERNAL_LIBTOMMATH is defined, bignum.c includes this
+ * libtommath.c file instead of using the external LibTomMath library.
+ */
+#include "c_types.h"
+#include "os.h"
+#include "stdarg.h"
+
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
+#define BN_MP_INVMOD_C
+#define BN_S_MP_EXPTMOD_C /* Note: #undef in tommath_superclass.h; this would
+                          * require BN_MP_EXPTMOD_FAST_C instead */
+#define BN_S_MP_MUL_DIGS_C
+#define BN_MP_INVMOD_SLOW_C
+#define BN_S_MP_SQR_C
+#define BN_S_MP_MUL_HIGH_DIGS_C /* Note: #undef in tommath_superclass.h; this
+                                * would require other than mp_reduce */
+
+#ifdef LTM_FAST
+
+/* Use faster div at the cost of about 1 kB */
+#define BN_MP_MUL_D_C
+
+/* Include faster exptmod (Montgomery) at the cost of about 2.5 kB in code */
+#define BN_MP_EXPTMOD_FAST_C
+#define BN_MP_MONTGOMERY_SETUP_C
+#define BN_FAST_MP_MONTGOMERY_REDUCE_C
+#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+#define BN_MP_MUL_2_C
+
+/* Include faster sqr at the cost of about 0.5 kB in code */
+#define BN_FAST_S_MP_SQR_C
+
+#else /* LTM_FAST */
+
+#define BN_MP_DIV_SMALL
+#define BN_MP_INIT_MULTI_C
+#define BN_MP_CLEAR_MULTI_C
+#define BN_MP_ABS_C
+#endif /* LTM_FAST */
+
+/* Current uses do not require support for negative exponent in exptmod, so we
+ * can save about 1.5 kB in leaving out invmod. */
+#define LTM_NO_NEG_EXP
+
+/* from tommath.h */
+
+#ifndef MIN
+   #define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+#ifndef MAX
+   #define MAX(x,y) ((x)>(y)?(x):(y))
+#endif
+
+#define  OPT_CAST(x) (x *)
+
+typedef unsigned long mp_digit;
+typedef u64 mp_word;
+
+#define DIGIT_BIT          28
+#define MP_28BIT
+
+
+#define XMALLOC  os_malloc
+#define XFREE    os_free
+#define XREALLOC os_realloc
+
+
+#define MP_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
+
+#define MP_LT        -1   /* less than */
+#define MP_EQ         0   /* equal to */
+#define MP_GT         1   /* greater than */
+
+#define MP_ZPOS       0   /* positive integer */
+#define MP_NEG        1   /* negative */
+
+#define MP_OKAY       0   /* ok result */
+#define MP_MEM        -2  /* out of mem */
+#define MP_VAL        -3  /* invalid input */
+
+#define MP_YES        1   /* yes response */
+#define MP_NO         0   /* no response */
+
+typedef int           mp_err;
+
+/* define this to use lower memory usage routines (exptmods mostly) */
+#define MP_LOW_MEM
+
+/* default precision */
+#ifndef MP_PREC
+   #ifndef MP_LOW_MEM
+      #define MP_PREC                 32     /* default digits of precision */
+   #else
+      #define MP_PREC                 8      /* default digits of precision */
+   #endif   
+#endif
+
+/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
+#define MP_WARRAY               (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))
+
+/* the infamous mp_int structure */
+typedef struct  {
+    int used, alloc, sign;
+    mp_digit *dp;
+} mp_int;
+
+
+/* ---> Basic Manipulations <--- */
+#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
+#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
+#define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
+
+
+/* prototypes for copied functions */
+#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
+static int s_mp_exptmod(mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode);
+static int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
+static int s_mp_sqr(mp_int * a, mp_int * b);
+static int s_mp_mul_high_digs(mp_int * a, mp_int * b, mp_int * c, int digs);
+
+static int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
+
+#ifdef BN_MP_INIT_MULTI_C
+static int mp_init_multi(mp_int *mp, ...);
+#endif
+#ifdef BN_MP_CLEAR_MULTI_C
+static void mp_clear_multi(mp_int *mp, ...);
+#endif
+static int mp_lshd(mp_int * a, int b);
+static void mp_set(mp_int * a, mp_digit b);
+static void mp_clamp(mp_int * a);
+static void mp_exch(mp_int * a, mp_int * b);
+static void mp_rshd(mp_int * a, int b);
+static void mp_zero(mp_int * a);
+static int mp_mod_2d(mp_int * a, int b, mp_int * c);
+static int mp_div_2d(mp_int * a, int b, mp_int * c, mp_int * d);
+static int mp_init_copy(mp_int * a, mp_int * b);
+static int mp_mul_2d(mp_int * a, int b, mp_int * c);
+#ifndef LTM_NO_NEG_EXP
+static int mp_div_2(mp_int * a, mp_int * b);
+static int mp_invmod(mp_int * a, mp_int * b, mp_int * c);
+static int mp_invmod_slow(mp_int * a, mp_int * b, mp_int * c);
+#endif /* LTM_NO_NEG_EXP */
+static int mp_copy(mp_int * a, mp_int * b);
+static int mp_count_bits(mp_int * a);
+static int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d);
+static int mp_mod(mp_int * a, mp_int * b, mp_int * c);
+static int mp_grow(mp_int * a, int size);
+static int mp_cmp_mag(mp_int * a, mp_int * b);
+#ifdef BN_MP_ABS_C
+static int mp_abs(mp_int * a, mp_int * b);
+#endif
+static int mp_sqr(mp_int * a, mp_int * b);
+static int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d);
+static int mp_reduce_2k_setup_l(mp_int *a, mp_int *d);
+static int mp_2expt(mp_int * a, int b);
+static int mp_reduce_setup(mp_int * a, mp_int * b);
+static int mp_reduce(mp_int * x, mp_int * m, mp_int * mu);
+static int mp_init_size(mp_int * a, int size);
+#ifdef BN_MP_EXPTMOD_FAST_C
+static int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode);
+#endif /* BN_MP_EXPTMOD_FAST_C */
+#ifdef BN_FAST_S_MP_SQR_C
+static int fast_s_mp_sqr (mp_int * a, mp_int * b);
+#endif /* BN_FAST_S_MP_SQR_C */
+#ifdef BN_MP_MUL_D_C
+static int mp_mul_d (mp_int * a, mp_digit b, mp_int * c);
+#endif /* BN_MP_MUL_D_C */
+
+
+
+/* functions from bn_<func name>.c */
+
+
+/* reverse an array, used for radix code */
+static void ICACHE_FLASH_ATTR
+bn_reverse (unsigned char *s, int len)
+{
+  int     ix, iy;
+  unsigned char t;
+
+  ix = 0;
+  iy = len - 1;
+  while (ix < iy) {
+    t     = s[ix];
+    s[ix] = s[iy];
+    s[iy] = t;
+    ++ix;
+    --iy;
+  }
+}
+
+
+/* low level addition, based on HAC pp.594, Algorithm 14.7 */
+static int ICACHE_FLASH_ATTR
+s_mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int *x;
+  int     olduse, res, min, max;
+
+  /* find sizes, we let |a| <= |b| which means we have to sort
+   * them.  "x" will point to the input with the most digits
+   */
+  if (a->used > b->used) {
+    min = b->used;
+    max = a->used;
+    x = a;
+  } else {
+    min = a->used;
+    max = b->used;
+    x = b;
+  }
+
+  /* init result */
+  if (c->alloc < max + 1) {
+    if ((res = mp_grow (c, max + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* get old used digit count and set new one */
+  olduse = c->used;
+  c->used = max + 1;
+
+  {
+    register mp_digit u, *tmpa, *tmpb, *tmpc;
+    register int i;
+
+    /* alias for digit pointers */
+
+    /* first input */
+    tmpa = a->dp;
+
+    /* second input */
+    tmpb = b->dp;
+
+    /* destination */
+    tmpc = c->dp;
+
+    /* zero the carry */
+    u = 0;
+    for (i = 0; i < min; i++) {
+      /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
+      *tmpc = *tmpa++ + *tmpb++ + u;
+
+      /* U = carry bit of T[i] */
+      u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+      /* take away carry bit from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* now copy higher words if any, that is in A+B 
+     * if A or B has more digits add those in 
+     */
+    if (min != max) {
+      for (; i < max; i++) {
+        /* T[i] = X[i] + U */
+        *tmpc = x->dp[i] + u;
+
+        /* U = carry bit of T[i] */
+        u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+        /* take away carry bit from T[i] */
+        *tmpc++ &= MP_MASK;
+      }
+    }
+
+    /* add carry */
+    *tmpc++ = u;
+
+    /* clear digits above oldused */
+    for (i = c->used; i < olduse; i++) {
+      *tmpc++ = 0;
+    }
+  }
+
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
+static int ICACHE_FLASH_ATTR
+s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     olduse, res, min, max;
+
+  /* find sizes */
+  min = b->used;
+  max = a->used;
+
+  /* init result */
+  if (c->alloc < max) {
+    if ((res = mp_grow (c, max)) != MP_OKAY) {
+      return res;
+    }
+  }
+  olduse = c->used;
+  c->used = max;
+
+  {
+    register mp_digit u, *tmpa, *tmpb, *tmpc;
+    register int i;
+
+    /* alias for digit pointers */
+    tmpa = a->dp;
+    tmpb = b->dp;
+    tmpc = c->dp;
+
+    /* set carry to zero */
+    u = 0;
+    for (i = 0; i < min; i++) {
+      /* T[i] = A[i] - B[i] - U */
+      *tmpc = *tmpa++ - *tmpb++ - u;
+
+      /* U = carry bit of T[i]
+       * Note this saves performing an AND operation since
+       * if a carry does occur it will propagate all the way to the
+       * MSB.  As a result a single shift is enough to get the carry
+       */
+      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+      /* Clear carry from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* now copy higher words if any, e.g. if A has more digits than B  */
+    for (; i < max; i++) {
+      /* T[i] = A[i] - U */
+      *tmpc = *tmpa++ - u;
+
+      /* U = carry bit of T[i] */
+      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+      /* Clear carry from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* clear digits above used (since we may not have grown result above) */
+    for (i = c->used; i < olduse; i++) {
+      *tmpc++ = 0;
+    }
+  }
+
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+/* init a new mp_int */
+static int ICACHE_FLASH_ATTR
+mp_init (mp_int * a)
+{
+  int i;
+
+  /* allocate memory required and clear it */
+  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC);
+  if (a->dp == NULL) {
+    return MP_MEM;
+  }
+
+  /* set the digits to zero */
+  for (i = 0; i < MP_PREC; i++) {
+      a->dp[i] = 0;
+  }
+
+  /* set the used to zero, allocated digits to the default precision
+   * and sign to positive */
+  a->used  = 0;
+  a->alloc = MP_PREC;
+  a->sign  = MP_ZPOS;
+
+  return MP_OKAY;
+}
+
+
+/* clear one (frees)  */
+static void ICACHE_FLASH_ATTR
+mp_clear (mp_int * a)
+{
+  int i;
+
+  /* only do anything if a hasn't been freed previously */
+  if (a->dp != NULL) {
+    /* first zero the digits */
+    for (i = 0; i < a->used; i++) {
+        a->dp[i] = 0;
+    }
+
+    /* free ram */
+    XFREE(a->dp);
+
+    /* reset members to make debugging easier */
+    a->dp    = NULL;
+    a->alloc = a->used = 0;
+    a->sign  = MP_ZPOS;
+  }
+}
+
+
+/* high level addition (handles signs) */
+static int ICACHE_FLASH_ATTR
+mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     sa, sb, res;
+
+  /* get sign of both inputs */
+  sa = a->sign;
+  sb = b->sign;
+
+  /* handle two cases, not four */
+  if (sa == sb) {
+    /* both positive or both negative */
+    /* add their magnitudes, copy the sign */
+    c->sign = sa;
+    res = s_mp_add (a, b, c);
+  } else {
+    /* one positive, the other negative */
+    /* subtract the one with the greater magnitude from */
+    /* the one of the lesser magnitude.  The result gets */
+    /* the sign of the one with the greater magnitude. */
+    if (mp_cmp_mag (a, b) == MP_LT) {
+      c->sign = sb;
+      res = s_mp_sub (b, a, c);
+    } else {
+      c->sign = sa;
+      res = s_mp_sub (a, b, c);
+    }
+  }
+  return res;
+}
+
+
+/* high level subtraction (handles signs) */
+static int ICACHE_FLASH_ATTR
+mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     sa, sb, res;
+
+  sa = a->sign;
+  sb = b->sign;
+
+  if (sa != sb) {
+    /* subtract a negative from a positive, OR */
+    /* subtract a positive from a negative. */
+    /* In either case, ADD their magnitudes, */
+    /* and use the sign of the first number. */
+    c->sign = sa;
+    res = s_mp_add (a, b, c);
+  } else {
+    /* subtract a positive from a positive, OR */
+    /* subtract a negative from a negative. */
+    /* First, take the difference between their */
+    /* magnitudes, then... */
+    if (mp_cmp_mag (a, b) != MP_LT) {
+      /* Copy the sign from the first */
+      c->sign = sa;
+      /* The first has a larger or equal magnitude */
+      res = s_mp_sub (a, b, c);
+    } else {
+      /* The result has the *opposite* sign from */
+      /* the first number. */
+      c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+      /* The second has a larger magnitude */
+      res = s_mp_sub (b, a, c);
+    }
+  }
+  return res;
+}
+
+
+/* high level multiplication (handles sign) */
+static int ICACHE_FLASH_ATTR
+mp_mul (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res, neg;
+  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+
+  /* use Toom-Cook? */
+#ifdef BN_MP_TOOM_MUL_C
+  if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) {
+    res = mp_toom_mul(a, b, c);
+  } else 
+#endif
+#ifdef BN_MP_KARATSUBA_MUL_C
+  /* use Karatsuba? */
+  if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) {
+    res = mp_karatsuba_mul (a, b, c);
+  } else 
+#endif
+  {
+    /* can we use the fast multiplier?
+     *
+     * The fast multiplier can be used if the output will 
+     * have less than MP_WARRAY digits and the number of 
+     * digits won't affect carry propagation
+     */
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
+    int     digs = a->used + b->used + 1;
+
+    if ((digs < MP_WARRAY) &&
+        MIN(a->used, b->used) <= 
+        (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+      res = fast_s_mp_mul_digs (a, b, c, digs);
+    } else 
+#endif
+#ifdef BN_S_MP_MUL_DIGS_C
+      res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
+#else
+#error mp_mul could fail
+      res = MP_VAL;
+#endif
+
+  }
+  c->sign = (c->used > 0) ? neg : MP_ZPOS;
+  return res;
+}
+
+
+/* d = a * b (mod c) */
+static int ICACHE_FLASH_ATTR
+mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  int     res;
+  mp_int  t;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_mul (a, b, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, c, d);
+  mp_clear (&t);
+  return res;
+}
+
+
+/* c = a mod b, 0 <= c < b */
+static int ICACHE_FLASH_ATTR
+mp_mod (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  t;
+  int     res;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+
+  if (t.sign != b->sign) {
+    res = mp_add (b, &t, c);
+  } else {
+    res = MP_OKAY;
+    mp_exch (&t, c);
+  }
+
+  mp_clear (&t);
+  return res;
+}
+
+
+/* this is a shell function that calls either the normal or Montgomery
+ * exptmod functions.  Originally the call to the montgomery code was
+ * embedded in the normal function but that wasted a lot of stack space
+ * for nothing (since 99% of the time the Montgomery code would be called)
+ */
+static int ICACHE_FLASH_ATTR
+mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
+{
+  int dr;
+
+  /* modulus P must be positive */
+  if (P->sign == MP_NEG) {
+     return MP_VAL;
+  }
+
+  /* if exponent X is negative we have to recurse */
+  if (X->sign == MP_NEG) {
+#ifdef LTM_NO_NEG_EXP
+        return MP_VAL;
+#else /* LTM_NO_NEG_EXP */
+#ifdef BN_MP_INVMOD_C
+     mp_int tmpG, tmpX;
+     int err;
+
+     /* first compute 1/G mod P */
+     if ((err = mp_init(&tmpG)) != MP_OKAY) {
+        return err;
+     }
+     if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
+        mp_clear(&tmpG);
+        return err;
+     }
+
+     /* now get |X| */
+     if ((err = mp_init(&tmpX)) != MP_OKAY) {
+        mp_clear(&tmpG);
+        return err;
+     }
+     if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
+        mp_clear_multi(&tmpG, &tmpX, NULL);
+        return err;
+     }
+
+     /* and now compute (1/G)**|X| instead of G**X [X < 0] */
+     err = mp_exptmod(&tmpG, &tmpX, P, Y);
+     mp_clear_multi(&tmpG, &tmpX, NULL);
+     return err;
+#else 
+#error mp_exptmod would always fail
+     /* no invmod */
+     return MP_VAL;
+#endif
+#endif /* LTM_NO_NEG_EXP */
+  }
+
+/* modified diminished radix reduction */
+#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C)
+  if (mp_reduce_is_2k_l(P) == MP_YES) {
+     return s_mp_exptmod(G, X, P, Y, 1);
+  }
+#endif
+
+#ifdef BN_MP_DR_IS_MODULUS_C
+  /* is it a DR modulus? */
+  dr = mp_dr_is_modulus(P);
+#else
+  /* default to no */
+  dr = 0;
+#endif
+
+#ifdef BN_MP_REDUCE_IS_2K_C
+  /* if not, is it a unrestricted DR modulus? */
+  if (dr == 0) {
+     dr = mp_reduce_is_2k(P) << 1;
+  }
+#endif
+    
+  /* if the modulus is odd or dr != 0 use the montgomery method */
+#ifdef BN_MP_EXPTMOD_FAST_C
+  if (mp_isodd (P) == 1 || dr !=  0) {
+    return mp_exptmod_fast (G, X, P, Y, dr);
+  } else {
+#endif
+#ifdef BN_S_MP_EXPTMOD_C
+    /* otherwise use the generic Barrett reduction technique */
+    return s_mp_exptmod (G, X, P, Y, 0);
+#else
+#error mp_exptmod could fail
+    /* no exptmod for evens */
+    return MP_VAL;
+#endif
+#ifdef BN_MP_EXPTMOD_FAST_C
+  }
+#endif
+}
+
+
+/* compare two ints (signed)*/
+static int ICACHE_FLASH_ATTR
+mp_cmp (mp_int * a, mp_int * b)
+{
+  /* compare based on sign */
+  if (a->sign != b->sign) {
+     if (a->sign == MP_NEG) {
+        return MP_LT;
+     } else {
+        return MP_GT;
+     }
+  }
+  
+  /* compare digits */
+  if (a->sign == MP_NEG) {
+     /* if negative compare opposite direction */
+     return mp_cmp_mag(b, a);
+  } else {
+     return mp_cmp_mag(a, b);
+  }
+}
+
+
+/* compare a digit */
+static int ICACHE_FLASH_ATTR
+mp_cmp_d(mp_int * a, mp_digit b)
+{
+  /* compare based on sign */
+  if (a->sign == MP_NEG) {
+    return MP_LT;
+  }
+
+  /* compare based on magnitude */
+  if (a->used > 1) {
+    return MP_GT;
+  }
+
+  /* compare the only digit of a to b */
+  if (a->dp[0] > b) {
+    return MP_GT;
+  } else if (a->dp[0] < b) {
+    return MP_LT;
+  } else {
+    return MP_EQ;
+  }
+}
+
+
+#ifndef LTM_NO_NEG_EXP
+/* hac 14.61, pp608 */
+static int ICACHE_FLASH_ATTR
+mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+  /* b cannot be negative */
+  if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+    return MP_VAL;
+  }
+
+#ifdef BN_FAST_MP_INVMOD_C
+  /* if the modulus is odd we can use a faster routine instead */
+  if (mp_isodd (b) == 1) {
+    return fast_mp_invmod (a, b, c);
+  }
+#endif
+
+#ifdef BN_MP_INVMOD_SLOW_C
+  return mp_invmod_slow(a, b, c);
+#endif
+
+#ifndef BN_FAST_MP_INVMOD_C
+#ifndef BN_MP_INVMOD_SLOW_C
+#error mp_invmod would always fail
+#endif
+#endif
+  return MP_VAL;
+}
+#endif /* LTM_NO_NEG_EXP */
+
+
+/* get the size for an unsigned equivalent */
+static int ICACHE_FLASH_ATTR
+mp_unsigned_bin_size (mp_int * a)
+{
+  int     size = mp_count_bits (a);
+  return (size / 8 + ((size & 7) != 0 ? 1 : 0));
+}
+
+
+#ifndef LTM_NO_NEG_EXP
+/* hac 14.61, pp608 */
+static int ICACHE_FLASH_ATTR
+mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  x, y, u, v, A, B, C, D;
+  int     res;
+
+  /* b cannot be negative */
+  if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+    return MP_VAL;
+  }
+
+  /* init temps */
+  if ((res = mp_init_multi(&x, &y, &u, &v, 
+                           &A, &B, &C, &D, NULL)) != MP_OKAY) {
+     return res;
+  }
+
+  /* x = a, y = b */
+  if ((res = mp_mod(a, b, &x)) != MP_OKAY) {
+      goto LBL_ERR;
+  }
+  if ((res = mp_copy (b, &y)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+
+  /* 2. [modified] if x,y are both even then return an error! */
+  if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) {
+    res = MP_VAL;
+    goto LBL_ERR;
+  }
+
+  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  mp_set (&A, 1);
+  mp_set (&D, 1);
+
+top:
+  /* 4.  while u is even do */
+  while (mp_iseven (&u) == 1) {
+    /* 4.1 u = u/2 */
+    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    /* 4.2 if A or B is odd then */
+    if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) {
+      /* A = (A+y)/2, B = (B-x)/2 */
+      if ((res = mp_add (&A, &y, &A)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+    }
+    /* A = A/2, B = B/2 */
+    if ((res = mp_div_2 (&A, &A)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* 5.  while v is even do */
+  while (mp_iseven (&v) == 1) {
+    /* 5.1 v = v/2 */
+    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    /* 5.2 if C or D is odd then */
+    if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) {
+      /* C = (C+y)/2, D = (D-x)/2 */
+      if ((res = mp_add (&C, &y, &C)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+    }
+    /* C = C/2, D = D/2 */
+    if ((res = mp_div_2 (&C, &C)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* 6.  if u >= v then */
+  if (mp_cmp (&u, &v) != MP_LT) {
+    /* u = u - v, A = A - C, B = B - D */
+    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  } else {
+    /* v - v - u, C = C - A, D = D - B */
+    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* if not zero goto step 4 */
+  if (mp_iszero (&u) == 0)
+    goto top;
+
+  /* now a = C, b = D, gcd == g*v */
+
+  /* if v != 1 then there is no inverse */
+  if (mp_cmp_d (&v, 1) != MP_EQ) {
+    res = MP_VAL;
+    goto LBL_ERR;
+  }
+
+  /* if its too low */
+  while (mp_cmp_d(&C, 0) == MP_LT) {
+      if ((res = mp_add(&C, b, &C)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+  }
+  
+  /* too big */
+  while (mp_cmp_mag(&C, b) != MP_LT) {
+      if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+  }
+  
+  /* C is now the inverse */
+  mp_exch (&C, c);
+  res = MP_OKAY;
+LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL);
+  return res;
+}
+#endif /* LTM_NO_NEG_EXP */
+
+
+/* compare maginitude of two ints (unsigned) */
+static int ICACHE_FLASH_ATTR
+mp_cmp_mag (mp_int * a, mp_int * b)
+{
+  int     n;
+  mp_digit *tmpa, *tmpb;
+
+  /* compare based on # of non-zero digits */
+  if (a->used > b->used) {
+    return MP_GT;
+  }
+  
+  if (a->used < b->used) {
+    return MP_LT;
+  }
+
+  /* alias for a */
+  tmpa = a->dp + (a->used - 1);
+
+  /* alias for b */
+  tmpb = b->dp + (a->used - 1);
+
+  /* compare based on digits  */
+  for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
+    if (*tmpa > *tmpb) {
+      return MP_GT;
+    }
+
+    if (*tmpa < *tmpb) {
+      return MP_LT;
+    }
+  }
+  return MP_EQ;
+}
+
+
+/* reads a unsigned char array, assumes the msb is stored first [big endian] */
+static int ICACHE_FLASH_ATTR
+mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c)
+{
+  int     res;
+
+  /* make sure there are at least two digits */
+  if (a->alloc < 2) {
+     if ((res = mp_grow(a, 2)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* zero the int */
+  mp_zero (a);
+
+  /* read the bytes in */
+  while (c-- > 0) {
+    if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) {
+      return res;
+    }
+
+#ifndef MP_8BIT
+      a->dp[0] |= *b++;
+      a->used += 1;
+#else
+      a->dp[0] = (*b & MP_MASK);
+      a->dp[1] |= ((*b++ >> 7U) & 1);
+      a->used += 2;
+#endif
+  }
+  mp_clamp (a);
+  return MP_OKAY;
+}
+
+
+/* store in unsigned [big endian] format */
+static int ICACHE_FLASH_ATTR
+mp_to_unsigned_bin (mp_int * a, unsigned char *b)
+{
+  int     x, res;
+  mp_int  t;
+
+  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+    return res;
+  }
+
+  x = 0;
+  while (mp_iszero (&t) == 0) {
+#ifndef MP_8BIT
+      b[x++] = (unsigned char) (t.dp[0] & 255);
+#else
+      b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7));
+#endif
+    if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+  }
+  bn_reverse (b, x);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+/* shift right by a certain bit count (store quotient in c, optional remainder in d) */
+static int ICACHE_FLASH_ATTR
+mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
+{
+  mp_digit D, r, rr;
+  int     x, res;
+  mp_int  t;
+
+
+  /* if the shift count is <= 0 then we do no work */
+  if (b <= 0) {
+    res = mp_copy (a, c);
+    if (d != NULL) {
+      mp_zero (d);
+    }
+    return res;
+  }
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  /* get the remainder */
+  if (d != NULL) {
+    if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+  }
+
+  /* copy */
+  if ((res = mp_copy (a, c)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+
+  /* shift by as many digits in the bit count */
+  if (b >= (int)DIGIT_BIT) {
+    mp_rshd (c, b / DIGIT_BIT);
+  }
+
+  /* shift any bit count < DIGIT_BIT */
+  D = (mp_digit) (b % DIGIT_BIT);
+  if (D != 0) {
+    register mp_digit *tmpc, mask, shift;
+
+    /* mask */
+    mask = (((mp_digit)1) << D) - 1;
+
+    /* shift for lsb */
+    shift = DIGIT_BIT - D;
+
+    /* alias */
+    tmpc = c->dp + (c->used - 1);
+
+    /* carry */
+    r = 0;
+    for (x = c->used - 1; x >= 0; x--) {
+      /* get the lower  bits of this word in a temp */
+      rr = *tmpc & mask;
+
+      /* shift the current word and mix in the carry bits from the previous word */
+      *tmpc = (*tmpc >> D) | (r << shift);
+      --tmpc;
+
+      /* set the carry to the carry bits of the current word found above */
+      r = rr;
+    }
+  }
+  mp_clamp (c);
+  if (d != NULL) {
+    mp_exch (&t, d);
+  }
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+static int ICACHE_FLASH_ATTR
+mp_init_copy (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  if ((res = mp_init (a)) != MP_OKAY) {
+    return res;
+  }
+  return mp_copy (b, a);
+}
+
+
+/* set to zero */
+static void ICACHE_FLASH_ATTR
+mp_zero (mp_int * a)
+{
+  int       n;
+  mp_digit *tmp;
+
+  a->sign = MP_ZPOS;
+  a->used = 0;
+
+  tmp = a->dp;
+  for (n = 0; n < a->alloc; n++) {
+     *tmp++ = 0;
+  }
+}
+
+
+/* copy, b = a */
+static int ICACHE_FLASH_ATTR
+mp_copy (mp_int * a, mp_int * b)
+{
+  int     res, n;
+
+  /* if dst == src do nothing */
+  if (a == b) {
+    return MP_OKAY;
+  }
+
+  /* grow dest */
+  if (b->alloc < a->used) {
+     if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* zero b and copy the parameters over */
+  {
+    register mp_digit *tmpa, *tmpb;
+
+    /* pointer aliases */
+
+    /* source */
+    tmpa = a->dp;
+
+    /* destination */
+    tmpb = b->dp;
+
+    /* copy all the digits */
+    for (n = 0; n < a->used; n++) {
+      *tmpb++ = *tmpa++;
+    }
+
+    /* clear high digits */
+    for (; n < b->used; n++) {
+      *tmpb++ = 0;
+    }
+  }
+
+  /* copy used count and sign */
+  b->used = a->used;
+  b->sign = a->sign;
+  return MP_OKAY;
+}
+
+
+/* shift right a certain amount of digits */
+static void ICACHE_FLASH_ATTR
+mp_rshd (mp_int * a, int b)
+{
+  int     x;
+
+  /* if b <= 0 then ignore it */
+  if (b <= 0) {
+    return;
+  }
+
+  /* if b > used then simply zero it and return */
+  if (a->used <= b) {
+    mp_zero (a);
+    return;
+  }
+
+  {
+    register mp_digit *bottom, *top;
+
+    /* shift the digits down */
+
+    /* bottom */
+    bottom = a->dp;
+
+    /* top [offset into digits] */
+    top = a->dp + b;
+
+    /* this is implemented as a sliding window where 
+     * the window is b-digits long and digits from 
+     * the top of the window are copied to the bottom
+     *
+     * e.g.
+
+     b-2 | b-1 | b0 | b1 | b2 | ... | bb |   ---->
+                 /\                   |      ---->
+                  \-------------------/      ---->
+     */
+    for (x = 0; x < (a->used - b); x++) {
+      *bottom++ = *top++;
+    }
+
+    /* zero the top digits */
+    for (; x < a->used; x++) {
+      *bottom++ = 0;
+    }
+  }
+  
+  /* remove excess digits */
+  a->used -= b;
+}
+
+
+/* swap the elements of two integers, for cases where you can't simply swap the 
+ * mp_int pointers around
+ */
+static void ICACHE_FLASH_ATTR
+mp_exch (mp_int * a, mp_int * b)
+{
+  mp_int  t;
+
+  t  = *a;
+  *a = *b;
+  *b = t;
+}
+
+
+/* trim unused digits 
+ *
+ * This is used to ensure that leading zero digits are
+ * trimed and the leading "used" digit will be non-zero
+ * Typically very fast.  Also fixes the sign if there
+ * are no more leading digits
+ */
+static void ICACHE_FLASH_ATTR
+mp_clamp (mp_int * a)
+{
+  /* decrease used while the most significant digit is
+   * zero.
+   */
+  while (a->used > 0 && a->dp[a->used - 1] == 0) {
+    --(a->used);
+  }
+
+  /* reset the sign flag if used == 0 */
+  if (a->used == 0) {
+    a->sign = MP_ZPOS;
+  }
+}
+
+
+/* grow as required */
+static int ICACHE_FLASH_ATTR
+mp_grow (mp_int * a, int size)
+{
+  int     i;
+  mp_digit *tmp;
+
+  /* if the alloc size is smaller alloc more ram */
+  if (a->alloc < size) {
+    /* ensure there are always at least MP_PREC digits extra on top */
+    size += (MP_PREC * 2) - (size % MP_PREC);
+
+    /* reallocate the array a->dp
+     *
+     * We store the return in a temporary variable
+     * in case the operation failed we don't want
+     * to overwrite the dp member of a.
+     */
+    tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size);
+    if (tmp == NULL) {
+      /* reallocation failed but "a" is still valid [can be freed] */
+      return MP_MEM;
+    }
+
+    /* reallocation succeeded so set a->dp */
+    a->dp = tmp;
+
+    /* zero excess digits */
+    i        = a->alloc;
+    a->alloc = size;
+    for (; i < a->alloc; i++) {
+      a->dp[i] = 0;
+    }
+  }
+  return MP_OKAY;
+}
+
+
+#ifdef BN_MP_ABS_C
+/* b = |a| 
+ *
+ * Simple function copies the input and fixes the sign to positive
+ */
+static int ICACHE_FLASH_ATTR
+mp_abs (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  /* copy a to b */
+  if (a != b) {
+     if ((res = mp_copy (a, b)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  /* force the sign of b to positive */
+  b->sign = MP_ZPOS;
+
+  return MP_OKAY;
+}
+#endif
+
+
+/* set to a digit */
+static void ICACHE_FLASH_ATTR
+mp_set (mp_int * a, mp_digit b)
+{
+  mp_zero (a);
+  a->dp[0] = b & MP_MASK;
+  a->used  = (a->dp[0] != 0) ? 1 : 0;
+}
+
+
+#ifndef LTM_NO_NEG_EXP
+/* b = a/2 */
+static int ICACHE_FLASH_ATTR
+mp_div_2(mp_int * a, mp_int * b)
+{
+  int     x, res, oldused;
+
+  /* copy */
+  if (b->alloc < a->used) {
+    if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  oldused = b->used;
+  b->used = a->used;
+  {
+    register mp_digit r, rr, *tmpa, *tmpb;
+
+    /* source alias */
+    tmpa = a->dp + b->used - 1;
+
+    /* dest alias */
+    tmpb = b->dp + b->used - 1;
+
+    /* carry */
+    r = 0;
+    for (x = b->used - 1; x >= 0; x--) {
+      /* get the carry for the next iteration */
+      rr = *tmpa & 1;
+
+      /* shift the current digit, add in carry and store */
+      *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
+
+      /* forward carry to next iteration */
+      r = rr;
+    }
+
+    /* zero excess digits */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+  mp_clamp (b);
+  return MP_OKAY;
+}
+#endif /* LTM_NO_NEG_EXP */
+
+
+/* shift left by a certain bit count */
+static int ICACHE_FLASH_ATTR
+mp_mul_2d (mp_int * a, int b, mp_int * c)
+{
+  mp_digit d;
+  int      res;
+
+  /* copy */
+  if (a != c) {
+     if ((res = mp_copy (a, c)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) {
+     if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  /* shift by as many digits in the bit count */
+  if (b >= (int)DIGIT_BIT) {
+    if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* shift any bit count < DIGIT_BIT */
+  d = (mp_digit) (b % DIGIT_BIT);
+  if (d != 0) {
+    register mp_digit *tmpc, shift, mask, r, rr;
+    register int x;
+
+    /* bitmask for carries */
+    mask = (((mp_digit)1) << d) - 1;
+
+    /* shift for msbs */
+    shift = DIGIT_BIT - d;
+
+    /* alias */
+    tmpc = c->dp;
+
+    /* carry */
+    r    = 0;
+    for (x = 0; x < c->used; x++) {
+      /* get the higher bits of the current word */
+      rr = (*tmpc >> shift) & mask;
+
+      /* shift the current word and OR in the carry */
+      *tmpc = ((*tmpc << d) | r) & MP_MASK;
+      ++tmpc;
+
+      /* set the carry to the carry bits of the current word */
+      r = rr;
+    }
+    
+    /* set final carry */
+    if (r != 0) {
+       c->dp[(c->used)++] = r;
+    }
+  }
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+#ifdef BN_MP_INIT_MULTI_C
+static int ICACHE_FLASH_ATTR
+mp_init_multi(mp_int *mp, ...) 
+{
+    mp_err res = MP_OKAY;      /* Assume ok until proven otherwise */
+    int n = 0;                 /* Number of ok inits */
+    mp_int* cur_arg = mp;
+    va_list args;
+
+    va_start(args, mp);        /* init args to next argument from caller */
+    while (cur_arg != NULL) {
+        if (mp_init(cur_arg) != MP_OKAY) {
+            /* Oops - error! Back-track and mp_clear what we already
+               succeeded in init-ing, then return error.
+            */
+            va_list clean_args;
+            
+            /* end the current list */
+            va_end(args);
+            
+            /* now start cleaning up */            
+            cur_arg = mp;
+            va_start(clean_args, mp);
+            while (n--) {
+                mp_clear(cur_arg);
+                cur_arg = va_arg(clean_args, mp_int*);
+            }
+            va_end(clean_args);
+            res = MP_MEM;
+            break;
+        }
+        n++;
+        cur_arg = va_arg(args, mp_int*);
+    }
+    va_end(args);
+    return res;                /* Assumed ok, if error flagged above. */
+}
+#endif
+
+
+#ifdef BN_MP_CLEAR_MULTI_C
+static void ICACHE_FLASH_ATTR
+mp_clear_multi(mp_int *mp, ...) 
+{
+    mp_int* next_mp = mp;
+    va_list args;
+    va_start(args, mp);
+    while (next_mp != NULL) {
+        mp_clear(next_mp);
+        next_mp = va_arg(args, mp_int*);
+    }
+    va_end(args);
+}
+#endif
+
+
+/* shift left a certain amount of digits */
+static int ICACHE_FLASH_ATTR
+mp_lshd (mp_int * a, int b)
+{
+  int     x, res;
+
+  /* if its less than zero return */
+  if (b <= 0) {
+    return MP_OKAY;
+  }
+
+  /* grow to fit the new digits */
+  if (a->alloc < a->used + b) {
+     if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  {
+    register mp_digit *top, *bottom;
+
+    /* increment the used by the shift amount then copy upwards */
+    a->used += b;
+
+    /* top */
+    top = a->dp + a->used - 1;
+
+    /* base */
+    bottom = a->dp + a->used - 1 - b;
+
+    /* much like mp_rshd this is implemented using a sliding window
+     * except the window goes the otherway around.  Copying from
+     * the bottom to the top.  see bn_mp_rshd.c for more info.
+     */
+    for (x = a->used - 1; x >= b; x--) {
+      *top-- = *bottom--;
+    }
+
+    /* zero the lower digits */
+    top = a->dp;
+    for (x = 0; x < b; x++) {
+      *top++ = 0;
+    }
+  }
+  return MP_OKAY;
+}
+
+
+/* returns the number of bits in an int */
+static int ICACHE_FLASH_ATTR
+mp_count_bits (mp_int * a)
+{
+  int     r;
+  mp_digit q;
+
+  /* shortcut */
+  if (a->used == 0) {
+    return 0;
+  }
+
+  /* get number of digits and add that */
+  r = (a->used - 1) * DIGIT_BIT;
+  
+  /* take the last digit and count the bits in it */
+  q = a->dp[a->used - 1];
+  while (q > ((mp_digit) 0)) {
+    ++r;
+    q >>= ((mp_digit) 1);
+  }
+  return r;
+}
+
+
+/* calc a value mod 2**b */
+static int ICACHE_FLASH_ATTR
+mp_mod_2d (mp_int * a, int b, mp_int * c)
+{
+  int     x, res;
+
+  /* if b is <= 0 then zero the int */
+  if (b <= 0) {
+    mp_zero (c);
+    return MP_OKAY;
+  }
+
+  /* if the modulus is larger than the value than return */
+  if (b >= (int) (a->used * DIGIT_BIT)) {
+    res = mp_copy (a, c);
+    return res;
+  }
+
+  /* copy */
+  if ((res = mp_copy (a, c)) != MP_OKAY) {
+    return res;
+  }
+
+  /* zero digits above the last digit of the modulus */
+  for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
+    c->dp[x] = 0;
+  }
+  /* clear the digit that is not completely outside/inside the modulus */
+  c->dp[b / DIGIT_BIT] &=
+    (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1));
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+#ifdef BN_MP_DIV_SMALL
+
+/* slower bit-bang division... also smaller */
+static int ICACHE_FLASH_ATTR
+mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+   mp_int ta, tb, tq, q;
+   int    res, n, n2;
+
+  /* is divisor zero ? */
+  if (mp_iszero (b) == 1) {
+    return MP_VAL;
+  }
+
+  /* if a < b then q=0, r = a */
+  if (mp_cmp_mag (a, b) == MP_LT) {
+    if (d != NULL) {
+      res = mp_copy (a, d);
+    } else {
+      res = MP_OKAY;
+    }
+    if (c != NULL) {
+      mp_zero (c);
+    }
+    return res;
+  }
+       
+  /* init our temps */
+  if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) {
+     return res;
+  }
+
+
+  mp_set(&tq, 1);
+  n = mp_count_bits(a) - mp_count_bits(b);
+  if (((res = mp_abs(a, &ta)) != MP_OKAY) ||
+      ((res = mp_abs(b, &tb)) != MP_OKAY) || 
+      ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
+      ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {
+      goto LBL_ERR;
+  }
+
+  while (n-- >= 0) {
+     if (mp_cmp(&tb, &ta) != MP_GT) {
+        if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
+            ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {
+           goto LBL_ERR;
+        }
+     }
+     if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
+         ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {
+           goto LBL_ERR;
+     }
+  }
+
+  /* now q == quotient and ta == remainder */
+  n  = a->sign;
+  n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
+  if (c != NULL) {
+     mp_exch(c, &q);
+     c->sign  = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;
+  }
+  if (d != NULL) {
+     mp_exch(d, &ta);
+     d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;
+  }
+LBL_ERR:
+   mp_clear_multi(&ta, &tb, &tq, &q, NULL);
+   return res;
+}
+
+#else
+
+/* integer signed division. 
+ * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
+ * HAC pp.598 Algorithm 14.20
+ *
+ * Note that the description in HAC is horribly 
+ * incomplete.  For example, it doesn't consider 
+ * the case where digits are removed from 'x' in 
+ * the inner loop.  It also doesn't consider the 
+ * case that y has fewer than three digits, etc..
+ *
+ * The overall algorithm is as described as 
+ * 14.20 from HAC but fixed to treat these cases.
+*/
+static int ICACHE_FLASH_ATTR
+mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  mp_int  q, x, y, t1, t2;
+  int     res, n, t, i, norm, neg;
+
+  /* is divisor zero ? */
+  if (mp_iszero (b) == 1) {
+    return MP_VAL;
+  }
+
+  /* if a < b then q=0, r = a */
+  if (mp_cmp_mag (a, b) == MP_LT) {
+    if (d != NULL) {
+      res = mp_copy (a, d);
+    } else {
+      res = MP_OKAY;
+    }
+    if (c != NULL) {
+      mp_zero (c);
+    }
+    return res;
+  }
+
+  if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) {
+    return res;
+  }
+  q.used = a->used + 2;
+
+  if ((res = mp_init (&t1)) != MP_OKAY) {
+    goto LBL_Q;
+  }
+
+  if ((res = mp_init (&t2)) != MP_OKAY) {
+    goto LBL_T1;
+  }
+
+  if ((res = mp_init_copy (&x, a)) != MP_OKAY) {
+    goto LBL_T2;
+  }
+
+  if ((res = mp_init_copy (&y, b)) != MP_OKAY) {
+    goto LBL_X;
+  }
+
+  /* fix the sign */
+  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+  x.sign = y.sign = MP_ZPOS;
+
+  /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
+  norm = mp_count_bits(&y) % DIGIT_BIT;
+  if (norm < (int)(DIGIT_BIT-1)) {
+     norm = (DIGIT_BIT-1) - norm;
+     if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) {
+       goto LBL_Y;
+     }
+     if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) {
+       goto LBL_Y;
+     }
+  } else {
+     norm = 0;
+  }
+
+  /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
+  n = x.used - 1;
+  t = y.used - 1;
+
+  /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
+  if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */
+    goto LBL_Y;
+  }
+
+  while (mp_cmp (&x, &y) != MP_LT) {
+    ++(q.dp[n - t]);
+    if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+  }
+
+  /* reset y by shifting it back down */
+  mp_rshd (&y, n - t);
+
+  /* step 3. for i from n down to (t + 1) */
+  for (i = n; i >= (t + 1); i--) {
+    if (i > x.used) {
+      continue;
+    }
+
+    /* step 3.1 if xi == yt then set q{i-t-1} to b-1, 
+     * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
+    if (x.dp[i] == y.dp[t]) {
+      q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
+    } else {
+      mp_word tmp;
+      tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
+      tmp |= ((mp_word) x.dp[i - 1]);
+      tmp /= ((mp_word) y.dp[t]);
+      if (tmp > (mp_word) MP_MASK)
+        tmp = MP_MASK;
+      q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));
+    }
+
+    /* while (q{i-t-1} * (yt * b + y{t-1})) > 
+             xi * b**2 + xi-1 * b + xi-2 
+     
+       do q{i-t-1} -= 1; 
+    */
+    q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;
+    do {
+      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;
+
+      /* find left hand */
+      mp_zero (&t1);
+      t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
+      t1.dp[1] = y.dp[t];
+      t1.used = 2;
+      if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+
+      /* find right hand */
+      t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
+      t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
+      t2.dp[2] = x.dp[i];
+      t2.used = 3;
+    } while (mp_cmp_mag(&t1, &t2) == MP_GT);
+
+    /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
+    if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
+    if (x.sign == MP_NEG) {
+      if ((res = mp_copy (&y, &t1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+      if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+      if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+
+      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;
+    }
+  }
+
+  /* now q is the quotient and x is the remainder 
+   * [which we have to normalize] 
+   */
+  
+  /* get sign before writing to c */
+  x.sign = x.used == 0 ? MP_ZPOS : a->sign;
+
+  if (c != NULL) {
+    mp_clamp (&q);
+    mp_exch (&q, c);
+    c->sign = neg;
+  }
+
+  if (d != NULL) {
+    mp_div_2d (&x, norm, &x, NULL);
+    mp_exch (&x, d);
+  }
+
+  res = MP_OKAY;
+
+LBL_Y:mp_clear (&y);
+LBL_X:mp_clear (&x);
+LBL_T2:mp_clear (&t2);
+LBL_T1:mp_clear (&t1);
+LBL_Q:mp_clear (&q);
+  return res;
+}
+
+#endif
+
+
+#ifdef MP_LOW_MEM
+   #define TAB_SIZE 32
+#else
+   #define TAB_SIZE 256
+#endif
+
+static int ICACHE_FLASH_ATTR
+s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+  mp_int  M[TAB_SIZE], res, mu;
+  mp_digit buf;
+  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+  int (*redux)(mp_int*,mp_int*,mp_int*);
+
+  /* find window size */
+  x = mp_count_bits (X);
+  if (x <= 7) {
+    winsize = 2;
+  } else if (x <= 36) {
+    winsize = 3;
+  } else if (x <= 140) {
+    winsize = 4;
+  } else if (x <= 450) {
+    winsize = 5;
+  } else if (x <= 1303) {
+    winsize = 6;
+  } else if (x <= 3529) {
+    winsize = 7;
+  } else {
+    winsize = 8;
+  }
+
+#ifdef MP_LOW_MEM
+    if (winsize > 5) {
+       winsize = 5;
+    }
+#endif
+
+  /* init M array */
+  /* init first cell */
+  if ((err = mp_init(&M[1])) != MP_OKAY) {
+     return err; 
+  }
+
+  /* now init the second half of the array */
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    if ((err = mp_init(&M[x])) != MP_OKAY) {
+      for (y = 1<<(winsize-1); y < x; y++) {
+        mp_clear (&M[y]);
+      }
+      mp_clear(&M[1]);
+      return err;
+    }
+  }
+
+  /* create mu, used for Barrett reduction */
+  if ((err = mp_init (&mu)) != MP_OKAY) {
+    goto LBL_M;
+  }
+  
+  if (redmode == 0) {
+     if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
+        goto LBL_MU;
+     }
+     redux = mp_reduce;
+  } else {
+     if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) {
+        goto LBL_MU;
+     }
+     redux = mp_reduce_2k_l;
+  }    
+
+  /* create M table
+   *
+   * The M table contains powers of the base, 
+   * e.g. M[x] = G**x mod P
+   *
+   * The first half of the table is not 
+   * computed though accept for M[0] and M[1]
+   */
+  if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
+    goto LBL_MU;
+  }
+
+  /* compute the value at M[1<<(winsize-1)] by squaring 
+   * M[1] (winsize-1) times 
+   */
+  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+    goto LBL_MU;
+  }
+
+  for (x = 0; x < (winsize - 1); x++) {
+    /* square it */
+    if ((err = mp_sqr (&M[1 << (winsize - 1)], 
+                       &M[1 << (winsize - 1)])) != MP_OKAY) {
+      goto LBL_MU;
+    }
+
+    /* reduce modulo P */
+    if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {
+      goto LBL_MU;
+    }
+  }
+
+  /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
+   * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
+   */
+  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+      goto LBL_MU;
+    }
+    if ((err = redux (&M[x], P, &mu)) != MP_OKAY) {
+      goto LBL_MU;
+    }
+  }
+
+  /* setup result */
+  if ((err = mp_init (&res)) != MP_OKAY) {
+    goto LBL_MU;
+  }
+  mp_set (&res, 1);
+
+  /* set initial mode and bit cnt */
+  mode   = 0;
+  bitcnt = 1;
+  buf    = 0;
+  digidx = X->used - 1;
+  bitcpy = 0;
+  bitbuf = 0;
+
+  for (;;) {
+    /* grab next digit as required */
+    if (--bitcnt == 0) {
+      /* if digidx == -1 we are out of digits */
+      if (digidx == -1) {
+        break;
+      }
+      /* read next digit and reset the bitcnt */
+      buf    = X->dp[digidx--];
+      bitcnt = (int) DIGIT_BIT;
+    }
+
+    /* grab the next msb from the exponent */
+    y     = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
+    buf <<= (mp_digit)1;
+
+    /* if the bit is zero and mode == 0 then we ignore it
+     * These represent the leading zero bits before the first 1 bit
+     * in the exponent.  Technically this opt is not required but it
+     * does lower the # of trivial squaring/reductions used
+     */
+    if (mode == 0 && y == 0) {
+      continue;
+    }
+
+    /* if the bit is zero and mode == 1 then we square */
+    if (mode == 1 && y == 0) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      continue;
+    }
+
+    /* else we add it to the window */
+    bitbuf |= (y << (winsize - ++bitcpy));
+    mode    = 2;
+
+    if (bitcpy == winsize) {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < winsize; x++) {
+        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+
+      /* then multiply */
+      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+      mode   = 1;
+    }
+  }
+
+  /* if bits remain then square/multiply */
+  if (mode == 2 && bitcpy > 0) {
+    /* square then multiply if the bit is set */
+    for (x = 0; x < bitcpy; x++) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      bitbuf <<= 1;
+      if ((bitbuf & (1 << winsize)) != 0) {
+        /* then multiply */
+        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+    }
+  }
+
+  mp_exch (&res, Y);
+  err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_MU:mp_clear (&mu);
+LBL_M:
+  mp_clear(&M[1]);
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    mp_clear (&M[x]);
+  }
+  return err;
+}
+
+
+/* computes b = a*a */
+static int ICACHE_FLASH_ATTR
+mp_sqr (mp_int * a, mp_int * b)
+{
+  int     res;
+
+#ifdef BN_MP_TOOM_SQR_C
+  /* use Toom-Cook? */
+  if (a->used >= TOOM_SQR_CUTOFF) {
+    res = mp_toom_sqr(a, b);
+  /* Karatsuba? */
+  } else 
+#endif
+#ifdef BN_MP_KARATSUBA_SQR_C
+if (a->used >= KARATSUBA_SQR_CUTOFF) {
+    res = mp_karatsuba_sqr (a, b);
+  } else 
+#endif
+  {
+#ifdef BN_FAST_S_MP_SQR_C
+    /* can we use the fast comba multiplier? */
+    if ((a->used * 2 + 1) < MP_WARRAY && 
+         a->used < 
+         (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
+      res = fast_s_mp_sqr (a, b);
+    } else
+#endif
+#ifdef BN_S_MP_SQR_C
+      res = s_mp_sqr (a, b);
+#else
+#error mp_sqr could fail
+      res = MP_VAL;
+#endif
+  }
+  b->sign = MP_ZPOS;
+  return res;
+}
+
+
+/* reduces a modulo n where n is of the form 2**p - d 
+   This differs from reduce_2k since "d" can be larger
+   than a single digit.
+*/
+static int ICACHE_FLASH_ATTR
+mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d)
+{
+   mp_int q;
+   int    p, res;
+   
+   if ((res = mp_init(&q)) != MP_OKAY) {
+      return res;
+   }
+   
+   p = mp_count_bits(n);    
+top:
+   /* q = a/2**p, a = a mod 2**p */
+   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   /* q = q * d */
+   if ((res = mp_mul(&q, d, &q)) != MP_OKAY) { 
+      goto ERR;
+   }
+   
+   /* a = a + q */
+   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   if (mp_cmp_mag(a, n) != MP_LT) {
+      s_mp_sub(a, n, a);
+      goto top;
+   }
+   
+ERR:
+   mp_clear(&q);
+   return res;
+}
+
+
+/* determines the setup value */
+static int ICACHE_FLASH_ATTR
+mp_reduce_2k_setup_l(mp_int *a, mp_int *d)
+{
+   int    res;
+   mp_int tmp;
+   
+   if ((res = mp_init(&tmp)) != MP_OKAY) {
+      return res;
+   }
+   
+   if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+ERR:
+   mp_clear(&tmp);
+   return res;
+}
+
+
+/* computes a = 2**b 
+ *
+ * Simple algorithm which zeroes the int, grows it then just sets one bit
+ * as required.
+ */
+static int ICACHE_FLASH_ATTR
+mp_2expt (mp_int * a, int b)
+{
+  int     res;
+
+  /* zero a as per default */
+  mp_zero (a);
+
+  /* grow a to accommodate the single bit */
+  if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) {
+    return res;
+  }
+
+  /* set the used count of where the bit will go */
+  a->used = b / DIGIT_BIT + 1;
+
+  /* put the single bit in its place */
+  a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);
+
+  return MP_OKAY;
+}
+
+
+/* pre-calculate the value required for Barrett reduction
+ * For a given modulus "b" it calulates the value required in "a"
+ */
+static int ICACHE_FLASH_ATTR
+mp_reduce_setup (mp_int * a, mp_int * b)
+{
+  int     res;
+  
+  if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {
+    return res;
+  }
+  return mp_div (a, b, a, NULL);
+}
+
+
+/* reduces x mod m, assumes 0 < x < m**2, mu is 
+ * precomputed via mp_reduce_setup.
+ * From HAC pp.604 Algorithm 14.42
+ */
+static int ICACHE_FLASH_ATTR
+mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
+{
+  mp_int  q;
+  int     res, um = m->used;
+
+  /* q = x */
+  if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
+    return res;
+  }
+
+  /* q1 = x / b**(k-1)  */
+  mp_rshd (&q, um - 1);         
+
+  /* according to HAC this optimization is ok */
+  if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
+    if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  } else {
+#ifdef BN_S_MP_MUL_HIGH_DIGS_C
+    if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+    if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+#else 
+    { 
+#error mp_reduce would always fail
+      res = MP_VAL;
+      goto CLEANUP;
+    }
+#endif
+  }
+
+  /* q3 = q2 / b**(k+1) */
+  mp_rshd (&q, um + 1);         
+
+  /* x = x mod b**(k+1), quick (no division) */
+  if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* q = q * m mod b**(k+1), quick (no division) */
+  if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* x = x - q */
+  if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* If x < 0, add b**(k+1) to it */
+  if (mp_cmp_d (x, 0) == MP_LT) {
+    mp_set (&q, 1);
+    if ((res = mp_lshd (&q, um + 1)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+    if ((res = mp_add (x, &q, x)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  }
+
+  /* Back off if it's too big */
+  while (mp_cmp (x, m) != MP_LT) {
+    if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  }
+  
+CLEANUP:
+  mp_clear (&q);
+
+  return res;
+}
+
+
+/* multiplies |a| * |b| and only computes up to digs digits of result
+ * HAC pp. 595, Algorithm 14.12  Modified so you can control how 
+ * many digits of output are created.
+ */
+static int ICACHE_FLASH_ATTR
+s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  mp_int  t;
+  int     res, pa, pb, ix, iy;
+  mp_digit u;
+  mp_word r;
+  mp_digit tmpx, *tmpt, *tmpy;
+
+  /* can we use the fast multiplier? */
+  if (((digs) < MP_WARRAY) &&
+      MIN (a->used, b->used) < 
+          (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_s_mp_mul_digs (a, b, c, digs);
+  }
+
+  if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
+    return res;
+  }
+  t.used = digs;
+
+  /* compute the digits of the product directly */
+  pa = a->used;
+  for (ix = 0; ix < pa; ix++) {
+    /* set the carry to zero */
+    u = 0;
+
+    /* limit ourselves to making digs digits of output */
+    pb = MIN (b->used, digs - ix);
+
+    /* setup some aliases */
+    /* copy of the digit from a used within the nested loop */
+    tmpx = a->dp[ix];
+    
+    /* an alias for the destination shifted ix places */
+    tmpt = t.dp + ix;
+    
+    /* an alias for the digits of b */
+    tmpy = b->dp;
+
+    /* compute the columns of the output and propagate the carry */
+    for (iy = 0; iy < pb; iy++) {
+      /* compute the column as a mp_word */
+      r       = ((mp_word)*tmpt) +
+                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+                ((mp_word) u);
+
+      /* the new column is the lower part of the result */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* get the carry word from the result */
+      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+    }
+    /* set carry if it is placed below digs */
+    if (ix + iy < digs) {
+      *tmpt = u;
+    }
+  }
+
+  mp_clamp (&t);
+  mp_exch (&t, c);
+
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+/* Fast (comba) multiplier
+ *
+ * This is the fast column-array [comba] multiplier.  It is 
+ * designed to compute the columns of the product first 
+ * then handle the carries afterwards.  This has the effect 
+ * of making the nested loops that compute the columns very
+ * simple and schedulable on super-scalar processors.
+ *
+ * This has been modified to produce a variable number of 
+ * digits of output so if say only a half-product is required 
+ * you don't have to compute the upper half (a feature 
+ * required for fast Barrett reduction).
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ *
+ */
+static int ICACHE_FLASH_ATTR
+fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  int     olduse, res, pa, ix, iz;
+  mp_digit W[MP_WARRAY];
+  register mp_word  _W;
+
+  /* grow the destination as required */
+  if (c->alloc < digs) {
+    if ((res = mp_grow (c, digs)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* number of output digits to produce */
+  pa = MIN(digs, a->used + b->used);
+
+  /* clear the carry */
+  _W = 0;
+  for (ix = 0; ix < pa; ix++) { 
+      int      tx, ty;
+      int      iy;
+      mp_digit *tmpx, *tmpy;
+
+      /* get offsets into the two bignums */
+      ty = MIN(b->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = a->dp + tx;
+      tmpy = b->dp + ty;
+
+      /* this is the number of times the loop will iterrate, essentially 
+         while (tx++ < a->used && ty-- >= 0) { ... }
+       */
+      iy = MIN(a->used-tx, ty+1);
+
+      /* execute loop */
+      for (iz = 0; iz < iy; ++iz) {
+         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+
+      }
+
+      /* store term */
+      W[ix] = ((mp_digit)_W) & MP_MASK;
+
+      /* make next carry */
+      _W = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+  /* setup dest */
+  olduse  = c->used;
+  c->used = pa;
+
+  {
+    register mp_digit *tmpc;
+    tmpc = c->dp;
+    for (ix = 0; ix < pa+1; ix++) {
+      /* now extract the previous digit [below the carry] */
+      *tmpc++ = W[ix];
+    }
+
+    /* clear unused digits [that existed in the old copy of c] */
+    for (; ix < olduse; ix++) {
+      *tmpc++ = 0;
+    }
+  }
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+/* init an mp_init for a given size */
+static int ICACHE_FLASH_ATTR
+mp_init_size (mp_int * a, int size)
+{
+  int x;
+
+  /* pad size so there are always extra digits */
+  size += (MP_PREC * 2) - (size % MP_PREC);    
+  
+  /* alloc mem */
+  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size);
+  if (a->dp == NULL) {
+    return MP_MEM;
+  }
+
+  /* set the members */
+  a->used  = 0;
+  a->alloc = size;
+  a->sign  = MP_ZPOS;
+
+  /* zero the digits */
+  for (x = 0; x < size; x++) {
+      a->dp[x] = 0;
+  }
+
+  return MP_OKAY;
+}
+
+
+/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
+static int ICACHE_FLASH_ATTR
+s_mp_sqr (mp_int * a, mp_int * b)
+{
+  mp_int  t;
+  int     res, ix, iy, pa;
+  mp_word r;
+  mp_digit u, tmpx, *tmpt;
+
+  pa = a->used;
+  if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
+    return res;
+  }
+
+  /* default used is maximum possible size */
+  t.used = 2*pa + 1;
+
+  for (ix = 0; ix < pa; ix++) {
+    /* first calculate the digit at 2*ix */
+    /* calculate double precision result */
+    r = ((mp_word) t.dp[2*ix]) +
+        ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
+
+    /* store lower part in result */
+    t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
+
+    /* get the carry */
+    u           = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+    /* left hand side of A[ix] * A[iy] */
+    tmpx        = a->dp[ix];
+
+    /* alias for where to store the results */
+    tmpt        = t.dp + (2*ix + 1);
+    
+    for (iy = ix + 1; iy < pa; iy++) {
+      /* first calculate the product */
+      r       = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
+
+      /* now calculate the double precision result, note we use
+       * addition instead of *2 since it's easier to optimize
+       */
+      r       = ((mp_word) *tmpt) + r + r + ((mp_word) u);
+
+      /* store lower part */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* get carry */
+      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+    }
+    /* propagate upwards */
+    while (u != ((mp_digit) 0)) {
+      r       = ((mp_word) *tmpt) + ((mp_word) u);
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+    }
+  }
+
+  mp_clamp (&t);
+  mp_exch (&t, b);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+/* multiplies |a| * |b| and does not compute the lower digs digits
+ * [meant to get the higher part of the product]
+ */
+static int ICACHE_FLASH_ATTR
+s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  mp_int  t;
+  int     res, pa, pb, ix, iy;
+  mp_digit u;
+  mp_word r;
+  mp_digit tmpx, *tmpt, *tmpy;
+
+  /* can we use the fast multiplier? */
+#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+  if (((a->used + b->used + 1) < MP_WARRAY)
+      && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_s_mp_mul_high_digs (a, b, c, digs);
+  }
+#endif
+
+  if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
+    return res;
+  }
+  t.used = a->used + b->used + 1;
+
+  pa = a->used;
+  pb = b->used;
+  for (ix = 0; ix < pa; ix++) {
+    /* clear the carry */
+    u = 0;
+
+    /* left hand side of A[ix] * B[iy] */
+    tmpx = a->dp[ix];
+
+    /* alias to the address of where the digits will be stored */
+    tmpt = &(t.dp[digs]);
+
+    /* alias for where to read the right hand side from */
+    tmpy = b->dp + (digs - ix);
+
+    for (iy = digs - ix; iy < pb; iy++) {
+      /* calculate the double precision result */
+      r       = ((mp_word)*tmpt) +
+                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+                ((mp_word) u);
+
+      /* get the lower part */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* carry the carry */
+      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+    }
+    *tmpt = u;
+  }
+  mp_clamp (&t);
+  mp_exch (&t, c);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+#ifdef BN_MP_MONTGOMERY_SETUP_C
+/* setups the montgomery reduction stuff */
+static int ICACHE_FLASH_ATTR
+mp_montgomery_setup (mp_int * n, mp_digit * rho)
+{
+  mp_digit x, b;
+
+/* fast inversion mod 2**k
+ *
+ * Based on the fact that
+ *
+ * XA = 1 (mod 2**n)  =>  (X(2-XA)) A = 1 (mod 2**2n)
+ *                    =>  2*X*A - X*X*A*A = 1
+ *                    =>  2*(1) - (1)     = 1
+ */
+  b = n->dp[0];
+
+  if ((b & 1) == 0) {
+    return MP_VAL;
+  }
+
+  x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
+  x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
+#if !defined(MP_8BIT)
+  x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
+#endif
+#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
+  x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
+#endif
+#ifdef MP_64BIT
+  x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
+#endif
+
+  /* rho = -1/m mod b */
+  *rho = (unsigned long)(((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK;
+
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+/* computes xR**-1 == x (mod N) via Montgomery Reduction
+ *
+ * This is an optimized implementation of montgomery_reduce
+ * which uses the comba method to quickly calculate the columns of the
+ * reduction.
+ *
+ * Based on Algorithm 14.32 on pp.601 of HAC.
+*/
+int ICACHE_FLASH_ATTR
+fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+  int     ix, res, olduse;
+  mp_word W[MP_WARRAY];
+
+  /* get old used count */
+  olduse = x->used;
+
+  /* grow a as required */
+  if (x->alloc < n->used + 1) {
+    if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* first we have to get the digits of the input into
+   * an array of double precision words W[...]
+   */
+  {
+    register mp_word *_W;
+    register mp_digit *tmpx;
+
+    /* alias for the W[] array */
+    _W   = W;
+
+    /* alias for the digits of  x*/
+    tmpx = x->dp;
+
+    /* copy the digits of a into W[0..a->used-1] */
+    for (ix = 0; ix < x->used; ix++) {
+      *_W++ = *tmpx++;
+    }
+
+    /* zero the high words of W[a->used..m->used*2] */
+    for (; ix < n->used * 2 + 1; ix++) {
+      *_W++ = 0;
+    }
+  }
+
+  /* now we proceed to zero successive digits
+   * from the least significant upwards
+   */
+  for (ix = 0; ix < n->used; ix++) {
+    /* mu = ai * m' mod b
+     *
+     * We avoid a double precision multiplication (which isn't required)
+     * by casting the value down to a mp_digit.  Note this requires
+     * that W[ix-1] have  the carry cleared (see after the inner loop)
+     */
+    register mp_digit mu;
+    mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
+
+    /* a = a + mu * m * b**i
+     *
+     * This is computed in place and on the fly.  The multiplication
+     * by b**i is handled by offseting which columns the results
+     * are added to.
+     *
+     * Note the comba method normally doesn't handle carries in the
+     * inner loop In this case we fix the carry from the previous
+     * column since the Montgomery reduction requires digits of the
+     * result (so far) [see above] to work.  This is
+     * handled by fixing up one carry after the inner loop.  The
+     * carry fixups are done in order so after these loops the
+     * first m->used words of W[] have the carries fixed
+     */
+    {
+      register int iy;
+      register mp_digit *tmpn;
+      register mp_word *_W;
+
+      /* alias for the digits of the modulus */
+      tmpn = n->dp;
+
+      /* Alias for the columns set by an offset of ix */
+      _W = W + ix;
+
+      /* inner loop */
+      for (iy = 0; iy < n->used; iy++) {
+          *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
+      }
+    }
+
+    /* now fix carry for next digit, W[ix+1] */
+    W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
+  }
+
+  /* now we have to propagate the carries and
+   * shift the words downward [all those least
+   * significant digits we zeroed].
+   */
+  {
+    register mp_digit *tmpx;
+    register mp_word *_W, *_W1;
+
+    /* nox fix rest of carries */
+
+    /* alias for current word */
+    _W1 = W + ix;
+
+    /* alias for next word, where the carry goes */
+    _W = W + ++ix;
+
+    for (; ix <= n->used * 2 + 1; ix++) {
+      *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
+    }
+
+    /* copy out, A = A/b**n
+     *
+     * The result is A/b**n but instead of converting from an
+     * array of mp_word to mp_digit than calling mp_rshd
+     * we just copy them in the right order
+     */
+
+    /* alias for destination word */
+    tmpx = x->dp;
+
+    /* alias for shifted double precision result */
+    _W = W + n->used;
+
+    for (ix = 0; ix < n->used + 1; ix++) {
+      *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
+    }
+
+    /* zero oldused digits, if the input a was larger than
+     * m->used+1 we'll have to clear the digits
+     */
+    for (; ix < olduse; ix++) {
+      *tmpx++ = 0;
+    }
+  }
+
+  /* set the max used and clamp */
+  x->used = n->used + 1;
+  mp_clamp (x);
+
+  /* if A >= m then A = A - m */
+  if (mp_cmp_mag (x, n) != MP_LT) {
+    return s_mp_sub (x, n, x);
+  }
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_MP_MUL_2_C
+/* b = a*2 */
+static int ICACHE_FLASH_ATTR
+mp_mul_2(mp_int * a, mp_int * b)
+{
+  int     x, res, oldused;
+
+  /* grow to accommodate result */
+  if (b->alloc < a->used + 1) {
+    if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  oldused = b->used;
+  b->used = a->used;
+
+  {
+    register mp_digit r, rr, *tmpa, *tmpb;
+
+    /* alias for source */
+    tmpa = a->dp;
+    
+    /* alias for dest */
+    tmpb = b->dp;
+
+    /* carry */
+    r = 0;
+    for (x = 0; x < a->used; x++) {
+    
+      /* get what will be the *next* carry bit from the 
+       * MSB of the current digit 
+       */
+      rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
+      
+      /* now shift up this digit, add in the carry [from the previous] */
+      *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
+      
+      /* copy the carry that would be from the source 
+       * digit into the next iteration 
+       */
+      r = rr;
+    }
+
+    /* new leading digit? */
+    if (r != 0) {
+      /* add a MSB which is always 1 at this point */
+      *tmpb = 1;
+      ++(b->used);
+    }
+
+    /* now zero any excess digits on the destination 
+     * that we didn't write to 
+     */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+/*
+ * shifts with subtractions when the result is greater than b.
+ *
+ * The method is slightly modified to shift B unconditionally up to just under
+ * the leading bit of b.  This saves a lot of multiple precision shifting.
+ */
+static int ICACHE_FLASH_ATTR
+mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
+{
+  int     x, bits, res;
+
+  /* how many bits of last digit does b use */
+  bits = mp_count_bits (b) % DIGIT_BIT;
+
+  if (b->used > 1) {
+     if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
+        return res;
+     }
+  } else {
+     mp_set(a, 1);
+     bits = 1;
+  }
+
+
+  /* now compute C = A * B mod b */
+  for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
+    if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
+      return res;
+    }
+    if (mp_cmp_mag (a, b) != MP_LT) {
+      if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
+        return res;
+      }
+    }
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_MP_EXPTMOD_FAST_C
+/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
+ *
+ * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.
+ * The value of k changes based on the size of the exponent.
+ *
+ * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
+ */
+
+static int ICACHE_FLASH_ATTR
+mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+  mp_int  M[TAB_SIZE], res;
+  mp_digit buf, mp;
+  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+
+  /* use a pointer to the reduction algorithm.  This allows us to use
+   * one of many reduction algorithms without modding the guts of
+   * the code with if statements everywhere.
+   */
+  int     (*redux)(mp_int*,mp_int*,mp_digit);
+
+  /* find window size */
+  x = mp_count_bits (X);
+  if (x <= 7) {
+    winsize = 2;
+  } else if (x <= 36) {
+    winsize = 3;
+  } else if (x <= 140) {
+    winsize = 4;
+  } else if (x <= 450) {
+    winsize = 5;
+  } else if (x <= 1303) {
+    winsize = 6;
+  } else if (x <= 3529) {
+    winsize = 7;
+  } else {
+    winsize = 8;
+  }
+
+#ifdef MP_LOW_MEM
+  if (winsize > 5) {
+     winsize = 5;
+  }
+#endif
+
+  /* init M array */
+  /* init first cell */
+  if ((err = mp_init(&M[1])) != MP_OKAY) {
+     return err;
+  }
+
+  /* now init the second half of the array */
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    if ((err = mp_init(&M[x])) != MP_OKAY) {
+      for (y = 1<<(winsize-1); y < x; y++) {
+        mp_clear (&M[y]);
+      }
+      mp_clear(&M[1]);
+      return err;
+    }
+  }
+
+  /* determine and setup reduction code */
+  if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_SETUP_C     
+     /* now setup montgomery  */
+     if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
+        goto LBL_M;
+     }
+#else
+     err = MP_VAL;
+     goto LBL_M;
+#endif
+
+     /* automatically pick the comba one if available (saves quite a few calls/ifs) */
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+     if (((P->used * 2 + 1) < MP_WARRAY) &&
+          P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+        redux = fast_mp_montgomery_reduce;
+     } else 
+#endif
+     {
+#ifdef BN_MP_MONTGOMERY_REDUCE_C
+        /* use slower baseline Montgomery method */
+        redux = mp_montgomery_reduce;
+#else
+        err = MP_VAL;
+        goto LBL_M;
+#endif
+     }
+  } else if (redmode == 1) {
+#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
+     /* setup DR reduction for moduli of the form B**k - b */
+     mp_dr_setup(P, &mp);
+     redux = mp_dr_reduce;
+#else
+     err = MP_VAL;
+     goto LBL_M;
+#endif
+  } else {
+#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
+     /* setup DR reduction for moduli of the form 2**k - b */
+     if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
+        goto LBL_M;
+     }
+     redux = mp_reduce_2k;
+#else
+     err = MP_VAL;
+     goto LBL_M;
+#endif
+  }
+
+  /* setup result */
+  if ((err = mp_init (&res)) != MP_OKAY) {
+    goto LBL_M;
+  }
+
+  /* create M table
+   *
+
+   *
+   * The first half of the table is not computed though accept for M[0] and M[1]
+   */
+
+  if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+     /* now we need R mod m */
+     if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
+       goto LBL_RES;
+     }
+#else 
+     err = MP_VAL;
+     goto LBL_RES;
+#endif
+
+     /* now set M[1] to G * R mod m */
+     if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
+       goto LBL_RES;
+     }
+  } else {
+     mp_set(&res, 1);
+     if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
+        goto LBL_RES;
+     }
+  }
+
+  /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
+  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+    goto LBL_RES;
+  }
+
+  for (x = 0; x < (winsize - 1); x++) {
+    if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) {
+      goto LBL_RES;
+    }
+    if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {
+      goto LBL_RES;
+    }
+  }
+
+  /* create upper table */
+  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+      goto LBL_RES;
+    }
+    if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
+      goto LBL_RES;
+    }
+  }
+
+  /* set initial mode and bit cnt */
+  mode   = 0;
+  bitcnt = 1;
+  buf    = 0;
+  digidx = X->used - 1;
+  bitcpy = 0;
+  bitbuf = 0;
+
+  for (;;) {
+    /* grab next digit as required */
+    if (--bitcnt == 0) {
+      /* if digidx == -1 we are out of digits so break */
+      if (digidx == -1) {
+        break;
+      }
+      /* read next digit and reset bitcnt */
+      buf    = X->dp[digidx--];
+      bitcnt = (int)DIGIT_BIT;
+    }
+
+    /* grab the next msb from the exponent */
+    y     = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
+    buf <<= (mp_digit)1;
+
+    /* if the bit is zero and mode == 0 then we ignore it
+     * These represent the leading zero bits before the first 1 bit
+     * in the exponent.  Technically this opt is not required but it
+     * does lower the # of trivial squaring/reductions used
+     */
+    if (mode == 0 && y == 0) {
+      continue;
+    }
+
+    /* if the bit is zero and mode == 1 then we square */
+    if (mode == 1 && y == 0) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      continue;
+    }
+
+    /* else we add it to the window */
+    bitbuf |= (y << (winsize - ++bitcpy));
+    mode    = 2;
+
+    if (bitcpy == winsize) {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < winsize; x++) {
+        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, mp)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+
+      /* then multiply */
+      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+      mode   = 1;
+    }
+  }
+
+  /* if bits remain then square/multiply */
+  if (mode == 2 && bitcpy > 0) {
+    /* square then multiply if the bit is set */
+    for (x = 0; x < bitcpy; x++) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* get next bit of the window */
+      bitbuf <<= 1;
+      if ((bitbuf & (1 << winsize)) != 0) {
+        /* then multiply */
+        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, mp)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+    }
+  }
+
+  if (redmode == 0) {
+     /* fixup result if Montgomery reduction is used
+      * recall that any value in a Montgomery system is
+      * actually multiplied by R mod n.  So we have
+      * to reduce one more time to cancel out the factor
+      * of R.
+      */
+     if ((err = redux(&res, P, mp)) != MP_OKAY) {
+       goto LBL_RES;
+     }
+  }
+
+  /* swap res with Y */
+  mp_exch (&res, Y);
+  err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_M:
+  mp_clear(&M[1]);
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    mp_clear (&M[x]);
+  }
+  return err;
+}
+#endif
+
+
+#ifdef BN_FAST_S_MP_SQR_C
+/* the jist of squaring...
+ * you do like mult except the offset of the tmpx [one that 
+ * starts closer to zero] can't equal the offset of tmpy.  
+ * So basically you set up iy like before then you min it with
+ * (ty-tx) so that it never happens.  You double all those 
+ * you add in the inner loop
+
+After that loop you do the squares and add them in.
+*/
+
+static int ICACHE_FLASH_ATTR
+fast_s_mp_sqr (mp_int * a, mp_int * b)
+{
+  int       olduse, res, pa, ix, iz;
+  mp_digit   W[MP_WARRAY], *tmpx;
+  mp_word   W1;
+
+  /* grow the destination as required */
+  pa = a->used + a->used;
+  if (b->alloc < pa) {
+    if ((res = mp_grow (b, pa)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* number of output digits to produce */
+  W1 = 0;
+  for (ix = 0; ix < pa; ix++) { 
+      int      tx, ty, iy;
+      mp_word  _W;
+      mp_digit *tmpy;
+
+      /* clear counter */
+      _W = 0;
+
+      /* get offsets into the two bignums */
+      ty = MIN(a->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = a->dp + tx;
+      tmpy = a->dp + ty;
+
+      /* this is the number of times the loop will iterrate, essentially
+         while (tx++ < a->used && ty-- >= 0) { ... }
+       */
+      iy = MIN(a->used-tx, ty+1);
+
+      /* now for squaring tx can never equal ty 
+       * we halve the distance since they approach at a rate of 2x
+       * and we have to round because odd cases need to be executed
+       */
+      iy = MIN(iy, (ty-tx+1)>>1);
+
+      /* execute loop */
+      for (iz = 0; iz < iy; iz++) {
+         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+      }
+
+      /* double the inner product and add carry */
+      _W = _W + _W + W1;
+
+      /* even columns have the square term in them */
+      if ((ix&1) == 0) {
+         _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
+      }
+
+      /* store it */
+      W[ix] = (mp_digit)(_W & MP_MASK);
+
+      /* make next carry */
+      W1 = _W >> ((mp_word)DIGIT_BIT);
+  }
+
+  /* setup dest */
+  olduse  = b->used;
+  b->used = a->used+a->used;
+
+  {
+    mp_digit *tmpb;
+    tmpb = b->dp;
+    for (ix = 0; ix < pa; ix++) {
+      *tmpb++ = W[ix] & MP_MASK;
+    }
+
+    /* clear unused digits [that existed in the old copy of c] */
+    for (; ix < olduse; ix++) {
+      *tmpb++ = 0;
+    }
+  }
+  mp_clamp (b);
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_MP_MUL_D_C
+/* multiply by a digit */
+static int ICACHE_FLASH_ATTR
+mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  mp_digit u, *tmpa, *tmpc;
+  mp_word  r;
+  int      ix, res, olduse;
+
+  /* make sure c is big enough to hold a*b */
+  if (c->alloc < a->used + 1) {
+    if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* get the original destinations used count */
+  olduse = c->used;
+
+  /* set the sign */
+  c->sign = a->sign;
+
+  /* alias for a->dp [source] */
+  tmpa = a->dp;
+
+  /* alias for c->dp [dest] */
+  tmpc = c->dp;
+
+  /* zero carry */
+  u = 0;
+
+  /* compute columns */
+  for (ix = 0; ix < a->used; ix++) {
+    /* compute product and carry sum for this term */
+    r       = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
+
+    /* mask off higher bits to get a single digit */
+    *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+    /* send carry into next iteration */
+    u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+  }
+
+  /* store final carry [if any] and increment ix offset  */
+  *tmpc++ = u;
+  ++ix;
+
+  /* now zero digits above the top */
+  while (ix++ < olduse) {
+     *tmpc++ = 0;
+  }
+
+  /* set used count */
+  c->used = a->used + 1;
+  mp_clamp(c);
+
+  return MP_OKAY;
+}
+#endif
diff --git a/components/wpa_supplicant/include/wpa2/tls/pkcs1.h b/components/wpa_supplicant/include/wpa2/tls/pkcs1.h
new file mode 100644 (file)
index 0000000..ed64def
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * PKCS #1 (RSA Encryption)
+ * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef PKCS1_H
+#define PKCS1_H
+
+int pkcs1_encrypt(int block_type, struct crypto_rsa_key *key,
+                 int use_private, const u8 *in, size_t inlen,
+                 u8 *out, size_t *outlen);
+int pkcs1_v15_private_key_decrypt(struct crypto_rsa_key *key,
+                                 const u8 *in, size_t inlen,
+                                 u8 *out, size_t *outlen);
+int pkcs1_decrypt_public_key(struct crypto_rsa_key *key,
+                            const u8 *crypt, size_t crypt_len,
+                            u8 *plain, size_t *plain_len);
+
+#endif /* PKCS1_H */
diff --git a/components/wpa_supplicant/include/wpa2/tls/pkcs5.h b/components/wpa_supplicant/include/wpa2/tls/pkcs5.h
new file mode 100644 (file)
index 0000000..20ddadc
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * PKCS #5 (Password-based Encryption)
+ * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef PKCS5_H
+#define PKCS5_H
+
+u8 * pkcs5_decrypt(const u8 *enc_alg, size_t enc_alg_len,
+                  const u8 *enc_data, size_t enc_data_len,
+                  const char *passwd, size_t *data_len);
+
+#endif /* PKCS5_H */
diff --git a/components/wpa_supplicant/include/wpa2/tls/pkcs8.h b/components/wpa_supplicant/include/wpa2/tls/pkcs8.h
new file mode 100644 (file)
index 0000000..bebf840
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * PKCS #8 (Private-key information syntax)
+ * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef PKCS8_H
+#define PKCS8_H
+
+struct crypto_private_key * pkcs8_key_import(const u8 *buf, size_t len);
+struct crypto_private_key *
+pkcs8_enc_key_import(const u8 *buf, size_t len, const char *passwd);
+
+#endif /* PKCS8_H */
diff --git a/components/wpa_supplicant/include/wpa2/tls/rsa.h b/components/wpa_supplicant/include/wpa2/tls/rsa.h
new file mode 100644 (file)
index 0000000..c236a9d
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * RSA
+ * Copyright (c) 2006, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef RSA_H
+#define RSA_H
+
+struct crypto_rsa_key;
+
+struct crypto_rsa_key *
+crypto_rsa_import_public_key(const u8 *buf, size_t len);
+struct crypto_rsa_key *
+crypto_rsa_import_private_key(const u8 *buf, size_t len);
+size_t crypto_rsa_get_modulus_len(struct crypto_rsa_key *key);
+int crypto_rsa_exptmod(const u8 *in, size_t inlen, u8 *out, size_t *outlen,
+                      struct crypto_rsa_key *key, int use_private);
+void crypto_rsa_free(struct crypto_rsa_key *key);
+
+#endif /* RSA_H */
diff --git a/components/wpa_supplicant/include/wpa2/tls/tls.h b/components/wpa_supplicant/include/wpa2/tls/tls.h
new file mode 100644 (file)
index 0000000..983999b
--- /dev/null
@@ -0,0 +1,537 @@
+/*
+ * SSL/TLS interface definition
+ * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef TLS_H
+#define TLS_H
+
+struct tls_connection;
+
+struct tls_keys {
+       const u8 *master_key; /* TLS master secret */
+       size_t master_key_len;
+       const u8 *client_random;
+       size_t client_random_len;
+       const u8 *server_random;
+       size_t server_random_len;
+};
+
+enum tls_event {
+       TLS_CERT_CHAIN_SUCCESS,
+       TLS_CERT_CHAIN_FAILURE,
+       TLS_PEER_CERTIFICATE,
+       TLS_ALERT
+};
+
+/*
+ * Note: These are used as identifier with external programs and as such, the
+ * values must not be changed.
+ */
+enum tls_fail_reason {
+       TLS_FAIL_UNSPECIFIED = 0,
+       TLS_FAIL_UNTRUSTED = 1,
+       TLS_FAIL_REVOKED = 2,
+       TLS_FAIL_NOT_YET_VALID = 3,
+       TLS_FAIL_EXPIRED = 4,
+       TLS_FAIL_SUBJECT_MISMATCH = 5,
+       TLS_FAIL_ALTSUBJECT_MISMATCH = 6,
+       TLS_FAIL_BAD_CERTIFICATE = 7,
+       TLS_FAIL_SERVER_CHAIN_PROBE = 8
+};
+
+union tls_event_data {
+       struct {
+               int depth;
+               const char *subject;
+               enum tls_fail_reason reason;
+               const char *reason_txt;
+               const struct wpabuf *cert;
+       } cert_fail;
+
+       struct {
+               int depth;
+               const char *subject;
+               const struct wpabuf *cert;
+               const u8 *hash;
+               size_t hash_len;
+       } peer_cert;
+
+       struct {
+               int is_local;
+               const char *type;
+               const char *description;
+       } alert;
+};
+
+struct tls_config {
+       const char *opensc_engine_path;
+       const char *pkcs11_engine_path;
+       const char *pkcs11_module_path;
+       int fips_mode;
+       int cert_in_cb;
+
+       void (*event_cb)(void *ctx, enum tls_event ev,
+                        union tls_event_data *data);
+       void *cb_ctx;
+};
+
+#define TLS_CONN_ALLOW_SIGN_RSA_MD5 BIT(0)
+#define TLS_CONN_DISABLE_TIME_CHECKS BIT(1)
+#define TLS_CONN_DISABLE_SESSION_TICKET BIT(2)
+#define TLS_CONN_REQUEST_OCSP BIT(3)
+#define TLS_CONN_REQUIRE_OCSP BIT(4)
+
+/**
+ * struct tls_connection_params - Parameters for TLS connection
+ * @ca_cert: File or reference name for CA X.509 certificate in PEM or DER
+ * format
+ * @ca_cert_blob: ca_cert as inlined data or %NULL if not used
+ * @ca_cert_blob_len: ca_cert_blob length
+ * @ca_path: Path to CA certificates (OpenSSL specific)
+ * @subject_match: String to match in the subject of the peer certificate or
+ * %NULL to allow all subjects
+ * @altsubject_match: String to match in the alternative subject of the peer
+ * certificate or %NULL to allow all alternative subjects
+ * @client_cert: File or reference name for client X.509 certificate in PEM or
+ * DER format
+ * @client_cert_blob: client_cert as inlined data or %NULL if not used
+ * @client_cert_blob_len: client_cert_blob length
+ * @private_key: File or reference name for client private key in PEM or DER
+ * format (traditional format (RSA PRIVATE KEY) or PKCS#8 (PRIVATE KEY)
+ * @private_key_blob: private_key as inlined data or %NULL if not used
+ * @private_key_blob_len: private_key_blob length
+ * @private_key_passwd: Passphrase for decrypted private key, %NULL if no
+ * passphrase is used.
+ * @dh_file: File name for DH/DSA data in PEM format, or %NULL if not used
+ * @dh_blob: dh_file as inlined data or %NULL if not used
+ * @dh_blob_len: dh_blob length
+ * @engine: 1 = use engine (e.g., a smartcard) for private key operations
+ * (this is OpenSSL specific for now)
+ * @engine_id: engine id string (this is OpenSSL specific for now)
+ * @ppin: pointer to the pin variable in the configuration
+ * (this is OpenSSL specific for now)
+ * @key_id: the private key's id when using engine (this is OpenSSL
+ * specific for now)
+ * @cert_id: the certificate's id when using engine
+ * @ca_cert_id: the CA certificate's id when using engine
+ * @flags: Parameter options (TLS_CONN_*)
+ * @ocsp_stapling_response: DER encoded file with cached OCSP stapling response
+ *     or %NULL if OCSP is not enabled
+ *
+ * TLS connection parameters to be configured with tls_connection_set_params()
+ * and tls_global_set_params().
+ *
+ * Certificates and private key can be configured either as a reference name
+ * (file path or reference to certificate store) or by providing the same data
+ * as a pointer to the data in memory. Only one option will be used for each
+ * field.
+ */
+struct tls_connection_params {
+       const char *ca_cert;
+       const u8 *ca_cert_blob;
+       size_t ca_cert_blob_len;
+       const char *ca_path;
+       const char *subject_match;
+       const char *altsubject_match;
+       const char *client_cert;
+       const u8 *client_cert_blob;
+       size_t client_cert_blob_len;
+       const char *private_key;
+       const u8 *private_key_blob;
+       size_t private_key_blob_len;
+       const char *private_key_passwd;
+       const char *dh_file;
+       const u8 *dh_blob;
+       size_t dh_blob_len;
+
+       /* OpenSSL specific variables */
+       int engine;
+       const char *engine_id;
+       const char *pin;
+       const char *key_id;
+       const char *cert_id;
+       const char *ca_cert_id;
+
+       unsigned int flags;
+       const char *ocsp_stapling_response;
+};
+
+
+/**
+ * tls_init - Initialize TLS library
+ * @conf: Configuration data for TLS library
+ * Returns: Context data to be used as tls_ctx in calls to other functions,
+ * or %NULL on failure.
+ *
+ * Called once during program startup and once for each RSN pre-authentication
+ * session. In other words, there can be two concurrent TLS contexts. If global
+ * library initialization is needed (i.e., one that is shared between both
+ * authentication types), the TLS library wrapper should maintain a reference
+ * counter and do global initialization only when moving from 0 to 1 reference.
+ */
+void * tls_init(void);
+
+/**
+ * tls_deinit - Deinitialize TLS library
+ * @tls_ctx: TLS context data from tls_init()
+ *
+ * Called once during program shutdown and once for each RSN pre-authentication
+ * session. If global library deinitialization is needed (i.e., one that is
+ * shared between both authentication types), the TLS library wrapper should
+ * maintain a reference counter and do global deinitialization only when moving
+ * from 1 to 0 references.
+ */
+void tls_deinit(void *tls_ctx);
+
+/**
+ * tls_get_errors - Process pending errors
+ * @tls_ctx: TLS context data from tls_init()
+ * Returns: Number of found error, 0 if no errors detected.
+ *
+ * Process all pending TLS errors.
+ */
+int tls_get_errors(void *tls_ctx);
+
+/**
+ * tls_connection_init - Initialize a new TLS connection
+ * @tls_ctx: TLS context data from tls_init()
+ * Returns: Connection context data, conn for other function calls
+ */
+struct tls_connection * tls_connection_init(void *tls_ctx);
+
+/**
+ * tls_connection_deinit - Free TLS connection data
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ *
+ * Release all resources allocated for TLS connection.
+ */
+void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn);
+
+/**
+ * tls_connection_established - Has the TLS connection been completed?
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * Returns: 1 if TLS connection has been completed, 0 if not.
+ */
+int tls_connection_established(void *tls_ctx, struct tls_connection *conn);
+
+/**
+ * tls_connection_shutdown - Shutdown TLS connection
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * Returns: 0 on success, -1 on failure
+ *
+ * Shutdown current TLS connection without releasing all resources. New
+ * connection can be started by using the same conn without having to call
+ * tls_connection_init() or setting certificates etc. again. The new
+ * connection should try to use session resumption.
+ */
+int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn);
+
+enum {
+       TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED = -3,
+       TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED = -2
+};
+
+/**
+ * tls_connection_set_params - Set TLS connection parameters
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * @params: Connection parameters
+ * Returns: 0 on success, -1 on failure,
+ * TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED (-2) on possible PIN error causing
+ * PKCS#11 engine failure, or
+ * TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED (-3) on failure to verify the
+ * PKCS#11 engine private key.
+ */
+int __must_check
+tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
+                         const struct tls_connection_params *params);
+
+/**
+ * tls_global_set_params - Set TLS parameters for all TLS connection
+ * @tls_ctx: TLS context data from tls_init()
+ * @params: Global TLS parameters
+ * Returns: 0 on success, -1 on failure,
+ * TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED (-2) on possible PIN error causing
+ * PKCS#11 engine failure, or
+ * TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED (-3) on failure to verify the
+ * PKCS#11 engine private key.
+ */
+int __must_check tls_global_set_params(
+       void *tls_ctx, const struct tls_connection_params *params);
+
+/**
+ * tls_global_set_verify - Set global certificate verification options
+ * @tls_ctx: TLS context data from tls_init()
+ * @check_crl: 0 = do not verify CRLs, 1 = verify CRL for the user certificate,
+ * 2 = verify CRL for all certificates
+ * Returns: 0 on success, -1 on failure
+ */
+int __must_check tls_global_set_verify(void *tls_ctx, int check_crl);
+
+/**
+ * tls_connection_set_verify - Set certificate verification options
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * @verify_peer: 1 = verify peer certificate
+ * Returns: 0 on success, -1 on failure
+ */
+int __must_check tls_connection_set_verify(void *tls_ctx,
+                                          struct tls_connection *conn,
+                                          int verify_peer);
+
+/**
+ * tls_connection_get_keys - Get master key and random data from TLS connection
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * @keys: Structure of key/random data (filled on success)
+ * Returns: 0 on success, -1 on failure
+ */
+int __must_check tls_connection_get_keys(void *tls_ctx,
+                                        struct tls_connection *conn,
+                                        struct tls_keys *keys);
+
+/**
+ * tls_connection_prf - Use TLS-PRF to derive keying material
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * @label: Label (e.g., description of the key) for PRF
+ * @server_random_first: seed is 0 = client_random|server_random,
+ * 1 = server_random|client_random
+ * @out: Buffer for output data from TLS-PRF
+ * @out_len: Length of the output buffer
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is optional to implement if tls_connection_get_keys() provides
+ * access to master secret and server/client random values. If these values are
+ * not exported from the TLS library, tls_connection_prf() is required so that
+ * further keying material can be derived from the master secret. If not
+ * implemented, the function will still need to be defined, but it can just
+ * return -1. Example implementation of this function is in tls_prf_sha1_md5()
+ * when it is called with seed set to client_random|server_random (or
+ * server_random|client_random).
+ */
+int __must_check  tls_connection_prf(void *tls_ctx,
+                                    struct tls_connection *conn,
+                                    const char *label,
+                                    int server_random_first,
+                                    u8 *out, size_t out_len);
+
+/**
+ * tls_connection_handshake - Process TLS handshake (client side)
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * @in_data: Input data from TLS server
+ * @appl_data: Pointer to application data pointer, or %NULL if dropped
+ * Returns: Output data, %NULL on failure
+ *
+ * The caller is responsible for freeing the returned output data. If the final
+ * handshake message includes application data, this is decrypted and
+ * appl_data (if not %NULL) is set to point this data. The caller is
+ * responsible for freeing appl_data.
+ *
+ * This function is used during TLS handshake. The first call is done with
+ * in_data == %NULL and the library is expected to return ClientHello packet.
+ * This packet is then send to the server and a response from server is given
+ * to TLS library by calling this function again with in_data pointing to the
+ * TLS message from the server.
+ *
+ * If the TLS handshake fails, this function may return %NULL. However, if the
+ * TLS library has a TLS alert to send out, that should be returned as the
+ * output data. In this case, tls_connection_get_failed() must return failure
+ * (> 0).
+ *
+ * tls_connection_established() should return 1 once the TLS handshake has been
+ * completed successfully.
+ */
+struct wpabuf * tls_connection_handshake(void *tls_ctx,
+                                        struct tls_connection *conn,
+                                        const struct wpabuf *in_data,
+                                        struct wpabuf **appl_data);
+
+struct wpabuf * tls_connection_handshake2(void *tls_ctx,
+                                         struct tls_connection *conn,
+                                         const struct wpabuf *in_data,
+                                         struct wpabuf **appl_data,
+                                         int *more_data_needed);
+
+/**
+ * tls_connection_server_handshake - Process TLS handshake (server side)
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * @in_data: Input data from TLS peer
+ * @appl_data: Pointer to application data pointer, or %NULL if dropped
+ * Returns: Output data, %NULL on failure
+ *
+ * The caller is responsible for freeing the returned output data.
+ */
+struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
+                                               struct tls_connection *conn,
+                                               const struct wpabuf *in_data,
+                                               struct wpabuf **appl_data);
+
+/**
+ * tls_connection_encrypt - Encrypt data into TLS tunnel
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * @in_data: Plaintext data to be encrypted
+ * Returns: Encrypted TLS data or %NULL on failure
+ *
+ * This function is used after TLS handshake has been completed successfully to
+ * send data in the encrypted tunnel. The caller is responsible for freeing the
+ * returned output data.
+ */
+struct wpabuf * tls_connection_encrypt(void *tls_ctx,
+                                      struct tls_connection *conn,
+                                      const struct wpabuf *in_data);
+
+/**
+ * tls_connection_decrypt - Decrypt data from TLS tunnel
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * @in_data: Encrypted TLS data
+ * Returns: Decrypted TLS data or %NULL on failure
+ *
+ * This function is used after TLS handshake has been completed successfully to
+ * receive data from the encrypted tunnel. The caller is responsible for
+ * freeing the returned output data.
+ */
+struct wpabuf * tls_connection_decrypt(void *tls_ctx,
+                                      struct tls_connection *conn,
+                                      const struct wpabuf *in_data);
+
+struct wpabuf * tls_connection_decrypt2(void *tls_ctx,
+                                       struct tls_connection *conn,
+                                       const struct wpabuf *in_data,
+                                       int *more_data_needed);
+
+/**
+ * tls_connection_resumed - Was session resumption used
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * Returns: 1 if current session used session resumption, 0 if not
+ */
+int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn);
+
+enum {
+       TLS_CIPHER_NONE,
+       TLS_CIPHER_RC4_SHA /* 0x0005 */,
+       TLS_CIPHER_AES128_SHA /* 0x002f */,
+       TLS_CIPHER_RSA_DHE_AES128_SHA /* 0x0031 */,
+       TLS_CIPHER_ANON_DH_AES128_SHA /* 0x0034 */
+};
+
+/**
+ * tls_connection_set_cipher_list - Configure acceptable cipher suites
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers
+ * (TLS_CIPHER_*).
+ * Returns: 0 on success, -1 on failure
+ */
+int __must_check tls_connection_set_cipher_list(void *tls_ctx,
+                                               struct tls_connection *conn,
+                                               u8 *ciphers);
+
+/**
+ * tls_get_cipher - Get current cipher name
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * @buf: Buffer for the cipher name
+ * @buflen: buf size
+ * Returns: 0 on success, -1 on failure
+ *
+ * Get the name of the currently used cipher.
+ */
+int __must_check tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
+                               char *buf, size_t buflen);
+
+/**
+ * tls_connection_enable_workaround - Enable TLS workaround options
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is used to enable connection-specific workaround options for
+ * buffer SSL/TLS implementations.
+ */
+int __must_check tls_connection_enable_workaround(void *tls_ctx,
+                                                 struct tls_connection *conn);
+
+/**
+ * tls_connection_client_hello_ext - Set TLS extension for ClientHello
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * @ext_type: Extension type
+ * @data: Extension payload (%NULL to remove extension)
+ * @data_len: Extension payload length
+ * Returns: 0 on success, -1 on failure
+ */
+int __must_check tls_connection_client_hello_ext(void *tls_ctx,
+                                                struct tls_connection *conn,
+                                                int ext_type, const u8 *data,
+                                                size_t data_len);
+
+/**
+ * tls_connection_get_failed - Get connection failure status
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ *
+ * Returns >0 if connection has failed, 0 if not.
+ */
+int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn);
+
+/**
+ * tls_connection_get_read_alerts - Get connection read alert status
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * Returns: Number of times a fatal read (remote end reported error) has
+ * happened during this connection.
+ */
+int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn);
+
+/**
+ * tls_connection_get_write_alerts - Get connection write alert status
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * Returns: Number of times a fatal write (locally detected error) has happened
+ * during this connection.
+ */
+int tls_connection_get_write_alerts(void *tls_ctx,
+                                   struct tls_connection *conn);
+
+/**
+ * tls_connection_get_keyblock_size - Get TLS key_block size
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * Returns: Size of the key_block for the negotiated cipher suite or -1 on
+ * failure
+ */
+int tls_connection_get_keyblock_size(void *tls_ctx,
+                                    struct tls_connection *conn);
+
+/**
+ * tls_capabilities - Get supported TLS capabilities
+ * @tls_ctx: TLS context data from tls_init()
+ * Returns: Bit field of supported TLS capabilities (TLS_CAPABILITY_*)
+ */
+unsigned int tls_capabilities(void *tls_ctx);
+
+typedef int (*tls_session_ticket_cb)
+(void *ctx, const u8 *ticket, size_t len, const u8 *client_random,
+ const u8 *server_random, u8 *master_secret);
+
+int __must_check  tls_connection_set_session_ticket_cb(
+       void *tls_ctx, struct tls_connection *conn,
+       tls_session_ticket_cb cb, void *ctx);
+
+int tls_prf_sha1_md5(const u8 *secret, size_t secret_len, const char *label,
+             const u8 *seed, size_t seed_len, u8 *out, size_t outlen);
+
+#endif /* TLS_H */
diff --git a/components/wpa_supplicant/include/wpa2/tls/tlsv1_client.h b/components/wpa_supplicant/include/wpa2/tls/tlsv1_client.h
new file mode 100644 (file)
index 0000000..8ec85f1
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * TLS v1.0/v1.1/v1.2 client (RFC 2246, RFC 4346, RFC 5246)
+ * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef TLSV1_CLIENT_H
+#define TLSV1_CLIENT_H
+
+#include "tlsv1_cred.h"
+
+struct tlsv1_client;
+
+int tlsv1_client_global_init(void);
+void tlsv1_client_global_deinit(void);
+struct tlsv1_client * tlsv1_client_init(void);
+void tlsv1_client_deinit(struct tlsv1_client *conn);
+int tlsv1_client_established(struct tlsv1_client *conn);
+int tlsv1_client_prf(struct tlsv1_client *conn, const char *label,
+                    int server_random_first, u8 *out, size_t out_len);
+u8 * tlsv1_client_handshake(struct tlsv1_client *conn,
+                           const u8 *in_data, size_t in_len,
+                           size_t *out_len, u8 **appl_data,
+                           size_t *appl_data_len, int *need_more_data);
+int tlsv1_client_encrypt(struct tlsv1_client *conn,
+                        const u8 *in_data, size_t in_len,
+                        u8 *out_data, size_t out_len);
+struct wpabuf * tlsv1_client_decrypt(struct tlsv1_client *conn,
+                                    const u8 *in_data, size_t in_len,
+                                    int *need_more_data);
+int tlsv1_client_get_cipher(struct tlsv1_client *conn, char *buf,
+                           size_t buflen);
+int tlsv1_client_shutdown(struct tlsv1_client *conn);
+int tlsv1_client_resumed(struct tlsv1_client *conn);
+int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type,
+                          const u8 *data, size_t data_len);
+int tlsv1_client_get_keys(struct tlsv1_client *conn, struct tls_keys *keys);
+int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn);
+int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers);
+int tlsv1_client_set_cred(struct tlsv1_client *conn,
+                         struct tlsv1_credentials *cred);
+void tlsv1_client_set_time_checks(struct tlsv1_client *conn, int enabled);
+
+typedef int (*tlsv1_client_session_ticket_cb)
+(void *ctx, const u8 *ticket, size_t len, const u8 *client_random,
+ const u8 *server_random, u8 *master_secret);
+
+void tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn,
+                                       tlsv1_client_session_ticket_cb cb,
+                                       void *ctx);
+
+#endif /* TLSV1_CLIENT_H */
diff --git a/components/wpa_supplicant/include/wpa2/tls/tlsv1_client_i.h b/components/wpa_supplicant/include/wpa2/tls/tlsv1_client_i.h
new file mode 100644 (file)
index 0000000..55fdcf8
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * TLSv1 client - internal structures
+ * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef TLSV1_CLIENT_I_H
+#define TLSV1_CLIENT_I_H
+
+struct tlsv1_client {
+       enum {
+               CLIENT_HELLO, SERVER_HELLO, SERVER_CERTIFICATE,
+               SERVER_KEY_EXCHANGE, SERVER_CERTIFICATE_REQUEST,
+               SERVER_HELLO_DONE, CLIENT_KEY_EXCHANGE, CHANGE_CIPHER_SPEC,
+               SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, ACK_FINISHED,
+               ESTABLISHED, FAILED
+       } state;
+
+       struct tlsv1_record_layer rl;
+
+       u8 session_id[TLS_SESSION_ID_MAX_LEN];
+       size_t session_id_len;
+       u8 client_random[TLS_RANDOM_LEN];
+       u8 server_random[TLS_RANDOM_LEN];
+       u8 master_secret[TLS_MASTER_SECRET_LEN];
+
+       u8 alert_level;
+       u8 alert_description;
+
+       unsigned int certificate_requested:1;
+       unsigned int session_resumed:1;
+       unsigned int session_ticket_included:1;
+       unsigned int use_session_ticket:1;
+       unsigned int disable_time_checks:1;
+
+       struct crypto_public_key *server_rsa_key;
+
+       struct tls_verify_hash verify;
+
+#define MAX_CIPHER_COUNT 30
+       u16 cipher_suites[MAX_CIPHER_COUNT];
+       size_t num_cipher_suites;
+
+       u16 prev_cipher_suite;
+
+       u8 *client_hello_ext;
+       size_t client_hello_ext_len;
+
+       /* The prime modulus used for Diffie-Hellman */
+       u8 *dh_p;
+       size_t dh_p_len;
+       /* The generator used for Diffie-Hellman */
+       u8 *dh_g;
+       size_t dh_g_len;
+       /* The server's Diffie-Hellman public value */
+       u8 *dh_ys;
+       size_t dh_ys_len;
+
+       struct tlsv1_credentials *cred;
+
+       tlsv1_client_session_ticket_cb session_ticket_cb;
+       void *session_ticket_cb_ctx;
+
+       struct wpabuf *partial_input;
+};
+
+
+void tls_alert(struct tlsv1_client *conn, u8 level, u8 description);
+void tlsv1_client_free_dh(struct tlsv1_client *conn);
+int tls_derive_pre_master_secret(u8 *pre_master_secret);
+int tls_derive_keys(struct tlsv1_client *conn,
+                   const u8 *pre_master_secret, size_t pre_master_secret_len);
+u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len);
+u8 * tlsv1_client_send_alert(struct tlsv1_client *conn, u8 level,
+                            u8 description, size_t *out_len);
+u8 * tlsv1_client_handshake_write(struct tlsv1_client *conn, size_t *out_len,
+                                 int no_appl_data);
+int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct,
+                                  const u8 *buf, size_t *len,
+                                  u8 **out_data, size_t *out_len);
+
+#endif /* TLSV1_CLIENT_I_H */
diff --git a/components/wpa_supplicant/include/wpa2/tls/tlsv1_common.h b/components/wpa_supplicant/include/wpa2/tls/tlsv1_common.h
new file mode 100644 (file)
index 0000000..f28c0cd
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * TLSv1 common definitions
+ * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef TLSV1_COMMON_H
+#define TLSV1_COMMON_H
+
+#include "crypto/crypto.h"
+
+#define TLS_VERSION_1 0x0301 /* TLSv1 */
+#define TLS_VERSION_1_1 0x0302 /* TLSv1.1 */
+#define TLS_VERSION_1_2 0x0303 /* TLSv1.2 */
+#ifdef CONFIG_TLSV12
+#define TLS_VERSION TLS_VERSION_1_2
+#else /* CONFIG_TLSV12 */
+#ifdef CONFIG_TLSV11
+#define TLS_VERSION TLS_VERSION_1_1
+#else /* CONFIG_TLSV11 */
+#define TLS_VERSION TLS_VERSION_1
+#endif /* CONFIG_TLSV11 */
+#endif /* CONFIG_TLSV12 */
+#define TLS_RANDOM_LEN 32
+#define TLS_PRE_MASTER_SECRET_LEN 48
+#define TLS_MASTER_SECRET_LEN 48
+#define TLS_SESSION_ID_MAX_LEN 32
+#define TLS_VERIFY_DATA_LEN 12
+
+/* HandshakeType */
+enum {
+       TLS_HANDSHAKE_TYPE_HELLO_REQUEST = 0,
+       TLS_HANDSHAKE_TYPE_CLIENT_HELLO = 1,
+       TLS_HANDSHAKE_TYPE_SERVER_HELLO = 2,
+       TLS_HANDSHAKE_TYPE_NEW_SESSION_TICKET = 4 /* RFC 4507 */,
+       TLS_HANDSHAKE_TYPE_CERTIFICATE = 11,
+       TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE = 12,
+       TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST = 13,
+       TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE = 14,
+       TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY = 15,
+       TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE = 16,
+       TLS_HANDSHAKE_TYPE_FINISHED = 20,
+       TLS_HANDSHAKE_TYPE_CERTIFICATE_URL = 21 /* RFC 4366 */,
+       TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS = 22 /* RFC 4366 */
+};
+
+/* CipherSuite */
+#define TLS_NULL_WITH_NULL_NULL                        0x0000 /* RFC 2246 */
+#define TLS_RSA_WITH_NULL_MD5                  0x0001 /* RFC 2246 */
+#define TLS_RSA_WITH_NULL_SHA                  0x0002 /* RFC 2246 */
+#define TLS_RSA_EXPORT_WITH_RC4_40_MD5         0x0003 /* RFC 2246 */
+#define TLS_RSA_WITH_RC4_128_MD5               0x0004 /* RFC 2246 */
+#define TLS_RSA_WITH_RC4_128_SHA               0x0005 /* RFC 2246 */
+#define TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5     0x0006 /* RFC 2246 */
+#define TLS_RSA_WITH_IDEA_CBC_SHA              0x0007 /* RFC 2246 */
+#define TLS_RSA_EXPORT_WITH_DES40_CBC_SHA      0x0008 /* RFC 2246 */
+#define TLS_RSA_WITH_DES_CBC_SHA               0x0009 /* RFC 2246 */
+#define TLS_RSA_WITH_3DES_EDE_CBC_SHA          0x000A /* RFC 2246 */
+#define TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA   0x000B /* RFC 2246 */
+#define TLS_DH_DSS_WITH_DES_CBC_SHA            0x000C /* RFC 2246 */
+#define TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA       0x000D /* RFC 2246 */
+#define TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA   0x000E /* RFC 2246 */
+#define TLS_DH_RSA_WITH_DES_CBC_SHA            0x000F /* RFC 2246 */
+#define TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA       0x0010 /* RFC 2246 */
+#define TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA  0x0011 /* RFC 2246 */
+#define TLS_DHE_DSS_WITH_DES_CBC_SHA           0x0012 /* RFC 2246 */
+#define TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA      0x0013 /* RFC 2246 */
+#define TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA  0x0014 /* RFC 2246 */
+#define TLS_DHE_RSA_WITH_DES_CBC_SHA           0x0015 /* RFC 2246 */
+#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA      0x0016 /* RFC 2246 */
+#define TLS_DH_anon_EXPORT_WITH_RC4_40_MD5     0x0017 /* RFC 2246 */
+#define TLS_DH_anon_WITH_RC4_128_MD5           0x0018 /* RFC 2246 */
+#define TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA  0x0019 /* RFC 2246 */
+#define TLS_DH_anon_WITH_DES_CBC_SHA           0x001A /* RFC 2246 */
+#define TLS_DH_anon_WITH_3DES_EDE_CBC_SHA      0x001B /* RFC 2246 */
+#define TLS_RSA_WITH_AES_128_CBC_SHA           0x002F /* RFC 3268 */
+#define TLS_DH_DSS_WITH_AES_128_CBC_SHA                0x0030 /* RFC 3268 */
+#define TLS_DH_RSA_WITH_AES_128_CBC_SHA                0x0031 /* RFC 3268 */
+#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA       0x0032 /* RFC 3268 */
+#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA       0x0033 /* RFC 3268 */
+#define TLS_DH_anon_WITH_AES_128_CBC_SHA       0x0034 /* RFC 3268 */
+#define TLS_RSA_WITH_AES_256_CBC_SHA           0x0035 /* RFC 3268 */
+#define TLS_DH_DSS_WITH_AES_256_CBC_SHA                0x0036 /* RFC 3268 */
+#define TLS_DH_RSA_WITH_AES_256_CBC_SHA                0x0037 /* RFC 3268 */
+#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA       0x0038 /* RFC 3268 */
+#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA       0x0039 /* RFC 3268 */
+#define TLS_DH_anon_WITH_AES_256_CBC_SHA       0x003A /* RFC 3268 */
+#define TLS_RSA_WITH_NULL_SHA256               0x003B /* RFC 5246 */
+#define TLS_RSA_WITH_AES_128_CBC_SHA256                0x003C /* RFC 5246 */
+#define TLS_RSA_WITH_AES_256_CBC_SHA256                0x003D /* RFC 5246 */
+#define TLS_DH_DSS_WITH_AES_128_CBC_SHA256     0x003E /* RFC 5246 */
+#define TLS_DH_RSA_WITH_AES_128_CBC_SHA256     0x003F /* RFC 5246 */
+#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA256    0x0040 /* RFC 5246 */
+#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256    0x0067 /* RFC 5246 */
+#define TLS_DH_DSS_WITH_AES_256_CBC_SHA256     0x0068 /* RFC 5246 */
+#define TLS_DH_RSA_WITH_AES_256_CBC_SHA256     0x0069 /* RFC 5246 */
+#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA256    0x006A /* RFC 5246 */
+#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256    0x006B /* RFC 5246 */
+#define TLS_DH_anon_WITH_AES_128_CBC_SHA256    0x006C /* RFC 5246 */
+#define TLS_DH_anon_WITH_AES_256_CBC_SHA256    0x006D /* RFC 5246 */
+
+/* CompressionMethod */
+#define TLS_COMPRESSION_NULL 0
+
+/* HashAlgorithm */
+enum {
+       TLS_HASH_ALG_NONE = 0,
+       TLS_HASH_ALG_MD5 = 1,
+       TLS_HASH_ALG_SHA1 = 2,
+       TLS_HASH_ALG_SHA224 = 3,
+       TLS_HASH_ALG_SHA256 = 4,
+       TLS_HASH_ALG_SHA384 = 5,
+       TLS_HASH_ALG_SHA512 = 6
+};
+
+/* SignatureAlgorithm */
+enum {
+       TLS_SIGN_ALG_ANONYMOUS = 0,
+       TLS_SIGN_ALG_RSA = 1,
+       TLS_SIGN_ALG_DSA = 2,
+       TLS_SIGN_ALG_ECDSA = 3,
+};
+
+/* AlertLevel */
+#define TLS_ALERT_LEVEL_WARNING 1
+#define TLS_ALERT_LEVEL_FATAL 2
+
+/* AlertDescription */
+#define TLS_ALERT_CLOSE_NOTIFY                 0
+#define TLS_ALERT_UNEXPECTED_MESSAGE           10
+#define TLS_ALERT_BAD_RECORD_MAC               20
+#define TLS_ALERT_DECRYPTION_FAILED            21
+#define TLS_ALERT_RECORD_OVERFLOW              22
+#define TLS_ALERT_DECOMPRESSION_FAILURE                30
+#define TLS_ALERT_HANDSHAKE_FAILURE            40
+#define TLS_ALERT_BAD_CERTIFICATE              42
+#define TLS_ALERT_UNSUPPORTED_CERTIFICATE      43
+#define TLS_ALERT_CERTIFICATE_REVOKED          44
+#define TLS_ALERT_CERTIFICATE_EXPIRED          45
+#define TLS_ALERT_CERTIFICATE_UNKNOWN          46
+#define TLS_ALERT_ILLEGAL_PARAMETER            47
+#define TLS_ALERT_UNKNOWN_CA                   48
+#define TLS_ALERT_ACCESS_DENIED                        49
+#define TLS_ALERT_DECODE_ERROR                 50
+#define TLS_ALERT_DECRYPT_ERROR                        51
+#define TLS_ALERT_EXPORT_RESTRICTION           60
+#define TLS_ALERT_PROTOCOL_VERSION             70
+#define TLS_ALERT_INSUFFICIENT_SECURITY                71
+#define TLS_ALERT_INTERNAL_ERROR               80
+#define TLS_ALERT_USER_CANCELED                        90
+#define TLS_ALERT_NO_RENEGOTIATION             100
+#define TLS_ALERT_UNSUPPORTED_EXTENSION                110 /* RFC 4366 */
+#define TLS_ALERT_CERTIFICATE_UNOBTAINABLE     111 /* RFC 4366 */
+#define TLS_ALERT_UNRECOGNIZED_NAME            112 /* RFC 4366 */
+#define TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE      113 /* RFC 4366 */
+#define TLS_ALERT_BAD_CERTIFICATE_HASH_VALUE   114 /* RFC 4366 */
+
+/* ChangeCipherSpec */
+enum {
+       TLS_CHANGE_CIPHER_SPEC = 1
+};
+
+/* TLS Extensions */
+#define TLS_EXT_SERVER_NAME                    0 /* RFC 4366 */
+#define TLS_EXT_MAX_FRAGMENT_LENGTH            1 /* RFC 4366 */
+#define TLS_EXT_CLIENT_CERTIFICATE_URL         2 /* RFC 4366 */
+#define TLS_EXT_TRUSTED_CA_KEYS                        3 /* RFC 4366 */
+#define TLS_EXT_TRUNCATED_HMAC                 4 /* RFC 4366 */
+#define TLS_EXT_STATUS_REQUEST                 5 /* RFC 4366 */
+#define TLS_EXT_SESSION_TICKET                 35 /* RFC 4507 */
+
+#define TLS_EXT_PAC_OPAQUE TLS_EXT_SESSION_TICKET /* EAP-FAST terminology */
+
+
+typedef enum {
+       TLS_KEY_X_NULL,
+       TLS_KEY_X_RSA,
+       TLS_KEY_X_RSA_EXPORT,
+       TLS_KEY_X_DH_DSS_EXPORT,
+       TLS_KEY_X_DH_DSS,
+       TLS_KEY_X_DH_RSA_EXPORT,
+       TLS_KEY_X_DH_RSA,
+       TLS_KEY_X_DHE_DSS_EXPORT,
+       TLS_KEY_X_DHE_DSS,
+       TLS_KEY_X_DHE_RSA_EXPORT,
+       TLS_KEY_X_DHE_RSA,
+       TLS_KEY_X_DH_anon_EXPORT,
+       TLS_KEY_X_DH_anon
+} tls_key_exchange;
+
+typedef enum {
+       TLS_CIPHER_NULL,
+       TLS_CIPHER_RC4_40,
+       TLS_CIPHER_RC4_128,
+       TLS_CIPHER_RC2_CBC_40,
+       TLS_CIPHER_IDEA_CBC,
+       TLS_CIPHER_DES40_CBC,
+       TLS_CIPHER_DES_CBC,
+       TLS_CIPHER_3DES_EDE_CBC,
+       TLS_CIPHER_AES_128_CBC,
+       TLS_CIPHER_AES_256_CBC
+} tls_cipher;
+
+typedef enum {
+       TLS_HASH_NULL,
+       TLS_HASH_MD5,
+       TLS_HASH_SHA,
+       TLS_HASH_SHA256
+} tls_hash;
+
+struct tls_cipher_suite {
+       u16 suite;
+       tls_key_exchange key_exchange;
+       tls_cipher cipher;
+       tls_hash hash;
+};
+
+typedef enum {
+       TLS_CIPHER_STREAM,
+       TLS_CIPHER_BLOCK
+} tls_cipher_type;
+
+struct tls_cipher_data {
+       tls_cipher cipher;
+       tls_cipher_type type;
+       size_t key_material;
+       size_t expanded_key_material;
+       size_t block_size; /* also iv_size */
+       enum crypto_cipher_alg alg;
+};
+
+
+struct tls_verify_hash {
+       struct crypto_hash *md5_client;
+       struct crypto_hash *sha1_client;
+       struct crypto_hash *sha256_client;
+       struct crypto_hash *md5_server;
+       struct crypto_hash *sha1_server;
+       struct crypto_hash *sha256_server;
+       struct crypto_hash *md5_cert;
+       struct crypto_hash *sha1_cert;
+       struct crypto_hash *sha256_cert;
+};
+
+
+const struct tls_cipher_suite * tls_get_cipher_suite(u16 suite);
+const struct tls_cipher_data * tls_get_cipher_data(tls_cipher cipher);
+int tls_server_key_exchange_allowed(tls_cipher cipher);
+int tls_parse_cert(const u8 *buf, size_t len, struct crypto_public_key **pk);
+int tls_verify_hash_init(struct tls_verify_hash *verify);
+void tls_verify_hash_add(struct tls_verify_hash *verify, const u8 *buf,
+                        size_t len);
+void tls_verify_hash_free(struct tls_verify_hash *verify);
+int tls_version_ok(u16 ver);
+const char * tls_version_str(u16 ver);
+int tls_prf(u16 ver, const u8 *secret, size_t secret_len, const char *label,
+           const u8 *seed, size_t seed_len, u8 *out, size_t outlen);
+
+#endif /* TLSV1_COMMON_H */
diff --git a/components/wpa_supplicant/include/wpa2/tls/tlsv1_cred.h b/components/wpa_supplicant/include/wpa2/tls/tlsv1_cred.h
new file mode 100644 (file)
index 0000000..68fbdc9
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * TLSv1 credentials
+ * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef TLSV1_CRED_H
+#define TLSV1_CRED_H
+
+struct tlsv1_credentials {
+       struct x509_certificate *trusted_certs;
+       struct x509_certificate *cert;
+       struct crypto_private_key *key;
+
+       /* Diffie-Hellman parameters */
+       u8 *dh_p; /* prime */
+       size_t dh_p_len;
+       u8 *dh_g; /* generator */
+       size_t dh_g_len;
+};
+
+
+struct tlsv1_credentials * tlsv1_cred_alloc(void);
+void tlsv1_cred_free(struct tlsv1_credentials *cred);
+int tlsv1_set_ca_cert(struct tlsv1_credentials *cred, const char *cert,
+                     const u8 *cert_blob, size_t cert_blob_len,
+                     const char *path);
+int tlsv1_set_cert(struct tlsv1_credentials *cred, const char *cert,
+                  const u8 *cert_blob, size_t cert_blob_len);
+int tlsv1_set_private_key(struct tlsv1_credentials *cred,
+                         const char *private_key,
+                         const char *private_key_passwd,
+                         const u8 *private_key_blob,
+                         size_t private_key_blob_len);
+int tlsv1_set_dhparams(struct tlsv1_credentials *cred, const char *dh_file,
+                      const u8 *dh_blob, size_t dh_blob_len);
+
+#endif /* TLSV1_CRED_H */
diff --git a/components/wpa_supplicant/include/wpa2/tls/tlsv1_record.h b/components/wpa_supplicant/include/wpa2/tls/tlsv1_record.h
new file mode 100644 (file)
index 0000000..48abcb0
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * TLSv1 Record Protocol
+ * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef TLSV1_RECORD_H
+#define TLSV1_RECORD_H
+
+#include "crypto/crypto.h"
+
+#define TLS_MAX_WRITE_MAC_SECRET_LEN 32
+#define TLS_MAX_WRITE_KEY_LEN 32
+#define TLS_MAX_IV_LEN 16
+#define TLS_MAX_KEY_BLOCK_LEN (2 * (TLS_MAX_WRITE_MAC_SECRET_LEN + \
+                                   TLS_MAX_WRITE_KEY_LEN + TLS_MAX_IV_LEN))
+
+#define TLS_SEQ_NUM_LEN 8
+#define TLS_RECORD_HEADER_LEN 5
+
+/* ContentType */
+enum {
+       TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC = 20,
+       TLS_CONTENT_TYPE_ALERT = 21,
+       TLS_CONTENT_TYPE_HANDSHAKE = 22,
+       TLS_CONTENT_TYPE_APPLICATION_DATA = 23
+};
+
+struct tlsv1_record_layer {
+       u16 tls_version;
+
+       u8 write_mac_secret[TLS_MAX_WRITE_MAC_SECRET_LEN];
+       u8 read_mac_secret[TLS_MAX_WRITE_MAC_SECRET_LEN];
+       u8 write_key[TLS_MAX_WRITE_KEY_LEN];
+       u8 read_key[TLS_MAX_WRITE_KEY_LEN];
+       u8 write_iv[TLS_MAX_IV_LEN];
+       u8 read_iv[TLS_MAX_IV_LEN];
+
+       size_t hash_size;
+       size_t key_material_len;
+       size_t iv_size; /* also block_size */
+
+       enum crypto_hash_alg hash_alg;
+       enum crypto_cipher_alg cipher_alg;
+
+       u8 write_seq_num[TLS_SEQ_NUM_LEN];
+       u8 read_seq_num[TLS_SEQ_NUM_LEN];
+
+       u16 cipher_suite;
+       u16 write_cipher_suite;
+       u16 read_cipher_suite;
+
+       struct crypto_cipher *write_cbc;
+       struct crypto_cipher *read_cbc;
+};
+
+
+int tlsv1_record_set_cipher_suite(struct tlsv1_record_layer *rl,
+                                 u16 cipher_suite);
+int tlsv1_record_change_write_cipher(struct tlsv1_record_layer *rl);
+int tlsv1_record_change_read_cipher(struct tlsv1_record_layer *rl);
+int tlsv1_record_send(struct tlsv1_record_layer *rl, u8 content_type, u8 *buf,
+                     size_t buf_size, const u8 *payload, size_t payload_len,
+                     size_t *out_len);
+int tlsv1_record_receive(struct tlsv1_record_layer *rl,
+                        const u8 *in_data, size_t in_len,
+                        u8 *out_data, size_t *out_len, u8 *alert);
+
+#endif /* TLSV1_RECORD_H */
diff --git a/components/wpa_supplicant/include/wpa2/tls/tlsv1_server.h b/components/wpa_supplicant/include/wpa2/tls/tlsv1_server.h
new file mode 100644 (file)
index 0000000..a18c69e
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * TLS v1.0/v1.1/v1.2 server (RFC 2246, RFC 4346, RFC 5246)
+ * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef TLSV1_SERVER_H
+#define TLSV1_SERVER_H
+
+#include "tlsv1_cred.h"
+
+struct tlsv1_server;
+
+int tlsv1_server_global_init(void);
+void tlsv1_server_global_deinit(void);
+struct tlsv1_server * tlsv1_server_init(struct tlsv1_credentials *cred);
+void tlsv1_server_deinit(struct tlsv1_server *conn);
+int tlsv1_server_established(struct tlsv1_server *conn);
+int tlsv1_server_prf(struct tlsv1_server *conn, const char *label,
+                    int server_random_first, u8 *out, size_t out_len);
+u8 * tlsv1_server_handshake(struct tlsv1_server *conn,
+                           const u8 *in_data, size_t in_len, size_t *out_len);
+int tlsv1_server_encrypt(struct tlsv1_server *conn,
+                        const u8 *in_data, size_t in_len,
+                        u8 *out_data, size_t out_len);
+int tlsv1_server_decrypt(struct tlsv1_server *conn,
+                        const u8 *in_data, size_t in_len,
+                        u8 *out_data, size_t out_len);
+int tlsv1_server_get_cipher(struct tlsv1_server *conn, char *buf,
+                           size_t buflen);
+int tlsv1_server_shutdown(struct tlsv1_server *conn);
+int tlsv1_server_resumed(struct tlsv1_server *conn);
+int tlsv1_server_get_keys(struct tlsv1_server *conn, struct tls_keys *keys);
+int tlsv1_server_get_keyblock_size(struct tlsv1_server *conn);
+int tlsv1_server_set_cipher_list(struct tlsv1_server *conn, u8 *ciphers);
+int tlsv1_server_set_verify(struct tlsv1_server *conn, int verify_peer);
+
+typedef int (*tlsv1_server_session_ticket_cb)
+(void *ctx, const u8 *ticket, size_t len, const u8 *client_random,
+ const u8 *server_random, u8 *master_secret);
+
+void tlsv1_server_set_session_ticket_cb(struct tlsv1_server *conn,
+                                       tlsv1_server_session_ticket_cb cb,
+                                       void *ctx);
+
+#endif /* TLSV1_SERVER_H */
diff --git a/components/wpa_supplicant/include/wpa2/tls/tlsv1_server_i.h b/components/wpa_supplicant/include/wpa2/tls/tlsv1_server_i.h
new file mode 100644 (file)
index 0000000..1f61533
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * TLSv1 server - internal structures
+ * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef TLSV1_SERVER_I_H
+#define TLSV1_SERVER_I_H
+
+struct tlsv1_server {
+       enum {
+               CLIENT_HELLO, SERVER_HELLO, SERVER_CERTIFICATE,
+               SERVER_KEY_EXCHANGE, SERVER_CERTIFICATE_REQUEST,
+               SERVER_HELLO_DONE, CLIENT_CERTIFICATE, CLIENT_KEY_EXCHANGE,
+               CERTIFICATE_VERIFY, CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
+               SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED,
+               ESTABLISHED, FAILED
+       } state;
+
+       struct tlsv1_record_layer rl;
+
+       u8 session_id[TLS_SESSION_ID_MAX_LEN];
+       size_t session_id_len;
+       u8 client_random[TLS_RANDOM_LEN];
+       u8 server_random[TLS_RANDOM_LEN];
+       u8 master_secret[TLS_MASTER_SECRET_LEN];
+
+       u8 alert_level;
+       u8 alert_description;
+
+       struct crypto_public_key *client_rsa_key;
+
+       struct tls_verify_hash verify;
+
+#define MAX_CIPHER_COUNT 30
+       u16 cipher_suites[MAX_CIPHER_COUNT];
+       size_t num_cipher_suites;
+
+       u16 cipher_suite;
+
+       struct tlsv1_credentials *cred;
+
+       int verify_peer;
+       u16 client_version;
+
+       u8 *session_ticket;
+       size_t session_ticket_len;
+
+       tlsv1_server_session_ticket_cb session_ticket_cb;
+       void *session_ticket_cb_ctx;
+
+       int use_session_ticket;
+
+       u8 *dh_secret;
+       size_t dh_secret_len;
+};
+
+
+void tlsv1_server_alert(struct tlsv1_server *conn, u8 level, u8 description);
+int tlsv1_server_derive_keys(struct tlsv1_server *conn,
+                            const u8 *pre_master_secret,
+                            size_t pre_master_secret_len);
+u8 * tlsv1_server_handshake_write(struct tlsv1_server *conn, size_t *out_len);
+u8 * tlsv1_server_send_alert(struct tlsv1_server *conn, u8 level,
+                            u8 description, size_t *out_len);
+int tlsv1_server_process_handshake(struct tlsv1_server *conn, u8 ct,
+                                  const u8 *buf, size_t *len);
+
+#endif /* TLSV1_SERVER_I_H */
diff --git a/components/wpa_supplicant/include/wpa2/tls/x509v3.h b/components/wpa_supplicant/include/wpa2/tls/x509v3.h
new file mode 100644 (file)
index 0000000..91a35ba
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * X.509v3 certificate parsing and processing
+ * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef X509V3_H
+#define X509V3_H
+
+#include "asn1.h"
+
+struct x509_algorithm_identifier {
+       struct asn1_oid oid;
+};
+
+struct x509_name_attr {
+       enum x509_name_attr_type {
+               X509_NAME_ATTR_NOT_USED,
+               X509_NAME_ATTR_DC,
+               X509_NAME_ATTR_CN,
+               X509_NAME_ATTR_C,
+               X509_NAME_ATTR_L,
+               X509_NAME_ATTR_ST,
+               X509_NAME_ATTR_O,
+               X509_NAME_ATTR_OU
+       } type;
+       char *value;
+};
+
+#define X509_MAX_NAME_ATTRIBUTES 20
+
+struct x509_name {
+       struct x509_name_attr attr[X509_MAX_NAME_ATTRIBUTES];
+       size_t num_attr;
+       char *email; /* emailAddress */
+
+       /* from alternative name extension */
+       char *alt_email; /* rfc822Name */
+       char *dns; /* dNSName */
+       char *uri; /* uniformResourceIdentifier */
+       u8 *ip; /* iPAddress */
+       size_t ip_len; /* IPv4: 4, IPv6: 16 */
+       struct asn1_oid rid; /* registeredID */
+};
+
+struct x509_certificate {
+       struct x509_certificate *next;
+       enum { X509_CERT_V1 = 0, X509_CERT_V2 = 1, X509_CERT_V3 = 2 } version;
+       unsigned long serial_number;
+       struct x509_algorithm_identifier signature;
+       struct x509_name issuer;
+       struct x509_name subject;
+       os_time_t not_before;
+       os_time_t not_after;
+       struct x509_algorithm_identifier public_key_alg;
+       u8 *public_key;
+       size_t public_key_len;
+       struct x509_algorithm_identifier signature_alg;
+       u8 *sign_value;
+       size_t sign_value_len;
+
+       /* Extensions */
+       unsigned int extensions_present;
+#define X509_EXT_BASIC_CONSTRAINTS             (1 << 0)
+#define X509_EXT_PATH_LEN_CONSTRAINT           (1 << 1)
+#define X509_EXT_KEY_USAGE                     (1 << 2)
+#define X509_EXT_SUBJECT_ALT_NAME              (1 << 3)
+#define X509_EXT_ISSUER_ALT_NAME               (1 << 4)
+
+       /* BasicConstraints */
+       int ca; /* cA */
+       unsigned long path_len_constraint; /* pathLenConstraint */
+
+       /* KeyUsage */
+       unsigned long key_usage;
+#define X509_KEY_USAGE_DIGITAL_SIGNATURE       (1 << 0)
+#define X509_KEY_USAGE_NON_REPUDIATION         (1 << 1)
+#define X509_KEY_USAGE_KEY_ENCIPHERMENT                (1 << 2)
+#define X509_KEY_USAGE_DATA_ENCIPHERMENT       (1 << 3)
+#define X509_KEY_USAGE_KEY_AGREEMENT           (1 << 4)
+#define X509_KEY_USAGE_KEY_CERT_SIGN           (1 << 5)
+#define X509_KEY_USAGE_CRL_SIGN                        (1 << 6)
+#define X509_KEY_USAGE_ENCIPHER_ONLY           (1 << 7)
+#define X509_KEY_USAGE_DECIPHER_ONLY           (1 << 8)
+
+       /*
+        * The DER format certificate follows struct x509_certificate. These
+        * pointers point to that buffer.
+        */
+       const u8 *cert_start;
+       size_t cert_len;
+       const u8 *tbs_cert_start;
+       size_t tbs_cert_len;
+};
+
+enum {
+       X509_VALIDATE_OK,
+       X509_VALIDATE_BAD_CERTIFICATE,
+       X509_VALIDATE_UNSUPPORTED_CERTIFICATE,
+       X509_VALIDATE_CERTIFICATE_REVOKED,
+       X509_VALIDATE_CERTIFICATE_EXPIRED,
+       X509_VALIDATE_CERTIFICATE_UNKNOWN,
+       X509_VALIDATE_UNKNOWN_CA
+};
+
+void x509_certificate_free(struct x509_certificate *cert);
+struct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len);
+void x509_name_string(struct x509_name *name, char *buf, size_t len);
+int x509_name_compare(struct x509_name *a, struct x509_name *b);
+void x509_certificate_chain_free(struct x509_certificate *cert);
+int x509_certificate_check_signature(struct x509_certificate *issuer,
+                                    struct x509_certificate *cert);
+int x509_certificate_chain_validate(struct x509_certificate *trusted,
+                                   struct x509_certificate *chain,
+                                   int *reason, int disable_time_checks);
+struct x509_certificate *
+x509_certificate_get_subject(struct x509_certificate *chain,
+                            struct x509_name *name);
+int x509_certificate_self_signed(struct x509_certificate *cert);
+
+#endif /* X509V3_H */
diff --git a/components/wpa_supplicant/include/wpa2/utils/base64.h b/components/wpa_supplicant/include/wpa2/utils/base64.h
new file mode 100644 (file)
index 0000000..91eb874
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Base64 encoding/decoding (RFC1341)
+ * Copyright (c) 2005, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef BASE64_H
+#define BASE64_H
+
+unsigned char * _base64_encode(const unsigned char *src, size_t len,
+                             size_t *out_len);
+unsigned char * _base64_decode(const unsigned char *src, size_t len,
+                             size_t *out_len);
+
+#endif /* BASE64_H */
diff --git a/components/wpa_supplicant/include/wpa2/utils/ext_password.h b/components/wpa_supplicant/include/wpa2/utils/ext_password.h
new file mode 100644 (file)
index 0000000..e3e46ea
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * External password backend
+ * Copyright (c) 2012, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef EXT_PASSWORD_H
+#define EXT_PASSWORD_H
+
+struct ext_password_data;
+
+#ifdef CONFIG_EXT_PASSWORD
+
+struct ext_password_data * ext_password_init(const char *backend,
+                                            const char *params);
+void ext_password_deinit(struct ext_password_data *data);
+
+struct wpabuf * ext_password_get(struct ext_password_data *data,
+                                const char *name);
+void ext_password_free(struct wpabuf *pw);
+
+#else /* CONFIG_EXT_PASSWORD */
+
+#define ext_password_init(b, p) ((void *) 1)
+#define ext_password_deinit(d) do { } while (0)
+#define ext_password_get(d, n) (NULL)
+#define ext_password_free(p) do { } while (0)
+
+#endif /* CONFIG_EXT_PASSWORD */
+
+#endif /* EXT_PASSWORD_H */
diff --git a/components/wpa_supplicant/include/wpa2/utils/ext_password_i.h b/components/wpa_supplicant/include/wpa2/utils/ext_password_i.h
new file mode 100644 (file)
index 0000000..043e731
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * External password backend - internal definitions
+ * Copyright (c) 2012, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef EXT_PASSWORD_I_H
+#define EXT_PASSWORD_I_H
+
+#include "ext_password.h"
+
+struct ext_password_backend {
+       const char *name;
+       void * (*init)(const char *params);
+       void (*deinit)(void *ctx);
+       struct wpabuf * (*get)(void *ctx, const char *name);
+};
+
+struct wpabuf * ext_password_alloc(size_t len);
+
+#endif /* EXT_PASSWORD_I_H */
diff --git a/components/wpa_supplicant/port/include/byteswap.h b/components/wpa_supplicant/port/include/byteswap.h
new file mode 100644 (file)
index 0000000..1a8bb8f
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010 Espressif System
+ */
+
+#ifndef BYTESWAP_H
+#define BYTESWAP_H
+
+/* Swap bytes in 16 bit value.  */
+#ifdef __GNUC__
+# define __bswap_16(x) \
+    (__extension__                                                           \
+     ({ unsigned short int __bsx = (x);                                              \
+        ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8)); }))
+#else
+static INLINE unsigned short int
+__bswap_16 (unsigned short int __bsx)
+{
+  return ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8));
+}
+#endif
+
+/* Swap bytes in 32 bit value.  */
+#ifdef __GNUC__
+# define __bswap_32(x) \
+    (__extension__                                                           \
+     ({ unsigned int __bsx = (x);                                            \
+        ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >>  8) |    \
+        (((__bsx) & 0x0000ff00) <<  8) | (((__bsx) & 0x000000ff) << 24)); }))
+#else
+static INLINE unsigned int
+__bswap_32 (unsigned int __bsx)
+{
+  return ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >>  8) |
+         (((__bsx) & 0x0000ff00) <<  8) | (((__bsx) & 0x000000ff) << 24));
+}
+#endif
+
+#if defined __GNUC__ && __GNUC__ >= 2
+/* Swap bytes in 64 bit value.  */
+# define __bswap_constant_64(x) \
+     ((((x) & 0xff00000000000000ull) >> 56)                                  \
+      | (((x) & 0x00ff000000000000ull) >> 40)                                \
+      | (((x) & 0x0000ff0000000000ull) >> 24)                                \
+      | (((x) & 0x000000ff00000000ull) >> 8)                                 \
+      | (((x) & 0x00000000ff000000ull) << 8)                                 \
+      | (((x) & 0x0000000000ff0000ull) << 24)                                \
+      | (((x) & 0x000000000000ff00ull) << 40)                                \
+      | (((x) & 0x00000000000000ffull) << 56))
+
+# define __bswap_64(x) \
+     (__extension__                                                          \
+      ({ union { __extension__ unsigned long long int __ll;                  \
+                unsigned int __l[2]; } __w, __r;                             \
+         if (__builtin_constant_p (x))                                       \
+          __r.__ll = __bswap_constant_64 (x);                                \
+        else                                                                 \
+          {                                                                  \
+            __w.__ll = (x);                                                  \
+            __r.__l[0] = __bswap_32 (__w.__l[1]);                            \
+            __r.__l[1] = __bswap_32 (__w.__l[0]);                            \
+          }                                                                  \
+        __r.__ll; }))
+#endif
+
+#endif /* BYTESWAP_H */
diff --git a/components/wpa_supplicant/port/include/endian.h b/components/wpa_supplicant/port/include/endian.h
new file mode 100644 (file)
index 0000000..e2df616
--- /dev/null
@@ -0,0 +1,229 @@
+/*-
+ * Copyright (c) 2002 Thomas Moestl <tmm@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _ENDIAN_H_
+#define _ENDIAN_H_
+
+#include "byteswap.h"
+
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN 4321
+#endif
+#ifndef LITTLE_ENDIAN
+#define LITTLE_ENDIAN 1234
+#endif
+
+#ifndef BYTE_ORDER
+#ifdef __IEEE_LITTLE_ENDIAN
+#define BYTE_ORDER LITTLE_ENDIAN
+#else
+#define BYTE_ORDER BIG_ENDIAN
+#endif
+#endif
+
+#define _UINT8_T_DECLARED
+#ifndef _UINT8_T_DECLARED
+typedef        __uint8_t       uint8_t;
+#define        _UINT8_T_DECLARED
+#endif
+
+#define _UINT16_T_DECLARED
+#ifndef _UINT16_T_DECLARED
+typedef        __uint16_t      uint16_t;
+#define        _UINT16_T_DECLARED
+#endif
+#define _UINT32_T_DECLARED
+#ifndef _UINT32_T_DECLARED
+typedef        __uint32_t      uint32_t;
+#define        _UINT32_T_DECLARED
+#endif
+#define _UINT64_T_DECLARED
+#ifndef _UINT64_T_DECLARED
+typedef        __uint64_t      uint64_t;
+#define        _UINT64_T_DECLARED
+#endif
+/*
+ * General byte order swapping functions.
+ */
+#define        bswap16(x)      __bswap16(x)
+#define        bswap32(x)      __bswap32(x)
+#define        bswap64(x)      __bswap64(x)
+
+/*
+ * Host to big endian, host to little endian, big endian to host, and little
+ * endian to host byte order functions as detailed in byteorder(9).
+ */
+#if 1 //BYTE_ORDER == _LITTLE_ENDIAN
+#define __bswap16     __bswap_16
+#define __bswap32     __bswap_32
+#define        htobe16(x)      bswap16((x))
+#define        htobe32(x)      bswap32((x))
+#define        htobe64(x)      bswap64((x))
+#define        htole16(x)      ((uint16_t)(x))
+#define        htole32(x)      ((uint32_t)(x))
+#define        htole64(x)      ((uint64_t)(x))
+
+#define        be16toh(x)      bswap16((x))
+#define        be32toh(x)      bswap32((x))
+#define        be64toh(x)      bswap64((x))
+#define        le16toh(x)      ((uint16_t)(x))
+#define        le32toh(x)      ((uint32_t)(x))
+#define        le64toh(x)      ((uint64_t)(x))
+
+#ifndef htons
+#define htons htobe16
+#endif //htons
+
+#else /* _BYTE_ORDER != _LITTLE_ENDIAN */
+#define        htobe16(x)      ((uint16_t)(x))
+#define        htobe32(x)      ((uint32_t)(x))
+#define        htobe64(x)      ((uint64_t)(x))
+#define        htole16(x)      bswap16((x))
+#define        htole32(x)      bswap32((x))
+#define        htole64(x)      bswap64((x))
+
+#define        be16toh(x)      ((uint16_t)(x))
+#define        be32toh(x)      ((uint32_t)(x))
+#define        be64toh(x)      ((uint64_t)(x))
+#define        le16toh(x)      bswap16((x))
+#define        le32toh(x)      bswap32((x))
+#define        le64toh(x)      bswap64((x))
+#endif /* _BYTE_ORDER == _LITTLE_ENDIAN */
+
+/* Alignment-agnostic encode/decode bytestream to/from little/big endian. */
+
+static INLINE uint16_t
+be16dec(const void *pp)
+{
+       uint8_t const *p = (uint8_t const *)pp;
+
+       return ((p[0] << 8) | p[1]);
+}
+
+static INLINE uint32_t
+be32dec(const void *pp)
+{
+       uint8_t const *p = (uint8_t const *)pp;
+
+       return (((unsigned)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
+}
+
+static INLINE uint64_t
+be64dec(const void *pp)
+{
+       uint8_t const *p = (uint8_t const *)pp;
+
+       return (((uint64_t)be32dec(p) << 32) | be32dec(p + 4));
+}
+
+static INLINE uint16_t
+le16dec(const void *pp)
+{
+       uint8_t const *p = (uint8_t const *)pp;
+
+       return ((p[1] << 8) | p[0]);
+}
+
+static INLINE uint32_t
+le32dec(const void *pp)
+{
+       uint8_t const *p = (uint8_t const *)pp;
+
+       return (((unsigned)p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);
+}
+
+static INLINE uint64_t
+le64dec(const void *pp)
+{
+       uint8_t const *p = (uint8_t const *)pp;
+
+       return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p));
+}
+
+static INLINE void
+be16enc(void *pp, uint16_t u)
+{
+       uint8_t *p = (uint8_t *)pp;
+
+       p[0] = (u >> 8) & 0xff;
+       p[1] = u & 0xff;
+}
+
+static INLINE void
+be32enc(void *pp, uint32_t u)
+{
+       uint8_t *p = (uint8_t *)pp;
+
+       p[0] = (u >> 24) & 0xff;
+       p[1] = (u >> 16) & 0xff;
+       p[2] = (u >> 8) & 0xff;
+       p[3] = u & 0xff;
+}
+
+static INLINE void
+be64enc(void *pp, uint64_t u)
+{
+       uint8_t *p = (uint8_t *)pp;
+
+       be32enc(p, (uint32_t)(u >> 32));
+       be32enc(p + 4, (uint32_t)(u & 0xffffffffU));
+}
+
+static INLINE void
+le16enc(void *pp, uint16_t u)
+{
+       uint8_t *p = (uint8_t *)pp;
+
+       p[0] = u & 0xff;
+       p[1] = (u >> 8) & 0xff;
+}
+
+static INLINE void
+le32enc(void *pp, uint32_t u)
+{
+       uint8_t *p = (uint8_t *)pp;
+
+       p[0] = u & 0xff;
+       p[1] = (u >> 8) & 0xff;
+       p[2] = (u >> 16) & 0xff;
+       p[3] = (u >> 24) & 0xff;
+}
+
+static INLINE void
+le64enc(void *pp, uint64_t u)
+{
+       uint8_t *p = (uint8_t *)pp;
+
+       le32enc(p, (uint32_t)(u & 0xffffffffU));
+       le32enc(p + 4, (uint32_t)(u >> 32));
+}
+
+#endif /* _ENDIAN_H_ */
diff --git a/components/wpa_supplicant/port/include/os.h b/components/wpa_supplicant/port/include/os.h
new file mode 100644 (file)
index 0000000..e6da894
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * OS specific functions
+ * Copyright (c) 2005-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.
+ */
+
+#ifndef OS_H
+#define OS_H
+#include "esp_types.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "rom/ets_sys.h"
+#include "lwip/mem.h"
+typedef long os_time_t;
+
+/**
+ * os_sleep - Sleep (sec, usec)
+ * @sec: Number of seconds to sleep
+ * @usec: Number of microseconds to sleep
+ */
+void os_sleep(os_time_t sec, os_time_t usec);
+
+struct os_time {
+       os_time_t sec;
+       os_time_t usec;
+};
+
+/**
+ * os_get_time - Get current time (sec, usec)
+ * @t: Pointer to buffer for the time
+ * Returns: 0 on success, -1 on failure
+ */
+int os_get_time(struct os_time *t);
+
+
+/* Helper macros for handling struct os_time */
+
+#define os_time_before(a, b) \
+       ((a)->sec < (b)->sec || \
+        ((a)->sec == (b)->sec && (a)->usec < (b)->usec))
+
+#define os_time_sub(a, b, res) do { \
+       (res)->sec = (a)->sec - (b)->sec; \
+       (res)->usec = (a)->usec - (b)->usec; \
+       if ((res)->usec < 0) { \
+               (res)->sec--; \
+               (res)->usec += 1000000; \
+       } \
+} while (0)
+
+/**
+ * os_mktime - Convert broken-down time into seconds since 1970-01-01
+ * @year: Four digit year
+ * @month: Month (1 .. 12)
+ * @day: Day of month (1 .. 31)
+ * @hour: Hour (0 .. 23)
+ * @min: Minute (0 .. 59)
+ * @sec: Second (0 .. 60)
+ * @t: Buffer for returning calendar time representation (seconds since
+ * 1970-01-01 00:00:00)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Note: The result is in seconds from Epoch, i.e., in UTC, not in local time
+ * which is used by POSIX mktime().
+ */
+int os_mktime(int year, int month, int day, int hour, int min, int sec,
+             os_time_t *t);
+
+
+/**
+ * os_daemonize - Run in the background (detach from the controlling terminal)
+ * @pid_file: File name to write the process ID to or %NULL to skip this
+ * Returns: 0 on success, -1 on failure
+ */
+int os_daemonize(const char *pid_file);
+
+/**
+ * os_daemonize_terminate - Stop running in the background (remove pid file)
+ * @pid_file: File name to write the process ID to or %NULL to skip this
+ */
+void os_daemonize_terminate(const char *pid_file);
+
+/**
+ * os_get_random - Get cryptographically strong pseudo random data
+ * @buf: Buffer for pseudo random data
+ * @len: Length of the buffer
+ * Returns: 0 on success, -1 on failure
+ */
+int os_get_random(unsigned char *buf, size_t len);
+
+/**
+ * os_random - Get pseudo random value (not necessarily very strong)
+ * Returns: Pseudo random value
+ */
+unsigned long os_random(void);
+
+/**
+ * os_rel2abs_path - Get an absolute path for a file
+ * @rel_path: Relative path to a file
+ * Returns: Absolute path for the file or %NULL on failure
+ *
+ * This function tries to convert a relative path of a file to an absolute path
+ * in order for the file to be found even if current working directory has
+ * changed. The returned value is allocated and caller is responsible for
+ * freeing it. It is acceptable to just return the same path in an allocated
+ * buffer, e.g., return strdup(rel_path). This function is only used to find
+ * configuration files when os_daemonize() may have changed the current working
+ * directory and relative path would be pointing to a different location.
+ */
+char * os_rel2abs_path(const char *rel_path);
+
+/**
+ * os_program_init - Program initialization (called at start)
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is called when a programs starts. If there are any OS specific
+ * processing that is needed, it can be placed here. It is also acceptable to
+ * just return 0 if not special processing is needed.
+ */
+int os_program_init(void);
+
+/**
+ * os_program_deinit - Program deinitialization (called just before exit)
+ *
+ * This function is called just before a program exists. If there are any OS
+ * specific processing, e.g., freeing resourced allocated in os_program_init(),
+ * it should be done here. It is also acceptable for this function to do
+ * nothing.
+ */
+void os_program_deinit(void);
+
+/**
+ * os_setenv - Set environment variable
+ * @name: Name of the variable
+ * @value: Value to set to the variable
+ * @overwrite: Whether existing variable should be overwritten
+ * Returns: 0 on success, -1 on error
+ *
+ * This function is only used for wpa_cli action scripts. OS wrapper does not
+ * need to implement this if such functionality is not needed.
+ */
+int os_setenv(const char *name, const char *value, int overwrite);
+
+/**
+ * os_unsetenv - Delete environent variable
+ * @name: Name of the variable
+ * Returns: 0 on success, -1 on error
+ *
+ * This function is only used for wpa_cli action scripts. OS wrapper does not
+ * need to implement this if such functionality is not needed.
+ */
+int os_unsetenv(const char *name);
+
+/**
+ * os_readfile - Read a file to an allocated memory buffer
+ * @name: Name of the file to read
+ * @len: For returning the length of the allocated buffer
+ * Returns: Pointer to the allocated buffer or %NULL on failure
+ *
+ * This function allocates memory and reads the given file to this buffer. Both
+ * binary and text files can be read with this function. The caller is
+ * responsible for freeing the returned buffer with os_free().
+ */
+char * os_readfile(const char *name, size_t *len);
+
+/*
+ * The following functions are wrapper for standard ANSI C or POSIX functions.
+ * By default, they are just defined to use the standard function name and no
+ * os_*.c implementation is needed for them. This avoids extra function calls
+ * by allowing the C pre-processor take care of the function name mapping.
+ *
+ * If the target system uses a C library that does not provide these functions,
+ * build_config.h can be used to define the wrappers to use a different
+ * function name. This can be done on function-by-function basis since the
+ * defines here are only used if build_config.h does not define the os_* name.
+ * If needed, os_*.c file can be used to implement the functions that are not
+ * included in the C library on the target system. Alternatively,
+ * OS_NO_C_LIB_DEFINES can be defined to skip all defines here in which case
+ * these functions need to be implemented in os_*.c file for the target system.
+ */
+#ifndef os_malloc
+#define os_malloc(s) malloc((s))
+#endif
+#ifndef os_realloc
+#define os_realloc(p, s) realloc((p), (s))
+#endif
+#ifndef os_zalloc
+#define os_zalloc(s) calloc(1, (s))
+#endif
+#ifndef os_free
+#define os_free(p) free((p))
+#endif
+
+
+#ifndef os_strdup
+#ifdef _MSC_VER
+#define os_strdup(s) _strdup(s)
+#else
+#define os_strdup(s) strdup(s)
+#endif
+#endif
+char * ets_strdup(const char *s);
+
+#ifndef os_memcpy
+#define os_memcpy(d, s, n) memcpy((d), (s), (n))
+#endif
+#ifndef os_memmove
+#define os_memmove(d, s, n) memmove((d), (s), (n))
+#endif
+#ifndef os_memset
+#define os_memset(s, c, n) memset(s, c, n)
+#endif
+#ifndef os_memcmp
+#define os_memcmp(s1, s2, n) memcmp((s1), (s2), (n))
+#endif
+
+#ifndef os_strlen
+#define os_strlen(s) strlen(s)
+#endif
+#ifndef os_strcasecmp
+#ifdef _MSC_VER
+#define os_strcasecmp(s1, s2) _stricmp((s1), (s2))
+#else
+#define os_strcasecmp(s1, s2) strcasecmp((s1), (s2))
+#endif
+#endif
+#ifndef os_strncasecmp
+#ifdef _MSC_VER
+#define os_strncasecmp(s1, s2, n) _strnicmp((s1), (s2), (n))
+#else
+#define os_strncasecmp(s1, s2, n) strncasecmp((s1), (s2), (n))
+#endif
+#endif
+#ifndef os_strchr
+#define os_strchr(s, c) strchr((s), (c))
+#endif
+#ifndef os_strcmp
+#define os_strcmp(s1, s2) strcmp((s1), (s2))
+#endif
+#ifndef os_strncmp
+#define os_strncmp(s1, s2, n) strncmp((s1), (s2), (n))
+#endif
+#ifndef os_strncpy
+#define os_strncpy(d, s, n) strncpy((d), (s), (n))
+#endif
+#ifndef os_strrchr
+//hard cold
+#define os_strrchr(s, c)  NULL
+#endif
+#ifndef os_strstr
+#define os_strstr(h, n) strstr((h), (n))
+#endif
+
+#ifndef os_snprintf
+#ifdef _MSC_VER
+#define os_snprintf _snprintf
+#else
+#define os_snprintf vsnprintf
+#endif
+#endif
+
+/**
+ * os_strlcpy - Copy a string with size bound and NUL-termination
+ * @dest: Destination
+ * @src: Source
+ * @siz: Size of the target buffer
+ * Returns: Total length of the target string (length of src) (not including
+ * NUL-termination)
+ *
+ * This function matches in behavior with the strlcpy(3) function in OpenBSD.
+ */
+size_t os_strlcpy(char *dest, const char *src, size_t siz);
+
+
+
+#endif /* OS_H */
diff --git a/components/wpa_supplicant/src/crypto/aes-cbc.c b/components/wpa_supplicant/src/crypto/aes-cbc.c
new file mode 100644 (file)
index 0000000..0162077
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * AES-128 CBC
+ *
+ * Copyright (c) 2003-2007, 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 "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/aes.h"
+#include "crypto/aes_wrap.h"
+
+/**
+ * aes_128_cbc_encrypt - AES-128 CBC encryption
+ * @key: Encryption key
+ * @iv: Encryption IV for CBC mode (16 bytes)
+ * @data: Data to encrypt in-place
+ * @data_len: Length of data in bytes (must be divisible by 16)
+ * Returns: 0 on success, -1 on failure
+ */
+int 
+aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
+{
+       void *ctx;
+       u8 cbc[AES_BLOCK_SIZE];
+       u8 *pos = data;
+       int i, j, blocks;
+
+       ctx = aes_encrypt_init(key, 16);
+       if (ctx == NULL)
+               return -1;
+       os_memcpy(cbc, iv, AES_BLOCK_SIZE);
+
+       blocks = data_len / AES_BLOCK_SIZE;
+       for (i = 0; i < blocks; i++) {
+               for (j = 0; j < AES_BLOCK_SIZE; j++)
+                       cbc[j] ^= pos[j];
+               aes_encrypt(ctx, cbc, cbc);
+               os_memcpy(pos, cbc, AES_BLOCK_SIZE);
+               pos += AES_BLOCK_SIZE;
+       }
+       aes_encrypt_deinit(ctx);
+       return 0;
+}
+
+
+/**
+ * aes_128_cbc_decrypt - AES-128 CBC decryption
+ * @key: Decryption key
+ * @iv: Decryption IV for CBC mode (16 bytes)
+ * @data: Data to decrypt in-place
+ * @data_len: Length of data in bytes (must be divisible by 16)
+ * Returns: 0 on success, -1 on failure
+ */
+int 
+aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
+{
+       void *ctx;
+       u8 cbc[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE];
+       u8 *pos = data;
+       int i, j, blocks;
+
+       ctx = aes_decrypt_init(key, 16);
+       if (ctx == NULL)
+               return -1;
+       os_memcpy(cbc, iv, AES_BLOCK_SIZE);
+
+       blocks = data_len / AES_BLOCK_SIZE;
+       for (i = 0; i < blocks; i++) {
+               os_memcpy(tmp, pos, AES_BLOCK_SIZE);
+               aes_decrypt(ctx, pos, pos);
+               for (j = 0; j < AES_BLOCK_SIZE; j++)
+                       pos[j] ^= cbc[j];
+               os_memcpy(cbc, tmp, AES_BLOCK_SIZE);
+               pos += AES_BLOCK_SIZE;
+       }
+       aes_decrypt_deinit(ctx);
+       return 0;
+}
diff --git a/components/wpa_supplicant/src/crypto/aes-internal-dec.c b/components/wpa_supplicant/src/crypto/aes-internal-dec.c
new file mode 100644 (file)
index 0000000..46371c5
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * AES (Rijndael) cipher - decrypt
+ *
+ * Modifications to public domain implementation:
+ * - support only 128-bit keys
+ * - cleanup
+ * - use C pre-processor to make it easier to change S table access
+ * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
+ *   cost of reduced throughput (quite small difference on Pentium 4,
+ *   10-25% when using -O1 or -O2 optimization)
+ *
+ * Copyright (c) 2003-2005, 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 "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/crypto.h"
+#include "crypto/aes_i.h"
+
+
+
+//static unsigned char aes_priv_buf[AES_PRIV_SIZE];
+
+/**
+ * Expand the cipher key into the decryption key schedule.
+ *
+ * @return     the number of rounds for the given cipher key size.
+ */
+static int  rijndaelKeySetupDec(u32 rk[], const u8 cipherKey[], int keyBits)
+{
+       int Nr, i, j;
+       u32 temp;
+
+       /* expand the cipher key: */
+       Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits);
+       if (Nr < 0)
+               return Nr;
+       /* invert the order of the round keys: */
+       for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
+               temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
+               temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
+               temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
+               temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
+       }
+       /* apply the inverse MixColumn transform to all round keys but the
+        * first and the last: */
+       for (i = 1; i < Nr; i++) {
+               rk += 4;
+               for (j = 0; j < 4; j++) {
+                       rk[j] = TD0_(TE4((rk[j] >> 24)       )) ^
+                               TD1_(TE4((rk[j] >> 16) & 0xff)) ^
+                               TD2_(TE4((rk[j] >>  8) & 0xff)) ^
+                               TD3_(TE4((rk[j]      ) & 0xff));
+               }
+       }
+
+       return Nr;
+}
+
+void *  aes_decrypt_init(const u8 *key, size_t len)
+{
+       u32 *rk;
+       int res;
+       rk = os_malloc(AES_PRIV_SIZE);
+       if (rk == NULL)
+               return NULL;
+       res = rijndaelKeySetupDec(rk, key, len * 8);
+       if (res < 0) {
+               os_free(rk);
+               return NULL;
+       }
+       rk[AES_PRIV_NR_POS] = res;
+       return rk;
+}
+
+static void  rijndaelDecrypt(const u32 rk[/*44*/], int Nr, const u8 ct[16],
+                           u8 pt[16])
+{
+       u32 s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+       int r;
+#endif /* ?FULL_UNROLL */
+
+       /*
+        * map byte array block to cipher state
+        * and add initial round key:
+        */
+       s0 = GETU32(ct     ) ^ rk[0];
+       s1 = GETU32(ct +  4) ^ rk[1];
+       s2 = GETU32(ct +  8) ^ rk[2];
+       s3 = GETU32(ct + 12) ^ rk[3];
+
+#define ROUND(i,d,s) \
+d##0 = TD0(s##0) ^ TD1(s##3) ^ TD2(s##2) ^ TD3(s##1) ^ rk[4 * i]; \
+d##1 = TD0(s##1) ^ TD1(s##0) ^ TD2(s##3) ^ TD3(s##2) ^ rk[4 * i + 1]; \
+d##2 = TD0(s##2) ^ TD1(s##1) ^ TD2(s##0) ^ TD3(s##3) ^ rk[4 * i + 2]; \
+d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3]
+
+#ifdef FULL_UNROLL
+
+       ROUND(1,t,s);
+       ROUND(2,s,t);
+       ROUND(3,t,s);
+       ROUND(4,s,t);
+       ROUND(5,t,s);
+       ROUND(6,s,t);
+       ROUND(7,t,s);
+       ROUND(8,s,t);
+       ROUND(9,t,s);
+       if (Nr > 10) {
+               ROUND(10,s,t);
+               ROUND(11,t,s);
+               if (Nr > 12) {
+                       ROUND(12,s,t);
+                       ROUND(13,t,s);
+               }
+       }
+
+       rk += Nr << 2;
+
+#else  /* !FULL_UNROLL */
+
+       /* Nr - 1 full rounds: */
+       r = Nr >> 1;
+       for (;;) {
+               ROUND(1,t,s);
+               rk += 8;
+               if (--r == 0)
+                       break;
+               ROUND(0,s,t);
+       }
+
+#endif /* ?FULL_UNROLL */
+
+#undef ROUND
+
+       /*
+        * apply last round and
+        * map cipher state to byte array block:
+        */
+       s0 = TD41(t0) ^ TD42(t3) ^ TD43(t2) ^ TD44(t1) ^ rk[0];
+       PUTU32(pt     , s0);
+       s1 = TD41(t1) ^ TD42(t0) ^ TD43(t3) ^ TD44(t2) ^ rk[1];
+       PUTU32(pt +  4, s1);
+       s2 = TD41(t2) ^ TD42(t1) ^ TD43(t0) ^ TD44(t3) ^ rk[2];
+       PUTU32(pt +  8, s2);
+       s3 = TD41(t3) ^ TD42(t2) ^ TD43(t1) ^ TD44(t0) ^ rk[3];
+       PUTU32(pt + 12, s3);
+}
+
+void  aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
+{
+       u32 *rk = ctx;
+       rijndaelDecrypt(ctx, rk[AES_PRIV_NR_POS], crypt, plain);
+}
+
+
+void  aes_decrypt_deinit(void *ctx)
+{
+       os_memset(ctx, 0, AES_PRIV_SIZE);
+       os_free(ctx);
+}
diff --git a/components/wpa_supplicant/src/crypto/aes-internal-enc.c b/components/wpa_supplicant/src/crypto/aes-internal-enc.c
new file mode 100644 (file)
index 0000000..7b1080c
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * AES (Rijndael) cipher - encrypt
+ *
+ * Modifications to public domain implementation:
+ * - support only 128-bit keys
+ * - cleanup
+ * - use C pre-processor to make it easier to change S table access
+ * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
+ *   cost of reduced throughput (quite small difference on Pentium 4,
+ *   10-25% when using -O1 or -O2 optimization)
+ *
+ * Copyright (c) 2003-2005, 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 "crypto/includes.h"
+#include "crypto/common.h"
+#include "crypto/crypto.h"
+#include "crypto/aes_i.h"
+
+#include "os.h"
+
+void  rijndaelEncrypt(const u32 rk[], int Nr, const u8 pt[16], u8 ct[16])
+{
+       u32 s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+       int r;
+#endif /* ?FULL_UNROLL */
+
+       /*
+        * map byte array block to cipher state
+        * and add initial round key:
+        */
+       s0 = GETU32(pt     ) ^ rk[0];
+       s1 = GETU32(pt +  4) ^ rk[1];
+       s2 = GETU32(pt +  8) ^ rk[2];
+       s3 = GETU32(pt + 12) ^ rk[3];
+
+#define ROUND(i,d,s) \
+d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \
+d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \
+d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \
+d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]
+
+#ifdef FULL_UNROLL
+
+       ROUND(1,t,s);
+       ROUND(2,s,t);
+       ROUND(3,t,s);
+       ROUND(4,s,t);
+       ROUND(5,t,s);
+       ROUND(6,s,t);
+       ROUND(7,t,s);
+       ROUND(8,s,t);
+       ROUND(9,t,s);
+       if (Nr > 10) {
+               ROUND(10,s,t);
+               ROUND(11,t,s);
+               if (Nr > 12) {
+                       ROUND(12,s,t);
+                       ROUND(13,t,s);
+               }
+       }
+
+       rk += Nr << 2;
+
+#else  /* !FULL_UNROLL */
+
+       /* Nr - 1 full rounds: */
+       r = Nr >> 1;
+       for (;;) {
+               ROUND(1,t,s);
+               rk += 8;
+               if (--r == 0)
+                       break;
+               ROUND(0,s,t);
+       }
+
+#endif /* ?FULL_UNROLL */
+
+#undef ROUND
+
+       /*
+        * apply last round and
+        * map cipher state to byte array block:
+        */
+       s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0];
+       PUTU32(ct     , s0);
+       s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1];
+       PUTU32(ct +  4, s1);
+       s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2];
+       PUTU32(ct +  8, s2);
+       s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3];
+       PUTU32(ct + 12, s3);
+}
+
+
+void *  aes_encrypt_init(const u8 *key, size_t len)
+{
+       u32 *rk;
+       int res;
+       rk = os_malloc(AES_PRIV_SIZE);
+       if (rk == NULL)
+               return NULL;
+       res = rijndaelKeySetupEnc(rk, key, len * 8);
+       if (res < 0) {
+               os_free(rk);
+               return NULL;
+       }
+       rk[AES_PRIV_NR_POS] = res;
+       return rk;
+}
+
+
+void  aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
+{
+       u32 *rk = ctx;
+       rijndaelEncrypt(ctx, rk[AES_PRIV_NR_POS], plain, crypt);
+}
+
+
+void  aes_encrypt_deinit(void *ctx)
+{
+       os_memset(ctx, 0, AES_PRIV_SIZE);
+       os_free(ctx);
+}
diff --git a/components/wpa_supplicant/src/crypto/aes-internal.c b/components/wpa_supplicant/src/crypto/aes-internal.c
new file mode 100644 (file)
index 0000000..9618239
--- /dev/null
@@ -0,0 +1,854 @@
+/*
+ * AES (Rijndael) cipher
+ *
+ * Modifications to public domain implementation:
+ * - support only 128-bit keys
+ * - cleanup
+ * - use C pre-processor to make it easier to change S table access
+ * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
+ *   cost of reduced throughput (quite small difference on Pentium 4,
+ *   10-25% when using -O1 or -O2 optimization)
+ *
+ * Copyright (c) 2003-2005, 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 "crypto/includes.h"
+
+//#include "wpa/common.h"
+#include "crypto/common.h"
+#include "crypto/crypto.h"
+#include "crypto/aes_i.h"
+
+/*
+ * rijndael-alg-fst.c
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define AES_SMALL_TABLES
+
+/*
+Te0[x] = S [x].[02, 01, 01, 03];
+Te1[x] = S [x].[03, 02, 01, 01];
+Te2[x] = S [x].[01, 03, 02, 01];
+Te3[x] = S [x].[01, 01, 03, 02];
+Te4[x] = S [x].[01, 01, 01, 01];
+
+Td0[x] = Si[x].[0e, 09, 0d, 0b];
+Td1[x] = Si[x].[0b, 0e, 09, 0d];
+Td2[x] = Si[x].[0d, 0b, 0e, 09];
+Td3[x] = Si[x].[09, 0d, 0b, 0e];
+Td4[x] = Si[x].[01, 01, 01, 01];
+*/
+
+const u32 Te0[256] /* ICACHE_RODATA_ATTR */ = {
+    0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+    0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+    0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+    0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+    0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+    0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+    0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+    0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+    0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+    0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+    0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+    0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+    0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+    0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+    0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+    0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+    0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+    0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+    0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+    0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+    0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+    0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+    0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+    0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+    0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+    0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+    0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+    0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+    0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+    0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+    0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+    0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+    0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+    0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+    0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+    0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+    0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+    0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+    0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+    0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+    0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+    0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+    0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+    0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+    0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+    0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+    0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+    0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+    0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+    0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+    0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+    0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+    0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+    0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+    0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+    0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+    0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+    0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+    0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+    0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+    0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+    0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+    0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+    0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+};
+#ifndef AES_SMALL_TABLES
+const u32 Te1[256] /* ICACHE_RODATA_ATTR */ = {
+    0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
+    0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
+    0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
+    0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
+    0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
+    0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
+    0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
+    0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
+    0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
+    0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
+    0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
+    0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
+    0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
+    0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
+    0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
+    0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
+    0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
+    0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
+    0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
+    0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
+    0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
+    0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
+    0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
+    0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
+    0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
+    0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
+    0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
+    0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
+    0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
+    0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
+    0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
+    0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
+    0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
+    0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
+    0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
+    0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
+    0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
+    0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
+    0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
+    0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
+    0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
+    0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
+    0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
+    0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
+    0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
+    0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
+    0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
+    0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
+    0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
+    0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
+    0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
+    0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
+    0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
+    0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
+    0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
+    0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
+    0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
+    0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
+    0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
+    0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
+    0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
+    0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
+    0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
+    0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
+};
+const u32 Te2[256] /* ICACHE_RODATA_ATTR */ = {
+    0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
+    0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
+    0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
+    0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
+    0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
+    0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
+    0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
+    0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
+    0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
+    0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
+    0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
+    0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
+    0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
+    0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
+    0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
+    0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
+    0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
+    0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
+    0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
+    0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
+    0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
+    0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
+    0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
+    0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
+    0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
+    0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
+    0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
+    0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
+    0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
+    0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
+    0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
+    0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
+    0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
+    0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
+    0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
+    0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
+    0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
+    0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
+    0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
+    0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
+    0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
+    0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
+    0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
+    0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
+    0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
+    0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
+    0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
+    0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
+    0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
+    0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
+    0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
+    0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
+    0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
+    0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
+    0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
+    0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
+    0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
+    0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
+    0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
+    0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
+    0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
+    0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
+    0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
+    0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
+};
+const u32 Te3[256] /* ICACHE_RODATA_ATTR */ = {
+
+    0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
+    0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
+    0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
+    0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
+    0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
+    0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
+    0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
+    0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
+    0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
+    0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
+    0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
+    0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
+    0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
+    0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
+    0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
+    0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
+    0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
+    0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
+    0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
+    0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
+    0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
+    0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
+    0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
+    0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
+    0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
+    0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
+    0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
+    0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
+    0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
+    0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
+    0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
+    0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
+    0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
+    0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
+    0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
+    0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
+    0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
+    0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
+    0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
+    0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
+    0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
+    0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
+    0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
+    0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
+    0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
+    0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
+    0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
+    0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
+    0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
+    0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
+    0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
+    0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
+    0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
+    0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
+    0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
+    0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
+    0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
+    0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
+    0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
+    0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
+    0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
+    0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
+    0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
+    0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
+};
+const u32 Te4[256] /* ICACHE_RODATA_ATTR */ = {
+    0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
+    0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
+    0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
+    0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
+    0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
+    0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
+    0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
+    0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
+    0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
+    0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
+    0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
+    0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
+    0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
+    0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
+    0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
+    0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
+    0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
+    0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
+    0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
+    0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
+    0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
+    0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
+    0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
+    0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
+    0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
+    0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
+    0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
+    0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
+    0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
+    0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
+    0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
+    0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
+    0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
+    0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
+    0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
+    0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
+    0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
+    0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
+    0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
+    0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
+    0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
+    0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
+    0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
+    0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
+    0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
+    0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
+    0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
+    0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
+    0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
+    0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
+    0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
+    0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
+    0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
+    0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
+    0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
+    0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
+    0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
+    0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
+    0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
+    0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
+    0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
+    0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
+    0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
+    0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
+};
+#endif /* AES_SMALL_TABLES */
+const u32 Td0[256] /* ICACHE_RODATA_ATTR */ = {
+    0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
+    0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
+    0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
+    0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
+    0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
+    0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
+    0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
+    0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
+    0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
+    0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
+    0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
+    0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
+    0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
+    0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
+    0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
+    0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
+    0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
+    0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
+    0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
+    0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
+    0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
+    0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
+    0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
+    0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
+    0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
+    0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
+    0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
+    0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
+    0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
+    0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
+    0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
+    0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
+    0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
+    0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
+    0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
+    0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
+    0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
+    0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
+    0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
+    0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
+    0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
+    0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
+    0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
+    0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
+    0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
+    0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
+    0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
+    0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
+    0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
+    0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
+    0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
+    0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
+    0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
+    0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
+    0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
+    0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
+    0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
+    0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
+    0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
+    0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
+    0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
+    0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
+    0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
+    0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
+};
+#ifndef AES_SMALL_TABLES
+const u32 Td1[256] /* ICACHE_RODATA_ATTR */ = {
+    0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
+    0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
+    0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
+    0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
+    0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
+    0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
+    0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
+    0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
+    0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
+    0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
+    0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
+    0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
+    0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
+    0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
+    0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
+    0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
+    0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
+    0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
+    0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
+    0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
+    0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
+    0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
+    0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
+    0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
+    0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
+    0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
+    0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
+    0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
+    0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
+    0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
+    0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
+    0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
+    0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
+    0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
+    0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
+    0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
+    0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
+    0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
+    0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
+    0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
+    0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
+    0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
+    0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
+    0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
+    0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
+    0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
+    0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
+    0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
+    0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
+    0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
+    0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
+    0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
+    0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
+    0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
+    0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
+    0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
+    0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
+    0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
+    0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
+    0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
+    0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
+    0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
+    0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
+    0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
+};
+const u32 Td2[256] /* ICACHE_RODATA_ATTR */ = {
+    0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
+    0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
+    0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
+    0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
+    0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
+    0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
+    0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
+    0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
+    0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
+    0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
+    0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
+    0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
+    0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
+    0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
+    0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
+    0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
+    0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
+    0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
+    0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
+    0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
+
+    0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
+    0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
+    0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
+    0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
+    0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
+    0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
+    0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
+    0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
+    0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
+    0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
+    0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
+    0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
+    0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
+    0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
+    0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
+    0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
+    0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
+    0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
+    0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
+    0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
+    0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
+    0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
+    0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
+    0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
+    0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
+    0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
+    0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
+    0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
+    0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
+    0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
+    0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
+    0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
+    0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
+    0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
+    0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
+    0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
+    0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
+    0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
+    0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
+    0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
+    0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
+    0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
+    0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
+    0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
+};
+const u32 Td3[256] /* ICACHE_RODATA_ATTR */ = {
+    0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
+    0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
+    0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
+    0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
+    0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
+    0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
+    0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
+    0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
+    0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
+    0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
+    0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
+    0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
+    0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
+    0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
+    0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
+    0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
+    0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
+    0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
+    0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
+    0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
+    0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
+    0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
+    0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
+    0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
+    0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
+    0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
+    0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
+    0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
+    0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
+    0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
+    0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
+    0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
+    0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
+    0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
+    0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
+    0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
+    0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
+    0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
+    0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
+    0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
+    0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
+    0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
+    0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
+    0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
+    0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
+    0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
+    0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
+    0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
+    0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
+    0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
+    0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
+    0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
+    0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
+    0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
+    0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
+    0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
+    0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
+    0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
+    0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
+    0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
+    0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
+    0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
+    0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
+    0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
+};
+const u32 Td4[256] /* ICACHE_RODATA_ATTR */ = {
+    0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
+    0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
+    0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
+    0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
+    0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
+    0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
+    0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
+    0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
+    0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
+    0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
+    0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
+    0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
+    0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
+    0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
+    0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
+    0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
+    0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
+    0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
+    0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
+    0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
+    0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
+    0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
+    0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
+    0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
+    0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
+    0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
+    0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
+    0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
+    0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
+    0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
+    0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
+    0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
+    0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
+    0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
+    0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
+    0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
+    0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
+    0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
+    0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
+    0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
+    0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
+    0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
+    0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
+    0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
+    0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
+    0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
+    0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
+    0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
+    0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
+    0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
+    0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
+    0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
+    0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
+    0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
+    0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
+    0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
+    0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
+    0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
+    0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
+    0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
+    0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
+    0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
+    0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
+    0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
+};
+const u32 rcon[] /* ICACHE_RODATA_ATTR */ = {
+       0x01000000, 0x02000000, 0x04000000, 0x08000000,
+       0x10000000, 0x20000000, 0x40000000, 0x80000000,
+       0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+#else /* AES_SMALL_TABLES */
+const u8 Td4s[256] /* ICACHE_RODATA_ATTR */ = {
+    0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U,
+    0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU,
+    0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U,
+    0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU,
+    0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU,
+    0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU,
+    0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U,
+    0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U,
+    0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U,
+    0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U,
+    0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU,
+    0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U,
+    0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU,
+    0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U,
+    0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U,
+    0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU,
+    0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU,
+    0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U,
+    0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U,
+    0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU,
+    0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U,
+    0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,
+    0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U,
+    0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U,
+    0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U,
+    0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU,
+    0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU,
+    0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU,
+    0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U,
+    0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U,
+    0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U,
+    0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,
+};
+const u8 rcons[] /* ICACHE_RODATA_ATTR */ = {
+       0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
+       /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+#endif /* AES_SMALL_TABLES */
+/**
+ * Expand the cipher key into the encryption key schedule.
+ *
+ * @return     the number of rounds for the given cipher key size.
+ */
+int rijndaelKeySetupEnc(u32 rk[], const u8 cipherKey[], int keyBits)
+{
+       int i;
+       u32 temp;
+
+       rk[0] = GETU32(cipherKey     );
+       rk[1] = GETU32(cipherKey +  4);
+       rk[2] = GETU32(cipherKey +  8);
+       rk[3] = GETU32(cipherKey + 12);
+
+       if (keyBits == 128) {
+               for (i = 0; i < 10; i++) {
+                       temp  = rk[3];
+                       rk[4] = rk[0] ^ TE421(temp) ^ TE432(temp) ^
+                               TE443(temp) ^ TE414(temp) ^ RCON(i);
+                       rk[5] = rk[1] ^ rk[4];
+                       rk[6] = rk[2] ^ rk[5];
+                       rk[7] = rk[3] ^ rk[6];
+                       rk += 4;
+               }
+               return 10;
+       }
+
+       rk[4] = GETU32(cipherKey + 16);
+       rk[5] = GETU32(cipherKey + 20);
+
+       if (keyBits == 192) {
+               for (i = 0; i < 8; i++) {
+                       temp  = rk[5];
+                       rk[6] = rk[0] ^ TE421(temp) ^ TE432(temp) ^
+                               TE443(temp) ^ TE414(temp) ^ RCON(i);
+                       rk[7] = rk[1] ^ rk[6];
+                       rk[8] = rk[2] ^ rk[7];
+                       rk[9] = rk[3] ^ rk[8];
+                       if (i == 7)
+                               return 12;
+                       rk[10] = rk[4] ^ rk[9];
+                       rk[11] = rk[5] ^ rk[10];
+                       rk += 6;
+               }
+       }
+
+       rk[6] = GETU32(cipherKey + 24);
+       rk[7] = GETU32(cipherKey + 28);
+
+       if (keyBits == 256) {
+               for (i = 0; i < 7; i++) {
+                       temp  = rk[7];
+                       rk[8] = rk[0] ^ TE421(temp) ^ TE432(temp) ^
+                               TE443(temp) ^ TE414(temp) ^ RCON(i);
+                       rk[9] = rk[1] ^ rk[8];
+                       rk[10] = rk[2] ^ rk[9];
+                       rk[11] = rk[3] ^ rk[10];
+                       if (i == 6)
+                               return 14;
+                       temp  = rk[11];
+                       rk[12] = rk[4] ^ TE411(temp) ^ TE422(temp) ^
+                               TE433(temp) ^ TE444(temp);
+                       rk[13] = rk[5] ^ rk[12];
+                       rk[14] = rk[6] ^ rk[13];
+                       rk[15] = rk[7] ^ rk[14];
+                       rk += 8;
+               }
+       }
+
+       return -1;
+}
diff --git a/components/wpa_supplicant/src/crypto/aes-unwrap.c b/components/wpa_supplicant/src/crypto/aes-unwrap.c
new file mode 100644 (file)
index 0000000..4a92f1c
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * AES key unwrap (128-bit KEK, RFC3394)
+ *
+ * Copyright (c) 2003-2007, 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 "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/aes.h"
+#include "crypto/aes_wrap.h"
+
+/**
+ * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * @kek: Key encryption key (KEK)
+ * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
+ * bytes
+ * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits
+ * @plain: Plaintext key, n * 64 bits
+ * Returns: 0 on success, -1 on failure (e.g., integrity verification failed)
+ */
+int 
+aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain)
+{
+       u8 a[8], *r, b[16];
+       int i, j;
+       void *ctx;
+
+       /* 1) Initialize variables. */
+       os_memcpy(a, cipher, 8);
+       r = plain;
+       os_memcpy(r, cipher + 8, 8 * n);
+
+       ctx = aes_decrypt_init(kek, 16);
+       if (ctx == NULL)
+               return -1;
+
+       /* 2) Compute intermediate values.
+        * For j = 5 to 0
+        *     For i = n to 1
+        *         B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
+        *         A = MSB(64, B)
+        *         R[i] = LSB(64, B)
+        */
+       for (j = 5; j >= 0; j--) {
+               r = plain + (n - 1) * 8;
+               for (i = n; i >= 1; i--) {
+                       os_memcpy(b, a, 8);
+                       b[7] ^= n * j + i;
+
+                       os_memcpy(b + 8, r, 8);
+                       aes_decrypt(ctx, b, b);
+                       os_memcpy(a, b, 8);
+                       os_memcpy(r, b + 8, 8);
+                       r -= 8;
+               }
+       }
+       aes_decrypt_deinit(ctx);
+
+       /* 3) Output results.
+        *
+        * These are already in @plain due to the location of temporary
+        * variables. Just verify that the IV matches with the expected value.
+        */
+       for (i = 0; i < 8; i++) {
+               if (a[i] != 0xa6)
+                       return -1;
+       }
+
+       return 0;
+}
diff --git a/components/wpa_supplicant/src/crypto/aes-wrap.c b/components/wpa_supplicant/src/crypto/aes-wrap.c
new file mode 100644 (file)
index 0000000..388dd97
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ *
+ * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/aes.h"
+#include "crypto/aes_wrap.h"
+
+/**
+ * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * @kek: 16-octet Key encryption key (KEK)
+ * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
+ * bytes
+ * @plain: Plaintext key to be wrapped, n * 64 bits
+ * @cipher: Wrapped key, (n + 1) * 64 bits
+ * Returns: 0 on success, -1 on failure
+ */
+int  aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher)
+{
+       u8 *a, *r, b[16];
+       int i, j;
+       void *ctx;
+
+       a = cipher;
+       r = cipher + 8;
+
+       /* 1) Initialize variables. */
+       os_memset(a, 0xa6, 8);
+       os_memcpy(r, plain, 8 * n);
+
+       ctx = aes_encrypt_init(kek, 16);
+       if (ctx == NULL)
+               return -1;
+
+       /* 2) Calculate intermediate values.
+        * For j = 0 to 5
+        *     For i=1 to n
+        *         B = AES(K, A | R[i])
+        *         A = MSB(64, B) ^ t where t = (n*j)+i
+        *         R[i] = LSB(64, B)
+        */
+       for (j = 0; j <= 5; j++) {
+               r = cipher + 8;
+               for (i = 1; i <= n; i++) {
+                       os_memcpy(b, a, 8);
+                       os_memcpy(b + 8, r, 8);
+                       aes_encrypt(ctx, b, b);
+                       os_memcpy(a, b, 8);
+                       a[7] ^= n * j + i;
+                       os_memcpy(r, b + 8, 8);
+                       r += 8;
+               }
+       }
+       aes_encrypt_deinit(ctx);
+
+       /* 3) Output the results.
+        *
+        * These are already in @cipher due to the location of temporary
+        * variables.
+        */
+
+       return 0;
+}
diff --git a/components/wpa_supplicant/src/crypto/bignum.c b/components/wpa_supplicant/src/crypto/bignum.c
new file mode 100644 (file)
index 0000000..7b8446c
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Big number math
+ * Copyright (c) 2006, 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 "crypto/includes.h"
+#include "crypto/common.h"
+#include "wpa/wpabuf.h"
+#include "wpa/wpa_debug.h"
+#include "bignum.h"
+
+#define CONFIG_INTERNAL_LIBTOMMATH 
+#ifdef CONFIG_INTERNAL_LIBTOMMATH
+#include "libtommath.h"
+#else /* CONFIG_INTERNAL_LIBTOMMATH */
+#include <tommath.h>
+#endif /* CONFIG_INTERNAL_LIBTOMMATH */
+
+
+/*
+ * The current version is just a wrapper for LibTomMath library, so
+ * struct bignum is just typecast to mp_int.
+ */
+
+/**
+ * bignum_init - Allocate memory for bignum
+ * Returns: Pointer to allocated bignum or %NULL on failure
+ */
+struct bignum * 
+bignum_init(void)
+{
+       struct bignum *n = (struct bignum *)os_zalloc(sizeof(mp_int));
+       if (n == NULL)
+               return NULL;
+       if (mp_init((mp_int *) n) != MP_OKAY) {
+               os_free(n);
+               n = NULL;
+       }
+       return n;
+}
+
+
+/**
+ * bignum_deinit - Free bignum
+ * @n: Bignum from bignum_init()
+ */
+void 
+bignum_deinit(struct bignum *n)
+{
+       if (n) {
+               mp_clear((mp_int *) n);
+               os_free(n);
+       }
+}
+
+
+/**
+ * bignum_get_unsigned_bin - Get length of bignum as an unsigned binary buffer
+ * @n: Bignum from bignum_init()
+ * Returns: Length of n if written to a binary buffer
+ */
+size_t 
+bignum_get_unsigned_bin_len(struct bignum *n)
+{
+       return mp_unsigned_bin_size((mp_int *) n);
+}
+
+
+/**
+ * bignum_get_unsigned_bin - Set binary buffer to unsigned bignum
+ * @n: Bignum from bignum_init()
+ * @buf: Buffer for the binary number
+ * @len: Length of the buffer, can be %NULL if buffer is known to be long
+ * enough. Set to used buffer length on success if not %NULL.
+ * Returns: 0 on success, -1 on failure
+ */
+int 
+bignum_get_unsigned_bin(const struct bignum *n, u8 *buf, size_t *len)
+{
+       size_t need = mp_unsigned_bin_size((mp_int *) n);
+       if (len && need > *len) {
+               *len = need;
+               return -1;
+       }
+       if (mp_to_unsigned_bin((mp_int *) n, buf) != MP_OKAY) {
+               wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
+               return -1;
+       }
+       if (len)
+               *len = need;
+       return 0;
+}
+
+
+/**
+ * bignum_set_unsigned_bin - Set bignum based on unsigned binary buffer
+ * @n: Bignum from bignum_init(); to be set to the given value
+ * @buf: Buffer with unsigned binary value
+ * @len: Length of buf in octets
+ * Returns: 0 on success, -1 on failure
+ */
+int 
+bignum_set_unsigned_bin(struct bignum *n, const u8 *buf, size_t len)
+{
+       if (mp_read_unsigned_bin((mp_int *) n, (u8 *) buf, len) != MP_OKAY) {
+               wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
+               return -1;
+       }
+       return 0;
+}
+
+
+/**
+ * bignum_cmp - Signed comparison
+ * @a: Bignum from bignum_init()
+ * @b: Bignum from bignum_init()
+ * Returns: 0 on success, -1 on failure
+ */
+int 
+bignum_cmp(const struct bignum *a, const struct bignum *b)
+{
+       return mp_cmp((mp_int *) a, (mp_int *) b);
+}
+
+
+/**
+ * bignum_cmd_d - Compare bignum to standard integer
+ * @a: Bignum from bignum_init()
+ * @b: Small integer
+ * Returns: 0 on success, -1 on failure
+ */
+int 
+bignum_cmp_d(const struct bignum *a, unsigned long b)
+{
+       return mp_cmp_d((mp_int *) a, b);
+}
+
+
+/**
+ * bignum_add - c = a + b
+ * @a: Bignum from bignum_init()
+ * @b: Bignum from bignum_init()
+ * @c: Bignum from bignum_init(); used to store the result of a + b
+ * Returns: 0 on success, -1 on failure
+ */
+int 
+bignum_add(const struct bignum *a, const struct bignum *b,
+              struct bignum *c)
+{
+       if (mp_add((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) {
+               wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
+               return -1;
+       }
+       return 0;
+}
+
+
+/**
+ * bignum_sub - c = a - b
+ * @a: Bignum from bignum_init()
+ * @b: Bignum from bignum_init()
+ * @c: Bignum from bignum_init(); used to store the result of a - b
+ * Returns: 0 on success, -1 on failure
+ */
+int 
+bignum_sub(const struct bignum *a, const struct bignum *b,
+              struct bignum *c)
+{
+       if (mp_sub((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) {
+               wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
+               return -1;
+       }
+       return 0;
+}
+
+
+/**
+ * bignum_mul - c = a * b
+ * @a: Bignum from bignum_init()
+ * @b: Bignum from bignum_init()
+ * @c: Bignum from bignum_init(); used to store the result of a * b
+ * Returns: 0 on success, -1 on failure
+ */
+int 
+bignum_mul(const struct bignum *a, const struct bignum *b,
+              struct bignum *c)
+{
+       if (mp_mul((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) {
+               wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
+               return -1;
+       }
+       return 0;
+}
+
+
+/**
+ * bignum_mulmod - d = a * b (mod c)
+ * @a: Bignum from bignum_init()
+ * @b: Bignum from bignum_init()
+ * @c: Bignum from bignum_init(); modulus
+ * @d: Bignum from bignum_init(); used to store the result of a * b (mod c)
+ * Returns: 0 on success, -1 on failure
+ */
+int 
+bignum_mulmod(const struct bignum *a, const struct bignum *b,
+                 const struct bignum *c, struct bignum *d)
+{
+       if (mp_mulmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d)
+           != MP_OKAY) {
+               wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
+               return -1;
+       }
+       return 0;
+}
+
+
+/**
+ * bignum_exptmod - Modular exponentiation: d = a^b (mod c)
+ * @a: Bignum from bignum_init(); base
+ * @b: Bignum from bignum_init(); exponent
+ * @c: Bignum from bignum_init(); modulus
+ * @d: Bignum from bignum_init(); used to store the result of a^b (mod c)
+ * Returns: 0 on success, -1 on failure
+ */
+int 
+bignum_exptmod(const struct bignum *a, const struct bignum *b,
+                  const struct bignum *c, struct bignum *d)
+{
+       if (mp_exptmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d)
+           != MP_OKAY) {
+               wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
+               return -1;
+       }
+       return 0;
+}
diff --git a/components/wpa_supplicant/src/crypto/bignum.h b/components/wpa_supplicant/src/crypto/bignum.h
new file mode 100644 (file)
index 0000000..f25e267
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Big number math
+ * Copyright (c) 2006, 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.
+ */
+
+#ifndef BIGNUM_H
+#define BIGNUM_H
+
+struct bignum;
+
+struct bignum * bignum_init(void);
+void bignum_deinit(struct bignum *n);
+size_t bignum_get_unsigned_bin_len(struct bignum *n);
+int bignum_get_unsigned_bin(const struct bignum *n, u8 *buf, size_t *len);
+int bignum_set_unsigned_bin(struct bignum *n, const u8 *buf, size_t len);
+int bignum_cmp(const struct bignum *a, const struct bignum *b);
+int bignum_cmp_d(const struct bignum *a, unsigned long b);
+int bignum_add(const struct bignum *a, const struct bignum *b,
+              struct bignum *c);
+int bignum_sub(const struct bignum *a, const struct bignum *b,
+              struct bignum *c);
+int bignum_mul(const struct bignum *a, const struct bignum *b,
+              struct bignum *c);
+int bignum_mulmod(const struct bignum *a, const struct bignum *b,
+                 const struct bignum *c, struct bignum *d);
+int bignum_exptmod(const struct bignum *a, const struct bignum *b,
+                  const struct bignum *c, struct bignum *d);
+
+#endif /* BIGNUM_H */
diff --git a/components/wpa_supplicant/src/crypto/crypto_internal-cipher.c b/components/wpa_supplicant/src/crypto/crypto_internal-cipher.c
new file mode 100644 (file)
index 0000000..7d89795
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * Crypto wrapper for internal crypto implementation - Cipher wrappers
+ * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+//#include "wpa/includes.h"
+
+//#include "wpa/common.h"
+#include "crypto/common.h"
+#include "crypto/crypto.h"
+#include "crypto/aes.h"
+#if defined(CONFIG_DES) || defined(CONFIG_DES3)
+#include "crypto/des_i.h"
+#endif
+
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
+
+struct crypto_cipher {
+       enum crypto_cipher_alg alg;
+       union {
+               struct {
+                       size_t used_bytes;
+                       u8 key[16];
+                       size_t keylen;
+               } rc4;
+               struct {
+                       u8 cbc[32];
+                       void *ctx_enc;
+                       void *ctx_dec;
+               } aes;
+#ifdef CONFIG_DES3
+               struct {
+                       struct des3_key_s key;
+                       u8 cbc[8];
+               } des3;
+#endif
+#ifdef CONFIG_DES
+               struct {
+                       u32 ek[32];
+                       u32 dk[32];
+                       u8 cbc[8];
+               } des;
+#endif
+       } u;
+};
+
+
+struct crypto_cipher *  crypto_cipher_init(enum crypto_cipher_alg alg,
+                                         const u8 *iv, const u8 *key,
+                                         size_t key_len)
+{
+       struct crypto_cipher *ctx;
+
+       ctx = (struct crypto_cipher *)os_zalloc(sizeof(*ctx));
+       if (ctx == NULL)
+               return NULL;
+
+       ctx->alg = alg;
+
+       switch (alg) {
+       case CRYPTO_CIPHER_ALG_RC4:
+               if (key_len > sizeof(ctx->u.rc4.key)) {
+                       os_free(ctx);
+                       return NULL;
+               }
+               ctx->u.rc4.keylen = key_len;
+               os_memcpy(ctx->u.rc4.key, key, key_len);
+               break;
+       case CRYPTO_CIPHER_ALG_AES:
+               ctx->u.aes.ctx_enc = aes_encrypt_init(key, key_len);
+               if (ctx->u.aes.ctx_enc == NULL) {
+                       os_free(ctx);
+                       return NULL;
+               }
+               ctx->u.aes.ctx_dec = aes_decrypt_init(key, key_len);
+               if (ctx->u.aes.ctx_dec == NULL) {
+                       aes_encrypt_deinit(ctx->u.aes.ctx_enc);
+                       os_free(ctx);
+                       return NULL;
+               }
+               os_memcpy(ctx->u.aes.cbc, iv, AES_BLOCK_SIZE);
+               break;
+#ifdef CONFIG_DES3
+       case CRYPTO_CIPHER_ALG_3DES:
+               if (key_len != 24) {
+                       os_free(ctx);
+                       return NULL;
+               }
+               des3_key_setup(key, &ctx->u.des3.key);
+               os_memcpy(ctx->u.des3.cbc, iv, 8);
+               break;
+#endif
+#ifdef CONFIG_DES
+       case CRYPTO_CIPHER_ALG_DES:
+               if (key_len != 8) {
+                       os_free(ctx);
+                       return NULL;
+               }
+               des_key_setup(key, ctx->u.des.ek, ctx->u.des.dk);
+               os_memcpy(ctx->u.des.cbc, iv, 8);
+               break;
+#endif
+       default:
+               os_free(ctx);
+               return NULL;
+       }
+
+       return ctx;
+}
+
+
+int  crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
+                         u8 *crypt, size_t len)
+{
+       size_t i, j, blocks;
+
+       switch (ctx->alg) {
+       case CRYPTO_CIPHER_ALG_RC4:
+               if (plain != crypt)
+                       os_memcpy(crypt, plain, len);
+               rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
+                        ctx->u.rc4.used_bytes, crypt, len);
+               ctx->u.rc4.used_bytes += len;
+               break;
+       case CRYPTO_CIPHER_ALG_AES:
+               if (len % AES_BLOCK_SIZE)
+                       return -1;
+               blocks = len / AES_BLOCK_SIZE;
+               for (i = 0; i < blocks; i++) {
+                       for (j = 0; j < AES_BLOCK_SIZE; j++)
+                               ctx->u.aes.cbc[j] ^= plain[j];
+                       aes_encrypt(ctx->u.aes.ctx_enc, ctx->u.aes.cbc,
+                                   ctx->u.aes.cbc);
+                       os_memcpy(crypt, ctx->u.aes.cbc, AES_BLOCK_SIZE);
+                       plain += AES_BLOCK_SIZE;
+                       crypt += AES_BLOCK_SIZE;
+               }
+               break;
+#ifdef CONFIG_DES3
+       case CRYPTO_CIPHER_ALG_3DES:
+               if (len % 8)
+                       return -1;
+               blocks = len / 8;
+               for (i = 0; i < blocks; i++) {
+                       for (j = 0; j < 8; j++)
+                               ctx->u.des3.cbc[j] ^= plain[j];
+                       des3_encrypt(ctx->u.des3.cbc, &ctx->u.des3.key,
+                                    ctx->u.des3.cbc);
+                       os_memcpy(crypt, ctx->u.des3.cbc, 8);
+                       plain += 8;
+                       crypt += 8;
+               }
+               break;
+#endif
+#ifdef CONFIG_DES
+       case CRYPTO_CIPHER_ALG_DES:
+               if (len % 8)
+                       return -1;
+               blocks = len / 8;
+               for (i = 0; i < blocks; i++) {
+                       for (j = 0; j < 8; j++)
+                               ctx->u.des3.cbc[j] ^= plain[j];
+                       des_block_encrypt(ctx->u.des.cbc, ctx->u.des.ek,
+                                         ctx->u.des.cbc);
+                       os_memcpy(crypt, ctx->u.des.cbc, 8);
+                       plain += 8;
+                       crypt += 8;
+               }
+               break;
+#endif
+       default:
+               return -1;
+       }
+
+       return 0;
+}
+
+
+int  crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
+                         u8 *plain, size_t len)
+{
+       size_t i, j, blocks;
+       u8 tmp[32];
+
+       switch (ctx->alg) {
+       case CRYPTO_CIPHER_ALG_RC4:
+               if (plain != crypt)
+                       os_memcpy(plain, crypt, len);
+               rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
+                        ctx->u.rc4.used_bytes, plain, len);
+               ctx->u.rc4.used_bytes += len;
+               break;
+       case CRYPTO_CIPHER_ALG_AES:
+               if (len % AES_BLOCK_SIZE)
+                       return -1;
+               blocks = len / AES_BLOCK_SIZE;
+               for (i = 0; i < blocks; i++) {
+                       os_memcpy(tmp, crypt, AES_BLOCK_SIZE);
+                       aes_decrypt(ctx->u.aes.ctx_dec, crypt, plain);
+                       for (j = 0; j < AES_BLOCK_SIZE; j++)
+                               plain[j] ^= ctx->u.aes.cbc[j];
+                       os_memcpy(ctx->u.aes.cbc, tmp, AES_BLOCK_SIZE);
+                       plain += AES_BLOCK_SIZE;
+                       crypt += AES_BLOCK_SIZE;
+               }
+               break;
+#ifdef CONFIG_DES3
+       case CRYPTO_CIPHER_ALG_3DES:
+               if (len % 8)
+                       return -1;
+               blocks = len / 8;
+               for (i = 0; i < blocks; i++) {
+                       os_memcpy(tmp, crypt, 8);
+                       des3_decrypt(crypt, &ctx->u.des3.key, plain);
+                       for (j = 0; j < 8; j++)
+                               plain[j] ^= ctx->u.des3.cbc[j];
+                       os_memcpy(ctx->u.des3.cbc, tmp, 8);
+                       plain += 8;
+                       crypt += 8;
+               }
+               break;
+#endif
+#ifdef CONFIG_DES
+       case CRYPTO_CIPHER_ALG_DES:
+               if (len % 8)
+                       return -1;
+               blocks = len / 8;
+               for (i = 0; i < blocks; i++) {
+                       os_memcpy(tmp, crypt, 8);
+                       des_block_decrypt(crypt, ctx->u.des.dk, plain);
+                       for (j = 0; j < 8; j++)
+                               plain[j] ^= ctx->u.des.cbc[j];
+                       os_memcpy(ctx->u.des.cbc, tmp, 8);
+                       plain += 8;
+                       crypt += 8;
+               }
+               break;
+#endif
+       default:
+               return -1;
+       }
+
+       return 0;
+}
+
+
+void  crypto_cipher_deinit(struct crypto_cipher *ctx)
+{
+       switch (ctx->alg) {
+       case CRYPTO_CIPHER_ALG_AES:
+               aes_encrypt_deinit(ctx->u.aes.ctx_enc);
+               aes_decrypt_deinit(ctx->u.aes.ctx_dec);
+               break;
+#ifdef CONFIG_DES3
+       case CRYPTO_CIPHER_ALG_3DES:
+               break;
+#endif
+       default:
+               break;
+       }
+       os_free(ctx);
+}
diff --git a/components/wpa_supplicant/src/crypto/crypto_internal-modexp.c b/components/wpa_supplicant/src/crypto/crypto_internal-modexp.c
new file mode 100644 (file)
index 0000000..ea97857
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Crypto wrapper for internal crypto implementation - modexp
+ * 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 "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "bignum.h"
+#include "crypto/crypto.h"
+
+
+int 
+crypto_mod_exp(const u8 *base, size_t base_len,
+                  const u8 *power, size_t power_len,
+                  const u8 *modulus, size_t modulus_len,
+                  u8 *result, size_t *result_len)
+{
+       struct bignum *bn_base, *bn_exp, *bn_modulus, *bn_result;
+       int ret = -1;
+
+       bn_base = bignum_init();
+       bn_exp = bignum_init();
+       bn_modulus = bignum_init();
+       bn_result = bignum_init();
+
+       if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL ||
+           bn_result == NULL)
+               goto error;
+
+       if (bignum_set_unsigned_bin(bn_base, base, base_len) < 0 ||
+           bignum_set_unsigned_bin(bn_exp, power, power_len) < 0 ||
+           bignum_set_unsigned_bin(bn_modulus, modulus, modulus_len) < 0)
+               goto error;
+
+       if (bignum_exptmod(bn_base, bn_exp, bn_modulus, bn_result) < 0)
+               goto error;
+
+       ret = bignum_get_unsigned_bin(bn_result, result, result_len);
+
+error:
+       bignum_deinit(bn_base);
+       bignum_deinit(bn_exp);
+       bignum_deinit(bn_modulus);
+       bignum_deinit(bn_result);
+       return ret;
+}
diff --git a/components/wpa_supplicant/src/crypto/crypto_internal-rsa.c b/components/wpa_supplicant/src/crypto/crypto_internal-rsa.c
new file mode 100644 (file)
index 0000000..19934f0
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Crypto wrapper for internal crypto implementation - RSA parts
+ * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "crypto/common.h"
+#include "crypto/crypto.h"
+
+#include "wpa/includes.h"
+#include "wpa/common.h"
+#include "wpa/wpa_debug.h"
+
+#include "wpa2/tls/rsa.h"
+#include "wpa2/tls/pkcs1.h"
+#include "wpa2/tls/pkcs8.h"
+
+/* Dummy structures; these are just typecast to struct crypto_rsa_key */
+struct crypto_public_key;
+struct crypto_private_key;
+
+
+struct crypto_public_key *  crypto_public_key_import(const u8 *key, size_t len)
+{
+       return (struct crypto_public_key *)
+               crypto_rsa_import_public_key(key, len);
+}
+
+
+struct crypto_private_key *  crypto_private_key_import(const u8 *key,
+                                                     size_t len,
+                                                     const char *passwd)
+{
+       struct crypto_private_key *res;
+
+       /* First, check for possible PKCS #8 encoding */
+       res = pkcs8_key_import(key, len);
+       if (res)
+               return res;
+
+       if (passwd) {
+               /* Try to parse as encrypted PKCS #8 */
+               res = pkcs8_enc_key_import(key, len, passwd);
+               if (res)
+                       return res;
+       }
+
+       /* Not PKCS#8, so try to import PKCS #1 encoded RSA private key */
+       wpa_printf(MSG_DEBUG, "Trying to parse PKCS #1 encoded RSA private "
+                  "key");
+       return (struct crypto_private_key *)
+               crypto_rsa_import_private_key(key, len);
+}
+
+
+struct crypto_public_key *  crypto_public_key_from_cert(const u8 *buf,
+                                                      size_t len)
+{
+       /* No X.509 support in crypto_internal.c */
+       return NULL;
+}
+
+
+int  crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
+                                       const u8 *in, size_t inlen,
+                                       u8 *out, size_t *outlen)
+{
+       return pkcs1_encrypt(2, (struct crypto_rsa_key *) key,
+                            0, in, inlen, out, outlen);
+}
+
+
+int  crypto_private_key_decrypt_pkcs1_v15(struct crypto_private_key *key,
+                                        const u8 *in, size_t inlen,
+                                        u8 *out, size_t *outlen)
+{
+       return pkcs1_v15_private_key_decrypt((struct crypto_rsa_key *) key,
+                                            in, inlen, out, outlen);
+}
+
+
+int  crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
+                                 const u8 *in, size_t inlen,
+                                 u8 *out, size_t *outlen)
+{
+       return pkcs1_encrypt(1, (struct crypto_rsa_key *) key,
+                            1, in, inlen, out, outlen);
+}
+
+
+void  crypto_public_key_free(struct crypto_public_key *key)
+{
+       crypto_rsa_free((struct crypto_rsa_key *) key);
+}
+
+
+void  crypto_private_key_free(struct crypto_private_key *key)
+{
+       crypto_rsa_free((struct crypto_rsa_key *) key);
+}
+
+
+int  crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key,
+                                   const u8 *crypt, size_t crypt_len,
+                                   u8 *plain, size_t *plain_len)
+{
+       return pkcs1_decrypt_public_key((struct crypto_rsa_key *) key,
+                                       crypt, crypt_len, plain, plain_len);
+}
diff --git a/components/wpa_supplicant/src/crypto/crypto_internal.c b/components/wpa_supplicant/src/crypto/crypto_internal.c
new file mode 100644 (file)
index 0000000..d8d59df
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * Crypto wrapper for internal crypto implementation
+ * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "crypto/includes.h"
+#include "crypto/common.h"
+//#include "wpa/common.h"
+#include "crypto/crypto.h"
+//#include "crypto/sha256_i.h"
+#include "crypto/sha1_i.h"
+#include "crypto/md5_i.h"
+
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
+
+struct crypto_hash {
+       enum crypto_hash_alg alg;
+       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;
+};
+
+
+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[32];
+       size_t i;
+
+       ctx = (struct crypto_hash *)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;
+#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);
+                       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);
+               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);
+               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);
+               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;
+       }
+
+       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;
+#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;
+       }
+}
+
+
+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;
+#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;
+                       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;
+#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);
+
+       return 0;
+}
+
+
+int  crypto_global_init(void)
+{
+       return 0;
+}
+
+
+void  crypto_global_deinit(void)
+{
+}
diff --git a/components/wpa_supplicant/src/crypto/dh_group5.c b/components/wpa_supplicant/src/crypto/dh_group5.c
new file mode 100644 (file)
index 0000000..710f5c7
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Diffie-Hellman group 5 operations
+ * Copyright (c) 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 "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/dh_groups.h"
+#include "crypto/dh_group5.h"
+
+
+void * 
+dh5_init(struct wpabuf **priv, struct wpabuf **publ)
+{
+       *publ = dh_init(dh_groups_get(5), priv);
+       if (*publ == 0)
+               return NULL;
+       return (void *) 1;
+}
+
+
+struct wpabuf * 
+dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
+                                 const struct wpabuf *own_private)
+{
+       return dh_derive_shared(peer_public, own_private, dh_groups_get(5));
+}
+
+
+void 
+dh5_free(void *ctx)
+{
+}
diff --git a/components/wpa_supplicant/src/crypto/dh_groups.c b/components/wpa_supplicant/src/crypto/dh_groups.c
new file mode 100644 (file)
index 0000000..6ec9a36
--- /dev/null
@@ -0,0 +1,641 @@
+/*
+ * Diffie-Hellman groups
+ * Copyright (c) 2007, 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 "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/crypto.h"
+#include "crypto/random.h"
+#include "crypto/dh_groups.h"
+#include "wpa/wpabuf.h"
+#include "wpa/wpa_debug.h"
+
+extern int crypto_mod_exp(const u8 *base, size_t base_len,
+                  const u8 *power, size_t power_len,
+                  const u8 *modulus, size_t modulus_len,
+                  u8 *result, size_t *result_len);
+
+#ifdef ALL_DH_GROUPS
+
+/* RFC 4306, B.1. Group 1 - 768 Bit MODP
+ * Generator: 2
+ * Prime: 2^768 - 2 ^704 - 1 + 2^64 * { [2^638 pi] + 149686 }
+ */
+static const u8 dh_group1_generator[1] = { 0x02 };
+static const u8 dh_group1_prime[96] = {
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+       0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+       0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+       0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+       0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+       0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+       0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+       0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+       0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+       0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x3A, 0x36, 0x20,
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* RFC 4306, B.2. Group 2 - 1024 Bit MODP
+ * Generator: 2
+ * Prime: 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }
+ */
+static const u8 dh_group2_generator[1] = { 0x02 };
+static const u8 dh_group2_prime[128] = {
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+       0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+       0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+       0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+       0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+       0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+       0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+       0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+       0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+       0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+       0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+       0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+       0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+       0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+#endif /* ALL_DH_GROUPS */
+
+/* RFC 3526, 2. Group 5 - 1536 Bit MODP
+ * Generator: 2
+ * Prime: 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 }
+ */
+static const u8 dh_group5_generator[1] = { 0x02 };
+static const u8 dh_group5_prime[192] = {
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+       0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+       0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+       0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+       0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+       0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+       0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+       0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+       0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+       0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+       0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+       0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+       0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+       0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+       0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+       0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
+       0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+       0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
+       0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+       0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+       0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+       0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27,
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+#ifdef ALL_DH_GROUPS
+
+/* RFC 3526, 3. Group 14 - 2048 Bit MODP
+ * Generator: 2
+ * Prime: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }
+ */
+static const u8 dh_group14_generator[1] = { 0x02 };
+static const u8 dh_group14_prime[256] = {
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+       0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+       0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+       0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+       0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+       0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+       0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+       0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+       0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+       0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+       0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+       0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+       0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+       0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+       0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+       0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
+       0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+       0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
+       0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+       0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+       0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+       0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
+       0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+       0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
+       0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
+       0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+       0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
+       0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
+       0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+       0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68,
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* RFC 3526, 4. Group 15 - 3072 Bit MODP
+ * Generator: 2
+ * Prime: 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 }
+ */
+static const u8 dh_group15_generator[1] = { 0x02 };
+static const u8 dh_group15_prime[384] = {
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+       0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+       0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+       0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+       0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+       0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+       0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+       0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+       0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+       0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+       0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+       0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+       0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+       0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+       0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+       0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
+       0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+       0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
+       0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+       0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+       0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+       0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
+       0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+       0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
+       0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
+       0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+       0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
+       0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
+       0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+       0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
+       0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
+       0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+       0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
+       0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
+       0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+       0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
+       0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
+       0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+       0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
+       0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
+       0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+       0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
+       0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
+       0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+       0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
+       0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA,
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* RFC 3526, 5. Group 16 - 4096 Bit MODP
+ * Generator: 2
+ * Prime: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 }
+ */
+static const u8 dh_group16_generator[1] = { 0x02 };
+static const u8 dh_group16_prime[512] = {
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+       0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+       0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+       0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+       0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+       0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+       0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+       0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+       0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+       0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+       0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+       0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+       0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+       0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+       0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+       0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
+       0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+       0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
+       0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+       0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+       0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+       0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
+       0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+       0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
+       0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
+       0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+       0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
+       0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
+       0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+       0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
+       0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
+       0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+       0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
+       0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
+       0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+       0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
+       0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
+       0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+       0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
+       0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
+       0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+       0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
+       0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
+       0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+       0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
+       0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
+       0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
+       0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
+       0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
+       0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
+       0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
+       0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
+       0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
+       0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
+       0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
+       0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
+       0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
+       0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
+       0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
+       0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
+       0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
+       0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* RFC 3526, 6. Group 17 - 6144 Bit MODP
+ * Generator: 2
+ * Prime: 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 }
+ */
+static const u8 dh_group17_generator[1] = { 0x02 };
+static const u8 dh_group17_prime[768] = {
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+       0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+       0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+       0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+       0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+       0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+       0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+       0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+       0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+       0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+       0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+       0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+       0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+       0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+       0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+       0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
+       0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+       0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
+       0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+       0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+       0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+       0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
+       0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+       0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
+       0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
+       0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+       0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
+       0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
+       0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+       0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
+       0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
+       0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+       0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
+       0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
+       0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+       0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
+       0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
+       0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+       0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
+       0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
+       0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+       0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
+       0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
+       0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+       0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
+       0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
+       0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
+       0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
+       0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
+       0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
+       0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
+       0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
+       0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
+       0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
+       0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
+       0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
+       0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
+       0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
+       0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
+       0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
+       0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
+       0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92,
+       0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26,
+       0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE,
+       0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
+       0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E,
+       0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE,
+       0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31,
+       0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18,
+       0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED,
+       0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
+       0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B,
+       0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42,
+       0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF,
+       0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC,
+       0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03,
+       0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
+       0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82,
+       0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E,
+       0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3,
+       0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE,
+       0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5,
+       0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
+       0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8,
+       0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0,
+       0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28,
+       0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76,
+       0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0,
+       0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
+       0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32,
+       0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68,
+       0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE,
+       0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6,
+       0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xCC, 0x40, 0x24,
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* RFC 3526, 7. Group 18 - 8192 Bit MODP
+ * Generator: 2
+ * Prime: 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 }
+ */
+static const u8 dh_group18_generator[1] = { 0x02 };
+static const u8 dh_group18_prime[1024] = {
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+       0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+       0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+       0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+       0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+       0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+       0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+       0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+       0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+       0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+       0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+       0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+       0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+       0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+       0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+       0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
+       0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+       0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
+       0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+       0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+       0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+       0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
+       0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+       0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
+       0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
+       0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+       0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
+       0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
+       0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+       0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
+       0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
+       0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+       0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
+       0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
+       0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+       0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
+       0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
+       0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+       0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
+       0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
+       0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+       0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
+       0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
+       0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+       0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
+       0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
+       0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
+       0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
+       0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
+       0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
+       0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
+       0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
+       0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
+       0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
+       0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
+       0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
+       0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
+       0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
+       0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
+       0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
+       0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
+       0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92,
+       0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26,
+       0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE,
+       0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
+       0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E,
+       0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE,
+       0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31,
+       0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18,
+       0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED,
+       0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
+       0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B,
+       0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42,
+       0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF,
+       0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC,
+       0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03,
+       0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
+       0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82,
+       0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E,
+       0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3,
+       0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE,
+       0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5,
+       0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
+       0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8,
+       0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0,
+       0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28,
+       0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76,
+       0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0,
+       0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
+       0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32,
+       0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68,
+       0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE,
+       0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6,
+       0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xBE, 0x11, 0x59,
+       0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4,
+       0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C,
+       0xD8, 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA,
+       0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00,
+       0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED,
+       0x25, 0x76, 0xF6, 0x93, 0x6B, 0xA4, 0x24, 0x66,
+       0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68,
+       0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78,
+       0x23, 0x8F, 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D,
+       0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9,
+       0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07,
+       0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, 0xF0, 0xC7,
+       0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B,
+       0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD,
+       0xFA, 0x9D, 0x4B, 0x7F, 0xA2, 0xC0, 0x87, 0xE8,
+       0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A,
+       0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6,
+       0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, 0x2D,
+       0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36,
+       0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1,
+       0x64, 0xF3, 0x1C, 0xC5, 0x08, 0x46, 0x85, 0x1D,
+       0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1,
+       0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73,
+       0xFA, 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68,
+       0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92,
+       0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7,
+       0x88, 0x9A, 0x00, 0x2E, 0xD5, 0xEE, 0x38, 0x2B,
+       0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47,
+       0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA,
+       0x9E, 0x30, 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF,
+       0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71,
+       0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF,
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+#endif /* ALL_DH_GROUPS */
+
+
+#define DH_GROUP(id) \
+{ id, dh_group ## id ## _generator, sizeof(dh_group ## id ## _generator), \
+dh_group ## id ## _prime, sizeof(dh_group ## id ## _prime) }
+               
+
+static struct dh_group dh_groups[] = {
+       DH_GROUP(5),
+#ifdef ALL_DH_GROUPS
+       DH_GROUP(1),
+       DH_GROUP(2),
+       DH_GROUP(14),
+       DH_GROUP(15),
+       DH_GROUP(16),
+       DH_GROUP(17),
+       DH_GROUP(18)
+#endif /* ALL_DH_GROUPS */
+};
+
+#define NUM_DH_GROUPS (sizeof(dh_groups) / sizeof(dh_groups[0]))
+
+
+const struct dh_group * 
+dh_groups_get(int id)
+{
+       size_t i;
+
+       for (i = 0; i < NUM_DH_GROUPS; i++) {
+               if (dh_groups[i].id == id)
+                       return &dh_groups[i];
+       }
+       return NULL;
+}
+
+/**
+ * dh_init - Initialize Diffie-Hellman handshake
+ * @dh: Selected Diffie-Hellman group
+ * @priv: Pointer for returning Diffie-Hellman private key
+ * Returns: Diffie-Hellman public value
+ */
+struct wpabuf * 
+dh_init(const struct dh_group *dh, struct wpabuf **priv)
+{
+       struct wpabuf *pv;
+       size_t pv_len;
+
+       if (dh == NULL)
+               return NULL;
+
+       wpabuf_free(*priv);
+       *priv = wpabuf_alloc(dh->prime_len);
+       if (*priv == NULL)
+               return NULL;
+
+       if (random_get_bytes(wpabuf_put(*priv, dh->prime_len), dh->prime_len))
+       {
+               wpabuf_free(*priv);
+               *priv = NULL;
+               return NULL;
+       }
+
+       if (os_memcmp(wpabuf_head(*priv), dh->prime, dh->prime_len) > 0) {
+               /* Make sure private value is smaller than prime */
+               *(wpabuf_mhead_u8(*priv)) = 0;
+       }
+       wpa_hexdump_buf_key(MSG_DEBUG, "DH: private value", *priv);
+
+       pv_len = dh->prime_len;
+       pv = wpabuf_alloc(pv_len);
+       if (pv == NULL)
+               return NULL;
+       if (crypto_mod_exp(dh->generator, dh->generator_len,
+                          wpabuf_head(*priv), wpabuf_len(*priv),
+                          dh->prime, dh->prime_len, wpabuf_mhead(pv),
+                          &pv_len) < 0) {
+               wpabuf_free(pv);
+               wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed");
+               return NULL;
+       }
+       wpabuf_put(pv, pv_len);
+       wpa_hexdump_buf(MSG_DEBUG, "DH: public value", pv);
+
+       return pv;
+}
+
+
+/**
+ * dh_derive_shared - Derive shared Diffie-Hellman key
+ * @peer_public: Diffie-Hellman public value from peer
+ * @own_private: Diffie-Hellman private key from dh_init()
+ * @dh: Selected Diffie-Hellman group
+ * Returns: Diffie-Hellman shared key
+ */
+struct wpabuf * 
+dh_derive_shared(const struct wpabuf *peer_public,
+                                const struct wpabuf *own_private,
+                                const struct dh_group *dh)
+{
+       struct wpabuf *shared;
+       size_t shared_len;
+
+       if (dh == NULL || peer_public == NULL || own_private == NULL)
+               return NULL;
+
+       shared_len = dh->prime_len;
+       shared = wpabuf_alloc(shared_len);
+       if (shared == NULL)
+               return NULL;
+       if (crypto_mod_exp(wpabuf_head(peer_public), wpabuf_len(peer_public),
+                          wpabuf_head(own_private), wpabuf_len(own_private),
+                          dh->prime, dh->prime_len,
+                          wpabuf_mhead(shared), &shared_len) < 0) {
+               wpabuf_free(shared);
+               wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed");
+               return NULL;
+       }
+       wpabuf_put(shared, shared_len);
+       wpa_hexdump_buf_key(MSG_DEBUG, "DH: shared key", shared);
+
+       return shared;
+}
diff --git a/components/wpa_supplicant/src/crypto/libtommath.h b/components/wpa_supplicant/src/crypto/libtommath.h
new file mode 100644 (file)
index 0000000..31f9706
--- /dev/null
@@ -0,0 +1,3440 @@
+/*
+ * Minimal code for RSA support from LibTomMath 0.41
+ * http://libtom.org/
+ * http://libtom.org/files/ltm-0.41.tar.bz2
+ * This library was released in public domain by Tom St Denis.
+ *
+ * The combination in this file may not use all of the optimized algorithms
+ * from LibTomMath and may be considerable slower than the LibTomMath with its
+ * default settings. The main purpose of having this version here is to make it
+ * easier to build bignum.c wrapper without having to install and build an
+ * external library.
+ *
+ * If CONFIG_INTERNAL_LIBTOMMATH is defined, bignum.c includes this
+ * libtommath.c file instead of using the external LibTomMath library.
+ */
+//#include "c_types.h"
+#include "os.h"
+#include "stdarg.h"
+
+
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
+#define BN_MP_INVMOD_C
+#define BN_S_MP_EXPTMOD_C /* Note: #undef in tommath_superclass.h; this would
+                          * require BN_MP_EXPTMOD_FAST_C instead */
+#define BN_S_MP_MUL_DIGS_C
+#define BN_MP_INVMOD_SLOW_C
+#define BN_S_MP_SQR_C
+#define BN_S_MP_MUL_HIGH_DIGS_C /* Note: #undef in tommath_superclass.h; this
+                                * would require other than mp_reduce */
+
+#ifdef LTM_FAST
+
+/* Use faster div at the cost of about 1 kB */
+#define BN_MP_MUL_D_C
+
+/* Include faster exptmod (Montgomery) at the cost of about 2.5 kB in code */
+#define BN_MP_EXPTMOD_FAST_C
+#define BN_MP_MONTGOMERY_SETUP_C
+#define BN_FAST_MP_MONTGOMERY_REDUCE_C
+#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+#define BN_MP_MUL_2_C
+
+/* Include faster sqr at the cost of about 0.5 kB in code */
+#define BN_FAST_S_MP_SQR_C
+
+#else /* LTM_FAST */
+
+#define BN_MP_DIV_SMALL
+#define BN_MP_INIT_MULTI_C
+#define BN_MP_CLEAR_MULTI_C
+#define BN_MP_ABS_C
+#endif /* LTM_FAST */
+
+/* Current uses do not require support for negative exponent in exptmod, so we
+ * can save about 1.5 kB in leaving out invmod. */
+#define LTM_NO_NEG_EXP
+
+/* from tommath.h */
+
+#ifndef MIN
+   #define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+#ifndef MAX
+   #define MAX(x,y) ((x)>(y)?(x):(y))
+#endif
+
+#define  OPT_CAST(x) (x *)
+
+typedef unsigned long mp_digit;
+typedef u64 mp_word;
+
+#define DIGIT_BIT          28
+#define MP_28BIT
+
+
+#define XMALLOC  os_malloc
+#define XFREE    os_free
+#define XREALLOC os_realloc
+
+
+#define MP_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
+
+#define MP_LT        -1   /* less than */
+#define MP_EQ         0   /* equal to */
+#define MP_GT         1   /* greater than */
+
+#define MP_ZPOS       0   /* positive integer */
+#define MP_NEG        1   /* negative */
+
+#define MP_OKAY       0   /* ok result */
+#define MP_MEM        -2  /* out of mem */
+#define MP_VAL        -3  /* invalid input */
+
+#define MP_YES        1   /* yes response */
+#define MP_NO         0   /* no response */
+
+typedef int           mp_err;
+
+/* define this to use lower memory usage routines (exptmods mostly) */
+#define MP_LOW_MEM
+
+/* default precision */
+#ifndef MP_PREC
+   #ifndef MP_LOW_MEM
+      #define MP_PREC                 32     /* default digits of precision */
+   #else
+      #define MP_PREC                 8      /* default digits of precision */
+   #endif   
+#endif
+
+/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
+#define MP_WARRAY               (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))
+
+/* the infamous mp_int structure */
+typedef struct  {
+    int used, alloc, sign;
+    mp_digit *dp;
+} mp_int;
+
+
+/* ---> Basic Manipulations <--- */
+#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
+#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
+#define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
+
+
+/* prototypes for copied functions */
+#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
+static int s_mp_exptmod(mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode);
+static int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
+static int s_mp_sqr(mp_int * a, mp_int * b);
+static int s_mp_mul_high_digs(mp_int * a, mp_int * b, mp_int * c, int digs);
+
+static int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
+
+#ifdef BN_MP_INIT_MULTI_C
+static int mp_init_multi(mp_int *mp, ...);
+#endif
+#ifdef BN_MP_CLEAR_MULTI_C
+static void mp_clear_multi(mp_int *mp, ...);
+#endif
+static int mp_lshd(mp_int * a, int b);
+static void mp_set(mp_int * a, mp_digit b);
+static void mp_clamp(mp_int * a);
+static void mp_exch(mp_int * a, mp_int * b);
+static void mp_rshd(mp_int * a, int b);
+static void mp_zero(mp_int * a);
+static int mp_mod_2d(mp_int * a, int b, mp_int * c);
+static int mp_div_2d(mp_int * a, int b, mp_int * c, mp_int * d);
+static int mp_init_copy(mp_int * a, mp_int * b);
+static int mp_mul_2d(mp_int * a, int b, mp_int * c);
+#ifndef LTM_NO_NEG_EXP
+static int mp_div_2(mp_int * a, mp_int * b);
+static int mp_invmod(mp_int * a, mp_int * b, mp_int * c);
+static int mp_invmod_slow(mp_int * a, mp_int * b, mp_int * c);
+#endif /* LTM_NO_NEG_EXP */
+static int mp_copy(mp_int * a, mp_int * b);
+static int mp_count_bits(mp_int * a);
+static int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d);
+static int mp_mod(mp_int * a, mp_int * b, mp_int * c);
+static int mp_grow(mp_int * a, int size);
+static int mp_cmp_mag(mp_int * a, mp_int * b);
+#ifdef BN_MP_ABS_C
+static int mp_abs(mp_int * a, mp_int * b);
+#endif
+static int mp_sqr(mp_int * a, mp_int * b);
+static int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d);
+static int mp_reduce_2k_setup_l(mp_int *a, mp_int *d);
+static int mp_2expt(mp_int * a, int b);
+static int mp_reduce_setup(mp_int * a, mp_int * b);
+static int mp_reduce(mp_int * x, mp_int * m, mp_int * mu);
+static int mp_init_size(mp_int * a, int size);
+#ifdef BN_MP_EXPTMOD_FAST_C
+static int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode);
+#endif /* BN_MP_EXPTMOD_FAST_C */
+#ifdef BN_FAST_S_MP_SQR_C
+static int fast_s_mp_sqr (mp_int * a, mp_int * b);
+#endif /* BN_FAST_S_MP_SQR_C */
+#ifdef BN_MP_MUL_D_C
+static int mp_mul_d (mp_int * a, mp_digit b, mp_int * c);
+#endif /* BN_MP_MUL_D_C */
+
+
+
+/* functions from bn_<func name>.c */
+
+
+/* reverse an array, used for radix code */
+static void 
+bn_reverse (unsigned char *s, int len)
+{
+  int     ix, iy;
+  unsigned char t;
+
+  ix = 0;
+  iy = len - 1;
+  while (ix < iy) {
+    t     = s[ix];
+    s[ix] = s[iy];
+    s[iy] = t;
+    ++ix;
+    --iy;
+  }
+}
+
+
+/* low level addition, based on HAC pp.594, Algorithm 14.7 */
+static int 
+s_mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int *x;
+  int     olduse, res, min, max;
+
+  /* find sizes, we let |a| <= |b| which means we have to sort
+   * them.  "x" will point to the input with the most digits
+   */
+  if (a->used > b->used) {
+    min = b->used;
+    max = a->used;
+    x = a;
+  } else {
+    min = a->used;
+    max = b->used;
+    x = b;
+  }
+
+  /* init result */
+  if (c->alloc < max + 1) {
+    if ((res = mp_grow (c, max + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* get old used digit count and set new one */
+  olduse = c->used;
+  c->used = max + 1;
+
+  {
+    register mp_digit u, *tmpa, *tmpb, *tmpc;
+    register int i;
+
+    /* alias for digit pointers */
+
+    /* first input */
+    tmpa = a->dp;
+
+    /* second input */
+    tmpb = b->dp;
+
+    /* destination */
+    tmpc = c->dp;
+
+    /* zero the carry */
+    u = 0;
+    for (i = 0; i < min; i++) {
+      /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
+      *tmpc = *tmpa++ + *tmpb++ + u;
+
+      /* U = carry bit of T[i] */
+      u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+      /* take away carry bit from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* now copy higher words if any, that is in A+B 
+     * if A or B has more digits add those in 
+     */
+    if (min != max) {
+      for (; i < max; i++) {
+        /* T[i] = X[i] + U */
+        *tmpc = x->dp[i] + u;
+
+        /* U = carry bit of T[i] */
+        u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+        /* take away carry bit from T[i] */
+        *tmpc++ &= MP_MASK;
+      }
+    }
+
+    /* add carry */
+    *tmpc++ = u;
+
+    /* clear digits above oldused */
+    for (i = c->used; i < olduse; i++) {
+      *tmpc++ = 0;
+    }
+  }
+
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
+static int 
+s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     olduse, res, min, max;
+
+  /* find sizes */
+  min = b->used;
+  max = a->used;
+
+  /* init result */
+  if (c->alloc < max) {
+    if ((res = mp_grow (c, max)) != MP_OKAY) {
+      return res;
+    }
+  }
+  olduse = c->used;
+  c->used = max;
+
+  {
+    register mp_digit u, *tmpa, *tmpb, *tmpc;
+    register int i;
+
+    /* alias for digit pointers */
+    tmpa = a->dp;
+    tmpb = b->dp;
+    tmpc = c->dp;
+
+    /* set carry to zero */
+    u = 0;
+    for (i = 0; i < min; i++) {
+      /* T[i] = A[i] - B[i] - U */
+      *tmpc = *tmpa++ - *tmpb++ - u;
+
+      /* U = carry bit of T[i]
+       * Note this saves performing an AND operation since
+       * if a carry does occur it will propagate all the way to the
+       * MSB.  As a result a single shift is enough to get the carry
+       */
+      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+      /* Clear carry from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* now copy higher words if any, e.g. if A has more digits than B  */
+    for (; i < max; i++) {
+      /* T[i] = A[i] - U */
+      *tmpc = *tmpa++ - u;
+
+      /* U = carry bit of T[i] */
+      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+      /* Clear carry from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* clear digits above used (since we may not have grown result above) */
+    for (i = c->used; i < olduse; i++) {
+      *tmpc++ = 0;
+    }
+  }
+
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+/* init a new mp_int */
+static int 
+mp_init (mp_int * a)
+{
+  int i;
+
+  /* allocate memory required and clear it */
+  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC);
+  if (a->dp == NULL) {
+    return MP_MEM;
+  }
+
+  /* set the digits to zero */
+  for (i = 0; i < MP_PREC; i++) {
+      a->dp[i] = 0;
+  }
+
+  /* set the used to zero, allocated digits to the default precision
+   * and sign to positive */
+  a->used  = 0;
+  a->alloc = MP_PREC;
+  a->sign  = MP_ZPOS;
+
+  return MP_OKAY;
+}
+
+
+/* clear one (frees)  */
+static void 
+mp_clear (mp_int * a)
+{
+  int i;
+
+  /* only do anything if a hasn't been freed previously */
+  if (a->dp != NULL) {
+    /* first zero the digits */
+    for (i = 0; i < a->used; i++) {
+        a->dp[i] = 0;
+    }
+
+    /* free ram */
+    XFREE(a->dp);
+
+    /* reset members to make debugging easier */
+    a->dp    = NULL;
+    a->alloc = a->used = 0;
+    a->sign  = MP_ZPOS;
+  }
+}
+
+
+/* high level addition (handles signs) */
+static int 
+mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     sa, sb, res;
+
+  /* get sign of both inputs */
+  sa = a->sign;
+  sb = b->sign;
+
+  /* handle two cases, not four */
+  if (sa == sb) {
+    /* both positive or both negative */
+    /* add their magnitudes, copy the sign */
+    c->sign = sa;
+    res = s_mp_add (a, b, c);
+  } else {
+    /* one positive, the other negative */
+    /* subtract the one with the greater magnitude from */
+    /* the one of the lesser magnitude.  The result gets */
+    /* the sign of the one with the greater magnitude. */
+    if (mp_cmp_mag (a, b) == MP_LT) {
+      c->sign = sb;
+      res = s_mp_sub (b, a, c);
+    } else {
+      c->sign = sa;
+      res = s_mp_sub (a, b, c);
+    }
+  }
+  return res;
+}
+
+
+/* high level subtraction (handles signs) */
+static int 
+mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     sa, sb, res;
+
+  sa = a->sign;
+  sb = b->sign;
+
+  if (sa != sb) {
+    /* subtract a negative from a positive, OR */
+    /* subtract a positive from a negative. */
+    /* In either case, ADD their magnitudes, */
+    /* and use the sign of the first number. */
+    c->sign = sa;
+    res = s_mp_add (a, b, c);
+  } else {
+    /* subtract a positive from a positive, OR */
+    /* subtract a negative from a negative. */
+    /* First, take the difference between their */
+    /* magnitudes, then... */
+    if (mp_cmp_mag (a, b) != MP_LT) {
+      /* Copy the sign from the first */
+      c->sign = sa;
+      /* The first has a larger or equal magnitude */
+      res = s_mp_sub (a, b, c);
+    } else {
+      /* The result has the *opposite* sign from */
+      /* the first number. */
+      c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+      /* The second has a larger magnitude */
+      res = s_mp_sub (b, a, c);
+    }
+  }
+  return res;
+}
+
+
+/* high level multiplication (handles sign) */
+static int 
+mp_mul (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res, neg;
+  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+
+  /* use Toom-Cook? */
+#ifdef BN_MP_TOOM_MUL_C
+  if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) {
+    res = mp_toom_mul(a, b, c);
+  } else 
+#endif
+#ifdef BN_MP_KARATSUBA_MUL_C
+  /* use Karatsuba? */
+  if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) {
+    res = mp_karatsuba_mul (a, b, c);
+  } else 
+#endif
+  {
+    /* can we use the fast multiplier?
+     *
+     * The fast multiplier can be used if the output will 
+     * have less than MP_WARRAY digits and the number of 
+     * digits won't affect carry propagation
+     */
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
+    int     digs = a->used + b->used + 1;
+
+    if ((digs < MP_WARRAY) &&
+        MIN(a->used, b->used) <= 
+        (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+      res = fast_s_mp_mul_digs (a, b, c, digs);
+    } else 
+#endif
+#ifdef BN_S_MP_MUL_DIGS_C
+      res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
+#else
+#error mp_mul could fail
+      res = MP_VAL;
+#endif
+
+  }
+  c->sign = (c->used > 0) ? neg : MP_ZPOS;
+  return res;
+}
+
+
+/* d = a * b (mod c) */
+static int 
+mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  int     res;
+  mp_int  t;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_mul (a, b, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, c, d);
+  mp_clear (&t);
+  return res;
+}
+
+
+/* c = a mod b, 0 <= c < b */
+static int 
+mp_mod (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  t;
+  int     res;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+
+  if (t.sign != b->sign) {
+    res = mp_add (b, &t, c);
+  } else {
+    res = MP_OKAY;
+    mp_exch (&t, c);
+  }
+
+  mp_clear (&t);
+  return res;
+}
+
+
+/* this is a shell function that calls either the normal or Montgomery
+ * exptmod functions.  Originally the call to the montgomery code was
+ * embedded in the normal function but that wasted a lot of stack space
+ * for nothing (since 99% of the time the Montgomery code would be called)
+ */
+static int 
+mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
+{
+  int dr;
+
+  /* modulus P must be positive */
+  if (P->sign == MP_NEG) {
+     return MP_VAL;
+  }
+
+  /* if exponent X is negative we have to recurse */
+  if (X->sign == MP_NEG) {
+#ifdef LTM_NO_NEG_EXP
+        return MP_VAL;
+#else /* LTM_NO_NEG_EXP */
+#ifdef BN_MP_INVMOD_C
+     mp_int tmpG, tmpX;
+     int err;
+
+     /* first compute 1/G mod P */
+     if ((err = mp_init(&tmpG)) != MP_OKAY) {
+        return err;
+     }
+     if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
+        mp_clear(&tmpG);
+        return err;
+     }
+
+     /* now get |X| */
+     if ((err = mp_init(&tmpX)) != MP_OKAY) {
+        mp_clear(&tmpG);
+        return err;
+     }
+     if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
+        mp_clear_multi(&tmpG, &tmpX, NULL);
+        return err;
+     }
+
+     /* and now compute (1/G)**|X| instead of G**X [X < 0] */
+     err = mp_exptmod(&tmpG, &tmpX, P, Y);
+     mp_clear_multi(&tmpG, &tmpX, NULL);
+     return err;
+#else 
+#error mp_exptmod would always fail
+     /* no invmod */
+     return MP_VAL;
+#endif
+#endif /* LTM_NO_NEG_EXP */
+  }
+
+/* modified diminished radix reduction */
+#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C)
+  if (mp_reduce_is_2k_l(P) == MP_YES) {
+     return s_mp_exptmod(G, X, P, Y, 1);
+  }
+#endif
+
+#ifdef BN_MP_DR_IS_MODULUS_C
+  /* is it a DR modulus? */
+  dr = mp_dr_is_modulus(P);
+#else
+  /* default to no */
+  dr = 0;
+#endif
+
+#ifdef BN_MP_REDUCE_IS_2K_C
+  /* if not, is it a unrestricted DR modulus? */
+  if (dr == 0) {
+     dr = mp_reduce_is_2k(P) << 1;
+  }
+#endif
+    
+  /* if the modulus is odd or dr != 0 use the montgomery method */
+#ifdef BN_MP_EXPTMOD_FAST_C
+  if (mp_isodd (P) == 1 || dr !=  0) {
+    return mp_exptmod_fast (G, X, P, Y, dr);
+  } else {
+#endif
+#ifdef BN_S_MP_EXPTMOD_C
+    /* otherwise use the generic Barrett reduction technique */
+    return s_mp_exptmod (G, X, P, Y, 0);
+#else
+#error mp_exptmod could fail
+    /* no exptmod for evens */
+    return MP_VAL;
+#endif
+#ifdef BN_MP_EXPTMOD_FAST_C
+  }
+#endif
+}
+
+
+/* compare two ints (signed)*/
+static int 
+mp_cmp (mp_int * a, mp_int * b)
+{
+  /* compare based on sign */
+  if (a->sign != b->sign) {
+     if (a->sign == MP_NEG) {
+        return MP_LT;
+     } else {
+        return MP_GT;
+     }
+  }
+  
+  /* compare digits */
+  if (a->sign == MP_NEG) {
+     /* if negative compare opposite direction */
+     return mp_cmp_mag(b, a);
+  } else {
+     return mp_cmp_mag(a, b);
+  }
+}
+
+
+/* compare a digit */
+static int 
+mp_cmp_d(mp_int * a, mp_digit b)
+{
+  /* compare based on sign */
+  if (a->sign == MP_NEG) {
+    return MP_LT;
+  }
+
+  /* compare based on magnitude */
+  if (a->used > 1) {
+    return MP_GT;
+  }
+
+  /* compare the only digit of a to b */
+  if (a->dp[0] > b) {
+    return MP_GT;
+  } else if (a->dp[0] < b) {
+    return MP_LT;
+  } else {
+    return MP_EQ;
+  }
+}
+
+
+#ifndef LTM_NO_NEG_EXP
+/* hac 14.61, pp608 */
+static int 
+mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+  /* b cannot be negative */
+  if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+    return MP_VAL;
+  }
+
+#ifdef BN_FAST_MP_INVMOD_C
+  /* if the modulus is odd we can use a faster routine instead */
+  if (mp_isodd (b) == 1) {
+    return fast_mp_invmod (a, b, c);
+  }
+#endif
+
+#ifdef BN_MP_INVMOD_SLOW_C
+  return mp_invmod_slow(a, b, c);
+#endif
+
+#ifndef BN_FAST_MP_INVMOD_C
+#ifndef BN_MP_INVMOD_SLOW_C
+#error mp_invmod would always fail
+#endif
+#endif
+  return MP_VAL;
+}
+#endif /* LTM_NO_NEG_EXP */
+
+
+/* get the size for an unsigned equivalent */
+static int 
+mp_unsigned_bin_size (mp_int * a)
+{
+  int     size = mp_count_bits (a);
+  return (size / 8 + ((size & 7) != 0 ? 1 : 0));
+}
+
+
+#ifndef LTM_NO_NEG_EXP
+/* hac 14.61, pp608 */
+static int 
+mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  x, y, u, v, A, B, C, D;
+  int     res;
+
+  /* b cannot be negative */
+  if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+    return MP_VAL;
+  }
+
+  /* init temps */
+  if ((res = mp_init_multi(&x, &y, &u, &v, 
+                           &A, &B, &C, &D, NULL)) != MP_OKAY) {
+     return res;
+  }
+
+  /* x = a, y = b */
+  if ((res = mp_mod(a, b, &x)) != MP_OKAY) {
+      goto LBL_ERR;
+  }
+  if ((res = mp_copy (b, &y)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+
+  /* 2. [modified] if x,y are both even then return an error! */
+  if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) {
+    res = MP_VAL;
+    goto LBL_ERR;
+  }
+
+  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  mp_set (&A, 1);
+  mp_set (&D, 1);
+
+top:
+  /* 4.  while u is even do */
+  while (mp_iseven (&u) == 1) {
+    /* 4.1 u = u/2 */
+    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    /* 4.2 if A or B is odd then */
+    if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) {
+      /* A = (A+y)/2, B = (B-x)/2 */
+      if ((res = mp_add (&A, &y, &A)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+    }
+    /* A = A/2, B = B/2 */
+    if ((res = mp_div_2 (&A, &A)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* 5.  while v is even do */
+  while (mp_iseven (&v) == 1) {
+    /* 5.1 v = v/2 */
+    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    /* 5.2 if C or D is odd then */
+    if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) {
+      /* C = (C+y)/2, D = (D-x)/2 */
+      if ((res = mp_add (&C, &y, &C)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+    }
+    /* C = C/2, D = D/2 */
+    if ((res = mp_div_2 (&C, &C)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* 6.  if u >= v then */
+  if (mp_cmp (&u, &v) != MP_LT) {
+    /* u = u - v, A = A - C, B = B - D */
+    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  } else {
+    /* v - v - u, C = C - A, D = D - B */
+    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* if not zero goto step 4 */
+  if (mp_iszero (&u) == 0)
+    goto top;
+
+  /* now a = C, b = D, gcd == g*v */
+
+  /* if v != 1 then there is no inverse */
+  if (mp_cmp_d (&v, 1) != MP_EQ) {
+    res = MP_VAL;
+    goto LBL_ERR;
+  }
+
+  /* if its too low */
+  while (mp_cmp_d(&C, 0) == MP_LT) {
+      if ((res = mp_add(&C, b, &C)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+  }
+  
+  /* too big */
+  while (mp_cmp_mag(&C, b) != MP_LT) {
+      if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+  }
+  
+  /* C is now the inverse */
+  mp_exch (&C, c);
+  res = MP_OKAY;
+LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL);
+  return res;
+}
+#endif /* LTM_NO_NEG_EXP */
+
+
+/* compare maginitude of two ints (unsigned) */
+static int 
+mp_cmp_mag (mp_int * a, mp_int * b)
+{
+  int     n;
+  mp_digit *tmpa, *tmpb;
+
+  /* compare based on # of non-zero digits */
+  if (a->used > b->used) {
+    return MP_GT;
+  }
+  
+  if (a->used < b->used) {
+    return MP_LT;
+  }
+
+  /* alias for a */
+  tmpa = a->dp + (a->used - 1);
+
+  /* alias for b */
+  tmpb = b->dp + (a->used - 1);
+
+  /* compare based on digits  */
+  for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
+    if (*tmpa > *tmpb) {
+      return MP_GT;
+    }
+
+    if (*tmpa < *tmpb) {
+      return MP_LT;
+    }
+  }
+  return MP_EQ;
+}
+
+
+/* reads a unsigned char array, assumes the msb is stored first [big endian] */
+static int 
+mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c)
+{
+  int     res;
+
+  /* make sure there are at least two digits */
+  if (a->alloc < 2) {
+     if ((res = mp_grow(a, 2)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* zero the int */
+  mp_zero (a);
+
+  /* read the bytes in */
+  while (c-- > 0) {
+    if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) {
+      return res;
+    }
+
+#ifndef MP_8BIT
+      a->dp[0] |= *b++;
+      a->used += 1;
+#else
+      a->dp[0] = (*b & MP_MASK);
+      a->dp[1] |= ((*b++ >> 7U) & 1);
+      a->used += 2;
+#endif
+  }
+  mp_clamp (a);
+  return MP_OKAY;
+}
+
+
+/* store in unsigned [big endian] format */
+static int 
+mp_to_unsigned_bin (mp_int * a, unsigned char *b)
+{
+  int     x, res;
+  mp_int  t;
+
+  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+    return res;
+  }
+
+  x = 0;
+  while (mp_iszero (&t) == 0) {
+#ifndef MP_8BIT
+      b[x++] = (unsigned char) (t.dp[0] & 255);
+#else
+      b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7));
+#endif
+    if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+  }
+  bn_reverse (b, x);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+/* shift right by a certain bit count (store quotient in c, optional remainder in d) */
+static int 
+mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
+{
+  mp_digit D, r, rr;
+  int     x, res;
+  mp_int  t;
+
+
+  /* if the shift count is <= 0 then we do no work */
+  if (b <= 0) {
+    res = mp_copy (a, c);
+    if (d != NULL) {
+      mp_zero (d);
+    }
+    return res;
+  }
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  /* get the remainder */
+  if (d != NULL) {
+    if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+  }
+
+  /* copy */
+  if ((res = mp_copy (a, c)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+
+  /* shift by as many digits in the bit count */
+  if (b >= (int)DIGIT_BIT) {
+    mp_rshd (c, b / DIGIT_BIT);
+  }
+
+  /* shift any bit count < DIGIT_BIT */
+  D = (mp_digit) (b % DIGIT_BIT);
+  if (D != 0) {
+    register mp_digit *tmpc, mask, shift;
+
+    /* mask */
+    mask = (((mp_digit)1) << D) - 1;
+
+    /* shift for lsb */
+    shift = DIGIT_BIT - D;
+
+    /* alias */
+    tmpc = c->dp + (c->used - 1);
+
+    /* carry */
+    r = 0;
+    for (x = c->used - 1; x >= 0; x--) {
+      /* get the lower  bits of this word in a temp */
+      rr = *tmpc & mask;
+
+      /* shift the current word and mix in the carry bits from the previous word */
+      *tmpc = (*tmpc >> D) | (r << shift);
+      --tmpc;
+
+      /* set the carry to the carry bits of the current word found above */
+      r = rr;
+    }
+  }
+  mp_clamp (c);
+  if (d != NULL) {
+    mp_exch (&t, d);
+  }
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+static int 
+mp_init_copy (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  if ((res = mp_init (a)) != MP_OKAY) {
+    return res;
+  }
+  return mp_copy (b, a);
+}
+
+
+/* set to zero */
+static void 
+mp_zero (mp_int * a)
+{
+  int       n;
+  mp_digit *tmp;
+
+  a->sign = MP_ZPOS;
+  a->used = 0;
+
+  tmp = a->dp;
+  for (n = 0; n < a->alloc; n++) {
+     *tmp++ = 0;
+  }
+}
+
+
+/* copy, b = a */
+static int 
+mp_copy (mp_int * a, mp_int * b)
+{
+  int     res, n;
+
+  /* if dst == src do nothing */
+  if (a == b) {
+    return MP_OKAY;
+  }
+
+  /* grow dest */
+  if (b->alloc < a->used) {
+     if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* zero b and copy the parameters over */
+  {
+    register mp_digit *tmpa, *tmpb;
+
+    /* pointer aliases */
+
+    /* source */
+    tmpa = a->dp;
+
+    /* destination */
+    tmpb = b->dp;
+
+    /* copy all the digits */
+    for (n = 0; n < a->used; n++) {
+      *tmpb++ = *tmpa++;
+    }
+
+    /* clear high digits */
+    for (; n < b->used; n++) {
+      *tmpb++ = 0;
+    }
+  }
+
+  /* copy used count and sign */
+  b->used = a->used;
+  b->sign = a->sign;
+  return MP_OKAY;
+}
+
+
+/* shift right a certain amount of digits */
+static void 
+mp_rshd (mp_int * a, int b)
+{
+  int     x;
+
+  /* if b <= 0 then ignore it */
+  if (b <= 0) {
+    return;
+  }
+
+  /* if b > used then simply zero it and return */
+  if (a->used <= b) {
+    mp_zero (a);
+    return;
+  }
+
+  {
+    register mp_digit *bottom, *top;
+
+    /* shift the digits down */
+
+    /* bottom */
+    bottom = a->dp;
+
+    /* top [offset into digits] */
+    top = a->dp + b;
+
+    /* this is implemented as a sliding window where 
+     * the window is b-digits long and digits from 
+     * the top of the window are copied to the bottom
+     *
+     * e.g.
+
+     b-2 | b-1 | b0 | b1 | b2 | ... | bb |   ---->
+                 /\                   |      ---->
+                  \-------------------/      ---->
+     */
+    for (x = 0; x < (a->used - b); x++) {
+      *bottom++ = *top++;
+    }
+
+    /* zero the top digits */
+    for (; x < a->used; x++) {
+      *bottom++ = 0;
+    }
+  }
+  
+  /* remove excess digits */
+  a->used -= b;
+}
+
+
+/* swap the elements of two integers, for cases where you can't simply swap the 
+ * mp_int pointers around
+ */
+static void 
+mp_exch (mp_int * a, mp_int * b)
+{
+  mp_int  t;
+
+  t  = *a;
+  *a = *b;
+  *b = t;
+}
+
+
+/* trim unused digits 
+ *
+ * This is used to ensure that leading zero digits are
+ * trimed and the leading "used" digit will be non-zero
+ * Typically very fast.  Also fixes the sign if there
+ * are no more leading digits
+ */
+static void 
+mp_clamp (mp_int * a)
+{
+  /* decrease used while the most significant digit is
+   * zero.
+   */
+  while (a->used > 0 && a->dp[a->used - 1] == 0) {
+    --(a->used);
+  }
+
+  /* reset the sign flag if used == 0 */
+  if (a->used == 0) {
+    a->sign = MP_ZPOS;
+  }
+}
+
+
+/* grow as required */
+static int 
+mp_grow (mp_int * a, int size)
+{
+  int     i;
+  mp_digit *tmp;
+
+  /* if the alloc size is smaller alloc more ram */
+  if (a->alloc < size) {
+    /* ensure there are always at least MP_PREC digits extra on top */
+    size += (MP_PREC * 2) - (size % MP_PREC);
+
+    /* reallocate the array a->dp
+     *
+     * We store the return in a temporary variable
+     * in case the operation failed we don't want
+     * to overwrite the dp member of a.
+     */
+    tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size);
+    if (tmp == NULL) {
+      /* reallocation failed but "a" is still valid [can be freed] */
+      return MP_MEM;
+    }
+
+    /* reallocation succeeded so set a->dp */
+    a->dp = tmp;
+
+    /* zero excess digits */
+    i        = a->alloc;
+    a->alloc = size;
+    for (; i < a->alloc; i++) {
+      a->dp[i] = 0;
+    }
+  }
+  return MP_OKAY;
+}
+
+
+#ifdef BN_MP_ABS_C
+/* b = |a| 
+ *
+ * Simple function copies the input and fixes the sign to positive
+ */
+static int 
+mp_abs (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  /* copy a to b */
+  if (a != b) {
+     if ((res = mp_copy (a, b)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  /* force the sign of b to positive */
+  b->sign = MP_ZPOS;
+
+  return MP_OKAY;
+}
+#endif
+
+
+/* set to a digit */
+static void 
+mp_set (mp_int * a, mp_digit b)
+{
+  mp_zero (a);
+  a->dp[0] = b & MP_MASK;
+  a->used  = (a->dp[0] != 0) ? 1 : 0;
+}
+
+
+#ifndef LTM_NO_NEG_EXP
+/* b = a/2 */
+static int 
+mp_div_2(mp_int * a, mp_int * b)
+{
+  int     x, res, oldused;
+
+  /* copy */
+  if (b->alloc < a->used) {
+    if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  oldused = b->used;
+  b->used = a->used;
+  {
+    register mp_digit r, rr, *tmpa, *tmpb;
+
+    /* source alias */
+    tmpa = a->dp + b->used - 1;
+
+    /* dest alias */
+    tmpb = b->dp + b->used - 1;
+
+    /* carry */
+    r = 0;
+    for (x = b->used - 1; x >= 0; x--) {
+      /* get the carry for the next iteration */
+      rr = *tmpa & 1;
+
+      /* shift the current digit, add in carry and store */
+      *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
+
+      /* forward carry to next iteration */
+      r = rr;
+    }
+
+    /* zero excess digits */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+  mp_clamp (b);
+  return MP_OKAY;
+}
+#endif /* LTM_NO_NEG_EXP */
+
+
+/* shift left by a certain bit count */
+static int 
+mp_mul_2d (mp_int * a, int b, mp_int * c)
+{
+  mp_digit d;
+  int      res;
+
+  /* copy */
+  if (a != c) {
+     if ((res = mp_copy (a, c)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) {
+     if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  /* shift by as many digits in the bit count */
+  if (b >= (int)DIGIT_BIT) {
+    if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* shift any bit count < DIGIT_BIT */
+  d = (mp_digit) (b % DIGIT_BIT);
+  if (d != 0) {
+    register mp_digit *tmpc, shift, mask, r, rr;
+    register int x;
+
+    /* bitmask for carries */
+    mask = (((mp_digit)1) << d) - 1;
+
+    /* shift for msbs */
+    shift = DIGIT_BIT - d;
+
+    /* alias */
+    tmpc = c->dp;
+
+    /* carry */
+    r    = 0;
+    for (x = 0; x < c->used; x++) {
+      /* get the higher bits of the current word */
+      rr = (*tmpc >> shift) & mask;
+
+      /* shift the current word and OR in the carry */
+      *tmpc = ((*tmpc << d) | r) & MP_MASK;
+      ++tmpc;
+
+      /* set the carry to the carry bits of the current word */
+      r = rr;
+    }
+    
+    /* set final carry */
+    if (r != 0) {
+       c->dp[(c->used)++] = r;
+    }
+  }
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+#ifdef BN_MP_INIT_MULTI_C
+static int 
+mp_init_multi(mp_int *mp, ...) 
+{
+    mp_err res = MP_OKAY;      /* Assume ok until proven otherwise */
+    int n = 0;                 /* Number of ok inits */
+    mp_int* cur_arg = mp;
+    va_list args;
+
+    va_start(args, mp);        /* init args to next argument from caller */
+    while (cur_arg != NULL) {
+        if (mp_init(cur_arg) != MP_OKAY) {
+            /* Oops - error! Back-track and mp_clear what we already
+               succeeded in init-ing, then return error.
+            */
+            va_list clean_args;
+            
+            /* end the current list */
+            va_end(args);
+            
+            /* now start cleaning up */            
+            cur_arg = mp;
+            va_start(clean_args, mp);
+            while (n--) {
+                mp_clear(cur_arg);
+                cur_arg = va_arg(clean_args, mp_int*);
+            }
+            va_end(clean_args);
+            res = MP_MEM;
+            break;
+        }
+        n++;
+        cur_arg = va_arg(args, mp_int*);
+    }
+    va_end(args);
+    return res;                /* Assumed ok, if error flagged above. */
+}
+#endif
+
+
+#ifdef BN_MP_CLEAR_MULTI_C
+static void 
+mp_clear_multi(mp_int *mp, ...) 
+{
+    mp_int* next_mp = mp;
+    va_list args;
+    va_start(args, mp);
+    while (next_mp != NULL) {
+        mp_clear(next_mp);
+        next_mp = va_arg(args, mp_int*);
+    }
+    va_end(args);
+}
+#endif
+
+
+/* shift left a certain amount of digits */
+static int 
+mp_lshd (mp_int * a, int b)
+{
+  int     x, res;
+
+  /* if its less than zero return */
+  if (b <= 0) {
+    return MP_OKAY;
+  }
+
+  /* grow to fit the new digits */
+  if (a->alloc < a->used + b) {
+     if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  {
+    register mp_digit *top, *bottom;
+
+    /* increment the used by the shift amount then copy upwards */
+    a->used += b;
+
+    /* top */
+    top = a->dp + a->used - 1;
+
+    /* base */
+    bottom = a->dp + a->used - 1 - b;
+
+    /* much like mp_rshd this is implemented using a sliding window
+     * except the window goes the otherway around.  Copying from
+     * the bottom to the top.  see bn_mp_rshd.c for more info.
+     */
+    for (x = a->used - 1; x >= b; x--) {
+      *top-- = *bottom--;
+    }
+
+    /* zero the lower digits */
+    top = a->dp;
+    for (x = 0; x < b; x++) {
+      *top++ = 0;
+    }
+  }
+  return MP_OKAY;
+}
+
+
+/* returns the number of bits in an int */
+static int 
+mp_count_bits (mp_int * a)
+{
+  int     r;
+  mp_digit q;
+
+  /* shortcut */
+  if (a->used == 0) {
+    return 0;
+  }
+
+  /* get number of digits and add that */
+  r = (a->used - 1) * DIGIT_BIT;
+  
+  /* take the last digit and count the bits in it */
+  q = a->dp[a->used - 1];
+  while (q > ((mp_digit) 0)) {
+    ++r;
+    q >>= ((mp_digit) 1);
+  }
+  return r;
+}
+
+
+/* calc a value mod 2**b */
+static int 
+mp_mod_2d (mp_int * a, int b, mp_int * c)
+{
+  int     x, res;
+
+  /* if b is <= 0 then zero the int */
+  if (b <= 0) {
+    mp_zero (c);
+    return MP_OKAY;
+  }
+
+  /* if the modulus is larger than the value than return */
+  if (b >= (int) (a->used * DIGIT_BIT)) {
+    res = mp_copy (a, c);
+    return res;
+  }
+
+  /* copy */
+  if ((res = mp_copy (a, c)) != MP_OKAY) {
+    return res;
+  }
+
+  /* zero digits above the last digit of the modulus */
+  for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
+    c->dp[x] = 0;
+  }
+  /* clear the digit that is not completely outside/inside the modulus */
+  c->dp[b / DIGIT_BIT] &=
+    (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1));
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+#ifdef BN_MP_DIV_SMALL
+
+/* slower bit-bang division... also smaller */
+static int 
+mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+   mp_int ta, tb, tq, q;
+   int    res, n, n2;
+
+  /* is divisor zero ? */
+  if (mp_iszero (b) == 1) {
+    return MP_VAL;
+  }
+
+  /* if a < b then q=0, r = a */
+  if (mp_cmp_mag (a, b) == MP_LT) {
+    if (d != NULL) {
+      res = mp_copy (a, d);
+    } else {
+      res = MP_OKAY;
+    }
+    if (c != NULL) {
+      mp_zero (c);
+    }
+    return res;
+  }
+       
+  /* init our temps */
+  if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) {
+     return res;
+  }
+
+
+  mp_set(&tq, 1);
+  n = mp_count_bits(a) - mp_count_bits(b);
+  if (((res = mp_abs(a, &ta)) != MP_OKAY) ||
+      ((res = mp_abs(b, &tb)) != MP_OKAY) || 
+      ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
+      ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {
+      goto LBL_ERR;
+  }
+
+  while (n-- >= 0) {
+     if (mp_cmp(&tb, &ta) != MP_GT) {
+        if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
+            ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {
+           goto LBL_ERR;
+        }
+     }
+     if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
+         ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {
+           goto LBL_ERR;
+     }
+  }
+
+  /* now q == quotient and ta == remainder */
+  n  = a->sign;
+  n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
+  if (c != NULL) {
+     mp_exch(c, &q);
+     c->sign  = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;
+  }
+  if (d != NULL) {
+     mp_exch(d, &ta);
+     d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;
+  }
+LBL_ERR:
+   mp_clear_multi(&ta, &tb, &tq, &q, NULL);
+   return res;
+}
+
+#else
+
+/* integer signed division. 
+ * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
+ * HAC pp.598 Algorithm 14.20
+ *
+ * Note that the description in HAC is horribly 
+ * incomplete.  For example, it doesn't consider 
+ * the case where digits are removed from 'x' in 
+ * the inner loop.  It also doesn't consider the 
+ * case that y has fewer than three digits, etc..
+ *
+ * The overall algorithm is as described as 
+ * 14.20 from HAC but fixed to treat these cases.
+*/
+static int 
+mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  mp_int  q, x, y, t1, t2;
+  int     res, n, t, i, norm, neg;
+
+  /* is divisor zero ? */
+  if (mp_iszero (b) == 1) {
+    return MP_VAL;
+  }
+
+  /* if a < b then q=0, r = a */
+  if (mp_cmp_mag (a, b) == MP_LT) {
+    if (d != NULL) {
+      res = mp_copy (a, d);
+    } else {
+      res = MP_OKAY;
+    }
+    if (c != NULL) {
+      mp_zero (c);
+    }
+    return res;
+  }
+
+  if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) {
+    return res;
+  }
+  q.used = a->used + 2;
+
+  if ((res = mp_init (&t1)) != MP_OKAY) {
+    goto LBL_Q;
+  }
+
+  if ((res = mp_init (&t2)) != MP_OKAY) {
+    goto LBL_T1;
+  }
+
+  if ((res = mp_init_copy (&x, a)) != MP_OKAY) {
+    goto LBL_T2;
+  }
+
+  if ((res = mp_init_copy (&y, b)) != MP_OKAY) {
+    goto LBL_X;
+  }
+
+  /* fix the sign */
+  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+  x.sign = y.sign = MP_ZPOS;
+
+  /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
+  norm = mp_count_bits(&y) % DIGIT_BIT;
+  if (norm < (int)(DIGIT_BIT-1)) {
+     norm = (DIGIT_BIT-1) - norm;
+     if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) {
+       goto LBL_Y;
+     }
+     if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) {
+       goto LBL_Y;
+     }
+  } else {
+     norm = 0;
+  }
+
+  /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
+  n = x.used - 1;
+  t = y.used - 1;
+
+  /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
+  if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */
+    goto LBL_Y;
+  }
+
+  while (mp_cmp (&x, &y) != MP_LT) {
+    ++(q.dp[n - t]);
+    if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+  }
+
+  /* reset y by shifting it back down */
+  mp_rshd (&y, n - t);
+
+  /* step 3. for i from n down to (t + 1) */
+  for (i = n; i >= (t + 1); i--) {
+    if (i > x.used) {
+      continue;
+    }
+
+    /* step 3.1 if xi == yt then set q{i-t-1} to b-1, 
+     * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
+    if (x.dp[i] == y.dp[t]) {
+      q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
+    } else {
+      mp_word tmp;
+      tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
+      tmp |= ((mp_word) x.dp[i - 1]);
+      tmp /= ((mp_word) y.dp[t]);
+      if (tmp > (mp_word) MP_MASK)
+        tmp = MP_MASK;
+      q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));
+    }
+
+    /* while (q{i-t-1} * (yt * b + y{t-1})) > 
+             xi * b**2 + xi-1 * b + xi-2 
+     
+       do q{i-t-1} -= 1; 
+    */
+    q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;
+    do {
+      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;
+
+      /* find left hand */
+      mp_zero (&t1);
+      t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
+      t1.dp[1] = y.dp[t];
+      t1.used = 2;
+      if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+
+      /* find right hand */
+      t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
+      t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
+      t2.dp[2] = x.dp[i];
+      t2.used = 3;
+    } while (mp_cmp_mag(&t1, &t2) == MP_GT);
+
+    /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
+    if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
+    if (x.sign == MP_NEG) {
+      if ((res = mp_copy (&y, &t1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+      if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+      if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+
+      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;
+    }
+  }
+
+  /* now q is the quotient and x is the remainder 
+   * [which we have to normalize] 
+   */
+  
+  /* get sign before writing to c */
+  x.sign = x.used == 0 ? MP_ZPOS : a->sign;
+
+  if (c != NULL) {
+    mp_clamp (&q);
+    mp_exch (&q, c);
+    c->sign = neg;
+  }
+
+  if (d != NULL) {
+    mp_div_2d (&x, norm, &x, NULL);
+    mp_exch (&x, d);
+  }
+
+  res = MP_OKAY;
+
+LBL_Y:mp_clear (&y);
+LBL_X:mp_clear (&x);
+LBL_T2:mp_clear (&t2);
+LBL_T1:mp_clear (&t1);
+LBL_Q:mp_clear (&q);
+  return res;
+}
+
+#endif
+
+
+#ifdef MP_LOW_MEM
+   #define TAB_SIZE 32
+#else
+   #define TAB_SIZE 256
+#endif
+
+static int 
+s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+  mp_int  M[TAB_SIZE], res, mu;
+  mp_digit buf;
+  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+  int (*redux)(mp_int*,mp_int*,mp_int*);
+
+  /* find window size */
+  x = mp_count_bits (X);
+  if (x <= 7) {
+    winsize = 2;
+  } else if (x <= 36) {
+    winsize = 3;
+  } else if (x <= 140) {
+    winsize = 4;
+  } else if (x <= 450) {
+    winsize = 5;
+  } else if (x <= 1303) {
+    winsize = 6;
+  } else if (x <= 3529) {
+    winsize = 7;
+  } else {
+    winsize = 8;
+  }
+
+#ifdef MP_LOW_MEM
+    if (winsize > 5) {
+       winsize = 5;
+    }
+#endif
+
+  /* init M array */
+  /* init first cell */
+  if ((err = mp_init(&M[1])) != MP_OKAY) {
+     return err; 
+  }
+
+  /* now init the second half of the array */
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    if ((err = mp_init(&M[x])) != MP_OKAY) {
+      for (y = 1<<(winsize-1); y < x; y++) {
+        mp_clear (&M[y]);
+      }
+      mp_clear(&M[1]);
+      return err;
+    }
+  }
+
+  /* create mu, used for Barrett reduction */
+  if ((err = mp_init (&mu)) != MP_OKAY) {
+    goto LBL_M;
+  }
+  
+  if (redmode == 0) {
+     if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
+        goto LBL_MU;
+     }
+     redux = mp_reduce;
+  } else {
+     if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) {
+        goto LBL_MU;
+     }
+     redux = mp_reduce_2k_l;
+  }    
+
+  /* create M table
+   *
+   * The M table contains powers of the base, 
+   * e.g. M[x] = G**x mod P
+   *
+   * The first half of the table is not 
+   * computed though accept for M[0] and M[1]
+   */
+  if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
+    goto LBL_MU;
+  }
+
+  /* compute the value at M[1<<(winsize-1)] by squaring 
+   * M[1] (winsize-1) times 
+   */
+  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+    goto LBL_MU;
+  }
+
+  for (x = 0; x < (winsize - 1); x++) {
+    /* square it */
+    if ((err = mp_sqr (&M[1 << (winsize - 1)], 
+                       &M[1 << (winsize - 1)])) != MP_OKAY) {
+      goto LBL_MU;
+    }
+
+    /* reduce modulo P */
+    if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {
+      goto LBL_MU;
+    }
+  }
+
+  /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
+   * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
+   */
+  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+      goto LBL_MU;
+    }
+    if ((err = redux (&M[x], P, &mu)) != MP_OKAY) {
+      goto LBL_MU;
+    }
+  }
+
+  /* setup result */
+  if ((err = mp_init (&res)) != MP_OKAY) {
+    goto LBL_MU;
+  }
+  mp_set (&res, 1);
+
+  /* set initial mode and bit cnt */
+  mode   = 0;
+  bitcnt = 1;
+  buf    = 0;
+  digidx = X->used - 1;
+  bitcpy = 0;
+  bitbuf = 0;
+
+  for (;;) {
+    /* grab next digit as required */
+    if (--bitcnt == 0) {
+      /* if digidx == -1 we are out of digits */
+      if (digidx == -1) {
+        break;
+      }
+      /* read next digit and reset the bitcnt */
+      buf    = X->dp[digidx--];
+      bitcnt = (int) DIGIT_BIT;
+    }
+
+    /* grab the next msb from the exponent */
+    y     = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
+    buf <<= (mp_digit)1;
+
+    /* if the bit is zero and mode == 0 then we ignore it
+     * These represent the leading zero bits before the first 1 bit
+     * in the exponent.  Technically this opt is not required but it
+     * does lower the # of trivial squaring/reductions used
+     */
+    if (mode == 0 && y == 0) {
+      continue;
+    }
+
+    /* if the bit is zero and mode == 1 then we square */
+    if (mode == 1 && y == 0) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      continue;
+    }
+
+    /* else we add it to the window */
+    bitbuf |= (y << (winsize - ++bitcpy));
+    mode    = 2;
+
+    if (bitcpy == winsize) {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < winsize; x++) {
+        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+
+      /* then multiply */
+      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+      mode   = 1;
+    }
+  }
+
+  /* if bits remain then square/multiply */
+  if (mode == 2 && bitcpy > 0) {
+    /* square then multiply if the bit is set */
+    for (x = 0; x < bitcpy; x++) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      bitbuf <<= 1;
+      if ((bitbuf & (1 << winsize)) != 0) {
+        /* then multiply */
+        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+    }
+  }
+
+  mp_exch (&res, Y);
+  err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_MU:mp_clear (&mu);
+LBL_M:
+  mp_clear(&M[1]);
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    mp_clear (&M[x]);
+  }
+  return err;
+}
+
+
+/* computes b = a*a */
+static int 
+mp_sqr (mp_int * a, mp_int * b)
+{
+  int     res;
+
+#ifdef BN_MP_TOOM_SQR_C
+  /* use Toom-Cook? */
+  if (a->used >= TOOM_SQR_CUTOFF) {
+    res = mp_toom_sqr(a, b);
+  /* Karatsuba? */
+  } else 
+#endif
+#ifdef BN_MP_KARATSUBA_SQR_C
+if (a->used >= KARATSUBA_SQR_CUTOFF) {
+    res = mp_karatsuba_sqr (a, b);
+  } else 
+#endif
+  {
+#ifdef BN_FAST_S_MP_SQR_C
+    /* can we use the fast comba multiplier? */
+    if ((a->used * 2 + 1) < MP_WARRAY && 
+         a->used < 
+         (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
+      res = fast_s_mp_sqr (a, b);
+    } else
+#endif
+#ifdef BN_S_MP_SQR_C
+      res = s_mp_sqr (a, b);
+#else
+#error mp_sqr could fail
+      res = MP_VAL;
+#endif
+  }
+  b->sign = MP_ZPOS;
+  return res;
+}
+
+
+/* reduces a modulo n where n is of the form 2**p - d 
+   This differs from reduce_2k since "d" can be larger
+   than a single digit.
+*/
+static int 
+mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d)
+{
+   mp_int q;
+   int    p, res;
+   
+   if ((res = mp_init(&q)) != MP_OKAY) {
+      return res;
+   }
+   
+   p = mp_count_bits(n);    
+top:
+   /* q = a/2**p, a = a mod 2**p */
+   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   /* q = q * d */
+   if ((res = mp_mul(&q, d, &q)) != MP_OKAY) { 
+      goto ERR;
+   }
+   
+   /* a = a + q */
+   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   if (mp_cmp_mag(a, n) != MP_LT) {
+      s_mp_sub(a, n, a);
+      goto top;
+   }
+   
+ERR:
+   mp_clear(&q);
+   return res;
+}
+
+
+/* determines the setup value */
+static int 
+mp_reduce_2k_setup_l(mp_int *a, mp_int *d)
+{
+   int    res;
+   mp_int tmp;
+   
+   if ((res = mp_init(&tmp)) != MP_OKAY) {
+      return res;
+   }
+   
+   if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+ERR:
+   mp_clear(&tmp);
+   return res;
+}
+
+
+/* computes a = 2**b 
+ *
+ * Simple algorithm which zeroes the int, grows it then just sets one bit
+ * as required.
+ */
+static int 
+mp_2expt (mp_int * a, int b)
+{
+  int     res;
+
+  /* zero a as per default */
+  mp_zero (a);
+
+  /* grow a to accommodate the single bit */
+  if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) {
+    return res;
+  }
+
+  /* set the used count of where the bit will go */
+  a->used = b / DIGIT_BIT + 1;
+
+  /* put the single bit in its place */
+  a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);
+
+  return MP_OKAY;
+}
+
+
+/* pre-calculate the value required for Barrett reduction
+ * For a given modulus "b" it calulates the value required in "a"
+ */
+static int 
+mp_reduce_setup (mp_int * a, mp_int * b)
+{
+  int     res;
+  
+  if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {
+    return res;
+  }
+  return mp_div (a, b, a, NULL);
+}
+
+
+/* reduces x mod m, assumes 0 < x < m**2, mu is 
+ * precomputed via mp_reduce_setup.
+ * From HAC pp.604 Algorithm 14.42
+ */
+static int 
+mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
+{
+  mp_int  q;
+  int     res, um = m->used;
+
+  /* q = x */
+  if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
+    return res;
+  }
+
+  /* q1 = x / b**(k-1)  */
+  mp_rshd (&q, um - 1);         
+
+  /* according to HAC this optimization is ok */
+  if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
+    if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  } else {
+#ifdef BN_S_MP_MUL_HIGH_DIGS_C
+    if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+    if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+#else 
+    { 
+#error mp_reduce would always fail
+      res = MP_VAL;
+      goto CLEANUP;
+    }
+#endif
+  }
+
+  /* q3 = q2 / b**(k+1) */
+  mp_rshd (&q, um + 1);         
+
+  /* x = x mod b**(k+1), quick (no division) */
+  if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* q = q * m mod b**(k+1), quick (no division) */
+  if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* x = x - q */
+  if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* If x < 0, add b**(k+1) to it */
+  if (mp_cmp_d (x, 0) == MP_LT) {
+    mp_set (&q, 1);
+    if ((res = mp_lshd (&q, um + 1)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+    if ((res = mp_add (x, &q, x)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  }
+
+  /* Back off if it's too big */
+  while (mp_cmp (x, m) != MP_LT) {
+    if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  }
+  
+CLEANUP:
+  mp_clear (&q);
+
+  return res;
+}
+
+
+/* multiplies |a| * |b| and only computes up to digs digits of result
+ * HAC pp. 595, Algorithm 14.12  Modified so you can control how 
+ * many digits of output are created.
+ */
+static int 
+s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  mp_int  t;
+  int     res, pa, pb, ix, iy;
+  mp_digit u;
+  mp_word r;
+  mp_digit tmpx, *tmpt, *tmpy;
+
+  /* can we use the fast multiplier? */
+  if (((digs) < MP_WARRAY) &&
+      MIN (a->used, b->used) < 
+          (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_s_mp_mul_digs (a, b, c, digs);
+  }
+
+  if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
+    return res;
+  }
+  t.used = digs;
+
+  /* compute the digits of the product directly */
+  pa = a->used;
+  for (ix = 0; ix < pa; ix++) {
+    /* set the carry to zero */
+    u = 0;
+
+    /* limit ourselves to making digs digits of output */
+    pb = MIN (b->used, digs - ix);
+
+    /* setup some aliases */
+    /* copy of the digit from a used within the nested loop */
+    tmpx = a->dp[ix];
+    
+    /* an alias for the destination shifted ix places */
+    tmpt = t.dp + ix;
+    
+    /* an alias for the digits of b */
+    tmpy = b->dp;
+
+    /* compute the columns of the output and propagate the carry */
+    for (iy = 0; iy < pb; iy++) {
+      /* compute the column as a mp_word */
+      r       = ((mp_word)*tmpt) +
+                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+                ((mp_word) u);
+
+      /* the new column is the lower part of the result */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* get the carry word from the result */
+      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+    }
+    /* set carry if it is placed below digs */
+    if (ix + iy < digs) {
+      *tmpt = u;
+    }
+  }
+
+  mp_clamp (&t);
+  mp_exch (&t, c);
+
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+/* Fast (comba) multiplier
+ *
+ * This is the fast column-array [comba] multiplier.  It is 
+ * designed to compute the columns of the product first 
+ * then handle the carries afterwards.  This has the effect 
+ * of making the nested loops that compute the columns very
+ * simple and schedulable on super-scalar processors.
+ *
+ * This has been modified to produce a variable number of 
+ * digits of output so if say only a half-product is required 
+ * you don't have to compute the upper half (a feature 
+ * required for fast Barrett reduction).
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ *
+ */
+static int 
+fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  int     olduse, res, pa, ix, iz;
+  mp_digit W[MP_WARRAY];
+  register mp_word  _W;
+
+  /* grow the destination as required */
+  if (c->alloc < digs) {
+    if ((res = mp_grow (c, digs)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* number of output digits to produce */
+  pa = MIN(digs, a->used + b->used);
+
+  /* clear the carry */
+  _W = 0;
+  for (ix = 0; ix < pa; ix++) { 
+      int      tx, ty;
+      int      iy;
+      mp_digit *tmpx, *tmpy;
+
+      /* get offsets into the two bignums */
+      ty = MIN(b->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = a->dp + tx;
+      tmpy = b->dp + ty;
+
+      /* this is the number of times the loop will iterrate, essentially 
+         while (tx++ < a->used && ty-- >= 0) { ... }
+       */
+      iy = MIN(a->used-tx, ty+1);
+
+      /* execute loop */
+      for (iz = 0; iz < iy; ++iz) {
+         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+
+      }
+
+      /* store term */
+      W[ix] = ((mp_digit)_W) & MP_MASK;
+
+      /* make next carry */
+      _W = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+  /* setup dest */
+  olduse  = c->used;
+  c->used = pa;
+
+  {
+    register mp_digit *tmpc;
+    tmpc = c->dp;
+    for (ix = 0; ix < pa+1; ix++) {
+      /* now extract the previous digit [below the carry] */
+      *tmpc++ = W[ix];
+    }
+
+    /* clear unused digits [that existed in the old copy of c] */
+    for (; ix < olduse; ix++) {
+      *tmpc++ = 0;
+    }
+  }
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+/* init an mp_init for a given size */
+static int 
+mp_init_size (mp_int * a, int size)
+{
+  int x;
+
+  /* pad size so there are always extra digits */
+  size += (MP_PREC * 2) - (size % MP_PREC);    
+  
+  /* alloc mem */
+  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size);
+  if (a->dp == NULL) {
+    return MP_MEM;
+  }
+
+  /* set the members */
+  a->used  = 0;
+  a->alloc = size;
+  a->sign  = MP_ZPOS;
+
+  /* zero the digits */
+  for (x = 0; x < size; x++) {
+      a->dp[x] = 0;
+  }
+
+  return MP_OKAY;
+}
+
+
+/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
+static int 
+s_mp_sqr (mp_int * a, mp_int * b)
+{
+  mp_int  t;
+  int     res, ix, iy, pa;
+  mp_word r;
+  mp_digit u, tmpx, *tmpt;
+
+  pa = a->used;
+  if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
+    return res;
+  }
+
+  /* default used is maximum possible size */
+  t.used = 2*pa + 1;
+
+  for (ix = 0; ix < pa; ix++) {
+    /* first calculate the digit at 2*ix */
+    /* calculate double precision result */
+    r = ((mp_word) t.dp[2*ix]) +
+        ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
+
+    /* store lower part in result */
+    t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
+
+    /* get the carry */
+    u           = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+    /* left hand side of A[ix] * A[iy] */
+    tmpx        = a->dp[ix];
+
+    /* alias for where to store the results */
+    tmpt        = t.dp + (2*ix + 1);
+    
+    for (iy = ix + 1; iy < pa; iy++) {
+      /* first calculate the product */
+      r       = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
+
+      /* now calculate the double precision result, note we use
+       * addition instead of *2 since it's easier to optimize
+       */
+      r       = ((mp_word) *tmpt) + r + r + ((mp_word) u);
+
+      /* store lower part */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* get carry */
+      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+    }
+    /* propagate upwards */
+    while (u != ((mp_digit) 0)) {
+      r       = ((mp_word) *tmpt) + ((mp_word) u);
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+    }
+  }
+
+  mp_clamp (&t);
+  mp_exch (&t, b);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+/* multiplies |a| * |b| and does not compute the lower digs digits
+ * [meant to get the higher part of the product]
+ */
+static int 
+s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  mp_int  t;
+  int     res, pa, pb, ix, iy;
+  mp_digit u;
+  mp_word r;
+  mp_digit tmpx, *tmpt, *tmpy;
+
+  /* can we use the fast multiplier? */
+#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+  if (((a->used + b->used + 1) < MP_WARRAY)
+      && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_s_mp_mul_high_digs (a, b, c, digs);
+  }
+#endif
+
+  if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
+    return res;
+  }
+  t.used = a->used + b->used + 1;
+
+  pa = a->used;
+  pb = b->used;
+  for (ix = 0; ix < pa; ix++) {
+    /* clear the carry */
+    u = 0;
+
+    /* left hand side of A[ix] * B[iy] */
+    tmpx = a->dp[ix];
+
+    /* alias to the address of where the digits will be stored */
+    tmpt = &(t.dp[digs]);
+
+    /* alias for where to read the right hand side from */
+    tmpy = b->dp + (digs - ix);
+
+    for (iy = digs - ix; iy < pb; iy++) {
+      /* calculate the double precision result */
+      r       = ((mp_word)*tmpt) +
+                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+                ((mp_word) u);
+
+      /* get the lower part */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* carry the carry */
+      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+    }
+    *tmpt = u;
+  }
+  mp_clamp (&t);
+  mp_exch (&t, c);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+#ifdef BN_MP_MONTGOMERY_SETUP_C
+/* setups the montgomery reduction stuff */
+static int 
+mp_montgomery_setup (mp_int * n, mp_digit * rho)
+{
+  mp_digit x, b;
+
+/* fast inversion mod 2**k
+ *
+ * Based on the fact that
+ *
+ * XA = 1 (mod 2**n)  =>  (X(2-XA)) A = 1 (mod 2**2n)
+ *                    =>  2*X*A - X*X*A*A = 1
+ *                    =>  2*(1) - (1)     = 1
+ */
+  b = n->dp[0];
+
+  if ((b & 1) == 0) {
+    return MP_VAL;
+  }
+
+  x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
+  x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
+#if !defined(MP_8BIT)
+  x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
+#endif
+#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
+  x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
+#endif
+#ifdef MP_64BIT
+  x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
+#endif
+
+  /* rho = -1/m mod b */
+  *rho = (unsigned long)(((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK;
+
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+/* computes xR**-1 == x (mod N) via Montgomery Reduction
+ *
+ * This is an optimized implementation of montgomery_reduce
+ * which uses the comba method to quickly calculate the columns of the
+ * reduction.
+ *
+ * Based on Algorithm 14.32 on pp.601 of HAC.
+*/
+int 
+fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+  int     ix, res, olduse;
+  mp_word W[MP_WARRAY];
+
+  /* get old used count */
+  olduse = x->used;
+
+  /* grow a as required */
+  if (x->alloc < n->used + 1) {
+    if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* first we have to get the digits of the input into
+   * an array of double precision words W[...]
+   */
+  {
+    register mp_word *_W;
+    register mp_digit *tmpx;
+
+    /* alias for the W[] array */
+    _W   = W;
+
+    /* alias for the digits of  x*/
+    tmpx = x->dp;
+
+    /* copy the digits of a into W[0..a->used-1] */
+    for (ix = 0; ix < x->used; ix++) {
+      *_W++ = *tmpx++;
+    }
+
+    /* zero the high words of W[a->used..m->used*2] */
+    for (; ix < n->used * 2 + 1; ix++) {
+      *_W++ = 0;
+    }
+  }
+
+  /* now we proceed to zero successive digits
+   * from the least significant upwards
+   */
+  for (ix = 0; ix < n->used; ix++) {
+    /* mu = ai * m' mod b
+     *
+     * We avoid a double precision multiplication (which isn't required)
+     * by casting the value down to a mp_digit.  Note this requires
+     * that W[ix-1] have  the carry cleared (see after the inner loop)
+     */
+    register mp_digit mu;
+    mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
+
+    /* a = a + mu * m * b**i
+     *
+     * This is computed in place and on the fly.  The multiplication
+     * by b**i is handled by offseting which columns the results
+     * are added to.
+     *
+     * Note the comba method normally doesn't handle carries in the
+     * inner loop In this case we fix the carry from the previous
+     * column since the Montgomery reduction requires digits of the
+     * result (so far) [see above] to work.  This is
+     * handled by fixing up one carry after the inner loop.  The
+     * carry fixups are done in order so after these loops the
+     * first m->used words of W[] have the carries fixed
+     */
+    {
+      register int iy;
+      register mp_digit *tmpn;
+      register mp_word *_W;
+
+      /* alias for the digits of the modulus */
+      tmpn = n->dp;
+
+      /* Alias for the columns set by an offset of ix */
+      _W = W + ix;
+
+      /* inner loop */
+      for (iy = 0; iy < n->used; iy++) {
+          *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
+      }
+    }
+
+    /* now fix carry for next digit, W[ix+1] */
+    W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
+  }
+
+  /* now we have to propagate the carries and
+   * shift the words downward [all those least
+   * significant digits we zeroed].
+   */
+  {
+    register mp_digit *tmpx;
+    register mp_word *_W, *_W1;
+
+    /* nox fix rest of carries */
+
+    /* alias for current word */
+    _W1 = W + ix;
+
+    /* alias for next word, where the carry goes */
+    _W = W + ++ix;
+
+    for (; ix <= n->used * 2 + 1; ix++) {
+      *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
+    }
+
+    /* copy out, A = A/b**n
+     *
+     * The result is A/b**n but instead of converting from an
+     * array of mp_word to mp_digit than calling mp_rshd
+     * we just copy them in the right order
+     */
+
+    /* alias for destination word */
+    tmpx = x->dp;
+
+    /* alias for shifted double precision result */
+    _W = W + n->used;
+
+    for (ix = 0; ix < n->used + 1; ix++) {
+      *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
+    }
+
+    /* zero oldused digits, if the input a was larger than
+     * m->used+1 we'll have to clear the digits
+     */
+    for (; ix < olduse; ix++) {
+      *tmpx++ = 0;
+    }
+  }
+
+  /* set the max used and clamp */
+  x->used = n->used + 1;
+  mp_clamp (x);
+
+  /* if A >= m then A = A - m */
+  if (mp_cmp_mag (x, n) != MP_LT) {
+    return s_mp_sub (x, n, x);
+  }
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_MP_MUL_2_C
+/* b = a*2 */
+static int 
+mp_mul_2(mp_int * a, mp_int * b)
+{
+  int     x, res, oldused;
+
+  /* grow to accommodate result */
+  if (b->alloc < a->used + 1) {
+    if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  oldused = b->used;
+  b->used = a->used;
+
+  {
+    register mp_digit r, rr, *tmpa, *tmpb;
+
+    /* alias for source */
+    tmpa = a->dp;
+    
+    /* alias for dest */
+    tmpb = b->dp;
+
+    /* carry */
+    r = 0;
+    for (x = 0; x < a->used; x++) {
+    
+      /* get what will be the *next* carry bit from the 
+       * MSB of the current digit 
+       */
+      rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
+      
+      /* now shift up this digit, add in the carry [from the previous] */
+      *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
+      
+      /* copy the carry that would be from the source 
+       * digit into the next iteration 
+       */
+      r = rr;
+    }
+
+    /* new leading digit? */
+    if (r != 0) {
+      /* add a MSB which is always 1 at this point */
+      *tmpb = 1;
+      ++(b->used);
+    }
+
+    /* now zero any excess digits on the destination 
+     * that we didn't write to 
+     */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+/*
+ * shifts with subtractions when the result is greater than b.
+ *
+ * The method is slightly modified to shift B unconditionally up to just under
+ * the leading bit of b.  This saves a lot of multiple precision shifting.
+ */
+static int 
+mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
+{
+  int     x, bits, res;
+
+  /* how many bits of last digit does b use */
+  bits = mp_count_bits (b) % DIGIT_BIT;
+
+  if (b->used > 1) {
+     if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
+        return res;
+     }
+  } else {
+     mp_set(a, 1);
+     bits = 1;
+  }
+
+
+  /* now compute C = A * B mod b */
+  for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
+    if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
+      return res;
+    }
+    if (mp_cmp_mag (a, b) != MP_LT) {
+      if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
+        return res;
+      }
+    }
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_MP_EXPTMOD_FAST_C
+/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
+ *
+ * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.
+ * The value of k changes based on the size of the exponent.
+ *
+ * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
+ */
+
+static int 
+mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+  mp_int  M[TAB_SIZE], res;
+  mp_digit buf, mp;
+  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+
+  /* use a pointer to the reduction algorithm.  This allows us to use
+   * one of many reduction algorithms without modding the guts of
+   * the code with if statements everywhere.
+   */
+  int     (*redux)(mp_int*,mp_int*,mp_digit);
+
+  /* find window size */
+  x = mp_count_bits (X);
+  if (x <= 7) {
+    winsize = 2;
+  } else if (x <= 36) {
+    winsize = 3;
+  } else if (x <= 140) {
+    winsize = 4;
+  } else if (x <= 450) {
+    winsize = 5;
+  } else if (x <= 1303) {
+    winsize = 6;
+  } else if (x <= 3529) {
+    winsize = 7;
+  } else {
+    winsize = 8;
+  }
+
+#ifdef MP_LOW_MEM
+  if (winsize > 5) {
+     winsize = 5;
+  }
+#endif
+
+  /* init M array */
+  /* init first cell */
+  if ((err = mp_init(&M[1])) != MP_OKAY) {
+     return err;
+  }
+
+  /* now init the second half of the array */
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    if ((err = mp_init(&M[x])) != MP_OKAY) {
+      for (y = 1<<(winsize-1); y < x; y++) {
+        mp_clear (&M[y]);
+      }
+      mp_clear(&M[1]);
+      return err;
+    }
+  }
+
+  /* determine and setup reduction code */
+  if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_SETUP_C     
+     /* now setup montgomery  */
+     if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
+        goto LBL_M;
+     }
+#else
+     err = MP_VAL;
+     goto LBL_M;
+#endif
+
+     /* automatically pick the comba one if available (saves quite a few calls/ifs) */
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+     if (((P->used * 2 + 1) < MP_WARRAY) &&
+          P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+        redux = fast_mp_montgomery_reduce;
+     } else 
+#endif
+     {
+#ifdef BN_MP_MONTGOMERY_REDUCE_C
+        /* use slower baseline Montgomery method */
+        redux = mp_montgomery_reduce;
+#else
+        err = MP_VAL;
+        goto LBL_M;
+#endif
+     }
+  } else if (redmode == 1) {
+#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
+     /* setup DR reduction for moduli of the form B**k - b */
+     mp_dr_setup(P, &mp);
+     redux = mp_dr_reduce;
+#else
+     err = MP_VAL;
+     goto LBL_M;
+#endif
+  } else {
+#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
+     /* setup DR reduction for moduli of the form 2**k - b */
+     if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
+        goto LBL_M;
+     }
+     redux = mp_reduce_2k;
+#else
+     err = MP_VAL;
+     goto LBL_M;
+#endif
+  }
+
+  /* setup result */
+  if ((err = mp_init (&res)) != MP_OKAY) {
+    goto LBL_M;
+  }
+
+  /* create M table
+   *
+
+   *
+   * The first half of the table is not computed though accept for M[0] and M[1]
+   */
+
+  if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+     /* now we need R mod m */
+     if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
+       goto LBL_RES;
+     }
+#else 
+     err = MP_VAL;
+     goto LBL_RES;
+#endif
+
+     /* now set M[1] to G * R mod m */
+     if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
+       goto LBL_RES;
+     }
+  } else {
+     mp_set(&res, 1);
+     if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
+        goto LBL_RES;
+     }
+  }
+
+  /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
+  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+    goto LBL_RES;
+  }
+
+  for (x = 0; x < (winsize - 1); x++) {
+    if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) {
+      goto LBL_RES;
+    }
+    if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {
+      goto LBL_RES;
+    }
+  }
+
+  /* create upper table */
+  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+      goto LBL_RES;
+    }
+    if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
+      goto LBL_RES;
+    }
+  }
+
+  /* set initial mode and bit cnt */
+  mode   = 0;
+  bitcnt = 1;
+  buf    = 0;
+  digidx = X->used - 1;
+  bitcpy = 0;
+  bitbuf = 0;
+
+  for (;;) {
+    /* grab next digit as required */
+    if (--bitcnt == 0) {
+      /* if digidx == -1 we are out of digits so break */
+      if (digidx == -1) {
+        break;
+      }
+      /* read next digit and reset bitcnt */
+      buf    = X->dp[digidx--];
+      bitcnt = (int)DIGIT_BIT;
+    }
+
+    /* grab the next msb from the exponent */
+    y     = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
+    buf <<= (mp_digit)1;
+
+    /* if the bit is zero and mode == 0 then we ignore it
+     * These represent the leading zero bits before the first 1 bit
+     * in the exponent.  Technically this opt is not required but it
+     * does lower the # of trivial squaring/reductions used
+     */
+    if (mode == 0 && y == 0) {
+      continue;
+    }
+
+    /* if the bit is zero and mode == 1 then we square */
+    if (mode == 1 && y == 0) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      continue;
+    }
+
+    /* else we add it to the window */
+    bitbuf |= (y << (winsize - ++bitcpy));
+    mode    = 2;
+
+    if (bitcpy == winsize) {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < winsize; x++) {
+        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, mp)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+
+      /* then multiply */
+      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+      mode   = 1;
+    }
+  }
+
+  /* if bits remain then square/multiply */
+  if (mode == 2 && bitcpy > 0) {
+    /* square then multiply if the bit is set */
+    for (x = 0; x < bitcpy; x++) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* get next bit of the window */
+      bitbuf <<= 1;
+      if ((bitbuf & (1 << winsize)) != 0) {
+        /* then multiply */
+        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, mp)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+    }
+  }
+
+  if (redmode == 0) {
+     /* fixup result if Montgomery reduction is used
+      * recall that any value in a Montgomery system is
+      * actually multiplied by R mod n.  So we have
+      * to reduce one more time to cancel out the factor
+      * of R.
+      */
+     if ((err = redux(&res, P, mp)) != MP_OKAY) {
+       goto LBL_RES;
+     }
+  }
+
+  /* swap res with Y */
+  mp_exch (&res, Y);
+  err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_M:
+  mp_clear(&M[1]);
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    mp_clear (&M[x]);
+  }
+  return err;
+}
+#endif
+
+
+#ifdef BN_FAST_S_MP_SQR_C
+/* the jist of squaring...
+ * you do like mult except the offset of the tmpx [one that 
+ * starts closer to zero] can't equal the offset of tmpy.  
+ * So basically you set up iy like before then you min it with
+ * (ty-tx) so that it never happens.  You double all those 
+ * you add in the inner loop
+
+After that loop you do the squares and add them in.
+*/
+
+static int 
+fast_s_mp_sqr (mp_int * a, mp_int * b)
+{
+  int       olduse, res, pa, ix, iz;
+  mp_digit   W[MP_WARRAY], *tmpx;
+  mp_word   W1;
+
+  /* grow the destination as required */
+  pa = a->used + a->used;
+  if (b->alloc < pa) {
+    if ((res = mp_grow (b, pa)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* number of output digits to produce */
+  W1 = 0;
+  for (ix = 0; ix < pa; ix++) { 
+      int      tx, ty, iy;
+      mp_word  _W;
+      mp_digit *tmpy;
+
+      /* clear counter */
+      _W = 0;
+
+      /* get offsets into the two bignums */
+      ty = MIN(a->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = a->dp + tx;
+      tmpy = a->dp + ty;
+
+      /* this is the number of times the loop will iterrate, essentially
+         while (tx++ < a->used && ty-- >= 0) { ... }
+       */
+      iy = MIN(a->used-tx, ty+1);
+
+      /* now for squaring tx can never equal ty 
+       * we halve the distance since they approach at a rate of 2x
+       * and we have to round because odd cases need to be executed
+       */
+      iy = MIN(iy, (ty-tx+1)>>1);
+
+      /* execute loop */
+      for (iz = 0; iz < iy; iz++) {
+         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+      }
+
+      /* double the inner product and add carry */
+      _W = _W + _W + W1;
+
+      /* even columns have the square term in them */
+      if ((ix&1) == 0) {
+         _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
+      }
+
+      /* store it */
+      W[ix] = (mp_digit)(_W & MP_MASK);
+
+      /* make next carry */
+      W1 = _W >> ((mp_word)DIGIT_BIT);
+  }
+
+  /* setup dest */
+  olduse  = b->used;
+  b->used = a->used+a->used;
+
+  {
+    mp_digit *tmpb;
+    tmpb = b->dp;
+    for (ix = 0; ix < pa; ix++) {
+      *tmpb++ = W[ix] & MP_MASK;
+    }
+
+    /* clear unused digits [that existed in the old copy of c] */
+    for (; ix < olduse; ix++) {
+      *tmpb++ = 0;
+    }
+  }
+  mp_clamp (b);
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_MP_MUL_D_C
+/* multiply by a digit */
+static int 
+mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  mp_digit u, *tmpa, *tmpc;
+  mp_word  r;
+  int      ix, res, olduse;
+
+  /* make sure c is big enough to hold a*b */
+  if (c->alloc < a->used + 1) {
+    if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* get the original destinations used count */
+  olduse = c->used;
+
+  /* set the sign */
+  c->sign = a->sign;
+
+  /* alias for a->dp [source] */
+  tmpa = a->dp;
+
+  /* alias for c->dp [dest] */
+  tmpc = c->dp;
+
+  /* zero carry */
+  u = 0;
+
+  /* compute columns */
+  for (ix = 0; ix < a->used; ix++) {
+    /* compute product and carry sum for this term */
+    r       = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
+
+    /* mask off higher bits to get a single digit */
+    *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+    /* send carry into next iteration */
+    u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+  }
+
+  /* store final carry [if any] and increment ix offset  */
+  *tmpc++ = u;
+  ++ix;
+
+  /* now zero digits above the top */
+  while (ix++ < olduse) {
+     *tmpc++ = 0;
+  }
+
+  /* set used count */
+  c->used = a->used + 1;
+  mp_clamp(c);
+
+  return MP_OKAY;
+}
+#endif
diff --git a/components/wpa_supplicant/src/crypto/md5-internal.c b/components/wpa_supplicant/src/crypto/md5-internal.c
new file mode 100644 (file)
index 0000000..a430e29
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * MD5 hash implementation and interface functions
+ * Copyright (c) 2003-2005, 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 "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/md5.h"
+#include "crypto/md5_i.h"
+#include "crypto/crypto.h"
+
+
+static void MD5Transform(u32 buf[4], u32 const in[16]);
+
+
+typedef struct MD5Context MD5_CTX;
+
+
+/**
+ * md5_vector - MD5 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 of failure
+ */
+int 
+md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+       MD5_CTX ctx;
+       size_t i;
+
+       MD5Init(&ctx);
+       for (i = 0; i < num_elem; i++)
+               MD5Update(&ctx, addr[i], len[i]);
+       MD5Final(mac, &ctx);
+       return 0;
+}
+
+
+/* ===== start - public domain MD5 implementation ===== */
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+#ifndef WORDS_BIGENDIAN
+#define byteReverse(buf, len)  /* Nothing */
+#else
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+static void byteReverse(unsigned char *buf, unsigned longs)
+{
+    u32 t;
+    do {
+       t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+           ((unsigned) buf[1] << 8 | buf[0]);
+       *(u32 *) buf = t;
+       buf += 4;
+    } while (--longs);
+}
+#endif
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void 
+MD5Init(struct MD5Context *ctx)
+{
+    ctx->buf[0] = 0x67452301;
+    ctx->buf[1] = 0xefcdab89;
+    ctx->buf[2] = 0x98badcfe;
+    ctx->buf[3] = 0x10325476;
+
+    ctx->bits[0] = 0;
+    ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void 
+MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
+{
+    u32 t;
+
+    /* Update bitcount */
+
+    t = ctx->bits[0];
+    if ((ctx->bits[0] = t + ((u32) len << 3)) < t)
+       ctx->bits[1]++;         /* Carry from low to high */
+    ctx->bits[1] += len >> 29;
+
+    t = (t >> 3) & 0x3f;       /* Bytes already in shsInfo->data */
+
+    /* Handle any leading odd-sized chunks */
+
+    if (t) {
+       unsigned char *p = (unsigned char *) ctx->in + t;
+
+       t = 64 - t;
+       if (len < t) {
+           os_memcpy(p, buf, len);
+           return;
+       }
+       os_memcpy(p, buf, t);
+       byteReverse(ctx->in, 16);
+       MD5Transform(ctx->buf, (u32 *) ctx->in);
+       buf += t;
+       len -= t;
+    }
+    /* Process data in 64-byte chunks */
+
+    while (len >= 64) {
+       os_memcpy(ctx->in, buf, 64);
+       byteReverse(ctx->in, 16);
+       MD5Transform(ctx->buf, (u32 *) ctx->in);
+       buf += 64;
+       len -= 64;
+    }
+
+    /* Handle any remaining bytes of data. */
+
+    os_memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void 
+MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+{
+    unsigned count;
+    unsigned char *p;
+
+    /* Compute number of bytes mod 64 */
+    count = (ctx->bits[0] >> 3) & 0x3F;
+
+    /* Set the first char of padding to 0x80.  This is safe since there is
+       always at least one byte free */
+    p = ctx->in + count;
+    *p++ = 0x80;
+
+    /* Bytes of padding needed to make 64 bytes */
+    count = 64 - 1 - count;
+
+    /* Pad out to 56 mod 64 */
+    if (count < 8) {
+       /* Two lots of padding:  Pad the first block to 64 bytes */
+       os_memset(p, 0, count);
+       byteReverse(ctx->in, 16);
+       MD5Transform(ctx->buf, (u32 *) ctx->in);
+
+       /* Now fill the next block with 56 bytes */
+       os_memset(ctx->in, 0, 56);
+    } else {
+       /* Pad block to 56 bytes */
+       os_memset(p, 0, count - 8);
+    }
+    byteReverse(ctx->in, 14);
+
+    /* Append length in bits and transform */
+    ((u32 *) ctx->in)[14] = ctx->bits[0];
+    ((u32 *) ctx->in)[15] = ctx->bits[1];
+
+    MD5Transform(ctx->buf, (u32 *) ctx->in);
+    byteReverse((unsigned char *) ctx->buf, 4);
+    os_memcpy(digest, ctx->buf, 16);
+    os_memset(ctx, 0, sizeof(struct MD5Context));      /* In case it's sensitive */
+}
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+       ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void 
+MD5Transform(u32 buf[4], u32 const in[16])
+{
+    register u32 a, b, c, d;
+
+    a = buf[0];
+    b = buf[1];
+    c = buf[2];
+    d = buf[3];
+
+    MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+    MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+    MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+    MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+    MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+    MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+    MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+    MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+    MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+    MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+    MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+    MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+    MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+    MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+    MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+    MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+    MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+    MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+    MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+    MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+    MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+    MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+    MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+    MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+    MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+    MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+    MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+    MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+    MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+    MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+    MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+    MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+    MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+    MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+    MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+    MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+    MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+    MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+    MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+    MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+    MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+    MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+    MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+    MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+    MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+    MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+    MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+    MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+    MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+    MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+    MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+    MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+    MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+    MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+    MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+    MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+    MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+    MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+    MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+    MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+    MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+    MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+    MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+    MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+    buf[0] += a;
+    buf[1] += b;
+    buf[2] += c;
+    buf[3] += d;
+}
+/* ===== end - public domain MD5 implementation ===== */
diff --git a/components/wpa_supplicant/src/crypto/md5.c b/components/wpa_supplicant/src/crypto/md5.c
new file mode 100644 (file)
index 0000000..3125c98
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * MD5 hash implementation and interface functions
+ * Copyright (c) 2003-2005, 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 "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/md5.h"
+#include "crypto/crypto.h"
+
+
+/**
+ * hmac_md5_vector - HMAC-MD5 over data vector (RFC 2104)
+ * @key: Key for HMAC operations
+ * @key_len: Length of the key in bytes
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash (16 bytes)
+ * Returns: 0 on success, -1 on failure
+ */
+int 
+hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
+                   const u8 *addr[], const size_t *len, u8 *mac)
+{
+       u8 k_pad[64]; /* padding - key XORd with ipad/opad */
+       u8 tk[16];
+       const u8 *_addr[6];
+       size_t i, _len[6];
+
+       if (num_elem > 5) {
+               /*
+                * Fixed limit on the number of fragments to avoid having to
+                * allocate memory (which could fail).
+                */
+               return -1;
+       }
+
+        /* if key is longer than 64 bytes reset it to key = MD5(key) */
+        if (key_len > 64) {
+               if (md5_vector(1, &key, &key_len, tk))
+                       return -1;
+               key = tk;
+               key_len = 16;
+        }
+
+       /* the HMAC_MD5 transform looks like:
+        *
+        * MD5(K XOR opad, MD5(K XOR ipad, text))
+        *
+        * where K is an n byte key
+        * ipad is the byte 0x36 repeated 64 times
+        * opad is the byte 0x5c repeated 64 times
+        * and text is the data being protected */
+
+       /* start out by storing key in ipad */
+       os_memset(k_pad, 0, sizeof(k_pad));
+       os_memcpy(k_pad, key, key_len);
+
+       /* XOR key with ipad values */
+       for (i = 0; i < 64; i++)
+               k_pad[i] ^= 0x36;
+
+       /* perform inner MD5 */
+       _addr[0] = k_pad;
+       _len[0] = 64;
+       for (i = 0; i < num_elem; i++) {
+               _addr[i + 1] = addr[i];
+               _len[i + 1] = len[i];
+       }
+       if (md5_vector(1 + num_elem, _addr, _len, mac))
+               return -1;
+
+       os_memset(k_pad, 0, sizeof(k_pad));
+       os_memcpy(k_pad, key, key_len);
+       /* XOR key with opad values */
+       for (i = 0; i < 64; i++)
+               k_pad[i] ^= 0x5c;
+
+       /* perform outer MD5 */
+       _addr[0] = k_pad;
+       _len[0] = 64;
+       _addr[1] = mac;
+       _len[1] = MD5_MAC_LEN;
+       return md5_vector(2, _addr, _len, mac);
+}
+
+
+/**
+ * hmac_md5 - HMAC-MD5 over data buffer (RFC 2104)
+ * @key: Key for HMAC operations
+ * @key_len: Length of the key in bytes
+ * @data: Pointers to the data area
+ * @data_len: Length of the data area
+ * @mac: Buffer for the hash (16 bytes)
+ * Returns: 0 on success, -1 on failure
+ */
+int 
+hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
+             u8 *mac)
+{
+       return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
+}
diff --git a/components/wpa_supplicant/src/crypto/rc4.c b/components/wpa_supplicant/src/crypto/rc4.c
new file mode 100644 (file)
index 0000000..6786322
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * RC4 stream cipher
+ * Copyright (c) 2002-2005, 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 "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/crypto.h"
+
+#define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
+
+int 
+rc4_skip(const u8 *key, size_t keylen, size_t skip,
+            u8 *data, size_t data_len)
+{
+       u32 i, j, k;
+       u8 S[256], *pos;
+       size_t kpos;
+
+       /* Setup RC4 state */
+       for (i = 0; i < 256; i++)
+               S[i] = i;
+       j = 0;
+       kpos = 0;
+       for (i = 0; i < 256; i++) {
+               j = (j + S[i] + key[kpos]) & 0xff;
+               kpos++;
+               if (kpos >= keylen)
+                       kpos = 0;
+               S_SWAP(i, j);
+       }
+
+       /* Skip the start of the stream */
+       i = j = 0;
+       for (k = 0; k < skip; k++) {
+               i = (i + 1) & 0xff;
+               j = (j + S[i]) & 0xff;
+               S_SWAP(i, j);
+       }
+
+       /* Apply RC4 to data */
+       pos = data;
+       for (k = 0; k < data_len; k++) {
+               i = (i + 1) & 0xff;
+               j = (j + S[i]) & 0xff;
+               S_SWAP(i, j);
+               *pos++ ^= S[(S[i] + S[j]) & 0xff];
+       }
+
+       return 0;
+}
diff --git a/components/wpa_supplicant/src/crypto/sha1-internal.c b/components/wpa_supplicant/src/crypto/sha1-internal.c
new file mode 100644 (file)
index 0000000..a1c255e
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * SHA1 hash implementation and interface functions
+ * Copyright (c) 2003-2005, 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 "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/sha1.h"
+#include "crypto/sha1_i.h"
+#include "crypto/md5.h"
+#include "crypto/crypto.h"
+
+typedef struct SHA1Context SHA1_CTX;
+
+void SHA1Transform(u32 state[5], const unsigned char buffer[64]);
+
+
+/**
+ * sha1_vector - SHA-1 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 of failure
+ */
+int 
+sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+       SHA1_CTX ctx;
+       size_t i;
+
+       SHA1Init(&ctx);
+       for (i = 0; i < num_elem; i++)
+               SHA1Update(&ctx, addr[i], len[i]);
+       SHA1Final(mac, &ctx);
+       return 0;
+}
+
+
+/* ===== start - public domain SHA1 implementation ===== */
+
+/*
+SHA-1 in C
+By Steve Reid <sreid@sea-to-sky.net>
+100% Public Domain
+
+-----------------
+Modified 7/98 
+By James H. Brown <jbrown@burgoyne.com>
+Still 100% Public Domain
+
+Corrected a problem which generated improper hash values on 16 bit machines
+Routine SHA1Update changed from
+       void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
+len)
+to
+       void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
+long len)
+
+The 'len' parameter was declared an int which works fine on 32 bit machines.
+However, on 16 bit machines an int is too small for the shifts being done
+against
+it.  This caused the hash function to generate incorrect values if len was
+greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
+
+Since the file IO in main() reads 16K at a time, any file 8K or larger would
+be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
+"a"s).
+
+I also changed the declaration of variables i & j in SHA1Update to 
+unsigned long from unsigned int for the same reason.
+
+These changes should make no difference to any 32 bit implementations since
+an
+int and a long are the same size in those environments.
+
+--
+I also corrected a few compiler warnings generated by Borland C.
+1. Added #include <process.h> for exit() prototype
+2. Removed unused variable 'j' in SHA1Final
+3. Changed exit(0) to return(0) at end of main.
+
+ALL changes I made can be located by searching for comments containing 'JHB'
+-----------------
+Modified 8/98
+By Steve Reid <sreid@sea-to-sky.net>
+Still 100% public domain
+
+1- Removed #include <process.h> and used return() instead of exit()
+2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
+3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
+
+-----------------
+Modified 4/01
+By Saul Kravitz <Saul.Kravitz@celera.com>
+Still 100% PD
+Modified to run on Compaq Alpha hardware.  
+
+-----------------
+Modified 4/01
+By Jouni Malinen <j@w1.fi>
+Minor changes to match the coding style used in Dynamics.
+
+Modified September 24, 2004
+By Jouni Malinen <j@w1.fi>
+Fixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined.
+
+*/
+
+/*
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+  A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+  84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+  34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+#define SHA1HANDSOFF
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#ifndef WORDS_BIGENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \
+       (rol(block->l[i], 8) & 0x00FF00FF))
+#else
+#define blk0(i) block->l[i]
+#endif
+#define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \
+       block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) \
+       z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
+       w = rol(w, 30);
+#define R1(v,w,x,y,z,i) \
+       z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
+       w = rol(w, 30);
+#define R2(v,w,x,y,z,i) \
+       z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30);
+#define R3(v,w,x,y,z,i) \
+       z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
+       w = rol(w, 30);
+#define R4(v,w,x,y,z,i) \
+       z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
+       w=rol(w, 30);
+
+
+#ifdef VERBOSE  /* SAK */
+void SHAPrintContext(SHA1_CTX *context, char *msg)
+{
+       printf("%s (%d,%d) %x %x %x %x %x\n",
+              msg,
+              context->count[0], context->count[1], 
+              context->state[0],
+              context->state[1],
+              context->state[2],
+              context->state[3],
+              context->state[4]);
+}
+#endif
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void 
+SHA1Transform(u32 state[5], const unsigned char buffer[64])
+{
+       u32 a, b, c, d, e;
+       typedef union {
+               unsigned char c[64];
+               u32 l[16];
+       } CHAR64LONG16;
+       CHAR64LONG16* block;
+#ifdef SHA1HANDSOFF
+       CHAR64LONG16 workspace;
+       block = &workspace;
+       os_memcpy(block, buffer, 64);
+#else
+       block = (CHAR64LONG16 *) buffer;
+#endif
+       /* Copy context->state[] to working vars */
+       a = state[0];
+       b = state[1];
+       c = state[2];
+       d = state[3];
+       e = state[4];
+       /* 4 rounds of 20 operations each. Loop unrolled. */
+       R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+       R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+       R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+       R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+       R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+       R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+       R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+       R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+       R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+       R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+       R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+       R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+       R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+       R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+       R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+       R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+       R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+       R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+       R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+       R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+       /* Add the working vars back into context.state[] */
+       state[0] += a;
+       state[1] += b;
+       state[2] += c;
+       state[3] += d;
+       state[4] += e;
+       /* Wipe variables */
+       a = b = c = d = e = 0;
+#ifdef SHA1HANDSOFF
+       os_memset(block, 0, 64);
+#endif
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void 
+SHA1Init(SHA1_CTX* context)
+{
+       /* SHA1 initialization constants */
+       context->state[0] = 0x67452301;
+       context->state[1] = 0xEFCDAB89;
+       context->state[2] = 0x98BADCFE;
+       context->state[3] = 0x10325476;
+       context->state[4] = 0xC3D2E1F0;
+       context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void 
+SHA1Update(SHA1_CTX* context, const void *_data, u32 len)
+{
+       u32 i, j;
+       const unsigned char *data = _data;
+
+#ifdef VERBOSE
+       SHAPrintContext(context, "before");
+#endif
+       j = (context->count[0] >> 3) & 63;
+       if ((context->count[0] += len << 3) < (len << 3))
+               context->count[1]++;
+       context->count[1] += (len >> 29);
+       if ((j + len) > 63) {
+               os_memcpy(&context->buffer[j], data, (i = 64-j));
+               SHA1Transform(context->state, context->buffer);
+               for ( ; i + 63 < len; i += 64) {
+                       SHA1Transform(context->state, &data[i]);
+               }
+               j = 0;
+       }
+       else i = 0;
+       os_memcpy(&context->buffer[j], &data[i], len - i);
+#ifdef VERBOSE
+       SHAPrintContext(context, "after ");
+#endif
+}
+
+
+/* Add padding and return the message digest. */
+
+void 
+SHA1Final(unsigned char digest[20], SHA1_CTX* context)
+{
+       u32 i;
+       unsigned char finalcount[8];
+
+       for (i = 0; i < 8; i++) {
+               finalcount[i] = (unsigned char)
+                       ((context->count[(i >= 4 ? 0 : 1)] >>
+                         ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
+       }
+       SHA1Update(context, (unsigned char *) "\200", 1);
+       while ((context->count[0] & 504) != 448) {
+               SHA1Update(context, (unsigned char *) "\0", 1);
+       }
+       SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform()
+                                             */
+       for (i = 0; i < 20; i++) {
+               digest[i] = (unsigned char)
+                       ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) &
+                        255);
+       }
+       /* Wipe variables */
+       i = 0;
+       os_memset(context->buffer, 0, 64);
+       os_memset(context->state, 0, 20);
+       os_memset(context->count, 0, 8);
+       os_memset(finalcount, 0, 8);
+}
+
+/* ===== end - public domain SHA1 implementation ===== */
diff --git a/components/wpa_supplicant/src/crypto/sha1-pbkdf2.c b/components/wpa_supplicant/src/crypto/sha1-pbkdf2.c
new file mode 100644 (file)
index 0000000..915a23a
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * SHA1-based key derivation function (PBKDF2) for IEEE 802.11i
+ * Copyright (c) 2003-2005, 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 "crypto/includes.h"
+#include "crypto/common.h"
+#include "crypto/sha1.h"
+#include "crypto/md5.h"
+#include "crypto/crypto.h"
+
+static int 
+pbkdf2_sha1_f(const char *passphrase, const char *ssid,
+                        size_t ssid_len, int iterations, unsigned int count,
+                        u8 *digest)
+{
+       unsigned char tmp[SHA1_MAC_LEN], tmp2[SHA1_MAC_LEN];
+       int i, j;
+       unsigned char count_buf[4];
+       const u8 *addr[2];
+       size_t len[2];
+       size_t passphrase_len = os_strlen(passphrase);
+
+       addr[0] = (u8 *) ssid;
+       len[0] = ssid_len;
+       addr[1] = count_buf;
+       len[1] = 4;
+
+       /* F(P, S, c, i) = U1 xor U2 xor ... Uc
+        * U1 = PRF(P, S || i)
+        * U2 = PRF(P, U1)
+        * Uc = PRF(P, Uc-1)
+        */
+
+       count_buf[0] = (count >> 24) & 0xff;
+       count_buf[1] = (count >> 16) & 0xff;
+       count_buf[2] = (count >> 8) & 0xff;
+       count_buf[3] = count & 0xff;
+       if (hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len,
+                            tmp))
+               return -1;
+       os_memcpy(digest, tmp, SHA1_MAC_LEN);
+
+       for (i = 1; i < iterations; i++) {
+               if (hmac_sha1((u8 *) passphrase, passphrase_len, tmp,
+                             SHA1_MAC_LEN, tmp2))
+                       return -1;
+               os_memcpy(tmp, tmp2, SHA1_MAC_LEN);
+               for (j = 0; j < SHA1_MAC_LEN; j++)
+                       digest[j] ^= tmp2[j];
+       }
+
+       return 0;
+}
+
+
+/**
+ * pbkdf2_sha1 - SHA1-based key derivation function (PBKDF2) for IEEE 802.11i
+ * @passphrase: ASCII passphrase
+ * @ssid: SSID
+ * @ssid_len: SSID length in bytes
+ * @iterations: Number of iterations to run
+ * @buf: Buffer for the generated key
+ * @buflen: Length of the buffer in bytes
+ * Returns: 0 on success, -1 of failure
+ *
+ * This function is used to derive PSK for WPA-PSK. For this protocol,
+ * iterations is set to 4096 and buflen to 32. This function is described in
+ * IEEE Std 802.11-2004, Clause H.4. The main construction is from PKCS#5 v2.0.
+ */
+int 
+pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
+               int iterations, u8 *buf, size_t buflen)
+{
+       unsigned int count = 0;
+       unsigned char *pos = buf;
+       size_t left = buflen, plen;
+       unsigned char digest[SHA1_MAC_LEN];
+
+       while (left > 0) {
+               count++;
+               if (pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations,
+                                 count, digest))
+                       return -1;
+               plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left;
+               os_memcpy(pos, digest, plen);
+               pos += plen;
+               left -= plen;
+       }
+
+       return 0;
+}
diff --git a/components/wpa_supplicant/src/crypto/sha1.c b/components/wpa_supplicant/src/crypto/sha1.c
new file mode 100644 (file)
index 0000000..3d6da41
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * SHA1 hash implementation and interface functions
+ * Copyright (c) 2003-2005, 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 "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/sha1.h"
+#include "crypto/crypto.h"
+
+
+/**
+ * hmac_sha1_vector - HMAC-SHA1 over data vector (RFC 2104)
+ * @key: Key for HMAC operations
+ * @key_len: Length of the key in bytes
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash (20 bytes)
+ * Returns: 0 on success, -1 on failure
+ */
+int 
+hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
+                    const u8 *addr[], const size_t *len, u8 *mac)
+{
+       unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
+       unsigned char tk[20];
+       const u8 *_addr[6];
+       size_t _len[6], i;
+
+       if (num_elem > 5) {
+               /*
+                * Fixed limit on the number of fragments to avoid having to
+                * allocate memory (which could fail).
+                */
+               return -1;
+       }
+
+        /* if key is longer than 64 bytes reset it to key = SHA1(key) */
+        if (key_len > 64) {
+               if (sha1_vector(1, &key, &key_len, tk))
+                       return -1;
+               key = tk;
+               key_len = 20;
+        }
+
+       /* the HMAC_SHA1 transform looks like:
+        *
+        * SHA1(K XOR opad, SHA1(K XOR ipad, text))
+        *
+        * where K is an n byte key
+        * ipad is the byte 0x36 repeated 64 times
+        * opad is the byte 0x5c repeated 64 times
+        * and text is the data being protected */
+
+       /* start out by storing key in ipad */
+       os_memset(k_pad, 0, sizeof(k_pad));
+       os_memcpy(k_pad, key, key_len);
+       /* XOR key with ipad values */
+       for (i = 0; i < 64; i++)
+               k_pad[i] ^= 0x36;
+
+       /* perform inner SHA1 */
+       _addr[0] = k_pad;
+       _len[0] = 64;
+       for (i = 0; i < num_elem; i++) {
+               _addr[i + 1] = addr[i];
+               _len[i + 1] = len[i];
+       }
+       if (sha1_vector(1 + num_elem, _addr, _len, mac))
+               return -1;
+
+       os_memset(k_pad, 0, sizeof(k_pad));
+       os_memcpy(k_pad, key, key_len);
+       /* XOR key with opad values */
+       for (i = 0; i < 64; i++)
+               k_pad[i] ^= 0x5c;
+
+       /* perform outer SHA1 */
+       _addr[0] = k_pad;
+       _len[0] = 64;
+       _addr[1] = mac;
+       _len[1] = SHA1_MAC_LEN;
+       return sha1_vector(2, _addr, _len, mac);
+}
+
+
+/**
+ * hmac_sha1 - HMAC-SHA1 over data buffer (RFC 2104)
+ * @key: Key for HMAC operations
+ * @key_len: Length of the key in bytes
+ * @data: Pointers to the data area
+ * @data_len: Length of the data area
+ * @mac: Buffer for the hash (20 bytes)
+ * Returns: 0 on success, -1 of failure
+ */
+int 
+hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
+              u8 *mac)
+{
+       return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
+}
+
+/**
+ * sha1_prf - SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1)
+ * @key: Key for PRF
+ * @key_len: Length of the key in bytes
+ * @label: A unique label for each purpose of the PRF
+ * @data: Extra data to bind into the key
+ * @data_len: Length of the data
+ * @buf: Buffer for the generated pseudo-random key
+ * @buf_len: Number of bytes of key to generate
+ * Returns: 0 on success, -1 of failure
+ *
+ * This function is used to derive new, cryptographically separate keys from a
+ * given key (e.g., PMK in IEEE 802.11i).
+ */
+int 
+sha1_prf(const u8 *key, size_t key_len, const char *label,
+            const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
+{
+       u8 counter = 0;
+       size_t pos, plen;
+       u8 hash[SHA1_MAC_LEN];
+       size_t label_len = os_strlen(label) + 1;
+       const unsigned char *addr[3];
+       size_t len[3];
+
+       addr[0] = (u8 *) label;
+       len[0] = label_len;
+       addr[1] = data;
+       len[1] = data_len;
+       addr[2] = &counter;
+       len[2] = 1;
+
+       pos = 0;
+       while (pos < buf_len) {
+               plen = buf_len - pos;
+               if (plen >= SHA1_MAC_LEN) {
+                       if (hmac_sha1_vector(key, key_len, 3, addr, len,
+                                            &buf[pos]))
+                               return -1;
+                       pos += SHA1_MAC_LEN;
+               } else {
+                       if (hmac_sha1_vector(key, key_len, 3, addr, len,
+                                            hash))
+                               return -1;
+                       os_memcpy(&buf[pos], hash, plen);
+                       break;
+               }
+               counter++;
+       }
+
+       return 0;
+}
+
diff --git a/components/wpa_supplicant/src/crypto/sha256-internal.c b/components/wpa_supplicant/src/crypto/sha256-internal.c
new file mode 100644 (file)
index 0000000..9a1fca1
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * SHA-256 hash implementation and interface functions
+ * Copyright (c) 2003-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.
+ */
+
+#include "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/sha256.h"
+#include "crypto/crypto.h"
+
+#define SHA256_BLOCK_SIZE 64
+
+struct sha256_state {
+       u64 length;
+       u32 state[8], curlen;
+       u8 buf[SHA256_BLOCK_SIZE];
+};
+
+static void sha256_init(struct sha256_state *md);
+static int sha256_process(struct sha256_state *md, const unsigned char *in,
+                         unsigned long inlen);
+static int sha256_done(struct sha256_state *md, unsigned char *out);
+
+
+/**
+ * sha256_vector - SHA256 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 of failure
+ */
+int 
+sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
+                 u8 *mac)
+{
+       struct sha256_state ctx;
+       size_t i;
+
+       sha256_init(&ctx);
+       for (i = 0; i < num_elem; i++)
+               if (sha256_process(&ctx, addr[i], len[i]))
+                       return -1;
+       if (sha256_done(&ctx, mac))
+               return -1;
+       return 0;
+}
+
+
+/* ===== start - public domain SHA256 implementation ===== */
+
+/* This is based on SHA256 implementation in LibTomCrypt that was released into
+ * public domain by Tom St Denis. */
+
+/* the K array */
+static const unsigned long K[64] = {
+       0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
+       0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
+       0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
+       0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+       0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
+       0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
+       0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
+       0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+       0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
+       0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
+       0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
+       0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+       0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+
+/* Various logical functions */
+#define RORc(x, y) \
+( ((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \
+   ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
+#define Ch(x,y,z)       (z ^ (x & (y ^ z)))
+#define Maj(x,y,z)      (((x | y) & z) | (x & y)) 
+#define S(x, n)         RORc((x), (n))
+#define R(x, n)         (((x)&0xFFFFFFFFUL)>>(n))
+#define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
+#define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
+#define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
+#define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
+#ifndef MIN
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#endif
+
+/* compress 512-bits */
+static int 
+sha256_compress(struct sha256_state *md, unsigned char *buf)
+{
+       u32 S[8], W[64], t0, t1;
+       u32 t;
+       int i;
+
+       /* copy state into S */
+       for (i = 0; i < 8; i++) {
+               S[i] = md->state[i];
+       }
+
+       /* copy the state into 512-bits into W[0..15] */
+       for (i = 0; i < 16; i++)
+               W[i] = WPA_GET_BE32(buf + (4 * i));
+
+       /* fill W[16..63] */
+       for (i = 16; i < 64; i++) {
+               W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
+                       W[i - 16];
+       }        
+
+       /* Compress */
+#define RND(a,b,c,d,e,f,g,h,i)                          \
+       t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
+       t1 = Sigma0(a) + Maj(a, b, c);                  \
+       d += t0;                                        \
+       h  = t0 + t1;
+
+       for (i = 0; i < 64; ++i) {
+               RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
+               t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; 
+               S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
+       }
+
+       /* feedback */
+       for (i = 0; i < 8; i++) {
+               md->state[i] = md->state[i] + S[i];
+       }
+       return 0;
+}
+
+
+/* Initialize the hash state */
+static void 
+sha256_init(struct sha256_state *md)
+{
+       md->curlen = 0;
+       md->length = 0;
+       md->state[0] = 0x6A09E667UL;
+       md->state[1] = 0xBB67AE85UL;
+       md->state[2] = 0x3C6EF372UL;
+       md->state[3] = 0xA54FF53AUL;
+       md->state[4] = 0x510E527FUL;
+       md->state[5] = 0x9B05688CUL;
+       md->state[6] = 0x1F83D9ABUL;
+       md->state[7] = 0x5BE0CD19UL;
+}
+
+/**
+   Process a block of memory though the hash
+   @param md     The hash state
+   @param in     The data to hash
+   @param inlen  The length of the data (octets)
+   @return CRYPT_OK if successful
+*/
+static int 
+sha256_process(struct sha256_state *md, const unsigned char *in,
+                         unsigned long inlen)
+{
+       unsigned long n;
+
+       if (md->curlen >= sizeof(md->buf))
+               return -1;
+
+       while (inlen > 0) {
+               if (md->curlen == 0 && inlen >= SHA256_BLOCK_SIZE) {
+                       if (sha256_compress(md, (unsigned char *) in) < 0)
+                               return -1;
+                       md->length += SHA256_BLOCK_SIZE * 8;
+                       in += SHA256_BLOCK_SIZE;
+                       inlen -= SHA256_BLOCK_SIZE;
+               } else {
+                       n = MIN(inlen, (SHA256_BLOCK_SIZE - md->curlen));
+                       os_memcpy(md->buf + md->curlen, in, n);
+                       md->curlen += n;
+                       in += n;
+                       inlen -= n;
+                       if (md->curlen == SHA256_BLOCK_SIZE) {
+                               if (sha256_compress(md, md->buf) < 0)
+                                       return -1;
+                               md->length += 8 * SHA256_BLOCK_SIZE;
+                               md->curlen = 0;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+
+/**
+   Terminate the hash to get the digest
+   @param md  The hash state
+   @param out [out] The destination of the hash (32 bytes)
+   @return CRYPT_OK if successful
+*/
+static int 
+sha256_done(struct sha256_state *md, unsigned char *out)
+{
+       int i;
+
+       if (md->curlen >= sizeof(md->buf))
+               return -1;
+
+       /* increase the length of the message */
+       md->length += md->curlen * 8;
+
+       /* append the '1' bit */
+       md->buf[md->curlen++] = (unsigned char) 0x80;
+
+       /* if the length is currently above 56 bytes we append zeros
+        * then compress.  Then we can fall back to padding zeros and length
+        * encoding like normal.
+        */
+       if (md->curlen > 56) {
+               while (md->curlen < SHA256_BLOCK_SIZE) {
+                       md->buf[md->curlen++] = (unsigned char) 0;
+               }
+               sha256_compress(md, md->buf);
+               md->curlen = 0;
+       }
+
+       /* pad up to 56 bytes of zeroes */
+       while (md->curlen < 56) {
+               md->buf[md->curlen++] = (unsigned char) 0;
+       }
+
+       /* store length */
+       WPA_PUT_BE64(md->buf + 56, md->length);
+       sha256_compress(md, md->buf);
+
+       /* copy output */
+       for (i = 0; i < 8; i++)
+               WPA_PUT_BE32(out + (4 * i), md->state[i]);
+
+       return 0;
+}
+
+/* ===== end - public domain SHA256 implementation ===== */
diff --git a/components/wpa_supplicant/src/crypto/sha256.c b/components/wpa_supplicant/src/crypto/sha256.c
new file mode 100644 (file)
index 0000000..f62cc11
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * SHA-256 hash implementation and interface functions
+ * Copyright (c) 2003-2007, 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 "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/sha256.h"
+#include "crypto/crypto.h"
+
+
+/**
+ * hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104)
+ * @key: Key for HMAC operations
+ * @key_len: Length of the key in bytes
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash (32 bytes)
+ */
+void 
+hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
+                       const u8 *addr[], const size_t *len, u8 *mac)
+{
+       unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
+       unsigned char tk[32];
+       const u8 *_addr[6];
+       size_t _len[6], i;
+
+       if (num_elem > 5) {
+               /*
+                * Fixed limit on the number of fragments to avoid having to
+                * allocate memory (which could fail).
+                */
+               return;
+       }
+
+        /* if key is longer than 64 bytes reset it to key = SHA256(key) */
+        if (key_len > 64) {
+               sha256_vector(1, &key, &key_len, tk);
+               key = tk;
+               key_len = 32;
+        }
+
+       /* the HMAC_SHA256 transform looks like:
+        *
+        * SHA256(K XOR opad, SHA256(K XOR ipad, text))
+        *
+        * where K is an n byte key
+        * ipad is the byte 0x36 repeated 64 times
+        * opad is the byte 0x5c repeated 64 times
+        * and text is the data being protected */
+
+       /* start out by storing key in ipad */
+       os_memset(k_pad, 0, sizeof(k_pad));
+       os_memcpy(k_pad, key, key_len);
+       /* XOR key with ipad values */
+       for (i = 0; i < 64; i++)
+               k_pad[i] ^= 0x36;
+
+       /* perform inner SHA256 */
+       _addr[0] = k_pad;
+       _len[0] = 64;
+       for (i = 0; i < num_elem; i++) {
+               _addr[i + 1] = addr[i];
+               _len[i + 1] = len[i];
+       }
+       sha256_vector(1 + num_elem, _addr, _len, mac);
+
+       os_memset(k_pad, 0, sizeof(k_pad));
+       os_memcpy(k_pad, key, key_len);
+       /* XOR key with opad values */
+       for (i = 0; i < 64; i++)
+               k_pad[i] ^= 0x5c;
+
+       /* perform outer SHA256 */
+       _addr[0] = k_pad;
+       _len[0] = 64;
+       _addr[1] = mac;
+       _len[1] = SHA256_MAC_LEN;
+       sha256_vector(2, _addr, _len, mac);
+}
+
+
+/**
+ * hmac_sha256 - HMAC-SHA256 over data buffer (RFC 2104)
+ * @key: Key for HMAC operations
+ * @key_len: Length of the key in bytes
+ * @data: Pointers to the data area
+ * @data_len: Length of the data area
+ * @mac: Buffer for the hash (20 bytes)
+ */
+void 
+hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
+                size_t data_len, u8 *mac)
+{
+       hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
+}
+
+
+/**
+ * sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2)
+ * @key: Key for PRF
+ * @key_len: Length of the key in bytes
+ * @label: A unique label for each purpose of the PRF
+ * @data: Extra data to bind into the key
+ * @data_len: Length of the data
+ * @buf: Buffer for the generated pseudo-random key
+ * @buf_len: Number of bytes of key to generate
+ *
+ * This function is used to derive new, cryptographically separate keys from a
+ * given key.
+ */
+void 
+sha256_prf(const u8 *key, size_t key_len, const char *label,
+               const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
+{
+       u16 counter = 1;
+       size_t pos, plen;
+       u8 hash[SHA256_MAC_LEN];
+       const u8 *addr[4];
+       size_t len[4];
+       u8 counter_le[2], length_le[2];
+
+       addr[0] = counter_le;
+       len[0] = 2;
+       addr[1] = (u8 *) label;
+       len[1] = os_strlen(label);
+       addr[2] = data;
+       len[2] = data_len;
+       addr[3] = length_le;
+       len[3] = sizeof(length_le);
+
+       WPA_PUT_LE16(length_le, buf_len * 8);
+       pos = 0;
+       while (pos < buf_len) {
+               plen = buf_len - pos;
+               WPA_PUT_LE16(counter_le, counter);
+               if (plen >= SHA256_MAC_LEN) {
+                       hmac_sha256_vector(key, key_len, 4, addr, len,
+                                          &buf[pos]);
+                       pos += SHA256_MAC_LEN;
+               } else {
+                       hmac_sha256_vector(key, key_len, 4, addr, len, hash);
+                       os_memcpy(&buf[pos], hash, plen);
+                       break;
+               }
+               counter++;
+       }
+}