[pkg-wpa-devel] r967 - in /wpasupplicant/branches/upstream/current: src/ src/common/ src/crypto/ src/drivers/ src/eap_common/ src/eap_peer/ src/eap_server/ src/hlr_auc_gw/ src/tls/ src/utils/ src/wps/ wpa_supplicant/ wpa_supplicant/vs2005/eapol_test/ wpa_supplicant/vs2005/wpa_supplicant/ wpa_supplicant/vs2005/wpasvc/ wpa_supplicant/wpa_gui-qt4/ wpa_supplicant/wpa_gui/
kelmo-guest at users.alioth.debian.org
kelmo-guest at users.alioth.debian.org
Tue Jan 1 13:50:31 UTC 2008
Author: kelmo-guest
Date: Tue Jan 1 13:50:28 2008
New Revision: 967
URL: http://svn.debian.org/wsvn/?sc=1&rev=967
Log:
[svn-upgrade] Integrating new upstream version, wpasupplicant (0.6.2~git20080101.5da67aa)
Added:
wpasupplicant/branches/upstream/current/src/crypto/dh_groups.c
wpasupplicant/branches/upstream/current/src/crypto/dh_groups.h
wpasupplicant/branches/upstream/current/src/eap_common/eap_ikev2_common.c
wpasupplicant/branches/upstream/current/src/eap_common/eap_ikev2_common.h
wpasupplicant/branches/upstream/current/src/eap_common/ikev2_common.c
wpasupplicant/branches/upstream/current/src/eap_common/ikev2_common.h
wpasupplicant/branches/upstream/current/src/eap_peer/eap_ikev2.c
wpasupplicant/branches/upstream/current/src/eap_peer/ikev2.c
wpasupplicant/branches/upstream/current/src/eap_peer/ikev2.h
wpasupplicant/branches/upstream/current/src/eap_server/eap_ikev2.c
wpasupplicant/branches/upstream/current/src/eap_server/ikev2.c
wpasupplicant/branches/upstream/current/src/eap_server/ikev2.h
wpasupplicant/branches/upstream/current/src/wps/
wpasupplicant/branches/upstream/current/src/wps/.gitignore
wpasupplicant/branches/upstream/current/src/wps/Makefile
wpasupplicant/branches/upstream/current/src/wps/wps.c
wpasupplicant/branches/upstream/current/src/wps/wps.h
Modified:
wpasupplicant/branches/upstream/current/src/Makefile
wpasupplicant/branches/upstream/current/src/common/wpa_common.c
wpasupplicant/branches/upstream/current/src/crypto/aes_wrap.c
wpasupplicant/branches/upstream/current/src/crypto/aes_wrap.h
wpasupplicant/branches/upstream/current/src/crypto/crypto.h
wpasupplicant/branches/upstream/current/src/crypto/crypto_internal.c
wpasupplicant/branches/upstream/current/src/crypto/crypto_openssl.c
wpasupplicant/branches/upstream/current/src/crypto/ms_funcs.c
wpasupplicant/branches/upstream/current/src/crypto/ms_funcs.h
wpasupplicant/branches/upstream/current/src/crypto/sha1.h
wpasupplicant/branches/upstream/current/src/crypto/tls.h
wpasupplicant/branches/upstream/current/src/drivers/driver.h
wpasupplicant/branches/upstream/current/src/drivers/driver_ndis.c
wpasupplicant/branches/upstream/current/src/drivers/driver_wext.c
wpasupplicant/branches/upstream/current/src/drivers/scan_helpers.c
wpasupplicant/branches/upstream/current/src/eap_common/eap_defs.h
wpasupplicant/branches/upstream/current/src/eap_common/eap_gpsk_common.c
wpasupplicant/branches/upstream/current/src/eap_common/eap_psk_common.c
wpasupplicant/branches/upstream/current/src/eap_common/eap_psk_common.h
wpasupplicant/branches/upstream/current/src/eap_common/eap_sim_common.c
wpasupplicant/branches/upstream/current/src/eap_common/eap_wsc_common.c
wpasupplicant/branches/upstream/current/src/eap_common/eap_wsc_common.h
wpasupplicant/branches/upstream/current/src/eap_peer/eap_fast.c
wpasupplicant/branches/upstream/current/src/eap_peer/eap_methods.c
wpasupplicant/branches/upstream/current/src/eap_peer/eap_mschapv2.c
wpasupplicant/branches/upstream/current/src/eap_peer/eap_psk.c
wpasupplicant/branches/upstream/current/src/eap_peer/eap_wsc.c
wpasupplicant/branches/upstream/current/src/eap_server/eap_methods.c
wpasupplicant/branches/upstream/current/src/eap_server/eap_mschapv2.c
wpasupplicant/branches/upstream/current/src/eap_server/eap_peap.c
wpasupplicant/branches/upstream/current/src/eap_server/eap_psk.c
wpasupplicant/branches/upstream/current/src/eap_server/eap_ttls.c
wpasupplicant/branches/upstream/current/src/eap_server/eap_wsc.c
wpasupplicant/branches/upstream/current/src/hlr_auc_gw/milenage.c
wpasupplicant/branches/upstream/current/src/hlr_auc_gw/milenage.h
wpasupplicant/branches/upstream/current/src/tls/bignum.c
wpasupplicant/branches/upstream/current/src/tls/tlsv1_client_write.c
wpasupplicant/branches/upstream/current/src/tls/tlsv1_server_read.c
wpasupplicant/branches/upstream/current/src/tls/tlsv1_server_write.c
wpasupplicant/branches/upstream/current/src/utils/common.h
wpasupplicant/branches/upstream/current/src/utils/wpabuf.c
wpasupplicant/branches/upstream/current/src/utils/wpabuf.h
wpasupplicant/branches/upstream/current/wpa_supplicant/ChangeLog
wpasupplicant/branches/upstream/current/wpa_supplicant/Makefile
wpasupplicant/branches/upstream/current/wpa_supplicant/README
wpasupplicant/branches/upstream/current/wpa_supplicant/README-Windows.txt
wpasupplicant/branches/upstream/current/wpa_supplicant/defconfig
wpasupplicant/branches/upstream/current/wpa_supplicant/events.c
wpasupplicant/branches/upstream/current/wpa_supplicant/vs2005/eapol_test/eapol_test.vcproj
wpasupplicant/branches/upstream/current/wpa_supplicant/vs2005/wpa_supplicant/wpa_supplicant.vcproj
wpasupplicant/branches/upstream/current/wpa_supplicant/vs2005/wpasvc/wpasvc.vcproj
wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui-qt4/setup-mingw-cross-compiling
wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui-qt4/wpagui.cpp
wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui-qt4/wpamsg.h
wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui/wpamsg.h
wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_supplicant.c
wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_supplicant.conf
Modified: wpasupplicant/branches/upstream/current/src/Makefile
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/Makefile?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/Makefile (original)
+++ wpasupplicant/branches/upstream/current/src/Makefile Tue Jan 1 13:50:28 2008
@@ -1,4 +1,4 @@
-SUBDIRS=common crypto drivers hlr_auc_gw eapol_supp eap_common eap_peer eap_server l2_packet radius rsn_supp tls utils
+SUBDIRS=common crypto drivers hlr_auc_gw eapol_supp eap_common eap_peer eap_server l2_packet radius rsn_supp tls utils wps
all:
@echo Nothing to be made.
Modified: wpasupplicant/branches/upstream/current/src/common/wpa_common.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/common/wpa_common.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/common/wpa_common.c (original)
+++ wpasupplicant/branches/upstream/current/src/common/wpa_common.c Tue Jan 1 13:50:28 2008
@@ -58,8 +58,7 @@
break;
#ifdef CONFIG_IEEE80211R
case WPA_KEY_INFO_TYPE_AES_128_CMAC:
- omac1_aes_128(key, buf, len, mic);
- break;
+ return omac1_aes_128(key, buf, len, mic);
#endif /* CONFIG_IEEE80211R */
default:
return -1;
@@ -171,9 +170,12 @@
}
wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", buf, pos - buf);
- if (use_aes_cmac)
- omac1_aes_128(kck, buf, pos - buf, mic);
- else
+ if (use_aes_cmac) {
+ if (omac1_aes_128(kck, buf, pos - buf, mic)) {
+ os_free(buf);
+ return -1;
+ }
+ } else
hmac_md5(kck, 16, buf, pos - buf, mic);
os_free(buf);
Modified: wpasupplicant/branches/upstream/current/src/crypto/aes_wrap.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/crypto/aes_wrap.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/crypto/aes_wrap.c (original)
+++ wpasupplicant/branches/upstream/current/src/crypto/aes_wrap.c Tue Jan 1 13:50:28 2008
@@ -345,7 +345,7 @@
u8 *buf;
size_t buf_len;
u8 nonce_mac[BLOCK_SIZE], hdr_mac[BLOCK_SIZE], data_mac[BLOCK_SIZE];
- int i;
+ int i, ret = -1;
if (nonce_len > data_len)
buf_len = nonce_len;
@@ -363,23 +363,29 @@
buf[15] = 0;
os_memcpy(buf + 16, nonce, nonce_len);
- omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac);
+ if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac))
+ goto fail;
buf[15] = 1;
os_memcpy(buf + 16, hdr, hdr_len);
- omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac);
-
- aes_128_ctr_encrypt(key, nonce_mac, data, data_len);
+ if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac))
+ goto fail;
+
+ if (aes_128_ctr_encrypt(key, nonce_mac, data, data_len))
+ goto fail;
buf[15] = 2;
os_memcpy(buf + 16, data, data_len);
- omac1_aes_128(key, buf, 16 + data_len, data_mac);
-
- os_free(buf);
+ if (omac1_aes_128(key, buf, 16 + data_len, data_mac))
+ goto fail;
for (i = 0; i < BLOCK_SIZE; i++)
tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i];
- return 0;
+ ret = 0;
+fail:
+ os_free(buf);
+
+ return ret;
}
@@ -420,15 +426,24 @@
buf[15] = 0;
os_memcpy(buf + 16, nonce, nonce_len);
- omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac);
+ if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) {
+ os_free(buf);
+ return -1;
+ }
buf[15] = 1;
os_memcpy(buf + 16, hdr, hdr_len);
- omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac);
+ if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) {
+ os_free(buf);
+ return -1;
+ }
buf[15] = 2;
os_memcpy(buf + 16, data, data_len);
- omac1_aes_128(key, buf, 16 + data_len, data_mac);
+ if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) {
+ os_free(buf);
+ return -1;
+ }
os_free(buf);
@@ -437,9 +452,7 @@
return -2;
}
- aes_128_ctr_encrypt(key, nonce_mac, data, data_len);
-
- return 0;
+ return aes_128_ctr_encrypt(key, nonce_mac, data, data_len);
}
#endif /* CONFIG_NO_AES_EAX */
Modified: wpasupplicant/branches/upstream/current/src/crypto/aes_wrap.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/crypto/aes_wrap.h?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/crypto/aes_wrap.h (original)
+++ wpasupplicant/branches/upstream/current/src/crypto/aes_wrap.h Tue Jan 1 13:50:28 2008
@@ -22,23 +22,27 @@
#ifndef AES_WRAP_H
#define AES_WRAP_H
-int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher);
-int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain);
-int omac1_aes_128_vector(const u8 *key, size_t num_elem,
- const u8 *addr[], const size_t *len, u8 *mac);
-int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac);
-int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out);
-int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
- u8 *data, size_t data_len);
-int 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 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 aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data,
- size_t data_len);
-int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data,
- size_t data_len);
+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 */
Modified: wpasupplicant/branches/upstream/current/src/crypto/crypto.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/crypto/crypto.h?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/crypto/crypto.h (original)
+++ wpasupplicant/branches/upstream/current/src/crypto/crypto.h Tue Jan 1 13:50:28 2008
@@ -1,6 +1,6 @@
/*
* WPA Supplicant / wrapper functions for crypto libraries
- * Copyright (c) 2004-2005, Jouni Malinen <j at w1.fi>
+ * Copyright (c) 2004-2007, Jouni Malinen <j at 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
@@ -67,7 +67,8 @@
* Publication 186-2 for EAP-SIM. This PRF uses a function that is similar to
* SHA-1, but has different message padding.
*/
-int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen);
+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
@@ -222,8 +223,8 @@
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
* to implement this.
*/
-int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
- u8 *crypt, size_t len);
+int __must_check crypto_cipher_encrypt(struct crypto_cipher *ctx,
+ const u8 *plain, u8 *crypt, size_t len);
/**
* crypto_cipher_decrypt - Cipher decrypt
@@ -237,8 +238,8 @@
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
* to implement this.
*/
-int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
- u8 *plain, size_t len);
+int __must_check crypto_cipher_decrypt(struct crypto_cipher *ctx,
+ const u8 *crypt, u8 *plain, size_t len);
/**
* crypto_cipher_decrypt - Free cipher context
@@ -313,9 +314,9 @@
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
* to implement this.
*/
-int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
- const u8 *in, size_t inlen,
- u8 *out, size_t *outlen);
+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)
@@ -330,9 +331,9 @@
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
* to implement this.
*/
-int crypto_private_key_decrypt_pkcs1_v15(struct crypto_private_key *key,
- const u8 *in, size_t inlen,
- u8 *out, size_t *outlen);
+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)
@@ -347,9 +348,9 @@
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
* to implement this.
*/
-int crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
- const u8 *in, size_t inlen,
- u8 *out, size_t *outlen);
+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
@@ -380,9 +381,9 @@
* @plain_len: Plaintext length (max buffer size on input, real len on output);
* Returns: 0 on success, -1 on failure
*/
-int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key,
- const u8 *crypt, size_t crypt_len,
- u8 *plain, size_t *plain_len);
+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
@@ -391,7 +392,7 @@
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
* to implement this.
*/
-int crypto_global_init(void);
+int __must_check crypto_global_init(void);
/**
* crypto_global_deinit - Deinitialize crypto wrapper
@@ -422,9 +423,9 @@
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
* to implement this.
*/
-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);
+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);
#endif /* CRYPTO_H */
Modified: wpasupplicant/branches/upstream/current/src/crypto/crypto_internal.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/crypto/crypto_internal.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/crypto/crypto_internal.c (original)
+++ wpasupplicant/branches/upstream/current/src/crypto/crypto_internal.c Tue Jan 1 13:50:28 2008
@@ -684,7 +684,7 @@
u8 *result, size_t *result_len)
{
struct bignum *bn_base, *bn_exp, *bn_modulus, *bn_result;
- int ret = 0;
+ int ret = -1;
bn_base = bignum_init();
bn_exp = bignum_init();
Modified: wpasupplicant/branches/upstream/current/src/crypto/crypto_openssl.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/crypto/crypto_openssl.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/crypto/crypto_openssl.c (original)
+++ wpasupplicant/branches/upstream/current/src/crypto/crypto_openssl.c Tue Jan 1 13:50:28 2008
@@ -19,6 +19,7 @@
#include <openssl/sha.h>
#include <openssl/des.h>
#include <openssl/aes.h>
+#include <openssl/bn.h>
#include "common.h"
#include "crypto.h"
@@ -207,3 +208,41 @@
os_free(ctx);
}
#endif /* EAP_TLS_FUNCS */
+
+
+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)
+{
+ BIGNUM *bn_base, *bn_exp, *bn_modulus, *bn_result;
+ int ret = -1;
+ BN_CTX *ctx;
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL)
+ return -1;
+
+ bn_base = BN_bin2bn(base, base_len, NULL);
+ bn_exp = BN_bin2bn(power, power_len, NULL);
+ bn_modulus = BN_bin2bn(modulus, modulus_len, NULL);
+ bn_result = BN_new();
+
+ if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL ||
+ bn_result == NULL)
+ goto error;
+
+ if (BN_mod_exp(bn_result, bn_base, bn_exp, bn_modulus, ctx) != 1)
+ goto error;
+
+ *result_len = BN_bn2bin(bn_result, result);
+ ret = 0;
+
+error:
+ BN_free(bn_base);
+ BN_free(bn_exp);
+ BN_free(bn_modulus);
+ BN_free(bn_result);
+ BN_CTX_free(ctx);
+ return ret;
+}
Added: wpasupplicant/branches/upstream/current/src/crypto/dh_groups.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/crypto/dh_groups.c?rev=967&op=file
==============================================================================
--- wpasupplicant/branches/upstream/current/src/crypto/dh_groups.c (added)
+++ wpasupplicant/branches/upstream/current/src/crypto/dh_groups.c Tue Jan 1 13:50:28 2008
@@ -1,0 +1,620 @@
+/*
+ * Diffie-Hellman groups
+ * Copyright (c) 2007, Jouni Malinen <j at w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "crypto.h"
+#include "dh_groups.h"
+
+
+/* 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
+};
+
+/* 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
+};
+
+/* 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
+};
+
+
+#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(1),
+ DH_GROUP(2),
+ DH_GROUP(5),
+ DH_GROUP(14),
+ DH_GROUP(15),
+ DH_GROUP(16),
+ DH_GROUP(17),
+ DH_GROUP(18)
+};
+
+#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 (os_get_random(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_put(shared, shared_len), &shared_len) < 0) {
+ wpabuf_free(shared);
+ wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed");
+ return NULL;
+ }
+ wpa_hexdump_buf_key(MSG_DEBUG, "DH: shared key", shared);
+
+ return shared;
+}
Added: wpasupplicant/branches/upstream/current/src/crypto/dh_groups.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/crypto/dh_groups.h?rev=967&op=file
==============================================================================
--- wpasupplicant/branches/upstream/current/src/crypto/dh_groups.h (added)
+++ wpasupplicant/branches/upstream/current/src/crypto/dh_groups.h Tue Jan 1 13:50:28 2008
@@ -1,0 +1,32 @@
+/*
+ * Diffie-Hellman groups
+ * Copyright (c) 2007, Jouni Malinen <j at 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 */
Modified: wpasupplicant/branches/upstream/current/src/crypto/ms_funcs.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/crypto/ms_funcs.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/crypto/ms_funcs.c (original)
+++ wpasupplicant/branches/upstream/current/src/crypto/ms_funcs.c Tue Jan 1 13:50:28 2008
@@ -62,7 +62,7 @@
size_t i, len;
if (password_len > 256)
- return;
+ password_len = 256;
/* Convert password into unicode */
for (i = 0; i < password_len; i++) {
@@ -391,8 +391,9 @@
* @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII)
* @old_password_len: Length of old_password
* @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT)
- */
-void new_password_encrypted_with_old_nt_password_hash(
+ * Returns: 0 on success, -1 on failure
+ */
+int new_password_encrypted_with_old_nt_password_hash(
const u8 *new_password, size_t new_password_len,
const u8 *old_password, size_t old_password_len,
u8 *encrypted_pw_block)
@@ -400,8 +401,11 @@
u8 password_hash[16];
nt_password_hash(old_password, old_password_len, password_hash);
- encrypt_pw_block_with_password_hash(new_password, new_password_len,
- password_hash, encrypted_pw_block);
+ if (encrypt_pw_block_with_password_hash(new_password, new_password_len,
+ password_hash,
+ encrypted_pw_block))
+ return -1;
+ return 0;
}
Modified: wpasupplicant/branches/upstream/current/src/crypto/ms_funcs.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/crypto/ms_funcs.h?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/crypto/ms_funcs.h (original)
+++ wpasupplicant/branches/upstream/current/src/crypto/ms_funcs.h Tue Jan 1 13:50:28 2008
@@ -47,10 +47,10 @@
void get_asymetric_start_key(const u8 *master_key, u8 *session_key,
size_t session_key_len, int is_send,
int is_server);
-int encrypt_pw_block_with_password_hash(
+int __must_check encrypt_pw_block_with_password_hash(
const u8 *password, size_t password_len,
const u8 *password_hash, u8 *pw_block);
-void new_password_encrypted_with_old_nt_password_hash(
+int __must_check new_password_encrypted_with_old_nt_password_hash(
const u8 *new_password, size_t new_password_len,
const u8 *old_password, size_t old_password_len,
u8 *encrypted_pw_block);
Modified: wpasupplicant/branches/upstream/current/src/crypto/sha1.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/crypto/sha1.h?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/crypto/sha1.h (original)
+++ wpasupplicant/branches/upstream/current/src/crypto/sha1.h Tue Jan 1 13:50:28 2008
@@ -25,8 +25,9 @@
const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
void 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 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 __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);
void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
int iterations, u8 *buf, size_t buflen);
Modified: wpasupplicant/branches/upstream/current/src/crypto/tls.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/crypto/tls.h?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/crypto/tls.h (original)
+++ wpasupplicant/branches/upstream/current/src/crypto/tls.h Tue Jan 1 13:50:28 2008
@@ -189,8 +189,9 @@
* TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED (-3) on failure to verify the
* PKCS#11 engine private key.
*/
-int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
- const struct tls_connection_params *params);
+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
@@ -202,8 +203,8 @@
* TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED (-3) on failure to verify the
* PKCS#11 engine private key.
*/
-int tls_global_set_params(void *tls_ctx,
- const struct tls_connection_params *params);
+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
@@ -212,7 +213,7 @@
* 2 = verify CRL for all certificates
* Returns: 0 on success, -1 on failure
*/
-int tls_global_set_verify(void *tls_ctx, int check_crl);
+int __must_check tls_global_set_verify(void *tls_ctx, int check_crl);
/**
* tls_connection_set_verify - Set certificate verification options
@@ -221,8 +222,9 @@
* @verify_peer: 1 = verify peer certificate
* Returns: 0 on success, -1 on failure
*/
-int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
- int verify_peer);
+int __must_check tls_connection_set_verify(void *tls_ctx,
+ struct tls_connection *conn,
+ int verify_peer);
/**
* tls_connection_set_ia - Set TLS/IA parameters
@@ -234,8 +236,9 @@
* This function is used to configure TLS/IA in server mode where
* tls_connection_set_params() is not used.
*/
-int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
- int tls_ia);
+int __must_check tls_connection_set_ia(void *tls_ctx,
+ struct tls_connection *conn,
+ int tls_ia);
/**
* tls_connection_get_keys - Get master key and random data from TLS connection
@@ -244,8 +247,9 @@
* @keys: Structure of key/random data (filled on success)
* Returns: 0 on success, -1 on failure
*/
-int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
- struct tls_keys *keys);
+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
@@ -267,9 +271,11 @@
* when it is called with seed set to client_random|server_random (or
* server_random|client_random).
*/
-int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
- const char *label, int server_random_first,
- u8 *out, size_t out_len);
+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)
@@ -335,9 +341,10 @@
* This function is used after TLS handshake has been completed successfully to
* send data in the encrypted tunnel.
*/
-int tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn,
- const u8 *in_data, size_t in_len,
- u8 *out_data, size_t out_len);
+int __must_check tls_connection_encrypt(void *tls_ctx,
+ struct tls_connection *conn,
+ const u8 *in_data, size_t in_len,
+ u8 *out_data, size_t out_len);
/**
* tls_connection_decrypt - Decrypt data from TLS tunnel
@@ -352,9 +359,10 @@
* This function is used after TLS handshake has been completed successfully to
* receive data from the encrypted tunnel.
*/
-int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn,
- const u8 *in_data, size_t in_len,
- u8 *out_data, size_t out_len);
+int __must_check tls_connection_decrypt(void *tls_ctx,
+ struct tls_connection *conn,
+ const u8 *in_data, size_t in_len,
+ u8 *out_data, size_t out_len);
/**
* tls_connection_resumed - Was session resumption used
@@ -380,8 +388,9 @@
* (TLS_CIPHER_*).
* Returns: 0 on success, -1 on failure
*/
-int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
- u8 *ciphers);
+int __must_check tls_connection_set_cipher_list(void *tls_ctx,
+ struct tls_connection *conn,
+ u8 *ciphers);
/**
* tls_get_cipher - Get current cipher name
@@ -393,8 +402,8 @@
*
* Get the name of the currently used cipher.
*/
-int tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
- char *buf, size_t buflen);
+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
@@ -405,8 +414,8 @@
* This function is used to enable connection-specific workaround options for
* buffer SSL/TLS implementations.
*/
-int tls_connection_enable_workaround(void *tls_ctx,
- struct tls_connection *conn);
+int __must_check tls_connection_enable_workaround(void *tls_ctx,
+ struct tls_connection *conn);
/**
* tls_connection_client_hello_ext - Set TLS extension for ClientHello
@@ -417,9 +426,10 @@
* @data_len: Extension payload length
* Returns: 0 on success, -1 on failure
*/
-int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
- int ext_type, const u8 *data,
- size_t data_len);
+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
@@ -479,10 +489,9 @@
* This function is used to send the TLS/IA end phase message, e.g., when the
* EAP server completes EAP-TTLSv1.
*/
-int tls_connection_ia_send_phase_finished(void *tls_ctx,
- struct tls_connection *conn,
- int final,
- u8 *out_data, size_t out_len);
+int __must_check tls_connection_ia_send_phase_finished(
+ void *tls_ctx, struct tls_connection *conn, int final,
+ u8 *out_data, size_t out_len);
/**
* tls_connection_ia_final_phase_finished - Has final phase been completed
@@ -491,8 +500,8 @@
* Returns: 1 if valid FinalPhaseFinished has been received, 0 if not, or -1
* on failure
*/
-int tls_connection_ia_final_phase_finished(void *tls_ctx,
- struct tls_connection *conn);
+int __must_check tls_connection_ia_final_phase_finished(
+ void *tls_ctx, struct tls_connection *conn);
/**
* tls_connection_ia_permute_inner_secret - Permute TLS/IA inner secret
@@ -503,17 +512,16 @@
* @key_len: Length of session key material
* Returns: 0 on success, -1 on failure
*/
-int tls_connection_ia_permute_inner_secret(void *tls_ctx,
- struct tls_connection *conn,
- const u8 *key, size_t key_len);
+int __must_check tls_connection_ia_permute_inner_secret(
+ void *tls_ctx, struct tls_connection *conn,
+ const u8 *key, size_t key_len);
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 tls_connection_set_session_ticket_cb(void *tls_ctx,
- struct tls_connection *conn,
- tls_session_ticket_cb cb,
- void *ctx);
+int __must_check tls_connection_set_session_ticket_cb(
+ void *tls_ctx, struct tls_connection *conn,
+ tls_session_ticket_cb cb, void *ctx);
#endif /* TLS_H */
Modified: wpasupplicant/branches/upstream/current/src/drivers/driver.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/drivers/driver.h?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/drivers/driver.h (original)
+++ wpasupplicant/branches/upstream/current/src/drivers/driver.h Tue Jan 1 13:50:28 2008
@@ -1207,5 +1207,6 @@
u8 * wpa_scan_get_vendor_ie(struct wpa_scan_res *res, u32 vendor_type);
int wpa_scan_get_max_rate(struct wpa_scan_res *res);
void wpa_scan_results_free(struct wpa_scan_results *res);
+void wpa_scan_sort_results(struct wpa_scan_results *res);
#endif /* DRIVER_H */
Modified: wpasupplicant/branches/upstream/current/src/drivers/driver_ndis.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/drivers/driver_ndis.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/drivers/driver_ndis.c (original)
+++ wpasupplicant/branches/upstream/current/src/drivers/driver_ndis.c Tue Jan 1 13:50:28 2008
@@ -729,90 +729,49 @@
}
-static void wpa_driver_ndis_get_ies(struct wpa_scan_result *res, u8 *ie,
- size_t ie_len)
-{
- u8 *pos = ie;
- u8 *end = ie + ie_len;
- NDIS_802_11_FIXED_IEs *fixed;
-
- if (ie_len < sizeof(NDIS_802_11_FIXED_IEs))
- return;
-
- fixed = (NDIS_802_11_FIXED_IEs *) pos;
- res->tsf = WPA_GET_LE64(fixed->Timestamp);
- pos += sizeof(NDIS_802_11_FIXED_IEs);
- /* wpa_hexdump(MSG_MSGDUMP, "IEs", pos, end - pos); */
- while (pos + 1 < end && pos + 2 + pos[1] <= end) {
- u8 ielen = 2 + pos[1];
- if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
- os_memcmp(pos + 2, "\x00\x50\xf2\x01", 4) == 0) {
- if (ielen > SSID_MAX_WPA_IE_LEN) {
- pos += ielen;
- continue;
- }
- os_memcpy(res->wpa_ie, pos, ielen);
- res->wpa_ie_len = ielen;
- } else if (pos[0] == WLAN_EID_RSN) {
- if (ielen > SSID_MAX_WPA_IE_LEN) {
- pos += ielen;
- continue;
- }
- os_memcpy(res->rsn_ie, pos, ielen);
- res->rsn_ie_len = ielen;
- }
- pos += ielen;
- }
-}
-
-
-static int wpa_driver_ndis_get_scan_results(void *priv,
- struct wpa_scan_result *results,
- size_t max_size)
+static struct wpa_scan_results * wpa_driver_ndis_get_scan_results(void *priv)
{
struct wpa_driver_ndis_data *drv = priv;
NDIS_802_11_BSSID_LIST_EX *b;
size_t blen, count, i;
- int len, j;
+ int len;
char *pos;
+ struct wpa_scan_results *results;
+ struct wpa_scan_res *r;
blen = 65535;
b = os_zalloc(blen);
if (b == NULL)
- return -1;
+ return NULL;
len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen);
if (len < 0) {
wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results");
os_free(b);
- return -1;
+ return NULL;
}
count = b->NumberOfItems;
- if (count > max_size)
- count = max_size;
-
- os_memset(results, 0, max_size * sizeof(struct wpa_scan_result));
+ results = os_zalloc(sizeof(*results));
+ if (results == NULL) {
+ os_free(b);
+ return NULL;
+ }
+ results->res = os_zalloc(count * sizeof(struct wpa_scan_res *));
+ if (results->res == NULL) {
+ os_free(results);
+ os_free(b);
+ return NULL;
+ }
+
pos = (char *) &b->Bssid[0];
for (i = 0; i < count; i++) {
NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos;
- os_memcpy(results[i].bssid, bss->MacAddress, ETH_ALEN);
- os_memcpy(results[i].ssid, bss->Ssid.Ssid,
- bss->Ssid.SsidLength);
- results[i].ssid_len = bss->Ssid.SsidLength;
- if (bss->Privacy)
- results[i].caps |= IEEE80211_CAP_PRIVACY;
- if (bss->InfrastructureMode == Ndis802_11IBSS)
- results[i].caps |= IEEE80211_CAP_IBSS;
- else if (bss->InfrastructureMode == Ndis802_11Infrastructure)
- results[i].caps |= IEEE80211_CAP_ESS;
- results[i].level = (int) bss->Rssi;
- results[i].freq = bss->Configuration.DSConfig / 1000;
- for (j = 0; j < sizeof(bss->SupportedRates); j++) {
- if ((bss->SupportedRates[j] & 0x7f) >
- results[i].maxrate) {
- results[i].maxrate =
- bss->SupportedRates[j] & 0x7f;
- }
+ NDIS_802_11_FIXED_IEs *fixed;
+
+ if (bss->IELength < sizeof(NDIS_802_11_FIXED_IEs)) {
+ wpa_printf(MSG_DEBUG, "NDIS: too small IELength=%d",
+ (int) bss->IELength);
+ break;
}
if (((char *) bss->IEs) + bss->IELength > (char *) b + blen) {
/*
@@ -823,18 +782,37 @@
*/
wpa_printf(MSG_DEBUG, "NDIS: skipped invalid scan "
"result IE (BSSID=" MACSTR ") IELength=%d",
- MAC2STR(results[i].bssid),
+ MAC2STR(bss->MacAddress),
(int) bss->IELength);
break;
}
- wpa_driver_ndis_get_ies(&results[i], bss->IEs, bss->IELength);
+
+ r = os_zalloc(sizeof(*r) + bss->IELength -
+ sizeof(NDIS_802_11_FIXED_IEs));
+ if (r == NULL)
+ break;
+
+ os_memcpy(r->bssid, bss->MacAddress, ETH_ALEN);
+ r->level = (int) bss->Rssi;
+ r->freq = bss->Configuration.DSConfig / 1000;
+ fixed = (NDIS_802_11_FIXED_IEs *) bss->IEs;
+ r->beacon_int = WPA_GET_LE16((u8 *) &fixed->BeaconInterval);
+ r->caps = WPA_GET_LE16((u8 *) &fixed->Capabilities);
+ r->tsf = WPA_GET_LE64(fixed->Timestamp);
+ os_memcpy(r + 1, bss->IEs + sizeof(NDIS_802_11_FIXED_IEs),
+ bss->IELength - sizeof(NDIS_802_11_FIXED_IEs));
+ r->ie_len = bss->IELength - sizeof(NDIS_802_11_FIXED_IEs);
+
+ results->res[results->num++] = r;
+
pos += bss->Length;
if (pos > (char *) b + blen)
break;
}
os_free(b);
- return (int) count;
+
+ return results;
}
@@ -2826,7 +2804,7 @@
NULL /* set_countermeasures */,
NULL /* set_drop_unencrypted */,
wpa_driver_ndis_scan,
- wpa_driver_ndis_get_scan_results,
+ NULL /* get_scan_results */,
wpa_driver_ndis_deauthenticate,
wpa_driver_ndis_disassociate,
wpa_driver_ndis_associate,
@@ -2849,5 +2827,6 @@
NULL /* mlme_add_sta */,
NULL /* mlme_remove_sta */,
NULL /* update_ft_ies */,
- NULL /* send_ft_action */
+ NULL /* send_ft_action */,
+ wpa_driver_ndis_get_scan_results
};
Modified: wpasupplicant/branches/upstream/current/src/drivers/driver_wext.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/drivers/driver_wext.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/drivers/driver_wext.c (original)
+++ wpasupplicant/branches/upstream/current/src/drivers/driver_wext.c Tue Jan 1 13:50:28 2008
@@ -1125,52 +1125,6 @@
drv->ctx);
return ret;
-}
-
-
-/* Compare function for sorting scan results. Return >0 if @b is considered
- * better. */
-static int wpa_scan_result_compar(const void *a, const void *b)
-{
- struct wpa_scan_res **_wa = (void *) a;
- struct wpa_scan_res **_wb = (void *) b;
- struct wpa_scan_res *wa = *_wa;
- struct wpa_scan_res *wb = *_wb;
- int wpa_a, wpa_b, maxrate_a, maxrate_b;
-
- /* WPA/WPA2 support preferred */
- wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL ||
- wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL;
- wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL ||
- wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL;
-
- if (wpa_b && !wpa_a)
- return 1;
- if (!wpa_b && wpa_a)
- return -1;
-
- /* privacy support preferred */
- if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 &&
- (wb->caps & IEEE80211_CAP_PRIVACY))
- return 1;
- if ((wa->caps & IEEE80211_CAP_PRIVACY) &&
- (wb->caps & IEEE80211_CAP_PRIVACY) == 0)
- return -1;
-
- /* best/max rate preferred if signal level close enough XXX */
- maxrate_a = wpa_scan_get_max_rate(wa);
- maxrate_b = wpa_scan_get_max_rate(wb);
- if (maxrate_a != maxrate_b && abs(wb->level - wa->level) < 5)
- return maxrate_b - maxrate_a;
-
- /* use freq for channel preference */
-
- /* all things being equal, use signal level; if signal levels are
- * identical, use quality values since some drivers may only report
- * that value and leave the signal level zero */
- if (wb->level == wa->level)
- return wb->qual - wa->qual;
- return wb->level - wa->level;
}
@@ -1394,6 +1348,7 @@
if (tmp == NULL)
return;
hexstr2bin(spos, tmp + res->ie_len, bytes);
+ res->ie = tmp;
res->ie_len += bytes;
} else if (clen > 4 && os_strncmp(custom, "tsf=", 4) == 0) {
char *spos;
@@ -1583,9 +1538,6 @@
if (!first)
wpa_driver_wext_add_scan_entry(res, &data);
os_free(data.ie);
-
- qsort(res->res, res->num, sizeof(struct wpa_scan_res *),
- wpa_scan_result_compar);
wpa_printf(MSG_DEBUG, "Received %lu bytes of scan results (%lu BSSes)",
(unsigned long) len, (unsigned long) res->num);
Modified: wpasupplicant/branches/upstream/current/src/drivers/scan_helpers.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/drivers/scan_helpers.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/drivers/scan_helpers.c (original)
+++ wpasupplicant/branches/upstream/current/src/drivers/scan_helpers.c Tue Jan 1 13:50:28 2008
@@ -92,3 +92,56 @@
os_free(res->res);
os_free(res);
}
+
+
+/* Compare function for sorting scan results. Return >0 if @b is considered
+ * better. */
+static int wpa_scan_result_compar(const void *a, const void *b)
+{
+ struct wpa_scan_res **_wa = (void *) a;
+ struct wpa_scan_res **_wb = (void *) b;
+ struct wpa_scan_res *wa = *_wa;
+ struct wpa_scan_res *wb = *_wb;
+ int wpa_a, wpa_b, maxrate_a, maxrate_b;
+
+ /* WPA/WPA2 support preferred */
+ wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL ||
+ wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL;
+ wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL ||
+ wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL;
+
+ if (wpa_b && !wpa_a)
+ return 1;
+ if (!wpa_b && wpa_a)
+ return -1;
+
+ /* privacy support preferred */
+ if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 &&
+ (wb->caps & IEEE80211_CAP_PRIVACY))
+ return 1;
+ if ((wa->caps & IEEE80211_CAP_PRIVACY) &&
+ (wb->caps & IEEE80211_CAP_PRIVACY) == 0)
+ return -1;
+
+ /* best/max rate preferred if signal level close enough XXX */
+ maxrate_a = wpa_scan_get_max_rate(wa);
+ maxrate_b = wpa_scan_get_max_rate(wb);
+ if (maxrate_a != maxrate_b && abs(wb->level - wa->level) < 5)
+ return maxrate_b - maxrate_a;
+
+ /* use freq for channel preference */
+
+ /* all things being equal, use signal level; if signal levels are
+ * identical, use quality values since some drivers may only report
+ * that value and leave the signal level zero */
+ if (wb->level == wa->level)
+ return wb->qual - wa->qual;
+ return wb->level - wa->level;
+}
+
+
+void wpa_scan_sort_results(struct wpa_scan_results *res)
+{
+ qsort(res->res, res->num, sizeof(struct wpa_scan_res *),
+ wpa_scan_result_compar);
+}
Modified: wpasupplicant/branches/upstream/current/src/eap_common/eap_defs.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_common/eap_defs.h?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_common/eap_defs.h (original)
+++ wpasupplicant/branches/upstream/current/src/eap_common/eap_defs.h Tue Jan 1 13:50:28 2008
@@ -38,6 +38,10 @@
/* 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 */,
@@ -61,6 +65,7 @@
EAP_TYPE_PAX = 46 /* RFC 4746 */,
EAP_TYPE_PSK = 47 /* RFC 4764 */,
EAP_TYPE_SAKE = 48 /* RFC 4763 */,
+ EAP_TYPE_IKEV2 = 49 /* draft-tschofenig-eap-ikev2-15.txt */,
EAP_TYPE_EXPANDED = 254 /* RFC 3748 */,
EAP_TYPE_GPSK = 255 /* EXPERIMENTAL - type not yet allocated
* draft-ietf-emu-eap-gpsk-01.txt */
Modified: wpasupplicant/branches/upstream/current/src/eap_common/eap_gpsk_common.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_common/eap_gpsk_common.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_common/eap_gpsk_common.c (original)
+++ wpasupplicant/branches/upstream/current/src/eap_common/eap_gpsk_common.c Tue Jan 1 13:50:28 2008
@@ -66,7 +66,8 @@
n = (len + hashlen - 1) / hashlen;
for (i = 1; i <= n; i++) {
WPA_PUT_BE16(ibuf, i);
- omac1_aes_128_vector(psk, 2, addr, vlen, hash);
+ if (omac1_aes_128_vector(psk, 2, addr, vlen, hash))
+ return -1;
clen = left > hashlen ? hashlen : left;
os_memcpy(opos, hash, clen);
opos += clen;
Added: wpasupplicant/branches/upstream/current/src/eap_common/eap_ikev2_common.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_common/eap_ikev2_common.c?rev=967&op=file
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_common/eap_ikev2_common.c (added)
+++ wpasupplicant/branches/upstream/current/src/eap_common/eap_ikev2_common.c Tue Jan 1 13:50:28 2008
@@ -1,0 +1,132 @@
+/*
+ * EAP-IKEv2 common routines
+ * Copyright (c) 2007, Jouni Malinen <j at w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "eap_defs.h"
+#include "eap_common.h"
+#include "ikev2_common.h"
+#include "eap_ikev2_common.h"
+
+
+int eap_ikev2_derive_keymat(int prf, struct ikev2_keys *keys,
+ const u8 *i_nonce, size_t i_nonce_len,
+ const u8 *r_nonce, size_t r_nonce_len,
+ u8 *keymat)
+{
+ u8 *nonces;
+ size_t nlen;
+
+ /* KEYMAT = prf+(SK_d, Ni | Nr) */
+ if (keys->SK_d == NULL || i_nonce == NULL || r_nonce == NULL)
+ return -1;
+
+ nlen = i_nonce_len + r_nonce_len;
+ nonces = os_malloc(nlen);
+ if (nonces == NULL)
+ return -1;
+ os_memcpy(nonces, i_nonce, i_nonce_len);
+ os_memcpy(nonces + i_nonce_len, r_nonce, r_nonce_len);
+
+ if (ikev2_prf_plus(prf, keys->SK_d, keys->SK_d_len, nonces, nlen,
+ keymat, EAP_MSK_LEN + EAP_EMSK_LEN)) {
+ os_free(nonces);
+ return -1;
+ }
+ os_free(nonces);
+
+ wpa_hexdump_key(MSG_DEBUG, "EAP-IKEV2: KEYMAT",
+ keymat, EAP_MSK_LEN + EAP_EMSK_LEN);
+
+ return 0;
+}
+
+
+struct wpabuf * eap_ikev2_build_frag_ack(u8 id, u8 code)
+{
+ struct wpabuf *msg;
+
+#ifdef CCNS_PL
+ msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 1, code, id);
+ if (msg == NULL) {
+ wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory "
+ "for fragment ack");
+ return NULL;
+ }
+ wpabuf_put_u8(msg, 0); /* Flags */
+#else /* CCNS_PL */
+ msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 0, code, id);
+ if (msg == NULL) {
+ wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory "
+ "for fragment ack");
+ return NULL;
+ }
+#endif /* CCNS_PL */
+
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Send fragment ack");
+
+ return msg;
+}
+
+
+int eap_ikev2_validate_icv(int integ_alg, struct ikev2_keys *keys,
+ int initiator, const struct wpabuf *msg,
+ const u8 *pos, const u8 *end)
+{
+ const struct ikev2_integ_alg *integ;
+ size_t icv_len;
+ u8 icv[IKEV2_MAX_HASH_LEN];
+ const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;
+
+ integ = ikev2_get_integ(integ_alg);
+ if (integ == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG "
+ "transform / cannot validate ICV");
+ return -1;
+ }
+ icv_len = integ->hash_len;
+
+ if (end - pos < (int) icv_len) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Not enough room in the "
+ "message for Integrity Checksum Data");
+ return -1;
+ }
+
+ if (SK_a == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: No SK_a for ICV validation");
+ return -1;
+ }
+
+ if (ikev2_integ_hash(integ_alg, SK_a, keys->SK_integ_len,
+ wpabuf_head(msg),
+ wpabuf_len(msg) - icv_len, icv) < 0) {
+ wpa_printf(MSG_INFO, "EAP-IKEV2: Could not calculate ICV");
+ return -1;
+ }
+
+ if (os_memcmp(icv, end - icv_len, icv_len) != 0) {
+ wpa_printf(MSG_INFO, "EAP-IKEV2: Invalid ICV");
+ wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Calculated ICV",
+ icv, icv_len);
+ wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Received ICV",
+ end - icv_len, icv_len);
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Valid Integrity Checksum Data in "
+ "the received message");
+
+ return icv_len;
+}
Added: wpasupplicant/branches/upstream/current/src/eap_common/eap_ikev2_common.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_common/eap_ikev2_common.h?rev=967&op=file
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_common/eap_ikev2_common.h (added)
+++ wpasupplicant/branches/upstream/current/src/eap_common/eap_ikev2_common.h Tue Jan 1 13:50:28 2008
@@ -1,0 +1,42 @@
+/*
+ * EAP-IKEv2 definitions
+ * Copyright (c) 2007, Jouni Malinen <j at 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 EAP_IKEV2_COMMON_H
+#define EAP_IKEV2_COMMON_H
+
+#ifdef CCNS_PL
+/* incorrect bit order */
+#define IKEV2_FLAGS_LENGTH_INCLUDED 0x01
+#define IKEV2_FLAGS_MORE_FRAGMENTS 0x02
+#define IKEV2_FLAGS_ICV_INCLUDED 0x04
+#else /* CCNS_PL */
+#define IKEV2_FLAGS_LENGTH_INCLUDED 0x80
+#define IKEV2_FLAGS_MORE_FRAGMENTS 0x40
+#define IKEV2_FLAGS_ICV_INCLUDED 0x20
+#endif /* CCNS_PL */
+
+#define IKEV2_FRAGMENT_SIZE 1400
+
+struct ikev2_keys;
+
+int eap_ikev2_derive_keymat(int prf, struct ikev2_keys *keys,
+ const u8 *i_nonce, size_t i_nonce_len,
+ const u8 *r_nonce, size_t r_nonce_len,
+ u8 *keymat);
+struct wpabuf * eap_ikev2_build_frag_ack(u8 id, u8 code);
+int eap_ikev2_validate_icv(int integ_alg, struct ikev2_keys *keys,
+ int initiator, const struct wpabuf *msg,
+ const u8 *pos, const u8 *end);
+
+#endif /* EAP_IKEV2_COMMON_H */
Modified: wpasupplicant/branches/upstream/current/src/eap_common/eap_psk_common.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_common/eap_psk_common.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_common/eap_psk_common.c (original)
+++ wpasupplicant/branches/upstream/current/src/eap_common/eap_psk_common.c Tue Jan 1 13:50:28 2008
@@ -22,43 +22,53 @@
#define aes_block_size 16
-void eap_psk_key_setup(const u8 *psk, u8 *ak, u8 *kdk)
+int eap_psk_key_setup(const u8 *psk, u8 *ak, u8 *kdk)
{
os_memset(ak, 0, aes_block_size);
- aes_128_encrypt_block(psk, ak, ak);
+ if (aes_128_encrypt_block(psk, ak, ak))
+ return -1;
os_memcpy(kdk, ak, aes_block_size);
ak[aes_block_size - 1] ^= 0x01;
kdk[aes_block_size - 1] ^= 0x02;
- aes_128_encrypt_block(psk, ak, ak);
- aes_128_encrypt_block(psk, kdk, kdk);
+ if (aes_128_encrypt_block(psk, ak, ak) ||
+ aes_128_encrypt_block(psk, kdk, kdk))
+ return -1;
+ return 0;
}
-void eap_psk_derive_keys(const u8 *kdk, const u8 *rand_p, u8 *tek, u8 *msk,
- u8 *emsk)
+int eap_psk_derive_keys(const u8 *kdk, const u8 *rand_p, u8 *tek, u8 *msk,
+ u8 *emsk)
{
u8 hash[aes_block_size];
u8 counter = 1;
int i;
- aes_128_encrypt_block(kdk, rand_p, hash);
+ if (aes_128_encrypt_block(kdk, rand_p, hash))
+ return -1;
hash[aes_block_size - 1] ^= counter;
- aes_128_encrypt_block(kdk, hash, tek);
+ if (aes_128_encrypt_block(kdk, hash, tek))
+ return -1;
hash[aes_block_size - 1] ^= counter;
counter++;
for (i = 0; i < EAP_MSK_LEN / aes_block_size; i++) {
hash[aes_block_size - 1] ^= counter;
- aes_128_encrypt_block(kdk, hash, &msk[i * aes_block_size]);
+ if (aes_128_encrypt_block(kdk, hash, &msk[i * aes_block_size]))
+ return -1;
hash[aes_block_size - 1] ^= counter;
counter++;
}
for (i = 0; i < EAP_EMSK_LEN / aes_block_size; i++) {
hash[aes_block_size - 1] ^= counter;
- aes_128_encrypt_block(kdk, hash, &emsk[i * aes_block_size]);
+ if (aes_128_encrypt_block(kdk, hash,
+ &emsk[i * aes_block_size]))
+ return -1;
hash[aes_block_size - 1] ^= counter;
counter++;
}
+
+ return 0;
}
Modified: wpasupplicant/branches/upstream/current/src/eap_common/eap_psk_common.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_common/eap_psk_common.h?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_common/eap_psk_common.h (original)
+++ wpasupplicant/branches/upstream/current/src/eap_common/eap_psk_common.h Tue Jan 1 13:50:28 2008
@@ -71,8 +71,8 @@
#endif /* _MSC_VER */
-void eap_psk_key_setup(const u8 *psk, u8 *ak, u8 *kdk);
-void eap_psk_derive_keys(const u8 *kdk, const u8 *rand_p, u8 *tek, u8 *msk,
- u8 *emsk);
+int __must_check eap_psk_key_setup(const u8 *psk, u8 *ak, u8 *kdk);
+int __must_check eap_psk_derive_keys(const u8 *kdk, const u8 *rand_p, u8 *tek,
+ u8 *msk, u8 *emsk);
#endif /* EAP_PSK_COMMON_H */
Modified: wpasupplicant/branches/upstream/current/src/eap_common/eap_sim_common.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_common/eap_sim_common.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_common/eap_sim_common.c (original)
+++ wpasupplicant/branches/upstream/current/src/eap_common/eap_sim_common.c Tue Jan 1 13:50:28 2008
@@ -611,7 +611,10 @@
return NULL;
os_memcpy(decrypted, encr_data, encr_data_len);
- aes_128_cbc_decrypt(k_encr, iv, decrypted, encr_data_len);
+ if (aes_128_cbc_decrypt(k_encr, iv, decrypted, encr_data_len)) {
+ os_free(decrypted);
+ return NULL;
+ }
wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Decrypted AT_ENCR_DATA",
decrypted, encr_data_len);
@@ -810,11 +813,9 @@
wpa_printf(MSG_DEBUG, " (AT_ENCR_DATA data len %lu)",
(unsigned long) encr_len);
wpabuf_mhead_u8(msg->buf)[msg->encr + 1] = encr_len / 4 + 1;
- aes_128_cbc_encrypt(k_encr, wpabuf_head_u8(msg->buf) + msg->iv,
- wpabuf_mhead_u8(msg->buf) + msg->encr + 4,
- encr_len);
-
- return 0;
+ return aes_128_cbc_encrypt(k_encr, wpabuf_head_u8(msg->buf) + msg->iv,
+ wpabuf_mhead_u8(msg->buf) + msg->encr + 4,
+ encr_len);
}
Modified: wpasupplicant/branches/upstream/current/src/eap_common/eap_wsc_common.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_common/eap_wsc_common.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_common/eap_wsc_common.c (original)
+++ wpasupplicant/branches/upstream/current/src/eap_common/eap_wsc_common.c Tue Jan 1 13:50:28 2008
@@ -17,6 +17,7 @@
#include "common.h"
#include "eap_defs.h"
#include "eap_common.h"
+#include "wps/wps.h"
#include "eap_wsc_common.h"
struct wpabuf * eap_wsc_build_frag_ack(u8 id, u8 code)
Modified: wpasupplicant/branches/upstream/current/src/eap_common/eap_wsc_common.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_common/eap_wsc_common.h?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_common/eap_wsc_common.h (original)
+++ wpasupplicant/branches/upstream/current/src/eap_common/eap_wsc_common.h Tue Jan 1 13:50:28 2008
@@ -17,15 +17,6 @@
#define EAP_VENDOR_TYPE_WSC 1
-enum wsc_op_code {
- WSC_Start = 0x01,
- WSC_ACK = 0x02,
- WSC_NACK = 0x03,
- WSC_MSG = 0x04,
- WSC_Done = 0x05,
- WSC_FRAG_ACK = 0x06
-};
-
#define WSC_FLAGS_MF 0x01
#define WSC_FLAGS_LF 0x02
Added: wpasupplicant/branches/upstream/current/src/eap_common/ikev2_common.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_common/ikev2_common.c?rev=967&op=file
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_common/ikev2_common.c (added)
+++ wpasupplicant/branches/upstream/current/src/eap_common/ikev2_common.c Tue Jan 1 13:50:28 2008
@@ -1,0 +1,795 @@
+/*
+ * IKEv2 common routines for initiator and responder
+ * Copyright (c) 2007, Jouni Malinen <j at w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "sha1.h"
+#include "md5.h"
+#include "crypto.h"
+#include "ikev2_common.h"
+
+
+static struct ikev2_integ_alg ikev2_integ_algs[] = {
+ { AUTH_HMAC_SHA1_96, 20, 12 },
+ { AUTH_HMAC_MD5_96, 16, 12 }
+};
+
+#define NUM_INTEG_ALGS (sizeof(ikev2_integ_algs) / sizeof(ikev2_integ_algs[0]))
+
+
+static struct ikev2_prf_alg ikev2_prf_algs[] = {
+ { PRF_HMAC_SHA1, 20, 20 },
+ { PRF_HMAC_MD5, 16, 16 }
+};
+
+#define NUM_PRF_ALGS (sizeof(ikev2_prf_algs) / sizeof(ikev2_prf_algs[0]))
+
+
+static struct ikev2_encr_alg ikev2_encr_algs[] = {
+ { ENCR_AES_CBC, 16, 16 }, /* only 128-bit keys supported for now */
+ { ENCR_3DES, 24, 8 }
+};
+
+#define NUM_ENCR_ALGS (sizeof(ikev2_encr_algs) / sizeof(ikev2_encr_algs[0]))
+
+
+const struct ikev2_integ_alg * ikev2_get_integ(int id)
+{
+ size_t i;
+
+ for (i = 0; i < NUM_INTEG_ALGS; i++) {
+ if (ikev2_integ_algs[i].id == id)
+ return &ikev2_integ_algs[i];
+ }
+
+ return NULL;
+}
+
+
+int ikev2_integ_hash(int alg, const u8 *key, size_t key_len, const u8 *data,
+ size_t data_len, u8 *hash)
+{
+ u8 tmphash[IKEV2_MAX_HASH_LEN];
+
+ switch (alg) {
+ case AUTH_HMAC_SHA1_96:
+ if (key_len != 20)
+ return -1;
+ hmac_sha1(key, key_len, data, data_len, tmphash);
+ os_memcpy(hash, tmphash, 12);
+ break;
+ case AUTH_HMAC_MD5_96:
+ if (key_len != 16)
+ return -1;
+ hmac_md5(key, key_len, data, data_len, tmphash);
+ os_memcpy(hash, tmphash, 12);
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+
+const struct ikev2_prf_alg * ikev2_get_prf(int id)
+{
+ size_t i;
+
+ for (i = 0; i < NUM_PRF_ALGS; i++) {
+ if (ikev2_prf_algs[i].id == id)
+ return &ikev2_prf_algs[i];
+ }
+
+ return NULL;
+}
+
+
+int ikev2_prf_hash(int alg, const u8 *key, size_t key_len,
+ size_t num_elem, const u8 *addr[], const size_t *len,
+ u8 *hash)
+{
+ switch (alg) {
+ case PRF_HMAC_SHA1:
+ hmac_sha1_vector(key, key_len, num_elem, addr, len, hash);
+ break;
+ case PRF_HMAC_MD5:
+ hmac_md5_vector(key, key_len, num_elem, addr, len, hash);
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int ikev2_prf_plus(int alg, const u8 *key, size_t key_len,
+ const u8 *data, size_t data_len,
+ u8 *out, size_t out_len)
+{
+ u8 hash[IKEV2_MAX_HASH_LEN];
+ size_t hash_len;
+ u8 iter, *pos, *end;
+ const u8 *addr[3];
+ size_t len[3];
+ const struct ikev2_prf_alg *prf;
+ int res;
+
+ prf = ikev2_get_prf(alg);
+ if (prf == NULL)
+ return -1;
+ hash_len = prf->hash_len;
+
+ addr[0] = hash;
+ len[0] = hash_len;
+ addr[1] = data;
+ len[1] = data_len;
+ addr[2] = &iter;
+ len[2] = 1;
+
+ pos = out;
+ end = out + out_len;
+ iter = 1;
+ while (pos < end) {
+ size_t clen;
+ if (iter == 1)
+ res = ikev2_prf_hash(alg, key, key_len, 2, &addr[1],
+ &len[1], hash);
+ else
+ res = ikev2_prf_hash(alg, key, key_len, 3, addr, len,
+ hash);
+ if (res < 0)
+ return -1;
+ clen = hash_len;
+ if ((int) clen > end - pos)
+ clen = end - pos;
+ os_memcpy(pos, hash, clen);
+ pos += clen;
+ iter++;
+ }
+
+ return 0;
+}
+
+
+const struct ikev2_encr_alg * ikev2_get_encr(int id)
+{
+ size_t i;
+
+ for (i = 0; i < NUM_ENCR_ALGS; i++) {
+ if (ikev2_encr_algs[i].id == id)
+ return &ikev2_encr_algs[i];
+ }
+
+ return NULL;
+}
+
+
+#ifdef CCNS_PL
+/* from des.c */
+struct des3_key_s {
+ u32 ek[3][32];
+ u32 dk[3][32];
+};
+
+void des3_key_setup(const u8 *key, struct des3_key_s *dkey);
+void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt);
+void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain);
+#endif /* CCNS_PL */
+
+
+int ikev2_encr_encrypt(int alg, const u8 *key, size_t key_len, const u8 *iv,
+ const u8 *plain, u8 *crypt, size_t len)
+{
+ struct crypto_cipher *cipher;
+ int encr_alg;
+
+#ifdef CCNS_PL
+ if (alg == ENCR_3DES) {
+ struct des3_key_s des3key;
+ size_t i, blocks;
+ u8 *pos;
+
+ /* ECB mode is used incorrectly for 3DES!? */
+ if (key_len != 24) {
+ wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length");
+ return -1;
+ }
+ des3_key_setup(key, &des3key);
+
+ blocks = len / 8;
+ pos = crypt;
+ for (i = 0; i < blocks; i++) {
+ des3_encrypt(pos, &des3key, pos);
+ pos += 8;
+ }
+ } else {
+#endif /* CCNS_PL */
+ switch (alg) {
+ case ENCR_3DES:
+ encr_alg = CRYPTO_CIPHER_ALG_3DES;
+ break;
+ case ENCR_AES_CBC:
+ encr_alg = CRYPTO_CIPHER_ALG_AES;
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg);
+ return -1;
+ }
+
+ cipher = crypto_cipher_init(encr_alg, iv, key, key_len);
+ if (cipher == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher");
+ return -1;
+ }
+
+ if (crypto_cipher_encrypt(cipher, plain, crypt, len) < 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Encryption failed");
+ crypto_cipher_deinit(cipher);
+ return -1;
+ }
+ crypto_cipher_deinit(cipher);
+#ifdef CCNS_PL
+ }
+#endif /* CCNS_PL */
+
+ return 0;
+}
+
+
+int ikev2_encr_decrypt(int alg, const u8 *key, size_t key_len, const u8 *iv,
+ const u8 *crypt, u8 *plain, size_t len)
+{
+ struct crypto_cipher *cipher;
+ int encr_alg;
+
+#ifdef CCNS_PL
+ if (alg == ENCR_3DES) {
+ struct des3_key_s des3key;
+ size_t i, blocks;
+
+ /* ECB mode is used incorrectly for 3DES!? */
+ if (key_len != 24) {
+ wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length");
+ return -1;
+ }
+ des3_key_setup(key, &des3key);
+
+ if (len % 8) {
+ wpa_printf(MSG_INFO, "IKEV2: Invalid encrypted "
+ "length");
+ return -1;
+ }
+ blocks = len / 8;
+ for (i = 0; i < blocks; i++) {
+ des3_decrypt(crypt, &des3key, plain);
+ plain += 8;
+ crypt += 8;
+ }
+ } else {
+#endif /* CCNS_PL */
+ switch (alg) {
+ case ENCR_3DES:
+ encr_alg = CRYPTO_CIPHER_ALG_3DES;
+ break;
+ case ENCR_AES_CBC:
+ encr_alg = CRYPTO_CIPHER_ALG_AES;
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg);
+ return -1;
+ }
+
+ cipher = crypto_cipher_init(encr_alg, iv, key, key_len);
+ if (cipher == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher");
+ return -1;
+ }
+
+ if (crypto_cipher_decrypt(cipher, crypt, plain, len) < 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Decryption failed");
+ crypto_cipher_deinit(cipher);
+ return -1;
+ }
+ crypto_cipher_deinit(cipher);
+#ifdef CCNS_PL
+ }
+#endif /* CCNS_PL */
+
+ return 0;
+}
+
+
+int ikev2_parse_payloads(struct ikev2_payloads *payloads,
+ u8 next_payload, const u8 *pos, const u8 *end)
+{
+ const struct ikev2_payload_hdr *phdr;
+
+ os_memset(payloads, 0, sizeof(*payloads));
+
+ while (next_payload != IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) {
+ int plen, pdatalen;
+ const u8 *pdata;
+ wpa_printf(MSG_DEBUG, "IKEV2: Processing payload %u",
+ next_payload);
+ if (end - pos < (int) sizeof(*phdr)) {
+ wpa_printf(MSG_INFO, "IKEV2: Too short message for "
+ "payload header (left=%d)", end - pos);
+ }
+ phdr = (const struct ikev2_payload_hdr *) pos;
+ plen = WPA_GET_BE16(phdr->payload_length);
+ if (plen < (int) sizeof(*phdr) || pos + plen > end) {
+ wpa_printf(MSG_INFO, "IKEV2: Invalid payload header "
+ "length %d", plen);
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Next Payload: %u Flags: 0x%x"
+ " Payload Length: %d",
+ phdr->next_payload, phdr->flags, plen);
+
+ pdata = (const u8 *) (phdr + 1);
+ pdatalen = plen - sizeof(*phdr);
+
+ switch (next_payload) {
+ case IKEV2_PAYLOAD_SA:
+ wpa_printf(MSG_DEBUG, "IKEV2: Payload: Security "
+ "Association");
+ payloads->sa = pdata;
+ payloads->sa_len = pdatalen;
+ break;
+ case IKEV2_PAYLOAD_KEY_EXCHANGE:
+ wpa_printf(MSG_DEBUG, "IKEV2: Payload: Key "
+ "Exchange");
+ payloads->ke = pdata;
+ payloads->ke_len = pdatalen;
+ break;
+ case IKEV2_PAYLOAD_IDi:
+ wpa_printf(MSG_DEBUG, "IKEV2: Payload: IDi");
+ payloads->idi = pdata;
+ payloads->idi_len = pdatalen;
+ break;
+ case IKEV2_PAYLOAD_IDr:
+ wpa_printf(MSG_DEBUG, "IKEV2: Payload: IDr");
+ payloads->idr = pdata;
+ payloads->idr_len = pdatalen;
+ break;
+ case IKEV2_PAYLOAD_CERTIFICATE:
+ wpa_printf(MSG_DEBUG, "IKEV2: Payload: Certificate");
+ payloads->cert = pdata;
+ payloads->cert_len = pdatalen;
+ break;
+ case IKEV2_PAYLOAD_AUTHENTICATION:
+ wpa_printf(MSG_DEBUG, "IKEV2: Payload: "
+ "Authentication");
+ payloads->auth = pdata;
+ payloads->auth_len = pdatalen;
+ break;
+ case IKEV2_PAYLOAD_NONCE:
+ wpa_printf(MSG_DEBUG, "IKEV2: Payload: Nonce");
+ payloads->nonce = pdata;
+ payloads->nonce_len = pdatalen;
+ break;
+ case IKEV2_PAYLOAD_ENCRYPTED:
+ wpa_printf(MSG_DEBUG, "IKEV2: Payload: Encrypted");
+ payloads->encrypted = pdata;
+ payloads->encrypted_len = pdatalen;
+ break;
+ case IKEV2_PAYLOAD_NOTIFICATION:
+ wpa_printf(MSG_DEBUG, "IKEV2: Payload: "
+ "Notification");
+ payloads->notification = pdata;
+ payloads->notification_len = pdatalen;
+ break;
+ default:
+ if (phdr->flags & IKEV2_PAYLOAD_FLAGS_CRITICAL) {
+ wpa_printf(MSG_INFO, "IKEV2: Unsupported "
+ "critical payload %u - reject the "
+ "entire message", next_payload);
+ return -1;
+ } else {
+ wpa_printf(MSG_DEBUG, "IKEV2: Skipped "
+ "unsupported payload %u",
+ next_payload);
+ }
+ }
+
+ if (next_payload == IKEV2_PAYLOAD_ENCRYPTED &&
+ pos + plen == end) {
+ /*
+ * Next Payload in the case of Encrypted Payload is
+ * actually the payload type for the first embedded
+ * payload.
+ */
+ payloads->encr_next_payload = phdr->next_payload;
+ next_payload = IKEV2_PAYLOAD_NO_NEXT_PAYLOAD;
+ } else
+ next_payload = phdr->next_payload;
+
+ pos += plen;
+ }
+
+ if (pos != end) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected extra data after "
+ "payloads");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int ikev2_derive_auth_data(int prf_alg, const struct wpabuf *sign_msg,
+ const u8 *ID, size_t ID_len, u8 ID_type,
+ struct ikev2_keys *keys, int initiator,
+ const u8 *shared_secret, size_t shared_secret_len,
+ const u8 *nonce, size_t nonce_len,
+ const u8 *key_pad, size_t key_pad_len,
+ u8 *auth_data)
+{
+ size_t sign_len, buf_len;
+ u8 *sign_data, *pos, *buf, hash[IKEV2_MAX_HASH_LEN];
+ const struct ikev2_prf_alg *prf;
+ const u8 *SK_p = initiator ? keys->SK_pi : keys->SK_pr;
+
+ prf = ikev2_get_prf(prf_alg);
+ if (sign_msg == NULL || ID == NULL || SK_p == NULL ||
+ shared_secret == NULL || nonce == NULL || prf == NULL)
+ return -1;
+
+ /* prf(SK_pi/r,IDi/r') */
+ buf_len = 4 + ID_len;
+ buf = os_zalloc(buf_len);
+ if (buf == NULL)
+ return -1;
+ buf[0] = ID_type;
+ os_memcpy(buf + 4, ID, ID_len);
+ if (ikev2_prf_hash(prf->id, SK_p, keys->SK_prf_len,
+ 1, (const u8 **) &buf, &buf_len, hash) < 0) {
+ os_free(buf);
+ return -1;
+ }
+ os_free(buf);
+
+ /* sign_data = msg | Nr/i | prf(SK_pi/r,IDi/r') */
+ sign_len = wpabuf_len(sign_msg) + nonce_len + prf->hash_len;
+ sign_data = os_malloc(sign_len);
+ if (sign_data == NULL)
+ return -1;
+ pos = sign_data;
+ os_memcpy(pos, wpabuf_head(sign_msg), wpabuf_len(sign_msg));
+ pos += wpabuf_len(sign_msg);
+ os_memcpy(pos, nonce, nonce_len);
+ pos += nonce_len;
+ os_memcpy(pos, hash, prf->hash_len);
+
+ /* AUTH = prf(prf(Shared Secret, key pad, sign_data) */
+ if (ikev2_prf_hash(prf->id, shared_secret, shared_secret_len, 1,
+ &key_pad, &key_pad_len, hash) < 0 ||
+ ikev2_prf_hash(prf->id, hash, prf->hash_len, 1,
+ (const u8 **) &sign_data, &sign_len, auth_data) < 0)
+ {
+ os_free(sign_data);
+ return -1;
+ }
+ os_free(sign_data);
+
+ return 0;
+}
+
+
+u8 * ikev2_decrypt_payload(int encr_id, int integ_id,
+ struct ikev2_keys *keys, int initiator,
+ const struct ikev2_hdr *hdr,
+ const u8 *encrypted, size_t encrypted_len,
+ size_t *res_len)
+{
+ size_t iv_len;
+ const u8 *pos, *end, *iv, *integ;
+ u8 hash[IKEV2_MAX_HASH_LEN], *decrypted;
+ size_t decrypted_len, pad_len;
+ const struct ikev2_integ_alg *integ_alg;
+ const struct ikev2_encr_alg *encr_alg;
+ const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er;
+ const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;
+
+ if (encrypted == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: No Encrypted payload in SA_AUTH");
+ return NULL;
+ }
+
+ encr_alg = ikev2_get_encr(encr_id);
+ if (encr_alg == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type");
+ return NULL;
+ }
+ iv_len = encr_alg->block_size;
+
+ integ_alg = ikev2_get_integ(integ_id);
+ if (integ_alg == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type");
+ return NULL;
+ }
+
+ if (encrypted_len < iv_len + 1 + integ_alg->hash_len) {
+ wpa_printf(MSG_INFO, "IKEV2: No room for IV or Integrity "
+ "Checksum");
+ return NULL;
+ }
+
+ iv = encrypted;
+ pos = iv + iv_len;
+ end = encrypted + encrypted_len;
+ integ = end - integ_alg->hash_len;
+
+ if (SK_a == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: No SK_a available");
+ return NULL;
+ }
+ if (ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len,
+ (const u8 *) hdr,
+ integ - (const u8 *) hdr, hash) < 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Failed to calculate integrity "
+ "hash");
+ return NULL;
+ }
+ if (os_memcmp(integ, hash, integ_alg->hash_len) != 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Incorrect Integrity Checksum "
+ "Data");
+ return NULL;
+ }
+
+ if (SK_e == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: No SK_e available");
+ return NULL;
+ }
+
+ decrypted_len = integ - pos;
+ decrypted = os_malloc(decrypted_len);
+ if (decrypted == NULL)
+ return NULL;
+
+ if (ikev2_encr_decrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv, pos,
+ decrypted, decrypted_len) < 0) {
+ os_free(decrypted);
+ return NULL;
+ }
+
+ pad_len = decrypted[decrypted_len - 1];
+ if (decrypted_len < pad_len + 1) {
+ wpa_printf(MSG_INFO, "IKEV2: Invalid padding in encrypted "
+ "payload");
+ os_free(decrypted);
+ return NULL;
+ }
+
+ decrypted_len -= pad_len + 1;
+
+ *res_len = decrypted_len;
+ return decrypted;
+}
+
+
+void ikev2_update_hdr(struct wpabuf *msg)
+{
+ struct ikev2_hdr *hdr;
+
+ /* Update lenth field in HDR */
+ hdr = wpabuf_mhead(msg);
+ WPA_PUT_BE32(hdr->length, wpabuf_len(msg));
+}
+
+
+int ikev2_build_encrypted(int encr_id, int integ_id, struct ikev2_keys *keys,
+ int initiator, struct wpabuf *msg,
+ struct wpabuf *plain, u8 next_payload)
+{
+ struct ikev2_payload_hdr *phdr;
+ size_t plen;
+ size_t iv_len, pad_len;
+ u8 *icv, *iv;
+ const struct ikev2_integ_alg *integ_alg;
+ const struct ikev2_encr_alg *encr_alg;
+ const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er;
+ const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Adding Encrypted payload");
+
+ /* Encr - RFC 4306, Sect. 3.14 */
+
+ encr_alg = ikev2_get_encr(encr_id);
+ if (encr_alg == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type");
+ return -1;
+ }
+ iv_len = encr_alg->block_size;
+
+ integ_alg = ikev2_get_integ(integ_id);
+ if (integ_alg == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type");
+ return -1;
+ }
+
+ if (SK_e == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: No SK_e available");
+ return -1;
+ }
+
+ if (SK_a == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: No SK_a available");
+ return -1;
+ }
+
+ phdr = wpabuf_put(msg, sizeof(*phdr));
+ phdr->next_payload = next_payload;
+ phdr->flags = 0;
+
+ iv = wpabuf_put(msg, iv_len);
+ if (os_get_random(iv, iv_len)) {
+ wpa_printf(MSG_INFO, "IKEV2: Could not generate IV");
+ return -1;
+ }
+
+ pad_len = iv_len - (wpabuf_len(plain) + 1) % iv_len;
+ if (pad_len == iv_len)
+ pad_len = 0;
+ wpabuf_put(plain, pad_len);
+ wpabuf_put_u8(plain, pad_len);
+
+ if (ikev2_encr_encrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv,
+ wpabuf_head(plain), wpabuf_mhead(plain),
+ wpabuf_len(plain)) < 0)
+ return -1;
+
+ wpabuf_put_buf(msg, plain);
+
+ /* Need to update all headers (Length fields) prior to hash func */
+ icv = wpabuf_put(msg, integ_alg->hash_len);
+ plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
+ WPA_PUT_BE16(phdr->payload_length, plen);
+
+ ikev2_update_hdr(msg);
+
+ return ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len,
+ wpabuf_head(msg),
+ wpabuf_len(msg) - integ_alg->hash_len, icv);
+
+ return 0;
+}
+
+
+int ikev2_keys_set(struct ikev2_keys *keys)
+{
+ return keys->SK_d && keys->SK_ai && keys->SK_ar && keys->SK_ei &&
+ keys->SK_er && keys->SK_pi && keys->SK_pr;
+}
+
+
+void ikev2_free_keys(struct ikev2_keys *keys)
+{
+ os_free(keys->SK_d);
+ os_free(keys->SK_ai);
+ os_free(keys->SK_ar);
+ os_free(keys->SK_ei);
+ os_free(keys->SK_er);
+ os_free(keys->SK_pi);
+ os_free(keys->SK_pr);
+ keys->SK_d = keys->SK_ai = keys->SK_ar = keys->SK_ei = keys->SK_er =
+ keys->SK_pi = keys->SK_pr = NULL;
+}
+
+
+int ikev2_derive_sk_keys(const struct ikev2_prf_alg *prf,
+ const struct ikev2_integ_alg *integ,
+ const struct ikev2_encr_alg *encr,
+ const u8 *skeyseed, const u8 *data, size_t data_len,
+ struct ikev2_keys *keys)
+{
+ u8 *keybuf, *pos;
+ size_t keybuf_len;
+
+ /*
+ * {SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr } =
+ * prf+(SKEYSEED, Ni | Nr | SPIi | SPIr )
+ */
+ ikev2_free_keys(keys);
+ keys->SK_d_len = prf->key_len;
+ keys->SK_integ_len = integ->key_len;
+ keys->SK_encr_len = encr->key_len;
+ keys->SK_prf_len = prf->key_len;
+#ifdef CCNS_PL
+ /* Uses encryption key length for SK_d; should be PRF length */
+ keys->SK_d_len = keys->SK_encr_len;
+#endif /* CCNS_PL */
+
+ keybuf_len = keys->SK_d_len + 2 * keys->SK_integ_len +
+ 2 * keys->SK_encr_len + 2 * keys->SK_prf_len;
+ keybuf = os_malloc(keybuf_len);
+ if (keybuf == NULL)
+ return -1;
+
+ if (ikev2_prf_plus(prf->id, skeyseed, prf->hash_len,
+ data, data_len, keybuf, keybuf_len)) {
+ os_free(keybuf);
+ return -1;
+ }
+
+ pos = keybuf;
+
+ keys->SK_d = os_malloc(keys->SK_d_len);
+ if (keys->SK_d) {
+ os_memcpy(keys->SK_d, pos, keys->SK_d_len);
+ wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_d",
+ keys->SK_d, keys->SK_d_len);
+ }
+ pos += keys->SK_d_len;
+
+ keys->SK_ai = os_malloc(keys->SK_integ_len);
+ if (keys->SK_ai) {
+ os_memcpy(keys->SK_ai, pos, keys->SK_integ_len);
+ wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ai",
+ keys->SK_ai, keys->SK_integ_len);
+ }
+ pos += keys->SK_integ_len;
+
+ keys->SK_ar = os_malloc(keys->SK_integ_len);
+ if (keys->SK_ar) {
+ os_memcpy(keys->SK_ar, pos, keys->SK_integ_len);
+ wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ar",
+ keys->SK_ar, keys->SK_integ_len);
+ }
+ pos += keys->SK_integ_len;
+
+ keys->SK_ei = os_malloc(keys->SK_encr_len);
+ if (keys->SK_ei) {
+ os_memcpy(keys->SK_ei, pos, keys->SK_encr_len);
+ wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ei",
+ keys->SK_ei, keys->SK_encr_len);
+ }
+ pos += keys->SK_encr_len;
+
+ keys->SK_er = os_malloc(keys->SK_encr_len);
+ if (keys->SK_er) {
+ os_memcpy(keys->SK_er, pos, keys->SK_encr_len);
+ wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_er",
+ keys->SK_er, keys->SK_encr_len);
+ }
+ pos += keys->SK_encr_len;
+
+ keys->SK_pi = os_malloc(keys->SK_prf_len);
+ if (keys->SK_pi) {
+ os_memcpy(keys->SK_pi, pos, keys->SK_prf_len);
+ wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pi",
+ keys->SK_pi, keys->SK_prf_len);
+ }
+ pos += keys->SK_prf_len;
+
+ keys->SK_pr = os_malloc(keys->SK_prf_len);
+ if (keys->SK_pr) {
+ os_memcpy(keys->SK_pr, pos, keys->SK_prf_len);
+ wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pr",
+ keys->SK_pr, keys->SK_prf_len);
+ }
+
+ os_free(keybuf);
+
+ if (!ikev2_keys_set(keys)) {
+ ikev2_free_keys(keys);
+ return -1;
+ }
+
+ return 0;
+}
Added: wpasupplicant/branches/upstream/current/src/eap_common/ikev2_common.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_common/ikev2_common.h?rev=967&op=file
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_common/ikev2_common.h (added)
+++ wpasupplicant/branches/upstream/current/src/eap_common/ikev2_common.h Tue Jan 1 13:50:28 2008
@@ -1,0 +1,344 @@
+/*
+ * IKEv2 definitions
+ * Copyright (c) 2007, Jouni Malinen <j at 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 IKEV2_COMMON_H
+#define IKEV2_COMMON_H
+
+/*
+ * Nonce length must be at least 16 octets. It must also be at least half the
+ * key size of the negotiated PRF.
+ */
+#define IKEV2_NONCE_MIN_LEN 16
+#define IKEV2_NONCE_MAX_LEN 256
+
+/* IKE Header - RFC 4306, Sect. 3.1 */
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
+#define IKEV2_SPI_LEN 8
+
+struct ikev2_hdr {
+ u8 i_spi[IKEV2_SPI_LEN]; /* IKE_SA Initiator's SPI */
+ u8 r_spi[IKEV2_SPI_LEN]; /* IKE_SA Responder's SPI */
+ u8 next_payload;
+ u8 version; /* MjVer | MnVer */
+ u8 exchange_type;
+ u8 flags;
+ u8 message_id[4];
+ u8 length[4]; /* total length of HDR + payloads */
+} STRUCT_PACKED;
+
+struct ikev2_payload_hdr {
+ u8 next_payload;
+ u8 flags;
+ u8 payload_length[2]; /* this payload, including the payload header */
+} STRUCT_PACKED;
+
+struct ikev2_proposal {
+ u8 type; /* 0 (last) or 2 (more) */
+ u8 reserved;
+ u8 proposal_length[2]; /* including all transform and attributes */
+ u8 proposal_num;
+ u8 protocol_id; /* IKEV2_PROTOCOL_* */
+ u8 spi_size;
+ u8 num_transforms;
+ /* SPI of spi_size octets */
+ /* Transforms */
+} STRUCT_PACKED;
+
+struct ikev2_transform {
+ u8 type; /* 0 (last) or 3 (more) */
+ u8 reserved;
+ u8 transform_length[2]; /* including Header and Attributes */
+ u8 transform_type;
+ u8 reserved2;
+ u8 transform_id[2];
+ /* Transform Attributes */
+} STRUCT_PACKED;
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
+
+
+/* Current IKEv2 version from RFC 4306 */
+#define IKEV2_MjVer 2
+#define IKEV2_MnVer 0
+#ifdef CCNS_PL
+#define IKEV2_VERSION ((IKEV2_MjVer) | ((IKEV2_MnVer) << 4))
+#else /* CCNS_PL */
+#define IKEV2_VERSION (((IKEV2_MjVer) << 4) | (IKEV2_MnVer))
+#endif /* CCNS_PL */
+
+/* IKEv2 Exchange Types */
+enum {
+ /* 0-33 RESERVED */
+ IKE_SA_INIT = 34,
+ IKE_SA_AUTH = 35,
+ CREATE_CHILD_SA = 36,
+ INFORMATION = 37
+ /* 38-239 RESERVED TO IANA */
+ /* 240-255 Reserved for private use */
+};
+
+/* IKEv2 Flags */
+#define IKEV2_HDR_INITIATOR 0x08
+#define IKEV2_HDR_VERSION 0x10
+#define IKEV2_HDR_RESPONSE 0x20
+
+/* Payload Header Flags */
+#define IKEV2_PAYLOAD_FLAGS_CRITICAL 0x01
+
+
+/* EAP-IKEv2 Payload Types (in Next Payload Type field)
+ * http://www.iana.org/assignments/eap-ikev2-payloads */
+enum {
+ IKEV2_PAYLOAD_NO_NEXT_PAYLOAD = 0,
+ IKEV2_PAYLOAD_SA = 33,
+ IKEV2_PAYLOAD_KEY_EXCHANGE = 34,
+ IKEV2_PAYLOAD_IDi = 35,
+ IKEV2_PAYLOAD_IDr = 36,
+ IKEV2_PAYLOAD_CERTIFICATE = 37,
+ IKEV2_PAYLOAD_CERT_REQ = 38,
+ IKEV2_PAYLOAD_AUTHENTICATION = 39,
+ IKEV2_PAYLOAD_NONCE = 40,
+ IKEV2_PAYLOAD_NOTIFICATION = 41,
+ IKEV2_PAYLOAD_VENDOD_ID = 43,
+ IKEV2_PAYLOAD_ENCRYPTED = 46,
+ IKEV2_PAYLOAD_NEXT_FAST_ID = 121
+};
+
+
+/* IKEv2 Proposal - Protocol ID */
+enum {
+ IKEV2_PROTOCOL_RESERVED = 0,
+ IKEV2_PROTOCOL_IKE = 1, /* IKE is the only one allowed for EAP-IKEv2 */
+ IKEV2_PROTOCOL_AH = 2,
+ IKEV2_PROTOCOL_ESP = 3
+};
+
+
+/* IKEv2 Transform Types */
+enum {
+ IKEV2_TRANSFORM_ENCR = 1,
+ IKEV2_TRANSFORM_PRF = 2,
+ IKEV2_TRANSFORM_INTEG = 3,
+ IKEV2_TRANSFORM_DH = 4,
+ IKEV2_TRANSFORM_ESN = 5
+};
+
+/* IKEv2 Tranform Type 1 (Encryption Algorithm) */
+enum {
+ ENCR_DES_IV64 = 1,
+ ENCR_DES = 2,
+ ENCR_3DES = 3,
+ ENCR_RC5 = 4,
+ ENCR_IDEA = 5,
+ ENCR_CAST = 6,
+ ENCR_BLOWFISH = 7,
+ ENCR_3IDEA = 8,
+ ENCR_DES_IV32 = 9,
+ ENCR_NULL = 11,
+ ENCR_AES_CBC = 12,
+ ENCR_AES_CTR = 13
+};
+
+/* IKEv2 Transform Type 2 (Pseudo-random Function) */
+enum {
+ PRF_HMAC_MD5 = 1,
+ PRF_HMAC_SHA1 = 2,
+ PRF_HMAC_TIGER = 3,
+ PRF_AES128_XCBC = 4
+};
+
+/* IKEv2 Transform Type 3 (Integrity Algorithm) */
+enum {
+ AUTH_HMAC_MD5_96 = 1,
+ AUTH_HMAC_SHA1_96 = 2,
+ AUTH_DES_MAC = 3,
+ AUTH_KPDK_MD5 = 4,
+ AUTH_AES_XCBC_96 = 5
+};
+
+/* IKEv2 Transform Type 4 (Diffie-Hellman Group) */
+enum {
+ DH_GROUP1_768BIT_MODP = 1, /* RFC 4306 */
+ DH_GROUP2_1024BIT_MODP = 2, /* RFC 4306 */
+ DH_GROUP5_1536BIT_MODP = 5, /* RFC 3526 */
+ DH_GROUP5_2048BIT_MODP = 14, /* RFC 3526 */
+ DH_GROUP5_3072BIT_MODP = 15, /* RFC 3526 */
+ DH_GROUP5_4096BIT_MODP = 16, /* RFC 3526 */
+ DH_GROUP5_6144BIT_MODP = 17, /* RFC 3526 */
+ DH_GROUP5_8192BIT_MODP = 18 /* RFC 3526 */
+};
+
+
+/* Identification Data Types (RFC 4306, Sect. 3.5) */
+enum {
+ ID_IPV4_ADDR = 1,
+ ID_FQDN = 2,
+ ID_RFC822_ADDR = 3,
+ ID_IPV6_ADDR = 5,
+ ID_DER_ASN1_DN = 9,
+ ID_DER_ASN1_GN= 10,
+ ID_KEY_ID = 11
+};
+
+
+/* Certificate Encoding (RFC 4306, Sect. 3.6) */
+enum {
+ CERT_ENCODING_PKCS7_X509 = 1,
+ CERT_ENCODING_PGP_CERT = 2,
+ CERT_ENCODING_DNS_SIGNED_KEY = 3,
+ /* X.509 Certificate - Signature: DER encoded X.509 certificate whose
+ * public key is used to validate the sender's AUTH payload */
+ CERT_ENCODING_X509_CERT_SIGN = 4,
+ CERT_ENCODING_KERBEROS_TOKEN = 6,
+ /* DER encoded X.509 certificate revocation list */
+ CERT_ENCODING_CRL = 7,
+ CERT_ENCODING_ARL = 8,
+ CERT_ENCODING_SPKI_CERT = 9,
+ CERT_ENCODING_X509_CERT_ATTR = 10,
+ /* PKCS #1 encoded RSA key */
+ CERT_ENCODING_RAW_RSA_KEY = 11,
+ CERT_ENCODING_HASH_AND_URL_X509_CERT = 12,
+ CERT_ENCODING_HASH_AND_URL_X509_BUNDLE = 13
+};
+
+
+/* Authentication Method (RFC 4306, Sect. 3.8) */
+enum {
+ AUTH_RSA_SIGN = 1,
+ AUTH_SHARED_KEY_MIC = 2,
+ AUTH_DSS_SIGN = 3
+};
+
+
+/* Notify Message Types (RFC 4306, Sect. 3.10.1) */
+enum {
+ UNSUPPORTED_CRITICAL_PAYLOAD = 1,
+ INVALID_IKE_SPI = 4,
+ INVALID_MAJOR_VERSION = 5,
+ INVALID_SYNTAX = 7,
+ INVALID_MESSAGE_ID = 9,
+ INVALID_SPI = 11,
+ NO_PROPOSAL_CHOSEN = 14,
+ INVALID_KE_PAYLOAD = 17,
+ AUTHENTICATION_FAILED = 24,
+ SINGLE_PAIR_REQUIRED = 34,
+ NO_ADDITIONAL_SAS = 35,
+ INTERNAL_ADDRESS_FAILURE = 36,
+ FAILED_CP_REQUIRED = 37,
+ TS_UNACCEPTABLE = 38,
+ INVALID_SELECTORS = 39
+};
+
+
+struct ikev2_keys {
+ u8 *SK_d, *SK_ai, *SK_ar, *SK_ei, *SK_er, *SK_pi, *SK_pr;
+ size_t SK_d_len, SK_integ_len, SK_encr_len, SK_prf_len;
+};
+
+
+int ikev2_keys_set(struct ikev2_keys *keys);
+void ikev2_free_keys(struct ikev2_keys *keys);
+
+
+/* Maximum hash length for supported hash algorithms */
+#define IKEV2_MAX_HASH_LEN 20
+
+struct ikev2_integ_alg {
+ int id;
+ size_t key_len;
+ size_t hash_len;
+};
+
+struct ikev2_prf_alg {
+ int id;
+ size_t key_len;
+ size_t hash_len;
+};
+
+struct ikev2_encr_alg {
+ int id;
+ size_t key_len;
+ size_t block_size;
+};
+
+const struct ikev2_integ_alg * ikev2_get_integ(int id);
+int ikev2_integ_hash(int alg, const u8 *key, size_t key_len, const u8 *data,
+ size_t data_len, u8 *hash);
+const struct ikev2_prf_alg * ikev2_get_prf(int id);
+int ikev2_prf_hash(int alg, const u8 *key, size_t key_len,
+ size_t num_elem, const u8 *addr[], const size_t *len,
+ u8 *hash);
+int ikev2_prf_plus(int alg, const u8 *key, size_t key_len,
+ const u8 *data, size_t data_len,
+ u8 *out, size_t out_len);
+const struct ikev2_encr_alg * ikev2_get_encr(int id);
+int ikev2_encr_encrypt(int alg, const u8 *key, size_t key_len, const u8 *iv,
+ const u8 *plain, u8 *crypt, size_t len);
+int ikev2_encr_decrypt(int alg, const u8 *key, size_t key_len, const u8 *iv,
+ const u8 *crypt, u8 *plain, size_t len);
+
+int ikev2_derive_auth_data(int prf_alg, const struct wpabuf *sign_msg,
+ const u8 *ID, size_t ID_len, u8 ID_type,
+ struct ikev2_keys *keys, int initiator,
+ const u8 *shared_secret, size_t shared_secret_len,
+ const u8 *nonce, size_t nonce_len,
+ const u8 *key_pad, size_t key_pad_len,
+ u8 *auth_data);
+
+
+struct ikev2_payloads {
+ const u8 *sa;
+ size_t sa_len;
+ const u8 *ke;
+ size_t ke_len;
+ const u8 *idi;
+ size_t idi_len;
+ const u8 *idr;
+ size_t idr_len;
+ const u8 *cert;
+ size_t cert_len;
+ const u8 *auth;
+ size_t auth_len;
+ const u8 *nonce;
+ size_t nonce_len;
+ const u8 *encrypted;
+ size_t encrypted_len;
+ u8 encr_next_payload;
+ const u8 *notification;
+ size_t notification_len;
+};
+
+int ikev2_parse_payloads(struct ikev2_payloads *payloads,
+ u8 next_payload, const u8 *pos, const u8 *end);
+
+u8 * ikev2_decrypt_payload(int encr_id, int integ_id, struct ikev2_keys *keys,
+ int initiator, const struct ikev2_hdr *hdr,
+ const u8 *encrypted, size_t encrypted_len,
+ size_t *res_len);
+void ikev2_update_hdr(struct wpabuf *msg);
+int ikev2_build_encrypted(int encr_id, int integ_id, struct ikev2_keys *keys,
+ int initiator, struct wpabuf *msg,
+ struct wpabuf *plain, u8 next_payload);
+int ikev2_derive_sk_keys(const struct ikev2_prf_alg *prf,
+ const struct ikev2_integ_alg *integ,
+ const struct ikev2_encr_alg *encr,
+ const u8 *skeyseed, const u8 *data, size_t data_len,
+ struct ikev2_keys *keys);
+
+#endif /* IKEV2_COMMON_H */
Modified: wpasupplicant/branches/upstream/current/src/eap_peer/eap_fast.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_peer/eap_fast.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_peer/eap_fast.c (original)
+++ wpasupplicant/branches/upstream/current/src/eap_peer/eap_fast.c Tue Jan 1 13:50:28 2008
@@ -212,7 +212,10 @@
* fragments before data, so disable that workaround for CBC.
* TODO: consider making this configurable
*/
- tls_connection_enable_workaround(sm->ssl_ctx, data->ssl.conn);
+ if (tls_connection_enable_workaround(sm->ssl_ctx, data->ssl.conn)) {
+ wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to enable TLS "
+ "workarounds");
+ }
if (data->use_pac_binary_format &&
eap_fast_load_pac_bin(sm, &data->pac, config->pac_file) < 0) {
@@ -1432,10 +1435,10 @@
in_decrypted);
if (wpabuf_len(in_decrypted) < 4) {
- wpabuf_free(in_decrypted);
wpa_printf(MSG_INFO, "EAP-FAST: Too short Phase 2 "
"TLV frame (len=%lu)",
(unsigned long) wpabuf_len(in_decrypted));
+ wpabuf_free(in_decrypted);
return -1;
}
Added: wpasupplicant/branches/upstream/current/src/eap_peer/eap_ikev2.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_peer/eap_ikev2.c?rev=967&op=file
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_peer/eap_ikev2.c (added)
+++ wpasupplicant/branches/upstream/current/src/eap_peer/eap_ikev2.c Tue Jan 1 13:50:28 2008
@@ -1,0 +1,506 @@
+/*
+ * EAP-IKEv2 peer (draft-tschofenig-eap-ikev2-15.txt)
+ * Copyright (c) 2007, Jouni Malinen <j at w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "eap_i.h"
+#include "eap_common/eap_ikev2_common.h"
+#include "ikev2.h"
+
+
+struct eap_ikev2_data {
+ struct ikev2_responder_data ikev2;
+ enum { WAIT_START, MSG, WAIT_FRAG_ACK, DONE, FAIL } state;
+ struct wpabuf *in_buf;
+ struct wpabuf *out_buf;
+ size_t out_used;
+ size_t fragment_size;
+ int keys_ready;
+ u8 keymat[EAP_MSK_LEN + EAP_EMSK_LEN];
+ int keymat_ok;
+};
+
+
+static const char * eap_ikev2_state_txt(int state)
+{
+ switch (state) {
+ case WAIT_START:
+ return "WAIT_START";
+ case MSG:
+ return "MSG";
+ case WAIT_FRAG_ACK:
+ return "WAIT_FRAG_ACK";
+ case DONE:
+ return "DONE";
+ case FAIL:
+ return "FAIL";
+ default:
+ return "?";
+ }
+}
+
+
+static void eap_ikev2_state(struct eap_ikev2_data *data, int state)
+{
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: %s -> %s",
+ eap_ikev2_state_txt(data->state),
+ eap_ikev2_state_txt(state));
+ data->state = state;
+}
+
+
+static void * eap_ikev2_init(struct eap_sm *sm)
+{
+ struct eap_ikev2_data *data;
+ const u8 *identity, *password;
+ size_t identity_len, password_len;
+
+ identity = eap_get_config_identity(sm, &identity_len);
+ if (identity == NULL) {
+ wpa_printf(MSG_INFO, "EAP-IKEV2: No identity available");
+ return NULL;
+ }
+
+ data = os_zalloc(sizeof(*data));
+ if (data == NULL)
+ return NULL;
+ data->state = WAIT_START;
+ data->fragment_size = IKEV2_FRAGMENT_SIZE;
+ data->ikev2.state = SA_INIT;
+ data->ikev2.peer_auth = PEER_AUTH_SECRET;
+ data->ikev2.key_pad = (u8 *) os_strdup("Key Pad for EAP-IKEv2");
+ if (data->ikev2.key_pad == NULL)
+ goto failed;
+ data->ikev2.key_pad_len = 21;
+ data->ikev2.IDr = os_malloc(identity_len);
+ if (data->ikev2.IDr == NULL)
+ goto failed;
+ os_memcpy(data->ikev2.IDr, identity, identity_len);
+ data->ikev2.IDr_len = identity_len;
+
+ password = eap_get_config_password(sm, &password_len);
+ if (password) {
+ data->ikev2.shared_secret = os_malloc(password_len);
+ if (data->ikev2.shared_secret == NULL)
+ goto failed;
+ os_memcpy(data->ikev2.shared_secret, password, password_len);
+ data->ikev2.shared_secret_len = password_len;
+ }
+
+ return data;
+
+failed:
+ ikev2_responder_deinit(&data->ikev2);
+ os_free(data);
+ return NULL;
+}
+
+
+static void eap_ikev2_deinit(struct eap_sm *sm, void *priv)
+{
+ struct eap_ikev2_data *data = priv;
+ wpabuf_free(data->in_buf);
+ wpabuf_free(data->out_buf);
+ ikev2_responder_deinit(&data->ikev2);
+ os_free(data);
+}
+
+
+static int eap_ikev2_peer_keymat(struct eap_ikev2_data *data)
+{
+ if (eap_ikev2_derive_keymat(
+ data->ikev2.proposal.prf, &data->ikev2.keys,
+ data->ikev2.i_nonce, data->ikev2.i_nonce_len,
+ data->ikev2.r_nonce, data->ikev2.r_nonce_len,
+ data->keymat) < 0) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to "
+ "derive key material");
+ return -1;
+ }
+ data->keymat_ok = 1;
+ return 0;
+}
+
+
+static struct wpabuf * eap_ikev2_build_msg(struct eap_ikev2_data *data,
+ struct eap_method_ret *ret, u8 id)
+{
+ struct wpabuf *resp;
+ u8 flags;
+ size_t send_len, plen, icv_len = 0;
+
+ ret->ignore = FALSE;
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Generating Response");
+ ret->allowNotifications = TRUE;
+
+ flags = 0;
+ send_len = wpabuf_len(data->out_buf) - data->out_used;
+ if (1 + send_len > data->fragment_size) {
+ send_len = data->fragment_size - 1;
+ flags |= IKEV2_FLAGS_MORE_FRAGMENTS;
+ if (data->out_used == 0) {
+ flags |= IKEV2_FLAGS_LENGTH_INCLUDED;
+ send_len -= 4;
+ }
+ }
+#ifdef CCNS_PL
+ /* Some issues figuring out the length of the message if Message Length
+ * field not included?! */
+ if (!(flags & IKEV2_FLAGS_LENGTH_INCLUDED))
+ flags |= IKEV2_FLAGS_LENGTH_INCLUDED;
+#endif /* CCNS_PL */
+
+ plen = 1 + send_len;
+ if (flags & IKEV2_FLAGS_LENGTH_INCLUDED)
+ plen += 4;
+ if (data->keys_ready) {
+ const struct ikev2_integ_alg *integ;
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Add Integrity Checksum "
+ "Data");
+ flags |= IKEV2_FLAGS_ICV_INCLUDED;
+ integ = ikev2_get_integ(data->ikev2.proposal.integ);
+ if (integ == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG "
+ "transform / cannot generate ICV");
+ return NULL;
+ }
+ icv_len = integ->hash_len;
+
+ plen += icv_len;
+ }
+ resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, plen,
+ EAP_CODE_RESPONSE, id);
+ if (resp == NULL)
+ return NULL;
+
+ wpabuf_put_u8(resp, flags); /* Flags */
+ if (flags & IKEV2_FLAGS_LENGTH_INCLUDED)
+ wpabuf_put_be32(resp, wpabuf_len(data->out_buf));
+
+ wpabuf_put_data(resp, wpabuf_head_u8(data->out_buf) + data->out_used,
+ send_len);
+ data->out_used += send_len;
+
+ if (flags & IKEV2_FLAGS_ICV_INCLUDED) {
+ const u8 *msg = wpabuf_head(resp);
+ size_t len = wpabuf_len(resp);
+ ikev2_integ_hash(data->ikev2.proposal.integ,
+ data->ikev2.keys.SK_ar,
+ data->ikev2.keys.SK_integ_len,
+ msg, len, wpabuf_put(resp, icv_len));
+ }
+
+ ret->methodState = METHOD_MAY_CONT;
+ ret->decision = DECISION_FAIL;
+
+ if (data->out_used == wpabuf_len(data->out_buf)) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes "
+ "(message sent completely)",
+ (unsigned long) send_len);
+ wpabuf_free(data->out_buf);
+ data->out_buf = NULL;
+ data->out_used = 0;
+ switch (data->ikev2.state) {
+ case SA_AUTH:
+ /* SA_INIT was sent out, so message have to be
+ * integrity protected from now on. */
+ data->keys_ready = 1;
+ break;
+ case IKEV2_DONE:
+ ret->methodState = METHOD_DONE;
+ if (data->state == FAIL)
+ break;
+ ret->decision = DECISION_COND_SUCC;
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Authentication "
+ "completed successfully");
+ if (eap_ikev2_peer_keymat(data))
+ break;
+ eap_ikev2_state(data, DONE);
+ break;
+ case IKEV2_FAILED:
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Authentication "
+ "failed");
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_FAIL;
+ break;
+ default:
+ break;
+ }
+ } else {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes "
+ "(%lu more to send)", (unsigned long) send_len,
+ (unsigned long) wpabuf_len(data->out_buf) -
+ data->out_used);
+ eap_ikev2_state(data, WAIT_FRAG_ACK);
+ }
+
+ return resp;
+}
+
+
+static int eap_ikev2_process_icv(struct eap_ikev2_data *data,
+ const struct wpabuf *reqData,
+ u8 flags, const u8 *pos, const u8 **end)
+{
+ if (flags & IKEV2_FLAGS_ICV_INCLUDED) {
+ int icv_len = eap_ikev2_validate_icv(
+ data->ikev2.proposal.integ, &data->ikev2.keys, 1,
+ reqData, pos, *end);
+ if (icv_len < 0)
+ return -1;
+ /* Hide Integrity Checksum Data from further processing */
+ *end -= icv_len;
+ } else if (data->keys_ready) {
+ wpa_printf(MSG_INFO, "EAP-IKEV2: The message should have "
+ "included integrity checksum");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int eap_ikev2_process_cont(struct eap_ikev2_data *data,
+ const u8 *buf, size_t len)
+{
+ /* Process continuation of a pending message */
+ if (len > wpabuf_tailroom(data->in_buf)) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment overflow");
+ eap_ikev2_state(data, FAIL);
+ return -1;
+ }
+
+ wpabuf_put_data(data->in_buf, buf, len);
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received %lu bytes, waiting "
+ "for %lu bytes more", (unsigned long) len,
+ (unsigned long) wpabuf_tailroom(data->in_buf));
+
+ return 0;
+}
+
+
+static struct wpabuf * eap_ikev2_process_fragment(struct eap_ikev2_data *data,
+ struct eap_method_ret *ret,
+ u8 id, u8 flags,
+ u32 message_length,
+ const u8 *buf, size_t len)
+{
+ /* Process a fragment that is not the last one of the message */
+ if (data->in_buf == NULL && !(flags & IKEV2_FLAGS_LENGTH_INCLUDED)) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: No Message Length field in "
+ "a fragmented packet");
+ ret->ignore = TRUE;
+ return NULL;
+ }
+
+ if (data->in_buf == NULL) {
+ /* First fragment of the message */
+ data->in_buf = wpabuf_alloc(message_length);
+ if (data->in_buf == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: No memory for "
+ "message");
+ ret->ignore = TRUE;
+ return NULL;
+ }
+ wpabuf_put_data(data->in_buf, buf, len);
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received %lu bytes in first "
+ "fragment, waiting for %lu bytes more",
+ (unsigned long) len,
+ (unsigned long) wpabuf_tailroom(data->in_buf));
+ }
+
+ return eap_ikev2_build_frag_ack(id, EAP_CODE_RESPONSE);
+}
+
+
+static struct wpabuf * eap_ikev2_process(struct eap_sm *sm, void *priv,
+ struct eap_method_ret *ret,
+ const struct wpabuf *reqData)
+{
+ struct eap_ikev2_data *data = priv;
+ const u8 *start, *pos, *end;
+ size_t len;
+ u8 flags, id;
+ u32 message_length = 0;
+ struct wpabuf tmpbuf;
+
+ pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, reqData, &len);
+ if (pos == NULL) {
+ ret->ignore = TRUE;
+ return NULL;
+ }
+
+ id = eap_get_id(reqData);
+
+ start = pos;
+ end = start + len;
+
+ if (len == 0)
+ flags = 0; /* fragment ack */
+ else
+ flags = *pos++;
+
+ if (eap_ikev2_process_icv(data, reqData, flags, pos, &end) < 0) {
+ ret->ignore = TRUE;
+ return NULL;
+ }
+
+ if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) {
+ if (end - pos < 4) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Message underflow");
+ ret->ignore = TRUE;
+ return NULL;
+ }
+ message_length = WPA_GET_BE32(pos);
+ pos += 4;
+
+ if (message_length < (u32) (end - pos)) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Invalid Message "
+ "Length (%d; %d remaining in this msg)",
+ message_length, end - pos);
+ ret->ignore = TRUE;
+ return NULL;
+ }
+ }
+
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received packet: Flags 0x%x "
+ "Message Length %u", flags, message_length);
+
+ if (data->state == WAIT_FRAG_ACK) {
+#ifdef CCNS_PL
+ if (len > 1) /* Empty Flags field included in ACK */
+#else /* CCNS_PL */
+ if (len != 0)
+#endif /* CCNS_PL */
+ {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected payload "
+ "in WAIT_FRAG_ACK state");
+ ret->ignore = TRUE;
+ return NULL;
+ }
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment acknowledged");
+ eap_ikev2_state(data, MSG);
+ return eap_ikev2_build_msg(data, ret, id);
+ }
+
+ if (data->in_buf && eap_ikev2_process_cont(data, pos, end - pos) < 0) {
+ ret->ignore = TRUE;
+ return NULL;
+ }
+
+ if (flags & IKEV2_FLAGS_MORE_FRAGMENTS) {
+ return eap_ikev2_process_fragment(data, ret, id, flags,
+ message_length, pos,
+ end - pos);
+ }
+
+ if (data->in_buf == NULL) {
+ /* Wrap unfragmented messages as wpabuf without extra copy */
+ wpabuf_set(&tmpbuf, pos, end - pos);
+ data->in_buf = &tmpbuf;
+ }
+
+ if (ikev2_responder_process(&data->ikev2, data->in_buf) < 0) {
+ if (data->in_buf == &tmpbuf)
+ data->in_buf = NULL;
+ eap_ikev2_state(data, FAIL);
+ return NULL;
+ }
+
+ if (data->in_buf != &tmpbuf)
+ wpabuf_free(data->in_buf);
+ data->in_buf = NULL;
+
+ if (data->out_buf == NULL) {
+ data->out_buf = ikev2_responder_build(&data->ikev2);
+ if (data->out_buf == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to generate "
+ "IKEv2 message");
+ return NULL;
+ }
+ data->out_used = 0;
+ }
+
+ eap_ikev2_state(data, MSG);
+ return eap_ikev2_build_msg(data, ret, id);
+}
+
+
+static Boolean eap_ikev2_isKeyAvailable(struct eap_sm *sm, void *priv)
+{
+ struct eap_ikev2_data *data = priv;
+ return data->state == DONE && data->keymat_ok;
+}
+
+
+static u8 * eap_ikev2_getKey(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_ikev2_data *data = priv;
+ u8 *key;
+
+ if (data->state != DONE || !data->keymat_ok)
+ return NULL;
+
+ key = os_malloc(EAP_MSK_LEN);
+ if (key) {
+ os_memcpy(key, data->keymat, EAP_MSK_LEN);
+ *len = EAP_MSK_LEN;
+ }
+
+ return key;
+}
+
+
+static u8 * eap_ikev2_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_ikev2_data *data = priv;
+ u8 *key;
+
+ if (data->state != DONE || !data->keymat_ok)
+ return NULL;
+
+ key = os_malloc(EAP_EMSK_LEN);
+ if (key) {
+ os_memcpy(key, data->keymat + EAP_MSK_LEN, EAP_EMSK_LEN);
+ *len = EAP_EMSK_LEN;
+ }
+
+ return key;
+}
+
+
+int eap_peer_ikev2_register(void)
+{
+ struct eap_method *eap;
+ int ret;
+
+ eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
+ EAP_VENDOR_IETF, EAP_TYPE_IKEV2,
+ "IKEV2");
+ if (eap == NULL)
+ return -1;
+
+ eap->init = eap_ikev2_init;
+ eap->deinit = eap_ikev2_deinit;
+ eap->process = eap_ikev2_process;
+ eap->isKeyAvailable = eap_ikev2_isKeyAvailable;
+ eap->getKey = eap_ikev2_getKey;
+ eap->get_emsk = eap_ikev2_get_emsk;
+
+ ret = eap_peer_method_register(eap);
+ if (ret)
+ eap_peer_method_free(eap);
+ return ret;
+}
Modified: wpasupplicant/branches/upstream/current/src/eap_peer/eap_methods.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_peer/eap_methods.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_peer/eap_methods.c (original)
+++ wpasupplicant/branches/upstream/current/src/eap_peer/eap_methods.c Tue Jan 1 13:50:28 2008
@@ -462,6 +462,13 @@
}
#endif /* EAP_WSC */
+#ifdef EAP_IKEV2
+ if (ret == 0) {
+ int eap_peer_ikev2_register(void);
+ ret = eap_peer_ikev2_register();
+ }
+#endif /* EAP_IKEV2 */
+
#ifdef EAP_VENDOR_TEST
if (ret == 0) {
int eap_peer_vendor_test_register(void);
Modified: wpasupplicant/branches/upstream/current/src/eap_peer/eap_mschapv2.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_peer/eap_mschapv2.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_peer/eap_mschapv2.c (original)
+++ wpasupplicant/branches/upstream/current/src/eap_peer/eap_mschapv2.c Tue Jan 1 13:50:28 2008
@@ -623,13 +623,15 @@
/* Encrypted-Password */
if (pwhash) {
- encrypt_pw_block_with_password_hash(
- new_password, new_password_len,
- password, cp->encr_password);
+ if (encrypt_pw_block_with_password_hash(
+ new_password, new_password_len,
+ password, cp->encr_password))
+ goto fail;
} else {
- new_password_encrypted_with_old_nt_password_hash(
- new_password, new_password_len,
- password, password_len, cp->encr_password);
+ if (new_password_encrypted_with_old_nt_password_hash(
+ new_password, new_password_len,
+ password, password_len, cp->encr_password))
+ goto fail;
}
/* Encrypted-Hash */
@@ -647,10 +649,8 @@
}
/* Peer-Challenge */
- if (os_get_random(cp->peer_challenge, MSCHAPV2_CHAL_LEN)) {
- wpabuf_free(resp);
- return NULL;
- }
+ if (os_get_random(cp->peer_challenge, MSCHAPV2_CHAL_LEN))
+ goto fail;
/* Reserved, must be zero */
os_memset(cp->reserved, 0, 8);
@@ -694,6 +694,10 @@
"(change pw)", id, ms->mschapv2_id);
return resp;
+
+fail:
+ wpabuf_free(resp);
+ return NULL;
}
Modified: wpasupplicant/branches/upstream/current/src/eap_peer/eap_psk.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_peer/eap_psk.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_peer/eap_psk.c (original)
+++ wpasupplicant/branches/upstream/current/src/eap_peer/eap_psk.c Tue Jan 1 13:50:28 2008
@@ -48,7 +48,10 @@
data = os_zalloc(sizeof(*data));
if (data == NULL)
return NULL;
- eap_psk_key_setup(config->eappsk, data->ak, data->kdk);
+ if (eap_psk_key_setup(config->eappsk, data->ak, data->kdk)) {
+ os_free(data);
+ return NULL;
+ }
wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN);
wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN);
data->state = PSK_INIT;
@@ -154,7 +157,11 @@
os_memcpy(pos, hdr1->rand_s, EAP_PSK_RAND_LEN);
pos += EAP_PSK_RAND_LEN;
os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN);
- omac1_aes_128(data->ak, buf, buflen, hdr2->mac_p);
+ if (omac1_aes_128(data->ak, buf, buflen, hdr2->mac_p)) {
+ os_free(buf);
+ wpabuf_free(resp);
+ return NULL;
+ }
os_free(buf);
wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_P", hdr2->rand_p,
EAP_PSK_RAND_LEN);
@@ -225,7 +232,10 @@
return NULL;
os_memcpy(buf, data->id_s, data->id_s_len);
os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN);
- omac1_aes_128(data->ak, buf, buflen, mac);
+ if (omac1_aes_128(data->ak, buf, buflen, mac)) {
+ os_free(buf);
+ return NULL;
+ }
os_free(buf);
if (os_memcmp(mac, hdr3->mac_s, EAP_PSK_MAC_LEN) != 0) {
wpa_printf(MSG_WARNING, "EAP-PSK: Invalid MAC_S in third "
@@ -236,8 +246,12 @@
}
wpa_printf(MSG_DEBUG, "EAP-PSK: MAC_S verified successfully");
- eap_psk_derive_keys(data->kdk, data->rand_p, data->tek,
- data->msk, data->emsk);
+ if (eap_psk_derive_keys(data->kdk, data->rand_p, data->tek,
+ data->msk, data->emsk)) {
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_FAIL;
+ return NULL;
+ }
wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN);
wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN);
wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN);
@@ -331,9 +345,14 @@
wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (plaintext)",
rpchannel + 4 + 16, data_len);
- aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), wpabuf_head(resp),
- sizeof(struct eap_hdr) + 1 + sizeof(*hdr4),
- rpchannel + 4 + 16, data_len, rpchannel + 4);
+ if (aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce),
+ wpabuf_head(resp),
+ sizeof(struct eap_hdr) + 1 + sizeof(*hdr4),
+ rpchannel + 4 + 16, data_len, rpchannel + 4)) {
+ os_free(decrypted);
+ wpabuf_free(resp);
+ return NULL;
+ }
wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (PCHANNEL)",
rpchannel, 4 + 16 + data_len);
Modified: wpasupplicant/branches/upstream/current/src/eap_peer/eap_wsc.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_peer/eap_wsc.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_peer/eap_wsc.c (original)
+++ wpasupplicant/branches/upstream/current/src/eap_peer/eap_wsc.c Tue Jan 1 13:50:28 2008
@@ -17,123 +17,16 @@
#include "common.h"
#include "eap_i.h"
#include "eap_common/eap_wsc_common.h"
-
-
-struct wps_data {
- int registrar;
- int msg_num;
-};
-
-
-static struct wps_data * wps_init(int registrar)
-{
- struct wps_data *data = os_zalloc(sizeof(*data));
- if (data == NULL)
- return NULL;
- data->registrar = registrar;
- data->msg_num = 1;
- return data;
-}
-
-
-static void wps_deinit(struct wps_data *data)
-{
- os_free(data);
-}
-
-
-enum wps_process_res {
- WPS_DONE, WPS_CONTINUE, WPS_FAILURE, WPS_PENDING
-};
-
-static enum wps_process_res wps_process_msg(struct wps_data *wps, u8 op_code,
- const u8 *msg, size_t msg_len)
-{
- /* TODO: proper processing and/or sending to an external process */
-
- wpa_hexdump(MSG_MSGDUMP, "WPS: Received message", msg, msg_len);
- if ((wps->registrar && (wps->msg_num & 1) == 0) ||
- (!wps->registrar && (wps->msg_num & 1) == 1)) {
- wpa_printf(MSG_DEBUG, "WPS: Unexpected message number %d",
- wps->msg_num);
- return WPS_FAILURE;
- }
-
- if (wps->msg_num <= 8 && op_code == WSC_MSG) {
- wpa_printf(MSG_DEBUG, "WPS: Process M%d", wps->msg_num);
- } else if (wps->registrar && wps->msg_num == 9 &&
- op_code == WSC_Done) {
- wpa_printf(MSG_DEBUG, "WPS: Process Done");
- } else {
- wpa_printf(MSG_DEBUG, "WPS: Unexpected Op-Code %d "
- "(msg_num=%d)", op_code, wps->msg_num);
- return WPS_FAILURE;
- }
-
- wps->msg_num++;
- return WPS_CONTINUE;
-
-}
-
-
-static u8 * wps_get_msg(struct wps_data *wps, size_t *msg_len, u8 *op_code)
-{
- u8 *msg;
-
- /* TODO: proper processing and/or query from an external process */
-
- if ((wps->registrar && (wps->msg_num & 1) == 1) ||
- (!wps->registrar && (wps->msg_num & 1) == 0)) {
- wpa_printf(MSG_DEBUG, "WPS: Unexpected request for message "
- "number %d", wps->msg_num);
- return NULL;
- }
-
- if (wps->msg_num == 7 || wps->msg_num == 8) {
- msg = os_zalloc(2000);
- if (msg == NULL)
- return NULL;
- *msg_len = 2000;
- *op_code = WSC_MSG;
- *msg = WSC_MSG;
- wpa_printf(MSG_DEBUG, "WPS: Send M%d", wps->msg_num);
- } else if (wps->msg_num <= 6) {
- msg = os_zalloc(1);
- if (msg == NULL)
- return NULL;
- *msg_len = 1;
- *op_code = WSC_MSG;
- *msg = WSC_MSG;
- wpa_printf(MSG_DEBUG, "WPS: Send M%d", wps->msg_num);
- } else if (!wps->registrar && wps->msg_num == 9) {
- msg = os_zalloc(1);
- if (msg == NULL)
- return NULL;
- *msg_len = 1;
- *op_code = WSC_Done;
- *msg = WSC_Done;
- wpa_printf(MSG_DEBUG, "WPS: Send Done");
- } else if (wps->registrar && wps->msg_num == 10) {
- msg = os_zalloc(1);
- if (msg == NULL)
- return NULL;
- *msg_len = 1;
- *op_code = WSC_ACK;
- *msg = WSC_ACK;
- wpa_printf(MSG_DEBUG, "WPS: Send ACK");
- } else
- return NULL;
-
- wps->msg_num++;
- return msg;
-}
+#include "wps/wps.h"
struct eap_wsc_data {
enum { WAIT_START, MSG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state;
int registrar;
- u8 *in_buf, *out_buf, in_op_code, out_op_code;
- size_t in_len, in_used, out_len, out_used;
+ struct wpabuf *in_buf;
+ struct wpabuf *out_buf;
+ u8 in_op_code, out_op_code;
+ size_t out_used;
size_t fragment_size;
struct wps_data *wps;
};
@@ -195,7 +88,7 @@
return NULL;
data->state = registrar ? MSG : WAIT_START;
data->registrar = registrar;
- data->wps = wps_init(registrar);
+ data->wps = wps_init(0, registrar);
if (data->wps == NULL) {
os_free(data);
return NULL;
@@ -209,8 +102,8 @@
static void eap_wsc_deinit(struct eap_sm *sm, void *priv)
{
struct eap_wsc_data *data = priv;
- os_free(data->in_buf);
- os_free(data->out_buf);
+ wpabuf_free(data->in_buf);
+ wpabuf_free(data->out_buf);
wps_deinit(data->wps);
os_free(data);
}
@@ -228,7 +121,7 @@
ret->allowNotifications = TRUE;
flags = 0;
- send_len = data->out_len - data->out_used;
+ send_len = wpabuf_len(data->out_buf) - data->out_used;
if (2 + send_len > data->fragment_size) {
send_len = data->fragment_size - 2;
flags |= WSC_FLAGS_MF;
@@ -248,21 +141,22 @@
wpabuf_put_u8(resp, data->out_op_code); /* Op-Code */
wpabuf_put_u8(resp, flags); /* Flags */
if (flags & WSC_FLAGS_LF)
- wpabuf_put_be16(resp, data->out_len);
-
- wpabuf_put_data(resp, data->out_buf + data->out_used, send_len);
+ wpabuf_put_be16(resp, wpabuf_len(data->out_buf));
+
+ wpabuf_put_data(resp, wpabuf_head_u8(data->out_buf) + data->out_used,
+ send_len);
data->out_used += send_len;
ret->methodState = METHOD_MAY_CONT;
ret->decision = DECISION_FAIL;
- if (data->out_used == data->out_len) {
+ if (data->out_used == wpabuf_len(data->out_buf)) {
wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes "
"(message sent completely)",
(unsigned long) send_len);
- os_free(data->out_buf);
+ wpabuf_free(data->out_buf);
data->out_buf = NULL;
- data->out_len = data->out_used = 0;
+ data->out_used = 0;
if ((data->state == FAIL && data->out_op_code == WSC_ACK) ||
data->out_op_code == WSC_NACK ||
data->out_op_code == WSC_Done) {
@@ -273,11 +167,73 @@
} else {
wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes "
"(%lu more to send)", (unsigned long) send_len,
- (unsigned long) data->out_len - data->out_used);
+ (unsigned long) wpabuf_len(data->out_buf) -
+ data->out_used);
eap_wsc_state(data, WAIT_FRAG_ACK);
}
return resp;
+}
+
+
+static int eap_wsc_process_cont(struct eap_wsc_data *data,
+ const u8 *buf, size_t len, u8 op_code)
+{
+ /* Process continuation of a pending message */
+ if (op_code != data->in_op_code) {
+ wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d in "
+ "fragment (expected %d)",
+ op_code, data->in_op_code);
+ return -1;
+ }
+
+ if (len > wpabuf_tailroom(data->in_buf)) {
+ wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment overflow");
+ eap_wsc_state(data, FAIL);
+ return -1;
+ }
+
+ wpabuf_put_data(data->in_buf, buf, len);
+ wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes, waiting "
+ "for %lu bytes more", (unsigned long) len,
+ (unsigned long) wpabuf_tailroom(data->in_buf));
+
+ return 0;
+}
+
+
+static struct wpabuf * eap_wsc_process_fragment(struct eap_wsc_data *data,
+ struct eap_method_ret *ret,
+ u8 id, u8 flags, u8 op_code,
+ u16 message_length,
+ const u8 *buf, size_t len)
+{
+ /* Process a fragment that is not the last one of the message */
+ if (data->in_buf == NULL && !(flags & WSC_FLAGS_LF)) {
+ wpa_printf(MSG_DEBUG, "EAP-WSC: No Message Length field in a "
+ "fragmented packet");
+ ret->ignore = TRUE;
+ return NULL;
+ }
+
+ if (data->in_buf == NULL) {
+ /* First fragment of the message */
+ data->in_buf = wpabuf_alloc(message_length);
+ if (data->in_buf == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-WSC: No memory for "
+ "message");
+ ret->ignore = TRUE;
+ return NULL;
+ }
+ data->in_op_code = op_code;
+ wpabuf_put_data(data->in_buf, buf, len);
+ wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes in first "
+ "fragment, waiting for %lu bytes more",
+ (unsigned long) len,
+ (unsigned long) wpabuf_tailroom(data->in_buf));
+ }
+
+ return eap_wsc_build_frag_ack(id, EAP_CODE_RESPONSE);
}
@@ -290,9 +246,8 @@
size_t len;
u8 op_code, flags, id;
u16 message_length = 0;
- const u8 *msg;
- size_t msg_len;
enum wps_process_res res;
+ struct wpabuf tmpbuf;
pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, reqData,
&len);
@@ -367,72 +322,29 @@
return NULL;
}
- if (data->in_buf) {
- /* Process continuation of a pending message */
- if (op_code != data->in_op_code) {
- wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d "
- "in fragment (expected %d)",
- op_code, data->in_op_code);
- ret->ignore = TRUE;
- return NULL;
- }
-
- if (data->in_used + (end - pos) > data->in_len) {
- wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment overflow");
- ret->ignore = TRUE;
- return NULL;
- }
-
- os_memcpy(data->in_buf + data->in_used, pos, end - pos);
- data->in_used += end - pos;
- wpa_printf(MSG_DEBUG, "EAP-WSC: Received %u bytes, waiting "
- "for %lu bytes more", (unsigned int) (end - pos),
- (unsigned long) data->in_len - data->in_used);
+ if (data->in_buf &&
+ eap_wsc_process_cont(data, pos, end - pos, op_code) < 0) {
+ ret->ignore = TRUE;
+ return NULL;
}
if (flags & WSC_FLAGS_MF) {
- if (data->in_buf == NULL && !(flags & WSC_FLAGS_LF)) {
- wpa_printf(MSG_DEBUG, "EAP-WSC: No Message Length "
- "field in a fragmented packet");
- ret->ignore = TRUE;
- return NULL;
- }
-
- if (data->in_buf == NULL) {
- /* First fragment of the message */
- data->in_buf = os_malloc(message_length);
- if (data->in_buf == NULL) {
- wpa_printf(MSG_DEBUG, "EAP-WSC: No memory for "
- "message");
- ret->ignore = TRUE;
- return NULL;
- }
- data->in_len = message_length;
- data->in_used = end - pos;
- data->in_op_code = op_code;
- os_memcpy(data->in_buf, pos, data->in_used);
- wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes in "
- "first fragment, waiting for %lu bytes more",
- (unsigned long) data->in_used,
- (unsigned long) data->in_len - data->in_used);
- }
-
- return eap_wsc_build_frag_ack(id, EAP_CODE_RESPONSE);
- }
-
- if (data->in_buf) {
- msg = data->in_buf;
- msg_len = data->in_len;
- } else {
- msg = pos;
- msg_len = end - pos;
- }
-
- res = wps_process_msg(data->wps, op_code, msg, msg_len);
+ return eap_wsc_process_fragment(data, ret, id, flags, op_code,
+ message_length, pos,
+ end - pos);
+ }
+
+ if (data->in_buf == NULL) {
+ /* Wrap unfragmented messages as wpabuf without extra copy */
+ wpabuf_set(&tmpbuf, pos, end - pos);
+ data->in_buf = &tmpbuf;
+ }
+
+ res = wps_process_msg(data->wps, op_code, data->in_buf);
switch (res) {
case WPS_DONE:
wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing completed "
- "successfully - report EAP failure");
+ "successfully - wait for EAP failure");
eap_wsc_state(data, FAIL);
break;
case WPS_CONTINUE:
@@ -445,22 +357,24 @@
case WPS_PENDING:
wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing pending");
ret->ignore = TRUE;
- return NULL;
- }
-
- os_free(data->in_buf);
+ if (data->in_buf == &tmpbuf)
+ data->in_buf = NULL;
+ return NULL;
+ }
+
+ if (data->in_buf != &tmpbuf)
+ wpabuf_free(data->in_buf);
data->in_buf = NULL;
- data->in_len = data->in_used = 0;
send_msg:
if (data->out_buf == NULL) {
- data->out_buf = wps_get_msg(data->wps, &data->out_len,
- &data->out_op_code);
+ data->out_buf = wps_get_msg(data->wps, &data->out_op_code);
if (data->out_buf == NULL) {
wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to receive "
"message from WPS");
return NULL;
}
+ data->out_used = 0;
}
eap_wsc_state(data, MSG);
Added: wpasupplicant/branches/upstream/current/src/eap_peer/ikev2.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_peer/ikev2.c?rev=967&op=file
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_peer/ikev2.c (added)
+++ wpasupplicant/branches/upstream/current/src/eap_peer/ikev2.c Tue Jan 1 13:50:28 2008
@@ -1,0 +1,1302 @@
+/*
+ * IKEv2 responder (RFC 4306) for EAP-IKEV2
+ * Copyright (c) 2007, Jouni Malinen <j at w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "dh_groups.h"
+#include "ikev2.h"
+
+
+void ikev2_responder_deinit(struct ikev2_responder_data *data)
+{
+ ikev2_free_keys(&data->keys);
+ wpabuf_free(data->i_dh_public);
+ wpabuf_free(data->r_dh_private);
+ os_free(data->IDi);
+ os_free(data->IDr);
+ os_free(data->shared_secret);
+ wpabuf_free(data->i_sign_msg);
+ wpabuf_free(data->r_sign_msg);
+ os_free(data->key_pad);
+}
+
+
+static int ikev2_derive_keys(struct ikev2_responder_data *data)
+{
+ u8 *buf, *pos, *pad, skeyseed[IKEV2_MAX_HASH_LEN];
+ size_t buf_len, pad_len;
+ struct wpabuf *shared;
+ const struct ikev2_integ_alg *integ;
+ const struct ikev2_prf_alg *prf;
+ const struct ikev2_encr_alg *encr;
+ int ret;
+ const u8 *addr[2];
+ size_t len[2];
+
+ /* RFC 4306, Sect. 2.14 */
+
+ integ = ikev2_get_integ(data->proposal.integ);
+ prf = ikev2_get_prf(data->proposal.prf);
+ encr = ikev2_get_encr(data->proposal.encr);
+ if (integ == NULL || prf == NULL || encr == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: Unsupported proposal");
+ return -1;
+ }
+
+ shared = dh_derive_shared(data->i_dh_public, data->r_dh_private,
+ data->dh);
+ if (shared == NULL)
+ return -1;
+
+ /* Construct Ni | Nr | SPIi | SPIr */
+
+ buf_len = data->i_nonce_len + data->r_nonce_len + 2 * IKEV2_SPI_LEN;
+ buf = os_malloc(buf_len);
+ if (buf == NULL) {
+ wpabuf_free(shared);
+ return -1;
+ }
+
+ pos = buf;
+ os_memcpy(pos, data->i_nonce, data->i_nonce_len);
+ pos += data->i_nonce_len;
+ os_memcpy(pos, data->r_nonce, data->r_nonce_len);
+ pos += data->r_nonce_len;
+ os_memcpy(pos, data->i_spi, IKEV2_SPI_LEN);
+ pos += IKEV2_SPI_LEN;
+ os_memcpy(pos, data->r_spi, IKEV2_SPI_LEN);
+#ifdef CCNS_PL
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ {
+ int i;
+ u8 *tmp = pos - IKEV2_SPI_LEN;
+ /* Incorrect byte re-ordering on little endian hosts.. */
+ for (i = 0; i < IKEV2_SPI_LEN; i++)
+ *tmp++ = data->i_spi[IKEV2_SPI_LEN - 1 - i];
+ for (i = 0; i < IKEV2_SPI_LEN; i++)
+ *tmp++ = data->r_spi[IKEV2_SPI_LEN - 1 - i];
+ }
+#endif
+#endif /* CCNS_PL */
+
+ /* SKEYSEED = prf(Ni | Nr, g^ir) */
+ /* Use zero-padding per RFC 4306, Sect. 2.14 */
+ pad_len = data->dh->prime_len - wpabuf_len(shared);
+#ifdef CCNS_PL
+ /* Shared secret is not zero-padded correctly */
+ pad_len = 0;
+#endif /* CCNS_PL */
+ pad = os_zalloc(pad_len ? pad_len : 1);
+ if (pad == NULL) {
+ wpabuf_free(shared);
+ os_free(buf);
+ return -1;
+ }
+
+ addr[0] = pad;
+ len[0] = pad_len;
+ addr[1] = wpabuf_head(shared);
+ len[1] = wpabuf_len(shared);
+ if (ikev2_prf_hash(prf->id, buf, data->i_nonce_len + data->r_nonce_len,
+ 2, addr, len, skeyseed) < 0) {
+ wpabuf_free(shared);
+ os_free(buf);
+ os_free(pad);
+ return -1;
+ }
+ os_free(pad);
+ wpabuf_free(shared);
+
+ /* DH parameters are not needed anymore, so free them */
+ wpabuf_free(data->i_dh_public);
+ data->i_dh_public = NULL;
+ wpabuf_free(data->r_dh_private);
+ data->r_dh_private = NULL;
+
+ wpa_hexdump_key(MSG_DEBUG, "IKEV2: SKEYSEED",
+ skeyseed, prf->hash_len);
+
+ ret = ikev2_derive_sk_keys(prf, integ, encr, skeyseed, buf, buf_len,
+ &data->keys);
+ os_free(buf);
+ return ret;
+}
+
+
+static int ikev2_parse_transform(struct ikev2_proposal_data *prop,
+ const u8 *pos, const u8 *end)
+{
+ int transform_len;
+ const struct ikev2_transform *t;
+ u16 transform_id;
+ const u8 *tend;
+
+ if (end - pos < (int) sizeof(*t)) {
+ wpa_printf(MSG_INFO, "IKEV2: Too short transform");
+ return -1;
+ }
+
+ t = (const struct ikev2_transform *) pos;
+ transform_len = WPA_GET_BE16(t->transform_length);
+ if (transform_len < (int) sizeof(*t) || pos + transform_len > end) {
+ wpa_printf(MSG_INFO, "IKEV2: Invalid transform length %d",
+ transform_len);
+ return -1;
+ }
+ tend = pos + transform_len;
+
+ transform_id = WPA_GET_BE16(t->transform_id);
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Transform:");
+ wpa_printf(MSG_DEBUG, "IKEV2: Type: %d Transform Length: %d "
+ "Transform Type: %d Transform ID: %d",
+ t->type, transform_len, t->transform_type, transform_id);
+
+ if (t->type != 0 && t->type != 3) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Transform type");
+ return -1;
+ }
+
+ pos = (const u8 *) (t + 1);
+ if (pos < tend) {
+ wpa_hexdump(MSG_DEBUG, "IKEV2: Transform Attributes",
+ pos, tend - pos);
+ }
+
+ switch (t->transform_type) {
+ case IKEV2_TRANSFORM_ENCR:
+ if (ikev2_get_encr(transform_id)) {
+ if (transform_id == ENCR_AES_CBC) {
+ if (tend - pos != 4) {
+ wpa_printf(MSG_DEBUG, "IKEV2: No "
+ "Transform Attr for AES");
+ break;
+ }
+#ifdef CCNS_PL
+ if (WPA_GET_BE16(pos) != 0x001d /* ?? */) {
+ wpa_printf(MSG_DEBUG, "IKEV2: Not a "
+ "Key Size attribute for "
+ "AES");
+ break;
+ }
+#else /* CCNS_PL */
+ if (WPA_GET_BE16(pos) != 0x800e) {
+ wpa_printf(MSG_DEBUG, "IKEV2: Not a "
+ "Key Size attribute for "
+ "AES");
+ break;
+ }
+#endif /* CCNS_PL */
+ if (WPA_GET_BE16(pos + 2) != 128) {
+ wpa_printf(MSG_DEBUG, "IKEV2: "
+ "Unsupported AES key size "
+ "%d bits",
+ WPA_GET_BE16(pos + 2));
+ break;
+ }
+ }
+ prop->encr = transform_id;
+ }
+ break;
+ case IKEV2_TRANSFORM_PRF:
+ if (ikev2_get_prf(transform_id))
+ prop->prf = transform_id;
+ break;
+ case IKEV2_TRANSFORM_INTEG:
+ if (ikev2_get_integ(transform_id))
+ prop->integ = transform_id;
+ break;
+ case IKEV2_TRANSFORM_DH:
+ if (dh_groups_get(transform_id))
+ prop->dh = transform_id;
+ break;
+ }
+
+ return transform_len;
+}
+
+
+static int ikev2_parse_proposal(struct ikev2_proposal_data *prop,
+ const u8 *pos, const u8 *end)
+{
+ const u8 *pend, *ppos;
+ int proposal_len, i;
+ const struct ikev2_proposal *p;
+
+ if (end - pos < (int) sizeof(*p)) {
+ wpa_printf(MSG_INFO, "IKEV2: Too short proposal");
+ return -1;
+ }
+
+ /* FIX: AND processing if multiple proposals use the same # */
+
+ p = (const struct ikev2_proposal *) pos;
+ proposal_len = WPA_GET_BE16(p->proposal_length);
+ if (proposal_len < (int) sizeof(*p) || pos + proposal_len > end) {
+ wpa_printf(MSG_INFO, "IKEV2: Invalid proposal length %d",
+ proposal_len);
+ return -1;
+ }
+ wpa_printf(MSG_DEBUG, "IKEV2: SAi1 Proposal # %d",
+ p->proposal_num);
+ wpa_printf(MSG_DEBUG, "IKEV2: Type: %d Proposal Length: %d "
+ " Protocol ID: %d",
+ p->type, proposal_len, p->protocol_id);
+ wpa_printf(MSG_DEBUG, "IKEV2: SPI Size: %d Transforms: %d",
+ p->spi_size, p->num_transforms);
+
+ if (p->type != 0 && p->type != 2) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal type");
+ return -1;
+ }
+
+ if (p->protocol_id != IKEV2_PROTOCOL_IKE) {
+ wpa_printf(MSG_DEBUG, "IKEV2: Unexpected Protocol ID "
+ "(only IKE allowed for EAP-IKEv2)");
+ return -1;
+ }
+
+ if (p->proposal_num != prop->proposal_num) {
+ if (p->proposal_num == prop->proposal_num + 1)
+ prop->proposal_num = p->proposal_num;
+ else {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal #");
+ return -1;
+ }
+ }
+
+ ppos = (const u8 *) (p + 1);
+ pend = pos + proposal_len;
+ if (ppos + p->spi_size > pend) {
+ wpa_printf(MSG_INFO, "IKEV2: Not enough room for SPI "
+ "in proposal");
+ return -1;
+ }
+ if (p->spi_size) {
+ wpa_hexdump(MSG_DEBUG, "IKEV2: SPI",
+ ppos, p->spi_size);
+ ppos += p->spi_size;
+ }
+
+ /*
+ * For initial IKE_SA negotiation, SPI Size MUST be zero; for
+ * subsequent negotiations, it must be 8 for IKE. We only support
+ * initial case for now.
+ */
+ if (p->spi_size != 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected SPI Size");
+ return -1;
+ }
+
+ if (p->num_transforms == 0) {
+ wpa_printf(MSG_INFO, "IKEV2: At least one transform required");
+ return -1;
+ }
+
+ for (i = 0; i < (int) p->num_transforms; i++) {
+ int tlen = ikev2_parse_transform(prop, ppos, pend);
+ if (tlen < 0)
+ return -1;
+ ppos += tlen;
+ }
+
+ if (ppos != pend) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected data after "
+ "transforms");
+ return -1;
+ }
+
+ return proposal_len;
+}
+
+
+static int ikev2_process_sai1(struct ikev2_responder_data *data,
+ const u8 *sai1, size_t sai1_len)
+{
+ struct ikev2_proposal_data prop;
+ const u8 *pos, *end;
+ int found = 0;
+
+ /* Security Association Payloads: <Proposals> */
+
+ if (sai1 == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: SAi1 not received");
+ return -1;
+ }
+
+ os_memset(&prop, 0, sizeof(prop));
+ prop.proposal_num = 1;
+
+ pos = sai1;
+ end = sai1 + sai1_len;
+
+ while (pos < end) {
+ int plen;
+
+ prop.integ = -1;
+ prop.prf = -1;
+ prop.encr = -1;
+ prop.dh = -1;
+ plen = ikev2_parse_proposal(&prop, pos, end);
+ if (plen < 0)
+ return -1;
+
+ if (!found && prop.integ != -1 && prop.prf != -1 &&
+ prop.encr != -1 && prop.dh != -1) {
+ os_memcpy(&data->proposal, &prop, sizeof(prop));
+ data->dh = dh_groups_get(prop.dh);
+ found = 1;
+ }
+
+ pos += plen;
+ }
+
+ if (pos != end) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected data after proposals");
+ return -1;
+ }
+
+ if (!found) {
+ wpa_printf(MSG_INFO, "IKEV2: No acceptable proposal found");
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Accepted proposal #%d: ENCR:%d PRF:%d "
+ "INTEG:%d D-H:%d", data->proposal.proposal_num,
+ data->proposal.encr, data->proposal.prf,
+ data->proposal.integ, data->proposal.dh);
+
+ return 0;
+}
+
+
+static int ikev2_process_kei(struct ikev2_responder_data *data,
+ const u8 *kei, size_t kei_len)
+{
+ u16 group;
+
+ /*
+ * Key Exchange Payload:
+ * DH Group # (16 bits)
+ * RESERVED (16 bits)
+ * Key Exchange Data (Diffie-Hellman public value)
+ */
+
+ if (kei == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: KEi not received");
+ return -1;
+ }
+
+ if (kei_len < 4 + 96) {
+ wpa_printf(MSG_INFO, "IKEV2: Too show Key Exchange Payload");
+ return -1;
+ }
+
+ group = WPA_GET_BE16(kei);
+ wpa_printf(MSG_DEBUG, "IKEV2: KEi DH Group #%u", group);
+
+ if (group != data->proposal.dh) {
+ wpa_printf(MSG_DEBUG, "IKEV2: KEi DH Group #%u does not match "
+ "with the selected proposal (%u)",
+ group, data->proposal.dh);
+ /* Reject message with Notify payload of type
+ * INVALID_KE_PAYLOAD (RFC 4306, Sect. 3.4) */
+ data->error_type = INVALID_KE_PAYLOAD;
+ data->state = NOTIFY;
+ return -1;
+ }
+
+ if (data->dh == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: Unsupported DH group");
+ return -1;
+ }
+
+ /* RFC 4306, Section 3.4:
+ * The length of DH public value MUST be equal to the lenght of the
+ * prime modulus.
+ */
+ if (kei_len - 4 != data->dh->prime_len) {
+ wpa_printf(MSG_INFO, "IKEV2: Invalid DH public value length "
+ "%d (expected %d)",
+ kei_len - 4, data->dh->prime_len);
+ return -1;
+ }
+
+ wpabuf_free(data->i_dh_public);
+ data->i_dh_public = wpabuf_alloc(kei_len - 4);
+ if (data->i_dh_public == NULL)
+ return -1;
+ wpabuf_put_data(data->i_dh_public, kei + 4, kei_len - 4);
+
+ wpa_hexdump_buf(MSG_DEBUG, "IKEV2: KEi Diffie-Hellman Public Value",
+ data->i_dh_public);
+
+ return 0;
+}
+
+
+static int ikev2_process_ni(struct ikev2_responder_data *data,
+ const u8 *ni, size_t ni_len)
+{
+ if (ni == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: Ni not received");
+ return -1;
+ }
+
+ if (ni_len < IKEV2_NONCE_MIN_LEN || ni_len > IKEV2_NONCE_MAX_LEN) {
+ wpa_printf(MSG_INFO, "IKEV2: Invalid Ni length %d", ni_len);
+ return -1;
+ }
+
+#ifdef CCNS_PL
+ /* Zeros are removed incorrectly from the beginning of the nonces */
+ while (ni_len > 1 && *ni == 0) {
+ ni_len--;
+ ni++;
+ }
+#endif /* CCNS_PL */
+
+ data->i_nonce_len = ni_len;
+ os_memcpy(data->i_nonce, ni, ni_len);
+ wpa_hexdump(MSG_MSGDUMP, "IKEV2: Ni",
+ data->i_nonce, data->i_nonce_len);
+
+ return 0;
+}
+
+
+static int ikev2_process_sa_init(struct ikev2_responder_data *data,
+ const struct ikev2_hdr *hdr,
+ struct ikev2_payloads *pl)
+{
+ if (ikev2_process_sai1(data, pl->sa, pl->sa_len) < 0 ||
+ ikev2_process_kei(data, pl->ke, pl->ke_len) < 0 ||
+ ikev2_process_ni(data, pl->nonce, pl->nonce_len) < 0)
+ return -1;
+
+ os_memcpy(data->i_spi, hdr->i_spi, IKEV2_SPI_LEN);
+
+ return 0;
+}
+
+
+static int ikev2_process_idi(struct ikev2_responder_data *data,
+ const u8 *idi, size_t idi_len)
+{
+ u8 id_type;
+
+ if (idi == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: No IDi received");
+ return -1;
+ }
+
+ if (idi_len < 4) {
+ wpa_printf(MSG_INFO, "IKEV2: Too short IDi payload");
+ return -1;
+ }
+
+ id_type = idi[0];
+ idi += 4;
+ idi_len -= 4;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: IDi ID Type %d", id_type);
+ wpa_hexdump_ascii(MSG_DEBUG, "IKEV2: IDi", idi, idi_len);
+ os_free(data->IDi);
+ data->IDi = os_malloc(idi_len);
+ if (data->IDi == NULL)
+ return -1;
+ os_memcpy(data->IDi, idi, idi_len);
+ data->IDi_len = idi_len;
+ data->IDi_type = id_type;
+
+ return 0;
+}
+
+
+static int ikev2_process_cert(struct ikev2_responder_data *data,
+ const u8 *cert, size_t cert_len)
+{
+ u8 cert_encoding;
+
+ if (cert == NULL) {
+ if (data->peer_auth == PEER_AUTH_CERT) {
+ wpa_printf(MSG_INFO, "IKEV2: No Certificate received");
+ return -1;
+ }
+ return 0;
+ }
+
+ if (cert_len < 1) {
+ wpa_printf(MSG_INFO, "IKEV2: No Cert Encoding field");
+ return -1;
+ }
+
+ cert_encoding = cert[0];
+ cert++;
+ cert_len--;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Cert Encoding %d", cert_encoding);
+ wpa_hexdump(MSG_MSGDUMP, "IKEV2: Certificate Data", cert, cert_len);
+
+ /* TODO: validate certificate */
+
+ return 0;
+}
+
+
+static int ikev2_process_auth_cert(struct ikev2_responder_data *data,
+ u8 method, const u8 *auth, size_t auth_len)
+{
+ if (method != AUTH_RSA_SIGN) {
+ wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication "
+ "method %d", method);
+ return -1;
+ }
+
+ /* TODO: validate AUTH */
+ return 0;
+}
+
+
+static int ikev2_process_auth_secret(struct ikev2_responder_data *data,
+ u8 method, const u8 *auth,
+ size_t auth_len)
+{
+ u8 auth_data[IKEV2_MAX_HASH_LEN];
+ const struct ikev2_prf_alg *prf;
+
+ if (method != AUTH_SHARED_KEY_MIC) {
+ wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication "
+ "method %d", method);
+ return -1;
+ }
+
+ /* msg | Nr | prf(SK_pi,IDi') */
+ if (ikev2_derive_auth_data(data->proposal.prf, data->i_sign_msg,
+ data->IDi, data->IDi_len, data->IDi_type,
+ &data->keys, 1, data->shared_secret,
+ data->shared_secret_len,
+ data->r_nonce, data->r_nonce_len,
+ data->key_pad, data->key_pad_len,
+ auth_data) < 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data");
+ return -1;
+ }
+
+ wpabuf_free(data->i_sign_msg);
+ data->i_sign_msg = NULL;
+
+ prf = ikev2_get_prf(data->proposal.prf);
+ if (prf == NULL)
+ return -1;
+
+ if (auth_len != prf->hash_len ||
+ os_memcmp(auth, auth_data, auth_len) != 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Invalid Authentication Data");
+ wpa_hexdump(MSG_DEBUG, "IKEV2: Received Authentication Data",
+ auth, auth_len);
+ wpa_hexdump(MSG_DEBUG, "IKEV2: Expected Authentication Data",
+ auth_data, prf->hash_len);
+ data->error_type = AUTHENTICATION_FAILED;
+ data->state = NOTIFY;
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Server authenticated successfully "
+ "using shared keys");
+
+ return 0;
+}
+
+
+static int ikev2_process_auth(struct ikev2_responder_data *data,
+ const u8 *auth, size_t auth_len)
+{
+ u8 auth_method;
+
+ if (auth == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: No Authentication Payload");
+ return -1;
+ }
+
+ if (auth_len < 4) {
+ wpa_printf(MSG_INFO, "IKEV2: Too short Authentication "
+ "Payload");
+ return -1;
+ }
+
+ auth_method = auth[0];
+ auth += 4;
+ auth_len -= 4;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Auth Method %d", auth_method);
+ wpa_hexdump(MSG_MSGDUMP, "IKEV2: Authentication Data", auth, auth_len);
+
+ switch (data->peer_auth) {
+ case PEER_AUTH_CERT:
+ return ikev2_process_auth_cert(data, auth_method, auth,
+ auth_len);
+ case PEER_AUTH_SECRET:
+ return ikev2_process_auth_secret(data, auth_method, auth,
+ auth_len);
+ }
+
+ return -1;
+}
+
+
+static int ikev2_process_sa_auth_decrypted(struct ikev2_responder_data *data,
+ u8 next_payload,
+ u8 *payload, size_t payload_len)
+{
+ struct ikev2_payloads pl;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Processing decrypted payloads");
+
+ if (ikev2_parse_payloads(&pl, next_payload, payload, payload +
+ payload_len) < 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Failed to parse decrypted "
+ "payloads");
+ return -1;
+ }
+
+ if (ikev2_process_idi(data, pl.idi, pl.idi_len) < 0 ||
+ ikev2_process_cert(data, pl.cert, pl.cert_len) < 0 ||
+ ikev2_process_auth(data, pl.auth, pl.auth_len) < 0)
+ return -1;
+
+ return 0;
+}
+
+
+static int ikev2_process_sa_auth(struct ikev2_responder_data *data,
+ const struct ikev2_hdr *hdr,
+ struct ikev2_payloads *pl)
+{
+ u8 *decrypted;
+ size_t decrypted_len;
+ int ret;
+
+ decrypted = ikev2_decrypt_payload(data->proposal.encr,
+ data->proposal.integ,
+ &data->keys, 1, hdr, pl->encrypted,
+ pl->encrypted_len, &decrypted_len);
+ if (decrypted == NULL)
+ return -1;
+
+ ret = ikev2_process_sa_auth_decrypted(data, pl->encr_next_payload,
+ decrypted, decrypted_len);
+ os_free(decrypted);
+
+ return ret;
+}
+
+
+static int ikev2_validate_rx_state(struct ikev2_responder_data *data,
+ u8 exchange_type, u32 message_id)
+{
+ switch (data->state) {
+ case SA_INIT:
+ /* Expect to receive IKE_SA_INIT: HDR, SAi1, KEi, Ni */
+ if (exchange_type != IKE_SA_INIT) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type "
+ "%u in SA_INIT state", exchange_type);
+ return -1;
+ }
+ if (message_id != 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u "
+ "in SA_INIT state", message_id);
+ return -1;
+ }
+ break;
+ case SA_AUTH:
+ /* Expect to receive IKE_SA_AUTH:
+ * HDR, SK {IDi, [CERT,] [CERTREQ,] [IDr,]
+ * AUTH, SAi2, TSi, TSr}
+ */
+ if (exchange_type != IKE_SA_AUTH) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type "
+ "%u in SA_AUTH state", exchange_type);
+ return -1;
+ }
+ if (message_id != 1) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u "
+ "in SA_AUTH state", message_id);
+ return -1;
+ }
+ break;
+ case CHILD_SA:
+ if (exchange_type != CREATE_CHILD_SA) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type "
+ "%u in CHILD_SA state", exchange_type);
+ return -1;
+ }
+ if (message_id != 2) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u "
+ "in CHILD_SA state", message_id);
+ return -1;
+ }
+ break;
+ case NOTIFY:
+ case IKEV2_DONE:
+ case IKEV2_FAILED:
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int ikev2_responder_process(struct ikev2_responder_data *data,
+ const struct wpabuf *buf)
+{
+ const struct ikev2_hdr *hdr;
+ u32 length, message_id;
+ const u8 *pos, *end;
+ struct ikev2_payloads pl;
+
+ wpa_printf(MSG_MSGDUMP, "IKEV2: Received message (len %lu)",
+ (unsigned long) wpabuf_len(buf));
+
+ if (wpabuf_len(buf) < sizeof(*hdr)) {
+ wpa_printf(MSG_INFO, "IKEV2: Too short frame to include HDR");
+ return -1;
+ }
+
+ data->error_type = 0;
+ hdr = (const struct ikev2_hdr *) wpabuf_head(buf);
+ end = wpabuf_head_u8(buf) + wpabuf_len(buf);
+ message_id = WPA_GET_BE32(hdr->message_id);
+ length = WPA_GET_BE32(hdr->length);
+
+ wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Initiator's SPI",
+ hdr->i_spi, IKEV2_SPI_LEN);
+ wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Responder's SPI",
+ hdr->r_spi, IKEV2_SPI_LEN);
+ wpa_printf(MSG_DEBUG, "IKEV2: Next Payload: %u Version: 0x%x "
+ "Exchange Type: %u",
+ hdr->next_payload, hdr->version, hdr->exchange_type);
+ wpa_printf(MSG_DEBUG, "IKEV2: Message ID: %u Length: %u",
+ message_id, length);
+
+ if (hdr->version != IKEV2_VERSION) {
+ wpa_printf(MSG_INFO, "IKEV2: Unsupported HDR version 0x%x "
+ "(expected 0x%x)", hdr->version, IKEV2_VERSION);
+ return -1;
+ }
+
+ if (length != wpabuf_len(buf)) {
+ wpa_printf(MSG_INFO, "IKEV2: Invalid length (HDR: %lu != "
+ "RX: %lu)", (unsigned long) length,
+ (unsigned long) wpabuf_len(buf));
+ return -1;
+ }
+
+ if (ikev2_validate_rx_state(data, hdr->exchange_type, message_id) < 0)
+ return -1;
+
+ if ((hdr->flags & (IKEV2_HDR_INITIATOR | IKEV2_HDR_RESPONSE)) !=
+ IKEV2_HDR_INITIATOR) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Flags value 0x%x",
+ hdr->flags);
+ return -1;
+ }
+
+ if (data->state != SA_INIT) {
+ if (os_memcmp(data->i_spi, hdr->i_spi, IKEV2_SPI_LEN) != 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA "
+ "Initiator's SPI");
+ return -1;
+ }
+ if (os_memcmp(data->r_spi, hdr->r_spi, IKEV2_SPI_LEN) != 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA "
+ "Responder's SPI");
+ return -1;
+ }
+ }
+
+ pos = (const u8 *) (hdr + 1);
+ if (ikev2_parse_payloads(&pl, hdr->next_payload, pos, end) < 0)
+ return -1;
+
+ if (data->state == SA_INIT) {
+ data->last_msg = LAST_MSG_SA_INIT;
+ if (ikev2_process_sa_init(data, hdr, &pl) < 0) {
+ if (data->state == NOTIFY)
+ return 0;
+ return -1;
+ }
+ wpabuf_free(data->i_sign_msg);
+ data->i_sign_msg = wpabuf_dup(buf);
+ }
+
+ if (data->state == SA_AUTH) {
+ data->last_msg = LAST_MSG_SA_AUTH;
+ if (ikev2_process_sa_auth(data, hdr, &pl) < 0) {
+ if (data->state == NOTIFY)
+ return 0;
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+static void ikev2_build_hdr(struct ikev2_responder_data *data,
+ struct wpabuf *msg, u8 exchange_type,
+ u8 next_payload, u32 message_id)
+{
+ struct ikev2_hdr *hdr;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Adding HDR");
+
+ /* HDR - RFC 4306, Sect. 3.1 */
+ hdr = wpabuf_put(msg, sizeof(*hdr));
+ os_memcpy(hdr->i_spi, data->i_spi, IKEV2_SPI_LEN);
+ os_memcpy(hdr->r_spi, data->r_spi, IKEV2_SPI_LEN);
+ hdr->next_payload = next_payload;
+ hdr->version = IKEV2_VERSION;
+ hdr->exchange_type = exchange_type;
+ hdr->flags = IKEV2_HDR_RESPONSE;
+ WPA_PUT_BE32(hdr->message_id, message_id);
+}
+
+
+static int ikev2_build_sar1(struct ikev2_responder_data *data,
+ struct wpabuf *msg, u8 next_payload)
+{
+ struct ikev2_payload_hdr *phdr;
+ size_t plen;
+ struct ikev2_proposal *p;
+ struct ikev2_transform *t;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Adding SAr1 payload");
+
+ /* SAr1 - RFC 4306, Sect. 2.7 and 3.3 */
+ phdr = wpabuf_put(msg, sizeof(*phdr));
+ phdr->next_payload = next_payload;
+ phdr->flags = 0;
+
+ p = wpabuf_put(msg, sizeof(*p));
+#ifdef CCNS_PL
+ /* Seems to require that the Proposal # is 1 even though RFC 4306
+ * Sect 3.3.1 has following requirement "When a proposal is accepted,
+ * all of the proposal numbers in the SA payload MUST be the same and
+ * MUST match the number on the proposal sent that was accepted.".
+ */
+ p->proposal_num = 1;
+#else /* CCNS_PL */
+ p->proposal_num = data->proposal.proposal_num;
+#endif /* CCNS_PL */
+ p->protocol_id = IKEV2_PROTOCOL_IKE;
+ p->num_transforms = 4;
+
+ t = wpabuf_put(msg, sizeof(*t));
+ t->type = 3;
+ t->transform_type = IKEV2_TRANSFORM_ENCR;
+ WPA_PUT_BE16(t->transform_id, data->proposal.encr);
+ if (data->proposal.encr == ENCR_AES_CBC) {
+ /* Transform Attribute: Key Len = 128 bits */
+#ifdef CCNS_PL
+ wpabuf_put_be16(msg, 0x001d); /* ?? */
+#else /* CCNS_PL */
+ wpabuf_put_be16(msg, 0x800e); /* AF=1, AttrType=14 */
+#endif /* CCNS_PL */
+ wpabuf_put_be16(msg, 128); /* 128-bit key */
+ }
+ plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) t;
+ WPA_PUT_BE16(t->transform_length, plen);
+
+ t = wpabuf_put(msg, sizeof(*t));
+ t->type = 3;
+ WPA_PUT_BE16(t->transform_length, sizeof(*t));
+ t->transform_type = IKEV2_TRANSFORM_PRF;
+ WPA_PUT_BE16(t->transform_id, data->proposal.prf);
+
+ t = wpabuf_put(msg, sizeof(*t));
+ t->type = 3;
+ WPA_PUT_BE16(t->transform_length, sizeof(*t));
+ t->transform_type = IKEV2_TRANSFORM_INTEG;
+ WPA_PUT_BE16(t->transform_id, data->proposal.integ);
+
+ t = wpabuf_put(msg, sizeof(*t));
+ WPA_PUT_BE16(t->transform_length, sizeof(*t));
+ t->transform_type = IKEV2_TRANSFORM_DH;
+ WPA_PUT_BE16(t->transform_id, data->proposal.dh);
+
+ plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) p;
+ WPA_PUT_BE16(p->proposal_length, plen);
+
+ plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
+ WPA_PUT_BE16(phdr->payload_length, plen);
+
+ return 0;
+}
+
+
+static int ikev2_build_ker(struct ikev2_responder_data *data,
+ struct wpabuf *msg, u8 next_payload)
+{
+ struct ikev2_payload_hdr *phdr;
+ size_t plen;
+ struct wpabuf *pv;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Adding KEr payload");
+
+ pv = dh_init(data->dh, &data->r_dh_private);
+ if (pv == NULL) {
+ wpa_printf(MSG_DEBUG, "IKEV2: Failed to initialize DH");
+ return -1;
+ }
+
+ /* KEr - RFC 4306, Sect. 3.4 */
+ phdr = wpabuf_put(msg, sizeof(*phdr));
+ phdr->next_payload = next_payload;
+ phdr->flags = 0;
+
+ wpabuf_put_be16(msg, data->proposal.dh); /* DH Group # */
+ wpabuf_put(msg, 2); /* RESERVED */
+ /*
+ * RFC 4306, Sect. 3.4: possible zero padding for public value to
+ * match the length of the prime.
+ */
+ wpabuf_put(msg, data->dh->prime_len - wpabuf_len(pv));
+ wpabuf_put_buf(msg, pv);
+ wpabuf_free(pv);
+
+ plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
+ WPA_PUT_BE16(phdr->payload_length, plen);
+ return 0;
+}
+
+
+static int ikev2_build_nr(struct ikev2_responder_data *data,
+ struct wpabuf *msg, u8 next_payload)
+{
+ struct ikev2_payload_hdr *phdr;
+ size_t plen;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Adding Nr payload");
+
+ /* Nr - RFC 4306, Sect. 3.9 */
+ phdr = wpabuf_put(msg, sizeof(*phdr));
+ phdr->next_payload = next_payload;
+ phdr->flags = 0;
+ wpabuf_put_data(msg, data->r_nonce, data->r_nonce_len);
+ plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
+ WPA_PUT_BE16(phdr->payload_length, plen);
+ return 0;
+}
+
+
+static int ikev2_build_idr(struct ikev2_responder_data *data,
+ struct wpabuf *msg, u8 next_payload)
+{
+ struct ikev2_payload_hdr *phdr;
+ size_t plen;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Adding IDr payload");
+
+ if (data->IDr == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: No IDr available");
+ return -1;
+ }
+
+ /* IDr - RFC 4306, Sect. 3.5 */
+ phdr = wpabuf_put(msg, sizeof(*phdr));
+ phdr->next_payload = next_payload;
+ phdr->flags = 0;
+ wpabuf_put_u8(msg, ID_KEY_ID);
+ wpabuf_put(msg, 3); /* RESERVED */
+ wpabuf_put_data(msg, data->IDr, data->IDr_len);
+ plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
+ WPA_PUT_BE16(phdr->payload_length, plen);
+ return 0;
+}
+
+
+static int ikev2_build_auth(struct ikev2_responder_data *data,
+ struct wpabuf *msg, u8 next_payload)
+{
+ struct ikev2_payload_hdr *phdr;
+ size_t plen;
+ const struct ikev2_prf_alg *prf;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Adding AUTH payload");
+
+ prf = ikev2_get_prf(data->proposal.prf);
+ if (prf == NULL)
+ return -1;
+
+ /* Authentication - RFC 4306, Sect. 3.8 */
+ phdr = wpabuf_put(msg, sizeof(*phdr));
+ phdr->next_payload = next_payload;
+ phdr->flags = 0;
+ wpabuf_put_u8(msg, AUTH_SHARED_KEY_MIC);
+ wpabuf_put(msg, 3); /* RESERVED */
+
+ /* msg | Ni | prf(SK_pr,IDr') */
+ if (ikev2_derive_auth_data(data->proposal.prf, data->r_sign_msg,
+ data->IDr, data->IDr_len, ID_KEY_ID,
+ &data->keys, 0, data->shared_secret,
+ data->shared_secret_len,
+ data->i_nonce, data->i_nonce_len,
+ data->key_pad, data->key_pad_len,
+ wpabuf_put(msg, prf->hash_len)) < 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data");
+ return -1;
+ }
+ wpabuf_free(data->r_sign_msg);
+ data->r_sign_msg = NULL;
+
+ plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
+ WPA_PUT_BE16(phdr->payload_length, plen);
+ return 0;
+}
+
+
+static int ikev2_build_notification(struct ikev2_responder_data *data,
+ struct wpabuf *msg, u8 next_payload)
+{
+ struct ikev2_payload_hdr *phdr;
+ size_t plen;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Adding Notification payload");
+
+ if (data->error_type == 0) {
+ wpa_printf(MSG_INFO, "IKEV2: No Notify Message Type "
+ "available");
+ return -1;
+ }
+
+ /* Notify - RFC 4306, Sect. 3.10 */
+ phdr = wpabuf_put(msg, sizeof(*phdr));
+ phdr->next_payload = next_payload;
+ phdr->flags = 0;
+#ifdef CCNS_PL
+ wpabuf_put_u8(msg, 1); /* Protocol ID: IKE_SA notification */
+#else /* CCNS_PL */
+ wpabuf_put_u8(msg, 0); /* Protocol ID: no existing SA */
+#endif /* CCNS_PL */
+ wpabuf_put_u8(msg, 0); /* SPI Size */
+ wpabuf_put_be16(msg, data->error_type);
+
+ switch (data->error_type) {
+ case INVALID_KE_PAYLOAD:
+ if (data->proposal.dh == -1) {
+ wpa_printf(MSG_INFO, "IKEV2: No DH Group selected for "
+ "INVALID_KE_PAYLOAD notifications");
+ return -1;
+ }
+ wpabuf_put_be16(msg, data->proposal.dh);
+ wpa_printf(MSG_DEBUG, "IKEV2: INVALID_KE_PAYLOAD - request "
+ "DH Group #%d", data->proposal.dh);
+ break;
+ case AUTHENTICATION_FAILED:
+ /* no associated data */
+ break;
+ default:
+ wpa_printf(MSG_INFO, "IKEV2: Unsupported Notify Message Type "
+ "%d", data->error_type);
+ return -1;
+ }
+
+ plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
+ WPA_PUT_BE16(phdr->payload_length, plen);
+ return 0;
+}
+
+
+static struct wpabuf * ikev2_build_sa_init(struct ikev2_responder_data *data)
+{
+ struct wpabuf *msg;
+
+ /* build IKE_SA_INIT: HDR, SAr1, KEr, Nr, [CERTREQ], [SK{IDr}] */
+
+ if (os_get_random(data->r_spi, IKEV2_SPI_LEN))
+ return NULL;
+ wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Responder's SPI",
+ data->r_spi, IKEV2_SPI_LEN);
+
+ data->r_nonce_len = IKEV2_NONCE_MIN_LEN;
+ if (os_get_random(data->r_nonce, data->r_nonce_len))
+ return NULL;
+#ifdef CCNS_PL
+ /* Zeros are removed incorrectly from the beginning of the nonces in
+ * key derivation; as a workaround, make sure Nr does not start with
+ * zero.. */
+ if (data->r_nonce[0] == 0)
+ data->r_nonce[0] = 1;
+#endif /* CCNS_PL */
+ wpa_hexdump(MSG_DEBUG, "IKEV2: Nr", data->r_nonce, data->r_nonce_len);
+
+ msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1500);
+ if (msg == NULL)
+ return NULL;
+
+ ikev2_build_hdr(data, msg, IKE_SA_INIT, IKEV2_PAYLOAD_SA, 0);
+ if (ikev2_build_sar1(data, msg, IKEV2_PAYLOAD_KEY_EXCHANGE) ||
+ ikev2_build_ker(data, msg, IKEV2_PAYLOAD_NONCE) ||
+ ikev2_build_nr(data, msg, data->peer_auth == PEER_AUTH_SECRET ?
+ IKEV2_PAYLOAD_ENCRYPTED :
+ IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) {
+ wpabuf_free(msg);
+ return NULL;
+ }
+
+ if (ikev2_derive_keys(data)) {
+ wpabuf_free(msg);
+ return NULL;
+ }
+
+ if (data->peer_auth == PEER_AUTH_CERT) {
+ /* TODO: CERTREQ with SHA-1 hashes of Subject Public Key Info
+ * for trust agents */
+ }
+
+ if (data->peer_auth == PEER_AUTH_SECRET) {
+ struct wpabuf *plain = wpabuf_alloc(data->IDr_len + 1000);
+ if (plain == NULL) {
+ wpabuf_free(msg);
+ return NULL;
+ }
+ if (ikev2_build_idr(data, plain,
+ IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) ||
+ ikev2_build_encrypted(data->proposal.encr,
+ data->proposal.integ,
+ &data->keys, 0, msg, plain,
+ IKEV2_PAYLOAD_IDr)) {
+ wpabuf_free(plain);
+ wpabuf_free(msg);
+ return NULL;
+ }
+ wpabuf_free(plain);
+ }
+
+ ikev2_update_hdr(msg);
+
+ wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_INIT)", msg);
+
+ data->state = SA_AUTH;
+
+ wpabuf_free(data->r_sign_msg);
+ data->r_sign_msg = wpabuf_dup(msg);
+
+ return msg;
+}
+
+
+static struct wpabuf * ikev2_build_sa_auth(struct ikev2_responder_data *data)
+{
+ struct wpabuf *msg, *plain;
+
+ /* build IKE_SA_AUTH: HDR, SK {IDr, [CERT,] AUTH} */
+
+ msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1000);
+ if (msg == NULL)
+ return NULL;
+ ikev2_build_hdr(data, msg, IKE_SA_AUTH, IKEV2_PAYLOAD_ENCRYPTED, 1);
+
+ plain = wpabuf_alloc(data->IDr_len + 1000);
+ if (plain == NULL) {
+ wpabuf_free(msg);
+ return NULL;
+ }
+
+ if (ikev2_build_idr(data, plain, IKEV2_PAYLOAD_AUTHENTICATION) ||
+ ikev2_build_auth(data, plain, IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) ||
+ ikev2_build_encrypted(data->proposal.encr, data->proposal.integ,
+ &data->keys, 0, msg, plain,
+ IKEV2_PAYLOAD_IDr)) {
+ wpabuf_free(plain);
+ wpabuf_free(msg);
+ return NULL;
+ }
+ wpabuf_free(plain);
+
+ wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_AUTH)", msg);
+
+ data->state = IKEV2_DONE;
+
+ return msg;
+}
+
+
+static struct wpabuf * ikev2_build_notify(struct ikev2_responder_data *data)
+{
+ struct wpabuf *msg;
+
+ msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + 1000);
+ if (msg == NULL)
+ return NULL;
+ if (data->last_msg == LAST_MSG_SA_AUTH) {
+ /* HDR, SK{N} */
+ struct wpabuf *plain = wpabuf_alloc(100);
+ if (plain == NULL) {
+ wpabuf_free(msg);
+ return NULL;
+ }
+ ikev2_build_hdr(data, msg, IKE_SA_AUTH,
+ IKEV2_PAYLOAD_ENCRYPTED, 1);
+ if (ikev2_build_notification(data, plain,
+ IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) ||
+ ikev2_build_encrypted(data->proposal.encr,
+ data->proposal.integ,
+ &data->keys, 0, msg, plain,
+ IKEV2_PAYLOAD_NOTIFICATION)) {
+ wpabuf_free(plain);
+ wpabuf_free(msg);
+ return NULL;
+ }
+ data->state = IKEV2_FAILED;
+ } else {
+ /* HDR, N */
+ ikev2_build_hdr(data, msg, IKE_SA_INIT,
+ IKEV2_PAYLOAD_NOTIFICATION, 0);
+ if (ikev2_build_notification(data, msg,
+ IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) {
+ wpabuf_free(msg);
+ return NULL;
+ }
+ data->state = SA_INIT;
+ }
+
+ ikev2_update_hdr(msg);
+
+ wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (Notification)",
+ msg);
+
+ return msg;
+}
+
+
+struct wpabuf * ikev2_responder_build(struct ikev2_responder_data *data)
+{
+ switch (data->state) {
+ case SA_INIT:
+ return ikev2_build_sa_init(data);
+ case SA_AUTH:
+ return ikev2_build_sa_auth(data);
+ case CHILD_SA:
+ return NULL;
+ case NOTIFY:
+ return ikev2_build_notify(data);
+ case IKEV2_DONE:
+ case IKEV2_FAILED:
+ return NULL;
+ }
+ return NULL;
+}
Added: wpasupplicant/branches/upstream/current/src/eap_peer/ikev2.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_peer/ikev2.h?rev=967&op=file
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_peer/ikev2.h (added)
+++ wpasupplicant/branches/upstream/current/src/eap_peer/ikev2.h Tue Jan 1 13:50:28 2008
@@ -1,0 +1,65 @@
+/*
+ * IKEv2 responder (RFC 4306) for EAP-IKEV2
+ * Copyright (c) 2007, Jouni Malinen <j at 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 IKEV2_H
+#define IKEV2_H
+
+#include "eap_common/ikev2_common.h"
+
+struct ikev2_proposal_data {
+ u8 proposal_num;
+ int integ;
+ int prf;
+ int encr;
+ int dh;
+};
+
+
+struct ikev2_responder_data {
+ enum { SA_INIT, SA_AUTH, CHILD_SA, NOTIFY, IKEV2_DONE, IKEV2_FAILED }
+ state;
+ u8 i_spi[IKEV2_SPI_LEN];
+ u8 r_spi[IKEV2_SPI_LEN];
+ u8 i_nonce[IKEV2_NONCE_MAX_LEN];
+ size_t i_nonce_len;
+ u8 r_nonce[IKEV2_NONCE_MAX_LEN];
+ size_t r_nonce_len;
+ struct wpabuf *i_dh_public;
+ struct wpabuf *r_dh_private;
+ struct ikev2_proposal_data proposal;
+ const struct dh_group *dh;
+ struct ikev2_keys keys;
+ u8 *IDi;
+ size_t IDi_len;
+ u8 IDi_type;
+ u8 *IDr;
+ size_t IDr_len;
+ struct wpabuf *r_sign_msg;
+ struct wpabuf *i_sign_msg;
+ u8 *shared_secret;
+ size_t shared_secret_len;
+ enum { PEER_AUTH_CERT, PEER_AUTH_SECRET } peer_auth;
+ u8 *key_pad;
+ size_t key_pad_len;
+ u16 error_type;
+ enum { LAST_MSG_SA_INIT, LAST_MSG_SA_AUTH } last_msg;
+};
+
+
+void ikev2_responder_deinit(struct ikev2_responder_data *data);
+int ikev2_responder_process(struct ikev2_responder_data *data,
+ const struct wpabuf *buf);
+struct wpabuf * ikev2_responder_build(struct ikev2_responder_data *data);
+
+#endif /* IKEV2_H */
Added: wpasupplicant/branches/upstream/current/src/eap_server/eap_ikev2.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_server/eap_ikev2.c?rev=967&op=file
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_server/eap_ikev2.c (added)
+++ wpasupplicant/branches/upstream/current/src/eap_server/eap_ikev2.c Tue Jan 1 13:50:28 2008
@@ -1,0 +1,535 @@
+/*
+ * EAP-IKEv2 server (draft-tschofenig-eap-ikev2-15.txt)
+ * Copyright (c) 2007, Jouni Malinen <j at w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "eap_i.h"
+#include "eap_common/eap_ikev2_common.h"
+#include "ikev2.h"
+
+
+struct eap_ikev2_data {
+ struct ikev2_initiator_data ikev2;
+ enum { MSG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state;
+ struct wpabuf *in_buf;
+ struct wpabuf *out_buf;
+ size_t out_used;
+ size_t fragment_size;
+ int keys_ready;
+ u8 keymat[EAP_MSK_LEN + EAP_EMSK_LEN];
+ int keymat_ok;
+};
+
+
+static const u8 * eap_ikev2_get_shared_secret(void *ctx, const u8 *IDr,
+ size_t IDr_len,
+ size_t *secret_len)
+{
+ struct eap_sm *sm = ctx;
+
+ if (IDr == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: No IDr received - default "
+ "to user identity from EAP-Identity");
+ IDr = sm->identity;
+ IDr_len = sm->identity_len;
+ }
+
+ if (eap_user_get(sm, IDr, IDr_len, 0) < 0 || sm->user == NULL ||
+ sm->user->password == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: No user entry found");
+ return NULL;
+ }
+
+ *secret_len = sm->user->password_len;
+ return sm->user->password;
+}
+
+
+static const char * eap_ikev2_state_txt(int state)
+{
+ switch (state) {
+ case MSG:
+ return "MSG";
+ case FRAG_ACK:
+ return "FRAG_ACK";
+ case WAIT_FRAG_ACK:
+ return "WAIT_FRAG_ACK";
+ case DONE:
+ return "DONE";
+ case FAIL:
+ return "FAIL";
+ default:
+ return "?";
+ }
+}
+
+
+static void eap_ikev2_state(struct eap_ikev2_data *data, int state)
+{
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: %s -> %s",
+ eap_ikev2_state_txt(data->state),
+ eap_ikev2_state_txt(state));
+ data->state = state;
+}
+
+
+static void * eap_ikev2_init(struct eap_sm *sm)
+{
+ struct eap_ikev2_data *data;
+
+ data = os_zalloc(sizeof(*data));
+ if (data == NULL)
+ return NULL;
+ data->state = MSG;
+ data->fragment_size = IKEV2_FRAGMENT_SIZE;
+ data->ikev2.state = SA_INIT;
+ data->ikev2.peer_auth = PEER_AUTH_SECRET;
+ data->ikev2.key_pad = (u8 *) os_strdup("Key Pad for EAP-IKEv2");
+ if (data->ikev2.key_pad == NULL)
+ goto failed;
+ data->ikev2.key_pad_len = 21;
+
+ /* TODO: make proposals configurable */
+ data->ikev2.proposal.proposal_num = 1;
+ data->ikev2.proposal.integ = AUTH_HMAC_SHA1_96;
+ data->ikev2.proposal.prf = PRF_HMAC_SHA1;
+ data->ikev2.proposal.encr = ENCR_AES_CBC;
+ data->ikev2.proposal.dh = DH_GROUP2_1024BIT_MODP;
+
+ data->ikev2.IDi = (u8 *) os_strdup("hostapd");
+ data->ikev2.IDi_len = 7;
+
+ data->ikev2.get_shared_secret = eap_ikev2_get_shared_secret;
+ data->ikev2.cb_ctx = sm;
+
+ return data;
+
+failed:
+ ikev2_initiator_deinit(&data->ikev2);
+ os_free(data);
+ return NULL;
+}
+
+
+static void eap_ikev2_reset(struct eap_sm *sm, void *priv)
+{
+ struct eap_ikev2_data *data = priv;
+ wpabuf_free(data->in_buf);
+ wpabuf_free(data->out_buf);
+ ikev2_initiator_deinit(&data->ikev2);
+ os_free(data);
+}
+
+
+static struct wpabuf * eap_ikev2_build_msg(struct eap_ikev2_data *data, u8 id)
+{
+ struct wpabuf *req;
+ u8 flags;
+ size_t send_len, plen, icv_len = 0;
+
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Generating Request");
+
+ flags = 0;
+ send_len = wpabuf_len(data->out_buf) - data->out_used;
+ if (1 + send_len > data->fragment_size) {
+ send_len = data->fragment_size - 1;
+ flags |= IKEV2_FLAGS_MORE_FRAGMENTS;
+ if (data->out_used == 0) {
+ flags |= IKEV2_FLAGS_LENGTH_INCLUDED;
+ send_len -= 4;
+ }
+ }
+
+ plen = 1 + send_len;
+ if (flags & IKEV2_FLAGS_LENGTH_INCLUDED)
+ plen += 4;
+ if (data->keys_ready) {
+ const struct ikev2_integ_alg *integ;
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Add Integrity Checksum "
+ "Data");
+ flags |= IKEV2_FLAGS_ICV_INCLUDED;
+ integ = ikev2_get_integ(data->ikev2.proposal.integ);
+ if (integ == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG "
+ "transform / cannot generate ICV");
+ return NULL;
+ }
+ icv_len = integ->hash_len;
+
+ plen += icv_len;
+ }
+ req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, plen,
+ EAP_CODE_REQUEST, id);
+ if (req == NULL)
+ return NULL;
+
+ wpabuf_put_u8(req, flags); /* Flags */
+ if (flags & IKEV2_FLAGS_LENGTH_INCLUDED)
+ wpabuf_put_be32(req, wpabuf_len(data->out_buf));
+
+ wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used,
+ send_len);
+ data->out_used += send_len;
+
+ if (flags & IKEV2_FLAGS_ICV_INCLUDED) {
+ const u8 *msg = wpabuf_head(req);
+ size_t len = wpabuf_len(req);
+ ikev2_integ_hash(data->ikev2.proposal.integ,
+ data->ikev2.keys.SK_ai,
+ data->ikev2.keys.SK_integ_len,
+ msg, len, wpabuf_put(req, icv_len));
+ }
+
+ if (data->out_used == wpabuf_len(data->out_buf)) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes "
+ "(message sent completely)",
+ (unsigned long) send_len);
+ wpabuf_free(data->out_buf);
+ data->out_buf = NULL;
+ data->out_used = 0;
+ } else {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes "
+ "(%lu more to send)", (unsigned long) send_len,
+ (unsigned long) wpabuf_len(data->out_buf) -
+ data->out_used);
+ eap_ikev2_state(data, WAIT_FRAG_ACK);
+ }
+
+ return req;
+}
+
+
+static struct wpabuf * eap_ikev2_buildReq(struct eap_sm *sm, void *priv, u8 id)
+{
+ struct eap_ikev2_data *data = priv;
+
+ switch (data->state) {
+ case MSG:
+ if (data->out_buf == NULL) {
+ data->out_buf = ikev2_initiator_build(&data->ikev2);
+ if (data->out_buf == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to "
+ "generate IKEv2 message");
+ return NULL;
+ }
+ data->out_used = 0;
+ }
+ /* pass through */
+ case WAIT_FRAG_ACK:
+ return eap_ikev2_build_msg(data, id);
+ case FRAG_ACK:
+ return eap_ikev2_build_frag_ack(id, EAP_CODE_REQUEST);
+ default:
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected state %d in "
+ "buildReq", data->state);
+ return NULL;
+ }
+}
+
+
+static Boolean eap_ikev2_check(struct eap_sm *sm, void *priv,
+ struct wpabuf *respData)
+{
+ const u8 *pos;
+ size_t len;
+
+ pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, respData,
+ &len);
+ if (pos == NULL) {
+ wpa_printf(MSG_INFO, "EAP-IKEV2: Invalid frame");
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+static int eap_ikev2_process_icv(struct eap_ikev2_data *data,
+ const struct wpabuf *respData,
+ u8 flags, const u8 *pos, const u8 **end)
+{
+ if (flags & IKEV2_FLAGS_ICV_INCLUDED) {
+ int icv_len = eap_ikev2_validate_icv(
+ data->ikev2.proposal.integ, &data->ikev2.keys, 0,
+ respData, pos, *end);
+ if (icv_len < 0)
+ return -1;
+ /* Hide Integrity Checksum Data from further processing */
+ *end -= icv_len;
+ } else if (data->keys_ready) {
+ wpa_printf(MSG_INFO, "EAP-IKEV2: The message should have "
+ "included integrity checksum");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int eap_ikev2_process_cont(struct eap_ikev2_data *data,
+ const u8 *buf, size_t len)
+{
+ /* Process continuation of a pending message */
+ if (len > wpabuf_tailroom(data->in_buf)) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment overflow");
+ eap_ikev2_state(data, FAIL);
+ return -1;
+ }
+
+ wpabuf_put_data(data->in_buf, buf, len);
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received %lu bytes, waiting for %lu "
+ "bytes more", (unsigned long) len,
+ (unsigned long) wpabuf_tailroom(data->in_buf));
+
+ return 0;
+}
+
+
+static int eap_ikev2_process_fragment(struct eap_ikev2_data *data,
+ u8 flags, u32 message_length,
+ const u8 *buf, size_t len)
+{
+ /* Process a fragment that is not the last one of the message */
+ if (data->in_buf == NULL && !(flags & IKEV2_FLAGS_LENGTH_INCLUDED)) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: No Message Length field in "
+ "a fragmented packet");
+ return -1;
+ }
+
+ if (data->in_buf == NULL) {
+ /* First fragment of the message */
+ data->in_buf = wpabuf_alloc(message_length);
+ if (data->in_buf == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: No memory for "
+ "message");
+ return -1;
+ }
+ wpabuf_put_data(data->in_buf, buf, len);
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received %lu bytes in first "
+ "fragment, waiting for %lu bytes more",
+ (unsigned long) len,
+ (unsigned long) wpabuf_tailroom(data->in_buf));
+ }
+
+ return 0;
+}
+
+
+static int eap_ikev2_server_keymat(struct eap_ikev2_data *data)
+{
+ if (eap_ikev2_derive_keymat(
+ data->ikev2.proposal.prf, &data->ikev2.keys,
+ data->ikev2.i_nonce, data->ikev2.i_nonce_len,
+ data->ikev2.r_nonce, data->ikev2.r_nonce_len,
+ data->keymat) < 0) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to derive "
+ "key material");
+ return -1;
+ }
+ data->keymat_ok = 1;
+ return 0;
+}
+
+
+static void eap_ikev2_process(struct eap_sm *sm, void *priv,
+ struct wpabuf *respData)
+{
+ struct eap_ikev2_data *data = priv;
+ const u8 *start, *pos, *end;
+ size_t len;
+ u8 flags;
+ u32 message_length = 0;
+ struct wpabuf tmpbuf;
+
+ pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, respData,
+ &len);
+ if (pos == NULL)
+ return; /* Should not happen; message already verified */
+
+ start = pos;
+ end = start + len;
+
+ if (len == 0) {
+ /* fragment ack */
+ flags = 0;
+ } else
+ flags = *pos++;
+
+ if (eap_ikev2_process_icv(data, respData, flags, pos, &end) < 0) {
+ eap_ikev2_state(data, FAIL);
+ return;
+ }
+
+ if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) {
+ if (end - pos < 4) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Message underflow");
+ eap_ikev2_state(data, FAIL);
+ return;
+ }
+ message_length = WPA_GET_BE32(pos);
+ pos += 4;
+
+ if (message_length < (u32) (end - pos)) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Invalid Message "
+ "Length (%d; %d remaining in this msg)",
+ message_length, end - pos);
+ eap_ikev2_state(data, FAIL);
+ return;
+ }
+ }
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received packet: Flags 0x%x "
+ "Message Length %u", flags, message_length);
+
+ if (data->state == WAIT_FRAG_ACK) {
+ if (len != 0) {
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected payload "
+ "in WAIT_FRAG_ACK state");
+ eap_ikev2_state(data, FAIL);
+ return;
+ }
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment acknowledged");
+ eap_ikev2_state(data, MSG);
+ return;
+ }
+
+ if (data->in_buf && eap_ikev2_process_cont(data, pos, end - pos) < 0) {
+ eap_ikev2_state(data, FAIL);
+ return;
+ }
+
+ if (flags & IKEV2_FLAGS_MORE_FRAGMENTS) {
+ if (eap_ikev2_process_fragment(data, flags, message_length,
+ pos, end - pos) < 0)
+ eap_ikev2_state(data, FAIL);
+ else
+ eap_ikev2_state(data, FRAG_ACK);
+ return;
+ }
+
+ if (data->in_buf == NULL) {
+ /* Wrap unfragmented messages as wpabuf without extra copy */
+ wpabuf_set(&tmpbuf, pos, end - pos);
+ data->in_buf = &tmpbuf;
+ }
+
+ if (ikev2_initiator_process(&data->ikev2, data->in_buf) < 0) {
+ if (data->in_buf == &tmpbuf)
+ data->in_buf = NULL;
+ eap_ikev2_state(data, FAIL);
+ return;
+ }
+
+ switch (data->ikev2.state) {
+ case SA_AUTH:
+ /* SA_INIT was sent out, so message have to be
+ * integrity protected from now on. */
+ data->keys_ready = 1;
+ break;
+ case IKEV2_DONE:
+ if (data->state == FAIL)
+ break;
+ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Authentication completed "
+ "successfully");
+ if (eap_ikev2_server_keymat(data))
+ break;
+ eap_ikev2_state(data, DONE);
+ break;
+ default:
+ break;
+ }
+
+ if (data->in_buf != &tmpbuf)
+ wpabuf_free(data->in_buf);
+ data->in_buf = NULL;
+}
+
+
+static Boolean eap_ikev2_isDone(struct eap_sm *sm, void *priv)
+{
+ struct eap_ikev2_data *data = priv;
+ return data->state == DONE || data->state == FAIL;
+}
+
+
+static Boolean eap_ikev2_isSuccess(struct eap_sm *sm, void *priv)
+{
+ struct eap_ikev2_data *data = priv;
+ return data->state == DONE && data->ikev2.state == IKEV2_DONE &&
+ data->keymat_ok;
+}
+
+
+static u8 * eap_ikev2_getKey(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_ikev2_data *data = priv;
+ u8 *key;
+
+ if (data->state != DONE || !data->keymat_ok)
+ return NULL;
+
+ key = os_malloc(EAP_MSK_LEN);
+ if (key) {
+ os_memcpy(key, data->keymat, EAP_MSK_LEN);
+ *len = EAP_MSK_LEN;
+ }
+
+ return key;
+}
+
+
+static u8 * eap_ikev2_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_ikev2_data *data = priv;
+ u8 *key;
+
+ if (data->state != DONE || !data->keymat_ok)
+ return NULL;
+
+ key = os_malloc(EAP_EMSK_LEN);
+ if (key) {
+ os_memcpy(key, data->keymat + EAP_MSK_LEN, EAP_EMSK_LEN);
+ *len = EAP_EMSK_LEN;
+ }
+
+ return key;
+}
+
+
+int eap_server_ikev2_register(void)
+{
+ struct eap_method *eap;
+ int ret;
+
+ eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
+ EAP_VENDOR_IETF, EAP_TYPE_IKEV2,
+ "IKEV2");
+ if (eap == NULL)
+ return -1;
+
+ eap->init = eap_ikev2_init;
+ eap->reset = eap_ikev2_reset;
+ eap->buildReq = eap_ikev2_buildReq;
+ eap->check = eap_ikev2_check;
+ eap->process = eap_ikev2_process;
+ eap->isDone = eap_ikev2_isDone;
+ eap->getKey = eap_ikev2_getKey;
+ eap->isSuccess = eap_ikev2_isSuccess;
+ eap->get_emsk = eap_ikev2_get_emsk;
+
+ ret = eap_server_method_register(eap);
+ if (ret)
+ eap_server_method_free(eap);
+ return ret;
+}
Modified: wpasupplicant/branches/upstream/current/src/eap_server/eap_methods.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_server/eap_methods.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_server/eap_methods.c (original)
+++ wpasupplicant/branches/upstream/current/src/eap_server/eap_methods.c Tue Jan 1 13:50:28 2008
@@ -261,6 +261,13 @@
}
#endif /* EAP_WSC */
+#ifdef EAP_IKEV2
+ if (ret == 0) {
+ int eap_server_ikev2_register(void);
+ ret = eap_server_ikev2_register();
+ }
+#endif /* EAP_IKEV2 */
+
return ret;
}
Modified: wpasupplicant/branches/upstream/current/src/eap_server/eap_mschapv2.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_server/eap_mschapv2.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_server/eap_mschapv2.c (original)
+++ wpasupplicant/branches/upstream/current/src/eap_server/eap_mschapv2.c Tue Jan 1 13:50:28 2008
@@ -397,23 +397,16 @@
* not be saved. */
if (sm->user->password_hash) {
pw_hash = sm->user->password;
- generate_authenticator_response_pwhash(
- sm->user->password, peer_challenge,
- data->auth_challenge, username, username_len,
- nt_response, data->auth_response);
} else {
nt_password_hash(sm->user->password,
sm->user->password_len,
pw_hash_buf);
pw_hash = pw_hash_buf;
- generate_authenticator_response(sm->user->password,
- sm->user->password_len,
- peer_challenge,
- data->auth_challenge,
- username, username_len,
- nt_response,
- data->auth_response);
}
+ generate_authenticator_response_pwhash(
+ pw_hash, peer_challenge, data->auth_challenge,
+ username, username_len, nt_response,
+ data->auth_response);
hash_nt_password_hash(pw_hash, pw_hash_hash);
get_master_key(pw_hash_hash, nt_response, data->master_key);
Modified: wpasupplicant/branches/upstream/current/src/eap_server/eap_peap.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_server/eap_peap.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_server/eap_peap.c (original)
+++ wpasupplicant/branches/upstream/current/src/eap_server/eap_peap.c Tue Jan 1 13:50:28 2008
@@ -532,23 +532,26 @@
}
hdr = wpabuf_head(in_decrypted);
if (wpabuf_len(in_decrypted) < (int) sizeof(*hdr)) {
+ wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
+ "EAP frame (len=%lu)",
+ (unsigned long) wpabuf_len(in_decrypted));
wpabuf_free(in_decrypted);
- wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
- "EAP frame (len=%d)", wpabuf_len(in_decrypted));
eap_peap_req_failure(sm, data);
return;
}
len = be_to_host16(hdr->length);
if (len > wpabuf_len(in_decrypted)) {
+ wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
+ "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
+ (unsigned long) wpabuf_len(in_decrypted),
+ (unsigned long) len);
wpabuf_free(in_decrypted);
- wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
- "Phase 2 EAP frame (len=%d hdr->length=%d)",
- wpabuf_len(in_decrypted), len);
eap_peap_req_failure(sm, data);
return;
}
wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "
- "identifier=%d length=%d", hdr->code, hdr->identifier, len);
+ "identifier=%d length=%lu", hdr->code, hdr->identifier,
+ (unsigned long) len);
switch (hdr->code) {
case EAP_CODE_RESPONSE:
eap_peap_process_phase2_response(sm, data, in_decrypted);
Modified: wpasupplicant/branches/upstream/current/src/eap_server/eap_psk.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_server/eap_psk.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_server/eap_psk.c (original)
+++ wpasupplicant/branches/upstream/current/src/eap_server/eap_psk.c Tue Jan 1 13:50:28 2008
@@ -119,18 +119,18 @@
/* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */
buflen = data->id_s_len + EAP_PSK_RAND_LEN;
buf = os_malloc(buflen);
- if (buf == NULL) {
- wpabuf_free(req);
- data->state = FAILURE;
- return NULL;
- }
+ if (buf == NULL)
+ goto fail;
+
os_memcpy(buf, data->id_s, data->id_s_len);
os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN);
- omac1_aes_128(data->ak, buf, buflen, psk->mac_s);
+ if (omac1_aes_128(data->ak, buf, buflen, psk->mac_s))
+ goto fail;
os_free(buf);
- eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, data->msk,
- data->emsk);
+ if (eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, data->msk,
+ data->emsk))
+ goto fail;
wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN);
wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN);
wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN);
@@ -142,13 +142,19 @@
pchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS << 6;
wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL (plaintext)",
pchannel, 4 + 16 + 1);
- aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce),
- wpabuf_head(req), 22,
- pchannel + 4 + 16, 1, pchannel + 4);
+ if (aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce),
+ wpabuf_head(req), 22,
+ pchannel + 4 + 16, 1, pchannel + 4))
+ goto fail;
wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL (encrypted)",
pchannel, 4 + 16 + 1);
return req;
+
+fail:
+ wpabuf_free(req);
+ data->state = FAILURE;
+ return NULL;
}
@@ -281,7 +287,10 @@
data->state = FAILURE;
return;
}
- eap_psk_key_setup(sm->user->password, data->ak, data->kdk);
+ if (eap_psk_key_setup(sm->user->password, data->ak, data->kdk)) {
+ data->state = FAILURE;
+ return;
+ }
wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN);
wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN);
@@ -303,7 +312,11 @@
os_memcpy(pos, data->rand_s, EAP_PSK_RAND_LEN);
pos += EAP_PSK_RAND_LEN;
os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN);
- omac1_aes_128(data->ak, buf, buflen, mac);
+ if (omac1_aes_128(data->ak, buf, buflen, mac)) {
+ os_free(buf);
+ data->state = FAILURE;
+ return;
+ }
os_free(buf);
wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", resp->mac_p, EAP_PSK_MAC_LEN);
if (os_memcmp(mac, resp->mac_p, EAP_PSK_MAC_LEN) != 0) {
Modified: wpasupplicant/branches/upstream/current/src/eap_server/eap_ttls.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_server/eap_ttls.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_server/eap_ttls.c (original)
+++ wpasupplicant/branches/upstream/current/src/eap_server/eap_ttls.c Tue Jan 1 13:50:28 2008
@@ -1341,8 +1341,9 @@
eap_ttls_state(data, FAILURE);
} else {
wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Unexpected "
- "frame from peer (payload len %d, expected "
- "empty frame)", left);
+ "frame from peer (payload len %lu, "
+ "expected empty frame)",
+ (unsigned long) left);
eap_ttls_state(data, FAILURE);
}
break;
Modified: wpasupplicant/branches/upstream/current/src/eap_server/eap_wsc.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_server/eap_wsc.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_server/eap_wsc.c (original)
+++ wpasupplicant/branches/upstream/current/src/eap_server/eap_wsc.c Tue Jan 1 13:50:28 2008
@@ -17,137 +17,16 @@
#include "common.h"
#include "eap_i.h"
#include "eap_common/eap_wsc_common.h"
-
-
-struct wps_data {
- int registrar;
- int msg_num;
-};
-
-
-static struct wps_data * wps_init(int registrar)
-{
- struct wps_data *data = os_zalloc(sizeof(*data));
- if (data == NULL)
- return NULL;
- data->registrar = registrar;
- data->msg_num = 1;
- return data;
-}
-
-
-static void wps_deinit(struct wps_data *data)
-{
- os_free(data);
-}
-
-
-enum wps_process_res {
- WPS_DONE, WPS_CONTINUE, WPS_FAILURE, WPS_PENDING
-};
-
-static enum wps_process_res wps_process_msg(struct wps_data *wps, u8 op_code,
- const u8 *msg, size_t msg_len)
-{
- /* TODO: proper processing and/or sending to an external process */
-
- wpa_hexdump(MSG_MSGDUMP, "WPS: Received message", msg, msg_len);
- if ((wps->registrar && (wps->msg_num & 1) == 0) ||
- (!wps->registrar && (wps->msg_num & 1) == 1)) {
- wpa_printf(MSG_DEBUG, "WPS: Unexpected message number %d",
- wps->msg_num);
- return WPS_FAILURE;
- }
-
- if (wps->msg_num <= 8 && op_code == WSC_MSG) {
- wpa_printf(MSG_DEBUG, "WPS: Process M%d", wps->msg_num);
- } else if (wps->registrar && wps->msg_num == 3 &&
- op_code == WSC_ACK) {
- wpa_printf(MSG_DEBUG, "WPS: Process ACK to M2/M2D");
- /* could send out next M2/M2D */
- return WPS_DONE;
- } else if (wps->registrar && wps->msg_num == 3 &&
- op_code == WSC_Done) {
- wpa_printf(MSG_DEBUG, "WPS: Process Done to M2/M2D");
- return WPS_DONE;
- } else if (wps->msg_num <= 8 && op_code == WSC_Done) {
- wpa_printf(MSG_DEBUG, "WPS: Process Done prior to completion");
- return WPS_DONE;
- } else if (wps->msg_num <= 8 && op_code == WSC_ACK) {
- wpa_printf(MSG_DEBUG, "WPS: Process ACK prior to completion");
- return WPS_DONE;
- } else if (wps->msg_num <= 8 && op_code == WSC_NACK) {
- wpa_printf(MSG_DEBUG, "WPS: Process NACK prior to completion");
- return WPS_DONE;
- } else if (wps->registrar && wps->msg_num == 9 &&
- op_code == WSC_Done) {
- wpa_printf(MSG_DEBUG, "WPS: Process Done");
- return WPS_DONE;
- } else if (!wps->registrar && wps->msg_num == 10 &&
- op_code == WSC_ACK) {
- wpa_printf(MSG_DEBUG, "WPS: Process ACK");
- return WPS_DONE;
- } else {
- wpa_printf(MSG_DEBUG, "WPS: Unexpected Op-Code %d "
- "(msg_num=%d)", op_code, wps->msg_num);
- return WPS_FAILURE;
- }
-
- wps->msg_num++;
- return WPS_CONTINUE;
-}
-
-
-static u8 * wps_get_msg(struct wps_data *wps, size_t *msg_len, u8 *op_code)
-{
- u8 *msg;
-
- /* TODO: proper processing and/or query from an external process */
-
- if ((wps->registrar && (wps->msg_num & 1) == 1) ||
- (!wps->registrar && (wps->msg_num & 1) == 0)) {
- wpa_printf(MSG_DEBUG, "WPS: Unexpected request for message "
- "number %d", wps->msg_num);
- return NULL;
- }
-
- if (wps->msg_num == 7 || wps->msg_num == 8) {
- msg = os_zalloc(2000);
- if (msg == NULL)
- return NULL;
- *msg_len = 2000;
- *op_code = WSC_MSG;
- *msg = WSC_MSG;
- wpa_printf(MSG_DEBUG, "WPS: Send M%d", wps->msg_num);
- } else if (wps->msg_num <= 6) {
- msg = os_zalloc(1);
- if (msg == NULL)
- return NULL;
- *msg_len = 1;
- *op_code = WSC_MSG;
- *msg = WSC_MSG;
- wpa_printf(MSG_DEBUG, "WPS: Send M%d", wps->msg_num);
- } else if (!wps->registrar && wps->msg_num == 9) {
- msg = os_zalloc(1);
- if (msg == NULL)
- return NULL;
- *msg_len = 1;
- *op_code = WSC_Done;
- *msg = WSC_Done;
- wpa_printf(MSG_DEBUG, "WPS: Send Done");
- } else
- return NULL;
-
- wps->msg_num++;
- return msg;
-}
+#include "wps/wps.h"
struct eap_wsc_data {
enum { START, MSG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state;
int registrar;
- u8 *in_buf, *out_buf, in_op_code, out_op_code;
- size_t in_len, in_used, out_len, out_used;
+ struct wpabuf *in_buf;
+ struct wpabuf *out_buf;
+ u8 in_op_code, out_op_code;
+ size_t out_used;
size_t fragment_size;
struct wps_data *wps;
};
@@ -207,7 +86,7 @@
return NULL;
data->state = registrar ? START : MSG;
data->registrar = registrar;
- data->wps = wps_init(registrar);
+ data->wps = wps_init(1, registrar);
if (data->wps == NULL) {
os_free(data);
return NULL;
@@ -221,8 +100,8 @@
static void eap_wsc_reset(struct eap_sm *sm, void *priv)
{
struct eap_wsc_data *data = priv;
- os_free(data->in_buf);
- os_free(data->out_buf);
+ wpabuf_free(data->in_buf);
+ wpabuf_free(data->out_buf);
wps_deinit(data->wps);
os_free(data);
}
@@ -249,25 +128,14 @@
}
-static struct wpabuf * eap_wsc_build_msg(struct eap_sm *sm,
- struct eap_wsc_data *data, u8 id)
+static struct wpabuf * eap_wsc_build_msg(struct eap_wsc_data *data, u8 id)
{
struct wpabuf *req;
u8 flags;
size_t send_len, plen;
- if (data->out_buf == NULL) {
- data->out_buf = wps_get_msg(data->wps, &data->out_len,
- &data->out_op_code);
- if (data->out_buf == NULL) {
- wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to receive "
- "message from WPS");
- return NULL;
- }
- }
-
flags = 0;
- send_len = data->out_len - data->out_used;
+ send_len = wpabuf_len(data->out_buf) - data->out_used;
if (2 + send_len > data->fragment_size) {
send_len = data->fragment_size - 2;
flags |= WSC_FLAGS_MF;
@@ -290,22 +158,25 @@
wpabuf_put_u8(req, data->out_op_code); /* Op-Code */
wpabuf_put_u8(req, flags); /* Flags */
if (flags & WSC_FLAGS_LF)
- wpabuf_put_be16(req, data->out_len);
-
- wpabuf_put_data(req, data->out_buf + data->out_used, send_len);
+ wpabuf_put_be16(req, wpabuf_len(data->out_buf));
+
+ wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used,
+ send_len);
data->out_used += send_len;
- if (data->out_used == data->out_len) {
- wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %u bytes "
- "(message sent completely)", send_len);
- os_free(data->out_buf);
+ if (data->out_used == wpabuf_len(data->out_buf)) {
+ wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes "
+ "(message sent completely)",
+ (unsigned long) send_len);
+ wpabuf_free(data->out_buf);
data->out_buf = NULL;
- data->out_len = data->out_used = 0;
+ data->out_used = 0;
eap_wsc_state(data, MSG);
} else {
- wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %u bytes "
- "(%u more to send)", send_len,
- data->out_len - data->out_used);
+ wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes "
+ "(%lu more to send)", (unsigned long) send_len,
+ (unsigned long) wpabuf_len(data->out_buf) -
+ data->out_used);
eap_wsc_state(data, WAIT_FRAG_ACK);
}
@@ -320,10 +191,22 @@
switch (data->state) {
case START:
return eap_wsc_build_start(sm, data, id);
+ case MSG:
+ if (data->out_buf == NULL) {
+ data->out_buf = wps_get_msg(data->wps,
+ &data->out_op_code);
+ if (data->out_buf == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to "
+ "receive message from WPS");
+ return NULL;
+ }
+ data->out_used = 0;
+ }
+ /* pass through */
+ case WAIT_FRAG_ACK:
+ return eap_wsc_build_msg(data, id);
case FRAG_ACK:
return eap_wsc_build_frag_ack(id, EAP_CODE_REQUEST);
- case MSG:
- return eap_wsc_build_msg(sm, data, id);
default:
wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected state %d in "
"buildReq", data->state);
@@ -349,6 +232,64 @@
}
+static int eap_wsc_process_cont(struct eap_wsc_data *data,
+ const u8 *buf, size_t len, u8 op_code)
+{
+ /* Process continuation of a pending message */
+ if (op_code != data->in_op_code) {
+ wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d in "
+ "fragment (expected %d)",
+ op_code, data->in_op_code);
+ eap_wsc_state(data, FAIL);
+ return -1;
+ }
+
+ if (len > wpabuf_tailroom(data->in_buf)) {
+ wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment overflow");
+ eap_wsc_state(data, FAIL);
+ return -1;
+ }
+
+ wpabuf_put_data(data->in_buf, buf, len);
+ wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes, waiting for %lu "
+ "bytes more", (unsigned long) len,
+ (unsigned long) wpabuf_tailroom(data->in_buf));
+
+ return 0;
+}
+
+
+static int eap_wsc_process_fragment(struct eap_wsc_data *data,
+ u8 flags, u8 op_code, u16 message_length,
+ const u8 *buf, size_t len)
+{
+ /* Process a fragment that is not the last one of the message */
+ if (data->in_buf == NULL && !(flags & WSC_FLAGS_LF)) {
+ wpa_printf(MSG_DEBUG, "EAP-WSC: No Message Length "
+ "field in a fragmented packet");
+ return -1;
+ }
+
+ if (data->in_buf == NULL) {
+ /* First fragment of the message */
+ data->in_buf = wpabuf_alloc(message_length);
+ if (data->in_buf == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-WSC: No memory for "
+ "message");
+ return -1;
+ }
+ data->in_op_code = op_code;
+ wpabuf_put_data(data->in_buf, buf, len);
+ wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes in "
+ "first fragment, waiting for %lu bytes more",
+ (unsigned long) len,
+ (unsigned long) wpabuf_tailroom(data->in_buf));
+ }
+
+ return 0;
+}
+
+
static void eap_wsc_process(struct eap_sm *sm, void *priv,
struct wpabuf *respData)
{
@@ -357,9 +298,8 @@
size_t len;
u8 op_code, flags;
u16 message_length = 0;
- const u8 *msg;
- size_t msg_len;
enum wps_process_res res;
+ struct wpabuf tmpbuf;
pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC,
respData, &len);
@@ -410,67 +350,29 @@
return;
}
- if (data->in_buf) {
- /* Process continuation of a pending message */
- if (op_code != data->in_op_code) {
- wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d "
- "in fragment (expected %d)",
- op_code, data->in_op_code);
+ if (data->in_buf &&
+ eap_wsc_process_cont(data, pos, end - pos, op_code) < 0) {
+ eap_wsc_state(data, FAIL);
+ return;
+ }
+
+ if (flags & WSC_FLAGS_MF) {
+ if (eap_wsc_process_fragment(data, flags, op_code,
+ message_length, pos, end - pos) <
+ 0)
eap_wsc_state(data, FAIL);
- return;
- }
-
- if (data->in_used + (end - pos) > data->in_len) {
- wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment overflow");
- eap_wsc_state(data, FAIL);
- return;
- }
-
- os_memcpy(data->in_buf + data->in_used, pos, end - pos);
- data->in_used += end - pos;
- wpa_printf(MSG_DEBUG, "EAP-WSC: Received %u bytes, waiting "
- "for %u bytes more", end - pos,
- data->in_len - data->in_used);
- }
-
- if (flags & WSC_FLAGS_MF) {
- if (data->in_buf == NULL && !(flags & WSC_FLAGS_LF)) {
- wpa_printf(MSG_DEBUG, "EAP-WSC: No Message Length "
- "field in a fragmented packet");
- return;
- }
-
- if (data->in_buf == NULL) {
- /* First fragment of the message */
- data->in_buf = os_malloc(message_length);
- if (data->in_buf == NULL) {
- wpa_printf(MSG_DEBUG, "EAP-WSC: No memory for "
- "message");
- return;
- }
- data->in_len = message_length;
- data->in_used = end - pos;
- data->in_op_code = op_code;
- os_memcpy(data->in_buf, pos, data->in_used);
- wpa_printf(MSG_DEBUG, "EAP-WSC: Received %u bytes in "
- "first fragment, waiting for %u bytes more",
- data->in_used,
- data->in_len - data->in_used);
- }
-
- eap_wsc_state(data, FRAG_ACK);
+ else
+ eap_wsc_state(data, FRAG_ACK);
return;
}
- if (data->in_buf) {
- msg = data->in_buf;
- msg_len = data->in_len;
- } else {
- msg = pos;
- msg_len = end - pos;
- }
-
- res = wps_process_msg(data->wps, op_code, msg, msg_len);
+ if (data->in_buf == NULL) {
+ /* Wrap unfragmented messages as wpabuf without extra copy */
+ wpabuf_set(&tmpbuf, pos, end - pos);
+ data->in_buf = &tmpbuf;
+ }
+
+ res = wps_process_msg(data->wps, op_code, data->in_buf);
switch (res) {
case WPS_DONE:
wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing completed "
@@ -490,9 +392,9 @@
break;
}
- os_free(data->in_buf);
+ if (data->in_buf != &tmpbuf)
+ wpabuf_free(data->in_buf);
data->in_buf = NULL;
- data->in_len = data->in_used = 0;
}
Added: wpasupplicant/branches/upstream/current/src/eap_server/ikev2.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_server/ikev2.c?rev=967&op=file
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_server/ikev2.c (added)
+++ wpasupplicant/branches/upstream/current/src/eap_server/ikev2.c Tue Jan 1 13:50:28 2008
@@ -1,0 +1,1204 @@
+/*
+ * IKEv2 initiator (RFC 4306) for EAP-IKEV2
+ * Copyright (c) 2007, Jouni Malinen <j at w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "dh_groups.h"
+#include "ikev2.h"
+
+
+static int ikev2_process_idr(struct ikev2_initiator_data *data,
+ const u8 *idr, size_t idr_len);
+
+
+void ikev2_initiator_deinit(struct ikev2_initiator_data *data)
+{
+ ikev2_free_keys(&data->keys);
+ wpabuf_free(data->r_dh_public);
+ wpabuf_free(data->i_dh_private);
+ os_free(data->IDi);
+ os_free(data->IDr);
+ os_free(data->shared_secret);
+ wpabuf_free(data->i_sign_msg);
+ wpabuf_free(data->r_sign_msg);
+ os_free(data->key_pad);
+}
+
+
+static int ikev2_derive_keys(struct ikev2_initiator_data *data)
+{
+ u8 *buf, *pos, *pad, skeyseed[IKEV2_MAX_HASH_LEN];
+ size_t buf_len, pad_len;
+ struct wpabuf *shared;
+ const struct ikev2_integ_alg *integ;
+ const struct ikev2_prf_alg *prf;
+ const struct ikev2_encr_alg *encr;
+ int ret;
+ const u8 *addr[2];
+ size_t len[2];
+
+ /* RFC 4306, Sect. 2.14 */
+
+ integ = ikev2_get_integ(data->proposal.integ);
+ prf = ikev2_get_prf(data->proposal.prf);
+ encr = ikev2_get_encr(data->proposal.encr);
+ if (integ == NULL || prf == NULL || encr == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: Unsupported proposal");
+ return -1;
+ }
+
+ shared = dh_derive_shared(data->r_dh_public, data->i_dh_private,
+ data->dh);
+ if (shared == NULL)
+ return -1;
+
+ /* Construct Ni | Nr | SPIi | SPIr */
+
+ buf_len = data->i_nonce_len + data->r_nonce_len + 2 * IKEV2_SPI_LEN;
+ buf = os_malloc(buf_len);
+ if (buf == NULL) {
+ wpabuf_free(shared);
+ return -1;
+ }
+
+ pos = buf;
+ os_memcpy(pos, data->i_nonce, data->i_nonce_len);
+ pos += data->i_nonce_len;
+ os_memcpy(pos, data->r_nonce, data->r_nonce_len);
+ pos += data->r_nonce_len;
+ os_memcpy(pos, data->i_spi, IKEV2_SPI_LEN);
+ pos += IKEV2_SPI_LEN;
+ os_memcpy(pos, data->r_spi, IKEV2_SPI_LEN);
+
+ /* SKEYSEED = prf(Ni | Nr, g^ir) */
+
+ /* Use zero-padding per RFC 4306, Sect. 2.14 */
+ pad_len = data->dh->prime_len - wpabuf_len(shared);
+ pad = os_zalloc(pad_len ? pad_len : 1);
+ if (pad == NULL) {
+ wpabuf_free(shared);
+ os_free(buf);
+ return -1;
+ }
+ addr[0] = pad;
+ len[0] = pad_len;
+ addr[1] = wpabuf_head(shared);
+ len[1] = wpabuf_len(shared);
+ if (ikev2_prf_hash(prf->id, buf, data->i_nonce_len + data->r_nonce_len,
+ 2, addr, len, skeyseed) < 0) {
+ wpabuf_free(shared);
+ os_free(buf);
+ os_free(pad);
+ return -1;
+ }
+ os_free(pad);
+ wpabuf_free(shared);
+
+ /* DH parameters are not needed anymore, so free them */
+ wpabuf_free(data->r_dh_public);
+ data->r_dh_public = NULL;
+ wpabuf_free(data->i_dh_private);
+ data->i_dh_private = NULL;
+
+ wpa_hexdump_key(MSG_DEBUG, "IKEV2: SKEYSEED",
+ skeyseed, prf->hash_len);
+
+ ret = ikev2_derive_sk_keys(prf, integ, encr, skeyseed, buf, buf_len,
+ &data->keys);
+ os_free(buf);
+ return ret;
+}
+
+
+static int ikev2_parse_transform(struct ikev2_initiator_data *data,
+ struct ikev2_proposal_data *prop,
+ const u8 *pos, const u8 *end)
+{
+ int transform_len;
+ const struct ikev2_transform *t;
+ u16 transform_id;
+ const u8 *tend;
+
+ if (end - pos < (int) sizeof(*t)) {
+ wpa_printf(MSG_INFO, "IKEV2: Too short transform");
+ return -1;
+ }
+
+ t = (const struct ikev2_transform *) pos;
+ transform_len = WPA_GET_BE16(t->transform_length);
+ if (transform_len < (int) sizeof(*t) || pos + transform_len > end) {
+ wpa_printf(MSG_INFO, "IKEV2: Invalid transform length %d",
+ transform_len);
+ return -1;
+ }
+ tend = pos + transform_len;
+
+ transform_id = WPA_GET_BE16(t->transform_id);
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Transform:");
+ wpa_printf(MSG_DEBUG, "IKEV2: Type: %d Transform Length: %d "
+ "Transform Type: %d Transform ID: %d",
+ t->type, transform_len, t->transform_type, transform_id);
+
+ if (t->type != 0 && t->type != 3) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Transform type");
+ return -1;
+ }
+
+ pos = (const u8 *) (t + 1);
+ if (pos < tend) {
+ wpa_hexdump(MSG_DEBUG, "IKEV2: Transform Attributes",
+ pos, tend - pos);
+ }
+
+ switch (t->transform_type) {
+ case IKEV2_TRANSFORM_ENCR:
+ if (ikev2_get_encr(transform_id) &&
+ transform_id == data->proposal.encr) {
+ if (transform_id == ENCR_AES_CBC) {
+ if (tend - pos != 4) {
+ wpa_printf(MSG_DEBUG, "IKEV2: No "
+ "Transform Attr for AES");
+ break;
+ }
+ if (WPA_GET_BE16(pos) != 0x800e) {
+ wpa_printf(MSG_DEBUG, "IKEV2: Not a "
+ "Key Size attribute for "
+ "AES");
+ break;
+ }
+ if (WPA_GET_BE16(pos + 2) != 128) {
+ wpa_printf(MSG_DEBUG, "IKEV2: "
+ "Unsupported AES key size "
+ "%d bits",
+ WPA_GET_BE16(pos + 2));
+ break;
+ }
+ }
+ prop->encr = transform_id;
+ }
+ break;
+ case IKEV2_TRANSFORM_PRF:
+ if (ikev2_get_prf(transform_id) &&
+ transform_id == data->proposal.prf)
+ prop->prf = transform_id;
+ break;
+ case IKEV2_TRANSFORM_INTEG:
+ if (ikev2_get_integ(transform_id) &&
+ transform_id == data->proposal.integ)
+ prop->integ = transform_id;
+ break;
+ case IKEV2_TRANSFORM_DH:
+ if (dh_groups_get(transform_id) &&
+ transform_id == data->proposal.dh)
+ prop->dh = transform_id;
+ break;
+ }
+
+ return transform_len;
+}
+
+
+static int ikev2_parse_proposal(struct ikev2_initiator_data *data,
+ struct ikev2_proposal_data *prop,
+ const u8 *pos, const u8 *end)
+{
+ const u8 *pend, *ppos;
+ int proposal_len, i;
+ const struct ikev2_proposal *p;
+
+ if (end - pos < (int) sizeof(*p)) {
+ wpa_printf(MSG_INFO, "IKEV2: Too short proposal");
+ return -1;
+ }
+
+ p = (const struct ikev2_proposal *) pos;
+ proposal_len = WPA_GET_BE16(p->proposal_length);
+ if (proposal_len < (int) sizeof(*p) || pos + proposal_len > end) {
+ wpa_printf(MSG_INFO, "IKEV2: Invalid proposal length %d",
+ proposal_len);
+ return -1;
+ }
+ wpa_printf(MSG_DEBUG, "IKEV2: SAi1 Proposal # %d",
+ p->proposal_num);
+ wpa_printf(MSG_DEBUG, "IKEV2: Type: %d Proposal Length: %d "
+ " Protocol ID: %d",
+ p->type, proposal_len, p->protocol_id);
+ wpa_printf(MSG_DEBUG, "IKEV2: SPI Size: %d Transforms: %d",
+ p->spi_size, p->num_transforms);
+
+ if (p->type != 0 && p->type != 2) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal type");
+ return -1;
+ }
+
+ if (p->protocol_id != IKEV2_PROTOCOL_IKE) {
+ wpa_printf(MSG_DEBUG, "IKEV2: Unexpected Protocol ID "
+ "(only IKE allowed for EAP-IKEv2)");
+ return -1;
+ }
+
+ if (p->proposal_num != prop->proposal_num) {
+ if (p->proposal_num == prop->proposal_num + 1)
+ prop->proposal_num = p->proposal_num;
+ else {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal #");
+ return -1;
+ }
+ }
+
+ ppos = (const u8 *) (p + 1);
+ pend = pos + proposal_len;
+ if (ppos + p->spi_size > pend) {
+ wpa_printf(MSG_INFO, "IKEV2: Not enough room for SPI "
+ "in proposal");
+ return -1;
+ }
+ if (p->spi_size) {
+ wpa_hexdump(MSG_DEBUG, "IKEV2: SPI",
+ ppos, p->spi_size);
+ ppos += p->spi_size;
+ }
+
+ /*
+ * For initial IKE_SA negotiation, SPI Size MUST be zero; for
+ * subsequent negotiations, it must be 8 for IKE. We only support
+ * initial case for now.
+ */
+ if (p->spi_size != 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected SPI Size");
+ return -1;
+ }
+
+ if (p->num_transforms == 0) {
+ wpa_printf(MSG_INFO, "IKEV2: At least one transform required");
+ return -1;
+ }
+
+ for (i = 0; i < (int) p->num_transforms; i++) {
+ int tlen = ikev2_parse_transform(data, prop, ppos, pend);
+ if (tlen < 0)
+ return -1;
+ ppos += tlen;
+ }
+
+ if (ppos != pend) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected data after "
+ "transforms");
+ return -1;
+ }
+
+ return proposal_len;
+}
+
+
+static int ikev2_process_sar1(struct ikev2_initiator_data *data,
+ const u8 *sar1, size_t sar1_len)
+{
+ struct ikev2_proposal_data prop;
+ const u8 *pos, *end;
+ int found = 0;
+
+ /* Security Association Payloads: <Proposals> */
+
+ if (sar1 == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: SAr1 not received");
+ return -1;
+ }
+
+ os_memset(&prop, 0, sizeof(prop));
+ prop.proposal_num = 1;
+
+ pos = sar1;
+ end = sar1 + sar1_len;
+
+ while (pos < end) {
+ int plen;
+
+ prop.integ = -1;
+ prop.prf = -1;
+ prop.encr = -1;
+ prop.dh = -1;
+ plen = ikev2_parse_proposal(data, &prop, pos, end);
+ if (plen < 0)
+ return -1;
+
+ if (!found && prop.integ != -1 && prop.prf != -1 &&
+ prop.encr != -1 && prop.dh != -1) {
+ found = 1;
+ }
+
+ pos += plen;
+
+ /* Only one proposal expected in SAr */
+ break;
+ }
+
+ if (pos != end) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected data after proposal");
+ return -1;
+ }
+
+ if (!found) {
+ wpa_printf(MSG_INFO, "IKEV2: No acceptable proposal found");
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Accepted proposal #%d: ENCR:%d PRF:%d "
+ "INTEG:%d D-H:%d", data->proposal.proposal_num,
+ data->proposal.encr, data->proposal.prf,
+ data->proposal.integ, data->proposal.dh);
+
+ return 0;
+}
+
+
+static int ikev2_process_ker(struct ikev2_initiator_data *data,
+ const u8 *ker, size_t ker_len)
+{
+ u16 group;
+
+ /*
+ * Key Exchange Payload:
+ * DH Group # (16 bits)
+ * RESERVED (16 bits)
+ * Key Exchange Data (Diffie-Hellman public value)
+ */
+
+ if (ker == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: KEr not received");
+ return -1;
+ }
+
+ if (ker_len < 4 + 96) {
+ wpa_printf(MSG_INFO, "IKEV2: Too show Key Exchange Payload");
+ return -1;
+ }
+
+ group = WPA_GET_BE16(ker);
+ wpa_printf(MSG_DEBUG, "IKEV2: KEr DH Group #%u", group);
+
+ if (group != data->proposal.dh) {
+ wpa_printf(MSG_DEBUG, "IKEV2: KEr DH Group #%u does not match "
+ "with the selected proposal (%u)",
+ group, data->proposal.dh);
+ return -1;
+ }
+
+ if (data->dh == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: Unsupported DH group");
+ return -1;
+ }
+
+ /* RFC 4306, Section 3.4:
+ * The length of DH public value MUST be equal to the lenght of the
+ * prime modulus.
+ */
+ if (ker_len - 4 != data->dh->prime_len) {
+ wpa_printf(MSG_INFO, "IKEV2: Invalid DH public value length "
+ "%d (expected %d)",
+ ker_len - 4, data->dh->prime_len);
+ return -1;
+ }
+
+ wpabuf_free(data->r_dh_public);
+ data->r_dh_public = wpabuf_alloc_copy(ker + 4, ker_len - 4);
+ if (data->r_dh_public == NULL)
+ return -1;
+
+ wpa_hexdump_buf(MSG_DEBUG, "IKEV2: KEr Diffie-Hellman Public Value",
+ data->r_dh_public);
+
+ return 0;
+}
+
+
+static int ikev2_process_nr(struct ikev2_initiator_data *data,
+ const u8 *nr, size_t nr_len)
+{
+ if (nr == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: Nr not received");
+ return -1;
+ }
+
+ if (nr_len < IKEV2_NONCE_MIN_LEN || nr_len > IKEV2_NONCE_MAX_LEN) {
+ wpa_printf(MSG_INFO, "IKEV2: Invalid Nr length %d", nr_len);
+ return -1;
+ }
+
+ data->r_nonce_len = nr_len;
+ os_memcpy(data->r_nonce, nr, nr_len);
+ wpa_hexdump(MSG_MSGDUMP, "IKEV2: Nr",
+ data->r_nonce, data->r_nonce_len);
+
+ return 0;
+}
+
+
+static int ikev2_process_sa_init_encr(struct ikev2_initiator_data *data,
+ const struct ikev2_hdr *hdr,
+ const u8 *encrypted,
+ size_t encrypted_len, u8 next_payload)
+{
+ u8 *decrypted;
+ size_t decrypted_len;
+ struct ikev2_payloads pl;
+ int ret = 0;
+
+ decrypted = ikev2_decrypt_payload(data->proposal.encr,
+ data->proposal.integ, &data->keys, 0,
+ hdr, encrypted, encrypted_len,
+ &decrypted_len);
+ if (decrypted == NULL)
+ return -1;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Processing decrypted payloads");
+
+ if (ikev2_parse_payloads(&pl, next_payload, decrypted,
+ decrypted + decrypted_len) < 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Failed to parse decrypted "
+ "payloads");
+ return -1;
+ }
+
+ if (pl.idr)
+ ret = ikev2_process_idr(data, pl.idr, pl.idr_len);
+
+ os_free(decrypted);
+
+ return ret;
+}
+
+
+static int ikev2_process_sa_init(struct ikev2_initiator_data *data,
+ const struct ikev2_hdr *hdr,
+ struct ikev2_payloads *pl)
+{
+ if (ikev2_process_sar1(data, pl->sa, pl->sa_len) < 0 ||
+ ikev2_process_ker(data, pl->ke, pl->ke_len) < 0 ||
+ ikev2_process_nr(data, pl->nonce, pl->nonce_len) < 0)
+ return -1;
+
+ os_memcpy(data->r_spi, hdr->r_spi, IKEV2_SPI_LEN);
+
+ if (ikev2_derive_keys(data) < 0)
+ return -1;
+
+ if (pl->encrypted) {
+ wpa_printf(MSG_DEBUG, "IKEV2: Encrypted payload in SA_INIT - "
+ "try to get IDr from it");
+ if (ikev2_process_sa_init_encr(data, hdr, pl->encrypted,
+ pl->encrypted_len,
+ pl->encr_next_payload) < 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Failed to process "
+ "encrypted payload");
+ return -1;
+ }
+ }
+
+ data->state = SA_AUTH;
+
+ return 0;
+}
+
+
+static int ikev2_process_idr(struct ikev2_initiator_data *data,
+ const u8 *idr, size_t idr_len)
+{
+ u8 id_type;
+
+ if (idr == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: No IDr received");
+ return -1;
+ }
+
+ if (idr_len < 4) {
+ wpa_printf(MSG_INFO, "IKEV2: Too short IDr payload");
+ return -1;
+ }
+
+ id_type = idr[0];
+ idr += 4;
+ idr_len -= 4;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: IDr ID Type %d", id_type);
+ wpa_hexdump_ascii(MSG_DEBUG, "IKEV2: IDr", idr, idr_len);
+ if (data->IDr) {
+ if (id_type != data->IDr_type || idr_len != data->IDr_len ||
+ os_memcmp(idr, data->IDr, idr_len) != 0) {
+ wpa_printf(MSG_INFO, "IKEV2: IDr differs from the one "
+ "received earlier");
+ wpa_printf(MSG_DEBUG, "IKEV2: Previous IDr ID Type %d",
+ id_type);
+ wpa_hexdump_ascii(MSG_DEBUG, "Previous IKEV2: IDr",
+ data->IDr, data->IDr_len);
+ return -1;
+ }
+ os_free(data->IDr);
+ }
+ data->IDr = os_malloc(idr_len);
+ if (data->IDr == NULL)
+ return -1;
+ os_memcpy(data->IDr, idr, idr_len);
+ data->IDr_len = idr_len;
+ data->IDr_type = id_type;
+
+ return 0;
+}
+
+
+static int ikev2_process_cert(struct ikev2_initiator_data *data,
+ const u8 *cert, size_t cert_len)
+{
+ u8 cert_encoding;
+
+ if (cert == NULL) {
+ if (data->peer_auth == PEER_AUTH_CERT) {
+ wpa_printf(MSG_INFO, "IKEV2: No Certificate received");
+ return -1;
+ }
+ return 0;
+ }
+
+ if (cert_len < 1) {
+ wpa_printf(MSG_INFO, "IKEV2: No Cert Encoding field");
+ return -1;
+ }
+
+ cert_encoding = cert[0];
+ cert++;
+ cert_len--;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Cert Encoding %d", cert_encoding);
+ wpa_hexdump(MSG_MSGDUMP, "IKEV2: Certificate Data", cert, cert_len);
+
+ /* TODO: validate certificate */
+
+ return 0;
+}
+
+
+static int ikev2_process_auth_cert(struct ikev2_initiator_data *data,
+ u8 method, const u8 *auth, size_t auth_len)
+{
+ if (method != AUTH_RSA_SIGN) {
+ wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication "
+ "method %d", method);
+ return -1;
+ }
+
+ /* TODO: validate AUTH */
+ return 0;
+}
+
+
+static int ikev2_process_auth_secret(struct ikev2_initiator_data *data,
+ u8 method, const u8 *auth,
+ size_t auth_len)
+{
+ u8 auth_data[IKEV2_MAX_HASH_LEN];
+ const struct ikev2_prf_alg *prf;
+
+ if (method != AUTH_SHARED_KEY_MIC) {
+ wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication "
+ "method %d", method);
+ return -1;
+ }
+
+ /* msg | Ni | prf(SK_pr,IDr') */
+ if (ikev2_derive_auth_data(data->proposal.prf, data->r_sign_msg,
+ data->IDr, data->IDr_len, data->IDr_type,
+ &data->keys, 0, data->shared_secret,
+ data->shared_secret_len,
+ data->i_nonce, data->i_nonce_len,
+ data->key_pad, data->key_pad_len,
+ auth_data) < 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data");
+ return -1;
+ }
+
+ wpabuf_free(data->r_sign_msg);
+ data->r_sign_msg = NULL;
+
+ prf = ikev2_get_prf(data->proposal.prf);
+ if (prf == NULL)
+ return -1;
+
+ if (auth_len != prf->hash_len ||
+ os_memcmp(auth, auth_data, auth_len) != 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Invalid Authentication Data");
+ wpa_hexdump(MSG_DEBUG, "IKEV2: Received Authentication Data",
+ auth, auth_len);
+ wpa_hexdump(MSG_DEBUG, "IKEV2: Expected Authentication Data",
+ auth_data, prf->hash_len);
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Peer authenticated successfully "
+ "using shared keys");
+
+ return 0;
+}
+
+
+static int ikev2_process_auth(struct ikev2_initiator_data *data,
+ const u8 *auth, size_t auth_len)
+{
+ u8 auth_method;
+
+ if (auth == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: No Authentication Payload");
+ return -1;
+ }
+
+ if (auth_len < 4) {
+ wpa_printf(MSG_INFO, "IKEV2: Too short Authentication "
+ "Payload");
+ return -1;
+ }
+
+ auth_method = auth[0];
+ auth += 4;
+ auth_len -= 4;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Auth Method %d", auth_method);
+ wpa_hexdump(MSG_MSGDUMP, "IKEV2: Authentication Data", auth, auth_len);
+
+ switch (data->peer_auth) {
+ case PEER_AUTH_CERT:
+ return ikev2_process_auth_cert(data, auth_method, auth,
+ auth_len);
+ case PEER_AUTH_SECRET:
+ return ikev2_process_auth_secret(data, auth_method, auth,
+ auth_len);
+ }
+
+ return -1;
+}
+
+
+static int ikev2_process_sa_auth_decrypted(struct ikev2_initiator_data *data,
+ u8 next_payload,
+ u8 *payload, size_t payload_len)
+{
+ struct ikev2_payloads pl;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Processing decrypted payloads");
+
+ if (ikev2_parse_payloads(&pl, next_payload, payload, payload +
+ payload_len) < 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Failed to parse decrypted "
+ "payloads");
+ return -1;
+ }
+
+ if (ikev2_process_idr(data, pl.idr, pl.idr_len) < 0 ||
+ ikev2_process_cert(data, pl.cert, pl.cert_len) < 0 ||
+ ikev2_process_auth(data, pl.auth, pl.auth_len) < 0)
+ return -1;
+
+ return 0;
+}
+
+
+static int ikev2_process_sa_auth(struct ikev2_initiator_data *data,
+ const struct ikev2_hdr *hdr,
+ struct ikev2_payloads *pl)
+{
+ u8 *decrypted;
+ size_t decrypted_len;
+ int ret;
+
+ decrypted = ikev2_decrypt_payload(data->proposal.encr,
+ data->proposal.integ,
+ &data->keys, 0, hdr, pl->encrypted,
+ pl->encrypted_len, &decrypted_len);
+ if (decrypted == NULL)
+ return -1;
+
+ ret = ikev2_process_sa_auth_decrypted(data, pl->encr_next_payload,
+ decrypted, decrypted_len);
+ os_free(decrypted);
+
+ if (ret == 0 && !data->unknown_user) {
+ wpa_printf(MSG_DEBUG, "IKEV2: Authentication completed");
+ data->state = IKEV2_DONE;
+ }
+
+ return ret;
+}
+
+
+static int ikev2_validate_rx_state(struct ikev2_initiator_data *data,
+ u8 exchange_type, u32 message_id)
+{
+ switch (data->state) {
+ case SA_INIT:
+ /* Expect to receive IKE_SA_INIT: HDR, SAr, KEr, Nr, [CERTREQ],
+ * [SK{IDr}] */
+ if (exchange_type != IKE_SA_INIT) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type "
+ "%u in SA_INIT state", exchange_type);
+ return -1;
+ }
+ if (message_id != 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u "
+ "in SA_INIT state", message_id);
+ return -1;
+ }
+ break;
+ case SA_AUTH:
+ /* Expect to receive IKE_SA_AUTH:
+ * HDR, SK {IDr, [CERT,] [CERTREQ,] [NFID,] AUTH}
+ */
+ if (exchange_type != IKE_SA_AUTH) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type "
+ "%u in SA_AUTH state", exchange_type);
+ return -1;
+ }
+ if (message_id != 1) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u "
+ "in SA_AUTH state", message_id);
+ return -1;
+ }
+ break;
+ case CHILD_SA:
+ if (exchange_type != CREATE_CHILD_SA) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type "
+ "%u in CHILD_SA state", exchange_type);
+ return -1;
+ }
+ if (message_id != 2) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u "
+ "in CHILD_SA state", message_id);
+ return -1;
+ }
+ break;
+ case IKEV2_DONE:
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int ikev2_initiator_process(struct ikev2_initiator_data *data,
+ const struct wpabuf *buf)
+{
+ const struct ikev2_hdr *hdr;
+ u32 length, message_id;
+ const u8 *pos, *end;
+ struct ikev2_payloads pl;
+
+ wpa_printf(MSG_MSGDUMP, "IKEV2: Received message (len %lu)",
+ (unsigned long) wpabuf_len(buf));
+
+ if (wpabuf_len(buf) < sizeof(*hdr)) {
+ wpa_printf(MSG_INFO, "IKEV2: Too short frame to include HDR");
+ return -1;
+ }
+
+ hdr = (const struct ikev2_hdr *) wpabuf_head(buf);
+ end = wpabuf_head_u8(buf) + wpabuf_len(buf);
+ message_id = WPA_GET_BE32(hdr->message_id);
+ length = WPA_GET_BE32(hdr->length);
+
+ wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Initiator's SPI",
+ hdr->i_spi, IKEV2_SPI_LEN);
+ wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Initiator's SPI",
+ hdr->r_spi, IKEV2_SPI_LEN);
+ wpa_printf(MSG_DEBUG, "IKEV2: Next Payload: %u Version: 0x%x "
+ "Exchange Type: %u",
+ hdr->next_payload, hdr->version, hdr->exchange_type);
+ wpa_printf(MSG_DEBUG, "IKEV2: Message ID: %u Length: %u",
+ message_id, length);
+
+ if (hdr->version != IKEV2_VERSION) {
+ wpa_printf(MSG_INFO, "IKEV2: Unsupported HDR version 0x%x "
+ "(expected 0x%x)", hdr->version, IKEV2_VERSION);
+ return -1;
+ }
+
+ if (length != wpabuf_len(buf)) {
+ wpa_printf(MSG_INFO, "IKEV2: Invalid length (HDR: %lu != "
+ "RX: %lu)", (unsigned long) length,
+ (unsigned long) wpabuf_len(buf));
+ return -1;
+ }
+
+ if (ikev2_validate_rx_state(data, hdr->exchange_type, message_id) < 0)
+ return -1;
+
+ if ((hdr->flags & (IKEV2_HDR_INITIATOR | IKEV2_HDR_RESPONSE)) !=
+ IKEV2_HDR_RESPONSE) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected Flags value 0x%x",
+ hdr->flags);
+ return -1;
+ }
+
+ if (data->state != SA_INIT) {
+ if (os_memcmp(data->i_spi, hdr->i_spi, IKEV2_SPI_LEN) != 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA "
+ "Initiator's SPI");
+ return -1;
+ }
+ if (os_memcmp(data->r_spi, hdr->r_spi, IKEV2_SPI_LEN) != 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA "
+ "Responder's SPI");
+ return -1;
+ }
+ }
+
+ pos = (const u8 *) (hdr + 1);
+ if (ikev2_parse_payloads(&pl, hdr->next_payload, pos, end) < 0)
+ return -1;
+
+ switch (data->state) {
+ case SA_INIT:
+ if (ikev2_process_sa_init(data, hdr, &pl) < 0)
+ return -1;
+ wpabuf_free(data->r_sign_msg);
+ data->r_sign_msg = wpabuf_dup(buf);
+ break;
+ case SA_AUTH:
+ if (ikev2_process_sa_auth(data, hdr, &pl) < 0)
+ return -1;
+ break;
+ case CHILD_SA:
+ case IKEV2_DONE:
+ break;
+ }
+
+ return 0;
+}
+
+
+static void ikev2_build_hdr(struct ikev2_initiator_data *data,
+ struct wpabuf *msg, u8 exchange_type,
+ u8 next_payload, u32 message_id)
+{
+ struct ikev2_hdr *hdr;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Adding HDR");
+
+ /* HDR - RFC 4306, Sect. 3.1 */
+ hdr = wpabuf_put(msg, sizeof(*hdr));
+ os_memcpy(hdr->i_spi, data->i_spi, IKEV2_SPI_LEN);
+ os_memcpy(hdr->r_spi, data->r_spi, IKEV2_SPI_LEN);
+ hdr->next_payload = next_payload;
+ hdr->version = IKEV2_VERSION;
+ hdr->exchange_type = exchange_type;
+ hdr->flags = IKEV2_HDR_INITIATOR;
+ WPA_PUT_BE32(hdr->message_id, message_id);
+}
+
+
+static int ikev2_build_sai(struct ikev2_initiator_data *data,
+ struct wpabuf *msg, u8 next_payload)
+{
+ struct ikev2_payload_hdr *phdr;
+ size_t plen;
+ struct ikev2_proposal *p;
+ struct ikev2_transform *t;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Adding SAi payload");
+
+ /* SAi1 - RFC 4306, Sect. 2.7 and 3.3 */
+ phdr = wpabuf_put(msg, sizeof(*phdr));
+ phdr->next_payload = next_payload;
+ phdr->flags = 0;
+
+ /* TODO: support for multiple proposals */
+ p = wpabuf_put(msg, sizeof(*p));
+ p->proposal_num = data->proposal.proposal_num;
+ p->protocol_id = IKEV2_PROTOCOL_IKE;
+ p->num_transforms = 4;
+
+ t = wpabuf_put(msg, sizeof(*t));
+ t->type = 3;
+ t->transform_type = IKEV2_TRANSFORM_ENCR;
+ WPA_PUT_BE16(t->transform_id, data->proposal.encr);
+ if (data->proposal.encr == ENCR_AES_CBC) {
+ /* Transform Attribute: Key Len = 128 bits */
+ wpabuf_put_be16(msg, 0x800e); /* AF=1, AttrType=14 */
+ wpabuf_put_be16(msg, 128); /* 128-bit key */
+ }
+ plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) t;
+ WPA_PUT_BE16(t->transform_length, plen);
+
+ t = wpabuf_put(msg, sizeof(*t));
+ t->type = 3;
+ WPA_PUT_BE16(t->transform_length, sizeof(*t));
+ t->transform_type = IKEV2_TRANSFORM_PRF;
+ WPA_PUT_BE16(t->transform_id, data->proposal.prf);
+
+ t = wpabuf_put(msg, sizeof(*t));
+ t->type = 3;
+ WPA_PUT_BE16(t->transform_length, sizeof(*t));
+ t->transform_type = IKEV2_TRANSFORM_INTEG;
+ WPA_PUT_BE16(t->transform_id, data->proposal.integ);
+
+ t = wpabuf_put(msg, sizeof(*t));
+ WPA_PUT_BE16(t->transform_length, sizeof(*t));
+ t->transform_type = IKEV2_TRANSFORM_DH;
+ WPA_PUT_BE16(t->transform_id, data->proposal.dh);
+
+ plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) p;
+ WPA_PUT_BE16(p->proposal_length, plen);
+
+ plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
+ WPA_PUT_BE16(phdr->payload_length, plen);
+
+ return 0;
+}
+
+
+static int ikev2_build_kei(struct ikev2_initiator_data *data,
+ struct wpabuf *msg, u8 next_payload)
+{
+ struct ikev2_payload_hdr *phdr;
+ size_t plen;
+ struct wpabuf *pv;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Adding KEi payload");
+
+ data->dh = dh_groups_get(data->proposal.dh);
+ pv = dh_init(data->dh, &data->i_dh_private);
+ if (pv == NULL) {
+ wpa_printf(MSG_DEBUG, "IKEV2: Failed to initialize DH");
+ return -1;
+ }
+
+ /* KEi - RFC 4306, Sect. 3.4 */
+ phdr = wpabuf_put(msg, sizeof(*phdr));
+ phdr->next_payload = next_payload;
+ phdr->flags = 0;
+
+ wpabuf_put_be16(msg, data->proposal.dh); /* DH Group # */
+ wpabuf_put(msg, 2); /* RESERVED */
+ /*
+ * RFC 4306, Sect. 3.4: possible zero padding for public value to
+ * match the length of the prime.
+ */
+ wpabuf_put(msg, data->dh->prime_len - wpabuf_len(pv));
+ wpabuf_put_buf(msg, pv);
+ os_free(pv);
+
+ plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
+ WPA_PUT_BE16(phdr->payload_length, plen);
+ return 0;
+}
+
+
+static int ikev2_build_ni(struct ikev2_initiator_data *data,
+ struct wpabuf *msg, u8 next_payload)
+{
+ struct ikev2_payload_hdr *phdr;
+ size_t plen;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Adding Ni payload");
+
+ /* Ni - RFC 4306, Sect. 3.9 */
+ phdr = wpabuf_put(msg, sizeof(*phdr));
+ phdr->next_payload = next_payload;
+ phdr->flags = 0;
+ wpabuf_put_data(msg, data->i_nonce, data->i_nonce_len);
+ plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
+ WPA_PUT_BE16(phdr->payload_length, plen);
+ return 0;
+}
+
+
+static int ikev2_build_idi(struct ikev2_initiator_data *data,
+ struct wpabuf *msg, u8 next_payload)
+{
+ struct ikev2_payload_hdr *phdr;
+ size_t plen;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Adding IDi payload");
+
+ if (data->IDi == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: No IDi available");
+ return -1;
+ }
+
+ /* IDi - RFC 4306, Sect. 3.5 */
+ phdr = wpabuf_put(msg, sizeof(*phdr));
+ phdr->next_payload = next_payload;
+ phdr->flags = 0;
+ wpabuf_put_u8(msg, ID_KEY_ID);
+ wpabuf_put(msg, 3); /* RESERVED */
+ wpabuf_put_data(msg, data->IDi, data->IDi_len);
+ plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
+ WPA_PUT_BE16(phdr->payload_length, plen);
+ return 0;
+}
+
+
+static int ikev2_build_auth(struct ikev2_initiator_data *data,
+ struct wpabuf *msg, u8 next_payload)
+{
+ struct ikev2_payload_hdr *phdr;
+ size_t plen;
+ const struct ikev2_prf_alg *prf;
+
+ wpa_printf(MSG_DEBUG, "IKEV2: Adding AUTH payload");
+
+ prf = ikev2_get_prf(data->proposal.prf);
+ if (prf == NULL)
+ return -1;
+
+ /* Authentication - RFC 4306, Sect. 3.8 */
+ phdr = wpabuf_put(msg, sizeof(*phdr));
+ phdr->next_payload = next_payload;
+ phdr->flags = 0;
+ wpabuf_put_u8(msg, AUTH_SHARED_KEY_MIC);
+ wpabuf_put(msg, 3); /* RESERVED */
+
+ /* msg | Nr | prf(SK_pi,IDi') */
+ if (ikev2_derive_auth_data(data->proposal.prf, data->i_sign_msg,
+ data->IDi, data->IDi_len, ID_KEY_ID,
+ &data->keys, 1, data->shared_secret,
+ data->shared_secret_len,
+ data->r_nonce, data->r_nonce_len,
+ data->key_pad, data->key_pad_len,
+ wpabuf_put(msg, prf->hash_len)) < 0) {
+ wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data");
+ return -1;
+ }
+ wpabuf_free(data->i_sign_msg);
+ data->i_sign_msg = NULL;
+
+ plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
+ WPA_PUT_BE16(phdr->payload_length, plen);
+ return 0;
+}
+
+
+static struct wpabuf * ikev2_build_sa_init(struct ikev2_initiator_data *data)
+{
+ struct wpabuf *msg;
+
+ /* build IKE_SA_INIT: HDR, SAi, KEi, Ni */
+
+ if (os_get_random(data->i_spi, IKEV2_SPI_LEN))
+ return NULL;
+ wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Initiator's SPI",
+ data->i_spi, IKEV2_SPI_LEN);
+
+ data->i_nonce_len = IKEV2_NONCE_MIN_LEN;
+ if (os_get_random(data->i_nonce, data->i_nonce_len))
+ return NULL;
+ wpa_hexdump(MSG_DEBUG, "IKEV2: Ni", data->i_nonce, data->i_nonce_len);
+
+ msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + 1000);
+ if (msg == NULL)
+ return NULL;
+
+ ikev2_build_hdr(data, msg, IKE_SA_INIT, IKEV2_PAYLOAD_SA, 0);
+ if (ikev2_build_sai(data, msg, IKEV2_PAYLOAD_KEY_EXCHANGE) ||
+ ikev2_build_kei(data, msg, IKEV2_PAYLOAD_NONCE) ||
+ ikev2_build_ni(data, msg, IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) {
+ wpabuf_free(msg);
+ return NULL;
+ }
+
+ ikev2_update_hdr(msg);
+
+ wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_INIT)", msg);
+
+ wpabuf_free(data->i_sign_msg);
+ data->i_sign_msg = wpabuf_dup(msg);
+
+ return msg;
+}
+
+
+static struct wpabuf * ikev2_build_sa_auth(struct ikev2_initiator_data *data)
+{
+ struct wpabuf *msg, *plain;
+ const u8 *secret;
+ size_t secret_len;
+
+ secret = data->get_shared_secret(data->cb_ctx, data->IDr,
+ data->IDr_len, &secret_len);
+ if (secret == NULL) {
+ wpa_printf(MSG_INFO, "IKEV2: Could not get shared secret - "
+ "use fake value");
+ /* draft-tschofenig-eap-ikev2-15.txt, Sect. 7:
+ * Use a random key to fake AUTH generation in order to prevent
+ * probing of user identities.
+ */
+ data->unknown_user = 1;
+ os_free(data->shared_secret);
+ data->shared_secret = os_malloc(16);
+ if (data->shared_secret == NULL)
+ return NULL;
+ data->shared_secret_len = 16;
+ if (os_get_random(data->shared_secret, 16))
+ return NULL;
+ } else {
+ os_free(data->shared_secret);
+ data->shared_secret = os_malloc(secret_len);
+ if (data->shared_secret == NULL)
+ return NULL;
+ os_memcpy(data->shared_secret, secret, secret_len);
+ data->shared_secret_len = secret_len;
+ }
+
+ /* build IKE_SA_AUTH: HDR, SK {IDi, [CERT,] [CERTREQ,] AUTH} */
+
+ msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1000);
+ if (msg == NULL)
+ return NULL;
+ ikev2_build_hdr(data, msg, IKE_SA_AUTH, IKEV2_PAYLOAD_ENCRYPTED, 1);
+
+ plain = wpabuf_alloc(data->IDr_len + 1000);
+ if (plain == NULL) {
+ wpabuf_free(msg);
+ return NULL;
+ }
+
+ if (ikev2_build_idi(data, plain, IKEV2_PAYLOAD_AUTHENTICATION) ||
+ ikev2_build_auth(data, plain, IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) ||
+ ikev2_build_encrypted(data->proposal.encr, data->proposal.integ,
+ &data->keys, 1, msg, plain,
+ IKEV2_PAYLOAD_IDi)) {
+ wpabuf_free(plain);
+ wpabuf_free(msg);
+ return NULL;
+ }
+ wpabuf_free(plain);
+
+ wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_AUTH)", msg);
+
+ return msg;
+}
+
+
+struct wpabuf * ikev2_initiator_build(struct ikev2_initiator_data *data)
+{
+ switch (data->state) {
+ case SA_INIT:
+ return ikev2_build_sa_init(data);
+ case SA_AUTH:
+ return ikev2_build_sa_auth(data);
+ case CHILD_SA:
+ return NULL;
+ case IKEV2_DONE:
+ return NULL;
+ }
+ return NULL;
+}
Added: wpasupplicant/branches/upstream/current/src/eap_server/ikev2.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/eap_server/ikev2.h?rev=967&op=file
==============================================================================
--- wpasupplicant/branches/upstream/current/src/eap_server/ikev2.h (added)
+++ wpasupplicant/branches/upstream/current/src/eap_server/ikev2.h Tue Jan 1 13:50:28 2008
@@ -1,0 +1,67 @@
+/*
+ * IKEv2 initiator (RFC 4306) for EAP-IKEV2
+ * Copyright (c) 2007, Jouni Malinen <j at 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 IKEV2_H
+#define IKEV2_H
+
+#include "eap_common/ikev2_common.h"
+
+struct ikev2_proposal_data {
+ u8 proposal_num;
+ int integ;
+ int prf;
+ int encr;
+ int dh;
+};
+
+
+struct ikev2_initiator_data {
+ enum { SA_INIT, SA_AUTH, CHILD_SA, IKEV2_DONE } state;
+ u8 i_spi[IKEV2_SPI_LEN];
+ u8 r_spi[IKEV2_SPI_LEN];
+ u8 i_nonce[IKEV2_NONCE_MAX_LEN];
+ size_t i_nonce_len;
+ u8 r_nonce[IKEV2_NONCE_MAX_LEN];
+ size_t r_nonce_len;
+ struct wpabuf *r_dh_public;
+ struct wpabuf *i_dh_private;
+ struct ikev2_proposal_data proposal;
+ const struct dh_group *dh;
+ struct ikev2_keys keys;
+ u8 *IDi;
+ size_t IDi_len;
+ u8 *IDr;
+ size_t IDr_len;
+ u8 IDr_type;
+ struct wpabuf *r_sign_msg;
+ struct wpabuf *i_sign_msg;
+ u8 *shared_secret;
+ size_t shared_secret_len;
+ enum { PEER_AUTH_CERT, PEER_AUTH_SECRET } peer_auth;
+ u8 *key_pad;
+ size_t key_pad_len;
+
+ const u8 * (*get_shared_secret)(void *ctx, const u8 *IDr,
+ size_t IDr_len, size_t *secret_len);
+ void *cb_ctx;
+ int unknown_user;
+};
+
+
+void ikev2_initiator_deinit(struct ikev2_initiator_data *data);
+int ikev2_initiator_process(struct ikev2_initiator_data *data,
+ const struct wpabuf *buf);
+struct wpabuf * ikev2_initiator_build(struct ikev2_initiator_data *data);
+
+#endif /* IKEV2_H */
Modified: wpasupplicant/branches/upstream/current/src/hlr_auc_gw/milenage.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/hlr_auc_gw/milenage.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/hlr_auc_gw/milenage.c (original)
+++ wpasupplicant/branches/upstream/current/src/hlr_auc_gw/milenage.c Tue Jan 1 13:50:28 2008
@@ -1,6 +1,6 @@
/*
* 3GPP AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208)
- * Copyright (c) 2006 <j at w1.fi>
+ * Copyright (c) 2006-2007 <j at 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
@@ -37,9 +37,10 @@
* @amf: AMF = 16-bit authentication management field
* @mac_a: Buffer for MAC-A = 64-bit network authentication code, or %NULL
* @mac_s: Buffer for MAC-S = 64-bit resync authentication code, or %NULL
+ * Returns: 0 on success, -1 on failure
*/
-static void milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
- const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s)
+static int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
+ const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s)
{
u8 tmp1[16], tmp2[16], tmp3[16];
int i;
@@ -47,7 +48,8 @@
/* tmp1 = TEMP = E_K(RAND XOR OP_C) */
for (i = 0; i < 16; i++)
tmp1[i] = _rand[i] ^ opc[i];
- aes_128_encrypt_block(k, tmp1, tmp1);
+ if (aes_128_encrypt_block(k, tmp1, tmp1))
+ return -1;
/* tmp2 = IN1 = SQN || AMF || SQN || AMF */
memcpy(tmp2, sqn, 6);
@@ -65,13 +67,15 @@
/* XOR with c1 (= ..00, i.e., NOP) */
/* f1 || f1* = E_K(tmp3) XOR OP_c */
- aes_128_encrypt_block(k, tmp3, tmp1);
+ if (aes_128_encrypt_block(k, tmp3, tmp1))
+ return -1;
for (i = 0; i < 16; i++)
tmp1[i] ^= opc[i];
if (mac_a)
memcpy(mac_a, tmp1, 8); /* f1 */
if (mac_s)
memcpy(mac_s, tmp1 + 8, 8); /* f1* */
+ return 0;
}
@@ -85,9 +89,10 @@
* @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL
* @ak: Buffer for AK = 48-bit anonymity key (f5), or %NULL
* @akstar: Buffer for AK = 48-bit anonymity key (f5*), or %NULL
+ * Returns: 0 on success, -1 on failure
*/
-static void milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
- u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar)
+static int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
+ u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar)
{
u8 tmp1[16], tmp2[16], tmp3[16];
int i;
@@ -95,7 +100,8 @@
/* tmp2 = TEMP = E_K(RAND XOR OP_C) */
for (i = 0; i < 16; i++)
tmp1[i] = _rand[i] ^ opc[i];
- aes_128_encrypt_block(k, tmp1, tmp2);
+ if (aes_128_encrypt_block(k, tmp1, tmp2))
+ return -1;
/* OUT2 = E_K(rot(TEMP XOR OP_C, r2) XOR c2) XOR OP_C */
/* OUT3 = E_K(rot(TEMP XOR OP_C, r3) XOR c3) XOR OP_C */
@@ -108,7 +114,8 @@
tmp1[i] = tmp2[i] ^ opc[i];
tmp1[15] ^= 1; /* XOR c2 (= ..01) */
/* f5 || f2 = E_K(tmp1) XOR OP_c */
- aes_128_encrypt_block(k, tmp1, tmp3);
+ if (aes_128_encrypt_block(k, tmp1, tmp3))
+ return -1;
for (i = 0; i < 16; i++)
tmp3[i] ^= opc[i];
if (res)
@@ -122,7 +129,8 @@
for (i = 0; i < 16; i++)
tmp1[(i + 12) % 16] = tmp2[i] ^ opc[i];
tmp1[15] ^= 2; /* XOR c3 (= ..02) */
- aes_128_encrypt_block(k, tmp1, ck);
+ if (aes_128_encrypt_block(k, tmp1, ck))
+ return -1;
for (i = 0; i < 16; i++)
ck[i] ^= opc[i];
}
@@ -133,7 +141,8 @@
for (i = 0; i < 16; i++)
tmp1[(i + 8) % 16] = tmp2[i] ^ opc[i];
tmp1[15] ^= 4; /* XOR c4 (= ..04) */
- aes_128_encrypt_block(k, tmp1, ik);
+ if (aes_128_encrypt_block(k, tmp1, ik))
+ return -1;
for (i = 0; i < 16; i++)
ik[i] ^= opc[i];
}
@@ -144,10 +153,13 @@
for (i = 0; i < 16; i++)
tmp1[(i + 4) % 16] = tmp2[i] ^ opc[i];
tmp1[15] ^= 8; /* XOR c5 (= ..08) */
- aes_128_encrypt_block(k, tmp1, tmp1);
+ if (aes_128_encrypt_block(k, tmp1, tmp1))
+ return -1;
for (i = 0; i < 6; i++)
akstar[i] = tmp1[i] ^ opc[i];
}
+
+ return 0;
}
@@ -175,9 +187,12 @@
*res_len = 0;
return;
}
+ if (milenage_f1(opc, k, _rand, sqn, amf, mac_a, NULL) ||
+ milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL)) {
+ *res_len = 0;
+ return;
+ }
*res_len = 8;
- milenage_f1(opc, k, _rand, sqn, amf, mac_a, NULL);
- milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL);
/* AUTN = (SQN ^ AK) || AMF || MAC */
for (i = 0; i < 6; i++)
@@ -203,11 +218,12 @@
u8 ak[6], mac_s[8];
int i;
- milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak);
+ if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
+ return -1;
for (i = 0; i < 6; i++)
sqn[i] = auts[i] ^ ak[i];
- milenage_f1(opc, k, _rand, sqn, amf, NULL, mac_s);
- if (memcmp(mac_s, auts + 6, 8) != 0)
+ if (milenage_f1(opc, k, _rand, sqn, amf, NULL, mac_s) ||
+ memcmp(mac_s, auts + 6, 8) != 0)
return -1;
return 0;
}
@@ -220,14 +236,15 @@
* @_rand: RAND = 128-bit random challenge
* @sres: Buffer for SRES = 32-bit SRES
* @kc: Buffer for Kc = 64-bit Kc
+ * Returns: 0 on success, -1 on failure
*/
-void gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres,
- u8 *kc)
+int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc)
{
u8 res[8], ck[16], ik[16];
int i;
- milenage_f2345(opc, k, _rand, res, ck, ik, NULL, NULL);
+ if (milenage_f2345(opc, k, _rand, res, ck, ik, NULL, NULL))
+ return -1;
for (i = 0; i < 8; i++)
kc[i] = ck[i] ^ ck[i + 8] ^ ik[i] ^ ik[i + 8];
@@ -238,6 +255,7 @@
for (i = 0; i < 4; i++)
sres[i] = res[i] ^ res[i + 4];
#endif /* GSM_MILENAGE_ALT_SRES */
+ return 0;
}
@@ -953,8 +971,8 @@
ret++;
}
- milenage_f1(opc, t->k, t->rand, t->sqn, t->amf, buf, buf2);
- if (memcmp(buf, t->f1, 8) != 0) {
+ if (milenage_f1(opc, t->k, t->rand, t->sqn, t->amf, buf, buf2)
+ || memcmp(buf, t->f1, 8) != 0) {
printf("- milenage_f1 failed\n");
ret++;
}
@@ -963,9 +981,9 @@
ret++;
}
- milenage_f2345(opc, t->k, t->rand, buf, buf2, buf3, buf4,
- buf5);
- if (memcmp(buf, t->f2, 8) != 0) {
+ if (milenage_f2345(opc, t->k, t->rand, buf, buf2, buf3, buf4,
+ buf5) ||
+ memcmp(buf, t->f2, 8) != 0) {
printf("- milenage_f2 failed\n");
ret++;
}
Modified: wpasupplicant/branches/upstream/current/src/hlr_auc_gw/milenage.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/hlr_auc_gw/milenage.h?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/hlr_auc_gw/milenage.h (original)
+++ wpasupplicant/branches/upstream/current/src/hlr_auc_gw/milenage.h Tue Jan 1 13:50:28 2008
@@ -1,6 +1,6 @@
/*
* UMTS AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208)
- * Copyright (c) 2006 <j at w1.fi>
+ * Copyright (c) 2006-2007 <j at 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
@@ -20,7 +20,7 @@
u8 *ck, u8 *res, size_t *res_len);
int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts,
u8 *sqn);
-void gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres,
- u8 *kc);
+int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres,
+ u8 *kc);
#endif /* MILENAGE_H */
Modified: wpasupplicant/branches/upstream/current/src/tls/bignum.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/tls/bignum.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/tls/bignum.c (original)
+++ wpasupplicant/branches/upstream/current/src/tls/bignum.c Tue Jan 1 13:50:28 2008
@@ -227,4 +227,4 @@
return -1;
}
return 0;
-}
+}
Modified: wpasupplicant/branches/upstream/current/src/tls/tlsv1_client_write.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/tls/tlsv1_client_write.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/tls/tlsv1_client_write.c (original)
+++ wpasupplicant/branches/upstream/current/src/tls/tlsv1_client_write.c Tue Jan 1 13:50:28 2008
@@ -254,10 +254,16 @@
os_free(csecret);
return -1;
}
- crypto_mod_exp(conn->dh_g, conn->dh_g_len,
- csecret_start, csecret_len,
- conn->dh_p, conn->dh_p_len,
- dh_yc, &dh_yc_len);
+ if (crypto_mod_exp(conn->dh_g, conn->dh_g_len,
+ csecret_start, csecret_len,
+ conn->dh_p, conn->dh_p_len,
+ dh_yc, &dh_yc_len)) {
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_INTERNAL_ERROR);
+ os_free(csecret);
+ os_free(dh_yc);
+ return -1;
+ }
wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)",
dh_yc, dh_yc_len);
@@ -289,10 +295,16 @@
}
/* shared = Ys^csecret mod p */
- crypto_mod_exp(conn->dh_ys, conn->dh_ys_len,
- csecret_start, csecret_len,
- conn->dh_p, conn->dh_p_len,
- shared, &shared_len);
+ if (crypto_mod_exp(conn->dh_ys, conn->dh_ys_len,
+ csecret_start, csecret_len,
+ conn->dh_p, conn->dh_p_len,
+ shared, &shared_len)) {
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_INTERNAL_ERROR);
+ os_free(csecret);
+ os_free(shared);
+ return -1;
+ }
wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange",
shared, shared_len);
Modified: wpasupplicant/branches/upstream/current/src/tls/tlsv1_server_read.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/tls/tlsv1_server_read.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/tls/tlsv1_server_read.c (original)
+++ wpasupplicant/branches/upstream/current/src/tls/tlsv1_server_read.c Tue Jan 1 13:50:28 2008
@@ -639,9 +639,15 @@
}
/* shared = Yc^secret mod p */
- crypto_mod_exp(dh_yc, dh_yc_len, conn->dh_secret, conn->dh_secret_len,
- conn->cred->dh_p, conn->cred->dh_p_len,
- shared, &shared_len);
+ if (crypto_mod_exp(dh_yc, dh_yc_len, conn->dh_secret,
+ conn->dh_secret_len,
+ conn->cred->dh_p, conn->cred->dh_p_len,
+ shared, &shared_len)) {
+ os_free(shared);
+ tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_INTERNAL_ERROR);
+ return -1;
+ }
wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange",
shared, shared_len);
Modified: wpasupplicant/branches/upstream/current/src/tls/tlsv1_server_write.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/tls/tlsv1_server_write.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/tls/tlsv1_server_write.c (original)
+++ wpasupplicant/branches/upstream/current/src/tls/tlsv1_server_write.c Tue Jan 1 13:50:28 2008
@@ -325,10 +325,15 @@
TLS_ALERT_INTERNAL_ERROR);
return -1;
}
- crypto_mod_exp(conn->cred->dh_g, conn->cred->dh_g_len,
- conn->dh_secret, conn->dh_secret_len,
- conn->cred->dh_p, conn->cred->dh_p_len,
- dh_ys, &dh_ys_len);
+ if (crypto_mod_exp(conn->cred->dh_g, conn->cred->dh_g_len,
+ conn->dh_secret, conn->dh_secret_len,
+ conn->cred->dh_p, conn->cred->dh_p_len,
+ dh_ys, &dh_ys_len)) {
+ tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_INTERNAL_ERROR);
+ os_free(dh_ys);
+ return -1;
+ }
wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)",
dh_ys, dh_ys_len);
Modified: wpasupplicant/branches/upstream/current/src/utils/common.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/utils/common.h?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/utils/common.h (original)
+++ wpasupplicant/branches/upstream/current/src/utils/common.h Tue Jan 1 13:50:28 2008
@@ -402,6 +402,13 @@
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 hexstr2bin(const char *hex, u8 *buf, size_t len);
Modified: wpasupplicant/branches/upstream/current/src/utils/wpabuf.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/utils/wpabuf.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/utils/wpabuf.c (original)
+++ wpasupplicant/branches/upstream/current/src/utils/wpabuf.c Tue Jan 1 13:50:28 2008
@@ -65,7 +65,6 @@
if (buf == NULL)
return NULL;
buf->size = len;
- buf->refcount = 1;
return buf;
}
@@ -78,7 +77,6 @@
buf->size = len;
buf->used = len;
- buf->refcount = 1;
buf->ext_data = data;
return buf;
@@ -111,9 +109,7 @@
{
if (buf == NULL)
return;
- buf->refcount--;
- if (buf->refcount > 0)
- return;
+ os_free(buf->ext_data);
os_free(buf);
}
Modified: wpasupplicant/branches/upstream/current/src/utils/wpabuf.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/utils/wpabuf.h?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/src/utils/wpabuf.h (original)
+++ wpasupplicant/branches/upstream/current/src/utils/wpabuf.h Tue Jan 1 13:50:28 2008
@@ -23,7 +23,6 @@
struct wpabuf {
size_t size; /* total size of the allocated buffer */
size_t used; /* length of data in the buffer */
- size_t refcount; /* number of users referencing this buffer */
u8 *ext_data; /* pointer to external data; NULL if data follows
* struct wpabuf */
/* optionally followed by the allocated buffer */
@@ -60,6 +59,16 @@
}
/**
+ * 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
@@ -91,12 +100,6 @@
static inline u8 * wpabuf_mhead_u8(struct wpabuf *buf)
{
return wpabuf_mhead(buf);
-}
-
-static inline struct wpabuf * wpabuf_ref(struct wpabuf *buf)
-{
- buf->refcount++;
- return buf;
}
static inline void wpabuf_put_u8(struct wpabuf *buf, u8 data)
Added: wpasupplicant/branches/upstream/current/src/wps/.gitignore
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/wps/.gitignore?rev=967&op=file
==============================================================================
--- wpasupplicant/branches/upstream/current/src/wps/.gitignore (added)
+++ wpasupplicant/branches/upstream/current/src/wps/.gitignore Tue Jan 1 13:50:28 2008
@@ -1,0 +1,1 @@
+*.d
Added: wpasupplicant/branches/upstream/current/src/wps/Makefile
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/wps/Makefile?rev=967&op=file
==============================================================================
--- wpasupplicant/branches/upstream/current/src/wps/Makefile (added)
+++ wpasupplicant/branches/upstream/current/src/wps/Makefile Tue Jan 1 13:50:28 2008
@@ -1,0 +1,6 @@
+all:
+ @echo Nothing to be made.
+
+clean:
+ for d in $(SUBDIRS); do make -C $$d clean; done
+ rm -f *~ *.o *.d
Added: wpasupplicant/branches/upstream/current/src/wps/wps.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/wps/wps.c?rev=967&op=file
==============================================================================
--- wpasupplicant/branches/upstream/current/src/wps/wps.c (added)
+++ wpasupplicant/branches/upstream/current/src/wps/wps.c Tue Jan 1 13:50:28 2008
@@ -1,0 +1,146 @@
+/*
+ * Wi-Fi Protected Setup
+ * Copyright (c) 2007, Jouni Malinen <j at w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "wps.h"
+
+
+struct wps_data {
+ int authenticator;
+ int registrar;
+ int msg_num;
+};
+
+
+struct wps_data * wps_init(int authenticator, int registrar)
+{
+ struct wps_data *data = os_zalloc(sizeof(*data));
+ if (data == NULL)
+ return NULL;
+ data->authenticator = authenticator;
+ data->registrar = registrar;
+ data->msg_num = 1;
+ return data;
+}
+
+
+void wps_deinit(struct wps_data *data)
+{
+ os_free(data);
+}
+
+
+enum wps_process_res wps_process_msg(struct wps_data *wps, u8 op_code,
+ const struct wpabuf *msg)
+{
+ /* TODO: proper processing and/or sending to an external process */
+
+ wpa_hexdump_buf(MSG_MSGDUMP, "WPS: Received message", msg);
+ if ((wps->registrar && (wps->msg_num & 1) == 0) ||
+ (!wps->registrar && (wps->msg_num & 1) == 1)) {
+ wpa_printf(MSG_DEBUG, "WPS: Unexpected message number %d",
+ wps->msg_num);
+ return WPS_FAILURE;
+ }
+
+ if (wps->msg_num <= 8 && op_code == WSC_MSG) {
+ wpa_printf(MSG_DEBUG, "WPS: Process M%d", wps->msg_num);
+ } else if (wps->registrar && wps->msg_num == 3 &&
+ op_code == WSC_ACK) {
+ wpa_printf(MSG_DEBUG, "WPS: Process ACK to M2/M2D");
+ /* could send out next M2/M2D */
+ return WPS_DONE;
+ } else if (wps->registrar && wps->msg_num == 3 &&
+ op_code == WSC_Done) {
+ wpa_printf(MSG_DEBUG, "WPS: Process Done to M2/M2D");
+ return WPS_DONE;
+ } else if (wps->msg_num <= 8 && op_code == WSC_Done) {
+ wpa_printf(MSG_DEBUG, "WPS: Process Done prior to completion");
+ return WPS_DONE;
+ } else if (wps->msg_num <= 8 && op_code == WSC_ACK) {
+ wpa_printf(MSG_DEBUG, "WPS: Process ACK prior to completion");
+ return WPS_DONE;
+ } else if (wps->msg_num <= 8 && op_code == WSC_NACK) {
+ wpa_printf(MSG_DEBUG, "WPS: Process NACK prior to completion");
+ return WPS_DONE;
+ } else if (wps->registrar && wps->msg_num == 9 &&
+ op_code == WSC_Done) {
+ wpa_printf(MSG_DEBUG, "WPS: Process Done");
+ if (wps->authenticator)
+ return WPS_DONE;
+ } else if (!wps->registrar && wps->msg_num == 10 &&
+ op_code == WSC_ACK) {
+ wpa_printf(MSG_DEBUG, "WPS: Process ACK");
+ return WPS_DONE;
+ } else {
+ wpa_printf(MSG_DEBUG, "WPS: Unexpected Op-Code %d "
+ "(msg_num=%d)", op_code, wps->msg_num);
+ return WPS_FAILURE;
+ }
+
+ wps->msg_num++;
+ return WPS_CONTINUE;
+}
+
+
+struct wpabuf * wps_get_msg(struct wps_data *wps, u8 *op_code)
+{
+ struct wpabuf *msg;
+
+ /* TODO: proper processing and/or query from an external process */
+
+ if ((wps->registrar && (wps->msg_num & 1) == 1) ||
+ (!wps->registrar && (wps->msg_num & 1) == 0)) {
+ wpa_printf(MSG_DEBUG, "WPS: Unexpected request for message "
+ "number %d", wps->msg_num);
+ return NULL;
+ }
+
+ if (wps->msg_num == 7 || wps->msg_num == 8) {
+ msg = wpabuf_alloc(2000);
+ if (msg == NULL)
+ return NULL;
+ *op_code = WSC_MSG;
+ wpabuf_put_u8(msg, WSC_MSG);
+ wpabuf_put(msg, 1999);
+ wpa_printf(MSG_DEBUG, "WPS: Send M%d", wps->msg_num);
+ } else if (wps->msg_num <= 6) {
+ msg = wpabuf_alloc(1);
+ if (msg == NULL)
+ return NULL;
+ *op_code = WSC_MSG;
+ wpabuf_put_u8(msg, WSC_MSG);
+ wpa_printf(MSG_DEBUG, "WPS: Send M%d", wps->msg_num);
+ } else if (!wps->registrar && wps->msg_num == 9) {
+ msg = wpabuf_alloc(1);
+ if (msg == NULL)
+ return NULL;
+ *op_code = WSC_Done;
+ wpabuf_put_u8(msg, WSC_Done);
+ wpa_printf(MSG_DEBUG, "WPS: Send Done");
+ } else if (wps->registrar && wps->msg_num == 10) {
+ msg = wpabuf_alloc(1);
+ if (msg == NULL)
+ return NULL;
+ *op_code = WSC_ACK;
+ wpabuf_put_u8(msg, WSC_ACK);
+ wpa_printf(MSG_DEBUG, "WPS: Send ACK");
+ } else
+ return NULL;
+
+ wps->msg_num++;
+ return msg;
+}
Added: wpasupplicant/branches/upstream/current/src/wps/wps.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/src/wps/wps.h?rev=967&op=file
==============================================================================
--- wpasupplicant/branches/upstream/current/src/wps/wps.h (added)
+++ wpasupplicant/branches/upstream/current/src/wps/wps.h Tue Jan 1 13:50:28 2008
@@ -1,0 +1,41 @@
+/*
+ * Wi-Fi Protected Setup
+ * Copyright (c) 2007, Jouni Malinen <j at 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 WPS_H
+#define WPS_H
+
+enum wsc_op_code {
+ WSC_Start = 0x01,
+ WSC_ACK = 0x02,
+ WSC_NACK = 0x03,
+ WSC_MSG = 0x04,
+ WSC_Done = 0x05,
+ WSC_FRAG_ACK = 0x06
+};
+
+
+struct wps_data * wps_init(int authenticator, int registrar);
+
+void wps_deinit(struct wps_data *data);
+
+enum wps_process_res {
+ WPS_DONE, WPS_CONTINUE, WPS_FAILURE, WPS_PENDING
+};
+enum wps_process_res wps_process_msg(struct wps_data *wps, u8 op_code,
+ const struct wpabuf *msg);
+
+struct wpabuf * wps_get_msg(struct wps_data *wps, u8 *op_code);
+
+
+#endif /* WPS_H */
Modified: wpasupplicant/branches/upstream/current/wpa_supplicant/ChangeLog
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/wpa_supplicant/ChangeLog?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/wpa_supplicant/ChangeLog (original)
+++ wpasupplicant/branches/upstream/current/wpa_supplicant/ChangeLog Tue Jan 1 13:50:28 2008
@@ -34,6 +34,15 @@
are converted internally to the new format), but all drivers should
start using the new get_scan_results2() to make them more likely to
work with new features
+ * Qt4 version of wpa_gui (wpa_gui-qt4 subdirectory) is now native Qt4
+ application, i.e., it does not require Qt3Support anymore; Windows
+ binary of wpa_gui.exe is now from this directory and only requires
+ QtCore4.dll and QtGui4.dll libraries
+ * updated Windows binary build to use Qt 4.3.3 and made Qt DLLs
+ available as a separate package to make wpa_gui installation easier:
+ http://w1.fi/wpa_supplicant/qt4/wpa_gui-qt433-windows-dll.zip
+ * added support for EAP-IKEv2 (draft-tschofenig-eap-ikev2-15.txt);
+ only shared key/password authentication is supported in this version
2007-11-24 - v0.6.1
* added support for configuring password as NtPasswordHash
Modified: wpasupplicant/branches/upstream/current/wpa_supplicant/Makefile
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/wpa_supplicant/Makefile?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/wpa_supplicant/Makefile (original)
+++ wpasupplicant/branches/upstream/current/wpa_supplicant/Makefile Tue Jan 1 13:50:28 2008
@@ -482,9 +482,25 @@
else
CFLAGS += -DEAP_WSC
OBJS += ../src/eap_peer/eap_wsc.o ../src/eap_common/eap_wsc_common.o
+OBJS += ../src/wps/wps.o
OBJS_h += ../src/eap_server/eap_wsc.o
endif
CONFIG_IEEE8021X_EAPOL=y
+endif
+
+ifdef CONFIG_EAP_IKEV2
+# EAP-IKEv2
+ifeq ($(CONFIG_EAP_IKEV2), dyn)
+CFLAGS += -DEAP_IKEV2_DYNAMIC
+EAPDYN += ../src/eap_peer/eap_ikev2.so ../src/eap_peer/ikev2.o
+EAPDYN += ../src/eap_common/eap_ikev2_common.o ../src/eap_common/ikev2_common.o
+else
+CFLAGS += -DEAP_IKEV2
+OBJS += ../src/eap_peer/eap_ikev2.o ../src/eap_peer/ikev2.o
+OBJS += ../src/eap_common/eap_ikev2_common.o ../src/eap_common/ikev2_common.o
+endif
+CONFIG_IEEE8021X_EAPOL=y
+NEED_DH_GROUPS=y
endif
ifdef CONFIG_EAP_VENDOR_TEST
@@ -882,6 +898,10 @@
OBJS += ../src/crypto/aes_wrap.o ../src/crypto/aes.o
endif
+ifdef NEED_DH_GROUPS
+OBJS += ../src/crypto/dh_groups.o
+endif
+
ifndef NEED_FIPS186_2_PRF
CFLAGS += -DCONFIG_NO_FIPS186_2_PRF
endif
@@ -910,19 +930,20 @@
ifdef CONFIG_DEBUG_FILE
CFLAGS += -DCONFIG_DEBUG_FILE
endif
+
+OBJS += ../src/drivers/scan_helpers.o
OBJS_wpa_rm := ctrl_iface.o mlme.o ctrl_iface_unix.o
OBJS_wpa := $(filter-out $(OBJS_wpa_rm),$(OBJS)) $(OBJS_h) tests/test_wpa.o
ifdef CONFIG_AUTHENTICATOR
OBJS_wpa += tests/link_test.o
endif
+OBJS_wpa += $(OBJS_l2)
OBJS += wpa_supplicant.o events.o blacklist.o wpas_glue.o scan.o
-OBJS_t := $(OBJS) eapol_test.o ../src/radius/radius.o ../src/radius/radius_client.o
+OBJS_t := $(OBJS) $(OBJS_l2) eapol_test.o ../src/radius/radius.o ../src/radius/radius_client.o
OBJS_t += ../src/utils/ip_addr.o
-OBJS_t2 := $(OBJS) preauth_test.o
+OBJS_t2 := $(OBJS) $(OBJS_l2) preauth_test.o
OBJS += $(CONFIG_MAIN).o
-
-OBJS += ../src/drivers/scan_helpers.o
ifdef CONFIG_PRIVSEP
OBJS_priv += $(OBJS_d) ../src/drivers/drivers.o ../src/drivers/scan_helpers.o
@@ -1029,9 +1050,13 @@
$(CC) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
-Deap_peer_sake_register=eap_peer_method_dynamic_init
-eap_wsc.so: ../src/eap_peer/eap_wsc.c ../src/eap_common/eap_wsc_common.c
+eap_wsc.so: ../src/eap_peer/eap_wsc.c ../src/eap_common/eap_wsc_common.c ../src/wps/wps.c
$(CC) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
-Deap_peer_wsc_register=eap_peer_method_dynamic_init
+
+eap_ikev2.so: ../src/eap_peer/eap_ikev2.c ../src/eap_peer/ikev2.c ../src/eap_common/eap_ikev2_common.o ../src/eap_common/ikev2_common.c
+ $(CC) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
+ -Deap_peer_ikev2_register=eap_peer_method_dynamic_init
%.so: %.c
$(CC) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $< \
@@ -1060,6 +1085,12 @@
wpa_gui: wpa_gui/Makefile
$(MAKE) -C wpa_gui
+wpa_gui-qt4/Makefile:
+ qmake -o wpa_gui-qt4/Makefile wpa_gui-qt4/wpa_gui.pro
+
+wpa_gui-qt4: wpa_gui-qt4/Makefile
+ $(MAKE) -C wpa_gui-qt4
+
TEST_MS_FUNCS_OBJS = ../src/crypto/crypto_openssl.o ../src/crypto/sha1.o ../src/crypto/md5.o \
../src/utils/os_unix.o ../src/crypto/rc4.o tests/test_ms_funcs.o
test-ms_funcs: $(TEST_MS_FUNCS_OBJS)
Modified: wpasupplicant/branches/upstream/current/wpa_supplicant/README
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/wpa_supplicant/README?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/wpa_supplicant/README (original)
+++ wpasupplicant/branches/upstream/current/wpa_supplicant/README Tue Jan 1 13:50:28 2008
@@ -90,6 +90,7 @@
* EAP-PSK
* EAP-PAX
* EAP-SAKE
+ * EAP-IKEv2
* EAP-GPSK
* LEAP (note: requires special support from the driver for IEEE 802.11
authentication)
@@ -383,6 +384,7 @@
CONFIG_EAP_GPSK=y
CONFIG_EAP_PAX=y
CONFIG_EAP_LEAP=y
+CONFIG_EAP_IKEV2=y
Following option can be used to include GSM SIM/USIM interface for GSM/UMTS
authentication algorithm (for EAP-SIM/EAP-AKA). This requires pcsc-lite
@@ -437,6 +439,7 @@
CONFIG_EAP_GPSK=y
CONFIG_EAP_PAX=y
CONFIG_EAP_LEAP=y
+CONFIG_EAP_IKEV2=y
CONFIG_PCSC=y
EAP-PEAP and EAP-TTLS will automatically include configured EAP
Modified: wpasupplicant/branches/upstream/current/wpa_supplicant/README-Windows.txt
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/wpa_supplicant/README-Windows.txt?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/wpa_supplicant/README-Windows.txt (original)
+++ wpasupplicant/branches/upstream/current/wpa_supplicant/README-Windows.txt Tue Jan 1 13:50:28 2008
@@ -38,8 +38,14 @@
--------------
Compiled binary version of the wpa_supplicant and additional tools is
-available from http://hostap.epitest.fi/wpa_supplicant/. These
-binaries can be used after installing WinPcap.
+available from http://w1.fi/wpa_supplicant/. These binaries can be
+used after installing WinPcap.
+
+wpa_gui uses Qt 4 framework and may need additional dynamic libraries
+(DLLs). These libraries are available from
+http://w1.fi/wpa_supplicant/qt4/wpa_gui-qt433-windows-dll.zip
+You can copy the DLL files from this ZIP package into the same directory
+with wpa_gui.exe to allow wpa_gui to be started.
Building wpa_supplicant with mingw
@@ -135,8 +141,8 @@
Using wpa_supplicant for Windows
--------------------------------
-wpa_supplicant and wpa_cli behave more or less identically to Linux
-version, so instructions in README and example wpa_supplicant.conf
+wpa_supplicant, wpa_cli, and wpa_gui behave more or less identically to
+Linux version, so instructions in README and example wpa_supplicant.conf
should be applicable for most parts. In addition, there is another
version of wpa_supplicant, wpasvc.exe, which can be used as a Windows
service and which reads its configuration from registry instead of
@@ -429,3 +435,14 @@
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
+
+
+
+ Qt Open Source Edition
+ ----------------------
+
+The Qt GUI Toolkit is Copyright (C) 1994-2007 Trolltech ASA.
+Qt Open Source Edition is licensed under GPL version 2.
+
+Source code for the library is available at
+http://w1.fi/wpa_supplicant/qt4/qt-win-opensource-src-4.3.3.zip
Modified: wpasupplicant/branches/upstream/current/wpa_supplicant/defconfig
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/wpa_supplicant/defconfig?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/wpa_supplicant/defconfig (original)
+++ wpasupplicant/branches/upstream/current/wpa_supplicant/defconfig Tue Jan 1 13:50:28 2008
@@ -166,6 +166,9 @@
# EAP-WSC for Wi-Fi Protected Setup
#CONFIG_EAP_WSC=y
+
+# EAP-IKEv2
+#CONFIG_EAP_IKEV2=y
# PKCS#12 (PFX) support (used to read private key and certificate file from
# a file that usually has extension .p12 or .pfx)
Modified: wpasupplicant/branches/upstream/current/wpa_supplicant/events.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/wpa_supplicant/events.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/wpa_supplicant/events.c (original)
+++ wpasupplicant/branches/upstream/current/wpa_supplicant/events.c Tue Jan 1 13:50:28 2008
@@ -394,7 +394,7 @@
wpa_printf(MSG_DEBUG, "%d: " MACSTR " ssid='%s' "
"wpa_ie_len=%u rsn_ie_len=%u caps=0x%x",
- i, MAC2STR(bss->bssid),
+ (int) i, MAC2STR(bss->bssid),
wpa_ssid_txt(ssid_, ssid_len),
wpa_ie_len, rsn_ie_len, bss->caps);
e = wpa_blacklist_get(wpa_s, bss->bssid);
@@ -458,7 +458,7 @@
wpa_printf(MSG_DEBUG, "%d: " MACSTR " ssid='%s' "
"wpa_ie_len=%u rsn_ie_len=%u caps=0x%x",
- i, MAC2STR(bss->bssid),
+ (int) i, MAC2STR(bss->bssid),
wpa_ssid_txt(ssid_, ssid_len),
wpa_ie_len, rsn_ie_len, bss->caps);
e = wpa_blacklist_get(wpa_s, bss->bssid);
Modified: wpasupplicant/branches/upstream/current/wpa_supplicant/vs2005/eapol_test/eapol_test.vcproj
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/wpa_supplicant/vs2005/eapol_test/eapol_test.vcproj?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/wpa_supplicant/vs2005/eapol_test/eapol_test.vcproj (original)
+++ wpasupplicant/branches/upstream/current/wpa_supplicant/vs2005/eapol_test/eapol_test.vcproj Tue Jan 1 13:50:28 2008
@@ -195,6 +195,10 @@
>
</File>
<File
+ RelativePath="..\..\..\src\eap_common\chap.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\utils\common.c"
>
</File>
@@ -352,6 +356,10 @@
</File>
<File
RelativePath="..\..\scan.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\drivers\scan_helpers.c"
>
</File>
<File
Modified: wpasupplicant/branches/upstream/current/wpa_supplicant/vs2005/wpa_supplicant/wpa_supplicant.vcproj
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/wpa_supplicant/vs2005/wpa_supplicant/wpa_supplicant.vcproj?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/wpa_supplicant/vs2005/wpa_supplicant/wpa_supplicant.vcproj (original)
+++ wpasupplicant/branches/upstream/current/wpa_supplicant/vs2005/wpa_supplicant/wpa_supplicant.vcproj Tue Jan 1 13:50:28 2008
@@ -195,6 +195,10 @@
>
</File>
<File
+ RelativePath="..\..\..\src\eap_common\chap.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\utils\common.c"
>
</File>
@@ -348,6 +352,10 @@
</File>
<File
RelativePath="..\..\scan.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\drivers\scan_helpers.c"
>
</File>
<File
Modified: wpasupplicant/branches/upstream/current/wpa_supplicant/vs2005/wpasvc/wpasvc.vcproj
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/wpa_supplicant/vs2005/wpasvc/wpasvc.vcproj?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/wpa_supplicant/vs2005/wpasvc/wpasvc.vcproj (original)
+++ wpasupplicant/branches/upstream/current/wpa_supplicant/vs2005/wpasvc/wpasvc.vcproj Tue Jan 1 13:50:28 2008
@@ -195,6 +195,10 @@
>
</File>
<File
+ RelativePath="..\..\..\src\eap_common\chap.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\utils\common.c"
>
</File>
@@ -348,6 +352,10 @@
</File>
<File
RelativePath="..\..\scan.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\drivers\scan_helpers.c"
>
</File>
<File
Modified: wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui-qt4/setup-mingw-cross-compiling
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui-qt4/setup-mingw-cross-compiling?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui-qt4/setup-mingw-cross-compiling (original)
+++ wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui-qt4/setup-mingw-cross-compiling Tue Jan 1 13:50:28 2008
@@ -4,8 +4,8 @@
# and I have no idea how to change these. For now, just override the
# directories in the Makefile.Release file after qmake run.
-qmake -spec /q/jm/qt4-win/4.0.0/mkspecs/win32-g++ wpa_gui.pro -o Makefile
+qmake -spec /q/jm/qt4-win/4.3.3/mkspecs/win32-g++ wpa_gui.pro -o Makefile
cat Makefile.Release |
- sed s%qt4/lib%qt4-win/4.0.0/lib%g |
- sed s%qt4/include%qt4-win/4.0.0/include%g > tmp.Makefile.Release &&
+ sed s%/usr/lib/qt4%/q/jm/qt4-win/4.3.3/lib%g |
+ sed s%/usr/include/qt4%/q/jm/qt4-win/4.3.3/include%g > tmp.Makefile.Release &&
mv -f tmp.Makefile.Release Makefile.Release
Modified: wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui-qt4/wpagui.cpp
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui-qt4/wpagui.cpp?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui-qt4/wpagui.cpp (original)
+++ wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui-qt4/wpagui.cpp Tue Jan 1 13:50:28 2008
@@ -1,6 +1,6 @@
/*
* wpa_gui - WpaGui class
- * Copyright (c) 2005-2006, Jouni Malinen <j at w1.fi>
+ * Copyright (c) 2005-2007, Jouni Malinen <j at 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
@@ -32,21 +32,21 @@
(void) statusBar();
- connect(helpIndexAction, SIGNAL(activated()), this, SLOT(helpIndex()));
- connect(helpContentsAction, SIGNAL(activated()), this,
+ connect(helpIndexAction, SIGNAL(triggered()), this, SLOT(helpIndex()));
+ connect(helpContentsAction, SIGNAL(triggered()), this,
SLOT(helpContents()));
- connect(helpAboutAction, SIGNAL(activated()), this, SLOT(helpAbout()));
- connect(fileExitAction, SIGNAL(activated()), this, SLOT(exitApp()));
+ connect(helpAboutAction, SIGNAL(triggered()), this, SLOT(helpAbout()));
+ connect(fileExitAction, SIGNAL(triggered()), this, SLOT(exitApp()));
connect(disconnectButton, SIGNAL(clicked()), this, SLOT(disconnect()));
connect(scanButton, SIGNAL(clicked()), this, SLOT(scan()));
connect(connectButton, SIGNAL(clicked()), this, SLOT(connectB()));
- connect(fileEventHistoryAction, SIGNAL(activated()), this,
+ connect(fileEventHistoryAction, SIGNAL(triggered()), this,
SLOT(eventHistory()));
connect(networkSelect, SIGNAL(activated(const QString&)), this,
SLOT(selectNetwork(const QString&)));
- connect(fileEdit_networkAction, SIGNAL(activated()), this,
+ connect(fileEdit_networkAction, SIGNAL(triggered()), this,
SLOT(editNetwork()));
- connect(fileAdd_NetworkAction, SIGNAL(activated()), this,
+ connect(fileAdd_NetworkAction, SIGNAL(triggered()), this,
SLOT(addNetwork()));
connect(adapterSelect, SIGNAL(activated(const QString&)), this,
SLOT(selectAdapter(const QString&)));
@@ -512,7 +512,7 @@
void WpaGui::helpAbout()
{
QMessageBox::about(this, "wpa_gui for wpa_supplicant",
- "Copyright (c) 2003-2006,\n"
+ "Copyright (c) 2003-2007,\n"
"Jouni Malinen <j at w1.fi>\n"
"and contributors.\n"
"\n"
Modified: wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui-qt4/wpamsg.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui-qt4/wpamsg.h?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui-qt4/wpamsg.h (original)
+++ wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui-qt4/wpamsg.h Tue Jan 1 13:50:28 2008
@@ -20,7 +20,6 @@
class WpaMsg {
public:
- WpaMsg() {}
WpaMsg(const QString &_msg, int _priority = 2)
: msg(_msg), priority(_priority)
{
Modified: wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui/wpamsg.h
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui/wpamsg.h?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui/wpamsg.h (original)
+++ wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_gui/wpamsg.h Tue Jan 1 13:50:28 2008
@@ -14,7 +14,6 @@
class WpaMsg {
public:
- WpaMsg() {}
WpaMsg(const QString &_msg, int _priority = 2)
: msg(_msg), priority(_priority)
{
Modified: wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_supplicant.c
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_supplicant.c?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_supplicant.c (original)
+++ wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_supplicant.c Tue Jan 1 13:50:28 2008
@@ -1298,17 +1298,24 @@
*/
int wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s)
{
+ int ret;
+
if (wpa_s->use_client_mlme || wpa_s->driver->get_scan_results2 == NULL)
- return wpa_supplicant_get_scan_results_old(wpa_s);
-
- wpa_scan_results_free(wpa_s->scan_res);
- wpa_s->scan_res = wpa_drv_get_scan_results2(wpa_s);
- if (wpa_s->scan_res == NULL) {
- wpa_printf(MSG_DEBUG, "Failed to get scan results");
- return -1;
- }
-
- return 0;
+ ret = wpa_supplicant_get_scan_results_old(wpa_s);
+ else {
+ wpa_scan_results_free(wpa_s->scan_res);
+ wpa_s->scan_res = wpa_drv_get_scan_results2(wpa_s);
+ if (wpa_s->scan_res == NULL) {
+ wpa_printf(MSG_DEBUG, "Failed to get scan results");
+ ret = -1;
+ } else
+ ret = 0;
+ }
+
+ if (wpa_s->scan_res)
+ wpa_scan_sort_results(wpa_s->scan_res);
+
+ return ret;
}
Modified: wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_supplicant.conf
URL: http://svn.debian.org/wsvn/wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_supplicant.conf?rev=967&op=diff
==============================================================================
--- wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_supplicant.conf (original)
+++ wpasupplicant/branches/upstream/current/wpa_supplicant/wpa_supplicant.conf Tue Jan 1 13:50:28 2008
@@ -620,6 +620,15 @@
password="foobar"
}
+# EAP-IKEv2 using shared secrets for both server and peer authentication
+network={
+ ssid="ikev2-example"
+ key_mgmt=WPA-EAP
+ eap=IKEV2
+ identity="user"
+ password="foobar"
+}
+
# EAP-FAST with WPA (WPA or WPA2)
network={
ssid="eap-fast-test"
More information about the Pkg-wpa-devel
mailing list