Cumulative patch from commit 3e7f1c7980c6e9fc7173f78aa72b2761fcd8924d (DO NOT MERGE)
3e7f1c7 GnuTLS: Add TLS event callbacks for chain success/failure and peer cert
0eb2ed0 GnuTLS: Add support for OCSP stapling as a client
cf08e9b Add MESH to modes capabilities
db5adfe Add SAE to auth_alg capabilities
0e1bb94 GnuTLS: Verify that server certificate EKU is valid for a server
d4d1f5c GnuTLS: Fix tls_disable_time_checks=1 processing
594d1fc GnuTLS: Add support for private_key and client_cert as blobs
79b1dd9 GnuTLS: Fix DER encoding certificate parsing
a165145 Add "GET tls_library" to provide information on TLS library and version
c3bb84b GnuTLS: Add event callbacks
8ddcd6b GnuTLS: Add support for domain_suffix_match
4bc13bf GnuTLS: Check for any unknown verification failure
e0d431a GnuTLS: Add more debug prints for version and session status
65ec7f4 GnuTLS: Move peer certificate validation into callback function
7c82457 GnuTLS: Remove support for versions older than 2.12.x
e1d63f6 GnuTLS: Remove old version number checks for 1.3.2
ae0a23a GnuTLS: Remove GNUTLS_INTERNAL_STRUCTURE_HACK
db4cf40 GnuTLS: Add support for ca_cert as a blob
224104d TLS: Reject openssl_ciphers parameter in non-OpenSSL cases
b09baf3 Work around Windows build issues
6dbbef9 Define host_to_le32() for Windows builds
7d28e46 Fix os_win32 build
0b40247 Remove Network Security Service (NSS) support
d166947 schannel: Reject subject_match, altsubject_match, suffix_match
59051f8 TLS: Reject subject_match, altsubject_match, suffix_match
f8717ac GnuTLS: Reject subject_match, altsubject_match, suffix_match
e24aef1 Fix a typo in domain_suffix_match documentation
394b547 Improve subject_match and domain_suffix_match documentation
8a42a07 trace: Fix out-of-memory testing logic
79cd993 Add address masks to BSSID lists
b83e455 Add network specific BSSID black and white lists
b3d6a0a Add generic parser for MAC address lists
21c74e8 nl80211: Use a helper function to put mesh_id
85e1fad nl80211: Use a helper function for putting beacon interval
6dfc557 Remove mesh_ht_mode network block parameter
54fe48b mesh: Use the shared function with IBSS to determine channel parameters
f7e889f mesh: Convert channel configuration to use common routines
6334330 mesh: Use a separate variable to track whether HT is enabled
1fc4ab2 nl80211: Move debug prints into nl80211_put_freq_params()
cae87ab nl80211: Add a helper function for putting basic rates
6b8b077 ibss/mesh: Enable HT40 if supported
a828f62 Make check_40mhz_2g4 common
fdd989d Make check_20mhz_bss common
0e550fe Make check_40mhz_5g common
6d5d098 Make get_pri_sec_chan() common
5144274 Introduce common allowed_ht40_channel_pair()
5f10b7f Use common hw_get_freq/hw_get_chan helpers in hostapd
269dfe2 Introduce common hw features
1830817 IBSS: Add WPA_DRIVER_FLAGS_HT_IBSS
f3b8ad4 SAE: Implement retransmission timer
a206e2a SAE: Centralize function for sending initial COMMIT
28c91ee bsd: Fix parsing of ieee80211req_scan_result on FreeBSD and DragonFly
96d1d97 Android: Remove hardcoded ICU include paths from hs20-osu-client
a354bcc D-Bus: Use NoMemory error message from CreateInterface
635874b Handle interface disabled/enabled more consistently
8f2cf37 P2P: Indicate reason=UNAVAILABLE for group netdev going down
86a7fbb Verify that eloop_register_read_sock() succeeds for ctrl_iface setup
27d9701 Fix a memory leak on WPA authenticator error path
c1c07dc Fix hostapd interface addition error path
a156ffd Add support for testing memory allocation failures
52b3943 D-Bus: Fix interface unregistration on error path
96dc9a6 D-Bus (old): Fix interface unregistration on error path
ef03557 Fix memory leak on wpa_supplicant_init_wpa() error path
52a8058 TDLS: Fix an interface addition error path
f2d5728 D-Bus: Fix string array dict entry parser in out-of-memory case
c61bc23 D-Bus: Fix byte array dict entry parser in out-of-memory case
dacf605 D-Bus: Fix Introspect() in case of os_strdup() failure
68a8669 D-Bus (old): Fix wpsReg error message
f0614bc D-Bus (old): Fix message handler error paths
a2af1c7 D-Bus (old): Fix memory leak on error path
3d2e2d5 trace: Fix compiler warning on 32-bit builds with bfd support
b9f6560 eloop: Fix WPA_TRACE tracking in case of realloc failure
e10422c Fix memory leak on hostapd BSS addition error path
2801659 Fix hostapd initialization error path on allocation failure
d58ade2 nl80211: Fix compilation with libnl 1.1 and 2.0
51f3427 crypto: Clear temporary stack buffers after use
77a2c39 crypto: Clear temporary heap allocations before freeing
a15a7fc DH: Clear memory explicitly on private key deinit
77c45e2 Add wpabuf_clear_free() to allow clearing of freed memory
a90c7d9 OpenSSL: Fix pbkdf2_sha1() wrapper
f6ebbcf AES-SIV: Make aes_s2v() static
dcf8fbc nl80211: Simplify event processing error paths
38751d8 nl80211: Remove cfg80211 state mismatch workaround for authentication
64ae244 nl80211: Check support for rekey offload on first use
Change-Id: Ice94c3cf8e39a6d2cac993aacd0f6d45b31c7c15
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/crypto/aes-eax.c b/src/crypto/aes-eax.c
index 21941c6..15a09f8 100644
--- a/src/crypto/aes-eax.c
+++ b/src/crypto/aes-eax.c
@@ -71,7 +71,7 @@
ret = 0;
fail:
- os_free(buf);
+ bin_clear_free(buf, buf_len);
return ret;
}
diff --git a/src/crypto/aes-siv.c b/src/crypto/aes-siv.c
index ff4b823..5ac82c2 100644
--- a/src/crypto/aes-siv.c
+++ b/src/crypto/aes-siv.c
@@ -11,6 +11,7 @@
#include "common.h"
#include "aes.h"
#include "aes_wrap.h"
+#include "aes_siv.h"
static const u8 zero[AES_BLOCK_SIZE];
@@ -60,8 +61,8 @@
}
-int aes_s2v(const u8 *key, size_t num_elem, const u8 *addr[],
- size_t *len, u8 *mac)
+static int aes_s2v(const u8 *key, size_t num_elem, const u8 *addr[],
+ size_t *len, u8 *mac)
{
u8 tmp[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE];
u8 *buf = NULL;
@@ -94,7 +95,7 @@
os_memcpy(buf, addr[i], len[i]);
xorend(buf, len[i], tmp, AES_BLOCK_SIZE);
ret = omac1_aes_128(key, buf, len[i], mac);
- os_free(buf);
+ bin_clear_free(buf, len[i]);
return ret;
}
diff --git a/src/crypto/crypto_module_tests.c b/src/crypto/crypto_module_tests.c
new file mode 100644
index 0000000..7137c27
--- /dev/null
+++ b/src/crypto/crypto_module_tests.c
@@ -0,0 +1,1679 @@
+/*
+ * crypto module tests
+ * Copyright (c) 2014-2015, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "crypto/aes_siv.h"
+#include "crypto/aes_wrap.h"
+#include "crypto/aes.h"
+#include "crypto/ms_funcs.h"
+#include "crypto/crypto.h"
+#include "crypto/sha1.h"
+#include "crypto/sha256.h"
+
+
+static int test_siv(void)
+{
+#ifdef CONFIG_MESH
+ /* RFC 5297, A.1. Deterministic Authenticated Encryption Example */
+ u8 key[] = {
+ 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
+ 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+ };
+ u8 ad[] = {
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27
+ };
+ u8 plaintext[] = {
+ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
+ 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee
+ };
+ u8 iv_c[] = {
+ 0x85, 0x63, 0x2d, 0x07, 0xc6, 0xe8, 0xf3, 0x7f,
+ 0x95, 0x0a, 0xcd, 0x32, 0x0a, 0x2e, 0xcc, 0x93,
+ 0x40, 0xc0, 0x2b, 0x96, 0x90, 0xc4, 0xdc, 0x04,
+ 0xda, 0xef, 0x7f, 0x6a, 0xfe, 0x5c
+ };
+ /* RFC 5297, A.2. Nonce-Based Authenticated Encryption Example */
+ u8 key_2[] = {
+ 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78,
+ 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
+ };
+ u8 ad1_2[] = {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+ 0xde, 0xad, 0xda, 0xda, 0xde, 0xad, 0xda, 0xda,
+ 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88,
+ 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00
+ };
+ u8 ad2_2[] = {
+ 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
+ 0x90, 0xa0
+ };
+ u8 nonce_2[] = {
+ 0x09, 0xf9, 0x11, 0x02, 0x9d, 0x74, 0xe3, 0x5b,
+ 0xd8, 0x41, 0x56, 0xc5, 0x63, 0x56, 0x88, 0xc0
+ };
+ u8 plaintext_2[] = {
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
+ 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x70, 0x6c, 0x61,
+ 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x20, 0x74,
+ 0x6f, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70,
+ 0x74, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20,
+ 0x53, 0x49, 0x56, 0x2d, 0x41, 0x45, 0x53
+ };
+ u8 iv_c_2[] = {
+ 0x7b, 0xdb, 0x6e, 0x3b, 0x43, 0x26, 0x67, 0xeb,
+ 0x06, 0xf4, 0xd1, 0x4b, 0xff, 0x2f, 0xbd, 0x0f,
+ 0xcb, 0x90, 0x0f, 0x2f, 0xdd, 0xbe, 0x40, 0x43,
+ 0x26, 0x60, 0x19, 0x65, 0xc8, 0x89, 0xbf, 0x17,
+ 0xdb, 0xa7, 0x7c, 0xeb, 0x09, 0x4f, 0xa6, 0x63,
+ 0xb7, 0xa3, 0xf7, 0x48, 0xba, 0x8a, 0xf8, 0x29,
+ 0xea, 0x64, 0xad, 0x54, 0x4a, 0x27, 0x2e, 0x9c,
+ 0x48, 0x5b, 0x62, 0xa3, 0xfd, 0x5c, 0x0d
+ };
+ u8 out[2 * AES_BLOCK_SIZE + sizeof(plaintext_2)];
+ const u8 *addr[3];
+ size_t len[3];
+
+ /* RFC 5297, A.1. Deterministic Authenticated Encryption Example */
+ addr[0] = ad;
+ len[0] = sizeof(ad);
+
+ if (aes_siv_encrypt(key, plaintext, sizeof(plaintext),
+ 1, addr, len, out)) {
+ wpa_printf(MSG_ERROR, "AES-SIV mode encryption failed");
+ return 1;
+ }
+ if (os_memcmp(out, iv_c, sizeof(iv_c)) != 0) {
+ wpa_printf(MSG_ERROR,
+ "AES-SIV mode encryption returned invalid cipher text");
+ return 1;
+ }
+
+ if (aes_siv_decrypt(key, iv_c, sizeof(iv_c), 1, addr, len, out)) {
+ wpa_printf(MSG_ERROR, "AES-SIV mode decryption failed");
+ return 1;
+ }
+ if (os_memcmp(out, plaintext, sizeof(plaintext)) != 0) {
+ wpa_printf(MSG_ERROR,
+ "AES-SIV mode decryption returned invalid plain text");
+ return 1;
+ }
+
+ /* RFC 5297, A.2. Nonce-Based Authenticated Encryption Example */
+ addr[0] = ad1_2;
+ len[0] = sizeof(ad1_2);
+ addr[1] = ad2_2;
+ len[1] = sizeof(ad2_2);
+ addr[2] = nonce_2;
+ len[2] = sizeof(nonce_2);
+
+ if (aes_siv_encrypt(key_2, plaintext_2, sizeof(plaintext_2),
+ 3, addr, len, out)) {
+ wpa_printf(MSG_ERROR, "AES-SIV mode encryption failed");
+ return 1;
+ }
+ if (os_memcmp(out, iv_c_2, sizeof(iv_c_2)) != 0) {
+ wpa_printf(MSG_ERROR,
+ "AES-SIV mode encryption returned invalid cipher text");
+ return 1;
+ }
+
+ if (aes_siv_decrypt(key_2, iv_c_2, sizeof(iv_c_2), 3, addr, len, out)) {
+ wpa_printf(MSG_ERROR, "AES-SIV mode decryption failed");
+ return 1;
+ }
+ if (os_memcmp(out, plaintext_2, sizeof(plaintext_2)) != 0) {
+ wpa_printf(MSG_ERROR,
+ "AES-SIV mode decryption returned invalid plain text");
+ return 1;
+ }
+
+ wpa_printf(MSG_INFO, "AES-SIV test cases passed");
+#endif /* CONFIG_MESH */
+
+ return 0;
+}
+
+
+/* OMAC1 AES-128 test vectors from
+ * http://csrc.nist.gov/CryptoToolkit/modes/proposedmodes/omac/omac-ad.pdf
+ * which are same as the examples from NIST SP800-38B
+ * http://csrc.nist.gov/CryptoToolkit/modes/800-38_Series_Publications/SP800-38B.pdf
+ */
+
+struct omac1_test_vector {
+ u8 k[16];
+ u8 msg[64];
+ int msg_len;
+ u8 tag[16];
+};
+
+static struct omac1_test_vector omac1_test_vectors[] =
+{
+ {
+ { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
+ { },
+ 0,
+ { 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
+ 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 }
+ },
+ {
+ { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
+ { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a},
+ 16,
+ { 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
+ 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c }
+ },
+ {
+ { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
+ { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+ 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11 },
+ 40,
+ { 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
+ 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 }
+ },
+ {
+ { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
+ { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+ 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+ 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+ 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
+ 64,
+ { 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
+ 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe }
+ },
+};
+
+
+static int test_omac1_vector(struct omac1_test_vector *tv, unsigned int i)
+{
+ u8 key[] = {
+ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+ };
+ u8 msg[] = { 0x12, 0x34, 0x56 };
+ u8 result[24], result2[24];
+ const u8 *addr[3];
+ size_t len[3];
+
+ if (omac1_aes_128(tv->k, tv->msg, tv->msg_len, result) ||
+ os_memcmp(result, tv->tag, 16) != 0) {
+ wpa_printf(MSG_ERROR, "OMAC1-AES-128 test vector %u failed", i);
+ return 1;
+ }
+
+ if (tv->msg_len > 1) {
+
+ addr[0] = tv->msg;
+ len[0] = 1;
+ addr[1] = tv->msg + 1;
+ len[1] = tv->msg_len - 1;
+
+ if (omac1_aes_128_vector(tv->k, 2, addr, len, result) ||
+ os_memcmp(result, tv->tag, 16) != 0) {
+ wpa_printf(MSG_ERROR,
+ "OMAC1-AES-128(vector) test vector %u failed",
+ i);
+ return 1;
+ }
+
+ addr[0] = tv->msg;
+ len[0] = tv->msg_len - 2;
+ addr[1] = tv->msg + tv->msg_len - 2;
+ len[1] = 1;
+ addr[2] = tv->msg + tv->msg_len - 1;
+ len[2] = 1;
+
+ if (omac1_aes_128_vector(tv->k, 3, addr, len, result) ||
+ os_memcmp(result, tv->tag, 16) != 0) {
+ wpa_printf(MSG_ERROR,
+ "OMAC1-AES-128(vector2) test vector %u failed",
+ i);
+ return 1;
+ }
+ }
+
+ addr[0] = &msg[0];
+ len[0] = 1;
+ addr[1] = &msg[1];
+ len[1] = 1;
+ addr[2] = &msg[2];
+ len[2] = 1;
+ if (omac1_aes_128(key, msg, sizeof(msg), result) ||
+ omac1_aes_128_vector(key, 3, addr, len, result2) ||
+ os_memcmp(result, result2, 16) != 0) {
+ wpa_printf(MSG_ERROR, "OMAC1-AES-128 short test mismatch");
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static int test_omac1(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(omac1_test_vectors); i++) {
+ if (test_omac1_vector(&omac1_test_vectors[i], i))
+ return 1;
+ }
+
+ wpa_printf(MSG_INFO, "OMAC1-AES-128 test cases passed");
+
+ return 0;
+}
+
+
+static int test_eax(void)
+{
+#ifdef EAP_PSK
+ u8 msg[] = { 0xF7, 0xFB };
+ u8 key[] = { 0x91, 0x94, 0x5D, 0x3F, 0x4D, 0xCB, 0xEE, 0x0B,
+ 0xF4, 0x5E, 0xF5, 0x22, 0x55, 0xF0, 0x95, 0xA4 };
+ u8 nonce[] = { 0xBE, 0xCA, 0xF0, 0x43, 0xB0, 0xA2, 0x3D, 0x84,
+ 0x31, 0x94, 0xBA, 0x97, 0x2C, 0x66, 0xDE, 0xBD };
+ u8 hdr[] = { 0xFA, 0x3B, 0xFD, 0x48, 0x06, 0xEB, 0x53, 0xFA };
+ u8 cipher[] = { 0x19, 0xDD, 0x5C, 0x4C, 0x93, 0x31, 0x04, 0x9D,
+ 0x0B, 0xDA, 0xB0, 0x27, 0x74, 0x08, 0xF6, 0x79,
+ 0x67, 0xE5 };
+ u8 data[sizeof(msg)], tag[AES_BLOCK_SIZE];
+
+ os_memcpy(data, msg, sizeof(msg));
+ if (aes_128_eax_encrypt(key, nonce, sizeof(nonce), hdr, sizeof(hdr),
+ data, sizeof(data), tag)) {
+ wpa_printf(MSG_ERROR, "AES-128 EAX mode encryption failed");
+ return 1;
+ }
+ if (os_memcmp(data, cipher, sizeof(data)) != 0) {
+ wpa_printf(MSG_ERROR,
+ "AES-128 EAX mode encryption returned invalid cipher text");
+ return 1;
+ }
+ if (os_memcmp(tag, cipher + sizeof(data), AES_BLOCK_SIZE) != 0) {
+ wpa_printf(MSG_ERROR,
+ "AES-128 EAX mode encryption returned invalid tag");
+ return 1;
+ }
+
+ if (aes_128_eax_decrypt(key, nonce, sizeof(nonce), hdr, sizeof(hdr),
+ data, sizeof(data), tag)) {
+ wpa_printf(MSG_ERROR, "AES-128 EAX mode decryption failed");
+ return 1;
+ }
+ if (os_memcmp(data, msg, sizeof(data)) != 0) {
+ wpa_printf(MSG_ERROR,
+ "AES-128 EAX mode decryption returned invalid plain text");
+ return 1;
+ }
+
+ wpa_printf(MSG_INFO, "AES-128 EAX mode test cases passed");
+#endif /* EAP_PSK */
+
+ return 0;
+}
+
+
+static int test_cbc(void)
+{
+ struct cbc_test_vector {
+ u8 key[16];
+ u8 iv[16];
+ u8 plain[32];
+ u8 cipher[32];
+ size_t len;
+ } vectors[] = {
+ {
+ { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
+ 0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 },
+ { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
+ 0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 },
+ "Single block msg",
+ { 0xe3, 0x53, 0x77, 0x9c, 0x10, 0x79, 0xae, 0xb8,
+ 0x27, 0x08, 0x94, 0x2d, 0xbe, 0x77, 0x18, 0x1a },
+ 16
+ },
+ {
+ { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0,
+ 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a },
+ { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28,
+ 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 },
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+ { 0xd2, 0x96, 0xcd, 0x94, 0xc2, 0xcc, 0xcf, 0x8a,
+ 0x3a, 0x86, 0x30, 0x28, 0xb5, 0xe1, 0xdc, 0x0a,
+ 0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9,
+ 0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1 },
+ 32
+ }
+ };
+ int ret = 0;
+ u8 *buf;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(vectors); i++) {
+ struct cbc_test_vector *tv = &vectors[i];
+
+ buf = os_malloc(tv->len);
+ if (buf == NULL) {
+ ret++;
+ break;
+ }
+
+ os_memcpy(buf, tv->plain, tv->len);
+ if (aes_128_cbc_encrypt(tv->key, tv->iv, buf, tv->len) ||
+ os_memcmp(buf, tv->cipher, tv->len) != 0) {
+ wpa_printf(MSG_ERROR, "AES-CBC encrypt %d failed", i);
+ ret++;
+ }
+
+ os_memcpy(buf, tv->cipher, tv->len);
+ if (aes_128_cbc_decrypt(tv->key, tv->iv, buf, tv->len) ||
+ os_memcmp(buf, tv->plain, tv->len) != 0) {
+ wpa_printf(MSG_ERROR, "AES-CBC decrypt %d failed", i);
+ ret++;
+ }
+
+ os_free(buf);
+ }
+
+ return ret;
+}
+
+
+static int test_ecb(void)
+{
+#ifdef EAP_PSK
+ struct ecb_test_vector {
+ char *key;
+ char *plaintext;
+ char *ciphertext;
+ } vectors[] = {
+ /* CAVS 11.1 - ECBGFSbox128.rsp */
+ {
+ "00000000000000000000000000000000",
+ "f34481ec3cc627bacd5dc3fb08f273e6",
+ "0336763e966d92595a567cc9ce537f5e"
+ },
+ {
+ "00000000000000000000000000000000",
+ "9798c4640bad75c7c3227db910174e72",
+ "a9a1631bf4996954ebc093957b234589"
+ },
+ {
+ "00000000000000000000000000000000",
+ "96ab5c2ff612d9dfaae8c31f30c42168",
+ "ff4f8391a6a40ca5b25d23bedd44a597"
+ },
+ {
+ "00000000000000000000000000000000",
+ "6a118a874519e64e9963798a503f1d35",
+ "dc43be40be0e53712f7e2bf5ca707209"
+ },
+ {
+ "00000000000000000000000000000000",
+ "cb9fceec81286ca3e989bd979b0cb284",
+ "92beedab1895a94faa69b632e5cc47ce"
+ },
+ {
+ "00000000000000000000000000000000",
+ "b26aeb1874e47ca8358ff22378f09144",
+ "459264f4798f6a78bacb89c15ed3d601"
+ },
+ {
+ "00000000000000000000000000000000",
+ "58c8e00b2631686d54eab84b91f0aca1",
+ "08a4e2efec8a8e3312ca7460b9040bbf"
+ },
+ /* CAVS 11.1 - ECBKeySbox128.rsp */
+ {
+ "10a58869d74be5a374cf867cfb473859",
+ "00000000000000000000000000000000",
+ "6d251e6944b051e04eaa6fb4dbf78465"
+ },
+ {
+ "caea65cdbb75e9169ecd22ebe6e54675",
+ "00000000000000000000000000000000",
+ "6e29201190152df4ee058139def610bb",
+ }
+ };
+ int ret = 0;
+ unsigned int i;
+ u8 key[16], plain[16], cipher[16], out[16];
+
+ for (i = 0; i < ARRAY_SIZE(vectors); i++) {
+ struct ecb_test_vector *tv = &vectors[i];
+
+ if (hexstr2bin(tv->key, key, sizeof(key)) ||
+ hexstr2bin(tv->plaintext, plain, sizeof(plain)) ||
+ hexstr2bin(tv->ciphertext, cipher, sizeof(cipher))) {
+ wpa_printf(MSG_ERROR, "Invalid AES-ECB test vector %u",
+ i);
+ ret++;
+ continue;
+ }
+
+ if (aes_128_encrypt_block(key, plain, out) < 0 ||
+ os_memcmp(out, cipher, 16) != 0) {
+ wpa_printf(MSG_ERROR, "AES-ECB encrypt %u failed", i);
+ ret++;
+ }
+ }
+
+ if (!ret)
+ wpa_printf(MSG_INFO, "AES ECB mode test cases passed");
+
+ return ret;
+#endif /* EAP_PSK */
+
+ return 0;
+}
+
+
+static int test_key_wrap(void)
+{
+ int ret = 0;
+
+ /* RFC 3394 - Test vector 4.1 */
+ u8 kek41[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+ u8 plain41[] = {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
+ };
+ u8 crypt41[] = {
+ 0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47,
+ 0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82,
+ 0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5
+ };
+ /* RFC 3394 - Test vector 4.2 */
+ u8 kek42[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
+ };
+ u8 plain42[] = {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
+ };
+ u8 crypt42[] = {
+ 0x96, 0x77, 0x8B, 0x25, 0xAE, 0x6C, 0xA4, 0x35,
+ 0xF9, 0x2B, 0x5B, 0x97, 0xC0, 0x50, 0xAE, 0xD2,
+ 0x46, 0x8A, 0xB8, 0xA1, 0x7A, 0xD8, 0x4E, 0x5D
+ };
+ /* RFC 3394 - Test vector 4.3 */
+ u8 kek43[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
+ };
+ u8 plain43[] = {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
+ };
+ u8 crypt43[] = {
+ 0x64, 0xE8, 0xC3, 0xF9, 0xCE, 0x0F, 0x5B, 0xA2,
+ 0x63, 0xE9, 0x77, 0x79, 0x05, 0x81, 0x8A, 0x2A,
+ 0x93, 0xC8, 0x19, 0x1E, 0x7D, 0x6E, 0x8A, 0xE7,
+ };
+ /* RFC 3394 - Test vector 4.4 */
+ u8 kek44[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
+ };
+ u8 plain44[] = {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ };
+ u8 crypt44[] = {
+ 0x03, 0x1D, 0x33, 0x26, 0x4E, 0x15, 0xD3, 0x32,
+ 0x68, 0xF2, 0x4E, 0xC2, 0x60, 0x74, 0x3E, 0xDC,
+ 0xE1, 0xC6, 0xC7, 0xDD, 0xEE, 0x72, 0x5A, 0x93,
+ 0x6B, 0xA8, 0x14, 0x91, 0x5C, 0x67, 0x62, 0xD2
+ };
+ /* RFC 3394 - Test vector 4.5 */
+ u8 kek45[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
+ };
+ u8 plain45[] = {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ };
+ u8 crypt45[] = {
+ 0xA8, 0xF9, 0xBC, 0x16, 0x12, 0xC6, 0x8B, 0x3F,
+ 0xF6, 0xE6, 0xF4, 0xFB, 0xE3, 0x0E, 0x71, 0xE4,
+ 0x76, 0x9C, 0x8B, 0x80, 0xA3, 0x2C, 0xB8, 0x95,
+ 0x8C, 0xD5, 0xD1, 0x7D, 0x6B, 0x25, 0x4D, 0xA1,
+ };
+ /* RFC 3394 - Test vector 4.6 */
+ u8 kek46[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
+ };
+ u8 plain46[] = {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+ };
+ u8 crypt46[] = {
+ 0x28, 0xC9, 0xF4, 0x04, 0xC4, 0xB8, 0x10, 0xF4,
+ 0xCB, 0xCC, 0xB3, 0x5C, 0xFB, 0x87, 0xF8, 0x26,
+ 0x3F, 0x57, 0x86, 0xE2, 0xD8, 0x0E, 0xD3, 0x26,
+ 0xCB, 0xC7, 0xF0, 0xE7, 0x1A, 0x99, 0xF4, 0x3B,
+ 0xFB, 0x98, 0x8B, 0x9B, 0x7A, 0x02, 0xDD, 0x21
+ };
+ u8 result[40];
+
+ wpa_printf(MSG_INFO, "RFC 3394 - Test vector 4.1");
+ if (aes_wrap(kek41, sizeof(kek41), sizeof(plain41) / 8, plain41,
+ result)) {
+ wpa_printf(MSG_ERROR, "AES-WRAP-128 reported failure");
+ ret++;
+ }
+ if (os_memcmp(result, crypt41, sizeof(crypt41)) != 0) {
+ wpa_printf(MSG_ERROR, "AES-WRAP-128 failed");
+ ret++;
+ }
+ if (aes_unwrap(kek41, sizeof(kek41), sizeof(plain41) / 8, crypt41,
+ result)) {
+ wpa_printf(MSG_ERROR, "AES-UNWRAP-128 reported failure");
+ ret++;
+ }
+ if (os_memcmp(result, plain41, sizeof(plain41)) != 0) {
+ wpa_printf(MSG_ERROR, "AES-UNWRAP-128 failed");
+ ret++;
+ }
+
+ wpa_printf(MSG_INFO, "RFC 3394 - Test vector 4.2");
+ if (aes_wrap(kek42, sizeof(kek42), sizeof(plain42) / 8, plain42,
+ result)) {
+ wpa_printf(MSG_ERROR, "AES-WRAP-192 reported failure");
+ ret++;
+ }
+ if (os_memcmp(result, crypt42, sizeof(crypt42)) != 0) {
+ wpa_printf(MSG_ERROR, "AES-WRAP-192 failed");
+ ret++;
+ }
+ if (aes_unwrap(kek42, sizeof(kek42), sizeof(plain42) / 8, crypt42,
+ result)) {
+ wpa_printf(MSG_ERROR, "AES-UNWRAP-192 reported failure");
+ ret++;
+ }
+ if (os_memcmp(result, plain42, sizeof(plain42)) != 0) {
+ wpa_printf(MSG_ERROR, "AES-UNWRAP-192 failed");
+ ret++;
+ }
+
+ wpa_printf(MSG_INFO, "RFC 3394 - Test vector 4.3");
+ if (aes_wrap(kek43, sizeof(kek43), sizeof(plain43) / 8, plain43,
+ result)) {
+ wpa_printf(MSG_ERROR, "AES-WRAP-256 reported failure");
+ ret++;
+ }
+ if (os_memcmp(result, crypt43, sizeof(crypt43)) != 0) {
+ wpa_printf(MSG_ERROR, "AES-WRAP-256 failed");
+ ret++;
+ }
+ if (aes_unwrap(kek43, sizeof(kek43), sizeof(plain43) / 8, crypt43,
+ result)) {
+ wpa_printf(MSG_ERROR, "AES-UNWRAP-256 reported failure");
+ ret++;
+ }
+ if (os_memcmp(result, plain43, sizeof(plain43)) != 0) {
+ wpa_printf(MSG_ERROR, "AES-UNWRAP-256 failed");
+ ret++;
+ }
+
+ wpa_printf(MSG_INFO, "RFC 3394 - Test vector 4.4");
+ if (aes_wrap(kek44, sizeof(kek44), sizeof(plain44) / 8, plain44,
+ result)) {
+ wpa_printf(MSG_ERROR, "AES-WRAP-192 reported failure");
+ ret++;
+ }
+ if (os_memcmp(result, crypt44, sizeof(crypt44)) != 0) {
+ wpa_printf(MSG_ERROR, "AES-WRAP-192 failed");
+ ret++;
+ }
+ if (aes_unwrap(kek44, sizeof(kek44), sizeof(plain44) / 8, crypt44,
+ result)) {
+ wpa_printf(MSG_ERROR, "AES-UNWRAP-192 reported failure");
+ ret++;
+ }
+ if (os_memcmp(result, plain44, sizeof(plain44)) != 0) {
+ wpa_printf(MSG_ERROR, "AES-UNWRAP-192 failed");
+ ret++;
+ }
+
+ wpa_printf(MSG_INFO, "RFC 3394 - Test vector 4.5");
+ if (aes_wrap(kek45, sizeof(kek45), sizeof(plain45) / 8, plain45,
+ result)) {
+ wpa_printf(MSG_ERROR, "AES-WRAP-256 reported failure");
+ ret++;
+ }
+ if (os_memcmp(result, crypt45, sizeof(crypt45)) != 0) {
+ wpa_printf(MSG_ERROR, "AES-WRAP-256 failed");
+ ret++;
+ }
+ if (aes_unwrap(kek45, sizeof(kek45), sizeof(plain45) / 8, crypt45,
+ result)) {
+ wpa_printf(MSG_ERROR, "AES-UNWRAP-256 reported failure");
+ ret++;
+ }
+ if (os_memcmp(result, plain45, sizeof(plain45)) != 0) {
+ wpa_printf(MSG_ERROR, "AES-UNWRAP-256 failed");
+ ret++;
+ }
+
+ wpa_printf(MSG_INFO, "RFC 3394 - Test vector 4.6");
+ if (aes_wrap(kek46, sizeof(kek46), sizeof(plain46) / 8, plain46,
+ result)) {
+ wpa_printf(MSG_ERROR, "AES-WRAP-256 reported failure");
+ ret++;
+ }
+ if (os_memcmp(result, crypt46, sizeof(crypt46)) != 0) {
+ wpa_printf(MSG_ERROR, "AES-WRAP-256 failed");
+ ret++;
+ }
+ if (aes_unwrap(kek46, sizeof(kek46), sizeof(plain46) / 8, crypt46,
+ result)) {
+ wpa_printf(MSG_ERROR, "AES-UNWRAP-256 reported failure");
+ ret++;
+ }
+ if (os_memcmp(result, plain46, sizeof(plain46)) != 0) {
+ wpa_printf(MSG_ERROR, "AES-UNWRAP-256 failed");
+ ret++;
+ }
+
+ if (!ret)
+ wpa_printf(MSG_INFO, "AES key wrap/unwrap test cases passed");
+
+ return ret;
+}
+
+
+static int test_md5(void)
+{
+ struct {
+ char *data;
+ char *hash;
+ } tests[] = {
+ {
+ "",
+ "\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04"
+ "\xe9\x80\x09\x98\xec\xf8\x42\x7e"
+ },
+ {
+ "a",
+ "\x0c\xc1\x75\xb9\xc0\xf1\xb6\xa8"
+ "\x31\xc3\x99\xe2\x69\x77\x26\x61"
+ },
+ {
+ "abc",
+ "\x90\x01\x50\x98\x3c\xd2\x4f\xb0"
+ "\xd6\x96\x3f\x7d\x28\xe1\x7f\x72"
+ },
+ {
+ "message digest",
+ "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d"
+ "\x52\x5a\x2f\x31\xaa\xf1\x61\xd0"
+ },
+ {
+ "abcdefghijklmnopqrstuvwxyz",
+ "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00"
+ "\x7d\xfb\x49\x6c\xca\x67\xe1\x3b"
+ },
+ {
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+ "0123456789",
+ "\xd1\x74\xab\x98\xd2\x77\xd9\xf5"
+ "\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f"
+ },
+ {
+ "12345678901234567890123456789012345678901234567890"
+ "123456789012345678901234567890",
+ "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55"
+ "\xac\x49\xda\x2e\x21\x07\xb6\x7a"
+ }
+ };
+ unsigned int i;
+ u8 hash[16];
+ const u8 *addr[2];
+ size_t len[2];
+ int errors = 0;
+
+ for (i = 0; i < ARRAY_SIZE(tests); i++) {
+ wpa_printf(MSG_INFO, "MD5 test case %d", i);
+
+ addr[0] = (u8 *) tests[i].data;
+ len[0] = strlen(tests[i].data);
+ if (md5_vector(1, addr, len, hash) < 0 ||
+ os_memcmp(hash, tests[i].hash, 16) != 0) {
+ wpa_printf(MSG_INFO, " FAIL");
+ errors++;
+ } else
+ wpa_printf(MSG_INFO, " OK");
+
+ if (len[0]) {
+ addr[0] = (u8 *) tests[i].data;
+ len[0] = strlen(tests[i].data);
+ addr[1] = (u8 *) tests[i].data + 1;
+ len[1] = strlen(tests[i].data) - 1;
+ if (md5_vector(1, addr, len, hash) < 0 ||
+ os_memcmp(hash, tests[i].hash, 16) != 0) {
+ wpa_printf(MSG_INFO, " FAIL");
+ errors++;
+ } else
+ wpa_printf(MSG_INFO, " OK");
+ }
+ }
+
+ if (!errors)
+ wpa_printf(MSG_INFO, "MD5 test cases passed");
+
+ return errors;
+}
+
+
+static int test_eap_fast(void)
+{
+#ifdef EAP_FAST
+ /* RFC 4851, Appendix B.1 */
+ const u8 pac_key[] = {
+ 0x0B, 0x97, 0x39, 0x0F, 0x37, 0x51, 0x78, 0x09,
+ 0x81, 0x1E, 0xFD, 0x9C, 0x6E, 0x65, 0x94, 0x2B,
+ 0x63, 0x2C, 0xE9, 0x53, 0x89, 0x38, 0x08, 0xBA,
+ 0x36, 0x0B, 0x03, 0x7C, 0xD1, 0x85, 0xE4, 0x14
+ };
+ const u8 seed[] = {
+ 0x3F, 0xFB, 0x11, 0xC4, 0x6C, 0xBF, 0xA5, 0x7A,
+ 0x54, 0x40, 0xDA, 0xE8, 0x22, 0xD3, 0x11, 0xD3,
+ 0xF7, 0x6D, 0xE4, 0x1D, 0xD9, 0x33, 0xE5, 0x93,
+ 0x70, 0x97, 0xEB, 0xA9, 0xB3, 0x66, 0xF4, 0x2A,
+ 0x00, 0x00, 0x00, 0x02, 0x6A, 0x66, 0x43, 0x2A,
+ 0x8D, 0x14, 0x43, 0x2C, 0xEC, 0x58, 0x2D, 0x2F,
+ 0xC7, 0x9C, 0x33, 0x64, 0xBA, 0x04, 0xAD, 0x3A,
+ 0x52, 0x54, 0xD6, 0xA5, 0x79, 0xAD, 0x1E, 0x00
+ };
+ const u8 master_secret[] = {
+ 0x4A, 0x1A, 0x51, 0x2C, 0x01, 0x60, 0xBC, 0x02,
+ 0x3C, 0xCF, 0xBC, 0x83, 0x3F, 0x03, 0xBC, 0x64,
+ 0x88, 0xC1, 0x31, 0x2F, 0x0B, 0xA9, 0xA2, 0x77,
+ 0x16, 0xA8, 0xD8, 0xE8, 0xBD, 0xC9, 0xD2, 0x29,
+ 0x38, 0x4B, 0x7A, 0x85, 0xBE, 0x16, 0x4D, 0x27,
+ 0x33, 0xD5, 0x24, 0x79, 0x87, 0xB1, 0xC5, 0xA2
+ };
+ const u8 key_block[] = {
+ 0x59, 0x59, 0xBE, 0x8E, 0x41, 0x3A, 0x77, 0x74,
+ 0x8B, 0xB2, 0xE5, 0xD3, 0x60, 0xAC, 0x4D, 0x35,
+ 0xDF, 0xFB, 0xC8, 0x1E, 0x9C, 0x24, 0x9C, 0x8B,
+ 0x0E, 0xC3, 0x1D, 0x72, 0xC8, 0x84, 0x9D, 0x57,
+ 0x48, 0x51, 0x2E, 0x45, 0x97, 0x6C, 0x88, 0x70,
+ 0xBE, 0x5F, 0x01, 0xD3, 0x64, 0xE7, 0x4C, 0xBB,
+ 0x11, 0x24, 0xE3, 0x49, 0xE2, 0x3B, 0xCD, 0xEF,
+ 0x7A, 0xB3, 0x05, 0x39, 0x5D, 0x64, 0x8A, 0x44,
+ 0x11, 0xB6, 0x69, 0x88, 0x34, 0x2E, 0x8E, 0x29,
+ 0xD6, 0x4B, 0x7D, 0x72, 0x17, 0x59, 0x28, 0x05,
+ 0xAF, 0xF9, 0xB7, 0xFF, 0x66, 0x6D, 0xA1, 0x96,
+ 0x8F, 0x0B, 0x5E, 0x06, 0x46, 0x7A, 0x44, 0x84,
+ 0x64, 0xC1, 0xC8, 0x0C, 0x96, 0x44, 0x09, 0x98,
+ 0xFF, 0x92, 0xA8, 0xB4, 0xC6, 0x42, 0x28, 0x71
+ };
+ const u8 sks[] = {
+ 0xD6, 0x4B, 0x7D, 0x72, 0x17, 0x59, 0x28, 0x05,
+ 0xAF, 0xF9, 0xB7, 0xFF, 0x66, 0x6D, 0xA1, 0x96,
+ 0x8F, 0x0B, 0x5E, 0x06, 0x46, 0x7A, 0x44, 0x84,
+ 0x64, 0xC1, 0xC8, 0x0C, 0x96, 0x44, 0x09, 0x98,
+ 0xFF, 0x92, 0xA8, 0xB4, 0xC6, 0x42, 0x28, 0x71
+ };
+ const u8 isk[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ const u8 imck[] = {
+ 0x16, 0x15, 0x3C, 0x3F, 0x21, 0x55, 0xEF, 0xD9,
+ 0x7F, 0x34, 0xAE, 0xC8, 0x1A, 0x4E, 0x66, 0x80,
+ 0x4C, 0xC3, 0x76, 0xF2, 0x8A, 0xA9, 0x6F, 0x96,
+ 0xC2, 0x54, 0x5F, 0x8C, 0xAB, 0x65, 0x02, 0xE1,
+ 0x18, 0x40, 0x7B, 0x56, 0xBE, 0xEA, 0xA7, 0xC5,
+ 0x76, 0x5D, 0x8F, 0x0B, 0xC5, 0x07, 0xC6, 0xB9,
+ 0x04, 0xD0, 0x69, 0x56, 0x72, 0x8B, 0x6B, 0xB8,
+ 0x15, 0xEC, 0x57, 0x7B
+ };
+ const u8 msk[] = {
+ 0x4D, 0x83, 0xA9, 0xBE, 0x6F, 0x8A, 0x74, 0xED,
+ 0x6A, 0x02, 0x66, 0x0A, 0x63, 0x4D, 0x2C, 0x33,
+ 0xC2, 0xDA, 0x60, 0x15, 0xC6, 0x37, 0x04, 0x51,
+ 0x90, 0x38, 0x63, 0xDA, 0x54, 0x3E, 0x14, 0xB9,
+ 0x27, 0x99, 0x18, 0x1E, 0x07, 0xBF, 0x0F, 0x5A,
+ 0x5E, 0x3C, 0x32, 0x93, 0x80, 0x8C, 0x6C, 0x49,
+ 0x67, 0xED, 0x24, 0xFE, 0x45, 0x40, 0xA0, 0x59,
+ 0x5E, 0x37, 0xC2, 0xE9, 0xD0, 0x5D, 0x0A, 0xE3
+ };
+ const u8 emsk[] = {
+ 0x3A, 0xD4, 0xAB, 0xDB, 0x76, 0xB2, 0x7F, 0x3B,
+ 0xEA, 0x32, 0x2C, 0x2B, 0x74, 0xF4, 0x28, 0x55,
+ 0xEF, 0x2D, 0xBA, 0x78, 0xC9, 0x57, 0x2F, 0x0D,
+ 0x06, 0xCD, 0x51, 0x7C, 0x20, 0x93, 0x98, 0xA9,
+ 0x76, 0xEA, 0x70, 0x21, 0xD7, 0x0E, 0x25, 0x54,
+ 0x97, 0xED, 0xB2, 0x8A, 0xF6, 0xED, 0xFD, 0x0A,
+ 0x2A, 0xE7, 0xA1, 0x58, 0x90, 0x10, 0x50, 0x44,
+ 0xB3, 0x82, 0x85, 0xDB, 0x06, 0x14, 0xD2, 0xF9
+ };
+ /* RFC 4851, Appendix B.2 */
+ u8 tlv[] = {
+ 0x80, 0x0C, 0x00, 0x38, 0x00, 0x01, 0x01, 0x00,
+ 0xD8, 0x6A, 0x8C, 0x68, 0x3C, 0x32, 0x31, 0xA8,
+ 0x56, 0x63, 0xB6, 0x40, 0x21, 0xFE, 0x21, 0x14,
+ 0x4E, 0xE7, 0x54, 0x20, 0x79, 0x2D, 0x42, 0x62,
+ 0xC9, 0xBF, 0x53, 0x7F, 0x54, 0xFD, 0xAC, 0x58,
+ 0x43, 0x24, 0x6E, 0x30, 0x92, 0x17, 0x6D, 0xCF,
+ 0xE6, 0xE0, 0x69, 0xEB, 0x33, 0x61, 0x6A, 0xCC,
+ 0x05, 0xC5, 0x5B, 0xB7
+ };
+ const u8 compound_mac[] = {
+ 0x43, 0x24, 0x6E, 0x30, 0x92, 0x17, 0x6D, 0xCF,
+ 0xE6, 0xE0, 0x69, 0xEB, 0x33, 0x61, 0x6A, 0xCC,
+ 0x05, 0xC5, 0x5B, 0xB7
+ };
+ u8 buf[512];
+ const u8 *simck, *cmk;
+ int errors = 0;
+
+ wpa_printf(MSG_INFO, "EAP-FAST test cases");
+
+ wpa_printf(MSG_INFO, "- T-PRF (SHA1) test case / master_secret");
+ if (sha1_t_prf(pac_key, sizeof(pac_key),
+ "PAC to master secret label hash",
+ seed, sizeof(seed), buf, sizeof(master_secret)) < 0 ||
+ os_memcmp(master_secret, buf, sizeof(master_secret)) != 0) {
+ wpa_printf(MSG_INFO, "T-PRF test - FAILED!");
+ errors++;
+ }
+
+ wpa_printf(MSG_INFO, "- PRF (TLS, SHA1/MD5) test case / key_block");
+ if (tls_prf_sha1_md5(master_secret, sizeof(master_secret),
+ "key expansion", seed, sizeof(seed),
+ buf, sizeof(key_block)) ||
+ os_memcmp(key_block, buf, sizeof(key_block)) != 0) {
+ wpa_printf(MSG_INFO, "PRF test - FAILED!");
+ errors++;
+ }
+
+ wpa_printf(MSG_INFO, "- T-PRF (SHA1) test case / IMCK");
+ if (sha1_t_prf(sks, sizeof(sks), "Inner Methods Compound Keys",
+ isk, sizeof(isk), buf, sizeof(imck)) < 0 ||
+ os_memcmp(imck, buf, sizeof(imck)) != 0) {
+ wpa_printf(MSG_INFO, "T-PRF test - FAILED!");
+ errors++;
+ }
+
+ simck = imck;
+ cmk = imck + 40;
+
+ wpa_printf(MSG_INFO, "- T-PRF (SHA1) test case / MSK");
+ if (sha1_t_prf(simck, 40, "Session Key Generating Function",
+ (u8 *) "", 0, buf, sizeof(msk)) < 0 ||
+ os_memcmp(msk, buf, sizeof(msk)) != 0) {
+ wpa_printf(MSG_INFO, "T-PRF test - FAILED!");
+ errors++;
+ }
+
+ wpa_printf(MSG_INFO, "- T-PRF (SHA1) test case / EMSK");
+ if (sha1_t_prf(simck, 40, "Extended Session Key Generating Function",
+ (u8 *) "", 0, buf, sizeof(msk)) < 0 ||
+ os_memcmp(emsk, buf, sizeof(emsk)) != 0) {
+ wpa_printf(MSG_INFO, "T-PRF test - FAILED!");
+ errors++;
+ }
+
+ wpa_printf(MSG_INFO, "- Compound MAC test case");
+ os_memset(tlv + sizeof(tlv) - 20, 0, 20);
+ if (hmac_sha1(cmk, 20, tlv, sizeof(tlv), tlv + sizeof(tlv) - 20) < 0 ||
+ os_memcmp(tlv + sizeof(tlv) - 20, compound_mac,
+ sizeof(compound_mac)) != 0) {
+ wpa_printf(MSG_INFO, "Compound MAC test - FAILED!");
+ errors++;
+ }
+
+ return errors;
+#else /* EAP_FAST */
+ return 0;
+#endif /* EAP_FAST */
+}
+
+
+static u8 key0[] =
+{
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b
+};
+static u8 data0[] = "Hi There";
+static u8 prf0[] =
+{
+ 0xbc, 0xd4, 0xc6, 0x50, 0xb3, 0x0b, 0x96, 0x84,
+ 0x95, 0x18, 0x29, 0xe0, 0xd7, 0x5f, 0x9d, 0x54,
+ 0xb8, 0x62, 0x17, 0x5e, 0xd9, 0xf0, 0x06, 0x06,
+ 0xe1, 0x7d, 0x8d, 0xa3, 0x54, 0x02, 0xff, 0xee,
+ 0x75, 0xdf, 0x78, 0xc3, 0xd3, 0x1e, 0x0f, 0x88,
+ 0x9f, 0x01, 0x21, 0x20, 0xc0, 0x86, 0x2b, 0xeb,
+ 0x67, 0x75, 0x3e, 0x74, 0x39, 0xae, 0x24, 0x2e,
+ 0xdb, 0x83, 0x73, 0x69, 0x83, 0x56, 0xcf, 0x5a
+};
+
+static u8 key1[] = "Jefe";
+static u8 data1[] = "what do ya want for nothing?";
+static u8 prf1[] =
+{
+ 0x51, 0xf4, 0xde, 0x5b, 0x33, 0xf2, 0x49, 0xad,
+ 0xf8, 0x1a, 0xeb, 0x71, 0x3a, 0x3c, 0x20, 0xf4,
+ 0xfe, 0x63, 0x14, 0x46, 0xfa, 0xbd, 0xfa, 0x58,
+ 0x24, 0x47, 0x59, 0xae, 0x58, 0xef, 0x90, 0x09,
+ 0xa9, 0x9a, 0xbf, 0x4e, 0xac, 0x2c, 0xa5, 0xfa,
+ 0x87, 0xe6, 0x92, 0xc4, 0x40, 0xeb, 0x40, 0x02,
+ 0x3e, 0x7b, 0xab, 0xb2, 0x06, 0xd6, 0x1d, 0xe7,
+ 0xb9, 0x2f, 0x41, 0x52, 0x90, 0x92, 0xb8, 0xfc
+};
+
+
+static u8 key2[] =
+{
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa
+};
+static u8 data2[] =
+{
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd
+};
+static u8 prf2[] =
+{
+ 0xe1, 0xac, 0x54, 0x6e, 0xc4, 0xcb, 0x63, 0x6f,
+ 0x99, 0x76, 0x48, 0x7b, 0xe5, 0xc8, 0x6b, 0xe1,
+ 0x7a, 0x02, 0x52, 0xca, 0x5d, 0x8d, 0x8d, 0xf1,
+ 0x2c, 0xfb, 0x04, 0x73, 0x52, 0x52, 0x49, 0xce,
+ 0x9d, 0xd8, 0xd1, 0x77, 0xea, 0xd7, 0x10, 0xbc,
+ 0x9b, 0x59, 0x05, 0x47, 0x23, 0x91, 0x07, 0xae,
+ 0xf7, 0xb4, 0xab, 0xd4, 0x3d, 0x87, 0xf0, 0xa6,
+ 0x8f, 0x1c, 0xbd, 0x9e, 0x2b, 0x6f, 0x76, 0x07
+};
+
+
+struct passphrase_test {
+ char *passphrase;
+ char *ssid;
+ char psk[32];
+};
+
+static struct passphrase_test passphrase_tests[] =
+{
+ {
+ "password",
+ "IEEE",
+ {
+ 0xf4, 0x2c, 0x6f, 0xc5, 0x2d, 0xf0, 0xeb, 0xef,
+ 0x9e, 0xbb, 0x4b, 0x90, 0xb3, 0x8a, 0x5f, 0x90,
+ 0x2e, 0x83, 0xfe, 0x1b, 0x13, 0x5a, 0x70, 0xe2,
+ 0x3a, 0xed, 0x76, 0x2e, 0x97, 0x10, 0xa1, 0x2e
+ }
+ },
+ {
+ "ThisIsAPassword",
+ "ThisIsASSID",
+ {
+ 0x0d, 0xc0, 0xd6, 0xeb, 0x90, 0x55, 0x5e, 0xd6,
+ 0x41, 0x97, 0x56, 0xb9, 0xa1, 0x5e, 0xc3, 0xe3,
+ 0x20, 0x9b, 0x63, 0xdf, 0x70, 0x7d, 0xd5, 0x08,
+ 0xd1, 0x45, 0x81, 0xf8, 0x98, 0x27, 0x21, 0xaf
+ }
+ },
+ {
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ",
+ {
+ 0xbe, 0xcb, 0x93, 0x86, 0x6b, 0xb8, 0xc3, 0x83,
+ 0x2c, 0xb7, 0x77, 0xc2, 0xf5, 0x59, 0x80, 0x7c,
+ 0x8c, 0x59, 0xaf, 0xcb, 0x6e, 0xae, 0x73, 0x48,
+ 0x85, 0x00, 0x13, 0x00, 0xa9, 0x81, 0xcc, 0x62
+ }
+ },
+};
+
+#define NUM_PASSPHRASE_TESTS ARRAY_SIZE(passphrase_tests)
+
+
+struct rfc6070_test {
+ char *p;
+ char *s;
+ int c;
+ char dk[32];
+ size_t dk_len;
+};
+
+static struct rfc6070_test rfc6070_tests[] =
+{
+ {
+ "password",
+ "salt",
+ 1,
+ {
+ 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
+ 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
+ 0x2f, 0xe0, 0x37, 0xa6
+ },
+ 20
+ },
+ {
+ "password",
+ "salt",
+ 2,
+ {
+ 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
+ 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
+ 0xd8, 0xde, 0x89, 0x57
+ },
+ 20
+ },
+ {
+ "password",
+ "salt",
+ 4096,
+ {
+ 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
+ 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
+ 0x65, 0xa4, 0x29, 0xc1
+ },
+ 20
+ },
+#if 0 /* This takes quite long to derive.. */
+ {
+ "password",
+ "salt",
+ 16777216,
+ {
+ 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4,
+ 0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c,
+ 0x26, 0x34, 0xe9, 0x84
+ },
+ 20
+ },
+#endif
+ {
+ "passwordPASSWORDpassword",
+ "saltSALTsaltSALTsaltSALTsaltSALTsalt",
+ 4096,
+ {
+ 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
+ 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
+ 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
+ 0x38
+ },
+ 25
+ },
+#if 0 /* \0 not currently supported in passphrase parameters.. */
+ {
+ "pass\0word",
+ "sa\0lt",
+ 4096,
+ {
+ 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
+ 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3
+ },
+ 16
+ },
+#endif
+};
+
+#define NUM_RFC6070_TESTS ARRAY_SIZE(rfc6070_tests)
+
+
+static int test_sha1(void)
+{
+ u8 res[512];
+ int ret = 0;
+ unsigned int i;
+
+ wpa_printf(MSG_INFO, "PRF-SHA1 test cases:");
+
+ if (sha1_prf(key0, sizeof(key0), "prefix", data0, sizeof(data0) - 1,
+ res, sizeof(prf0)) == 0 &&
+ os_memcmp(res, prf0, sizeof(prf0)) == 0)
+ wpa_printf(MSG_INFO, "Test case 0 - OK");
+ else {
+ wpa_printf(MSG_INFO, "Test case 0 - FAILED!");
+ ret++;
+ }
+
+ if (sha1_prf(key1, sizeof(key1) - 1, "prefix", data1, sizeof(data1) - 1,
+ res, sizeof(prf1)) == 0 &&
+ os_memcmp(res, prf1, sizeof(prf1)) == 0)
+ wpa_printf(MSG_INFO, "Test case 1 - OK");
+ else {
+ wpa_printf(MSG_INFO, "Test case 1 - FAILED!");
+ ret++;
+ }
+
+ if (sha1_prf(key2, sizeof(key2), "prefix", data2, sizeof(data2),
+ res, sizeof(prf2)) == 0 &&
+ os_memcmp(res, prf2, sizeof(prf2)) == 0)
+ wpa_printf(MSG_INFO, "Test case 2 - OK");
+ else {
+ wpa_printf(MSG_INFO, "Test case 2 - FAILED!");
+ ret++;
+ }
+
+ ret += test_eap_fast();
+
+ wpa_printf(MSG_INFO, "PBKDF2-SHA1 Passphrase test cases:");
+ for (i = 0; i < NUM_PASSPHRASE_TESTS; i++) {
+ u8 psk[32];
+ struct passphrase_test *test = &passphrase_tests[i];
+
+ if (pbkdf2_sha1(test->passphrase,
+ (const u8 *) test->ssid, strlen(test->ssid),
+ 4096, psk, 32) == 0 &&
+ os_memcmp(psk, test->psk, 32) == 0)
+ wpa_printf(MSG_INFO, "Test case %d - OK", i);
+ else {
+ wpa_printf(MSG_INFO, "Test case %d - FAILED!", i);
+ ret++;
+ }
+ }
+
+ wpa_printf(MSG_INFO, "PBKDF2-SHA1 test cases (RFC 6070):");
+ for (i = 0; i < NUM_RFC6070_TESTS; i++) {
+ u8 dk[25];
+ struct rfc6070_test *test = &rfc6070_tests[i];
+
+ if (pbkdf2_sha1(test->p, (const u8 *) test->s, strlen(test->s),
+ test->c, dk, test->dk_len) == 0 &&
+ os_memcmp(dk, test->dk, test->dk_len) == 0)
+ wpa_printf(MSG_INFO, "Test case %d - OK", i);
+ else {
+ wpa_printf(MSG_INFO, "Test case %d - FAILED!", i);
+ ret++;
+ }
+ }
+
+ if (!ret)
+ wpa_printf(MSG_INFO, "SHA1 test cases passed");
+ return ret;
+}
+
+
+struct {
+ char *data;
+ u8 hash[32];
+} tests[] = {
+ {
+ "abc",
+ {
+ 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
+ 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
+ 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
+ 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
+ }
+ },
+ {
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ {
+ 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
+ 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
+ 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
+ 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1
+ }
+ }
+};
+
+struct hmac_test {
+ u8 key[80];
+ size_t key_len;
+ u8 data[128];
+ size_t data_len;
+ u8 hash[32];
+} hmac_tests[] = {
+ /* draft-ietf-ipsec-ciph-sha-256-01.txt */
+ {
+ {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20
+ },
+ 32,
+ "abc", 3,
+ {
+ 0xa2, 0x1b, 0x1f, 0x5d, 0x4c, 0xf4, 0xf7, 0x3a,
+ 0x4d, 0xd9, 0x39, 0x75, 0x0f, 0x7a, 0x06, 0x6a,
+ 0x7f, 0x98, 0xcc, 0x13, 0x1c, 0xb1, 0x6a, 0x66,
+ 0x92, 0x75, 0x90, 0x21, 0xcf, 0xab, 0x81, 0x81
+ }
+ },
+ {
+ {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20
+ },
+ 32,
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ 56,
+ {
+ 0x10, 0x4f, 0xdc, 0x12, 0x57, 0x32, 0x8f, 0x08,
+ 0x18, 0x4b, 0xa7, 0x31, 0x31, 0xc5, 0x3c, 0xae,
+ 0xe6, 0x98, 0xe3, 0x61, 0x19, 0x42, 0x11, 0x49,
+ 0xea, 0x8c, 0x71, 0x24, 0x56, 0x69, 0x7d, 0x30
+ }
+ },
+ {
+ {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20
+ },
+ 32,
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ 112,
+ {
+ 0x47, 0x03, 0x05, 0xfc, 0x7e, 0x40, 0xfe, 0x34,
+ 0xd3, 0xee, 0xb3, 0xe7, 0x73, 0xd9, 0x5a, 0xab,
+ 0x73, 0xac, 0xf0, 0xfd, 0x06, 0x04, 0x47, 0xa5,
+ 0xeb, 0x45, 0x95, 0xbf, 0x33, 0xa9, 0xd1, 0xa3
+ }
+ },
+ {
+ {
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b
+ },
+ 32,
+ "Hi There",
+ 8,
+ {
+ 0x19, 0x8a, 0x60, 0x7e, 0xb4, 0x4b, 0xfb, 0xc6,
+ 0x99, 0x03, 0xa0, 0xf1, 0xcf, 0x2b, 0xbd, 0xc5,
+ 0xba, 0x0a, 0xa3, 0xf3, 0xd9, 0xae, 0x3c, 0x1c,
+ 0x7a, 0x3b, 0x16, 0x96, 0xa0, 0xb6, 0x8c, 0xf7
+ }
+ },
+ {
+ "Jefe",
+ 4,
+ "what do ya want for nothing?",
+ 28,
+ {
+ 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e,
+ 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
+ 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83,
+ 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43
+ }
+ },
+ {
+ {
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
+ },
+ 32,
+ {
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd
+ },
+ 50,
+ {
+ 0xcd, 0xcb, 0x12, 0x20, 0xd1, 0xec, 0xcc, 0xea,
+ 0x91, 0xe5, 0x3a, 0xba, 0x30, 0x92, 0xf9, 0x62,
+ 0xe5, 0x49, 0xfe, 0x6c, 0xe9, 0xed, 0x7f, 0xdc,
+ 0x43, 0x19, 0x1f, 0xbd, 0xe4, 0x5c, 0x30, 0xb0
+ }
+ },
+ {
+ {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+ 0x21, 0x22, 0x23, 0x24, 0x25
+ },
+ 37,
+ {
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd
+ },
+ 50,
+ {
+ 0xd4, 0x63, 0x3c, 0x17, 0xf6, 0xfb, 0x8d, 0x74,
+ 0x4c, 0x66, 0xde, 0xe0, 0xf8, 0xf0, 0x74, 0x55,
+ 0x6e, 0xc4, 0xaf, 0x55, 0xef, 0x07, 0x99, 0x85,
+ 0x41, 0x46, 0x8e, 0xb4, 0x9b, 0xd2, 0xe9, 0x17
+ }
+ },
+ {
+ {
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c
+ },
+ 32,
+ "Test With Truncation",
+ 20,
+ {
+ 0x75, 0x46, 0xaf, 0x01, 0x84, 0x1f, 0xc0, 0x9b,
+ 0x1a, 0xb9, 0xc3, 0x74, 0x9a, 0x5f, 0x1c, 0x17,
+ 0xd4, 0xf5, 0x89, 0x66, 0x8a, 0x58, 0x7b, 0x27,
+ 0x00, 0xa9, 0xc9, 0x7c, 0x11, 0x93, 0xcf, 0x42
+ }
+ },
+ {
+ {
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
+ },
+ 80,
+ "Test Using Larger Than Block-Size Key - Hash Key First",
+ 54,
+ {
+ 0x69, 0x53, 0x02, 0x5e, 0xd9, 0x6f, 0x0c, 0x09,
+ 0xf8, 0x0a, 0x96, 0xf7, 0x8e, 0x65, 0x38, 0xdb,
+ 0xe2, 0xe7, 0xb8, 0x20, 0xe3, 0xdd, 0x97, 0x0e,
+ 0x7d, 0xdd, 0x39, 0x09, 0x1b, 0x32, 0x35, 0x2f
+ }
+ },
+ {
+ {
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
+ },
+ 80,
+ "Test Using Larger Than Block-Size Key and Larger Than One "
+ "Block-Size Data",
+ 73,
+ {
+ 0x63, 0x55, 0xac, 0x22, 0xe8, 0x90, 0xd0, 0xa3,
+ 0xc8, 0x48, 0x1a, 0x5c, 0xa4, 0x82, 0x5b, 0xc8,
+ 0x84, 0xd3, 0xe7, 0xa1, 0xff, 0x98, 0xa2, 0xfc,
+ 0x2a, 0xc7, 0xd8, 0xe0, 0x64, 0xc3, 0xb2, 0xe6
+ }
+ }
+};
+
+
+static int test_sha256(void)
+{
+ unsigned int i;
+ u8 hash[32];
+ const u8 *addr[2];
+ size_t len[2];
+ int errors = 0;
+
+ for (i = 0; i < ARRAY_SIZE(tests); i++) {
+ wpa_printf(MSG_INFO, "SHA256 test case %d:", i + 1);
+
+ addr[0] = (u8 *) tests[i].data;
+ len[0] = strlen(tests[i].data);
+ sha256_vector(1, addr, len, hash);
+ if (memcmp(hash, tests[i].hash, 32) != 0) {
+ wpa_printf(MSG_INFO, " FAIL");
+ errors++;
+ } else
+ wpa_printf(MSG_INFO, " OK");
+
+ if (len[0]) {
+ addr[0] = (u8 *) tests[i].data;
+ len[0] = 1;
+ addr[1] = (u8 *) tests[i].data + 1;
+ len[1] = strlen(tests[i].data) - 1;
+ sha256_vector(2, addr, len, hash);
+ if (memcmp(hash, tests[i].hash, 32) != 0) {
+ wpa_printf(MSG_INFO, " FAIL");
+ errors++;
+ } else
+ wpa_printf(MSG_INFO, " OK");
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(hmac_tests); i++) {
+ struct hmac_test *t = &hmac_tests[i];
+
+ wpa_printf(MSG_INFO, "HMAC-SHA256 test case %d:", i + 1);
+
+ if (hmac_sha256(t->key, t->key_len, t->data, t->data_len,
+ hash) < 0 ||
+ os_memcmp(hash, t->hash, 32) != 0) {
+ wpa_printf(MSG_INFO, " FAIL");
+ errors++;
+ } else
+ wpa_printf(MSG_INFO, " OK");
+
+ addr[0] = t->data;
+ len[0] = t->data_len;
+ if (hmac_sha256_vector(t->key, t->key_len, 1, addr, len,
+ hash) < 0 ||
+ os_memcmp(hash, t->hash, 32) != 0) {
+ wpa_printf(MSG_INFO, " FAIL");
+ errors++;
+ } else
+ wpa_printf(MSG_INFO, " OK");
+
+ if (len[0]) {
+ addr[0] = t->data;
+ len[0] = 1;
+ addr[1] = t->data + 1;
+ len[1] = t->data_len - 1;
+ if (hmac_sha256_vector(t->key, t->key_len, 2, addr, len,
+ hash) < 0 ||
+ os_memcmp(hash, t->hash, 32) != 0) {
+ wpa_printf(MSG_INFO, " FAIL");
+ errors++;
+ } else
+ wpa_printf(MSG_INFO, " OK");
+ }
+ }
+
+ wpa_printf(MSG_INFO, "Test IEEE 802.11r KDF");
+ sha256_prf((u8 *) "abc", 3, "KDF test", (u8 *) "data", 4,
+ hash, sizeof(hash));
+ /* TODO: add proper test case for this */
+
+ if (!errors)
+ wpa_printf(MSG_INFO, "SHA256 test cases passed");
+ return errors;
+}
+
+
+static int test_ms_funcs(void)
+{
+ /* Test vector from RFC2759 example */
+ char *username = "User";
+ char *password = "clientPass";
+ u8 auth_challenge[] = {
+ 0x5B, 0x5D, 0x7C, 0x7D, 0x7B, 0x3F, 0x2F, 0x3E,
+ 0x3C, 0x2C, 0x60, 0x21, 0x32, 0x26, 0x26, 0x28
+ };
+ u8 peer_challenge[] = {
+ 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A,
+ 0x28, 0x29, 0x5F, 0x2B, 0x3A, 0x33, 0x7C, 0x7E
+ };
+ u8 password_hash[] = {
+ 0x44, 0xEB, 0xBA, 0x8D, 0x53, 0x12, 0xB8, 0xD6,
+ 0x11, 0x47, 0x44, 0x11, 0xF5, 0x69, 0x89, 0xAE
+ };
+ u8 nt_response[] = {
+ 0x82, 0x30, 0x9E, 0xCD, 0x8D, 0x70, 0x8B, 0x5E,
+ 0xA0, 0x8F, 0xAA, 0x39, 0x81, 0xCD, 0x83, 0x54,
+ 0x42, 0x33, 0x11, 0x4A, 0x3D, 0x85, 0xD6, 0xDF
+ };
+ u8 password_hash_hash[] = {
+ 0x41, 0xC0, 0x0C, 0x58, 0x4B, 0xD2, 0xD9, 0x1C,
+ 0x40, 0x17, 0xA2, 0xA1, 0x2F, 0xA5, 0x9F, 0x3F
+ };
+ u8 authenticator_response[] = {
+ 0x40, 0x7A, 0x55, 0x89, 0x11, 0x5F, 0xD0, 0xD6,
+ 0x20, 0x9F, 0x51, 0x0F, 0xE9, 0xC0, 0x45, 0x66,
+ 0x93, 0x2C, 0xDA, 0x56
+ };
+ u8 master_key[] = {
+ 0xFD, 0xEC, 0xE3, 0x71, 0x7A, 0x8C, 0x83, 0x8C,
+ 0xB3, 0x88, 0xE5, 0x27, 0xAE, 0x3C, 0xDD, 0x31
+ };
+ u8 send_start_key[] = {
+ 0x8B, 0x7C, 0xDC, 0x14, 0x9B, 0x99, 0x3A, 0x1B,
+ 0xA1, 0x18, 0xCB, 0x15, 0x3F, 0x56, 0xDC, 0xCB
+ };
+ u8 buf[32];
+ int errors = 0;
+
+ if (nt_password_hash((u8 *) password, os_strlen(password), buf) ||
+ os_memcmp(password_hash, buf, sizeof(password_hash)) != 0) {
+ wpa_printf(MSG_ERROR, "nt_password_hash failed");
+ errors++;
+ }
+
+ if (generate_nt_response(auth_challenge, peer_challenge,
+ (u8 *) username, os_strlen(username),
+ (u8 *) password, os_strlen(password), buf) ||
+ os_memcmp(nt_response, buf, sizeof(nt_response)) != 0) {
+ wpa_printf(MSG_ERROR, "generate_nt_response failed");
+ errors++;
+ }
+
+ if (hash_nt_password_hash(password_hash, buf) ||
+ os_memcmp(password_hash_hash, buf,
+ sizeof(password_hash_hash)) != 0) {
+ wpa_printf(MSG_ERROR, "hash_nt_password_hash failed");
+ errors++;
+ }
+
+ if (generate_authenticator_response((u8 *) password,
+ os_strlen(password),
+ peer_challenge, auth_challenge,
+ (u8 *) username,
+ os_strlen(username),
+ nt_response, buf) ||
+ os_memcmp(authenticator_response, buf,
+ sizeof(authenticator_response)) != 0) {
+ wpa_printf(MSG_ERROR, "generate_authenticator_response failed");
+ errors++;
+ }
+
+ if (get_master_key(password_hash_hash, nt_response, buf) ||
+ os_memcmp(master_key, buf, sizeof(master_key)) != 0) {
+ wpa_printf(MSG_ERROR, "get_master_key failed");
+ errors++;
+ }
+
+ if (get_asymetric_start_key(master_key, buf, sizeof(send_start_key),
+ 1, 1) ||
+ os_memcmp(send_start_key, buf, sizeof(send_start_key)) != 0) {
+ wpa_printf(MSG_ERROR, "get_asymetric_start_key failed");
+ errors++;
+ }
+
+ if (errors)
+ wpa_printf(MSG_ERROR, "ms_funcs: %d errors", errors);
+ else
+ wpa_printf(MSG_INFO, "ms_funcs test cases passed");
+
+ return errors;
+}
+
+
+int crypto_module_tests(void)
+{
+ int ret = 0;
+
+ wpa_printf(MSG_INFO, "crypto module tests");
+ if (test_siv() ||
+ test_omac1() ||
+ test_eax() ||
+ test_cbc() ||
+ test_ecb() ||
+ test_key_wrap() ||
+ test_md5() ||
+ test_sha1() ||
+ test_sha256() ||
+ test_ms_funcs())
+ ret = -1;
+
+ return ret;
+}
diff --git a/src/crypto/crypto_nss.c b/src/crypto/crypto_nss.c
deleted file mode 100644
index acd0a55..0000000
--- a/src/crypto/crypto_nss.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Crypto wrapper functions for NSS
- * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "includes.h"
-#include <nspr/prtypes.h>
-#include <nspr/plarenas.h>
-#include <nspr/plhash.h>
-#include <nspr/prtime.h>
-#include <nspr/prinrval.h>
-#include <nspr/prclist.h>
-#include <nspr/prlock.h>
-#include <nss/sechash.h>
-#include <nss/pk11pub.h>
-
-#include "common.h"
-#include "crypto.h"
-
-
-static int nss_hash(HASH_HashType type, unsigned int max_res_len,
- size_t num_elem, const u8 *addr[], const size_t *len,
- u8 *mac)
-{
- HASHContext *ctx;
- size_t i;
- unsigned int reslen;
-
- ctx = HASH_Create(type);
- if (ctx == NULL)
- return -1;
-
- HASH_Begin(ctx);
- for (i = 0; i < num_elem; i++)
- HASH_Update(ctx, addr[i], len[i]);
- HASH_End(ctx, mac, &reslen, max_res_len);
- HASH_Destroy(ctx);
-
- return 0;
-}
-
-
-void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
-{
- PK11Context *ctx = NULL;
- PK11SlotInfo *slot;
- SECItem *param = NULL;
- PK11SymKey *symkey = NULL;
- SECItem item;
- int olen;
- u8 pkey[8], next, tmp;
- int i;
-
- /* Add parity bits to the key */
- next = 0;
- for (i = 0; i < 7; i++) {
- tmp = key[i];
- pkey[i] = (tmp >> i) | next | 1;
- next = tmp << (7 - i);
- }
- pkey[i] = next | 1;
-
- slot = PK11_GetBestSlot(CKM_DES_ECB, NULL);
- if (slot == NULL) {
- wpa_printf(MSG_ERROR, "NSS: PK11_GetBestSlot failed");
- goto out;
- }
-
- item.type = siBuffer;
- item.data = pkey;
- item.len = 8;
- symkey = PK11_ImportSymKey(slot, CKM_DES_ECB, PK11_OriginDerive,
- CKA_ENCRYPT, &item, NULL);
- if (symkey == NULL) {
- wpa_printf(MSG_ERROR, "NSS: PK11_ImportSymKey failed");
- goto out;
- }
-
- param = PK11_GenerateNewParam(CKM_DES_ECB, symkey);
- if (param == NULL) {
- wpa_printf(MSG_ERROR, "NSS: PK11_GenerateNewParam failed");
- goto out;
- }
-
- ctx = PK11_CreateContextBySymKey(CKM_DES_ECB, CKA_ENCRYPT,
- symkey, param);
- if (ctx == NULL) {
- wpa_printf(MSG_ERROR, "NSS: PK11_CreateContextBySymKey("
- "CKM_DES_ECB) failed");
- goto out;
- }
-
- if (PK11_CipherOp(ctx, cypher, &olen, 8, (void *) clear, 8) !=
- SECSuccess) {
- wpa_printf(MSG_ERROR, "NSS: PK11_CipherOp failed");
- goto out;
- }
-
-out:
- if (ctx)
- PK11_DestroyContext(ctx, PR_TRUE);
- if (symkey)
- PK11_FreeSymKey(symkey);
- if (param)
- SECITEM_FreeItem(param, PR_TRUE);
-}
-
-
-int rc4_skip(const u8 *key, size_t keylen, size_t skip,
- u8 *data, size_t data_len)
-{
- return -1;
-}
-
-
-int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
-{
- return nss_hash(HASH_AlgMD5, 16, num_elem, addr, len, mac);
-}
-
-
-int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
-{
- return nss_hash(HASH_AlgSHA1, 20, num_elem, addr, len, mac);
-}
-
-
-int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
- u8 *mac)
-{
- return nss_hash(HASH_AlgSHA256, 32, num_elem, addr, len, mac);
-}
-
-
-void * aes_encrypt_init(const u8 *key, size_t len)
-{
- return NULL;
-}
-
-
-void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
-{
-}
-
-
-void aes_encrypt_deinit(void *ctx)
-{
-}
-
-
-void * aes_decrypt_init(const u8 *key, size_t len)
-{
- return NULL;
-}
-
-
-void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
-{
-}
-
-
-void aes_decrypt_deinit(void *ctx)
-{
-}
-
-
-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)
-{
- return -1;
-}
-
-
-struct crypto_cipher {
-};
-
-
-struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
- const u8 *iv, const u8 *key,
- size_t key_len)
-{
- return NULL;
-}
-
-
-int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
- u8 *crypt, size_t len)
-{
- return -1;
-}
-
-
-int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
- u8 *plain, size_t len)
-{
- return -1;
-}
-
-
-void crypto_cipher_deinit(struct crypto_cipher *ctx)
-{
-}
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index b4c59d1..adb42a4 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -258,7 +258,7 @@
"in AES encrypt", len);
}
EVP_CIPHER_CTX_cleanup(c);
- os_free(c);
+ bin_clear_free(c, sizeof(*c));
}
@@ -309,7 +309,7 @@
"in AES decrypt", len);
}
EVP_CIPHER_CTX_cleanup(c);
- os_free(ctx);
+ bin_clear_free(c, sizeof(*c));
}
@@ -507,8 +507,8 @@
return dh;
err:
- wpabuf_free(pubkey);
- wpabuf_free(privkey);
+ wpabuf_clear_free(pubkey);
+ wpabuf_clear_free(privkey);
DH_free(dh);
return NULL;
}
@@ -581,7 +581,7 @@
err:
BN_clear_free(pub_key);
- wpabuf_free(res);
+ wpabuf_clear_free(res);
return NULL;
}
@@ -638,7 +638,7 @@
HMAC_Init_ex(&ctx->ctx, key, key_len, md, NULL);
#else /* openssl < 0.9.9 */
if (HMAC_Init_ex(&ctx->ctx, key, key_len, md, NULL) != 1) {
- os_free(ctx);
+ bin_clear_free(ctx, sizeof(*ctx));
return NULL;
}
#endif /* openssl < 0.9.9 */
@@ -664,7 +664,7 @@
return -2;
if (mac == NULL || len == NULL) {
- os_free(ctx);
+ bin_clear_free(ctx, sizeof(*ctx));
return 0;
}
@@ -676,7 +676,7 @@
res = HMAC_Final(&ctx->ctx, mac, &mdlen);
#endif /* openssl < 0.9.9 */
HMAC_CTX_cleanup(&ctx->ctx);
- os_free(ctx);
+ bin_clear_free(ctx, sizeof(*ctx));
if (res == 1) {
*len = mdlen;
@@ -693,11 +693,11 @@
#if OPENSSL_VERSION_NUMBER < 0x00908000
if (PKCS5_PBKDF2_HMAC_SHA1(passphrase, os_strlen(passphrase),
(unsigned char *) ssid,
- ssid_len, 4096, buflen, buf) != 1)
+ ssid_len, iterations, buflen, buf) != 1)
return -1;
#else /* openssl < 0.9.8 */
if (PKCS5_PBKDF2_HMAC_SHA1(passphrase, os_strlen(passphrase), ssid,
- ssid_len, 4096, buflen, buf) != 1)
+ ssid_len, iterations, buflen, buf) != 1)
return -1;
#endif /* openssl < 0.9.8 */
return 0;
diff --git a/src/crypto/dh_groups.c b/src/crypto/dh_groups.c
index 58e94c3..d3b2631 100644
--- a/src/crypto/dh_groups.c
+++ b/src/crypto/dh_groups.c
@@ -1198,14 +1198,14 @@
if (dh == NULL)
return NULL;
- wpabuf_free(*priv);
+ wpabuf_clear_free(*priv);
*priv = wpabuf_alloc(dh->prime_len);
if (*priv == NULL)
return NULL;
if (random_get_bytes(wpabuf_put(*priv, dh->prime_len), dh->prime_len))
{
- wpabuf_free(*priv);
+ wpabuf_clear_free(*priv);
*priv = NULL;
return NULL;
}
@@ -1224,7 +1224,7 @@
wpabuf_head(*priv), wpabuf_len(*priv),
dh->prime, dh->prime_len, wpabuf_mhead(pv),
&pv_len) < 0) {
- wpabuf_free(pv);
+ wpabuf_clear_free(pv);
wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed");
return NULL;
}
@@ -1260,7 +1260,7 @@
wpabuf_head(own_private), wpabuf_len(own_private),
dh->prime, dh->prime_len,
wpabuf_mhead(shared), &shared_len) < 0) {
- wpabuf_free(shared);
+ wpabuf_clear_free(shared);
wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed");
return NULL;
}
diff --git a/src/crypto/md5.c b/src/crypto/md5.c
index db2b8cc..f64dfd3 100644
--- a/src/crypto/md5.c
+++ b/src/crypto/md5.c
@@ -30,6 +30,7 @@
u8 tk[16];
const u8 *_addr[6];
size_t i, _len[6];
+ int res;
if (num_elem > 5) {
/*
@@ -85,7 +86,10 @@
_len[0] = 64;
_addr[1] = mac;
_len[1] = MD5_MAC_LEN;
- return md5_vector(2, _addr, _len, mac);
+ res = md5_vector(2, _addr, _len, mac);
+ os_memset(k_pad, 0, sizeof(k_pad));
+ os_memset(tk, 0, sizeof(tk));
+ return res;
}
diff --git a/src/crypto/sha1-prf.c b/src/crypto/sha1-prf.c
index 90b9e74..4b2d137 100644
--- a/src/crypto/sha1-prf.c
+++ b/src/crypto/sha1-prf.c
@@ -61,6 +61,7 @@
}
counter++;
}
+ os_memset(hash, 0, sizeof(hash));
return 0;
}
diff --git a/src/crypto/sha1.c b/src/crypto/sha1.c
index d48c77d..8fce139 100644
--- a/src/crypto/sha1.c
+++ b/src/crypto/sha1.c
@@ -30,6 +30,7 @@
unsigned char tk[20];
const u8 *_addr[6];
size_t _len[6], i;
+ int ret;
if (num_elem > 5) {
/*
@@ -84,7 +85,9 @@
_len[0] = 64;
_addr[1] = mac;
_len[1] = SHA1_MAC_LEN;
- return sha1_vector(2, _addr, _len, mac);
+ ret = sha1_vector(2, _addr, _len, mac);
+ os_memset(k_pad, 0, sizeof(k_pad));
+ return ret;
}
diff --git a/src/crypto/sha256-prf.c b/src/crypto/sha256-prf.c
index 9a11208..79791c0 100644
--- a/src/crypto/sha256-prf.c
+++ b/src/crypto/sha256-prf.c
@@ -95,4 +95,6 @@
u8 mask = 0xff << (8 - buf_len_bits % 8);
buf[pos - 1] &= mask;
}
+
+ os_memset(hash, 0, sizeof(hash));
}
diff --git a/src/crypto/tls.h b/src/crypto/tls.h
index 345ebc7..a4f954c 100644
--- a/src/crypto/tls.h
+++ b/src/crypto/tls.h
@@ -556,4 +556,6 @@
void tls_connection_set_test_flags(struct tls_connection *conn, u32 flags);
+int tls_get_library_version(char *buf, size_t buf_len);
+
#endif /* TLS_H */
diff --git a/src/crypto/tls_gnutls.c b/src/crypto/tls_gnutls.c
index 20d0a31..f2eacb5 100644
--- a/src/crypto/tls_gnutls.c
+++ b/src/crypto/tls_gnutls.c
@@ -12,61 +12,15 @@
#ifdef PKCS12_FUNCS
#include <gnutls/pkcs12.h>
#endif /* PKCS12_FUNCS */
+#if GNUTLS_VERSION_NUMBER >= 0x030103
+#include <gnutls/ocsp.h>
+#endif /* 3.1.3 */
#include "common.h"
+#include "crypto/crypto.h"
#include "tls.h"
-#define WPA_TLS_RANDOM_SIZE 32
-#define WPA_TLS_MASTER_SIZE 48
-
-
-#if LIBGNUTLS_VERSION_NUMBER < 0x010302
-/* GnuTLS 1.3.2 added functions for using master secret. Older versions require
- * use of internal structures to get the master_secret and
- * {server,client}_random.
- */
-#define GNUTLS_INTERNAL_STRUCTURE_HACK
-#endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */
-
-
-#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
-/*
- * It looks like gnutls does not provide access to client/server_random and
- * master_key. This is somewhat unfortunate since these are needed for key
- * derivation in EAP-{TLS,TTLS,PEAP,FAST}. Workaround for now is a horrible
- * hack that copies the gnutls_session_int definition from gnutls_int.h so that
- * we can get the needed information.
- */
-
-typedef u8 uint8;
-typedef unsigned char opaque;
-typedef struct {
- uint8 suite[2];
-} cipher_suite_st;
-
-typedef struct {
- gnutls_connection_end_t entity;
- gnutls_kx_algorithm_t kx_algorithm;
- gnutls_cipher_algorithm_t read_bulk_cipher_algorithm;
- gnutls_mac_algorithm_t read_mac_algorithm;
- gnutls_compression_method_t read_compression_algorithm;
- gnutls_cipher_algorithm_t write_bulk_cipher_algorithm;
- gnutls_mac_algorithm_t write_mac_algorithm;
- gnutls_compression_method_t write_compression_algorithm;
- cipher_suite_st current_cipher_suite;
- opaque master_secret[WPA_TLS_MASTER_SIZE];
- opaque client_random[WPA_TLS_RANDOM_SIZE];
- opaque server_random[WPA_TLS_RANDOM_SIZE];
- /* followed by stuff we are not interested in */
-} security_parameters_st;
-
-struct gnutls_session_int {
- security_parameters_st security_parameters;
- /* followed by things we are not interested in */
-};
-#endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */
-
static int tls_gnutls_ref_count = 0;
struct tls_global {
@@ -78,17 +32,23 @@
int params_set;
gnutls_certificate_credentials_t xcred;
+
+ void (*event_cb)(void *ctx, enum tls_event ev,
+ union tls_event_data *data);
+ void *cb_ctx;
+ int cert_in_cb;
};
struct tls_connection {
+ struct tls_global *global;
gnutls_session_t session;
- char *subject_match, *altsubject_match;
int read_alerts, write_alerts, failed;
u8 *pre_shared_secret;
size_t pre_shared_secret_len;
int established;
int verify_peer;
+ unsigned int disable_time_checks:1;
struct wpabuf *push_buf;
struct wpabuf *pull_buf;
@@ -96,9 +56,15 @@
int params_set;
gnutls_certificate_credentials_t xcred;
+
+ char *suffix_match;
+ unsigned int flags;
};
+static int tls_connection_verify_peer(gnutls_session_t session);
+
+
static void tls_log_func(int level, const char *msg)
{
char *s, *pos;
@@ -129,17 +95,11 @@
{
struct tls_global *global;
-#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
- /* Because of the horrible hack to get master_secret and client/server
- * random, we need to make sure that the gnutls version is something
- * that is expected to have same structure definition for the session
- * data.. */
- const char *ver;
- const char *ok_ver[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", "1.2.9",
- "1.3.2",
- NULL };
- int i;
-#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
+ if (tls_gnutls_ref_count == 0) {
+ wpa_printf(MSG_DEBUG,
+ "GnuTLS: Library version %s (runtime) - %s (build)",
+ gnutls_check_version(NULL), GNUTLS_VERSION);
+ }
global = os_zalloc(sizeof(*global));
if (global == NULL)
@@ -151,28 +111,16 @@
}
tls_gnutls_ref_count++;
-#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
- ver = gnutls_check_version(NULL);
- if (ver == NULL) {
- tls_deinit(global);
- return NULL;
- }
- wpa_printf(MSG_DEBUG, "%s - gnutls version %s", __func__, ver);
- for (i = 0; ok_ver[i]; i++) {
- if (strcmp(ok_ver[i], ver) == 0)
- break;
- }
- if (ok_ver[i] == NULL) {
- wpa_printf(MSG_INFO, "Untested gnutls version %s - this needs "
- "to be tested and enabled in tls_gnutls.c", ver);
- tls_deinit(global);
- return NULL;
- }
-#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
-
gnutls_global_set_log_function(tls_log_func);
if (wpa_debug_show_keys)
gnutls_global_set_log_level(11);
+
+ if (conf) {
+ global->event_cb = conf->event_cb;
+ global->cb_ctx = conf->cb_ctx;
+ global->cert_in_cb = conf->cert_in_cb;
+ }
+
return global;
}
@@ -246,12 +194,7 @@
static int tls_gnutls_init_session(struct tls_global *global,
struct tls_connection *conn)
{
-#if LIBGNUTLS_VERSION_NUMBER >= 0x020200
const char *err;
-#else /* LIBGNUTLS_VERSION_NUMBER >= 0x020200 */
- const int cert_types[2] = { GNUTLS_CRT_X509, 0 };
- const int protos[2] = { GNUTLS_TLS1, 0 };
-#endif /* LIBGNUTLS_VERSION_NUMBER < 0x020200 */
int ret;
ret = gnutls_init(&conn->session,
@@ -266,7 +209,6 @@
if (ret < 0)
goto fail;
-#if LIBGNUTLS_VERSION_NUMBER >= 0x020200
ret = gnutls_priority_set_direct(conn->session, "NORMAL:-VERS-SSL3.0",
&err);
if (ret < 0) {
@@ -274,19 +216,11 @@
"'%s'", err);
goto fail;
}
-#else /* LIBGNUTLS_VERSION_NUMBER >= 0x020200 */
- ret = gnutls_certificate_type_set_priority(conn->session, cert_types);
- if (ret < 0)
- goto fail;
-
- ret = gnutls_protocol_set_priority(conn->session, protos);
- if (ret < 0)
- goto fail;
-#endif /* LIBGNUTLS_VERSION_NUMBER < 0x020200 */
gnutls_transport_set_pull_function(conn->session, tls_pull_func);
gnutls_transport_set_push_function(conn->session, tls_push_func);
gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr_t) conn);
+ gnutls_session_set_ptr(conn->session, conn);
return 0;
@@ -307,6 +241,7 @@
conn = os_zalloc(sizeof(*conn));
if (conn == NULL)
return NULL;
+ conn->global = global;
if (tls_gnutls_init_session(global, conn)) {
os_free(conn);
@@ -342,10 +277,9 @@
gnutls_certificate_free_credentials(conn->xcred);
gnutls_deinit(conn->session);
os_free(conn->pre_shared_secret);
- os_free(conn->subject_match);
- os_free(conn->altsubject_match);
wpabuf_free(conn->push_buf);
wpabuf_free(conn->pull_buf);
+ os_free(conn->suffix_match);
os_free(conn);
}
@@ -403,104 +337,6 @@
}
-#if 0
-static int tls_match_altsubject(X509 *cert, const char *match)
-{
- GENERAL_NAME *gen;
- char *field, *tmp;
- void *ext;
- int i, found = 0;
- size_t len;
-
- ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
-
- for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
- gen = sk_GENERAL_NAME_value(ext, i);
- switch (gen->type) {
- case GEN_EMAIL:
- field = "EMAIL";
- break;
- case GEN_DNS:
- field = "DNS";
- break;
- case GEN_URI:
- field = "URI";
- break;
- default:
- field = NULL;
- wpa_printf(MSG_DEBUG, "TLS: altSubjectName: "
- "unsupported type=%d", gen->type);
- break;
- }
-
- if (!field)
- continue;
-
- wpa_printf(MSG_DEBUG, "TLS: altSubjectName: %s:%s",
- field, gen->d.ia5->data);
- len = os_strlen(field) + 1 +
- strlen((char *) gen->d.ia5->data) + 1;
- tmp = os_malloc(len);
- if (tmp == NULL)
- continue;
- snprintf(tmp, len, "%s:%s", field, gen->d.ia5->data);
- if (strstr(tmp, match))
- found++;
- os_free(tmp);
- }
-
- return found;
-}
-#endif
-
-
-#if 0
-static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
-{
- char buf[256];
- X509 *err_cert;
- int err, depth;
- SSL *ssl;
- struct tls_connection *conn;
- char *match, *altmatch;
-
- err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
- err = X509_STORE_CTX_get_error(x509_ctx);
- depth = X509_STORE_CTX_get_error_depth(x509_ctx);
- ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
- SSL_get_ex_data_X509_STORE_CTX_idx());
- X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
-
- conn = SSL_get_app_data(ssl);
- match = conn ? conn->subject_match : NULL;
- altmatch = conn ? conn->altsubject_match : NULL;
-
- if (!preverify_ok) {
- wpa_printf(MSG_WARNING, "TLS: Certificate verification failed,"
- " error %d (%s) depth %d for '%s'", err,
- X509_verify_cert_error_string(err), depth, buf);
- } else {
- wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - "
- "preverify_ok=%d err=%d (%s) depth=%d buf='%s'",
- preverify_ok, err,
- X509_verify_cert_error_string(err), depth, buf);
- if (depth == 0 && match && strstr(buf, match) == NULL) {
- wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
- "match with '%s'", buf, match);
- preverify_ok = 0;
- } else if (depth == 0 && altmatch &&
- !tls_match_altsubject(err_cert, altmatch)) {
- wpa_printf(MSG_WARNING, "TLS: altSubjectName match "
- "'%s' not found", altmatch);
- preverify_ok = 0;
- }
- }
-
- return preverify_ok;
-}
-#endif
-
-
int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
const struct tls_connection_params *params)
{
@@ -509,86 +345,127 @@
if (conn == NULL || params == NULL)
return -1;
- os_free(conn->subject_match);
- conn->subject_match = NULL;
if (params->subject_match) {
- conn->subject_match = os_strdup(params->subject_match);
- if (conn->subject_match == NULL)
+ wpa_printf(MSG_INFO, "GnuTLS: subject_match not supported");
+ return -1;
+ }
+
+ if (params->altsubject_match) {
+ wpa_printf(MSG_INFO, "GnuTLS: altsubject_match not supported");
+ return -1;
+ }
+
+ os_free(conn->suffix_match);
+ conn->suffix_match = NULL;
+ if (params->suffix_match) {
+ conn->suffix_match = os_strdup(params->suffix_match);
+ if (conn->suffix_match == NULL)
return -1;
}
- os_free(conn->altsubject_match);
- conn->altsubject_match = NULL;
- if (params->altsubject_match) {
- conn->altsubject_match = os_strdup(params->altsubject_match);
- if (conn->altsubject_match == NULL)
- return -1;
+ conn->flags = params->flags;
+
+ if (params->openssl_ciphers) {
+ wpa_printf(MSG_INFO, "GnuTLS: openssl_ciphers not supported");
+ return -1;
}
/* TODO: gnutls_certificate_set_verify_flags(xcred, flags);
* to force peer validation(?) */
if (params->ca_cert) {
- conn->verify_peer = 1;
+ wpa_printf(MSG_DEBUG, "GnuTLS: Try to parse %s in DER format",
+ params->ca_cert);
ret = gnutls_certificate_set_x509_trust_file(
- conn->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM);
+ conn->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
if (ret < 0) {
- wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
- "in PEM format: %s", params->ca_cert,
+ wpa_printf(MSG_DEBUG,
+ "GnuTLS: Failed to read CA cert '%s' in DER format (%s) - try in PEM format",
+ params->ca_cert,
gnutls_strerror(ret));
ret = gnutls_certificate_set_x509_trust_file(
conn->xcred, params->ca_cert,
- GNUTLS_X509_FMT_DER);
+ GNUTLS_X509_FMT_PEM);
if (ret < 0) {
- wpa_printf(MSG_DEBUG, "Failed to read CA cert "
- "'%s' in DER format: %s",
+ wpa_printf(MSG_DEBUG,
+ "Failed to read CA cert '%s' in PEM format: %s",
params->ca_cert,
gnutls_strerror(ret));
return -1;
}
}
+ } else if (params->ca_cert_blob) {
+ gnutls_datum_t ca;
+
+ ca.data = (unsigned char *) params->ca_cert_blob;
+ ca.size = params->ca_cert_blob_len;
+
+ ret = gnutls_certificate_set_x509_trust_mem(
+ conn->xcred, &ca, GNUTLS_X509_FMT_DER);
+ if (ret < 0) {
+ wpa_printf(MSG_DEBUG,
+ "Failed to parse CA cert in DER format: %s",
+ gnutls_strerror(ret));
+ ret = gnutls_certificate_set_x509_trust_mem(
+ conn->xcred, &ca, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ wpa_printf(MSG_DEBUG,
+ "Failed to parse CA cert in PEM format: %s",
+ gnutls_strerror(ret));
+ return -1;
+ }
+ }
+ } else if (params->ca_path) {
+ wpa_printf(MSG_INFO, "GnuTLS: ca_path not supported");
+ return -1;
+ }
+
+ conn->disable_time_checks = 0;
+ if (params->ca_cert || params->ca_cert_blob) {
+ conn->verify_peer = 1;
+ gnutls_certificate_set_verify_function(
+ conn->xcred, tls_connection_verify_peer);
if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
gnutls_certificate_set_verify_flags(
conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
}
-#if LIBGNUTLS_VERSION_NUMBER >= 0x020800
if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
+ conn->disable_time_checks = 1;
gnutls_certificate_set_verify_flags(
conn->xcred,
GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
}
-#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x020800 */
}
if (params->client_cert && params->private_key) {
#if GNUTLS_VERSION_NUMBER >= 0x03010b
ret = gnutls_certificate_set_x509_key_file2(
conn->xcred, params->client_cert, params->private_key,
- GNUTLS_X509_FMT_PEM, params->private_key_passwd, 0);
+ GNUTLS_X509_FMT_DER, params->private_key_passwd, 0);
#else
/* private_key_passwd not (easily) supported here */
ret = gnutls_certificate_set_x509_key_file(
conn->xcred, params->client_cert, params->private_key,
- GNUTLS_X509_FMT_PEM);
+ GNUTLS_X509_FMT_DER);
#endif
if (ret < 0) {
wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
- "in PEM format: %s", gnutls_strerror(ret));
+ "in DER format: %s", gnutls_strerror(ret));
#if GNUTLS_VERSION_NUMBER >= 0x03010b
ret = gnutls_certificate_set_x509_key_file2(
conn->xcred, params->client_cert,
- params->private_key, GNUTLS_X509_FMT_DER,
+ params->private_key, GNUTLS_X509_FMT_PEM,
params->private_key_passwd, 0);
#else
ret = gnutls_certificate_set_x509_key_file(
conn->xcred, params->client_cert,
- params->private_key, GNUTLS_X509_FMT_DER);
+ params->private_key, GNUTLS_X509_FMT_PEM);
#endif
if (ret < 0) {
wpa_printf(MSG_DEBUG, "Failed to read client "
- "cert/key in DER format: %s",
+ "cert/key in PEM format: %s",
gnutls_strerror(ret));
return ret;
}
@@ -597,7 +474,6 @@
int pkcs12_ok = 0;
#ifdef PKCS12_FUNCS
/* Try to load in PKCS#12 format */
-#if LIBGNUTLS_VERSION_NUMBER >= 0x010302
ret = gnutls_certificate_set_x509_simple_pkcs12_file(
conn->xcred, params->private_key, GNUTLS_X509_FMT_DER,
params->private_key_passwd);
@@ -607,7 +483,6 @@
return -1;
} else
pkcs12_ok = 1;
-#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
#endif /* PKCS12_FUNCS */
if (!pkcs12_ok) {
@@ -615,8 +490,82 @@
"included");
return -1;
}
+ } else if (params->client_cert_blob && params->private_key_blob) {
+ gnutls_datum_t cert, key;
+
+ cert.data = (unsigned char *) params->client_cert_blob;
+ cert.size = params->client_cert_blob_len;
+ key.data = (unsigned char *) params->private_key_blob;
+ key.size = params->private_key_blob_len;
+
+#if GNUTLS_VERSION_NUMBER >= 0x03010b
+ ret = gnutls_certificate_set_x509_key_mem2(
+ conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER,
+ params->private_key_passwd, 0);
+#else
+ /* private_key_passwd not (easily) supported here */
+ ret = gnutls_certificate_set_x509_key_mem(
+ conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER);
+#endif
+ if (ret < 0) {
+ wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
+ "in DER format: %s", gnutls_strerror(ret));
+#if GNUTLS_VERSION_NUMBER >= 0x03010b
+ ret = gnutls_certificate_set_x509_key_mem2(
+ conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM,
+ params->private_key_passwd, 0);
+#else
+ /* private_key_passwd not (easily) supported here */
+ ret = gnutls_certificate_set_x509_key_mem(
+ conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM);
+#endif
+ if (ret < 0) {
+ wpa_printf(MSG_DEBUG, "Failed to read client "
+ "cert/key in PEM format: %s",
+ gnutls_strerror(ret));
+ return ret;
+ }
+ }
+ } else if (params->private_key_blob) {
+#ifdef PKCS12_FUNCS
+ gnutls_datum_t key;
+
+ key.data = (unsigned char *) params->private_key_blob;
+ key.size = params->private_key_blob_len;
+
+ /* Try to load in PKCS#12 format */
+ ret = gnutls_certificate_set_x509_simple_pkcs12_mem(
+ conn->xcred, &key, GNUTLS_X509_FMT_DER,
+ params->private_key_passwd);
+ if (ret != 0) {
+ wpa_printf(MSG_DEBUG, "Failed to load private_key in "
+ "PKCS#12 format: %s", gnutls_strerror(ret));
+ return -1;
+ }
+#else /* PKCS12_FUNCS */
+ wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not included");
+ return -1;
+#endif /* PKCS12_FUNCS */
}
+#if GNUTLS_VERSION_NUMBER >= 0x030103
+ if (params->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)) {
+ ret = gnutls_ocsp_status_request_enable_client(conn->session,
+ NULL, 0, NULL);
+ if (ret != GNUTLS_E_SUCCESS) {
+ wpa_printf(MSG_INFO,
+ "GnuTLS: Failed to enable OCSP client");
+ return -1;
+ }
+ }
+#else /* 3.1.3 */
+ if (params->flags & TLS_CONN_REQUIRE_OCSP) {
+ wpa_printf(MSG_INFO,
+ "GnuTLS: OCSP not supported by this version of GnuTLS");
+ return -1;
+ }
+#endif /* 3.1.3 */
+
conn->params_set = 1;
ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
@@ -654,17 +603,17 @@
if (params->ca_cert) {
ret = gnutls_certificate_set_x509_trust_file(
- global->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM);
+ global->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
if (ret < 0) {
wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
- "in PEM format: %s", params->ca_cert,
+ "in DER format: %s", params->ca_cert,
gnutls_strerror(ret));
ret = gnutls_certificate_set_x509_trust_file(
global->xcred, params->ca_cert,
- GNUTLS_X509_FMT_DER);
+ GNUTLS_X509_FMT_PEM);
if (ret < 0) {
wpa_printf(MSG_DEBUG, "Failed to read CA cert "
- "'%s' in DER format: %s",
+ "'%s' in PEM format: %s",
params->ca_cert,
gnutls_strerror(ret));
goto fail;
@@ -677,29 +626,27 @@
GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
}
-#if LIBGNUTLS_VERSION_NUMBER >= 0x020800
if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
gnutls_certificate_set_verify_flags(
global->xcred,
GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
}
-#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x020800 */
}
if (params->client_cert && params->private_key) {
/* TODO: private_key_passwd? */
ret = gnutls_certificate_set_x509_key_file(
global->xcred, params->client_cert,
- params->private_key, GNUTLS_X509_FMT_PEM);
+ params->private_key, GNUTLS_X509_FMT_DER);
if (ret < 0) {
wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
- "in PEM format: %s", gnutls_strerror(ret));
+ "in DER format: %s", gnutls_strerror(ret));
ret = gnutls_certificate_set_x509_key_file(
global->xcred, params->client_cert,
- params->private_key, GNUTLS_X509_FMT_DER);
+ params->private_key, GNUTLS_X509_FMT_PEM);
if (ret < 0) {
wpa_printf(MSG_DEBUG, "Failed to read client "
- "cert/key in DER format: %s",
+ "cert/key in PEM format: %s",
gnutls_strerror(ret));
goto fail;
}
@@ -708,7 +655,6 @@
int pkcs12_ok = 0;
#ifdef PKCS12_FUNCS
/* Try to load in PKCS#12 format */
-#if LIBGNUTLS_VERSION_NUMBER >= 0x010302
ret = gnutls_certificate_set_x509_simple_pkcs12_file(
global->xcred, params->private_key,
GNUTLS_X509_FMT_DER, params->private_key_passwd);
@@ -718,7 +664,6 @@
goto fail;
} else
pkcs12_ok = 1;
-#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
#endif /* PKCS12_FUNCS */
if (!pkcs12_ok) {
@@ -763,37 +708,23 @@
int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
struct tls_keys *keys)
{
-#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
- security_parameters_st *sec;
-#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
+#if GNUTLS_VERSION_NUMBER >= 0x030012
+ gnutls_datum_t client, server;
if (conn == NULL || conn->session == NULL || keys == NULL)
return -1;
os_memset(keys, 0, sizeof(*keys));
-
-#if LIBGNUTLS_VERSION_NUMBER < 0x020c00
-#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
- sec = &conn->session->security_parameters;
- keys->master_key = sec->master_secret;
- keys->master_key_len = WPA_TLS_MASTER_SIZE;
- keys->client_random = sec->client_random;
- keys->server_random = sec->server_random;
-#else /* GNUTLS_INTERNAL_STRUCTURE_HACK */
- keys->client_random =
- (u8 *) gnutls_session_get_client_random(conn->session);
- keys->server_random =
- (u8 *) gnutls_session_get_server_random(conn->session);
- /* No access to master_secret */
-#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
-#endif /* LIBGNUTLS_VERSION_NUMBER < 0x020c00 */
-
-#if LIBGNUTLS_VERSION_NUMBER < 0x020c00
- keys->client_random_len = WPA_TLS_RANDOM_SIZE;
- keys->server_random_len = WPA_TLS_RANDOM_SIZE;
-#endif /* LIBGNUTLS_VERSION_NUMBER < 0x020c00 */
+ gnutls_session_get_random(conn->session, &client, &server);
+ keys->client_random = client.data;
+ keys->server_random = server.data;
+ keys->client_random_len = client.size;
+ keys->server_random_len = client.size;
return 0;
+#else /* 3.0.18 */
+ return -1;
+#endif /* 3.0.18 */
}
@@ -801,86 +732,317 @@
const char *label, int server_random_first,
u8 *out, size_t out_len)
{
-#if LIBGNUTLS_VERSION_NUMBER >= 0x010302
if (conn == NULL || conn->session == NULL)
return -1;
return gnutls_prf(conn->session, os_strlen(label), label,
server_random_first, 0, NULL, out_len, (char *) out);
-#else /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
- return -1;
-#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
}
-static int tls_connection_verify_peer(struct tls_connection *conn,
- gnutls_alert_description_t *err)
+static void gnutls_tls_fail_event(struct tls_connection *conn,
+ const gnutls_datum_t *cert, int depth,
+ const char *subject, const char *err_str,
+ enum tls_fail_reason reason)
{
+ union tls_event_data ev;
+ struct tls_global *global = conn->global;
+ struct wpabuf *cert_buf = NULL;
+
+ if (global->event_cb == NULL)
+ return;
+
+ os_memset(&ev, 0, sizeof(ev));
+ ev.cert_fail.depth = depth;
+ ev.cert_fail.subject = subject ? subject : "";
+ ev.cert_fail.reason = reason;
+ ev.cert_fail.reason_txt = err_str;
+ if (cert) {
+ cert_buf = wpabuf_alloc_copy(cert->data, cert->size);
+ ev.cert_fail.cert = cert_buf;
+ }
+ global->event_cb(global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
+ wpabuf_free(cert_buf);
+}
+
+
+#if GNUTLS_VERSION_NUMBER < 0x030300
+static int server_eku_purpose(gnutls_x509_crt_t cert)
+{
+ unsigned int i;
+
+ for (i = 0; ; i++) {
+ char oid[128];
+ size_t oid_size = sizeof(oid);
+ int res;
+
+ res = gnutls_x509_crt_get_key_purpose_oid(cert, i, oid,
+ &oid_size, NULL);
+ if (res == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+ if (i == 0) {
+ /* No EKU - assume any use allowed */
+ return 1;
+ }
+ break;
+ }
+
+ if (res < 0) {
+ wpa_printf(MSG_INFO, "GnuTLS: Failed to get EKU");
+ return 0;
+ }
+
+ wpa_printf(MSG_DEBUG, "GnuTLS: Certificate purpose: %s", oid);
+ if (os_strcmp(oid, GNUTLS_KP_TLS_WWW_SERVER) == 0 ||
+ os_strcmp(oid, GNUTLS_KP_ANY) == 0)
+ return 1;
+ }
+
+ return 0;
+}
+#endif /* < 3.3.0 */
+
+
+static int check_ocsp(struct tls_connection *conn, gnutls_session_t session,
+ gnutls_alert_description_t *err)
+{
+#if GNUTLS_VERSION_NUMBER >= 0x030103
+ gnutls_datum_t response, buf;
+ gnutls_ocsp_resp_t resp;
+ unsigned int cert_status;
+ int res;
+
+ if (!(conn->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)))
+ return 0;
+
+ if (!gnutls_ocsp_status_request_is_checked(session, 0)) {
+ if (conn->flags & TLS_CONN_REQUIRE_OCSP) {
+ wpa_printf(MSG_INFO,
+ "GnuTLS: No valid OCSP response received");
+ goto ocsp_error;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "GnuTLS: Valid OCSP response was not received - continue since OCSP was not required");
+ return 0;
+ }
+
+ /*
+ * GnuTLS has already verified the OCSP response in
+ * check_ocsp_response() and rejected handshake if the certificate was
+ * found to be revoked. However, if the response indicates that the
+ * status is unknown, handshake continues and reaches here. We need to
+ * re-import the OCSP response to check for unknown certificate status,
+ * but we do not need to repeat gnutls_ocsp_resp_check_crt() and
+ * gnutls_ocsp_resp_verify_direct() calls.
+ */
+
+ res = gnutls_ocsp_status_request_get(session, &response);
+ if (res != GNUTLS_E_SUCCESS) {
+ wpa_printf(MSG_INFO,
+ "GnuTLS: OCSP response was received, but it was not valid");
+ goto ocsp_error;
+ }
+
+ if (gnutls_ocsp_resp_init(&resp) != GNUTLS_E_SUCCESS)
+ goto ocsp_error;
+
+ res = gnutls_ocsp_resp_import(resp, &response);
+ if (res != GNUTLS_E_SUCCESS) {
+ wpa_printf(MSG_INFO,
+ "GnuTLS: Could not parse received OCSP response: %s",
+ gnutls_strerror(res));
+ gnutls_ocsp_resp_deinit(resp);
+ goto ocsp_error;
+ }
+
+ res = gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &buf);
+ if (res == GNUTLS_E_SUCCESS) {
+ wpa_printf(MSG_DEBUG, "GnuTLS: %s", buf.data);
+ gnutls_free(buf.data);
+ }
+
+ res = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL,
+ NULL, &cert_status, NULL,
+ NULL, NULL, NULL);
+ gnutls_ocsp_resp_deinit(resp);
+ if (res != GNUTLS_E_SUCCESS) {
+ wpa_printf(MSG_INFO,
+ "GnuTLS: Failed to extract OCSP information: %s",
+ gnutls_strerror(res));
+ goto ocsp_error;
+ }
+
+ if (cert_status == GNUTLS_OCSP_CERT_GOOD) {
+ wpa_printf(MSG_DEBUG, "GnuTLS: OCSP cert status: good");
+ } else if (cert_status == GNUTLS_OCSP_CERT_REVOKED) {
+ wpa_printf(MSG_DEBUG,
+ "GnuTLS: OCSP cert status: revoked");
+ goto ocsp_error;
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "GnuTLS: OCSP cert status: unknown");
+ if (conn->flags & TLS_CONN_REQUIRE_OCSP)
+ goto ocsp_error;
+ wpa_printf(MSG_DEBUG,
+ "GnuTLS: OCSP was not required, so allow connection to continue");
+ }
+
+ return 0;
+
+ocsp_error:
+ gnutls_tls_fail_event(conn, NULL, 0, NULL,
+ "bad certificate status response",
+ TLS_FAIL_REVOKED);
+ *err = GNUTLS_A_CERTIFICATE_REVOKED;
+ return -1;
+#else /* GnuTLS 3.1.3 or newer */
+ return 0;
+#endif /* GnuTLS 3.1.3 or newer */
+}
+
+
+static int tls_connection_verify_peer(gnutls_session_t session)
+{
+ struct tls_connection *conn;
unsigned int status, num_certs, i;
struct os_time now;
const gnutls_datum_t *certs;
gnutls_x509_crt_t cert;
+ gnutls_alert_description_t err;
+ int res;
- if (gnutls_certificate_verify_peers2(conn->session, &status) < 0) {
+ conn = gnutls_session_get_ptr(session);
+ if (!conn->verify_peer) {
+ wpa_printf(MSG_DEBUG,
+ "GnuTLS: No peer certificate verification enabled");
+ return 0;
+ }
+
+ wpa_printf(MSG_DEBUG, "GnuTSL: Verifying peer certificate");
+
+#if GNUTLS_VERSION_NUMBER >= 0x030300
+ {
+ gnutls_typed_vdata_st data[1];
+ unsigned int elements = 0;
+
+ os_memset(data, 0, sizeof(data));
+ if (!conn->global->server) {
+ data[elements].type = GNUTLS_DT_KEY_PURPOSE_OID;
+ data[elements].data = (void *) GNUTLS_KP_TLS_WWW_SERVER;
+ elements++;
+ }
+ res = gnutls_certificate_verify_peers(session, data, 1,
+ &status);
+ }
+#else /* < 3.3.0 */
+ res = gnutls_certificate_verify_peers2(session, &status);
+#endif
+ if (res < 0) {
wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
"certificate chain");
- *err = GNUTLS_A_INTERNAL_ERROR;
- return -1;
+ err = GNUTLS_A_INTERNAL_ERROR;
+ goto out;
+ }
+
+#if GNUTLS_VERSION_NUMBER >= 0x030104
+ {
+ gnutls_datum_t info;
+ int ret, type;
+
+ type = gnutls_certificate_type_get(session);
+ ret = gnutls_certificate_verification_status_print(status, type,
+ &info, 0);
+ if (ret < 0) {
+ wpa_printf(MSG_DEBUG,
+ "GnuTLS: Failed to print verification status");
+ err = GNUTLS_A_INTERNAL_ERROR;
+ goto out;
+ }
+ wpa_printf(MSG_DEBUG, "GnuTLS: %s", info.data);
+ gnutls_free(info.data);
+ }
+#endif /* GnuTLS 3.1.4 or newer */
+
+ certs = gnutls_certificate_get_peers(session, &num_certs);
+ if (certs == NULL || num_certs == 0) {
+ wpa_printf(MSG_INFO, "TLS: No peer certificate chain received");
+ err = GNUTLS_A_UNKNOWN_CA;
+ goto out;
}
if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
- *err = GNUTLS_A_INTERNAL_ERROR;
if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
wpa_printf(MSG_INFO, "TLS: Certificate uses insecure "
"algorithm");
- *err = GNUTLS_A_INSUFFICIENT_SECURITY;
+ gnutls_tls_fail_event(conn, NULL, 0, NULL,
+ "certificate uses insecure algorithm",
+ TLS_FAIL_BAD_CERTIFICATE);
+ err = GNUTLS_A_INSUFFICIENT_SECURITY;
+ goto out;
}
-#if LIBGNUTLS_VERSION_NUMBER >= 0x020800
if (status & GNUTLS_CERT_NOT_ACTIVATED) {
wpa_printf(MSG_INFO, "TLS: Certificate not yet "
"activated");
- *err = GNUTLS_A_CERTIFICATE_EXPIRED;
+ gnutls_tls_fail_event(conn, NULL, 0, NULL,
+ "certificate not yet valid",
+ TLS_FAIL_NOT_YET_VALID);
+ err = GNUTLS_A_CERTIFICATE_EXPIRED;
+ goto out;
}
if (status & GNUTLS_CERT_EXPIRED) {
wpa_printf(MSG_INFO, "TLS: Certificate expired");
- *err = GNUTLS_A_CERTIFICATE_EXPIRED;
+ gnutls_tls_fail_event(conn, NULL, 0, NULL,
+ "certificate has expired",
+ TLS_FAIL_EXPIRED);
+ err = GNUTLS_A_CERTIFICATE_EXPIRED;
+ goto out;
}
-#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x020800 */
- return -1;
+ gnutls_tls_fail_event(conn, NULL, 0, NULL,
+ "untrusted certificate",
+ TLS_FAIL_UNTRUSTED);
+ err = GNUTLS_A_INTERNAL_ERROR;
+ goto out;
}
if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
"known issuer");
- *err = GNUTLS_A_UNKNOWN_CA;
- return -1;
+ gnutls_tls_fail_event(conn, NULL, 0, NULL, "signed not found",
+ TLS_FAIL_UNTRUSTED);
+ err = GNUTLS_A_UNKNOWN_CA;
+ goto out;
}
if (status & GNUTLS_CERT_REVOKED) {
wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
- *err = GNUTLS_A_CERTIFICATE_REVOKED;
- return -1;
+ gnutls_tls_fail_event(conn, NULL, 0, NULL,
+ "certificate revoked",
+ TLS_FAIL_REVOKED);
+ err = GNUTLS_A_CERTIFICATE_REVOKED;
+ goto out;
}
+ if (status != 0) {
+ wpa_printf(MSG_INFO, "TLS: Unknown verification status: %d",
+ status);
+ err = GNUTLS_A_INTERNAL_ERROR;
+ goto out;
+ }
+
+ if (check_ocsp(conn, session, &err))
+ goto out;
+
os_get_time(&now);
- certs = gnutls_certificate_get_peers(conn->session, &num_certs);
- if (certs == NULL) {
- wpa_printf(MSG_INFO, "TLS: No peer certificate chain "
- "received");
- *err = GNUTLS_A_UNKNOWN_CA;
- return -1;
- }
-
for (i = 0; i < num_certs; i++) {
char *buf;
size_t len;
if (gnutls_x509_crt_init(&cert) < 0) {
wpa_printf(MSG_INFO, "TLS: Certificate initialization "
"failed");
- *err = GNUTLS_A_BAD_CERTIFICATE;
- return -1;
+ err = GNUTLS_A_BAD_CERTIFICATE;
+ goto out;
}
if (gnutls_x509_crt_import(cert, &certs[i],
@@ -888,8 +1050,8 @@
wpa_printf(MSG_INFO, "TLS: Could not parse peer "
"certificate %d/%d", i + 1, num_certs);
gnutls_x509_crt_deinit(cert);
- *err = GNUTLS_A_BAD_CERTIFICATE;
- return -1;
+ err = GNUTLS_A_BAD_CERTIFICATE;
+ goto out;
}
gnutls_x509_crt_get_dn(cert, NULL, &len);
@@ -902,26 +1064,109 @@
wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
i + 1, num_certs, buf);
+ if (conn->global->event_cb) {
+ struct wpabuf *cert_buf = NULL;
+ union tls_event_data ev;
+#ifdef CONFIG_SHA256
+ u8 hash[32];
+ const u8 *_addr[1];
+ size_t _len[1];
+#endif /* CONFIG_SHA256 */
+
+ os_memset(&ev, 0, sizeof(ev));
+ if (conn->global->cert_in_cb) {
+ cert_buf = wpabuf_alloc_copy(certs[i].data,
+ certs[i].size);
+ ev.peer_cert.cert = cert_buf;
+ }
+#ifdef CONFIG_SHA256
+ _addr[0] = certs[i].data;
+ _len[0] = certs[i].size;
+ if (sha256_vector(1, _addr, _len, hash) == 0) {
+ ev.peer_cert.hash = hash;
+ ev.peer_cert.hash_len = sizeof(hash);
+ }
+#endif /* CONFIG_SHA256 */
+ ev.peer_cert.depth = i;
+ ev.peer_cert.subject = buf;
+ conn->global->event_cb(conn->global->cb_ctx,
+ TLS_PEER_CERTIFICATE, &ev);
+ wpabuf_free(cert_buf);
+ }
+
if (i == 0) {
- /* TODO: validate subject_match and altsubject_match */
+ if (conn->suffix_match &&
+ !gnutls_x509_crt_check_hostname(
+ cert, conn->suffix_match)) {
+ wpa_printf(MSG_WARNING,
+ "TLS: Domain suffix match '%s' not found",
+ conn->suffix_match);
+ gnutls_tls_fail_event(
+ conn, &certs[i], i, buf,
+ "Domain suffix mismatch",
+ TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
+ err = GNUTLS_A_BAD_CERTIFICATE;
+ gnutls_x509_crt_deinit(cert);
+ os_free(buf);
+ goto out;
+ }
+
+ /* TODO: validate altsubject_match.
+ * For now, any such configuration is rejected in
+ * tls_connection_set_params() */
+
+#if GNUTLS_VERSION_NUMBER < 0x030300
+ /*
+ * gnutls_certificate_verify_peers() not available, so
+ * need to check EKU separately.
+ */
+ if (!conn->global->server &&
+ !server_eku_purpose(cert)) {
+ wpa_printf(MSG_WARNING,
+ "GnuTLS: No server EKU");
+ gnutls_tls_fail_event(
+ conn, &certs[i], i, buf,
+ "No server EKU",
+ TLS_FAIL_BAD_CERTIFICATE);
+ err = GNUTLS_A_BAD_CERTIFICATE;
+ gnutls_x509_crt_deinit(cert);
+ os_free(buf);
+ goto out;
+ }
+#endif /* < 3.3.0 */
+ }
+
+ if (!conn->disable_time_checks &&
+ (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
+ gnutls_x509_crt_get_activation_time(cert) > now.sec)) {
+ wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
+ "not valid at this time",
+ i + 1, num_certs);
+ gnutls_tls_fail_event(
+ conn, &certs[i], i, buf,
+ "Certificate is not valid at this time",
+ TLS_FAIL_EXPIRED);
+ gnutls_x509_crt_deinit(cert);
+ os_free(buf);
+ err = GNUTLS_A_CERTIFICATE_EXPIRED;
+ goto out;
}
os_free(buf);
- if (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
- gnutls_x509_crt_get_activation_time(cert) > now.sec) {
- wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
- "not valid at this time",
- i + 1, num_certs);
- gnutls_x509_crt_deinit(cert);
- *err = GNUTLS_A_CERTIFICATE_EXPIRED;
- return -1;
- }
-
gnutls_x509_crt_deinit(cert);
}
+ if (conn->global->event_cb != NULL)
+ conn->global->event_cb(conn->global->cb_ctx,
+ TLS_CERT_CHAIN_SUCCESS, NULL);
+
return 0;
+
+out:
+ conn->failed++;
+ gnutls_alert_send(session, GNUTLS_AL_FATAL, err);
+ return GNUTLS_E_CERTIFICATE_ERROR;
}
@@ -979,6 +1224,8 @@
ret = gnutls_handshake(conn->session);
if (ret < 0) {
+ gnutls_alert_description_t alert;
+
switch (ret) {
case GNUTLS_E_AGAIN:
if (global->server && conn->established &&
@@ -989,10 +1236,20 @@
}
break;
case GNUTLS_E_FATAL_ALERT_RECEIVED:
+ alert = gnutls_alert_get(conn->session);
wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
- __func__, gnutls_alert_get_name(
- gnutls_alert_get(conn->session)));
+ __func__, gnutls_alert_get_name(alert));
conn->read_alerts++;
+ if (conn->global->event_cb != NULL) {
+ union tls_event_data ev;
+
+ os_memset(&ev, 0, sizeof(ev));
+ ev.alert.is_local = 0;
+ ev.alert.type = gnutls_alert_get_name(alert);
+ ev.alert.description = ev.alert.type;
+ conn->global->event_cb(conn->global->cb_ctx,
+ TLS_ALERT, &ev);
+ }
/* continue */
default:
wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
@@ -1001,18 +1258,21 @@
}
} else {
size_t size;
- gnutls_alert_description_t err;
-
- if (conn->verify_peer &&
- tls_connection_verify_peer(conn, &err)) {
- wpa_printf(MSG_INFO, "TLS: Peer certificate chain "
- "failed validation");
- conn->failed++;
- gnutls_alert_send(conn->session, GNUTLS_AL_FATAL, err);
- goto out;
- }
wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
+
+#if GNUTLS_VERSION_NUMBER >= 0x03010a
+ {
+ char *desc;
+
+ desc = gnutls_session_get_desc(conn->session);
+ if (desc) {
+ wpa_printf(MSG_DEBUG, "GnuTLS: %s", desc);
+ gnutls_free(desc);
+ }
+ }
+#endif /* GnuTLS 3.1.10 or newer */
+
conn->established = 1;
if (conn->push_buf == NULL) {
/* Need to return something to get final TLS ACK. */
@@ -1036,7 +1296,6 @@
*appl_data = gnutls_get_appl_data(conn);
}
-out:
out_data = conn->push_buf;
conn->push_buf = NULL;
return out_data;
@@ -1201,3 +1460,10 @@
{
return -1;
}
+
+
+int tls_get_library_version(char *buf, size_t buf_len)
+{
+ return os_snprintf(buf, buf_len, "GnuTLS build=%s run=%s",
+ GNUTLS_VERSION, gnutls_check_version(NULL));
+}
diff --git a/src/crypto/tls_internal.c b/src/crypto/tls_internal.c
index 6563ed2..86375d1 100644
--- a/src/crypto/tls_internal.c
+++ b/src/crypto/tls_internal.c
@@ -190,6 +190,26 @@
if (cred == NULL)
return -1;
+ if (params->subject_match) {
+ wpa_printf(MSG_INFO, "TLS: subject_match not supported");
+ return -1;
+ }
+
+ if (params->altsubject_match) {
+ wpa_printf(MSG_INFO, "TLS: altsubject_match not supported");
+ return -1;
+ }
+
+ if (params->suffix_match) {
+ wpa_printf(MSG_INFO, "TLS: suffix_match not supported");
+ return -1;
+ }
+
+ if (params->openssl_ciphers) {
+ wpa_printf(MSG_INFO, "GnuTLS: openssl_ciphers not supported");
+ return -1;
+ }
+
if (tlsv1_set_ca_cert(cred, params->ca_cert,
params->ca_cert_blob, params->ca_cert_blob_len,
params->ca_path)) {
@@ -652,3 +672,9 @@
#endif /* CONFIG_TLS_INTERNAL_SERVER */
return -1;
}
+
+
+int tls_get_library_version(char *buf, size_t buf_len)
+{
+ return os_snprintf(buf, buf_len, "internal");
+}
diff --git a/src/crypto/tls_none.c b/src/crypto/tls_none.c
index 1a1092a..a6d210a 100644
--- a/src/crypto/tls_none.c
+++ b/src/crypto/tls_none.c
@@ -192,3 +192,9 @@
{
return 0;
}
+
+
+int tls_get_library_version(char *buf, size_t buf_len)
+{
+ return os_snprintf(buf, buf_len, "none");
+}
diff --git a/src/crypto/tls_nss.c b/src/crypto/tls_nss.c
deleted file mode 100644
index c53c192..0000000
--- a/src/crypto/tls_nss.c
+++ /dev/null
@@ -1,645 +0,0 @@
-/*
- * SSL/TLS interface functions for NSS
- * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "includes.h"
-#include <nspr/prtypes.h>
-#include <nspr/plarenas.h>
-#include <nspr/plhash.h>
-#include <nspr/prio.h>
-#include <nspr/prclist.h>
-#include <nspr/prlock.h>
-#include <nspr/prinit.h>
-#include <nspr/prerror.h>
-#include <nspr/prmem.h>
-#include <nss/nss.h>
-#include <nss/nssilckt.h>
-#include <nss/ssl.h>
-#include <nss/pk11func.h>
-#include <nss/secerr.h>
-
-#include "common.h"
-#include "tls.h"
-
-static int tls_nss_ref_count = 0;
-
-static PRDescIdentity nss_layer_id;
-
-
-struct tls_connection {
- PRFileDesc *fd;
-
- int established;
- int verify_peer;
- u8 *push_buf, *pull_buf, *pull_buf_offset;
- size_t push_buf_len, pull_buf_len;
-};
-
-
-static PRStatus nss_io_close(PRFileDesc *fd)
-{
- wpa_printf(MSG_DEBUG, "NSS: I/O close");
- return PR_SUCCESS;
-}
-
-
-static PRInt32 nss_io_read(PRFileDesc *fd, void *buf, PRInt32 amount)
-{
- wpa_printf(MSG_DEBUG, "NSS: I/O read(%d)", amount);
- return PR_FAILURE;
-}
-
-
-static PRInt32 nss_io_write(PRFileDesc *fd, const void *buf, PRInt32 amount)
-{
- wpa_printf(MSG_DEBUG, "NSS: I/O write(%d)", amount);
- return PR_FAILURE;
-}
-
-
-static PRInt32 nss_io_writev(PRFileDesc *fd, const PRIOVec *iov,
- PRInt32 iov_size, PRIntervalTime timeout)
-{
- wpa_printf(MSG_DEBUG, "NSS: I/O writev(%d)", iov_size);
- return PR_FAILURE;
-}
-
-
-static PRInt32 nss_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
- PRIntn flags, PRIntervalTime timeout)
-{
- struct tls_connection *conn = (struct tls_connection *) fd->secret;
- u8 *end;
-
- wpa_printf(MSG_DEBUG, "NSS: I/O recv(%d)", amount);
-
- if (conn->pull_buf == NULL) {
- wpa_printf(MSG_DEBUG, "NSS: No data available to be read yet");
- return PR_FAILURE;
- }
-
- end = conn->pull_buf + conn->pull_buf_len;
- if (end - conn->pull_buf_offset < amount)
- amount = end - conn->pull_buf_offset;
- os_memcpy(buf, conn->pull_buf_offset, amount);
- conn->pull_buf_offset += amount;
- if (conn->pull_buf_offset == end) {
- wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
- os_free(conn->pull_buf);
- conn->pull_buf = conn->pull_buf_offset = NULL;
- conn->pull_buf_len = 0;
- } else {
- wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf",
- __func__,
- (unsigned long) (end - conn->pull_buf_offset));
- }
- return amount;
-}
-
-
-static PRInt32 nss_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount,
- PRIntn flags, PRIntervalTime timeout)
-{
- struct tls_connection *conn = (struct tls_connection *) fd->secret;
- u8 *nbuf;
-
- wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__);
- wpa_hexdump(MSG_MSGDUMP, "NSS: I/O send data", buf, amount);
-
- nbuf = os_realloc(conn->push_buf, conn->push_buf_len + amount);
- if (nbuf == NULL) {
- wpa_printf(MSG_ERROR, "NSS: Failed to allocate memory for the "
- "data to be sent");
- return PR_FAILURE;
- }
- os_memcpy(nbuf + conn->push_buf_len, buf, amount);
- conn->push_buf = nbuf;
- conn->push_buf_len += amount;
-
- return amount;
-}
-
-
-static PRInt32 nss_io_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount,
- PRIntn flags, PRNetAddr *addr,
- PRIntervalTime timeout)
-{
- wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__);
- return PR_FAILURE;
-}
-
-
-static PRInt32 nss_io_sendto(PRFileDesc *fd, const void *buf, PRInt32 amount,
- PRIntn flags, const PRNetAddr *addr,
- PRIntervalTime timeout)
-{
- wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__);
- return PR_FAILURE;
-}
-
-
-static PRStatus nss_io_getpeername(PRFileDesc *fd, PRNetAddr *addr)
-{
- wpa_printf(MSG_DEBUG, "NSS: I/O getpeername");
-
- /*
- * It Looks like NSS only supports IPv4 and IPv6 TCP sockets. Provide a
- * fake IPv4 address to work around this even though we are not really
- * using TCP.
- */
- os_memset(addr, 0, sizeof(*addr));
- addr->inet.family = PR_AF_INET;
-
- return PR_SUCCESS;
-}
-
-
-static PRStatus nss_io_getsocketoption(PRFileDesc *fd,
- PRSocketOptionData *data)
-{
- switch (data->option) {
- case PR_SockOpt_Nonblocking:
- wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(Nonblocking)");
- data->value.non_blocking = PR_TRUE;
- return PR_SUCCESS;
- default:
- wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(%d)",
- data->option);
- return PR_FAILURE;
- }
-}
-
-
-static const PRIOMethods nss_io = {
- PR_DESC_LAYERED,
- nss_io_close,
- nss_io_read,
- nss_io_write,
- NULL /* available */,
- NULL /* available64 */,
- NULL /* fsync */,
- NULL /* fseek */,
- NULL /* fseek64 */,
- NULL /* fileinfo */,
- NULL /* fileinfo64 */,
- nss_io_writev,
- NULL /* connect */,
- NULL /* accept */,
- NULL /* bind */,
- NULL /* listen */,
- NULL /* shutdown */,
- nss_io_recv,
- nss_io_send,
- nss_io_recvfrom,
- nss_io_sendto,
- NULL /* poll */,
- NULL /* acceptread */,
- NULL /* transmitfile */,
- NULL /* getsockname */,
- nss_io_getpeername,
- NULL /* reserved_fn_6 */,
- NULL /* reserved_fn_5 */,
- nss_io_getsocketoption,
- NULL /* setsocketoption */,
- NULL /* sendfile */,
- NULL /* connectcontinue */,
- NULL /* reserved_fn_3 */,
- NULL /* reserved_fn_2 */,
- NULL /* reserved_fn_1 */,
- NULL /* reserved_fn_0 */
-};
-
-
-static char * nss_password_cb(PK11SlotInfo *slot, PRBool retry, void *arg)
-{
- wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__);
- return NULL;
-}
-
-
-void * tls_init(const struct tls_config *conf)
-{
- char *dir;
-
- tls_nss_ref_count++;
- if (tls_nss_ref_count > 1)
- return (void *) 1;
-
- PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
-
- nss_layer_id = PR_GetUniqueIdentity("wpa_supplicant");
-
- PK11_SetPasswordFunc(nss_password_cb);
-
- dir = getenv("SSL_DIR");
- if (dir) {
- if (NSS_Init(dir) != SECSuccess) {
- wpa_printf(MSG_ERROR, "NSS: NSS_Init(cert_dir=%s) "
- "failed", dir);
- return NULL;
- }
- } else {
- if (NSS_NoDB_Init(NULL) != SECSuccess) {
- wpa_printf(MSG_ERROR, "NSS: NSS_NoDB_Init(NULL) "
- "failed");
- return NULL;
- }
- }
-
- if (SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, PR_FALSE) !=
- SECSuccess ||
- SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_FALSE) != SECSuccess ||
- SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess ||
- SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE) != SECSuccess) {
- wpa_printf(MSG_ERROR, "NSS: SSL_OptionSetDefault failed");
- return NULL;
- }
-
- if (NSS_SetDomesticPolicy() != SECSuccess) {
- wpa_printf(MSG_ERROR, "NSS: NSS_SetDomesticPolicy() failed");
- return NULL;
- }
-
- return (void *) 1;
-}
-
-void tls_deinit(void *ssl_ctx)
-{
- tls_nss_ref_count--;
- if (tls_nss_ref_count == 0) {
- if (NSS_Shutdown() != SECSuccess)
- wpa_printf(MSG_ERROR, "NSS: NSS_Shutdown() failed");
- }
-}
-
-
-int tls_get_errors(void *tls_ctx)
-{
- return 0;
-}
-
-
-static SECStatus nss_bad_cert_cb(void *arg, PRFileDesc *fd)
-{
- struct tls_connection *conn = arg;
- SECStatus res = SECSuccess;
- PRErrorCode err;
- CERTCertificate *cert;
- char *subject, *issuer;
-
- err = PR_GetError();
- if (IS_SEC_ERROR(err))
- wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (sec err "
- "%d)", err - SEC_ERROR_BASE);
- else
- wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (err %d)",
- err);
- cert = SSL_PeerCertificate(fd);
- subject = CERT_NameToAscii(&cert->subject);
- issuer = CERT_NameToAscii(&cert->issuer);
- wpa_printf(MSG_DEBUG, "NSS: Peer certificate subject='%s' issuer='%s'",
- subject, issuer);
- CERT_DestroyCertificate(cert);
- PR_Free(subject);
- PR_Free(issuer);
- if (conn->verify_peer)
- res = SECFailure;
-
- return res;
-}
-
-
-static void nss_handshake_cb(PRFileDesc *fd, void *client_data)
-{
- struct tls_connection *conn = client_data;
- wpa_printf(MSG_DEBUG, "NSS: Handshake completed");
- conn->established = 1;
-}
-
-
-struct tls_connection * tls_connection_init(void *tls_ctx)
-{
- struct tls_connection *conn;
-
- conn = os_zalloc(sizeof(*conn));
- if (conn == NULL)
- return NULL;
-
- conn->fd = PR_CreateIOLayerStub(nss_layer_id, &nss_io);
- if (conn->fd == NULL) {
- os_free(conn);
- return NULL;
- }
- conn->fd->secret = (void *) conn;
-
- conn->fd = SSL_ImportFD(NULL, conn->fd);
- if (conn->fd == NULL) {
- os_free(conn);
- return NULL;
- }
-
- if (SSL_OptionSet(conn->fd, SSL_SECURITY, PR_TRUE) != SECSuccess ||
- SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) !=
- SECSuccess ||
- SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) !=
- SECSuccess ||
- SSL_OptionSet(conn->fd, SSL_ENABLE_TLS, PR_TRUE) != SECSuccess ||
- SSL_BadCertHook(conn->fd, nss_bad_cert_cb, conn) != SECSuccess ||
- SSL_HandshakeCallback(conn->fd, nss_handshake_cb, conn) !=
- SECSuccess) {
- wpa_printf(MSG_ERROR, "NSS: Failed to set options");
- PR_Close(conn->fd);
- os_free(conn);
- return NULL;
- }
-
- SSL_ResetHandshake(conn->fd, PR_FALSE);
-
- return conn;
-}
-
-
-void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn)
-{
- PR_Close(conn->fd);
- os_free(conn->push_buf);
- os_free(conn->pull_buf);
- os_free(conn);
-}
-
-
-int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
-{
- return conn->established;
-}
-
-
-int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
-{
- return -1;
-}
-
-
-int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
- const struct tls_connection_params *params)
-{
- wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__);
- return 0;
-}
-
-
-int tls_global_set_params(void *tls_ctx,
- const struct tls_connection_params *params)
-{
- return -1;
-}
-
-
-int tls_global_set_verify(void *tls_ctx, int check_crl)
-{
- return -1;
-}
-
-
-int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
- int verify_peer)
-{
- conn->verify_peer = verify_peer;
- return 0;
-}
-
-
-int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
- struct tls_keys *keys)
-{
- /* NSS does not export master secret or client/server random. */
- return -1;
-}
-
-
-int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
- const char *label, int server_random_first,
- u8 *out, size_t out_len)
-{
- if (conn == NULL || server_random_first) {
- wpa_printf(MSG_INFO, "NSS: Unsupported PRF request "
- "(server_random_first=%d)",
- server_random_first);
- return -1;
- }
-
- if (SSL_ExportKeyingMaterial(conn->fd, label, NULL, 0, out, out_len) !=
- SECSuccess) {
- wpa_printf(MSG_INFO, "NSS: Failed to use TLS extractor "
- "(label='%s' out_len=%d", label, (int) out_len);
- return -1;
- }
-
- return 0;
-}
-
-
-struct wpabuf * tls_connection_handshake(void *tls_ctx,
- struct tls_connection *conn,
- const struct wpabuf *in_data,
- struct wpabuf **appl_data)
-{
- struct wpabuf *out_data;
-
- wpa_printf(MSG_DEBUG, "NSS: handshake: in_len=%u",
- in_data ? (unsigned int) wpabuf_len(in_data) : 0);
-
- if (appl_data)
- *appl_data = NULL;
-
- if (in_data && wpabuf_len(in_data) > 0) {
- if (conn->pull_buf) {
- wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
- "pull_buf", __func__,
- (unsigned long) conn->pull_buf_len);
- os_free(conn->pull_buf);
- }
- conn->pull_buf = os_malloc(wpabuf_len(in_data));
- if (conn->pull_buf == NULL)
- return NULL;
- os_memcpy(conn->pull_buf, wpabuf_head(in_data),
- wpabuf_len(in_data));
- conn->pull_buf_offset = conn->pull_buf;
- conn->pull_buf_len = wpabuf_len(in_data);
- }
-
- SSL_ForceHandshake(conn->fd);
-
- if (conn->established && conn->push_buf == NULL) {
- /* Need to return something to get final TLS ACK. */
- conn->push_buf = os_malloc(1);
- }
-
- if (conn->push_buf == NULL)
- return NULL;
- out_data = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len);
- if (out_data == NULL)
- os_free(conn->push_buf);
- conn->push_buf = NULL;
- conn->push_buf_len = 0;
- return out_data;
-}
-
-
-struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
- struct tls_connection *conn,
- const struct wpabuf *in_data,
- struct wpabuf **appl_data)
-{
- return NULL;
-}
-
-
-struct wpabuf * tls_connection_encrypt(void *tls_ctx,
- struct tls_connection *conn,
- const struct wpabuf *in_data)
-{
- PRInt32 res;
- struct wpabuf *buf;
-
- wpa_printf(MSG_DEBUG, "NSS: encrypt %d bytes",
- (int) wpabuf_len(in_data));
- res = PR_Send(conn->fd, wpabuf_head(in_data), wpabuf_len(in_data), 0,
- 0);
- if (res < 0) {
- wpa_printf(MSG_ERROR, "NSS: Encryption failed");
- return NULL;
- }
- if (conn->push_buf == NULL)
- return NULL;
- buf = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len);
- if (buf == NULL)
- os_free(conn->push_buf);
- conn->push_buf = NULL;
- conn->push_buf_len = 0;
- return buf;
-}
-
-
-struct wpabuf * tls_connection_decrypt(void *tls_ctx,
- struct tls_connection *conn,
- const struct wpabuf *in_data)
-{
- PRInt32 res;
- struct wpabuf *out;
-
- wpa_printf(MSG_DEBUG, "NSS: decrypt %d bytes",
- (int) wpabuf_len(in_data));
- if (conn->pull_buf) {
- wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
- "pull_buf", __func__,
- (unsigned long) conn->pull_buf_len);
- os_free(conn->pull_buf);
- }
- conn->pull_buf = os_malloc(wpabuf_len(in_data));
- if (conn->pull_buf == NULL)
- return NULL;
- os_memcpy(conn->pull_buf, wpabuf_head(in_data), wpabuf_len(in_data));
- conn->pull_buf_offset = conn->pull_buf;
- conn->pull_buf_len = wpabuf_len(in_data);
-
- /*
- * Even though we try to disable TLS compression, it is possible that
- * this cannot be done with all TLS libraries. Add extra buffer space
- * to handle the possibility of the decrypted data being longer than
- * input data.
- */
- out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
- if (out == NULL)
- return NULL;
-
- res = PR_Recv(conn->fd, wpabuf_mhead(out), wpabuf_size(out), 0, 0);
- wpa_printf(MSG_DEBUG, "NSS: PR_Recv: %d", res);
- if (res < 0) {
- wpabuf_free(out);
- return NULL;
- }
- wpabuf_put(out, res);
-
- return out;
-}
-
-
-int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
-{
- return 0;
-}
-
-
-int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
- u8 *ciphers)
-{
- return -1;
-}
-
-
-int tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
- char *buf, size_t buflen)
-{
- return -1;
-}
-
-
-int tls_connection_enable_workaround(void *tls_ctx,
- struct tls_connection *conn)
-{
- return -1;
-}
-
-
-int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
- int ext_type, const u8 *data,
- size_t data_len)
-{
- return -1;
-}
-
-
-int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
-{
- return 0;
-}
-
-
-int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
-{
- return 0;
-}
-
-
-int tls_connection_get_write_alerts(void *tls_ctx,
- struct tls_connection *conn)
-{
- return 0;
-}
-
-
-int tls_connection_get_keyblock_size(void *tls_ctx,
- struct tls_connection *conn)
-{
- return -1;
-}
-
-
-unsigned int tls_capabilities(void *tls_ctx)
-{
- return 0;
-}
-
-
-int tls_connection_set_session_ticket_cb(void *tls_ctx,
- struct tls_connection *conn,
- tls_session_ticket_cb cb,
- void *ctx)
-{
- return -1;
-}
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index c72134a..5433ebb 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -3554,3 +3554,11 @@
return -1;
#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
}
+
+
+int tls_get_library_version(char *buf, size_t buf_len)
+{
+ return os_snprintf(buf, buf_len, "OpenSSL build=%s run=%s",
+ OPENSSL_VERSION_TEXT,
+ SSLeay_version(SSLEAY_VERSION));
+}
diff --git a/src/crypto/tls_schannel.c b/src/crypto/tls_schannel.c
index 2c2daa8..a43b487 100644
--- a/src/crypto/tls_schannel.c
+++ b/src/crypto/tls_schannel.c
@@ -692,6 +692,26 @@
if (conn == NULL)
return -1;
+ if (params->subject_match) {
+ wpa_printf(MSG_INFO, "TLS: subject_match not supported");
+ return -1;
+ }
+
+ if (params->altsubject_match) {
+ wpa_printf(MSG_INFO, "TLS: altsubject_match not supported");
+ return -1;
+ }
+
+ if (params->suffix_match) {
+ wpa_printf(MSG_INFO, "TLS: suffix_match not supported");
+ return -1;
+ }
+
+ if (params->openssl_ciphers) {
+ wpa_printf(MSG_INFO, "GnuTLS: openssl_ciphers not supported");
+ return -1;
+ }
+
if (global->my_cert_store == NULL &&
(global->my_cert_store = CertOpenSystemStore(0, TEXT("MY"))) ==
NULL) {
@@ -730,3 +750,9 @@
{
return 0;
}
+
+
+int tls_get_library_version(char *buf, size_t buf_len)
+{
+ return os_snprintf(buf, buf_len, "schannel");
+}