summaryrefslogtreecommitdiff
path: root/src/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto')
-rw-r--r--src/crypto/Makefile4
-rw-r--r--src/crypto/aes-ccm.c2
-rw-r--r--src/crypto/aes-eax.c2
-rw-r--r--src/crypto/aes-gcm.c2
-rw-r--r--src/crypto/aes-omac1.c64
-rw-r--r--src/crypto/aes-siv.c188
-rw-r--r--src/crypto/aes-unwrap.c19
-rw-r--r--src/crypto/aes-wrap.c20
-rw-r--r--src/crypto/aes_siv.h19
-rw-r--r--src/crypto/aes_wrap.h15
-rw-r--r--src/crypto/crypto.h323
-rw-r--r--src/crypto/crypto_internal-rsa.c9
-rw-r--r--src/crypto/crypto_module_tests.c1679
-rw-r--r--src/crypto/crypto_nss.c207
-rw-r--r--src/crypto/crypto_openssl.c635
-rw-r--r--src/crypto/dh_groups.c674
-rw-r--r--src/crypto/dh_groups.h3
-rw-r--r--src/crypto/fips_prf_cryptoapi.c19
-rw-r--r--src/crypto/fips_prf_gnutls.c20
-rw-r--r--src/crypto/fips_prf_nss.c19
-rw-r--r--src/crypto/md5.c6
-rw-r--r--src/crypto/milenage.c4
-rw-r--r--src/crypto/ms_funcs.c1
-rw-r--r--src/crypto/random.c12
-rw-r--r--src/crypto/sha1-internal.c2
-rw-r--r--src/crypto/sha1-prf.c1
-rw-r--r--src/crypto/sha1.c5
-rw-r--r--src/crypto/sha256-kdf.c76
-rw-r--r--src/crypto/sha256-prf.c40
-rw-r--r--src/crypto/sha256.h8
-rw-r--r--src/crypto/sha384.h19
-rw-r--r--src/crypto/tls.h47
-rw-r--r--src/crypto/tls_gnutls.c939
-rw-r--r--src/crypto/tls_internal.c55
-rw-r--r--src/crypto/tls_none.c6
-rw-r--r--src/crypto/tls_nss.c645
-rw-r--r--src/crypto/tls_openssl.c1053
-rw-r--r--src/crypto/tls_schannel.c31
38 files changed, 5284 insertions, 1589 deletions
diff --git a/src/crypto/Makefile b/src/crypto/Makefile
index a605a65cd821e..3e90350c103ee 100644
--- a/src/crypto/Makefile
+++ b/src/crypto/Makefile
@@ -1,7 +1,7 @@
all: libcrypto.a
clean:
- rm -f *~ *.o *.d libcrypto.a
+ rm -f *~ *.o *.d *.gcno *.gcda *.gcov libcrypto.a
install:
@echo Nothing to be made.
@@ -9,6 +9,7 @@ install:
include ../lib.rules
+CFLAGS += -DCONFIG_CRYPTO_INTERNAL
CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT
CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
#CFLAGS += -DALL_DH_GROUPS
@@ -25,6 +26,7 @@ LIB_OBJS= \
aes-internal-dec.o \
aes-internal-enc.o \
aes-omac1.o \
+ aes-siv.o \
aes-unwrap.o \
aes-wrap.o \
des-internal.o \
diff --git a/src/crypto/aes-ccm.c b/src/crypto/aes-ccm.c
index d14670db8d65f..cf227785c3ca0 100644
--- a/src/crypto/aes-ccm.c
+++ b/src/crypto/aes-ccm.c
@@ -203,7 +203,7 @@ int aes_ccm_ad(const u8 *key, size_t key_len, const u8 *nonce,
aes_encrypt_deinit(aes);
- if (os_memcmp(x, t, M) != 0) {
+ if (os_memcmp_const(x, t, M) != 0) {
wpa_printf(MSG_EXCESSIVE, "CCM: Auth mismatch");
return -1;
}
diff --git a/src/crypto/aes-eax.c b/src/crypto/aes-eax.c
index 21941c66de5d3..15a09f8b461a4 100644
--- a/src/crypto/aes-eax.c
+++ b/src/crypto/aes-eax.c
@@ -71,7 +71,7 @@ int aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
ret = 0;
fail:
- os_free(buf);
+ bin_clear_free(buf, buf_len);
return ret;
}
diff --git a/src/crypto/aes-gcm.c b/src/crypto/aes-gcm.c
index 3d91c71de2dd9..84294d2d104ca 100644
--- a/src/crypto/aes-gcm.c
+++ b/src/crypto/aes-gcm.c
@@ -310,7 +310,7 @@ int aes_gcm_ad(const u8 *key, size_t key_len, const u8 *iv, size_t iv_len,
aes_encrypt_deinit(aes);
- if (os_memcmp(tag, T, 16) != 0) {
+ if (os_memcmp_const(tag, T, 16) != 0) {
wpa_printf(MSG_EXCESSIVE, "GCM: Tag mismatch");
return -1;
}
diff --git a/src/crypto/aes-omac1.c b/src/crypto/aes-omac1.c
index 27895eb007efe..375db5735be33 100644
--- a/src/crypto/aes-omac1.c
+++ b/src/crypto/aes-omac1.c
@@ -1,5 +1,5 @@
/*
- * One-key CBC MAC (OMAC1) hash with AES-128
+ * One-key CBC MAC (OMAC1) hash with AES
*
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
*
@@ -27,8 +27,9 @@ static void gf_mulx(u8 *pad)
/**
- * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128
- * @key: 128-bit key for the hash operation
+ * omac1_aes_vector - One-Key CBC MAC (OMAC1) hash with AES
+ * @key: Key for the hash operation
+ * @key_len: Key length in octets
* @num_elem: Number of elements in the data vector
* @addr: Pointers to the data areas
* @len: Lengths of the data blocks
@@ -39,15 +40,15 @@ static void gf_mulx(u8 *pad)
* OMAC1 was standardized with the name CMAC by NIST in a Special Publication
* (SP) 800-38B.
*/
-int omac1_aes_128_vector(const u8 *key, size_t num_elem,
- const u8 *addr[], const size_t *len, u8 *mac)
+int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac)
{
void *ctx;
u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
const u8 *pos, *end;
size_t i, e, left, total_len;
- ctx = aes_encrypt_init(key, 16);
+ ctx = aes_encrypt_init(key, key_len);
if (ctx == NULL)
return -1;
os_memset(cbc, 0, AES_BLOCK_SIZE);
@@ -65,6 +66,13 @@ int omac1_aes_128_vector(const u8 *key, size_t num_elem,
for (i = 0; i < AES_BLOCK_SIZE; i++) {
cbc[i] ^= *pos++;
if (pos >= end) {
+ /*
+ * Stop if there are no more bytes to process
+ * since there are no more entries in the array.
+ */
+ if (i + 1 == AES_BLOCK_SIZE &&
+ left == AES_BLOCK_SIZE)
+ break;
e++;
pos = addr[e];
end = pos + len[e];
@@ -83,6 +91,12 @@ int omac1_aes_128_vector(const u8 *key, size_t num_elem,
for (i = 0; i < left; i++) {
cbc[i] ^= *pos++;
if (pos >= end) {
+ /*
+ * Stop if there are no more bytes to process
+ * since there are no more entries in the array.
+ */
+ if (i + 1 == left)
+ break;
e++;
pos = addr[e];
end = pos + len[e];
@@ -101,6 +115,26 @@ int omac1_aes_128_vector(const u8 *key, size_t num_elem,
/**
+ * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128
+ * @key: 128-bit key for the hash operation
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
+ * Returns: 0 on success, -1 on failure
+ *
+ * This is a mode for using block cipher (AES in this case) for authentication.
+ * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
+ * (SP) 800-38B.
+ */
+int omac1_aes_128_vector(const u8 *key, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac)
+{
+ return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
+}
+
+
+/**
* omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
* @key: 128-bit key for the hash operation
* @data: Data buffer for which a MAC is determined
@@ -116,3 +150,21 @@ int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
{
return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
}
+
+
+/**
+ * omac1_aes_256 - One-Key CBC MAC (OMAC1) hash with AES-256 (aka AES-CMAC)
+ * @key: 256-bit key for the hash operation
+ * @data: Data buffer for which a MAC is determined
+ * @data_len: Length of data buffer in bytes
+ * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
+ * Returns: 0 on success, -1 on failure
+ *
+ * This is a mode for using block cipher (AES in this case) for authentication.
+ * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
+ * (SP) 800-38B.
+ */
+int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
+{
+ return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
+}
diff --git a/src/crypto/aes-siv.c b/src/crypto/aes-siv.c
new file mode 100644
index 0000000000000..5ac82c2e4b5c0
--- /dev/null
+++ b/src/crypto/aes-siv.c
@@ -0,0 +1,188 @@
+/*
+ * AES SIV (RFC 5297)
+ * Copyright (c) 2013 Cozybit, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "aes.h"
+#include "aes_wrap.h"
+#include "aes_siv.h"
+
+
+static const u8 zero[AES_BLOCK_SIZE];
+
+
+static void dbl(u8 *pad)
+{
+ int i, carry;
+
+ carry = pad[0] & 0x80;
+ for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
+ pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
+ pad[AES_BLOCK_SIZE - 1] <<= 1;
+ if (carry)
+ pad[AES_BLOCK_SIZE - 1] ^= 0x87;
+}
+
+
+static void xor(u8 *a, const u8 *b)
+{
+ int i;
+
+ for (i = 0; i < AES_BLOCK_SIZE; i++)
+ *a++ ^= *b++;
+}
+
+
+static void xorend(u8 *a, int alen, const u8 *b, int blen)
+{
+ int i;
+
+ if (alen < blen)
+ return;
+
+ for (i = 0; i < blen; i++)
+ a[alen - blen + i] ^= b[i];
+}
+
+
+static void pad_block(u8 *pad, const u8 *addr, size_t len)
+{
+ os_memset(pad, 0, AES_BLOCK_SIZE);
+ os_memcpy(pad, addr, len);
+
+ if (len < AES_BLOCK_SIZE)
+ pad[len] = 0x80;
+}
+
+
+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;
+ int ret;
+ size_t i;
+
+ if (!num_elem) {
+ os_memcpy(tmp, zero, sizeof(zero));
+ tmp[AES_BLOCK_SIZE - 1] = 1;
+ return omac1_aes_128(key, tmp, sizeof(tmp), mac);
+ }
+
+ ret = omac1_aes_128(key, zero, sizeof(zero), tmp);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < num_elem - 1; i++) {
+ ret = omac1_aes_128(key, addr[i], len[i], tmp2);
+ if (ret)
+ return ret;
+
+ dbl(tmp);
+ xor(tmp, tmp2);
+ }
+ if (len[i] >= AES_BLOCK_SIZE) {
+ buf = os_malloc(len[i]);
+ if (!buf)
+ return -ENOMEM;
+
+ os_memcpy(buf, addr[i], len[i]);
+ xorend(buf, len[i], tmp, AES_BLOCK_SIZE);
+ ret = omac1_aes_128(key, buf, len[i], mac);
+ bin_clear_free(buf, len[i]);
+ return ret;
+ }
+
+ dbl(tmp);
+ pad_block(tmp2, addr[i], len[i]);
+ xor(tmp, tmp2);
+
+ return omac1_aes_128(key, tmp, sizeof(tmp), mac);
+}
+
+
+int aes_siv_encrypt(const u8 *key, const u8 *pw,
+ size_t pwlen, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *out)
+{
+ const u8 *_addr[6];
+ size_t _len[6];
+ const u8 *k1 = key, *k2 = key + 16;
+ u8 v[AES_BLOCK_SIZE];
+ size_t i;
+ u8 *iv, *crypt_pw;
+
+ if (num_elem > ARRAY_SIZE(_addr) - 1)
+ return -1;
+
+ for (i = 0; i < num_elem; i++) {
+ _addr[i] = addr[i];
+ _len[i] = len[i];
+ }
+ _addr[num_elem] = pw;
+ _len[num_elem] = pwlen;
+
+ if (aes_s2v(k1, num_elem + 1, _addr, _len, v))
+ return -1;
+
+ iv = out;
+ crypt_pw = out + AES_BLOCK_SIZE;
+
+ os_memcpy(iv, v, AES_BLOCK_SIZE);
+ os_memcpy(crypt_pw, pw, pwlen);
+
+ /* zero out 63rd and 31st bits of ctr (from right) */
+ v[8] &= 0x7f;
+ v[12] &= 0x7f;
+ return aes_128_ctr_encrypt(k2, v, crypt_pw, pwlen);
+}
+
+
+int aes_siv_decrypt(const u8 *key, const u8 *iv_crypt, size_t iv_c_len,
+ size_t num_elem, const u8 *addr[], const size_t *len,
+ u8 *out)
+{
+ const u8 *_addr[6];
+ size_t _len[6];
+ const u8 *k1 = key, *k2 = key + 16;
+ size_t crypt_len;
+ size_t i;
+ int ret;
+ u8 iv[AES_BLOCK_SIZE];
+ u8 check[AES_BLOCK_SIZE];
+
+ if (iv_c_len < AES_BLOCK_SIZE || num_elem > ARRAY_SIZE(_addr) - 1)
+ return -1;
+ crypt_len = iv_c_len - AES_BLOCK_SIZE;
+
+ for (i = 0; i < num_elem; i++) {
+ _addr[i] = addr[i];
+ _len[i] = len[i];
+ }
+ _addr[num_elem] = out;
+ _len[num_elem] = crypt_len;
+
+ os_memcpy(iv, iv_crypt, AES_BLOCK_SIZE);
+ os_memcpy(out, iv_crypt + AES_BLOCK_SIZE, crypt_len);
+
+ iv[8] &= 0x7f;
+ iv[12] &= 0x7f;
+
+ ret = aes_128_ctr_encrypt(k2, iv, out, crypt_len);
+ if (ret)
+ return ret;
+
+ ret = aes_s2v(k1, num_elem + 1, _addr, _len, check);
+ if (ret)
+ return ret;
+ if (os_memcmp(check, iv_crypt, AES_BLOCK_SIZE) == 0)
+ return 0;
+
+ return -1;
+}
diff --git a/src/crypto/aes-unwrap.c b/src/crypto/aes-unwrap.c
index 9dd51602f3582..ec793d9dbf78b 100644
--- a/src/crypto/aes-unwrap.c
+++ b/src/crypto/aes-unwrap.c
@@ -1,5 +1,5 @@
/*
- * AES key unwrap (128-bit KEK, RFC3394)
+ * AES key unwrap (RFC3394)
*
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
*
@@ -14,26 +14,29 @@
#include "aes_wrap.h"
/**
- * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (RFC3394)
* @kek: Key encryption key (KEK)
+ * @kek_len: Length of KEK in octets
* @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
* bytes
* @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits
* @plain: Plaintext key, n * 64 bits
* Returns: 0 on success, -1 on failure (e.g., integrity verification failed)
*/
-int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain)
+int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher,
+ u8 *plain)
{
- u8 a[8], *r, b[16];
+ u8 a[8], *r, b[AES_BLOCK_SIZE];
int i, j;
void *ctx;
+ unsigned int t;
/* 1) Initialize variables. */
os_memcpy(a, cipher, 8);
r = plain;
os_memcpy(r, cipher + 8, 8 * n);
- ctx = aes_decrypt_init(kek, 16);
+ ctx = aes_decrypt_init(kek, kek_len);
if (ctx == NULL)
return -1;
@@ -48,7 +51,11 @@ int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain)
r = plain + (n - 1) * 8;
for (i = n; i >= 1; i--) {
os_memcpy(b, a, 8);
- b[7] ^= n * j + i;
+ t = n * j + i;
+ b[7] ^= t;
+ b[6] ^= t >> 8;
+ b[5] ^= t >> 16;
+ b[4] ^= t >> 24;
os_memcpy(b + 8, r, 8);
aes_decrypt(ctx, b, b);
diff --git a/src/crypto/aes-wrap.c b/src/crypto/aes-wrap.c
index 89d6f94bf7610..7ed34e803e4e5 100644
--- a/src/crypto/aes-wrap.c
+++ b/src/crypto/aes-wrap.c
@@ -1,5 +1,5 @@
/*
- * AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * AES Key Wrap Algorithm (RFC3394)
*
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
*
@@ -14,19 +14,21 @@
#include "aes_wrap.h"
/**
- * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
- * @kek: 16-octet Key encryption key (KEK)
+ * aes_wrap - Wrap keys with AES Key Wrap Algorithm (RFC3394)
+ * @kek: Key encryption key (KEK)
+ * @kek_len: Length of KEK in octets
* @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
* bytes
* @plain: Plaintext key to be wrapped, n * 64 bits
* @cipher: Wrapped key, (n + 1) * 64 bits
* Returns: 0 on success, -1 on failure
*/
-int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher)
+int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher)
{
- u8 *a, *r, b[16];
+ u8 *a, *r, b[AES_BLOCK_SIZE];
int i, j;
void *ctx;
+ unsigned int t;
a = cipher;
r = cipher + 8;
@@ -35,7 +37,7 @@ int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher)
os_memset(a, 0xa6, 8);
os_memcpy(r, plain, 8 * n);
- ctx = aes_encrypt_init(kek, 16);
+ ctx = aes_encrypt_init(kek, kek_len);
if (ctx == NULL)
return -1;
@@ -53,7 +55,11 @@ int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher)
os_memcpy(b + 8, r, 8);
aes_encrypt(ctx, b, b);
os_memcpy(a, b, 8);
- a[7] ^= n * j + i;
+ t = n * j + i;
+ a[7] ^= t;
+ a[6] ^= t >> 8;
+ a[5] ^= t >> 16;
+ a[4] ^= t >> 24;
os_memcpy(r, b + 8, 8);
r += 8;
}
diff --git a/src/crypto/aes_siv.h b/src/crypto/aes_siv.h
new file mode 100644
index 0000000000000..463cf6536107c
--- /dev/null
+++ b/src/crypto/aes_siv.h
@@ -0,0 +1,19 @@
+/*
+ * AES SIV (RFC 5297)
+ * Copyright (c) 2013 Cozybit, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef AES_SIV_H
+#define AES_SIV_H
+
+int aes_siv_encrypt(const u8 *key, const u8 *pw,
+ size_t pwlen, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *out);
+int aes_siv_decrypt(const u8 *key, const u8 *iv_crypt, size_t iv_c_len,
+ size_t num_elem, const u8 *addr[], const size_t *len,
+ u8 *out);
+
+#endif /* AES_SIV_H */
diff --git a/src/crypto/aes_wrap.h b/src/crypto/aes_wrap.h
index 0433c0434eed3..4a142093b0d62 100644
--- a/src/crypto/aes_wrap.h
+++ b/src/crypto/aes_wrap.h
@@ -1,8 +1,8 @@
/*
* AES-based functions
*
- * - AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
- * - One-Key CBC MAC (OMAC1) hash with AES-128
+ * - AES Key Wrap Algorithm (RFC3394)
+ * - One-Key CBC MAC (OMAC1) hash with AES-128 and AES-256
* - AES-128 CTR mode encryption
* - AES-128 EAX mode encryption/decryption
* - AES-128 CBC
@@ -18,13 +18,20 @@
#ifndef AES_WRAP_H
#define AES_WRAP_H
-int __must_check aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher);
-int __must_check aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain);
+int __must_check aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain,
+ u8 *cipher);
+int __must_check aes_unwrap(const u8 *kek, size_t kek_len, int n,
+ const u8 *cipher, u8 *plain);
+int __must_check omac1_aes_vector(const u8 *key, size_t key_len,
+ size_t num_elem, const u8 *addr[],
+ const size_t *len, u8 *mac);
int __must_check omac1_aes_128_vector(const u8 *key, size_t num_elem,
const u8 *addr[], const size_t *len,
u8 *mac);
int __must_check omac1_aes_128(const u8 *key, const u8 *data, size_t data_len,
u8 *mac);
+int __must_check omac1_aes_256(const u8 *key, const u8 *data, size_t data_len,
+ u8 *mac);
int __must_check aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out);
int __must_check aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
u8 *data, size_t data_len);
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index 26b9acf2f4244..f2d5662ff01e2 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -1,6 +1,6 @@
/*
- * WPA Supplicant / wrapper functions for crypto libraries
- * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
+ * Wrapper functions for crypto libraries
+ * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -271,6 +271,10 @@ struct crypto_private_key;
*/
struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len);
+struct crypto_public_key *
+crypto_public_key_import_parts(const u8 *n, size_t n_len,
+ const u8 *e, size_t e_len);
+
/**
* crypto_private_key_import - Import an RSA private key
* @key: Key buffer (DER encoded RSA private key)
@@ -457,4 +461,319 @@ int rc4_skip(const u8 *key, size_t keylen, size_t skip,
*/
int crypto_get_random(void *buf, size_t len);
+
+/**
+ * struct crypto_bignum - bignum
+ *
+ * Internal data structure for bignum implementation. The contents is specific
+ * to the used crypto library.
+ */
+struct crypto_bignum;
+
+/**
+ * crypto_bignum_init - Allocate memory for bignum
+ * Returns: Pointer to allocated bignum or %NULL on failure
+ */
+struct crypto_bignum * crypto_bignum_init(void);
+
+/**
+ * crypto_bignum_init_set - Allocate memory for bignum and set the value
+ * @buf: Buffer with unsigned binary value
+ * @len: Length of buf in octets
+ * Returns: Pointer to allocated bignum or %NULL on failure
+ */
+struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len);
+
+/**
+ * crypto_bignum_deinit - Free bignum
+ * @n: Bignum from crypto_bignum_init() or crypto_bignum_init_set()
+ * @clear: Whether to clear the value from memory
+ */
+void crypto_bignum_deinit(struct crypto_bignum *n, int clear);
+
+/**
+ * crypto_bignum_to_bin - Set binary buffer to unsigned bignum
+ * @a: Bignum
+ * @buf: Buffer for the binary number
+ * @len: Length of @buf in octets
+ * @padlen: Length in octets to pad the result to or 0 to indicate no padding
+ * Returns: Number of octets written on success, -1 on failure
+ */
+int crypto_bignum_to_bin(const struct crypto_bignum *a,
+ u8 *buf, size_t buflen, size_t padlen);
+
+/**
+ * crypto_bignum_add - c = a + b
+ * @a: Bignum
+ * @b: Bignum
+ * @c: Bignum; used to store the result of a + b
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_bignum_add(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ struct crypto_bignum *c);
+
+/**
+ * crypto_bignum_mod - c = a % b
+ * @a: Bignum
+ * @b: Bignum
+ * @c: Bignum; used to store the result of a % b
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_bignum_mod(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ struct crypto_bignum *c);
+
+/**
+ * crypto_bignum_exptmod - Modular exponentiation: d = a^b (mod c)
+ * @a: Bignum; base
+ * @b: Bignum; exponent
+ * @c: Bignum; modulus
+ * @d: Bignum; used to store the result of a^b (mod c)
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_bignum_exptmod(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ const struct crypto_bignum *c,
+ struct crypto_bignum *d);
+
+/**
+ * crypto_bignum_inverse - Inverse a bignum so that a * c = 1 (mod b)
+ * @a: Bignum
+ * @b: Bignum
+ * @c: Bignum; used to store the result
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_bignum_inverse(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ struct crypto_bignum *c);
+
+/**
+ * crypto_bignum_sub - c = a - b
+ * @a: Bignum
+ * @b: Bignum
+ * @c: Bignum; used to store the result of a - b
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_bignum_sub(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ struct crypto_bignum *c);
+
+/**
+ * crypto_bignum_div - c = a / b
+ * @a: Bignum
+ * @b: Bignum
+ * @c: Bignum; used to store the result of a / b
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_bignum_div(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ struct crypto_bignum *c);
+
+/**
+ * crypto_bignum_mulmod - d = a * b (mod c)
+ * @a: Bignum
+ * @b: Bignum
+ * @c: Bignum
+ * @d: Bignum; used to store the result of (a * b) % c
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_bignum_mulmod(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ const struct crypto_bignum *c,
+ struct crypto_bignum *d);
+
+/**
+ * crypto_bignum_cmp - Compare two bignums
+ * @a: Bignum
+ * @b: Bignum
+ * Returns: -1 if a < b, 0 if a == b, or 1 if a > b
+ */
+int crypto_bignum_cmp(const struct crypto_bignum *a,
+ const struct crypto_bignum *b);
+
+/**
+ * crypto_bignum_bits - Get size of a bignum in bits
+ * @a: Bignum
+ * Returns: Number of bits in the bignum
+ */
+int crypto_bignum_bits(const struct crypto_bignum *a);
+
+/**
+ * crypto_bignum_is_zero - Is the given bignum zero
+ * @a: Bignum
+ * Returns: 1 if @a is zero or 0 if not
+ */
+int crypto_bignum_is_zero(const struct crypto_bignum *a);
+
+/**
+ * crypto_bignum_is_one - Is the given bignum one
+ * @a: Bignum
+ * Returns: 1 if @a is one or 0 if not
+ */
+int crypto_bignum_is_one(const struct crypto_bignum *a);
+
+/**
+ * struct crypto_ec - Elliptic curve context
+ *
+ * Internal data structure for EC implementation. The contents is specific
+ * to the used crypto library.
+ */
+struct crypto_ec;
+
+/**
+ * crypto_ec_init - Initialize elliptic curve context
+ * @group: Identifying number for the ECC group (IANA "Group Description"
+ * attribute registrty for RFC 2409)
+ * Returns: Pointer to EC context or %NULL on failure
+ */
+struct crypto_ec * crypto_ec_init(int group);
+
+/**
+ * crypto_ec_deinit - Deinitialize elliptic curve context
+ * @e: EC context from crypto_ec_init()
+ */
+void crypto_ec_deinit(struct crypto_ec *e);
+
+/**
+ * crypto_ec_prime_len - Get length of the prime in octets
+ * @e: EC context from crypto_ec_init()
+ * Returns: Length of the prime defining the group
+ */
+size_t crypto_ec_prime_len(struct crypto_ec *e);
+
+/**
+ * crypto_ec_prime_len_bits - Get length of the prime in bits
+ * @e: EC context from crypto_ec_init()
+ * Returns: Length of the prime defining the group in bits
+ */
+size_t crypto_ec_prime_len_bits(struct crypto_ec *e);
+
+/**
+ * crypto_ec_get_prime - Get prime defining an EC group
+ * @e: EC context from crypto_ec_init()
+ * Returns: Prime (bignum) defining the group
+ */
+const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e);
+
+/**
+ * crypto_ec_get_order - Get order of an EC group
+ * @e: EC context from crypto_ec_init()
+ * Returns: Order (bignum) of the group
+ */
+const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e);
+
+/**
+ * struct crypto_ec_point - Elliptic curve point
+ *
+ * Internal data structure for EC implementation to represent a point. The
+ * contents is specific to the used crypto library.
+ */
+struct crypto_ec_point;
+
+/**
+ * crypto_ec_point_init - Initialize data for an EC point
+ * @e: EC context from crypto_ec_init()
+ * Returns: Pointer to EC point data or %NULL on failure
+ */
+struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e);
+
+/**
+ * crypto_ec_point_deinit - Deinitialize EC point data
+ * @p: EC point data from crypto_ec_point_init()
+ * @clear: Whether to clear the EC point value from memory
+ */
+void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear);
+
+/**
+ * crypto_ec_point_to_bin - Write EC point value as binary data
+ * @e: EC context from crypto_ec_init()
+ * @p: EC point data from crypto_ec_point_init()
+ * @x: Buffer for writing the binary data for x coordinate or %NULL if not used
+ * @y: Buffer for writing the binary data for y coordinate or %NULL if not used
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function can be used to write an EC point as binary data in a format
+ * that has the x and y coordinates in big endian byte order fields padded to
+ * the length of the prime defining the group.
+ */
+int crypto_ec_point_to_bin(struct crypto_ec *e,
+ const struct crypto_ec_point *point, u8 *x, u8 *y);
+
+/**
+ * crypto_ec_point_from_bin - Create EC point from binary data
+ * @e: EC context from crypto_ec_init()
+ * @val: Binary data to read the EC point from
+ * Returns: Pointer to EC point data or %NULL on failure
+ *
+ * This function readers x and y coordinates of the EC point from the provided
+ * buffer assuming the values are in big endian byte order with fields padded to
+ * the length of the prime defining the group.
+ */
+struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e,
+ const u8 *val);
+
+/**
+ * crypto_bignum_add - c = a + b
+ * @e: EC context from crypto_ec_init()
+ * @a: Bignum
+ * @b: Bignum
+ * @c: Bignum; used to store the result of a + b
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a,
+ const struct crypto_ec_point *b,
+ struct crypto_ec_point *c);
+
+/**
+ * crypto_bignum_mul - res = b * p
+ * @e: EC context from crypto_ec_init()
+ * @p: EC point
+ * @b: Bignum
+ * @res: EC point; used to store the result of b * p
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p,
+ const struct crypto_bignum *b,
+ struct crypto_ec_point *res);
+
+/**
+ * crypto_ec_point_invert - Compute inverse of an EC point
+ * @e: EC context from crypto_ec_init()
+ * @p: EC point to invert (and result of the operation)
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p);
+
+/**
+ * crypto_ec_point_solve_y_coord - Solve y coordinate for an x coordinate
+ * @e: EC context from crypto_ec_init()
+ * @p: EC point to use for the returning the result
+ * @x: x coordinate
+ * @y_bit: y-bit (0 or 1) for selecting the y value to use
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
+ struct crypto_ec_point *p,
+ const struct crypto_bignum *x, int y_bit);
+
+/**
+ * crypto_ec_point_is_at_infinity - Check whether EC point is neutral element
+ * @e: EC context from crypto_ec_init()
+ * @p: EC point
+ * Returns: 1 if the specified EC point is the neutral element of the group or
+ * 0 if not
+ */
+int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
+ const struct crypto_ec_point *p);
+
+/**
+ * crypto_ec_point_is_on_curve - Check whether EC point is on curve
+ * @e: EC context from crypto_ec_init()
+ * @p: EC point
+ * Returns: 1 if the specified EC point is on the curve or 0 if not
+ */
+int crypto_ec_point_is_on_curve(struct crypto_ec *e,
+ const struct crypto_ec_point *p);
+
#endif /* CRYPTO_H */
diff --git a/src/crypto/crypto_internal-rsa.c b/src/crypto/crypto_internal-rsa.c
index 54209fad3c01e..dc7f350af057a 100644
--- a/src/crypto/crypto_internal-rsa.c
+++ b/src/crypto/crypto_internal-rsa.c
@@ -26,6 +26,15 @@ struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
}
+struct crypto_public_key *
+crypto_public_key_import_parts(const u8 *n, size_t n_len,
+ const u8 *e, size_t e_len)
+{
+ return (struct crypto_public_key *)
+ crypto_rsa_import_public_key_parts(n, n_len, e, e_len);
+}
+
+
struct crypto_private_key * crypto_private_key_import(const u8 *key,
size_t len,
const char *passwd)
diff --git a/src/crypto/crypto_module_tests.c b/src/crypto/crypto_module_tests.c
new file mode 100644
index 0000000000000..7137c27d0e8c5
--- /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 acd0a55281c0e..0000000000000
--- 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 711e312d0fb04..f158ef43a645c 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -1,6 +1,6 @@
/*
- * WPA Supplicant / wrapper functions for libcrypto
- * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
+ * Wrapper functions for OpenSSL libcrypto
+ * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -19,23 +19,21 @@
#ifdef CONFIG_OPENSSL_CMAC
#include <openssl/cmac.h>
#endif /* CONFIG_OPENSSL_CMAC */
+#ifdef CONFIG_ECC
+#include <openssl/ec.h>
+#endif /* CONFIG_ECC */
#include "common.h"
#include "wpabuf.h"
#include "dh_group5.h"
+#include "sha1.h"
+#include "sha256.h"
+#include "sha384.h"
#include "crypto.h"
-#if OPENSSL_VERSION_NUMBER < 0x00907000
-#define DES_key_schedule des_key_schedule
-#define DES_cblock des_cblock
-#define DES_set_key(key, schedule) des_set_key((key), *(schedule))
-#define DES_ecb_encrypt(input, output, ks, enc) \
- des_ecb_encrypt((input), (output), *(ks), (enc))
-#endif /* openssl < 0.9.7 */
-
static BIGNUM * get_group5_prime(void)
{
-#if OPENSSL_VERSION_NUMBER < 0x00908000
+#ifdef OPENSSL_IS_BORINGSSL
static const unsigned char RFC3526_PRIME_1536[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,
0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,
@@ -55,20 +53,11 @@ static BIGNUM * get_group5_prime(void)
0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), NULL);
-#else /* openssl < 0.9.8 */
+#else /* OPENSSL_IS_BORINGSSL */
return get_rfc3526_prime_1536(NULL);
-#endif /* openssl < 0.9.8 */
+#endif /* OPENSSL_IS_BORINGSSL */
}
-#if OPENSSL_VERSION_NUMBER < 0x00908000
-#ifndef OPENSSL_NO_SHA256
-#ifndef OPENSSL_FIPS
-#define NO_SHA256_WRAPPER
-#endif
-#endif
-
-#endif /* openssl < 0.9.8 */
-
#ifdef OPENSSL_NO_SHA256
#define NO_SHA256_WRAPPER
#endif
@@ -125,7 +114,7 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
}
pkey[i] = next | 1;
- DES_set_key(&pkey, &ks);
+ DES_set_key((DES_cblock *) &pkey, &ks);
DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks,
DES_ENCRYPT);
}
@@ -194,8 +183,10 @@ static const EVP_CIPHER * aes_get_evp_cipher(size_t keylen)
switch (keylen) {
case 16:
return EVP_aes_128_ecb();
+#ifndef OPENSSL_IS_BORINGSSL
case 24:
return EVP_aes_192_ecb();
+#endif /* OPENSSL_IS_BORINGSSL */
case 32:
return EVP_aes_256_ecb();
}
@@ -251,7 +242,7 @@ void aes_encrypt_deinit(void *ctx)
"in AES encrypt", len);
}
EVP_CIPHER_CTX_cleanup(c);
- os_free(c);
+ bin_clear_free(c, sizeof(*c));
}
@@ -302,7 +293,34 @@ void aes_decrypt_deinit(void *ctx)
"in AES decrypt", len);
}
EVP_CIPHER_CTX_cleanup(c);
- os_free(ctx);
+ bin_clear_free(c, sizeof(*c));
+}
+
+
+int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher)
+{
+ AES_KEY actx;
+ int res;
+
+ if (AES_set_encrypt_key(kek, kek_len << 3, &actx))
+ return -1;
+ res = AES_wrap_key(&actx, NULL, cipher, plain, n * 8);
+ OPENSSL_cleanse(&actx, sizeof(actx));
+ return res <= 0 ? -1 : 0;
+}
+
+
+int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher,
+ u8 *plain)
+{
+ AES_KEY actx;
+ int res;
+
+ if (AES_set_decrypt_key(kek, kek_len << 3, &actx))
+ return -1;
+ res = AES_unwrap_key(&actx, NULL, plain, cipher, (n + 1) * 8);
+ OPENSSL_cleanse(&actx, sizeof(actx));
+ return res <= 0 ? -1 : 0;
}
@@ -335,10 +353,10 @@ int crypto_mod_exp(const u8 *base, size_t base_len,
ret = 0;
error:
- BN_free(bn_base);
- BN_free(bn_exp);
- BN_free(bn_modulus);
- BN_free(bn_result);
+ BN_clear_free(bn_base);
+ BN_clear_free(bn_exp);
+ BN_clear_free(bn_modulus);
+ BN_clear_free(bn_result);
BN_CTX_free(ctx);
return ret;
}
@@ -373,9 +391,11 @@ struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
case 16:
cipher = EVP_aes_128_cbc();
break;
+#ifndef OPENSSL_IS_BORINGSSL
case 24:
cipher = EVP_aes_192_cbc();
break;
+#endif /* OPENSSL_IS_BORINGSSL */
case 32:
cipher = EVP_aes_256_cbc();
break;
@@ -498,8 +518,8 @@ void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
return dh;
err:
- wpabuf_free(pubkey);
- wpabuf_free(privkey);
+ wpabuf_clear_free(pubkey);
+ wpabuf_clear_free(privkey);
DH_free(dh);
return NULL;
}
@@ -566,13 +586,13 @@ struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
if (keylen < 0)
goto err;
wpabuf_put(res, keylen);
- BN_free(pub_key);
+ BN_clear_free(pub_key);
return res;
err:
- BN_free(pub_key);
- wpabuf_free(res);
+ BN_clear_free(pub_key);
+ wpabuf_clear_free(res);
return NULL;
}
@@ -629,7 +649,7 @@ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
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 */
@@ -655,7 +675,7 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
return -2;
if (mac == NULL || len == NULL) {
- os_free(ctx);
+ bin_clear_free(ctx, sizeof(*ctx));
return 0;
}
@@ -667,7 +687,7 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
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;
@@ -678,43 +698,26 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
}
-int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,
- int iterations, u8 *buf, size_t buflen)
-{
-#if OPENSSL_VERSION_NUMBER < 0x00908000
- if (PKCS5_PBKDF2_HMAC_SHA1(passphrase, os_strlen(passphrase),
- (unsigned char *) ssid,
- ssid_len, 4096, 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)
- return -1;
-#endif /* openssl < 0.9.8 */
- return 0;
-}
-
-
-int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
- const u8 *addr[], const size_t *len, u8 *mac)
+static int openssl_hmac_vector(const EVP_MD *type, const u8 *key,
+ size_t key_len, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac,
+ unsigned int mdlen)
{
HMAC_CTX ctx;
size_t i;
- unsigned int mdlen;
int res;
HMAC_CTX_init(&ctx);
#if OPENSSL_VERSION_NUMBER < 0x00909000
- HMAC_Init_ex(&ctx, key, key_len, EVP_sha1(), NULL);
+ HMAC_Init_ex(&ctx, key, key_len, type, NULL);
#else /* openssl < 0.9.9 */
- if (HMAC_Init_ex(&ctx, key, key_len, EVP_sha1(), NULL) != 1)
+ if (HMAC_Init_ex(&ctx, key, key_len, type, NULL) != 1)
return -1;
#endif /* openssl < 0.9.9 */
for (i = 0; i < num_elem; i++)
HMAC_Update(&ctx, addr[i], len[i]);
- mdlen = 20;
#if OPENSSL_VERSION_NUMBER < 0x00909000
HMAC_Final(&ctx, mac, &mdlen);
res = 1;
@@ -727,6 +730,43 @@ int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
}
+#ifndef CONFIG_FIPS
+
+int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac)
+{
+ return openssl_hmac_vector(EVP_md5(), key ,key_len, num_elem, addr, len,
+ mac, 16);
+}
+
+
+int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
+ u8 *mac)
+{
+ return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
+}
+
+#endif /* CONFIG_FIPS */
+
+
+int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,
+ int iterations, u8 *buf, size_t buflen)
+{
+ if (PKCS5_PBKDF2_HMAC_SHA1(passphrase, os_strlen(passphrase), ssid,
+ ssid_len, iterations, buflen, buf) != 1)
+ return -1;
+ return 0;
+}
+
+
+int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac)
+{
+ return openssl_hmac_vector(EVP_sha1(), key, key_len, num_elem, addr,
+ len, mac, 20);
+}
+
+
int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
u8 *mac)
{
@@ -739,42 +779,37 @@ int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac)
{
- HMAC_CTX ctx;
- size_t i;
- unsigned int mdlen;
- int res;
+ return openssl_hmac_vector(EVP_sha256(), key, key_len, num_elem, addr,
+ len, mac, 32);
+}
- HMAC_CTX_init(&ctx);
-#if OPENSSL_VERSION_NUMBER < 0x00909000
- HMAC_Init_ex(&ctx, key, key_len, EVP_sha256(), NULL);
-#else /* openssl < 0.9.9 */
- if (HMAC_Init_ex(&ctx, key, key_len, EVP_sha256(), NULL) != 1)
- return -1;
-#endif /* openssl < 0.9.9 */
- for (i = 0; i < num_elem; i++)
- HMAC_Update(&ctx, addr[i], len[i]);
+int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
+ size_t data_len, u8 *mac)
+{
+ return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
+}
- mdlen = 32;
-#if OPENSSL_VERSION_NUMBER < 0x00909000
- HMAC_Final(&ctx, mac, &mdlen);
- res = 1;
-#else /* openssl < 0.9.9 */
- res = HMAC_Final(&ctx, mac, &mdlen);
-#endif /* openssl < 0.9.9 */
- HMAC_CTX_cleanup(&ctx);
+#endif /* CONFIG_SHA256 */
- return res == 1 ? 0 : -1;
+
+#ifdef CONFIG_SHA384
+
+int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac)
+{
+ return openssl_hmac_vector(EVP_sha384(), key, key_len, num_elem, addr,
+ len, mac, 32);
}
-int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
+int hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
size_t data_len, u8 *mac)
{
- return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
+ return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac);
}
-#endif /* CONFIG_SHA256 */
+#endif /* CONFIG_SHA384 */
int crypto_get_random(void *buf, size_t len)
@@ -786,8 +821,8 @@ int crypto_get_random(void *buf, size_t len)
#ifdef CONFIG_OPENSSL_CMAC
-int omac1_aes_128_vector(const u8 *key, size_t num_elem,
- const u8 *addr[], const size_t *len, u8 *mac)
+int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac)
{
CMAC_CTX *ctx;
int ret = -1;
@@ -797,8 +832,15 @@ int omac1_aes_128_vector(const u8 *key, size_t num_elem,
if (ctx == NULL)
return -1;
- if (!CMAC_Init(ctx, key, 16, EVP_aes_128_cbc(), NULL))
+ if (key_len == 32) {
+ if (!CMAC_Init(ctx, key, 32, EVP_aes_256_cbc(), NULL))
+ goto fail;
+ } else if (key_len == 16) {
+ if (!CMAC_Init(ctx, key, 16, EVP_aes_128_cbc(), NULL))
+ goto fail;
+ } else {
goto fail;
+ }
for (i = 0; i < num_elem; i++) {
if (!CMAC_Update(ctx, addr[i], len[i]))
goto fail;
@@ -813,8 +855,425 @@ fail:
}
+int omac1_aes_128_vector(const u8 *key, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac)
+{
+ return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
+}
+
+
int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
{
return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
}
+
+
+int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
+{
+ return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
+}
#endif /* CONFIG_OPENSSL_CMAC */
+
+
+struct crypto_bignum * crypto_bignum_init(void)
+{
+ return (struct crypto_bignum *) BN_new();
+}
+
+
+struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len)
+{
+ BIGNUM *bn = BN_bin2bn(buf, len, NULL);
+ return (struct crypto_bignum *) bn;
+}
+
+
+void crypto_bignum_deinit(struct crypto_bignum *n, int clear)
+{
+ if (clear)
+ BN_clear_free((BIGNUM *) n);
+ else
+ BN_free((BIGNUM *) n);
+}
+
+
+int crypto_bignum_to_bin(const struct crypto_bignum *a,
+ u8 *buf, size_t buflen, size_t padlen)
+{
+ int num_bytes, offset;
+
+ if (padlen > buflen)
+ return -1;
+
+ num_bytes = BN_num_bytes((const BIGNUM *) a);
+ if ((size_t) num_bytes > buflen)
+ return -1;
+ if (padlen > (size_t) num_bytes)
+ offset = padlen - num_bytes;
+ else
+ offset = 0;
+
+ os_memset(buf, 0, offset);
+ BN_bn2bin((const BIGNUM *) a, buf + offset);
+
+ return num_bytes + offset;
+}
+
+
+int crypto_bignum_add(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ struct crypto_bignum *c)
+{
+ return BN_add((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b) ?
+ 0 : -1;
+}
+
+
+int crypto_bignum_mod(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ struct crypto_bignum *c)
+{
+ int res;
+ BN_CTX *bnctx;
+
+ bnctx = BN_CTX_new();
+ if (bnctx == NULL)
+ return -1;
+ res = BN_mod((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b,
+ bnctx);
+ BN_CTX_free(bnctx);
+
+ return res ? 0 : -1;
+}
+
+
+int crypto_bignum_exptmod(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ const struct crypto_bignum *c,
+ struct crypto_bignum *d)
+{
+ int res;
+ BN_CTX *bnctx;
+
+ bnctx = BN_CTX_new();
+ if (bnctx == NULL)
+ return -1;
+ res = BN_mod_exp((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b,
+ (const BIGNUM *) c, bnctx);
+ BN_CTX_free(bnctx);
+
+ return res ? 0 : -1;
+}
+
+
+int crypto_bignum_inverse(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ struct crypto_bignum *c)
+{
+ BIGNUM *res;
+ BN_CTX *bnctx;
+
+ bnctx = BN_CTX_new();
+ if (bnctx == NULL)
+ return -1;
+ res = BN_mod_inverse((BIGNUM *) c, (const BIGNUM *) a,
+ (const BIGNUM *) b, bnctx);
+ BN_CTX_free(bnctx);
+
+ return res ? 0 : -1;
+}
+
+
+int crypto_bignum_sub(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ struct crypto_bignum *c)
+{
+ return BN_sub((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b) ?
+ 0 : -1;
+}
+
+
+int crypto_bignum_div(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ struct crypto_bignum *c)
+{
+ int res;
+
+ BN_CTX *bnctx;
+
+ bnctx = BN_CTX_new();
+ if (bnctx == NULL)
+ return -1;
+ res = BN_div((BIGNUM *) c, NULL, (const BIGNUM *) a,
+ (const BIGNUM *) b, bnctx);
+ BN_CTX_free(bnctx);
+
+ return res ? 0 : -1;
+}
+
+
+int crypto_bignum_mulmod(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ const struct crypto_bignum *c,
+ struct crypto_bignum *d)
+{
+ int res;
+
+ BN_CTX *bnctx;
+
+ bnctx = BN_CTX_new();
+ if (bnctx == NULL)
+ return -1;
+ res = BN_mod_mul((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b,
+ (const BIGNUM *) c, bnctx);
+ BN_CTX_free(bnctx);
+
+ return res ? 0 : -1;
+}
+
+
+int crypto_bignum_cmp(const struct crypto_bignum *a,
+ const struct crypto_bignum *b)
+{
+ return BN_cmp((const BIGNUM *) a, (const BIGNUM *) b);
+}
+
+
+int crypto_bignum_bits(const struct crypto_bignum *a)
+{
+ return BN_num_bits((const BIGNUM *) a);
+}
+
+
+int crypto_bignum_is_zero(const struct crypto_bignum *a)
+{
+ return BN_is_zero((const BIGNUM *) a);
+}
+
+
+int crypto_bignum_is_one(const struct crypto_bignum *a)
+{
+ return BN_is_one((const BIGNUM *) a);
+}
+
+
+#ifdef CONFIG_ECC
+
+struct crypto_ec {
+ EC_GROUP *group;
+ BN_CTX *bnctx;
+ BIGNUM *prime;
+ BIGNUM *order;
+};
+
+struct crypto_ec * crypto_ec_init(int group)
+{
+ struct crypto_ec *e;
+ int nid;
+
+ /* Map from IANA registry for IKE D-H groups to OpenSSL NID */
+ switch (group) {
+ case 19:
+ nid = NID_X9_62_prime256v1;
+ break;
+ case 20:
+ nid = NID_secp384r1;
+ break;
+ case 21:
+ nid = NID_secp521r1;
+ break;
+ case 25:
+ nid = NID_X9_62_prime192v1;
+ break;
+ case 26:
+ nid = NID_secp224r1;
+ break;
+ default:
+ return NULL;
+ }
+
+ e = os_zalloc(sizeof(*e));
+ if (e == NULL)
+ return NULL;
+
+ e->bnctx = BN_CTX_new();
+ e->group = EC_GROUP_new_by_curve_name(nid);
+ e->prime = BN_new();
+ e->order = BN_new();
+ if (e->group == NULL || e->bnctx == NULL || e->prime == NULL ||
+ e->order == NULL ||
+ !EC_GROUP_get_curve_GFp(e->group, e->prime, NULL, NULL, e->bnctx) ||
+ !EC_GROUP_get_order(e->group, e->order, e->bnctx)) {
+ crypto_ec_deinit(e);
+ e = NULL;
+ }
+
+ return e;
+}
+
+
+void crypto_ec_deinit(struct crypto_ec *e)
+{
+ if (e == NULL)
+ return;
+ BN_clear_free(e->order);
+ BN_clear_free(e->prime);
+ EC_GROUP_free(e->group);
+ BN_CTX_free(e->bnctx);
+ os_free(e);
+}
+
+
+struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e)
+{
+ if (e == NULL)
+ return NULL;
+ return (struct crypto_ec_point *) EC_POINT_new(e->group);
+}
+
+
+size_t crypto_ec_prime_len(struct crypto_ec *e)
+{
+ return BN_num_bytes(e->prime);
+}
+
+
+size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
+{
+ return BN_num_bits(e->prime);
+}
+
+
+const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e)
+{
+ return (const struct crypto_bignum *) e->prime;
+}
+
+
+const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e)
+{
+ return (const struct crypto_bignum *) e->order;
+}
+
+
+void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear)
+{
+ if (clear)
+ EC_POINT_clear_free((EC_POINT *) p);
+ else
+ EC_POINT_free((EC_POINT *) p);
+}
+
+
+int crypto_ec_point_to_bin(struct crypto_ec *e,
+ const struct crypto_ec_point *point, u8 *x, u8 *y)
+{
+ BIGNUM *x_bn, *y_bn;
+ int ret = -1;
+ int len = BN_num_bytes(e->prime);
+
+ x_bn = BN_new();
+ y_bn = BN_new();
+
+ if (x_bn && y_bn &&
+ EC_POINT_get_affine_coordinates_GFp(e->group, (EC_POINT *) point,
+ x_bn, y_bn, e->bnctx)) {
+ if (x) {
+ crypto_bignum_to_bin((struct crypto_bignum *) x_bn,
+ x, len, len);
+ }
+ if (y) {
+ crypto_bignum_to_bin((struct crypto_bignum *) y_bn,
+ y, len, len);
+ }
+ ret = 0;
+ }
+
+ BN_clear_free(x_bn);
+ BN_clear_free(y_bn);
+ return ret;
+}
+
+
+struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e,
+ const u8 *val)
+{
+ BIGNUM *x, *y;
+ EC_POINT *elem;
+ int len = BN_num_bytes(e->prime);
+
+ x = BN_bin2bn(val, len, NULL);
+ y = BN_bin2bn(val + len, len, NULL);
+ elem = EC_POINT_new(e->group);
+ if (x == NULL || y == NULL || elem == NULL) {
+ BN_clear_free(x);
+ BN_clear_free(y);
+ EC_POINT_clear_free(elem);
+ return NULL;
+ }
+
+ if (!EC_POINT_set_affine_coordinates_GFp(e->group, elem, x, y,
+ e->bnctx)) {
+ EC_POINT_clear_free(elem);
+ elem = NULL;
+ }
+
+ BN_clear_free(x);
+ BN_clear_free(y);
+
+ return (struct crypto_ec_point *) elem;
+}
+
+
+int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a,
+ const struct crypto_ec_point *b,
+ struct crypto_ec_point *c)
+{
+ return EC_POINT_add(e->group, (EC_POINT *) c, (const EC_POINT *) a,
+ (const EC_POINT *) b, e->bnctx) ? 0 : -1;
+}
+
+
+int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p,
+ const struct crypto_bignum *b,
+ struct crypto_ec_point *res)
+{
+ return EC_POINT_mul(e->group, (EC_POINT *) res, NULL,
+ (const EC_POINT *) p, (const BIGNUM *) b, e->bnctx)
+ ? 0 : -1;
+}
+
+
+int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p)
+{
+ return EC_POINT_invert(e->group, (EC_POINT *) p, e->bnctx) ? 0 : -1;
+}
+
+
+int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
+ struct crypto_ec_point *p,
+ const struct crypto_bignum *x, int y_bit)
+{
+ if (!EC_POINT_set_compressed_coordinates_GFp(e->group, (EC_POINT *) p,
+ (const BIGNUM *) x, y_bit,
+ e->bnctx) ||
+ !EC_POINT_is_on_curve(e->group, (EC_POINT *) p, e->bnctx))
+ return -1;
+ return 0;
+}
+
+
+int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
+ const struct crypto_ec_point *p)
+{
+ return EC_POINT_is_at_infinity(e->group, (const EC_POINT *) p);
+}
+
+
+int crypto_ec_point_is_on_curve(struct crypto_ec *e,
+ const struct crypto_ec_point *p)
+{
+ return EC_POINT_is_on_curve(e->group, (const EC_POINT *) p, e->bnctx);
+}
+
+#endif /* CONFIG_ECC */
diff --git a/src/crypto/dh_groups.c b/src/crypto/dh_groups.c
index f757b6b54e8f0..d3b263196e2d1 100644
--- a/src/crypto/dh_groups.c
+++ b/src/crypto/dh_groups.c
@@ -35,6 +35,20 @@ static const u8 dh_group1_prime[96] = {
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x3A, 0x36, 0x20,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
+static const u8 dh_group1_order[96] = {
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A,
+ 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68,
+ 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A,
+ 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91,
+ 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E,
+ 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D,
+ 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B,
+ 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22,
+ 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63,
+ 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1D, 0x1B, 0x10,
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
/* RFC 4306, B.2. Group 2 - 1024 Bit MODP
* Generator: 2
@@ -59,6 +73,24 @@ static const u8 dh_group2_prime[128] = {
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
+static const u8 dh_group2_order[128] = {
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A,
+ 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68,
+ 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A,
+ 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91,
+ 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E,
+ 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D,
+ 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B,
+ 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22,
+ 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63,
+ 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5,
+ 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6,
+ 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2,
+ 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3,
+ 0x24, 0x94, 0x33, 0x28, 0xF6, 0x73, 0x29, 0xC0,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
#endif /* ALL_DH_GROUPS */
@@ -93,6 +125,32 @@ static const u8 dh_group5_prime[192] = {
0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
+static const u8 dh_group5_order[192] = {
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A,
+ 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68,
+ 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A,
+ 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91,
+ 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E,
+ 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D,
+ 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B,
+ 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22,
+ 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63,
+ 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5,
+ 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6,
+ 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2,
+ 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3,
+ 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E,
+ 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82,
+ 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD,
+ 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF,
+ 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB,
+ 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D,
+ 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36,
+ 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02,
+ 0x78, 0xBA, 0x36, 0x04, 0x65, 0x11, 0xB9, 0x93,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
#ifdef ALL_DH_GROUPS
@@ -135,6 +193,40 @@ static const u8 dh_group14_prime[256] = {
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
+static const u8 dh_group14_order[256] = {
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A,
+ 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68,
+ 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A,
+ 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91,
+ 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E,
+ 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D,
+ 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B,
+ 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22,
+ 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63,
+ 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5,
+ 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6,
+ 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2,
+ 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3,
+ 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E,
+ 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82,
+ 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD,
+ 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF,
+ 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB,
+ 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D,
+ 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36,
+ 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02,
+ 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, 0x10, 0xBE,
+ 0x19, 0x48, 0x2F, 0x23, 0x17, 0x1B, 0x67, 0x1D,
+ 0xF1, 0xCF, 0x3B, 0x96, 0x0C, 0x07, 0x43, 0x01,
+ 0xCD, 0x93, 0xC1, 0xD1, 0x76, 0x03, 0xD1, 0x47,
+ 0xDA, 0xE2, 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64,
+ 0xEF, 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C,
+ 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, 0x72,
+ 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, 0x02, 0x88,
+ 0x0A, 0xB9, 0x47, 0x2D, 0x45, 0x56, 0x55, 0x34,
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
/* RFC 3526, 4. Group 15 - 3072 Bit MODP
* Generator: 2
@@ -191,6 +283,56 @@ static const u8 dh_group15_prime[384] = {
0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
+static const u8 dh_group15_order[384] = {
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A,
+ 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68,
+ 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A,
+ 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91,
+ 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E,
+ 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D,
+ 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B,
+ 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22,
+ 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63,
+ 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5,
+ 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6,
+ 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2,
+ 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3,
+ 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E,
+ 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82,
+ 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD,
+ 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF,
+ 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB,
+ 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D,
+ 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36,
+ 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02,
+ 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, 0x10, 0xBE,
+ 0x19, 0x48, 0x2F, 0x23, 0x17, 0x1B, 0x67, 0x1D,
+ 0xF1, 0xCF, 0x3B, 0x96, 0x0C, 0x07, 0x43, 0x01,
+ 0xCD, 0x93, 0xC1, 0xD1, 0x76, 0x03, 0xD1, 0x47,
+ 0xDA, 0xE2, 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64,
+ 0xEF, 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C,
+ 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, 0x72,
+ 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, 0x02, 0x88,
+ 0x0A, 0xB9, 0x47, 0x2D, 0x45, 0x55, 0x62, 0x16,
+ 0xD6, 0x99, 0x8B, 0x86, 0x82, 0x28, 0x3D, 0x19,
+ 0xD4, 0x2A, 0x90, 0xD5, 0xEF, 0x8E, 0x5D, 0x32,
+ 0x76, 0x7D, 0xC2, 0x82, 0x2C, 0x6D, 0xF7, 0x85,
+ 0x45, 0x75, 0x38, 0xAB, 0xAE, 0x83, 0x06, 0x3E,
+ 0xD9, 0xCB, 0x87, 0xC2, 0xD3, 0x70, 0xF2, 0x63,
+ 0xD5, 0xFA, 0xD7, 0x46, 0x6D, 0x84, 0x99, 0xEB,
+ 0x8F, 0x46, 0x4A, 0x70, 0x25, 0x12, 0xB0, 0xCE,
+ 0xE7, 0x71, 0xE9, 0x13, 0x0D, 0x69, 0x77, 0x35,
+ 0xF8, 0x97, 0xFD, 0x03, 0x6C, 0xC5, 0x04, 0x32,
+ 0x6C, 0x3B, 0x01, 0x39, 0x9F, 0x64, 0x35, 0x32,
+ 0x29, 0x0F, 0x95, 0x8C, 0x0B, 0xBD, 0x90, 0x06,
+ 0x5D, 0xF0, 0x8B, 0xAB, 0xBD, 0x30, 0xAE, 0xB6,
+ 0x3B, 0x84, 0xC4, 0x60, 0x5D, 0x6C, 0xA3, 0x71,
+ 0x04, 0x71, 0x27, 0xD0, 0x3A, 0x72, 0xD5, 0x98,
+ 0xA1, 0xED, 0xAD, 0xFE, 0x70, 0x7E, 0x88, 0x47,
+ 0x25, 0xC1, 0x68, 0x90, 0x54, 0x9D, 0x69, 0x65,
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
/* RFC 3526, 5. Group 16 - 4096 Bit MODP
* Generator: 2
@@ -263,6 +405,72 @@ static const u8 dh_group16_prime[512] = {
0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
+static const u8 dh_group16_order[512] = {
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A,
+ 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68,
+ 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A,
+ 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91,
+ 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E,
+ 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D,
+ 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B,
+ 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22,
+ 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63,
+ 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5,
+ 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6,
+ 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2,
+ 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3,
+ 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E,
+ 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82,
+ 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD,
+ 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF,
+ 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB,
+ 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D,
+ 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36,
+ 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02,
+ 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, 0x10, 0xBE,
+ 0x19, 0x48, 0x2F, 0x23, 0x17, 0x1B, 0x67, 0x1D,
+ 0xF1, 0xCF, 0x3B, 0x96, 0x0C, 0x07, 0x43, 0x01,
+ 0xCD, 0x93, 0xC1, 0xD1, 0x76, 0x03, 0xD1, 0x47,
+ 0xDA, 0xE2, 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64,
+ 0xEF, 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C,
+ 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, 0x72,
+ 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, 0x02, 0x88,
+ 0x0A, 0xB9, 0x47, 0x2D, 0x45, 0x55, 0x62, 0x16,
+ 0xD6, 0x99, 0x8B, 0x86, 0x82, 0x28, 0x3D, 0x19,
+ 0xD4, 0x2A, 0x90, 0xD5, 0xEF, 0x8E, 0x5D, 0x32,
+ 0x76, 0x7D, 0xC2, 0x82, 0x2C, 0x6D, 0xF7, 0x85,
+ 0x45, 0x75, 0x38, 0xAB, 0xAE, 0x83, 0x06, 0x3E,
+ 0xD9, 0xCB, 0x87, 0xC2, 0xD3, 0x70, 0xF2, 0x63,
+ 0xD5, 0xFA, 0xD7, 0x46, 0x6D, 0x84, 0x99, 0xEB,
+ 0x8F, 0x46, 0x4A, 0x70, 0x25, 0x12, 0xB0, 0xCE,
+ 0xE7, 0x71, 0xE9, 0x13, 0x0D, 0x69, 0x77, 0x35,
+ 0xF8, 0x97, 0xFD, 0x03, 0x6C, 0xC5, 0x04, 0x32,
+ 0x6C, 0x3B, 0x01, 0x39, 0x9F, 0x64, 0x35, 0x32,
+ 0x29, 0x0F, 0x95, 0x8C, 0x0B, 0xBD, 0x90, 0x06,
+ 0x5D, 0xF0, 0x8B, 0xAB, 0xBD, 0x30, 0xAE, 0xB6,
+ 0x3B, 0x84, 0xC4, 0x60, 0x5D, 0x6C, 0xA3, 0x71,
+ 0x04, 0x71, 0x27, 0xD0, 0x3A, 0x72, 0xD5, 0x98,
+ 0xA1, 0xED, 0xAD, 0xFE, 0x70, 0x7E, 0x88, 0x47,
+ 0x25, 0xC1, 0x68, 0x90, 0x54, 0x90, 0x84, 0x00,
+ 0x8D, 0x39, 0x1E, 0x09, 0x53, 0xC3, 0xF3, 0x6B,
+ 0xC4, 0x38, 0xCD, 0x08, 0x5E, 0xDD, 0x2D, 0x93,
+ 0x4C, 0xE1, 0x93, 0x8C, 0x35, 0x7A, 0x71, 0x1E,
+ 0x0D, 0x4A, 0x34, 0x1A, 0x5B, 0x0A, 0x85, 0xED,
+ 0x12, 0xC1, 0xF4, 0xE5, 0x15, 0x6A, 0x26, 0x74,
+ 0x6D, 0xDD, 0xE1, 0x6D, 0x82, 0x6F, 0x47, 0x7C,
+ 0x97, 0x47, 0x7E, 0x0A, 0x0F, 0xDF, 0x65, 0x53,
+ 0x14, 0x3E, 0x2C, 0xA3, 0xA7, 0x35, 0xE0, 0x2E,
+ 0xCC, 0xD9, 0x4B, 0x27, 0xD0, 0x48, 0x61, 0xD1,
+ 0x11, 0x9D, 0xD0, 0xC3, 0x28, 0xAD, 0xF3, 0xF6,
+ 0x8F, 0xB0, 0x94, 0xB8, 0x67, 0x71, 0x6B, 0xD7,
+ 0xDC, 0x0D, 0xEE, 0xBB, 0x10, 0xB8, 0x24, 0x0E,
+ 0x68, 0x03, 0x48, 0x93, 0xEA, 0xD8, 0x2D, 0x54,
+ 0xC9, 0xDA, 0x75, 0x4C, 0x46, 0xC7, 0xEE, 0xE0,
+ 0xC3, 0x7F, 0xDB, 0xEE, 0x48, 0x53, 0x60, 0x47,
+ 0xA6, 0xFA, 0x1A, 0xE4, 0x9A, 0x03, 0x18, 0xCC,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
/* RFC 3526, 6. Group 17 - 6144 Bit MODP
* Generator: 2
@@ -367,6 +575,104 @@ static const u8 dh_group17_prime[768] = {
0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xCC, 0x40, 0x24,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
+static const u8 dh_group17_order[768] = {
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A,
+ 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68,
+ 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A,
+ 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91,
+ 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E,
+ 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D,
+ 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B,
+ 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22,
+ 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63,
+ 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5,
+ 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6,
+ 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2,
+ 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3,
+ 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E,
+ 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82,
+ 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD,
+ 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF,
+ 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB,
+ 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D,
+ 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36,
+ 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02,
+ 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, 0x10, 0xBE,
+ 0x19, 0x48, 0x2F, 0x23, 0x17, 0x1B, 0x67, 0x1D,
+ 0xF1, 0xCF, 0x3B, 0x96, 0x0C, 0x07, 0x43, 0x01,
+ 0xCD, 0x93, 0xC1, 0xD1, 0x76, 0x03, 0xD1, 0x47,
+ 0xDA, 0xE2, 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64,
+ 0xEF, 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C,
+ 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, 0x72,
+ 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, 0x02, 0x88,
+ 0x0A, 0xB9, 0x47, 0x2D, 0x45, 0x55, 0x62, 0x16,
+ 0xD6, 0x99, 0x8B, 0x86, 0x82, 0x28, 0x3D, 0x19,
+ 0xD4, 0x2A, 0x90, 0xD5, 0xEF, 0x8E, 0x5D, 0x32,
+ 0x76, 0x7D, 0xC2, 0x82, 0x2C, 0x6D, 0xF7, 0x85,
+ 0x45, 0x75, 0x38, 0xAB, 0xAE, 0x83, 0x06, 0x3E,
+ 0xD9, 0xCB, 0x87, 0xC2, 0xD3, 0x70, 0xF2, 0x63,
+ 0xD5, 0xFA, 0xD7, 0x46, 0x6D, 0x84, 0x99, 0xEB,
+ 0x8F, 0x46, 0x4A, 0x70, 0x25, 0x12, 0xB0, 0xCE,
+ 0xE7, 0x71, 0xE9, 0x13, 0x0D, 0x69, 0x77, 0x35,
+ 0xF8, 0x97, 0xFD, 0x03, 0x6C, 0xC5, 0x04, 0x32,
+ 0x6C, 0x3B, 0x01, 0x39, 0x9F, 0x64, 0x35, 0x32,
+ 0x29, 0x0F, 0x95, 0x8C, 0x0B, 0xBD, 0x90, 0x06,
+ 0x5D, 0xF0, 0x8B, 0xAB, 0xBD, 0x30, 0xAE, 0xB6,
+ 0x3B, 0x84, 0xC4, 0x60, 0x5D, 0x6C, 0xA3, 0x71,
+ 0x04, 0x71, 0x27, 0xD0, 0x3A, 0x72, 0xD5, 0x98,
+ 0xA1, 0xED, 0xAD, 0xFE, 0x70, 0x7E, 0x88, 0x47,
+ 0x25, 0xC1, 0x68, 0x90, 0x54, 0x90, 0x84, 0x00,
+ 0x8D, 0x39, 0x1E, 0x09, 0x53, 0xC3, 0xF3, 0x6B,
+ 0xC4, 0x38, 0xCD, 0x08, 0x5E, 0xDD, 0x2D, 0x93,
+ 0x4C, 0xE1, 0x93, 0x8C, 0x35, 0x7A, 0x71, 0x1E,
+ 0x0D, 0x4A, 0x34, 0x1A, 0x5B, 0x0A, 0x85, 0xED,
+ 0x12, 0xC1, 0xF4, 0xE5, 0x15, 0x6A, 0x26, 0x74,
+ 0x6D, 0xDD, 0xE1, 0x6D, 0x82, 0x6F, 0x47, 0x7C,
+ 0x97, 0x47, 0x7E, 0x0A, 0x0F, 0xDF, 0x65, 0x53,
+ 0x14, 0x3E, 0x2C, 0xA3, 0xA7, 0x35, 0xE0, 0x2E,
+ 0xCC, 0xD9, 0x4B, 0x27, 0xD0, 0x48, 0x61, 0xD1,
+ 0x11, 0x9D, 0xD0, 0xC3, 0x28, 0xAD, 0xF3, 0xF6,
+ 0x8F, 0xB0, 0x94, 0xB8, 0x67, 0x71, 0x6B, 0xD7,
+ 0xDC, 0x0D, 0xEE, 0xBB, 0x10, 0xB8, 0x24, 0x0E,
+ 0x68, 0x03, 0x48, 0x93, 0xEA, 0xD8, 0x2D, 0x54,
+ 0xC9, 0xDA, 0x75, 0x4C, 0x46, 0xC7, 0xEE, 0xE0,
+ 0xC3, 0x7F, 0xDB, 0xEE, 0x48, 0x53, 0x60, 0x47,
+ 0xA6, 0xFA, 0x1A, 0xE4, 0x9A, 0x01, 0x42, 0x49,
+ 0x1B, 0x61, 0xFD, 0x5A, 0x69, 0x3E, 0x38, 0x13,
+ 0x60, 0xEA, 0x6E, 0x59, 0x30, 0x13, 0x23, 0x6F,
+ 0x64, 0xBA, 0x8F, 0x3B, 0x1E, 0xDD, 0x1B, 0xDE,
+ 0xFC, 0x7F, 0xCA, 0x03, 0x56, 0xCF, 0x29, 0x87,
+ 0x72, 0xED, 0x9C, 0x17, 0xA0, 0x98, 0x00, 0xD7,
+ 0x58, 0x35, 0x29, 0xF6, 0xC8, 0x13, 0xEC, 0x18,
+ 0x8B, 0xCB, 0x93, 0xD8, 0x43, 0x2D, 0x44, 0x8C,
+ 0x6D, 0x1F, 0x6D, 0xF5, 0xE7, 0xCD, 0x8A, 0x76,
+ 0xA2, 0x67, 0x36, 0x5D, 0x67, 0x6A, 0x5D, 0x8D,
+ 0xED, 0xBF, 0x8A, 0x23, 0xF3, 0x66, 0x12, 0xA5,
+ 0x99, 0x90, 0x28, 0xA8, 0x95, 0xEB, 0xD7, 0xA1,
+ 0x37, 0xDC, 0x7A, 0x00, 0x9B, 0xC6, 0x69, 0x5F,
+ 0xAC, 0xC1, 0xE5, 0x00, 0xE3, 0x25, 0xC9, 0x76,
+ 0x78, 0x19, 0x75, 0x0A, 0xE8, 0xB9, 0x0E, 0x81,
+ 0xFA, 0x41, 0x6B, 0xE7, 0x37, 0x3A, 0x7F, 0x7B,
+ 0x6A, 0xAF, 0x38, 0x17, 0xA3, 0x4C, 0x06, 0x41,
+ 0x5A, 0xD4, 0x20, 0x18, 0xC8, 0x05, 0x8E, 0x4F,
+ 0x2C, 0xF3, 0xE4, 0xBF, 0xDF, 0x63, 0xF4, 0x79,
+ 0x91, 0xD4, 0xBD, 0x3F, 0x1B, 0x66, 0x44, 0x5F,
+ 0x07, 0x8E, 0xA2, 0xDB, 0xFF, 0xAC, 0x2D, 0x62,
+ 0xA5, 0xEA, 0x03, 0xD9, 0x15, 0xA0, 0xAA, 0x55,
+ 0x66, 0x47, 0xB6, 0xBF, 0x5F, 0xA4, 0x70, 0xEC,
+ 0x0A, 0x66, 0x2F, 0x69, 0x07, 0xC0, 0x1B, 0xF0,
+ 0x53, 0xCB, 0x8A, 0xF7, 0x79, 0x4D, 0xF1, 0x94,
+ 0x03, 0x50, 0xEA, 0xC5, 0xDB, 0xE2, 0xED, 0x3B,
+ 0x7A, 0xA8, 0x55, 0x1E, 0xC5, 0x0F, 0xDF, 0xF8,
+ 0x75, 0x8C, 0xE6, 0x58, 0xD1, 0x89, 0xEA, 0xAE,
+ 0x6D, 0x2B, 0x64, 0xF6, 0x17, 0x79, 0x4B, 0x19,
+ 0x1C, 0x3F, 0xF4, 0x6B, 0xB7, 0x1E, 0x02, 0x34,
+ 0x02, 0x1F, 0x47, 0xB3, 0x1F, 0xA4, 0x30, 0x77,
+ 0x09, 0x5F, 0x96, 0xAD, 0x85, 0xBA, 0x3A, 0x6B,
+ 0x73, 0x4A, 0x7C, 0x8F, 0x36, 0xE6, 0x20, 0x12,
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
/* RFC 3526, 7. Group 18 - 8192 Bit MODP
* Generator: 2
@@ -503,29 +809,367 @@ static const u8 dh_group18_prime[1024] = {
0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
+static const u8 dh_group18_order[1024] = {
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A,
+ 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68,
+ 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A,
+ 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91,
+ 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E,
+ 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D,
+ 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B,
+ 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22,
+ 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63,
+ 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5,
+ 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6,
+ 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2,
+ 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3,
+ 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E,
+ 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82,
+ 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD,
+ 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF,
+ 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB,
+ 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D,
+ 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36,
+ 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02,
+ 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, 0x10, 0xBE,
+ 0x19, 0x48, 0x2F, 0x23, 0x17, 0x1B, 0x67, 0x1D,
+ 0xF1, 0xCF, 0x3B, 0x96, 0x0C, 0x07, 0x43, 0x01,
+ 0xCD, 0x93, 0xC1, 0xD1, 0x76, 0x03, 0xD1, 0x47,
+ 0xDA, 0xE2, 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64,
+ 0xEF, 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C,
+ 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, 0x72,
+ 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, 0x02, 0x88,
+ 0x0A, 0xB9, 0x47, 0x2D, 0x45, 0x55, 0x62, 0x16,
+ 0xD6, 0x99, 0x8B, 0x86, 0x82, 0x28, 0x3D, 0x19,
+ 0xD4, 0x2A, 0x90, 0xD5, 0xEF, 0x8E, 0x5D, 0x32,
+ 0x76, 0x7D, 0xC2, 0x82, 0x2C, 0x6D, 0xF7, 0x85,
+ 0x45, 0x75, 0x38, 0xAB, 0xAE, 0x83, 0x06, 0x3E,
+ 0xD9, 0xCB, 0x87, 0xC2, 0xD3, 0x70, 0xF2, 0x63,
+ 0xD5, 0xFA, 0xD7, 0x46, 0x6D, 0x84, 0x99, 0xEB,
+ 0x8F, 0x46, 0x4A, 0x70, 0x25, 0x12, 0xB0, 0xCE,
+ 0xE7, 0x71, 0xE9, 0x13, 0x0D, 0x69, 0x77, 0x35,
+ 0xF8, 0x97, 0xFD, 0x03, 0x6C, 0xC5, 0x04, 0x32,
+ 0x6C, 0x3B, 0x01, 0x39, 0x9F, 0x64, 0x35, 0x32,
+ 0x29, 0x0F, 0x95, 0x8C, 0x0B, 0xBD, 0x90, 0x06,
+ 0x5D, 0xF0, 0x8B, 0xAB, 0xBD, 0x30, 0xAE, 0xB6,
+ 0x3B, 0x84, 0xC4, 0x60, 0x5D, 0x6C, 0xA3, 0x71,
+ 0x04, 0x71, 0x27, 0xD0, 0x3A, 0x72, 0xD5, 0x98,
+ 0xA1, 0xED, 0xAD, 0xFE, 0x70, 0x7E, 0x88, 0x47,
+ 0x25, 0xC1, 0x68, 0x90, 0x54, 0x90, 0x84, 0x00,
+ 0x8D, 0x39, 0x1E, 0x09, 0x53, 0xC3, 0xF3, 0x6B,
+ 0xC4, 0x38, 0xCD, 0x08, 0x5E, 0xDD, 0x2D, 0x93,
+ 0x4C, 0xE1, 0x93, 0x8C, 0x35, 0x7A, 0x71, 0x1E,
+ 0x0D, 0x4A, 0x34, 0x1A, 0x5B, 0x0A, 0x85, 0xED,
+ 0x12, 0xC1, 0xF4, 0xE5, 0x15, 0x6A, 0x26, 0x74,
+ 0x6D, 0xDD, 0xE1, 0x6D, 0x82, 0x6F, 0x47, 0x7C,
+ 0x97, 0x47, 0x7E, 0x0A, 0x0F, 0xDF, 0x65, 0x53,
+ 0x14, 0x3E, 0x2C, 0xA3, 0xA7, 0x35, 0xE0, 0x2E,
+ 0xCC, 0xD9, 0x4B, 0x27, 0xD0, 0x48, 0x61, 0xD1,
+ 0x11, 0x9D, 0xD0, 0xC3, 0x28, 0xAD, 0xF3, 0xF6,
+ 0x8F, 0xB0, 0x94, 0xB8, 0x67, 0x71, 0x6B, 0xD7,
+ 0xDC, 0x0D, 0xEE, 0xBB, 0x10, 0xB8, 0x24, 0x0E,
+ 0x68, 0x03, 0x48, 0x93, 0xEA, 0xD8, 0x2D, 0x54,
+ 0xC9, 0xDA, 0x75, 0x4C, 0x46, 0xC7, 0xEE, 0xE0,
+ 0xC3, 0x7F, 0xDB, 0xEE, 0x48, 0x53, 0x60, 0x47,
+ 0xA6, 0xFA, 0x1A, 0xE4, 0x9A, 0x01, 0x42, 0x49,
+ 0x1B, 0x61, 0xFD, 0x5A, 0x69, 0x3E, 0x38, 0x13,
+ 0x60, 0xEA, 0x6E, 0x59, 0x30, 0x13, 0x23, 0x6F,
+ 0x64, 0xBA, 0x8F, 0x3B, 0x1E, 0xDD, 0x1B, 0xDE,
+ 0xFC, 0x7F, 0xCA, 0x03, 0x56, 0xCF, 0x29, 0x87,
+ 0x72, 0xED, 0x9C, 0x17, 0xA0, 0x98, 0x00, 0xD7,
+ 0x58, 0x35, 0x29, 0xF6, 0xC8, 0x13, 0xEC, 0x18,
+ 0x8B, 0xCB, 0x93, 0xD8, 0x43, 0x2D, 0x44, 0x8C,
+ 0x6D, 0x1F, 0x6D, 0xF5, 0xE7, 0xCD, 0x8A, 0x76,
+ 0xA2, 0x67, 0x36, 0x5D, 0x67, 0x6A, 0x5D, 0x8D,
+ 0xED, 0xBF, 0x8A, 0x23, 0xF3, 0x66, 0x12, 0xA5,
+ 0x99, 0x90, 0x28, 0xA8, 0x95, 0xEB, 0xD7, 0xA1,
+ 0x37, 0xDC, 0x7A, 0x00, 0x9B, 0xC6, 0x69, 0x5F,
+ 0xAC, 0xC1, 0xE5, 0x00, 0xE3, 0x25, 0xC9, 0x76,
+ 0x78, 0x19, 0x75, 0x0A, 0xE8, 0xB9, 0x0E, 0x81,
+ 0xFA, 0x41, 0x6B, 0xE7, 0x37, 0x3A, 0x7F, 0x7B,
+ 0x6A, 0xAF, 0x38, 0x17, 0xA3, 0x4C, 0x06, 0x41,
+ 0x5A, 0xD4, 0x20, 0x18, 0xC8, 0x05, 0x8E, 0x4F,
+ 0x2C, 0xF3, 0xE4, 0xBF, 0xDF, 0x63, 0xF4, 0x79,
+ 0x91, 0xD4, 0xBD, 0x3F, 0x1B, 0x66, 0x44, 0x5F,
+ 0x07, 0x8E, 0xA2, 0xDB, 0xFF, 0xAC, 0x2D, 0x62,
+ 0xA5, 0xEA, 0x03, 0xD9, 0x15, 0xA0, 0xAA, 0x55,
+ 0x66, 0x47, 0xB6, 0xBF, 0x5F, 0xA4, 0x70, 0xEC,
+ 0x0A, 0x66, 0x2F, 0x69, 0x07, 0xC0, 0x1B, 0xF0,
+ 0x53, 0xCB, 0x8A, 0xF7, 0x79, 0x4D, 0xF1, 0x94,
+ 0x03, 0x50, 0xEA, 0xC5, 0xDB, 0xE2, 0xED, 0x3B,
+ 0x7A, 0xA8, 0x55, 0x1E, 0xC5, 0x0F, 0xDF, 0xF8,
+ 0x75, 0x8C, 0xE6, 0x58, 0xD1, 0x89, 0xEA, 0xAE,
+ 0x6D, 0x2B, 0x64, 0xF6, 0x17, 0x79, 0x4B, 0x19,
+ 0x1C, 0x3F, 0xF4, 0x6B, 0xB7, 0x1E, 0x02, 0x34,
+ 0x02, 0x1F, 0x47, 0xB3, 0x1F, 0xA4, 0x30, 0x77,
+ 0x09, 0x5F, 0x96, 0xAD, 0x85, 0xBA, 0x3A, 0x6B,
+ 0x73, 0x4A, 0x7C, 0x8F, 0x36, 0xDF, 0x08, 0xAC,
+ 0xBA, 0x51, 0xC9, 0x37, 0x89, 0x7F, 0x72, 0xF2,
+ 0x1C, 0x3B, 0xBE, 0x5B, 0x54, 0x99, 0x6F, 0xC6,
+ 0x6C, 0x5F, 0x62, 0x68, 0x39, 0xDC, 0x98, 0xDD,
+ 0x1D, 0xE4, 0x19, 0x5B, 0x46, 0xCE, 0xE9, 0x80,
+ 0x3A, 0x0F, 0xD3, 0xDF, 0xC5, 0x7E, 0x23, 0xF6,
+ 0x92, 0xBB, 0x7B, 0x49, 0xB5, 0xD2, 0x12, 0x33,
+ 0x1D, 0x55, 0xB1, 0xCE, 0x2D, 0x72, 0x7A, 0xB4,
+ 0x1A, 0x11, 0xDA, 0x3A, 0x15, 0xF8, 0xE4, 0xBC,
+ 0x11, 0xC7, 0x8B, 0x65, 0xF1, 0xCE, 0xB2, 0x96,
+ 0xF1, 0xFE, 0xDC, 0x5F, 0x7E, 0x42, 0x45, 0x6C,
+ 0x91, 0x11, 0x17, 0x02, 0x52, 0x01, 0xBE, 0x03,
+ 0x89, 0xF5, 0xAB, 0xD4, 0x0D, 0x11, 0xF8, 0x63,
+ 0x9A, 0x39, 0xFE, 0x32, 0x36, 0x75, 0x18, 0x35,
+ 0xA5, 0xE5, 0xE4, 0x43, 0x17, 0xC1, 0xC2, 0xEE,
+ 0xFD, 0x4E, 0xA5, 0xBF, 0xD1, 0x60, 0x43, 0xF4,
+ 0x3C, 0xB4, 0x19, 0x81, 0xF6, 0xAD, 0xEE, 0x9D,
+ 0x03, 0x15, 0x9E, 0x7A, 0xD9, 0xD1, 0x3C, 0x53,
+ 0x36, 0x95, 0x09, 0xFC, 0x1F, 0xA2, 0x7C, 0x16,
+ 0xEF, 0x98, 0x87, 0x70, 0x3A, 0x55, 0xB5, 0x1B,
+ 0x22, 0xCB, 0xF4, 0x4C, 0xD0, 0x12, 0xAE, 0xE0,
+ 0xB2, 0x79, 0x8E, 0x62, 0x84, 0x23, 0x42, 0x8E,
+ 0xFC, 0xD5, 0xA4, 0x0C, 0xAE, 0xF6, 0xBF, 0x50,
+ 0xD8, 0xEA, 0x88, 0x5E, 0xBF, 0x73, 0xA6, 0xB9,
+ 0xFD, 0x79, 0xB5, 0xE1, 0x8F, 0x67, 0xD1, 0x34,
+ 0x1A, 0xC8, 0x23, 0x7A, 0x75, 0xC3, 0xCF, 0xC9,
+ 0x20, 0x04, 0xA1, 0xC5, 0xA4, 0x0E, 0x36, 0x6B,
+ 0xC4, 0x4D, 0x00, 0x17, 0x6A, 0xF7, 0x1C, 0x15,
+ 0xE4, 0x8C, 0x86, 0xD3, 0x7E, 0x01, 0x37, 0x23,
+ 0xCA, 0xAC, 0x72, 0x23, 0xAB, 0x3B, 0xF4, 0xD5,
+ 0x4F, 0x18, 0x28, 0x71, 0x3B, 0x2B, 0x4A, 0x6F,
+ 0xE4, 0x0F, 0xAB, 0x74, 0x40, 0x5C, 0xB7, 0x38,
+ 0xB0, 0x64, 0xC0, 0x6E, 0xCC, 0x76, 0xE9, 0xEF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/*
+ * RFC 5114, 2.1.
+ * Group 22 - 1024-bit MODP Group with 160-bit Prime Order Subgroup
+ */
+static const u8 dh_group22_generator[] = {
+ 0xA4, 0xD1, 0xCB, 0xD5, 0xC3, 0xFD, 0x34, 0x12,
+ 0x67, 0x65, 0xA4, 0x42, 0xEF, 0xB9, 0x99, 0x05,
+ 0xF8, 0x10, 0x4D, 0xD2, 0x58, 0xAC, 0x50, 0x7F,
+ 0xD6, 0x40, 0x6C, 0xFF, 0x14, 0x26, 0x6D, 0x31,
+ 0x26, 0x6F, 0xEA, 0x1E, 0x5C, 0x41, 0x56, 0x4B,
+ 0x77, 0x7E, 0x69, 0x0F, 0x55, 0x04, 0xF2, 0x13,
+ 0x16, 0x02, 0x17, 0xB4, 0xB0, 0x1B, 0x88, 0x6A,
+ 0x5E, 0x91, 0x54, 0x7F, 0x9E, 0x27, 0x49, 0xF4,
+ 0xD7, 0xFB, 0xD7, 0xD3, 0xB9, 0xA9, 0x2E, 0xE1,
+ 0x90, 0x9D, 0x0D, 0x22, 0x63, 0xF8, 0x0A, 0x76,
+ 0xA6, 0xA2, 0x4C, 0x08, 0x7A, 0x09, 0x1F, 0x53,
+ 0x1D, 0xBF, 0x0A, 0x01, 0x69, 0xB6, 0xA2, 0x8A,
+ 0xD6, 0x62, 0xA4, 0xD1, 0x8E, 0x73, 0xAF, 0xA3,
+ 0x2D, 0x77, 0x9D, 0x59, 0x18, 0xD0, 0x8B, 0xC8,
+ 0x85, 0x8F, 0x4D, 0xCE, 0xF9, 0x7C, 0x2A, 0x24,
+ 0x85, 0x5E, 0x6E, 0xEB, 0x22, 0xB3, 0xB2, 0xE5
+};
+static const u8 dh_group22_prime[] = {
+ 0xB1, 0x0B, 0x8F, 0x96, 0xA0, 0x80, 0xE0, 0x1D,
+ 0xDE, 0x92, 0xDE, 0x5E, 0xAE, 0x5D, 0x54, 0xEC,
+ 0x52, 0xC9, 0x9F, 0xBC, 0xFB, 0x06, 0xA3, 0xC6,
+ 0x9A, 0x6A, 0x9D, 0xCA, 0x52, 0xD2, 0x3B, 0x61,
+ 0x60, 0x73, 0xE2, 0x86, 0x75, 0xA2, 0x3D, 0x18,
+ 0x98, 0x38, 0xEF, 0x1E, 0x2E, 0xE6, 0x52, 0xC0,
+ 0x13, 0xEC, 0xB4, 0xAE, 0xA9, 0x06, 0x11, 0x23,
+ 0x24, 0x97, 0x5C, 0x3C, 0xD4, 0x9B, 0x83, 0xBF,
+ 0xAC, 0xCB, 0xDD, 0x7D, 0x90, 0xC4, 0xBD, 0x70,
+ 0x98, 0x48, 0x8E, 0x9C, 0x21, 0x9A, 0x73, 0x72,
+ 0x4E, 0xFF, 0xD6, 0xFA, 0xE5, 0x64, 0x47, 0x38,
+ 0xFA, 0xA3, 0x1A, 0x4F, 0xF5, 0x5B, 0xCC, 0xC0,
+ 0xA1, 0x51, 0xAF, 0x5F, 0x0D, 0xC8, 0xB4, 0xBD,
+ 0x45, 0xBF, 0x37, 0xDF, 0x36, 0x5C, 0x1A, 0x65,
+ 0xE6, 0x8C, 0xFD, 0xA7, 0x6D, 0x4D, 0xA7, 0x08,
+ 0xDF, 0x1F, 0xB2, 0xBC, 0x2E, 0x4A, 0x43, 0x71
+};
+static const u8 dh_group22_order[] = {
+ 0xF5, 0x18, 0xAA, 0x87, 0x81, 0xA8, 0xDF, 0x27,
+ 0x8A, 0xBA, 0x4E, 0x7D, 0x64, 0xB7, 0xCB, 0x9D,
+ 0x49, 0x46, 0x23, 0x53
+};
+
+/*
+ * RFC 5114, 2.2.
+ * Group 23 - 2048-bit MODP Group with 224-bit Prime Order Subgroup
+ */
+static const u8 dh_group23_generator[] = {
+ 0xAC, 0x40, 0x32, 0xEF, 0x4F, 0x2D, 0x9A, 0xE3,
+ 0x9D, 0xF3, 0x0B, 0x5C, 0x8F, 0xFD, 0xAC, 0x50,
+ 0x6C, 0xDE, 0xBE, 0x7B, 0x89, 0x99, 0x8C, 0xAF,
+ 0x74, 0x86, 0x6A, 0x08, 0xCF, 0xE4, 0xFF, 0xE3,
+ 0xA6, 0x82, 0x4A, 0x4E, 0x10, 0xB9, 0xA6, 0xF0,
+ 0xDD, 0x92, 0x1F, 0x01, 0xA7, 0x0C, 0x4A, 0xFA,
+ 0xAB, 0x73, 0x9D, 0x77, 0x00, 0xC2, 0x9F, 0x52,
+ 0xC5, 0x7D, 0xB1, 0x7C, 0x62, 0x0A, 0x86, 0x52,
+ 0xBE, 0x5E, 0x90, 0x01, 0xA8, 0xD6, 0x6A, 0xD7,
+ 0xC1, 0x76, 0x69, 0x10, 0x19, 0x99, 0x02, 0x4A,
+ 0xF4, 0xD0, 0x27, 0x27, 0x5A, 0xC1, 0x34, 0x8B,
+ 0xB8, 0xA7, 0x62, 0xD0, 0x52, 0x1B, 0xC9, 0x8A,
+ 0xE2, 0x47, 0x15, 0x04, 0x22, 0xEA, 0x1E, 0xD4,
+ 0x09, 0x93, 0x9D, 0x54, 0xDA, 0x74, 0x60, 0xCD,
+ 0xB5, 0xF6, 0xC6, 0xB2, 0x50, 0x71, 0x7C, 0xBE,
+ 0xF1, 0x80, 0xEB, 0x34, 0x11, 0x8E, 0x98, 0xD1,
+ 0x19, 0x52, 0x9A, 0x45, 0xD6, 0xF8, 0x34, 0x56,
+ 0x6E, 0x30, 0x25, 0xE3, 0x16, 0xA3, 0x30, 0xEF,
+ 0xBB, 0x77, 0xA8, 0x6F, 0x0C, 0x1A, 0xB1, 0x5B,
+ 0x05, 0x1A, 0xE3, 0xD4, 0x28, 0xC8, 0xF8, 0xAC,
+ 0xB7, 0x0A, 0x81, 0x37, 0x15, 0x0B, 0x8E, 0xEB,
+ 0x10, 0xE1, 0x83, 0xED, 0xD1, 0x99, 0x63, 0xDD,
+ 0xD9, 0xE2, 0x63, 0xE4, 0x77, 0x05, 0x89, 0xEF,
+ 0x6A, 0xA2, 0x1E, 0x7F, 0x5F, 0x2F, 0xF3, 0x81,
+ 0xB5, 0x39, 0xCC, 0xE3, 0x40, 0x9D, 0x13, 0xCD,
+ 0x56, 0x6A, 0xFB, 0xB4, 0x8D, 0x6C, 0x01, 0x91,
+ 0x81, 0xE1, 0xBC, 0xFE, 0x94, 0xB3, 0x02, 0x69,
+ 0xED, 0xFE, 0x72, 0xFE, 0x9B, 0x6A, 0xA4, 0xBD,
+ 0x7B, 0x5A, 0x0F, 0x1C, 0x71, 0xCF, 0xFF, 0x4C,
+ 0x19, 0xC4, 0x18, 0xE1, 0xF6, 0xEC, 0x01, 0x79,
+ 0x81, 0xBC, 0x08, 0x7F, 0x2A, 0x70, 0x65, 0xB3,
+ 0x84, 0xB8, 0x90, 0xD3, 0x19, 0x1F, 0x2B, 0xFA
+};
+static const u8 dh_group23_prime[] = {
+ 0xAD, 0x10, 0x7E, 0x1E, 0x91, 0x23, 0xA9, 0xD0,
+ 0xD6, 0x60, 0xFA, 0xA7, 0x95, 0x59, 0xC5, 0x1F,
+ 0xA2, 0x0D, 0x64, 0xE5, 0x68, 0x3B, 0x9F, 0xD1,
+ 0xB5, 0x4B, 0x15, 0x97, 0xB6, 0x1D, 0x0A, 0x75,
+ 0xE6, 0xFA, 0x14, 0x1D, 0xF9, 0x5A, 0x56, 0xDB,
+ 0xAF, 0x9A, 0x3C, 0x40, 0x7B, 0xA1, 0xDF, 0x15,
+ 0xEB, 0x3D, 0x68, 0x8A, 0x30, 0x9C, 0x18, 0x0E,
+ 0x1D, 0xE6, 0xB8, 0x5A, 0x12, 0x74, 0xA0, 0xA6,
+ 0x6D, 0x3F, 0x81, 0x52, 0xAD, 0x6A, 0xC2, 0x12,
+ 0x90, 0x37, 0xC9, 0xED, 0xEF, 0xDA, 0x4D, 0xF8,
+ 0xD9, 0x1E, 0x8F, 0xEF, 0x55, 0xB7, 0x39, 0x4B,
+ 0x7A, 0xD5, 0xB7, 0xD0, 0xB6, 0xC1, 0x22, 0x07,
+ 0xC9, 0xF9, 0x8D, 0x11, 0xED, 0x34, 0xDB, 0xF6,
+ 0xC6, 0xBA, 0x0B, 0x2C, 0x8B, 0xBC, 0x27, 0xBE,
+ 0x6A, 0x00, 0xE0, 0xA0, 0xB9, 0xC4, 0x97, 0x08,
+ 0xB3, 0xBF, 0x8A, 0x31, 0x70, 0x91, 0x88, 0x36,
+ 0x81, 0x28, 0x61, 0x30, 0xBC, 0x89, 0x85, 0xDB,
+ 0x16, 0x02, 0xE7, 0x14, 0x41, 0x5D, 0x93, 0x30,
+ 0x27, 0x82, 0x73, 0xC7, 0xDE, 0x31, 0xEF, 0xDC,
+ 0x73, 0x10, 0xF7, 0x12, 0x1F, 0xD5, 0xA0, 0x74,
+ 0x15, 0x98, 0x7D, 0x9A, 0xDC, 0x0A, 0x48, 0x6D,
+ 0xCD, 0xF9, 0x3A, 0xCC, 0x44, 0x32, 0x83, 0x87,
+ 0x31, 0x5D, 0x75, 0xE1, 0x98, 0xC6, 0x41, 0xA4,
+ 0x80, 0xCD, 0x86, 0xA1, 0xB9, 0xE5, 0x87, 0xE8,
+ 0xBE, 0x60, 0xE6, 0x9C, 0xC9, 0x28, 0xB2, 0xB9,
+ 0xC5, 0x21, 0x72, 0xE4, 0x13, 0x04, 0x2E, 0x9B,
+ 0x23, 0xF1, 0x0B, 0x0E, 0x16, 0xE7, 0x97, 0x63,
+ 0xC9, 0xB5, 0x3D, 0xCF, 0x4B, 0xA8, 0x0A, 0x29,
+ 0xE3, 0xFB, 0x73, 0xC1, 0x6B, 0x8E, 0x75, 0xB9,
+ 0x7E, 0xF3, 0x63, 0xE2, 0xFF, 0xA3, 0x1F, 0x71,
+ 0xCF, 0x9D, 0xE5, 0x38, 0x4E, 0x71, 0xB8, 0x1C,
+ 0x0A, 0xC4, 0xDF, 0xFE, 0x0C, 0x10, 0xE6, 0x4F
+};
+static const u8 dh_group23_order[] = {
+ 0x80, 0x1C, 0x0D, 0x34, 0xC5, 0x8D, 0x93, 0xFE,
+ 0x99, 0x71, 0x77, 0x10, 0x1F, 0x80, 0x53, 0x5A,
+ 0x47, 0x38, 0xCE, 0xBC, 0xBF, 0x38, 0x9A, 0x99,
+ 0xB3, 0x63, 0x71, 0xEB
+};
+
+/*
+ * RFC 5114, 2.3.
+ * Group 24 - 2048-bit MODP Group with 256-bit Prime Order Subgroup
+ */
+static const u8 dh_group24_generator[] = {
+ 0x3F, 0xB3, 0x2C, 0x9B, 0x73, 0x13, 0x4D, 0x0B,
+ 0x2E, 0x77, 0x50, 0x66, 0x60, 0xED, 0xBD, 0x48,
+ 0x4C, 0xA7, 0xB1, 0x8F, 0x21, 0xEF, 0x20, 0x54,
+ 0x07, 0xF4, 0x79, 0x3A, 0x1A, 0x0B, 0xA1, 0x25,
+ 0x10, 0xDB, 0xC1, 0x50, 0x77, 0xBE, 0x46, 0x3F,
+ 0xFF, 0x4F, 0xED, 0x4A, 0xAC, 0x0B, 0xB5, 0x55,
+ 0xBE, 0x3A, 0x6C, 0x1B, 0x0C, 0x6B, 0x47, 0xB1,
+ 0xBC, 0x37, 0x73, 0xBF, 0x7E, 0x8C, 0x6F, 0x62,
+ 0x90, 0x12, 0x28, 0xF8, 0xC2, 0x8C, 0xBB, 0x18,
+ 0xA5, 0x5A, 0xE3, 0x13, 0x41, 0x00, 0x0A, 0x65,
+ 0x01, 0x96, 0xF9, 0x31, 0xC7, 0x7A, 0x57, 0xF2,
+ 0xDD, 0xF4, 0x63, 0xE5, 0xE9, 0xEC, 0x14, 0x4B,
+ 0x77, 0x7D, 0xE6, 0x2A, 0xAA, 0xB8, 0xA8, 0x62,
+ 0x8A, 0xC3, 0x76, 0xD2, 0x82, 0xD6, 0xED, 0x38,
+ 0x64, 0xE6, 0x79, 0x82, 0x42, 0x8E, 0xBC, 0x83,
+ 0x1D, 0x14, 0x34, 0x8F, 0x6F, 0x2F, 0x91, 0x93,
+ 0xB5, 0x04, 0x5A, 0xF2, 0x76, 0x71, 0x64, 0xE1,
+ 0xDF, 0xC9, 0x67, 0xC1, 0xFB, 0x3F, 0x2E, 0x55,
+ 0xA4, 0xBD, 0x1B, 0xFF, 0xE8, 0x3B, 0x9C, 0x80,
+ 0xD0, 0x52, 0xB9, 0x85, 0xD1, 0x82, 0xEA, 0x0A,
+ 0xDB, 0x2A, 0x3B, 0x73, 0x13, 0xD3, 0xFE, 0x14,
+ 0xC8, 0x48, 0x4B, 0x1E, 0x05, 0x25, 0x88, 0xB9,
+ 0xB7, 0xD2, 0xBB, 0xD2, 0xDF, 0x01, 0x61, 0x99,
+ 0xEC, 0xD0, 0x6E, 0x15, 0x57, 0xCD, 0x09, 0x15,
+ 0xB3, 0x35, 0x3B, 0xBB, 0x64, 0xE0, 0xEC, 0x37,
+ 0x7F, 0xD0, 0x28, 0x37, 0x0D, 0xF9, 0x2B, 0x52,
+ 0xC7, 0x89, 0x14, 0x28, 0xCD, 0xC6, 0x7E, 0xB6,
+ 0x18, 0x4B, 0x52, 0x3D, 0x1D, 0xB2, 0x46, 0xC3,
+ 0x2F, 0x63, 0x07, 0x84, 0x90, 0xF0, 0x0E, 0xF8,
+ 0xD6, 0x47, 0xD1, 0x48, 0xD4, 0x79, 0x54, 0x51,
+ 0x5E, 0x23, 0x27, 0xCF, 0xEF, 0x98, 0xC5, 0x82,
+ 0x66, 0x4B, 0x4C, 0x0F, 0x6C, 0xC4, 0x16, 0x59
+};
+static const u8 dh_group24_prime[] = {
+ 0x87, 0xA8, 0xE6, 0x1D, 0xB4, 0xB6, 0x66, 0x3C,
+ 0xFF, 0xBB, 0xD1, 0x9C, 0x65, 0x19, 0x59, 0x99,
+ 0x8C, 0xEE, 0xF6, 0x08, 0x66, 0x0D, 0xD0, 0xF2,
+ 0x5D, 0x2C, 0xEE, 0xD4, 0x43, 0x5E, 0x3B, 0x00,
+ 0xE0, 0x0D, 0xF8, 0xF1, 0xD6, 0x19, 0x57, 0xD4,
+ 0xFA, 0xF7, 0xDF, 0x45, 0x61, 0xB2, 0xAA, 0x30,
+ 0x16, 0xC3, 0xD9, 0x11, 0x34, 0x09, 0x6F, 0xAA,
+ 0x3B, 0xF4, 0x29, 0x6D, 0x83, 0x0E, 0x9A, 0x7C,
+ 0x20, 0x9E, 0x0C, 0x64, 0x97, 0x51, 0x7A, 0xBD,
+ 0x5A, 0x8A, 0x9D, 0x30, 0x6B, 0xCF, 0x67, 0xED,
+ 0x91, 0xF9, 0xE6, 0x72, 0x5B, 0x47, 0x58, 0xC0,
+ 0x22, 0xE0, 0xB1, 0xEF, 0x42, 0x75, 0xBF, 0x7B,
+ 0x6C, 0x5B, 0xFC, 0x11, 0xD4, 0x5F, 0x90, 0x88,
+ 0xB9, 0x41, 0xF5, 0x4E, 0xB1, 0xE5, 0x9B, 0xB8,
+ 0xBC, 0x39, 0xA0, 0xBF, 0x12, 0x30, 0x7F, 0x5C,
+ 0x4F, 0xDB, 0x70, 0xC5, 0x81, 0xB2, 0x3F, 0x76,
+ 0xB6, 0x3A, 0xCA, 0xE1, 0xCA, 0xA6, 0xB7, 0x90,
+ 0x2D, 0x52, 0x52, 0x67, 0x35, 0x48, 0x8A, 0x0E,
+ 0xF1, 0x3C, 0x6D, 0x9A, 0x51, 0xBF, 0xA4, 0xAB,
+ 0x3A, 0xD8, 0x34, 0x77, 0x96, 0x52, 0x4D, 0x8E,
+ 0xF6, 0xA1, 0x67, 0xB5, 0xA4, 0x18, 0x25, 0xD9,
+ 0x67, 0xE1, 0x44, 0xE5, 0x14, 0x05, 0x64, 0x25,
+ 0x1C, 0xCA, 0xCB, 0x83, 0xE6, 0xB4, 0x86, 0xF6,
+ 0xB3, 0xCA, 0x3F, 0x79, 0x71, 0x50, 0x60, 0x26,
+ 0xC0, 0xB8, 0x57, 0xF6, 0x89, 0x96, 0x28, 0x56,
+ 0xDE, 0xD4, 0x01, 0x0A, 0xBD, 0x0B, 0xE6, 0x21,
+ 0xC3, 0xA3, 0x96, 0x0A, 0x54, 0xE7, 0x10, 0xC3,
+ 0x75, 0xF2, 0x63, 0x75, 0xD7, 0x01, 0x41, 0x03,
+ 0xA4, 0xB5, 0x43, 0x30, 0xC1, 0x98, 0xAF, 0x12,
+ 0x61, 0x16, 0xD2, 0x27, 0x6E, 0x11, 0x71, 0x5F,
+ 0x69, 0x38, 0x77, 0xFA, 0xD7, 0xEF, 0x09, 0xCA,
+ 0xDB, 0x09, 0x4A, 0xE9, 0x1E, 0x1A, 0x15, 0x97
+};
+static const u8 dh_group24_order[] = {
+ 0x8C, 0xF8, 0x36, 0x42, 0xA7, 0x09, 0xA0, 0x97,
+ 0xB4, 0x47, 0x99, 0x76, 0x40, 0x12, 0x9D, 0xA2,
+ 0x99, 0xB1, 0xA4, 0x7D, 0x1E, 0xB3, 0x75, 0x0B,
+ 0xA3, 0x08, 0xB0, 0xFE, 0x64, 0xF5, 0xFB, 0xD3
+};
#endif /* ALL_DH_GROUPS */
-#define DH_GROUP(id) \
+#define DH_GROUP(id,safe) \
{ id, dh_group ## id ## _generator, sizeof(dh_group ## id ## _generator), \
-dh_group ## id ## _prime, sizeof(dh_group ## id ## _prime) }
+dh_group ## id ## _prime, sizeof(dh_group ## id ## _prime), \
+dh_group ## id ## _order, sizeof(dh_group ## id ## _order), safe }
static struct dh_group dh_groups[] = {
- DH_GROUP(5),
+ DH_GROUP(5, 1),
#ifdef ALL_DH_GROUPS
- DH_GROUP(1),
- DH_GROUP(2),
- DH_GROUP(14),
- DH_GROUP(15),
- DH_GROUP(16),
- DH_GROUP(17),
- DH_GROUP(18)
+ DH_GROUP(1, 1),
+ DH_GROUP(2, 1),
+ DH_GROUP(14, 1),
+ DH_GROUP(15, 1),
+ DH_GROUP(16, 1),
+ DH_GROUP(17, 1),
+ DH_GROUP(18, 1),
+ DH_GROUP(22, 0),
+ DH_GROUP(23, 0),
+ DH_GROUP(24, 0)
#endif /* ALL_DH_GROUPS */
};
-#define NUM_DH_GROUPS (sizeof(dh_groups) / sizeof(dh_groups[0]))
+#define NUM_DH_GROUPS ARRAY_SIZE(dh_groups)
const struct dh_group * dh_groups_get(int id)
@@ -554,14 +1198,14 @@ struct wpabuf * dh_init(const struct dh_group *dh, struct wpabuf **priv)
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;
}
@@ -580,7 +1224,7 @@ struct wpabuf * dh_init(const struct dh_group *dh, struct wpabuf **priv)
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;
}
@@ -616,7 +1260,7 @@ struct wpabuf * dh_derive_shared(const struct wpabuf *peer_public,
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/dh_groups.h b/src/crypto/dh_groups.h
index 225f0067a17f9..d0e74b9206a80 100644
--- a/src/crypto/dh_groups.h
+++ b/src/crypto/dh_groups.h
@@ -15,6 +15,9 @@ struct dh_group {
size_t generator_len;
const u8 *prime;
size_t prime_len;
+ const u8 *order;
+ size_t order_len;
+ unsigned int safe_prime:1;
};
const struct dh_group * dh_groups_get(int id);
diff --git a/src/crypto/fips_prf_cryptoapi.c b/src/crypto/fips_prf_cryptoapi.c
deleted file mode 100644
index dca93a3d33660..0000000000000
--- a/src/crypto/fips_prf_cryptoapi.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * FIPS 186-2 PRF for Microsoft CryptoAPI
- * 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 "common.h"
-#include "crypto.h"
-
-
-int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
-{
- /* FIX: how to do this with CryptoAPI? */
- return -1;
-}
diff --git a/src/crypto/fips_prf_gnutls.c b/src/crypto/fips_prf_gnutls.c
deleted file mode 100644
index 947e6f6414628..0000000000000
--- a/src/crypto/fips_prf_gnutls.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * FIPS 186-2 PRF for libgcrypt
- * Copyright (c) 2004-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 <gcrypt.h>
-
-#include "common.h"
-#include "crypto.h"
-
-
-int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
-{
- /* FIX: how to do this with libgcrypt? */
- return -1;
-}
diff --git a/src/crypto/fips_prf_nss.c b/src/crypto/fips_prf_nss.c
deleted file mode 100644
index 2c962f4f1301f..0000000000000
--- a/src/crypto/fips_prf_nss.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * FIPS 186-2 PRF 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 <openssl/sha.h>
-
-#include "common.h"
-#include "crypto.h"
-
-
-int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
-{
- return -1;
-}
diff --git a/src/crypto/md5.c b/src/crypto/md5.c
index db2b8cc316bad..f64dfd3d43cd8 100644
--- a/src/crypto/md5.c
+++ b/src/crypto/md5.c
@@ -30,6 +30,7 @@ int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
u8 tk[16];
const u8 *_addr[6];
size_t i, _len[6];
+ int res;
if (num_elem > 5) {
/*
@@ -85,7 +86,10 @@ int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
_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/milenage.c b/src/crypto/milenage.c
index a7f9c6a286a89..6edea57e69e5d 100644
--- a/src/crypto/milenage.c
+++ b/src/crypto/milenage.c
@@ -217,7 +217,7 @@ int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts,
for (i = 0; i < 6; i++)
sqn[i] = auts[i] ^ ak[i];
if (milenage_f1(opc, k, _rand, sqn, amf, NULL, mac_s) ||
- memcmp(mac_s, auts + 6, 8) != 0)
+ os_memcmp_const(mac_s, auts + 6, 8) != 0)
return -1;
return 0;
}
@@ -312,7 +312,7 @@ int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand,
wpa_hexdump(MSG_DEBUG, "Milenage: MAC_A", mac_a, 8);
- if (os_memcmp(mac_a, autn + 8, 8) != 0) {
+ if (os_memcmp_const(mac_a, autn + 8, 8) != 0) {
wpa_printf(MSG_DEBUG, "Milenage: MAC mismatch");
wpa_hexdump(MSG_DEBUG, "Milenage: Received MAC_A",
autn + 8, 8);
diff --git a/src/crypto/ms_funcs.c b/src/crypto/ms_funcs.c
index b2bbab2b5c320..49a5c1c245d67 100644
--- a/src/crypto/ms_funcs.c
+++ b/src/crypto/ms_funcs.c
@@ -58,6 +58,7 @@ static int utf8_to_ucs2(const u8 *utf8_string, size_t utf8_string_len,
WPA_PUT_LE16(ucs2_buffer + j,
((c & 0xF) << 12) |
((c2 & 0x3F) << 6) | (c3 & 0x3F));
+ j += 2;
}
}
}
diff --git a/src/crypto/random.c b/src/crypto/random.c
index 053740e9bfea6..bc758aa572327 100644
--- a/src/crypto/random.c
+++ b/src/crypto/random.c
@@ -232,12 +232,8 @@ int random_pool_ready(void)
*/
fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
if (fd < 0) {
-#ifndef CONFIG_NO_STDOUT_DEBUG
- int error = errno;
- perror("open(/dev/random)");
wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s",
- strerror(error));
-#endif /* CONFIG_NO_STDOUT_DEBUG */
+ strerror(errno));
return -1;
}
@@ -417,12 +413,8 @@ void random_init(const char *entropy_file)
random_fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
if (random_fd < 0) {
-#ifndef CONFIG_NO_STDOUT_DEBUG
- int error = errno;
- perror("open(/dev/random)");
wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s",
- strerror(error));
-#endif /* CONFIG_NO_STDOUT_DEBUG */
+ strerror(errno));
return;
}
wpa_printf(MSG_DEBUG, "random: Trying to read entropy from "
diff --git a/src/crypto/sha1-internal.c b/src/crypto/sha1-internal.c
index 10bf153ca30e2..24bc3ffe1759b 100644
--- a/src/crypto/sha1-internal.c
+++ b/src/crypto/sha1-internal.c
@@ -19,6 +19,7 @@ typedef struct SHA1Context SHA1_CTX;
void SHA1Transform(u32 state[5], const unsigned char buffer[64]);
+#ifdef CONFIG_CRYPTO_INTERNAL
/**
* sha1_vector - SHA-1 hash for data vector
* @num_elem: Number of elements in the data vector
@@ -38,6 +39,7 @@ int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
SHA1Final(mac, &ctx);
return 0;
}
+#endif /* CONFIG_CRYPTO_INTERNAL */
/* ===== start - public domain SHA1 implementation ===== */
diff --git a/src/crypto/sha1-prf.c b/src/crypto/sha1-prf.c
index 90b9e74b745b1..4b2d1373067f8 100644
--- a/src/crypto/sha1-prf.c
+++ b/src/crypto/sha1-prf.c
@@ -61,6 +61,7 @@ int sha1_prf(const u8 *key, size_t key_len, const char *label,
}
counter++;
}
+ os_memset(hash, 0, sizeof(hash));
return 0;
}
diff --git a/src/crypto/sha1.c b/src/crypto/sha1.c
index d48c77d75c5f0..8fce139408f19 100644
--- a/src/crypto/sha1.c
+++ b/src/crypto/sha1.c
@@ -30,6 +30,7 @@ int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
unsigned char tk[20];
const u8 *_addr[6];
size_t _len[6], i;
+ int ret;
if (num_elem > 5) {
/*
@@ -84,7 +85,9 @@ int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
_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-kdf.c b/src/crypto/sha256-kdf.c
new file mode 100644
index 0000000000000..d8a1beb32e908
--- /dev/null
+++ b/src/crypto/sha256-kdf.c
@@ -0,0 +1,76 @@
+/*
+ * HMAC-SHA256 KDF (RFC 5295)
+ * Copyright (c) 2014, 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 "common.h"
+#include "sha256.h"
+
+
+/**
+ * hmac_sha256_kdf - HMAC-SHA256 based KDF (RFC 5295)
+ * @secret: Key for KDF
+ * @secret_len: Length of the key in bytes
+ * @label: A unique label for each purpose of the KDF
+ * @seed: Seed value to bind into the key
+ * @seed_len: Length of the seed
+ * @out: Buffer for the generated pseudo-random key
+ * @outlen: Number of bytes of key to generate
+ * Returns: 0 on success, -1 on failure.
+ *
+ * This function is used to derive new, cryptographically separate keys from a
+ * given key in ERP. This KDF is defined in RFC 5295, Chapter 3.1.2.
+ */
+int hmac_sha256_kdf(const u8 *secret, size_t secret_len,
+ const char *label, const u8 *seed, size_t seed_len,
+ u8 *out, size_t outlen)
+{
+ u8 T[SHA256_MAC_LEN];
+ u8 iter = 1;
+ const unsigned char *addr[4];
+ size_t len[4];
+ size_t pos, clen;
+
+ addr[0] = T;
+ len[0] = SHA256_MAC_LEN;
+ addr[1] = (const unsigned char *) label;
+ len[1] = os_strlen(label) + 1;
+ addr[2] = seed;
+ len[2] = seed_len;
+ addr[3] = &iter;
+ len[3] = 1;
+
+ if (hmac_sha256_vector(secret, secret_len, 3, &addr[1], &len[1], T) < 0)
+ return -1;
+
+ pos = 0;
+ for (;;) {
+ clen = outlen - pos;
+ if (clen > SHA256_MAC_LEN)
+ clen = SHA256_MAC_LEN;
+ os_memcpy(out + pos, T, clen);
+ pos += clen;
+
+ if (pos == outlen)
+ break;
+
+ if (iter == 255) {
+ os_memset(out, 0, outlen);
+ return -1;
+ }
+ iter++;
+
+ if (hmac_sha256_vector(secret, secret_len, 4, addr, len, T) < 0)
+ {
+ os_memset(out, 0, outlen);
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/crypto/sha256-prf.c b/src/crypto/sha256-prf.c
index 0da6d130a88e8..79791c06cf0bb 100644
--- a/src/crypto/sha256-prf.c
+++ b/src/crypto/sha256-prf.c
@@ -1,6 +1,6 @@
/*
* SHA256-based PRF (IEEE 802.11r)
- * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -29,12 +29,36 @@
void sha256_prf(const u8 *key, size_t key_len, const char *label,
const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
{
+ sha256_prf_bits(key, key_len, label, data, data_len, buf, buf_len * 8);
+}
+
+
+/**
+ * sha256_prf_bits - IEEE Std 802.11-2012, 11.6.1.7.2 Key derivation function
+ * @key: Key for KDF
+ * @key_len: Length of the key in bytes
+ * @label: A unique label for each purpose of the PRF
+ * @data: Extra data to bind into the key
+ * @data_len: Length of the data
+ * @buf: Buffer for the generated pseudo-random key
+ * @buf_len: Number of bits of key to generate
+ *
+ * This function is used to derive new, cryptographically separate keys from a
+ * given key. If the requested buf_len is not divisible by eight, the least
+ * significant 1-7 bits of the last octet in the output are not part of the
+ * requested output.
+ */
+void sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
+ const u8 *data, size_t data_len, u8 *buf,
+ size_t buf_len_bits)
+{
u16 counter = 1;
size_t pos, plen;
u8 hash[SHA256_MAC_LEN];
const u8 *addr[4];
size_t len[4];
u8 counter_le[2], length_le[2];
+ size_t buf_len = (buf_len_bits + 7) / 8;
addr[0] = counter_le;
len[0] = 2;
@@ -45,7 +69,7 @@ void sha256_prf(const u8 *key, size_t key_len, const char *label,
addr[3] = length_le;
len[3] = sizeof(length_le);
- WPA_PUT_LE16(length_le, buf_len * 8);
+ WPA_PUT_LE16(length_le, buf_len_bits);
pos = 0;
while (pos < buf_len) {
plen = buf_len - pos;
@@ -57,8 +81,20 @@ void sha256_prf(const u8 *key, size_t key_len, const char *label,
} else {
hmac_sha256_vector(key, key_len, 4, addr, len, hash);
os_memcpy(&buf[pos], hash, plen);
+ pos += plen;
break;
}
counter++;
}
+
+ /*
+ * Mask out unused bits in the last octet if it does not use all the
+ * bits.
+ */
+ if (buf_len_bits % 8) {
+ u8 mask = 0xff << (8 - buf_len_bits % 8);
+ buf[pos - 1] &= mask;
+ }
+
+ os_memset(hash, 0, sizeof(hash));
}
diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h
index fcac8004ca4f5..b15f51158f326 100644
--- a/src/crypto/sha256.h
+++ b/src/crypto/sha256.h
@@ -1,6 +1,6 @@
/*
* SHA256 hash implementation and interface functions
- * Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -17,8 +17,14 @@ int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
size_t data_len, u8 *mac);
void sha256_prf(const u8 *key, size_t key_len, const char *label,
const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
+void sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
+ const u8 *data, size_t data_len, u8 *buf,
+ size_t buf_len_bits);
void tls_prf_sha256(const u8 *secret, size_t secret_len,
const char *label, const u8 *seed, size_t seed_len,
u8 *out, size_t outlen);
+int hmac_sha256_kdf(const u8 *secret, size_t secret_len,
+ const char *label, const u8 *seed, size_t seed_len,
+ u8 *out, size_t outlen);
#endif /* SHA256_H */
diff --git a/src/crypto/sha384.h b/src/crypto/sha384.h
new file mode 100644
index 0000000000000..e6a1fe41e1a10
--- /dev/null
+++ b/src/crypto/sha384.h
@@ -0,0 +1,19 @@
+/*
+ * SHA384 hash implementation and interface functions
+ * Copyright (c) 2015, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef SHA384_H
+#define SHA384_H
+
+#define SHA384_MAC_LEN 48
+
+int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac);
+int hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
+ size_t data_len, u8 *mac);
+
+#endif /* SHA384_H */
diff --git a/src/crypto/tls.h b/src/crypto/tls.h
index b61e43939f879..9ae95a66c9ed6 100644
--- a/src/crypto/tls.h
+++ b/src/crypto/tls.h
@@ -1,6 +1,6 @@
/*
* SSL/TLS interface definition
- * Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -40,9 +40,14 @@ enum tls_fail_reason {
TLS_FAIL_SUBJECT_MISMATCH = 5,
TLS_FAIL_ALTSUBJECT_MISMATCH = 6,
TLS_FAIL_BAD_CERTIFICATE = 7,
- TLS_FAIL_SERVER_CHAIN_PROBE = 8
+ TLS_FAIL_SERVER_CHAIN_PROBE = 8,
+ TLS_FAIL_DOMAIN_SUFFIX_MISMATCH = 9,
+ TLS_FAIL_DOMAIN_MISMATCH = 10,
};
+
+#define TLS_MAX_ALT_SUBJECT 10
+
union tls_event_data {
struct {
int depth;
@@ -58,6 +63,8 @@ union tls_event_data {
const struct wpabuf *cert;
const u8 *hash;
size_t hash_len;
+ const char *altsubject[TLS_MAX_ALT_SUBJECT];
+ int num_altsubject;
} peer_cert;
struct {
@@ -73,6 +80,7 @@ struct tls_config {
const char *pkcs11_module_path;
int fips_mode;
int cert_in_cb;
+ const char *openssl_ciphers;
void (*event_cb)(void *ctx, enum tls_event ev,
union tls_event_data *data);
@@ -82,6 +90,11 @@ struct tls_config {
#define TLS_CONN_ALLOW_SIGN_RSA_MD5 BIT(0)
#define TLS_CONN_DISABLE_TIME_CHECKS BIT(1)
#define TLS_CONN_DISABLE_SESSION_TICKET BIT(2)
+#define TLS_CONN_REQUEST_OCSP BIT(3)
+#define TLS_CONN_REQUIRE_OCSP BIT(4)
+#define TLS_CONN_DISABLE_TLSv1_1 BIT(5)
+#define TLS_CONN_DISABLE_TLSv1_2 BIT(6)
+#define TLS_CONN_EAP_FAST BIT(7)
/**
* struct tls_connection_params - Parameters for TLS connection
@@ -94,6 +107,12 @@ struct tls_config {
* %NULL to allow all subjects
* @altsubject_match: String to match in the alternative subject of the peer
* certificate or %NULL to allow all alternative subjects
+ * @suffix_match: String to suffix match in the dNSName or CN of the peer
+ * certificate or %NULL to allow all domain names. This may allow subdomains an
+ * wildcard certificates. Each domain name label must have a full match.
+ * @domain_match: String to match in the dNSName or CN of the peer
+ * certificate or %NULL to allow all domain names. This requires a full,
+ * case-insensitive match.
* @client_cert: File or reference name for client X.509 certificate in PEM or
* DER format
* @client_cert_blob: client_cert as inlined data or %NULL if not used
@@ -116,7 +135,10 @@ struct tls_config {
* specific for now)
* @cert_id: the certificate's id when using engine
* @ca_cert_id: the CA certificate's id when using engine
+ * @openssl_ciphers: OpenSSL cipher configuration
* @flags: Parameter options (TLS_CONN_*)
+ * @ocsp_stapling_response: DER encoded file with cached OCSP stapling response
+ * or %NULL if OCSP is not enabled
*
* TLS connection parameters to be configured with tls_connection_set_params()
* and tls_global_set_params().
@@ -133,6 +155,8 @@ struct tls_connection_params {
const char *ca_path;
const char *subject_match;
const char *altsubject_match;
+ const char *suffix_match;
+ const char *domain_match;
const char *client_cert;
const u8 *client_cert_blob;
size_t client_cert_blob_len;
@@ -151,8 +175,10 @@ struct tls_connection_params {
const char *key_id;
const char *cert_id;
const char *ca_cert_id;
+ const char *openssl_ciphers;
unsigned int flags;
+ const char *ocsp_stapling_response;
};
@@ -526,4 +552,21 @@ int __must_check tls_connection_set_session_ticket_cb(
void *tls_ctx, struct tls_connection *conn,
tls_session_ticket_cb cb, void *ctx);
+void tls_connection_set_log_cb(struct tls_connection *conn,
+ void (*log_cb)(void *ctx, const char *msg),
+ void *ctx);
+
+#define TLS_BREAK_VERIFY_DATA BIT(0)
+#define TLS_BREAK_SRV_KEY_X_HASH BIT(1)
+#define TLS_BREAK_SRV_KEY_X_SIGNATURE BIT(2)
+#define TLS_DHE_PRIME_511B BIT(3)
+#define TLS_DHE_PRIME_767B BIT(4)
+#define TLS_DHE_PRIME_15 BIT(5)
+#define TLS_DHE_PRIME_58B BIT(6)
+#define TLS_DHE_NON_PRIME BIT(7)
+
+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 a5d72f407a8d2..65db6fcc25653 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 @@ struct tls_global {
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 {
- gnutls_session session;
- char *subject_match, *altsubject_match;
+ struct tls_global *global;
+ gnutls_session_t session;
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,16 @@ struct tls_connection {
int params_set;
gnutls_certificate_credentials_t xcred;
+
+ char *suffix_match;
+ char *domain_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;
@@ -125,23 +92,15 @@ static void tls_log_func(int level, const char *msg)
}
-extern int wpa_debug_show_keys;
-
void * tls_init(const struct tls_config *conf)
{
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)
@@ -153,28 +112,16 @@ void * tls_init(const struct tls_config *conf)
}
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;
}
@@ -201,7 +148,7 @@ int tls_get_errors(void *ssl_ctx)
}
-static ssize_t tls_pull_func(gnutls_transport_ptr ptr, void *buf,
+static ssize_t tls_pull_func(gnutls_transport_ptr_t ptr, void *buf,
size_t len)
{
struct tls_connection *conn = (struct tls_connection *) ptr;
@@ -230,7 +177,7 @@ static ssize_t tls_pull_func(gnutls_transport_ptr ptr, void *buf,
}
-static ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf,
+static ssize_t tls_push_func(gnutls_transport_ptr_t ptr, const void *buf,
size_t len)
{
struct tls_connection *conn = (struct tls_connection *) ptr;
@@ -248,12 +195,7 @@ static ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf,
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,
@@ -268,7 +210,6 @@ static int tls_gnutls_init_session(struct tls_global *global,
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) {
@@ -276,19 +217,11 @@ static int tls_gnutls_init_session(struct tls_global *global,
"'%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) conn);
+ gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr_t) conn);
+ gnutls_session_set_ptr(conn->session, conn);
return 0;
@@ -309,6 +242,7 @@ struct tls_connection * tls_connection_init(void *ssl_ctx)
conn = os_zalloc(sizeof(*conn));
if (conn == NULL)
return NULL;
+ conn->global = global;
if (tls_gnutls_init_session(global, conn)) {
os_free(conn);
@@ -344,10 +278,10 @@ void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
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->domain_match);
os_free(conn);
}
@@ -405,104 +339,6 @@ int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
}
-#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)
{
@@ -511,73 +347,142 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
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)
- return -1;
+ wpa_printf(MSG_INFO, "GnuTLS: subject_match not supported");
+ 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)
+ 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;
}
+#if GNUTLS_VERSION_NUMBER >= 0x030300
+ os_free(conn->domain_match);
+ conn->domain_match = NULL;
+ if (params->domain_match) {
+ conn->domain_match = os_strdup(params->domain_match);
+ if (conn->domain_match == NULL)
+ return -1;
+ }
+#else /* < 3.3.0 */
+ if (params->domain_match) {
+ wpa_printf(MSG_INFO, "GnuTLS: domain_match not supported");
+ return -1;
+ }
+#endif /* >= 3.3.0 */
+
+ 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) {
- /* TODO: private_key_passwd? */
+#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_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_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;
}
@@ -586,7 +491,6 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
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);
@@ -596,7 +500,6 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
return -1;
} else
pkcs12_ok = 1;
-#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
#endif /* PKCS12_FUNCS */
if (!pkcs12_ok) {
@@ -604,8 +507,82 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
"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,
@@ -643,17 +620,17 @@ int tls_global_set_params(void *tls_ctx,
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;
@@ -666,29 +643,27 @@ int tls_global_set_params(void *tls_ctx,
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;
}
@@ -697,7 +672,6 @@ int tls_global_set_params(void *tls_ctx,
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);
@@ -707,7 +681,6 @@ int tls_global_set_params(void *tls_ctx,
goto fail;
} else
pkcs12_ok = 1;
-#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
#endif /* PKCS12_FUNCS */
if (!pkcs12_ok) {
@@ -752,37 +725,23 @@ int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
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 */
}
@@ -790,86 +749,317 @@ 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 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 */
+}
+
+
+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;
-#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
+#else /* GnuTLS 3.1.3 or newer */
+ return 0;
+#endif /* GnuTLS 3.1.3 or newer */
}
-static int tls_connection_verify_peer(struct tls_connection *conn,
- gnutls_alert_description_t *err)
+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;
+
+ 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;
- if (gnutls_certificate_verify_peers2(conn->session, &status) < 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;
}
- 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;
+ 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);
+
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],
@@ -877,8 +1067,8 @@ static int tls_connection_verify_peer(struct tls_connection *conn,
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);
@@ -891,26 +1081,128 @@ static int tls_connection_verify_peer(struct tls_connection *conn,
wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
i + 1, num_certs, buf);
- if (i == 0) {
- /* TODO: validate subject_match and altsubject_match */
+ 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);
}
- os_free(buf);
+ if (i == 0) {
+ 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;
+ }
- if (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
- gnutls_x509_crt_get_activation_time(cert) > now.sec) {
+#if GNUTLS_VERSION_NUMBER >= 0x030300
+ if (conn->domain_match &&
+ !gnutls_x509_crt_check_hostname2(
+ cert, conn->domain_match,
+ GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) {
+ wpa_printf(MSG_WARNING,
+ "TLS: Domain match '%s' not found",
+ conn->domain_match);
+ gnutls_tls_fail_event(
+ conn, &certs[i], i, buf,
+ "Domain mismatch",
+ TLS_FAIL_DOMAIN_MISMATCH);
+ err = GNUTLS_A_BAD_CERTIFICATE;
+ gnutls_x509_crt_deinit(cert);
+ os_free(buf);
+ goto out;
+ }
+#endif /* >= 3.3.0 */
+
+ /* 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);
- *err = GNUTLS_A_CERTIFICATE_EXPIRED;
- return -1;
+ os_free(buf);
+ err = GNUTLS_A_CERTIFICATE_EXPIRED;
+ goto out;
}
+ os_free(buf);
+
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;
}
@@ -968,6 +1260,8 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
ret = gnutls_handshake(conn->session);
if (ret < 0) {
+ gnutls_alert_description_t alert;
+
switch (ret) {
case GNUTLS_E_AGAIN:
if (global->server && conn->established &&
@@ -978,10 +1272,20 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
}
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 "
@@ -990,18 +1294,21 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
}
} 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 */
- wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
conn->established = 1;
if (conn->push_buf == NULL) {
/* Need to return something to get final TLS ACK. */
@@ -1025,7 +1332,6 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
*appl_data = gnutls_get_appl_data(conn);
}
-out:
out_data = conn->push_buf;
conn->push_buf = NULL;
return out_data;
@@ -1190,3 +1496,10 @@ int tls_connection_set_session_ticket_cb(void *tls_ctx,
{
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 91f06900328a7..0c955da29f1d5 100644
--- a/src/crypto/tls_internal.c
+++ b/src/crypto/tls_internal.c
@@ -28,6 +28,7 @@ struct tls_global {
struct tls_connection {
struct tlsv1_client *client;
struct tlsv1_server *server;
+ struct tls_global *global;
};
@@ -85,6 +86,7 @@ struct tls_connection * tls_connection_init(void *tls_ctx)
conn = os_zalloc(sizeof(*conn));
if (conn == NULL)
return NULL;
+ conn->global = global;
#ifdef CONFIG_TLS_INTERNAL_CLIENT
if (!global->server) {
@@ -109,6 +111,28 @@ struct tls_connection * tls_connection_init(void *tls_ctx)
}
+#ifdef CONFIG_TESTING_OPTIONS
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+void tls_connection_set_test_flags(struct tls_connection *conn, u32 flags)
+{
+ if (conn->server)
+ tlsv1_server_set_test_flags(conn->server, flags);
+}
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
+#endif /* CONFIG_TESTING_OPTIONS */
+
+
+void tls_connection_set_log_cb(struct tls_connection *conn,
+ void (*log_cb)(void *ctx, const char *msg),
+ void *ctx)
+{
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+ if (conn->server)
+ tlsv1_server_set_log_cb(conn->server, log_cb, ctx);
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
+}
+
+
void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn)
{
if (conn == NULL)
@@ -166,6 +190,31 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
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->domain_match) {
+ wpa_printf(MSG_INFO, "TLS: domain_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)) {
@@ -628,3 +677,9 @@ int tls_connection_set_session_ticket_cb(void *tls_ctx,
#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 1a1092a184b51..a6d210afcf0f3 100644
--- a/src/crypto/tls_none.c
+++ b/src/crypto/tls_none.c
@@ -192,3 +192,9 @@ unsigned int tls_capabilities(void *tls_ctx)
{
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 c53c192a1cdea..0000000000000
--- 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 2c3db473258bc..52db8fc076ac9 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -1,6 +1,6 @@
/*
* SSL/TLS interface functions for OpenSSL
- * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -10,9 +10,11 @@
#ifndef CONFIG_SMARTCARD
#ifndef OPENSSL_NO_ENGINE
+#ifndef ANDROID
#define OPENSSL_NO_ENGINE
#endif
#endif
+#endif
#include <openssl/ssl.h>
#include <openssl/err.h>
@@ -22,51 +24,74 @@
#include <openssl/engine.h>
#endif /* OPENSSL_NO_ENGINE */
-#ifdef ANDROID
-#include <openssl/pem.h>
-#include "keystore_get.h"
-#endif /* ANDROID */
-
#include "common.h"
#include "crypto.h"
#include "tls.h"
-#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
-#define OPENSSL_d2i_TYPE const unsigned char **
-#else
-#define OPENSSL_d2i_TYPE unsigned char **
+#if defined(SSL_CTX_get_app_data) && defined(SSL_CTX_set_app_data)
+#define OPENSSL_SUPPORTS_CTX_APP_DATA
#endif
-#ifdef SSL_F_SSL_SET_SESSION_TICKET_EXT
-#ifdef SSL_OP_NO_TICKET
-/*
- * Session ticket override patch was merged into OpenSSL 0.9.9 tree on
- * 2008-11-15. This version uses a bit different API compared to the old patch.
- */
-#define CONFIG_OPENSSL_TICKET_OVERRIDE
+#if OPENSSL_VERSION_NUMBER < 0x10000000L
+/* ERR_remove_thread_state replaces ERR_remove_state and the latter is
+ * deprecated. However, OpenSSL 0.9.8 doesn't include
+ * ERR_remove_thread_state. */
+#define ERR_remove_thread_state(tid) ERR_remove_state(0)
#endif
+
+#if defined(OPENSSL_IS_BORINGSSL)
+/* stack_index_t is the return type of OpenSSL's sk_XXX_num() functions. */
+typedef size_t stack_index_t;
+#else
+typedef int stack_index_t;
#endif
+#ifdef SSL_set_tlsext_status_type
+#ifndef OPENSSL_NO_TLSEXT
+#define HAVE_OCSP
+#include <openssl/ocsp.h>
+#endif /* OPENSSL_NO_TLSEXT */
+#endif /* SSL_set_tlsext_status_type */
+
+#ifdef ANDROID
+#include <openssl/pem.h>
+#include <keystore/keystore_get.h>
+
+static BIO * BIO_from_keystore(const char *key)
+{
+ BIO *bio = NULL;
+ uint8_t *value = NULL;
+ int length = keystore_get(key, strlen(key), &value);
+ if (length != -1 && (bio = BIO_new(BIO_s_mem())) != NULL)
+ BIO_write(bio, value, length);
+ free(value);
+ return bio;
+}
+#endif /* ANDROID */
+
static int tls_openssl_ref_count = 0;
-struct tls_global {
+struct tls_context {
void (*event_cb)(void *ctx, enum tls_event ev,
union tls_event_data *data);
void *cb_ctx;
int cert_in_cb;
+ char *ocsp_stapling_response;
};
-static struct tls_global *tls_global = NULL;
+static struct tls_context *tls_global = NULL;
struct tls_connection {
+ struct tls_context *context;
+ SSL_CTX *ssl_ctx;
SSL *ssl;
BIO *ssl_in, *ssl_out;
#ifndef OPENSSL_NO_ENGINE
ENGINE *engine; /* functional reference to the engine */
EVP_PKEY *private_key; /* the private key if using engine */
#endif /* OPENSSL_NO_ENGINE */
- char *subject_match, *altsubject_match;
+ char *subject_match, *altsubject_match, *suffix_match, *domain_match;
int read_alerts, write_alerts, failed;
tls_session_ticket_cb session_ticket_cb;
@@ -79,13 +104,32 @@ struct tls_connection {
unsigned int ca_cert_verify:1;
unsigned int cert_probe:1;
unsigned int server_cert_only:1;
+ unsigned int invalid_hb_used:1;
u8 srv_cert_hash[32];
unsigned int flags;
+
+ X509 *peer_cert;
+ X509 *peer_issuer;
+ X509 *peer_issuer_issuer;
};
+static struct tls_context * tls_context_new(const struct tls_config *conf)
+{
+ struct tls_context *context = os_zalloc(sizeof(*context));
+ if (context == NULL)
+ return NULL;
+ if (conf) {
+ context->event_cb = conf->event_cb;
+ context->cb_ctx = conf->cb_ctx;
+ context->cert_in_cb = conf->cert_in_cb;
+ }
+ return context;
+}
+
+
#ifdef CONFIG_NO_STDOUT_DEBUG
static void _tls_show_errors(void)
@@ -351,7 +395,8 @@ static int tls_cryptoapi_cert(SSL *ssl, const char *name)
goto err;
}
- cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &priv->cert->pbCertEncoded,
+ cert = d2i_X509(NULL,
+ (const unsigned char **) &priv->cert->pbCertEncoded,
priv->cert->cbCertEncoded);
if (cert == NULL) {
wpa_printf(MSG_INFO, "CryptoAPI: Could not process X509 DER "
@@ -451,7 +496,8 @@ static int tls_cryptoapi_ca_cert(SSL_CTX *ssl_ctx, SSL *ssl, const char *name)
}
while ((ctx = CertEnumCertificatesInStore(cs, ctx))) {
- cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &ctx->pbCertEncoded,
+ cert = d2i_X509(NULL,
+ (const unsigned char **) &ctx->pbCertEncoded,
ctx->cbCertEncoded);
if (cert == NULL) {
wpa_printf(MSG_INFO, "CryptoAPI: Could not process "
@@ -511,6 +557,7 @@ static void ssl_info_cb(const SSL *ssl, int where, int ret)
wpa_printf(MSG_DEBUG, "SSL: %s:%s",
str, SSL_state_string_long(ssl));
} else if (where & SSL_CB_ALERT) {
+ struct tls_connection *conn = SSL_get_app_data((SSL *) ssl);
wpa_printf(MSG_INFO, "SSL: SSL3 alert: %s:%s:%s",
where & SSL_CB_READ ?
"read (remote end reported an error)" :
@@ -518,21 +565,19 @@ static void ssl_info_cb(const SSL *ssl, int where, int ret)
SSL_alert_type_string_long(ret),
SSL_alert_desc_string_long(ret));
if ((ret >> 8) == SSL3_AL_FATAL) {
- struct tls_connection *conn =
- SSL_get_app_data((SSL *) ssl);
if (where & SSL_CB_READ)
conn->read_alerts++;
else
conn->write_alerts++;
}
- if (tls_global->event_cb != NULL) {
+ if (conn->context->event_cb != NULL) {
union tls_event_data ev;
+ struct tls_context *context = conn->context;
os_memset(&ev, 0, sizeof(ev));
ev.alert.is_local = !(where & SSL_CB_READ);
ev.alert.type = SSL_alert_type_string_long(ret);
ev.alert.description = SSL_alert_desc_string_long(ret);
- tls_global->event_cb(tls_global->cb_ctx, TLS_ALERT,
- &ev);
+ context->event_cb(context->cb_ctx, TLS_ALERT, &ev);
}
} else if (where & SSL_CB_EXIT && ret <= 0) {
wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s",
@@ -644,12 +689,15 @@ static int tls_engine_load_dynamic_pkcs11(const char *pkcs11_so_path,
NULL, NULL
};
- if (!pkcs11_so_path || !pkcs11_module_path)
+ if (!pkcs11_so_path)
return 0;
pre_cmd[1] = pkcs11_so_path;
pre_cmd[3] = engine_id;
- post_cmd[1] = pkcs11_module_path;
+ if (pkcs11_module_path)
+ post_cmd[1] = pkcs11_module_path;
+ else
+ post_cmd[0] = NULL;
wpa_printf(MSG_DEBUG, "ENGINE: Loading pkcs11 Engine from %s",
pkcs11_so_path);
@@ -690,17 +738,13 @@ static int tls_engine_load_dynamic_opensc(const char *opensc_so_path)
void * tls_init(const struct tls_config *conf)
{
SSL_CTX *ssl;
+ struct tls_context *context;
+ const char *ciphers;
if (tls_openssl_ref_count == 0) {
- tls_global = os_zalloc(sizeof(*tls_global));
- if (tls_global == NULL)
+ tls_global = context = tls_context_new(conf);
+ if (context == NULL)
return NULL;
- if (conf) {
- tls_global->event_cb = conf->event_cb;
- tls_global->cb_ctx = conf->cb_ctx;
- tls_global->cert_in_cb = conf->cert_in_cb;
- }
-
#ifdef CONFIG_FIPS
#ifdef OPENSSL_FIPS
if (conf && conf->fips_mode) {
@@ -727,7 +771,7 @@ void * tls_init(const struct tls_config *conf)
#endif /* CONFIG_FIPS */
SSL_load_error_strings();
SSL_library_init();
-#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
+#ifndef OPENSSL_NO_SHA256
EVP_add_digest(EVP_sha256());
#endif /* OPENSSL_NO_SHA256 */
/* TODO: if /dev/urandom is available, PRNG is seeded
@@ -746,23 +790,48 @@ void * tls_init(const struct tls_config *conf)
#endif /* OPENSSL_NO_RC2 */
PKCS12_PBE_add();
#endif /* PKCS12_FUNCS */
+ } else {
+#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
+ /* Newer OpenSSL can store app-data per-SSL */
+ context = tls_context_new(conf);
+ if (context == NULL)
+ return NULL;
+#else /* OPENSSL_SUPPORTS_CTX_APP_DATA */
+ context = tls_global;
+#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
}
tls_openssl_ref_count++;
- ssl = SSL_CTX_new(TLSv1_method());
- if (ssl == NULL)
+ ssl = SSL_CTX_new(SSLv23_method());
+ if (ssl == NULL) {
+ tls_openssl_ref_count--;
+#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
+ if (context != tls_global)
+ os_free(context);
+#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
+ if (tls_openssl_ref_count == 0) {
+ os_free(tls_global);
+ tls_global = NULL;
+ }
return NULL;
+ }
+
+ SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv2);
+ SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv3);
SSL_CTX_set_info_callback(ssl, ssl_info_cb);
+#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
+ SSL_CTX_set_app_data(ssl, context);
+#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
#ifndef OPENSSL_NO_ENGINE
+ wpa_printf(MSG_DEBUG, "ENGINE: Loading dynamic engine");
+ ERR_load_ENGINE_strings();
+ ENGINE_load_dynamic();
+
if (conf &&
(conf->opensc_engine_path || conf->pkcs11_engine_path ||
conf->pkcs11_module_path)) {
- wpa_printf(MSG_DEBUG, "ENGINE: Loading dynamic engine");
- ERR_load_ENGINE_strings();
- ENGINE_load_dynamic();
-
if (tls_engine_load_dynamic_opensc(conf->opensc_engine_path) ||
tls_engine_load_dynamic_pkcs11(conf->pkcs11_engine_path,
conf->pkcs11_module_path)) {
@@ -772,6 +841,18 @@ void * tls_init(const struct tls_config *conf)
}
#endif /* OPENSSL_NO_ENGINE */
+ if (conf && conf->openssl_ciphers)
+ ciphers = conf->openssl_ciphers;
+ else
+ ciphers = "DEFAULT:!EXP:!LOW";
+ if (SSL_CTX_set_cipher_list(ssl, ciphers) != 1) {
+ wpa_printf(MSG_ERROR,
+ "OpenSSL: Failed to set cipher string '%s'",
+ ciphers);
+ tls_deinit(ssl);
+ return NULL;
+ }
+
return ssl;
}
@@ -779,6 +860,11 @@ void * tls_init(const struct tls_config *conf)
void tls_deinit(void *ssl_ctx)
{
SSL_CTX *ssl = ssl_ctx;
+#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
+ struct tls_context *context = SSL_CTX_get_app_data(ssl);
+ if (context != tls_global)
+ os_free(context);
+#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
SSL_CTX_free(ssl);
tls_openssl_ref_count--;
@@ -787,9 +873,11 @@ void tls_deinit(void *ssl_ctx)
ENGINE_cleanup();
#endif /* OPENSSL_NO_ENGINE */
CRYPTO_cleanup_all_ex_data();
- ERR_remove_state(0);
+ ERR_remove_thread_state(NULL);
ERR_free_strings();
EVP_cleanup();
+ os_free(tls_global->ocsp_stapling_response);
+ tls_global->ocsp_stapling_response = NULL;
os_free(tls_global);
tls_global = NULL;
}
@@ -806,16 +894,11 @@ static int tls_engine_init(struct tls_connection *conn, const char *engine_id,
wpa_printf(MSG_ERROR, "ENGINE: Engine ID not set");
return -1;
}
- if (pin == NULL) {
- wpa_printf(MSG_ERROR, "ENGINE: Smartcard PIN not set");
- return -1;
- }
- if (key_id == NULL) {
- wpa_printf(MSG_ERROR, "ENGINE: Key Id not set");
- return -1;
- }
ERR_clear_error();
+#ifdef ANDROID
+ ENGINE_load_dynamic();
+#endif
conn->engine = ENGINE_by_id(engine_id);
if (!conn->engine) {
wpa_printf(MSG_ERROR, "ENGINE: engine %s not available [%s]",
@@ -830,20 +913,35 @@ static int tls_engine_init(struct tls_connection *conn, const char *engine_id,
}
wpa_printf(MSG_DEBUG, "ENGINE: engine initialized");
- if (ENGINE_ctrl_cmd_string(conn->engine, "PIN", pin, 0) == 0) {
+#ifndef ANDROID
+ if (pin && ENGINE_ctrl_cmd_string(conn->engine, "PIN", pin, 0) == 0) {
wpa_printf(MSG_ERROR, "ENGINE: cannot set pin [%s]",
ERR_error_string(ERR_get_error(), NULL));
goto err;
}
- /* load private key first in-case PIN is required for cert */
- conn->private_key = ENGINE_load_private_key(conn->engine,
- key_id, NULL, NULL);
- if (!conn->private_key) {
- wpa_printf(MSG_ERROR, "ENGINE: cannot load private key with id"
- " '%s' [%s]", key_id,
- ERR_error_string(ERR_get_error(), NULL));
- ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
- goto err;
+#endif
+ if (key_id) {
+ /*
+ * Ensure that the ENGINE does not attempt to use the OpenSSL
+ * UI system to obtain a PIN, if we didn't provide one.
+ */
+ struct {
+ const void *password;
+ const char *prompt_info;
+ } key_cb = { "", NULL };
+
+ /* load private key first in-case PIN is required for cert */
+ conn->private_key = ENGINE_load_private_key(conn->engine,
+ key_id, NULL,
+ &key_cb);
+ if (!conn->private_key) {
+ wpa_printf(MSG_ERROR,
+ "ENGINE: cannot load private key with id '%s' [%s]",
+ key_id,
+ ERR_error_string(ERR_get_error(), NULL));
+ ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
+ goto err;
+ }
}
/* handle a certificate and/or CA certificate */
@@ -910,15 +1008,41 @@ int tls_get_errors(void *ssl_ctx)
return count;
}
+
+static void tls_msg_cb(int write_p, int version, int content_type,
+ const void *buf, size_t len, SSL *ssl, void *arg)
+{
+ struct tls_connection *conn = arg;
+ const u8 *pos = buf;
+
+ wpa_printf(MSG_DEBUG, "OpenSSL: %s ver=0x%x content_type=%d",
+ write_p ? "TX" : "RX", version, content_type);
+ wpa_hexdump_key(MSG_MSGDUMP, "OpenSSL: Message", buf, len);
+ if (content_type == 24 && len >= 3 && pos[0] == 1) {
+ size_t payload_len = WPA_GET_BE16(pos + 1);
+ if (payload_len + 3 > len) {
+ wpa_printf(MSG_ERROR, "OpenSSL: Heartbeat attack detected");
+ conn->invalid_hb_used = 1;
+ }
+ }
+}
+
+
struct tls_connection * tls_connection_init(void *ssl_ctx)
{
SSL_CTX *ssl = ssl_ctx;
struct tls_connection *conn;
long options;
+#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
+ struct tls_context *context = SSL_CTX_get_app_data(ssl);
+#else /* OPENSSL_SUPPORTS_CTX_APP_DATA */
+ struct tls_context *context = tls_global;
+#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
conn = os_zalloc(sizeof(*conn));
if (conn == NULL)
return NULL;
+ conn->ssl_ctx = ssl_ctx;
conn->ssl = SSL_new(ssl);
if (conn->ssl == NULL) {
tls_show_errors(MSG_INFO, __func__,
@@ -927,7 +1051,10 @@ struct tls_connection * tls_connection_init(void *ssl_ctx)
return NULL;
}
+ conn->context = context;
SSL_set_app_data(conn->ssl, conn);
+ SSL_set_msg_callback(conn->ssl, tls_msg_cb);
+ SSL_set_msg_callback_arg(conn->ssl, conn);
options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
SSL_OP_SINGLE_DH_USE;
#ifdef SSL_OP_NO_COMPRESSION
@@ -968,6 +1095,8 @@ void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
tls_engine_deinit(conn);
os_free(conn->subject_match);
os_free(conn->altsubject_match);
+ os_free(conn->suffix_match);
+ os_free(conn->domain_match);
os_free(conn->session_ticket);
os_free(conn);
}
@@ -998,7 +1127,8 @@ static int tls_match_altsubject_component(X509 *cert, int type,
{
GENERAL_NAME *gen;
void *ext;
- int i, found = 0;
+ int found = 0;
+ stack_index_t i;
ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
@@ -1058,6 +1188,112 @@ static int tls_match_altsubject(X509 *cert, const char *match)
}
+#ifndef CONFIG_NATIVE_WINDOWS
+static int domain_suffix_match(const u8 *val, size_t len, const char *match,
+ int full)
+{
+ size_t i, match_len;
+
+ /* Check for embedded nuls that could mess up suffix matching */
+ for (i = 0; i < len; i++) {
+ if (val[i] == '\0') {
+ wpa_printf(MSG_DEBUG, "TLS: Embedded null in a string - reject");
+ return 0;
+ }
+ }
+
+ match_len = os_strlen(match);
+ if (match_len > len || (full && match_len != len))
+ return 0;
+
+ if (os_strncasecmp((const char *) val + len - match_len, match,
+ match_len) != 0)
+ return 0; /* no match */
+
+ if (match_len == len)
+ return 1; /* exact match */
+
+ if (val[len - match_len - 1] == '.')
+ return 1; /* full label match completes suffix match */
+
+ wpa_printf(MSG_DEBUG, "TLS: Reject due to incomplete label match");
+ return 0;
+}
+#endif /* CONFIG_NATIVE_WINDOWS */
+
+
+static int tls_match_suffix(X509 *cert, const char *match, int full)
+{
+#ifdef CONFIG_NATIVE_WINDOWS
+ /* wincrypt.h has conflicting X509_NAME definition */
+ return -1;
+#else /* CONFIG_NATIVE_WINDOWS */
+ GENERAL_NAME *gen;
+ void *ext;
+ int i;
+ stack_index_t j;
+ int dns_name = 0;
+ X509_NAME *name;
+
+ wpa_printf(MSG_DEBUG, "TLS: Match domain against %s%s",
+ full ? "": "suffix ", match);
+
+ ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
+
+ for (j = 0; ext && j < sk_GENERAL_NAME_num(ext); j++) {
+ gen = sk_GENERAL_NAME_value(ext, j);
+ if (gen->type != GEN_DNS)
+ continue;
+ dns_name++;
+ wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate dNSName",
+ gen->d.dNSName->data,
+ gen->d.dNSName->length);
+ if (domain_suffix_match(gen->d.dNSName->data,
+ gen->d.dNSName->length, match, full) ==
+ 1) {
+ wpa_printf(MSG_DEBUG, "TLS: %s in dNSName found",
+ full ? "Match" : "Suffix match");
+ return 1;
+ }
+ }
+
+ if (dns_name) {
+ wpa_printf(MSG_DEBUG, "TLS: None of the dNSName(s) matched");
+ return 0;
+ }
+
+ name = X509_get_subject_name(cert);
+ i = -1;
+ for (;;) {
+ X509_NAME_ENTRY *e;
+ ASN1_STRING *cn;
+
+ i = X509_NAME_get_index_by_NID(name, NID_commonName, i);
+ if (i == -1)
+ break;
+ e = X509_NAME_get_entry(name, i);
+ if (e == NULL)
+ continue;
+ cn = X509_NAME_ENTRY_get_data(e);
+ if (cn == NULL)
+ continue;
+ wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate commonName",
+ cn->data, cn->length);
+ if (domain_suffix_match(cn->data, cn->length, match, full) == 1)
+ {
+ wpa_printf(MSG_DEBUG, "TLS: %s in commonName found",
+ full ? "Match" : "Suffix match");
+ return 1;
+ }
+ }
+
+ wpa_printf(MSG_DEBUG, "TLS: No CommonName %smatch found",
+ full ? "": "suffix ");
+ return 0;
+#endif /* CONFIG_NATIVE_WINDOWS */
+}
+
+
static enum tls_fail_reason openssl_tls_fail_reason(int err)
{
switch (err) {
@@ -1122,8 +1358,9 @@ static void openssl_tls_fail_event(struct tls_connection *conn,
{
union tls_event_data ev;
struct wpabuf *cert = NULL;
+ struct tls_context *context = conn->context;
- if (tls_global->event_cb == NULL)
+ if (context->event_cb == NULL)
return;
cert = get_x509_cert(err_cert);
@@ -1134,7 +1371,7 @@ static void openssl_tls_fail_event(struct tls_connection *conn,
ev.cert_fail.subject = subject;
ev.cert_fail.reason_txt = err_str;
ev.cert_fail.cert = cert;
- tls_global->event_cb(tls_global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
+ context->event_cb(context->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
wpabuf_free(cert);
}
@@ -1145,15 +1382,21 @@ static void openssl_tls_cert_event(struct tls_connection *conn,
{
struct wpabuf *cert = NULL;
union tls_event_data ev;
+ struct tls_context *context = conn->context;
+ char *altsubject[TLS_MAX_ALT_SUBJECT];
+ int alt, num_altsubject = 0;
+ GENERAL_NAME *gen;
+ void *ext;
+ stack_index_t i;
#ifdef CONFIG_SHA256
u8 hash[32];
#endif /* CONFIG_SHA256 */
- if (tls_global->event_cb == NULL)
+ if (context->event_cb == NULL)
return;
os_memset(&ev, 0, sizeof(ev));
- if (conn->cert_probe || tls_global->cert_in_cb) {
+ if (conn->cert_probe || context->cert_in_cb) {
cert = get_x509_cert(err_cert);
ev.peer_cert.cert = cert;
}
@@ -1171,8 +1414,52 @@ static void openssl_tls_cert_event(struct tls_connection *conn,
#endif /* CONFIG_SHA256 */
ev.peer_cert.depth = depth;
ev.peer_cert.subject = subject;
- tls_global->event_cb(tls_global->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
+
+ ext = X509_get_ext_d2i(err_cert, NID_subject_alt_name, NULL, NULL);
+ for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
+ char *pos;
+
+ if (num_altsubject == TLS_MAX_ALT_SUBJECT)
+ break;
+ gen = sk_GENERAL_NAME_value(ext, i);
+ if (gen->type != GEN_EMAIL &&
+ gen->type != GEN_DNS &&
+ gen->type != GEN_URI)
+ continue;
+
+ pos = os_malloc(10 + gen->d.ia5->length + 1);
+ if (pos == NULL)
+ break;
+ altsubject[num_altsubject++] = pos;
+
+ switch (gen->type) {
+ case GEN_EMAIL:
+ os_memcpy(pos, "EMAIL:", 6);
+ pos += 6;
+ break;
+ case GEN_DNS:
+ os_memcpy(pos, "DNS:", 4);
+ pos += 4;
+ break;
+ case GEN_URI:
+ os_memcpy(pos, "URI:", 4);
+ pos += 4;
+ break;
+ }
+
+ os_memcpy(pos, gen->d.ia5->data, gen->d.ia5->length);
+ pos += gen->d.ia5->length;
+ *pos = '\0';
+ }
+
+ for (alt = 0; alt < num_altsubject; alt++)
+ ev.peer_cert.altsubject[alt] = altsubject[alt];
+ ev.peer_cert.num_altsubject = num_altsubject;
+
+ context->event_cb(context->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
wpabuf_free(cert);
+ for (alt = 0; alt < num_altsubject; alt++)
+ os_free(altsubject[alt]);
}
@@ -1183,10 +1470,14 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
int err, depth;
SSL *ssl;
struct tls_connection *conn;
- char *match, *altmatch;
+ struct tls_context *context;
+ char *match, *altmatch, *suffix_match, *domain_match;
const char *err_str;
err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
+ if (!err_cert)
+ return 0;
+
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,
@@ -1196,8 +1487,19 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
conn = SSL_get_app_data(ssl);
if (conn == NULL)
return 0;
+
+ if (depth == 0)
+ conn->peer_cert = err_cert;
+ else if (depth == 1)
+ conn->peer_issuer = err_cert;
+ else if (depth == 2)
+ conn->peer_issuer_issuer = err_cert;
+
+ context = conn->context;
match = conn->subject_match;
altmatch = conn->altsubject_match;
+ suffix_match = conn->suffix_match;
+ domain_match = conn->domain_match;
if (!preverify_ok && !conn->ca_cert_verify)
preverify_ok = 1;
@@ -1214,7 +1516,11 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
err_str = X509_verify_cert_error_string(err);
#ifdef CONFIG_SHA256
- if (preverify_ok && depth == 0 && conn->server_cert_only) {
+ /*
+ * Do not require preverify_ok so we can explicity allow otherwise
+ * invalid pinned server certificates.
+ */
+ if (depth == 0 && conn->server_cert_only) {
struct wpabuf *cert;
cert = get_x509_cert(err_cert);
if (!cert) {
@@ -1232,6 +1538,14 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
err_str = "Server certificate mismatch";
err = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
preverify_ok = 0;
+ } else if (!preverify_ok) {
+ /*
+ * Certificate matches pinned certificate, allow
+ * regardless of other problems.
+ */
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: Ignore validation issues for a pinned server certificate");
+ preverify_ok = 1;
}
wpabuf_free(cert);
}
@@ -1266,6 +1580,22 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
openssl_tls_fail_event(conn, err_cert, err, depth, buf,
"AltSubject mismatch",
TLS_FAIL_ALTSUBJECT_MISMATCH);
+ } else if (depth == 0 && suffix_match &&
+ !tls_match_suffix(err_cert, suffix_match, 0)) {
+ wpa_printf(MSG_WARNING, "TLS: Domain suffix match '%s' not found",
+ suffix_match);
+ preverify_ok = 0;
+ openssl_tls_fail_event(conn, err_cert, err, depth, buf,
+ "Domain suffix mismatch",
+ TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
+ } else if (depth == 0 && domain_match &&
+ !tls_match_suffix(err_cert, domain_match, 1)) {
+ wpa_printf(MSG_WARNING, "TLS: Domain match '%s' not found",
+ domain_match);
+ preverify_ok = 0;
+ openssl_tls_fail_event(conn, err_cert, err, depth, buf,
+ "Domain mismatch",
+ TLS_FAIL_DOMAIN_MISMATCH);
} else
openssl_tls_cert_event(conn, err_cert, depth, buf);
@@ -1278,9 +1608,9 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
TLS_FAIL_SERVER_CHAIN_PROBE);
}
- if (preverify_ok && tls_global->event_cb != NULL)
- tls_global->event_cb(tls_global->cb_ctx,
- TLS_CERT_CHAIN_SUCCESS, NULL);
+ if (preverify_ok && context->event_cb != NULL)
+ context->event_cb(context->cb_ctx,
+ TLS_CERT_CHAIN_SUCCESS, NULL);
return preverify_ok;
}
@@ -1293,7 +1623,7 @@ static int tls_load_ca_der(void *_ssl_ctx, const char *ca_cert)
X509_LOOKUP *lookup;
int ret = 0;
- lookup = X509_STORE_add_lookup(ssl_ctx->cert_store,
+ lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(ssl_ctx),
X509_LOOKUP_file());
if (lookup == NULL) {
tls_show_errors(MSG_WARNING, __func__,
@@ -1319,36 +1649,24 @@ static int tls_load_ca_der(void *_ssl_ctx, const char *ca_cert)
#endif /* OPENSSL_NO_STDIO */
-#ifdef ANDROID
-static BIO * BIO_from_keystore(const char *key)
-{
- BIO *bio = NULL;
- char value[KEYSTORE_MESSAGE_SIZE];
- int length = keystore_get(key, strlen(key), value);
- if (length != -1 && (bio = BIO_new(BIO_s_mem())) != NULL)
- BIO_write(bio, value, length);
- return bio;
-}
-#endif /* ANDROID */
-
-
static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn,
const char *ca_cert, const u8 *ca_cert_blob,
size_t ca_cert_blob_len, const char *ca_path)
{
SSL_CTX *ssl_ctx = _ssl_ctx;
+ X509_STORE *store;
/*
* Remove previously configured trusted CA certificates before adding
* new ones.
*/
- X509_STORE_free(ssl_ctx->cert_store);
- ssl_ctx->cert_store = X509_STORE_new();
- if (ssl_ctx->cert_store == NULL) {
+ store = X509_STORE_new();
+ if (store == NULL) {
wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new "
"certificate store", __func__);
return -1;
}
+ SSL_CTX_set_cert_store(ssl_ctx, store);
SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
conn->ca_cert_verify = 1;
@@ -1392,7 +1710,8 @@ static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn,
}
if (ca_cert_blob) {
- X509 *cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &ca_cert_blob,
+ X509 *cert = d2i_X509(NULL,
+ (const unsigned char **) &ca_cert_blob,
ca_cert_blob_len);
if (cert == NULL) {
tls_show_errors(MSG_WARNING, __func__,
@@ -1400,7 +1719,8 @@ static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn,
return -1;
}
- if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) {
+ if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(ssl_ctx),
+ cert)) {
unsigned long err = ERR_peek_error();
tls_show_errors(MSG_WARNING, __func__,
"Failed to add ca_cert_blob to "
@@ -1426,7 +1746,7 @@ static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn,
if (ca_cert && os_strncmp("keystore://", ca_cert, 11) == 0) {
BIO *bio = BIO_from_keystore(&ca_cert[11]);
STACK_OF(X509_INFO) *stack = NULL;
- int i;
+ stack_index_t i;
if (bio) {
stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
@@ -1541,7 +1861,9 @@ int tls_global_set_verify(void *ssl_ctx, int check_crl)
static int tls_connection_set_subject_match(struct tls_connection *conn,
const char *subject_match,
- const char *altsubject_match)
+ const char *altsubject_match,
+ const char *suffix_match,
+ const char *domain_match)
{
os_free(conn->subject_match);
conn->subject_match = NULL;
@@ -1559,6 +1881,22 @@ static int tls_connection_set_subject_match(struct tls_connection *conn,
return -1;
}
+ os_free(conn->suffix_match);
+ conn->suffix_match = NULL;
+ if (suffix_match) {
+ conn->suffix_match = os_strdup(suffix_match);
+ if (conn->suffix_match == NULL)
+ return -1;
+ }
+
+ os_free(conn->domain_match);
+ conn->domain_match = NULL;
+ if (domain_match) {
+ conn->domain_match = os_strdup(domain_match);
+ if (conn->domain_match == NULL)
+ return -1;
+ }
+
return 0;
}
@@ -1813,7 +2151,7 @@ static int tls_read_pkcs12_blob(SSL_CTX *ssl_ctx, SSL *ssl,
#ifdef PKCS12_FUNCS
PKCS12 *p12;
- p12 = d2i_PKCS12(NULL, (OPENSSL_d2i_TYPE) &blob, len);
+ p12 = d2i_PKCS12(NULL, (const unsigned char **) &blob, len);
if (p12 == NULL) {
tls_show_errors(MSG_INFO, __func__,
"Failed to use PKCS#12 blob");
@@ -1894,20 +2232,21 @@ static int tls_connection_engine_ca_cert(void *_ssl_ctx,
#ifndef OPENSSL_NO_ENGINE
X509 *cert;
SSL_CTX *ssl_ctx = _ssl_ctx;
+ X509_STORE *store;
if (tls_engine_get_cert(conn, ca_cert_id, &cert))
return -1;
/* start off the same as tls_connection_ca_cert */
- X509_STORE_free(ssl_ctx->cert_store);
- ssl_ctx->cert_store = X509_STORE_new();
- if (ssl_ctx->cert_store == NULL) {
+ store = X509_STORE_new();
+ if (store == NULL) {
wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new "
"certificate store", __func__);
X509_free(cert);
return -1;
}
- if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) {
+ SSL_CTX_set_cert_store(ssl_ctx, store);
+ if (!X509_STORE_add_cert(store, cert)) {
unsigned long err = ERR_peek_error();
tls_show_errors(MSG_WARNING, __func__,
"Failed to add CA certificate from engine "
@@ -2022,26 +2361,6 @@ static int tls_connection_private_key(void *_ssl_ctx,
break;
}
-#ifdef ANDROID
- if (!ok && private_key &&
- os_strncmp("keystore://", private_key, 11) == 0) {
- BIO *bio = BIO_from_keystore(&private_key[11]);
- EVP_PKEY *pkey = NULL;
- if (bio) {
- pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
- BIO_free(bio);
- }
- if (pkey) {
- if (SSL_use_PrivateKey(conn->ssl, pkey) == 1) {
- wpa_printf(MSG_DEBUG, "OpenSSL: Private key "
- "from keystore");
- ok = 1;
- }
- EVP_PKEY_free(pkey);
- }
- }
-#endif /* ANDROID */
-
while (!ok && private_key) {
#ifndef OPENSSL_NO_STDIO
if (SSL_use_PrivateKey_file(conn->ssl, private_key,
@@ -2463,10 +2782,25 @@ openssl_connection_handshake(struct tls_connection *conn,
out_data = openssl_handshake(conn, in_data, server);
if (out_data == NULL)
return NULL;
+ if (conn->invalid_hb_used) {
+ wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response");
+ wpabuf_free(out_data);
+ return NULL;
+ }
if (SSL_is_init_finished(conn->ssl) && appl_data && in_data)
*appl_data = openssl_get_appl_data(conn, wpabuf_len(in_data));
+ if (conn->invalid_hb_used) {
+ wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response");
+ if (appl_data) {
+ wpabuf_free(*appl_data);
+ *appl_data = NULL;
+ }
+ wpabuf_free(out_data);
+ return NULL;
+ }
+
return out_data;
}
@@ -2568,13 +2902,23 @@ struct wpabuf * tls_connection_decrypt(void *tls_ctx,
}
wpabuf_put(buf, res);
+ if (conn->invalid_hb_used) {
+ wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response");
+ wpabuf_free(buf);
+ return NULL;
+ }
+
return buf;
}
int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
{
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ return conn ? SSL_cache_hit(conn->ssl) : 0;
+#else
return conn ? conn->ssl->hit : 0;
+#endif
}
@@ -2615,7 +2959,7 @@ int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
return -1;
}
ret = os_snprintf(pos, end - pos, ":%s", suite);
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
break;
pos += ret;
@@ -2670,15 +3014,9 @@ int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
if (conn == NULL || conn->ssl == NULL || ext_type != 35)
return -1;
-#ifdef CONFIG_OPENSSL_TICKET_OVERRIDE
if (SSL_set_session_ticket_ext(conn->ssl, (void *) data,
data_len) != 1)
return -1;
-#else /* CONFIG_OPENSSL_TICKET_OVERRIDE */
- if (SSL_set_hello_extension(conn->ssl, ext_type, (void *) data,
- data_len) != 1)
- return -1;
-#endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */
return 0;
}
@@ -2709,36 +3047,332 @@ int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
}
+#ifdef HAVE_OCSP
+
+static void ocsp_debug_print_resp(OCSP_RESPONSE *rsp)
+{
+#ifndef CONFIG_NO_STDOUT_DEBUG
+ BIO *out;
+ size_t rlen;
+ char *txt;
+ int res;
+
+ if (wpa_debug_level > MSG_DEBUG)
+ return;
+
+ out = BIO_new(BIO_s_mem());
+ if (!out)
+ return;
+
+ OCSP_RESPONSE_print(out, rsp, 0);
+ rlen = BIO_ctrl_pending(out);
+ txt = os_malloc(rlen + 1);
+ if (!txt) {
+ BIO_free(out);
+ return;
+ }
+
+ res = BIO_read(out, txt, rlen);
+ if (res > 0) {
+ txt[res] = '\0';
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP Response\n%s", txt);
+ }
+ os_free(txt);
+ BIO_free(out);
+#endif /* CONFIG_NO_STDOUT_DEBUG */
+}
+
+
+static void debug_print_cert(X509 *cert, const char *title)
+{
+#ifndef CONFIG_NO_STDOUT_DEBUG
+ BIO *out;
+ size_t rlen;
+ char *txt;
+ int res;
+
+ if (wpa_debug_level > MSG_DEBUG)
+ return;
+
+ out = BIO_new(BIO_s_mem());
+ if (!out)
+ return;
+
+ X509_print(out, cert);
+ rlen = BIO_ctrl_pending(out);
+ txt = os_malloc(rlen + 1);
+ if (!txt) {
+ BIO_free(out);
+ return;
+ }
+
+ res = BIO_read(out, txt, rlen);
+ if (res > 0) {
+ txt[res] = '\0';
+ wpa_printf(MSG_DEBUG, "OpenSSL: %s\n%s", title, txt);
+ }
+ os_free(txt);
+
+ BIO_free(out);
+#endif /* CONFIG_NO_STDOUT_DEBUG */
+}
+
+
+static int ocsp_resp_cb(SSL *s, void *arg)
+{
+ struct tls_connection *conn = arg;
+ const unsigned char *p;
+ int len, status, reason;
+ OCSP_RESPONSE *rsp;
+ OCSP_BASICRESP *basic;
+ OCSP_CERTID *id;
+ ASN1_GENERALIZEDTIME *produced_at, *this_update, *next_update;
+ X509_STORE *store;
+ STACK_OF(X509) *certs = NULL;
+
+ len = SSL_get_tlsext_status_ocsp_resp(s, &p);
+ if (!p) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: No OCSP response received");
+ return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1;
+ }
+
+ wpa_hexdump(MSG_DEBUG, "OpenSSL: OCSP response", p, len);
+
+ rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
+ if (!rsp) {
+ wpa_printf(MSG_INFO, "OpenSSL: Failed to parse OCSP response");
+ return 0;
+ }
+
+ ocsp_debug_print_resp(rsp);
+
+ status = OCSP_response_status(rsp);
+ if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
+ wpa_printf(MSG_INFO, "OpenSSL: OCSP responder error %d (%s)",
+ status, OCSP_response_status_str(status));
+ return 0;
+ }
+
+ basic = OCSP_response_get1_basic(rsp);
+ if (!basic) {
+ wpa_printf(MSG_INFO, "OpenSSL: Could not find BasicOCSPResponse");
+ return 0;
+ }
+
+ store = SSL_CTX_get_cert_store(conn->ssl_ctx);
+ if (conn->peer_issuer) {
+ debug_print_cert(conn->peer_issuer, "Add OCSP issuer");
+
+ if (X509_STORE_add_cert(store, conn->peer_issuer) != 1) {
+ tls_show_errors(MSG_INFO, __func__,
+ "OpenSSL: Could not add issuer to certificate store");
+ }
+ certs = sk_X509_new_null();
+ if (certs) {
+ X509 *cert;
+ cert = X509_dup(conn->peer_issuer);
+ if (cert && !sk_X509_push(certs, cert)) {
+ tls_show_errors(
+ MSG_INFO, __func__,
+ "OpenSSL: Could not add issuer to OCSP responder trust store");
+ X509_free(cert);
+ sk_X509_free(certs);
+ certs = NULL;
+ }
+ if (certs && conn->peer_issuer_issuer) {
+ cert = X509_dup(conn->peer_issuer_issuer);
+ if (cert && !sk_X509_push(certs, cert)) {
+ tls_show_errors(
+ MSG_INFO, __func__,
+ "OpenSSL: Could not add issuer's issuer to OCSP responder trust store");
+ X509_free(cert);
+ }
+ }
+ }
+ }
+
+ status = OCSP_basic_verify(basic, certs, store, OCSP_TRUSTOTHER);
+ sk_X509_pop_free(certs, X509_free);
+ if (status <= 0) {
+ tls_show_errors(MSG_INFO, __func__,
+ "OpenSSL: OCSP response failed verification");
+ OCSP_BASICRESP_free(basic);
+ OCSP_RESPONSE_free(rsp);
+ return 0;
+ }
+
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP response verification succeeded");
+
+ if (!conn->peer_cert) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: Peer certificate not available for OCSP status check");
+ OCSP_BASICRESP_free(basic);
+ OCSP_RESPONSE_free(rsp);
+ return 0;
+ }
+
+ if (!conn->peer_issuer) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: Peer issuer certificate not available for OCSP status check");
+ OCSP_BASICRESP_free(basic);
+ OCSP_RESPONSE_free(rsp);
+ return 0;
+ }
+
+ id = OCSP_cert_to_id(NULL, conn->peer_cert, conn->peer_issuer);
+ if (!id) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: Could not create OCSP certificate identifier");
+ OCSP_BASICRESP_free(basic);
+ OCSP_RESPONSE_free(rsp);
+ return 0;
+ }
+
+ if (!OCSP_resp_find_status(basic, id, &status, &reason, &produced_at,
+ &this_update, &next_update)) {
+ wpa_printf(MSG_INFO, "OpenSSL: Could not find current server certificate from OCSP response%s",
+ (conn->flags & TLS_CONN_REQUIRE_OCSP) ? "" :
+ " (OCSP not required)");
+ OCSP_BASICRESP_free(basic);
+ OCSP_RESPONSE_free(rsp);
+ return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1;
+ }
+
+ if (!OCSP_check_validity(this_update, next_update, 5 * 60, -1)) {
+ tls_show_errors(MSG_INFO, __func__,
+ "OpenSSL: OCSP status times invalid");
+ OCSP_BASICRESP_free(basic);
+ OCSP_RESPONSE_free(rsp);
+ return 0;
+ }
+
+ OCSP_BASICRESP_free(basic);
+ OCSP_RESPONSE_free(rsp);
+
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status for server certificate: %s",
+ OCSP_cert_status_str(status));
+
+ if (status == V_OCSP_CERTSTATUS_GOOD)
+ return 1;
+ if (status == V_OCSP_CERTSTATUS_REVOKED)
+ return 0;
+ if (conn->flags & TLS_CONN_REQUIRE_OCSP) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP required");
+ return 0;
+ }
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP was not required, so allow connection to continue");
+ return 1;
+}
+
+
+static int ocsp_status_cb(SSL *s, void *arg)
+{
+ char *tmp;
+ char *resp;
+ size_t len;
+
+ if (tls_global->ocsp_stapling_response == NULL) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - no response configured");
+ return SSL_TLSEXT_ERR_OK;
+ }
+
+ resp = os_readfile(tls_global->ocsp_stapling_response, &len);
+ if (resp == NULL) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - could not read response file");
+ /* TODO: Build OCSPResponse with responseStatus = internalError
+ */
+ return SSL_TLSEXT_ERR_OK;
+ }
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - send cached response");
+ tmp = OPENSSL_malloc(len);
+ if (tmp == NULL) {
+ os_free(resp);
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
+ }
+
+ os_memcpy(tmp, resp, len);
+ os_free(resp);
+ SSL_set_tlsext_status_ocsp_resp(s, tmp, len);
+
+ return SSL_TLSEXT_ERR_OK;
+}
+
+#endif /* HAVE_OCSP */
+
+
int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
const struct tls_connection_params *params)
{
int ret;
unsigned long err;
+ int can_pkcs11 = 0;
+ const char *key_id = params->key_id;
+ const char *cert_id = params->cert_id;
+ const char *ca_cert_id = params->ca_cert_id;
+ const char *engine_id = params->engine ? params->engine_id : NULL;
if (conn == NULL)
return -1;
+ /*
+ * If the engine isn't explicitly configured, and any of the
+ * cert/key fields are actually PKCS#11 URIs, then automatically
+ * use the PKCS#11 ENGINE.
+ */
+ if (!engine_id || os_strcmp(engine_id, "pkcs11") == 0)
+ can_pkcs11 = 1;
+
+ if (!key_id && params->private_key && can_pkcs11 &&
+ os_strncmp(params->private_key, "pkcs11:", 7) == 0) {
+ can_pkcs11 = 2;
+ key_id = params->private_key;
+ }
+
+ if (!cert_id && params->client_cert && can_pkcs11 &&
+ os_strncmp(params->client_cert, "pkcs11:", 7) == 0) {
+ can_pkcs11 = 2;
+ cert_id = params->client_cert;
+ }
+
+ if (!ca_cert_id && params->ca_cert && can_pkcs11 &&
+ os_strncmp(params->ca_cert, "pkcs11:", 7) == 0) {
+ can_pkcs11 = 2;
+ ca_cert_id = params->ca_cert;
+ }
+
+ /* If we need to automatically enable the PKCS#11 ENGINE, do so. */
+ if (can_pkcs11 == 2 && !engine_id)
+ engine_id = "pkcs11";
+
+ if (params->flags & TLS_CONN_EAP_FAST) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: Use TLSv1_method() for EAP-FAST");
+ if (SSL_set_ssl_method(conn->ssl, TLSv1_method()) != 1) {
+ tls_show_errors(MSG_INFO, __func__,
+ "Failed to set TLSv1_method() for EAP-FAST");
+ return -1;
+ }
+ }
+
while ((err = ERR_get_error())) {
wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s",
__func__, ERR_error_string(err, NULL));
}
- if (params->engine) {
+ if (engine_id) {
wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine");
- ret = tls_engine_init(conn, params->engine_id, params->pin,
- params->key_id, params->cert_id,
- params->ca_cert_id);
+ ret = tls_engine_init(conn, engine_id, params->pin,
+ key_id, cert_id, ca_cert_id);
if (ret)
return ret;
}
if (tls_connection_set_subject_match(conn,
params->subject_match,
- params->altsubject_match))
+ params->altsubject_match,
+ params->suffix_match,
+ params->domain_match))
return -1;
- if (params->engine && params->ca_cert_id) {
+ if (engine_id && ca_cert_id) {
if (tls_connection_engine_ca_cert(tls_ctx, conn,
- params->ca_cert_id))
+ ca_cert_id))
return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
} else if (tls_connection_ca_cert(tls_ctx, conn, params->ca_cert,
params->ca_cert_blob,
@@ -2746,15 +3380,15 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
params->ca_path))
return -1;
- if (params->engine && params->cert_id) {
- if (tls_connection_engine_client_cert(conn, params->cert_id))
+ if (engine_id && cert_id) {
+ if (tls_connection_engine_client_cert(conn, cert_id))
return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
} else if (tls_connection_client_cert(conn, params->client_cert,
params->client_cert_blob,
params->client_cert_blob_len))
return -1;
- if (params->engine && params->key_id) {
+ if (engine_id && key_id) {
wpa_printf(MSG_DEBUG, "TLS: Using private key from engine");
if (tls_connection_engine_private_key(conn))
return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
@@ -2774,13 +3408,45 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
return -1;
}
+ if (params->openssl_ciphers &&
+ SSL_set_cipher_list(conn->ssl, params->openssl_ciphers) != 1) {
+ wpa_printf(MSG_INFO,
+ "OpenSSL: Failed to set cipher string '%s'",
+ params->openssl_ciphers);
+ return -1;
+ }
+
#ifdef SSL_OP_NO_TICKET
if (params->flags & TLS_CONN_DISABLE_SESSION_TICKET)
SSL_set_options(conn->ssl, SSL_OP_NO_TICKET);
+#ifdef SSL_clear_options
else
SSL_clear_options(conn->ssl, SSL_OP_NO_TICKET);
+#endif /* SSL_clear_options */
#endif /* SSL_OP_NO_TICKET */
+#ifdef SSL_OP_NO_TLSv1_1
+ if (params->flags & TLS_CONN_DISABLE_TLSv1_1)
+ SSL_set_options(conn->ssl, SSL_OP_NO_TLSv1_1);
+ else
+ SSL_clear_options(conn->ssl, SSL_OP_NO_TLSv1_1);
+#endif /* SSL_OP_NO_TLSv1_1 */
+#ifdef SSL_OP_NO_TLSv1_2
+ if (params->flags & TLS_CONN_DISABLE_TLSv1_2)
+ SSL_set_options(conn->ssl, SSL_OP_NO_TLSv1_2);
+ else
+ SSL_clear_options(conn->ssl, SSL_OP_NO_TLSv1_2);
+#endif /* SSL_OP_NO_TLSv1_2 */
+
+#ifdef HAVE_OCSP
+ if (params->flags & TLS_CONN_REQUEST_OCSP) {
+ SSL_CTX *ssl_ctx = tls_ctx;
+ SSL_set_tlsext_status_type(conn->ssl, TLSEXT_STATUSTYPE_ocsp);
+ SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_resp_cb);
+ SSL_CTX_set_tlsext_status_arg(ssl_ctx, conn);
+ }
+#endif /* HAVE_OCSP */
+
conn->flags = params->flags;
tls_get_errors(tls_ctx);
@@ -2816,13 +3482,34 @@ int tls_global_set_params(void *tls_ctx,
return -1;
}
+ if (params->openssl_ciphers &&
+ SSL_CTX_set_cipher_list(ssl_ctx, params->openssl_ciphers) != 1) {
+ wpa_printf(MSG_INFO,
+ "OpenSSL: Failed to set cipher string '%s'",
+ params->openssl_ciphers);
+ return -1;
+ }
+
#ifdef SSL_OP_NO_TICKET
if (params->flags & TLS_CONN_DISABLE_SESSION_TICKET)
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TICKET);
+#ifdef SSL_CTX_clear_options
else
SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TICKET);
+#endif /* SSL_clear_options */
#endif /* SSL_OP_NO_TICKET */
+#ifdef HAVE_OCSP
+ SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_status_cb);
+ SSL_CTX_set_tlsext_status_arg(ssl_ctx, ssl_ctx);
+ os_free(tls_global->ocsp_stapling_response);
+ if (params->ocsp_stapling_response)
+ tls_global->ocsp_stapling_response =
+ os_strdup(params->ocsp_stapling_response);
+ else
+ tls_global->ocsp_stapling_response = NULL;
+#endif /* HAVE_OCSP */
+
return 0;
}
@@ -2875,9 +3562,15 @@ unsigned int tls_capabilities(void *tls_ctx)
* commented out unless explicitly needed for EAP-FAST in order to be able to
* build this file with unmodified openssl. */
+#ifdef OPENSSL_IS_BORINGSSL
+static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
+ STACK_OF(SSL_CIPHER) *peer_ciphers,
+ const SSL_CIPHER **cipher, void *arg)
+#else /* OPENSSL_IS_BORINGSSL */
static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
STACK_OF(SSL_CIPHER) *peer_ciphers,
SSL_CIPHER **cipher, void *arg)
+#endif /* OPENSSL_IS_BORINGSSL */
{
struct tls_connection *conn = arg;
int ret;
@@ -2901,7 +3594,6 @@ static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
}
-#ifdef CONFIG_OPENSSL_TICKET_OVERRIDE
static int tls_session_ticket_ext_cb(SSL *s, const unsigned char *data,
int len, void *arg)
{
@@ -2927,62 +3619,6 @@ static int tls_session_ticket_ext_cb(SSL *s, const unsigned char *data,
return 1;
}
-#else /* CONFIG_OPENSSL_TICKET_OVERRIDE */
-#ifdef SSL_OP_NO_TICKET
-static void tls_hello_ext_cb(SSL *s, int client_server, int type,
- unsigned char *data, int len, void *arg)
-{
- struct tls_connection *conn = arg;
-
- if (conn == NULL || conn->session_ticket_cb == NULL)
- return;
-
- wpa_printf(MSG_DEBUG, "OpenSSL: %s: type=%d length=%d", __func__,
- type, len);
-
- if (type == TLSEXT_TYPE_session_ticket && !client_server) {
- os_free(conn->session_ticket);
- conn->session_ticket = NULL;
-
- wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket "
- "extension", data, len);
- conn->session_ticket = os_malloc(len);
- if (conn->session_ticket == NULL)
- return;
-
- os_memcpy(conn->session_ticket, data, len);
- conn->session_ticket_len = len;
- }
-}
-#else /* SSL_OP_NO_TICKET */
-static int tls_hello_ext_cb(SSL *s, TLS_EXTENSION *ext, void *arg)
-{
- struct tls_connection *conn = arg;
-
- if (conn == NULL || conn->session_ticket_cb == NULL)
- return 0;
-
- wpa_printf(MSG_DEBUG, "OpenSSL: %s: type=%d length=%d", __func__,
- ext->type, ext->length);
-
- os_free(conn->session_ticket);
- conn->session_ticket = NULL;
-
- if (ext->type == 35) {
- wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket "
- "extension", ext->data, ext->length);
- conn->session_ticket = os_malloc(ext->length);
- if (conn->session_ticket == NULL)
- return SSL_AD_INTERNAL_ERROR;
-
- os_memcpy(conn->session_ticket, ext->data, ext->length);
- conn->session_ticket_len = ext->length;
- }
-
- return 0;
-}
-#endif /* SSL_OP_NO_TICKET */
-#endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */
#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
@@ -2999,33 +3635,12 @@ int tls_connection_set_session_ticket_cb(void *tls_ctx,
if (SSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb,
conn) != 1)
return -1;
-#ifdef CONFIG_OPENSSL_TICKET_OVERRIDE
SSL_set_session_ticket_ext_cb(conn->ssl,
tls_session_ticket_ext_cb, conn);
-#else /* CONFIG_OPENSSL_TICKET_OVERRIDE */
-#ifdef SSL_OP_NO_TICKET
- SSL_set_tlsext_debug_callback(conn->ssl, tls_hello_ext_cb);
- SSL_set_tlsext_debug_arg(conn->ssl, conn);
-#else /* SSL_OP_NO_TICKET */
- if (SSL_set_hello_extension_cb(conn->ssl, tls_hello_ext_cb,
- conn) != 1)
- return -1;
-#endif /* SSL_OP_NO_TICKET */
-#endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */
} else {
if (SSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1)
return -1;
-#ifdef CONFIG_OPENSSL_TICKET_OVERRIDE
SSL_set_session_ticket_ext_cb(conn->ssl, NULL, NULL);
-#else /* CONFIG_OPENSSL_TICKET_OVERRIDE */
-#ifdef SSL_OP_NO_TICKET
- SSL_set_tlsext_debug_callback(conn->ssl, NULL);
- SSL_set_tlsext_debug_arg(conn->ssl, conn);
-#else /* SSL_OP_NO_TICKET */
- if (SSL_set_hello_extension_cb(conn->ssl, NULL, NULL) != 1)
- return -1;
-#endif /* SSL_OP_NO_TICKET */
-#endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */
}
return 0;
@@ -3033,3 +3648,11 @@ int tls_connection_set_session_ticket_cb(void *tls_ctx,
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 2c2daa8a804b7..31a2c946d0478 100644
--- a/src/crypto/tls_schannel.c
+++ b/src/crypto/tls_schannel.c
@@ -692,6 +692,31 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
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->domain_match) {
+ wpa_printf(MSG_INFO, "TLS: domain_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 +755,9 @@ unsigned int tls_capabilities(void *tls_ctx)
{
return 0;
}
+
+
+int tls_get_library_version(char *buf, size_t buf_len)
+{
+ return os_snprintf(buf, buf_len, "schannel");
+}