[wpa_supplicant] Cumulative patch from b8491ae5a
Also revert local solution for encrypted IMSI and use the upstream version.
Bug: 134177972
Test: Device boots up and connects to WPA3/OWE wifi networks, run traffic.
Test: Able to turn on/off softap, associate wifi STA, run traffic.
Test: Regression test passed (Bug: 137653009)
Change-Id: Ie34a0138a3a2039b03101c788b43acbb33f8332a
diff --git a/src/crypto/aes_i.h b/src/crypto/aes_i.h
index 54375cf..b20ec92 100644
--- a/src/crypto/aes_i.h
+++ b/src/crypto/aes_i.h
@@ -65,7 +65,7 @@
#else /* AES_SMALL_TABLES */
-#define RCON(i) (rcons[(i)] << 24)
+#define RCON(i) ((u32) rcons[(i)] << 24)
static inline u32 rotr(u32 val, int bits)
{
@@ -94,10 +94,10 @@
#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8)
#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16)
#define TD3(i) rotr(Td0[(i) & 0xff], 24)
-#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24)
-#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16)
-#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8)
-#define TD44(i) (Td4s[(i) & 0xff])
+#define TD41(i) ((u32) Td4s[((i) >> 24) & 0xff] << 24)
+#define TD42(i) ((u32) Td4s[((i) >> 16) & 0xff] << 16)
+#define TD43(i) ((u32) Td4s[((i) >> 8) & 0xff] << 8)
+#define TD44(i) ((u32) Td4s[(i) & 0xff])
#define TD0_(i) Td0[(i) & 0xff]
#define TD1_(i) rotr(Td0[(i) & 0xff], 8)
#define TD2_(i) rotr(Td0[(i) & 0xff], 16)
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index 12109ce..15f8ad0 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -645,13 +645,6 @@
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
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index 1b0c1ec..fb278c2 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -570,8 +570,8 @@
failed = !q || !ctx || !tmp ||
!BN_mod_exp(tmp, pub, q, p, ctx) ||
!BN_is_one(tmp);
- BN_clear(q);
- BN_clear(tmp);
+ BN_clear_free(q);
+ BN_clear_free(tmp);
BN_CTX_free(ctx);
if (failed)
goto fail;
@@ -580,8 +580,8 @@
res = crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len,
prime, prime_len, secret, len);
fail:
- BN_clear(pub);
- BN_clear(p);
+ BN_clear_free(pub);
+ BN_clear_free(p);
return res;
}
@@ -1295,7 +1295,13 @@
int crypto_bignum_to_bin(const struct crypto_bignum *a,
u8 *buf, size_t buflen, size_t padlen)
{
+#ifdef OPENSSL_IS_BORINGSSL
+#else /* OPENSSL_IS_BORINGSSL */
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+#else
int num_bytes, offset;
+#endif
+#endif /* OPENSSL_IS_BORINGSSL */
if (TEST_FAIL())
return -1;
@@ -1303,6 +1309,14 @@
if (padlen > buflen)
return -1;
+#ifdef OPENSSL_IS_BORINGSSL
+ if (BN_bn2bin_padded(buf, padlen, (const BIGNUM *) a) == 0)
+ return -1;
+ return padlen;
+#else /* OPENSSL_IS_BORINGSSL */
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+ return BN_bn2binpad((const BIGNUM *) a, buf, padlen);
+#else
num_bytes = BN_num_bytes((const BIGNUM *) a);
if ((size_t) num_bytes > buflen)
return -1;
@@ -1315,6 +1329,8 @@
BN_bn2bin((const BIGNUM *) a, buf + offset);
return num_bytes + offset;
+#endif
+#endif /* OPENSSL_IS_BORINGSSL */
}
@@ -1476,12 +1492,6 @@
}
-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);
@@ -1870,7 +1880,7 @@
{
struct crypto_ecdh *ecdh;
EVP_PKEY *params = NULL;
- EC_KEY *ec_params;
+ EC_KEY *ec_params = NULL;
EVP_PKEY_CTX *kctx = NULL;
ecdh = os_zalloc(sizeof(*ecdh));
@@ -1913,6 +1923,7 @@
}
done:
+ EC_KEY_free(ec_params);
EVP_PKEY_free(params);
EVP_PKEY_CTX_free(kctx);
diff --git a/src/crypto/crypto_wolfssl.c b/src/crypto/crypto_wolfssl.c
index 976a008..4cedab4 100644
--- a/src/crypto/crypto_wolfssl.c
+++ b/src/crypto/crypto_wolfssl.c
@@ -1198,12 +1198,6 @@
}
-int crypto_bignum_bits(const struct crypto_bignum *a)
-{
- return mp_count_bits((mp_int *) a);
-}
-
-
int crypto_bignum_is_zero(const struct crypto_bignum *a)
{
return mp_iszero((mp_int *) a);
diff --git a/src/crypto/sha1-internal.c b/src/crypto/sha1-internal.c
index a491707..ffa04df 100644
--- a/src/crypto/sha1-internal.c
+++ b/src/crypto/sha1-internal.c
@@ -224,7 +224,7 @@
/* Wipe variables */
a = b = c = d = e = 0;
#ifdef SHA1HANDSOFF
- os_memset(block, 0, 64);
+ forced_memzero(block, 64);
#endif
}
@@ -300,7 +300,7 @@
os_memset(context->buffer, 0, 64);
os_memset(context->state, 0, 20);
os_memset(context->count, 0, 8);
- os_memset(finalcount, 0, 8);
+ forced_memzero(finalcount, sizeof(finalcount));
}
/* ===== end - public domain SHA1 implementation ===== */
diff --git a/src/crypto/sha1-prf.c b/src/crypto/sha1-prf.c
index 4b2d137..1385149 100644
--- a/src/crypto/sha1-prf.c
+++ b/src/crypto/sha1-prf.c
@@ -61,7 +61,7 @@
}
counter++;
}
- os_memset(hash, 0, sizeof(hash));
+ forced_memzero(hash, sizeof(hash));
return 0;
}
diff --git a/src/crypto/sha1-tlsprf.c b/src/crypto/sha1-tlsprf.c
index a11649a..5e8d159 100644
--- a/src/crypto/sha1-tlsprf.c
+++ b/src/crypto/sha1-tlsprf.c
@@ -92,10 +92,10 @@
SHA1_pos++;
}
- os_memset(A_MD5, 0, MD5_MAC_LEN);
- os_memset(P_MD5, 0, MD5_MAC_LEN);
- os_memset(A_SHA1, 0, SHA1_MAC_LEN);
- os_memset(P_SHA1, 0, SHA1_MAC_LEN);
+ forced_memzero(A_MD5, MD5_MAC_LEN);
+ forced_memzero(P_MD5, MD5_MAC_LEN);
+ forced_memzero(A_SHA1, SHA1_MAC_LEN);
+ forced_memzero(P_SHA1, SHA1_MAC_LEN);
return 0;
}
diff --git a/src/crypto/sha1-tprf.c b/src/crypto/sha1-tprf.c
index 562510f..c3acf19 100644
--- a/src/crypto/sha1-tprf.c
+++ b/src/crypto/sha1-tprf.c
@@ -66,7 +66,7 @@
len[0] = SHA1_MAC_LEN;
}
- os_memset(hash, 0, SHA1_MAC_LEN);
+ forced_memzero(hash, SHA1_MAC_LEN);
return 0;
}
diff --git a/src/crypto/sha1.c b/src/crypto/sha1.c
index 8fce139..76d7a68 100644
--- a/src/crypto/sha1.c
+++ b/src/crypto/sha1.c
@@ -86,7 +86,8 @@
_addr[1] = mac;
_len[1] = SHA1_MAC_LEN;
ret = sha1_vector(2, _addr, _len, mac);
- os_memset(k_pad, 0, sizeof(k_pad));
+ forced_memzero(k_pad, sizeof(k_pad));
+ forced_memzero(tk, sizeof(tk));
return ret;
}
diff --git a/src/crypto/sha256-kdf.c b/src/crypto/sha256-kdf.c
index af7d954..5a6b744 100644
--- a/src/crypto/sha256-kdf.c
+++ b/src/crypto/sha256-kdf.c
@@ -69,7 +69,7 @@
if (iter == 255) {
os_memset(out, 0, outlen);
- os_memset(T, 0, SHA256_MAC_LEN);
+ forced_memzero(T, SHA256_MAC_LEN);
return -1;
}
iter++;
@@ -77,11 +77,11 @@
if (hmac_sha256_vector(secret, secret_len, 4, addr, len, T) < 0)
{
os_memset(out, 0, outlen);
- os_memset(T, 0, SHA256_MAC_LEN);
+ forced_memzero(T, SHA256_MAC_LEN);
return -1;
}
}
- os_memset(T, 0, SHA256_MAC_LEN);
+ forced_memzero(T, SHA256_MAC_LEN);
return 0;
}
diff --git a/src/crypto/sha256-prf.c b/src/crypto/sha256-prf.c
index 722cad6..d665a99 100644
--- a/src/crypto/sha256-prf.c
+++ b/src/crypto/sha256-prf.c
@@ -102,7 +102,7 @@
buf[pos - 1] &= mask;
}
- os_memset(hash, 0, sizeof(hash));
+ forced_memzero(hash, sizeof(hash));
return 0;
}
diff --git a/src/crypto/sha256-tlsprf.c b/src/crypto/sha256-tlsprf.c
index 0528dad..9045cd3 100644
--- a/src/crypto/sha256-tlsprf.c
+++ b/src/crypto/sha256-tlsprf.c
@@ -26,8 +26,8 @@
* This function is used to derive new, cryptographically separate keys from a
* given key in TLS. This PRF is defined in RFC 2246, Chapter 5.
*/
-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 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)
{
size_t clen;
u8 A[SHA256_MAC_LEN];
@@ -50,12 +50,15 @@
* PRF(secret, label, seed) = P_SHA256(secret, label + seed)
*/
- hmac_sha256_vector(secret, secret_len, 2, &addr[1], &len[1], A);
+ if (hmac_sha256_vector(secret, secret_len, 2, &addr[1], &len[1], A) < 0)
+ return -1;
pos = 0;
while (pos < outlen) {
- hmac_sha256_vector(secret, secret_len, 3, addr, len, P);
- hmac_sha256(secret, secret_len, A, SHA256_MAC_LEN, A);
+ if (hmac_sha256_vector(secret, secret_len, 3, addr, len, P) <
+ 0 ||
+ hmac_sha256(secret, secret_len, A, SHA256_MAC_LEN, A) < 0)
+ return -1;
clen = outlen - pos;
if (clen > SHA256_MAC_LEN)
@@ -63,4 +66,6 @@
os_memcpy(out + pos, P, clen);
pos += clen;
}
+
+ return 0;
}
diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h
index 5219022..8054bbe 100644
--- a/src/crypto/sha256.h
+++ b/src/crypto/sha256.h
@@ -20,9 +20,9 @@
int 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 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);
diff --git a/src/crypto/sha384-kdf.c b/src/crypto/sha384-kdf.c
index 1d19627..babcb9e 100644
--- a/src/crypto/sha384-kdf.c
+++ b/src/crypto/sha384-kdf.c
@@ -69,7 +69,7 @@
if (iter == 255) {
os_memset(out, 0, outlen);
- os_memset(T, 0, SHA384_MAC_LEN);
+ forced_memzero(T, SHA384_MAC_LEN);
return -1;
}
iter++;
@@ -77,11 +77,11 @@
if (hmac_sha384_vector(secret, secret_len, 4, addr, len, T) < 0)
{
os_memset(out, 0, outlen);
- os_memset(T, 0, SHA384_MAC_LEN);
+ forced_memzero(T, SHA384_MAC_LEN);
return -1;
}
}
- os_memset(T, 0, SHA384_MAC_LEN);
+ forced_memzero(T, SHA384_MAC_LEN);
return 0;
}
diff --git a/src/crypto/sha384-prf.c b/src/crypto/sha384-prf.c
index 03e3cb3..420e78c 100644
--- a/src/crypto/sha384-prf.c
+++ b/src/crypto/sha384-prf.c
@@ -102,7 +102,7 @@
buf[pos - 1] &= mask;
}
- os_memset(hash, 0, sizeof(hash));
+ forced_memzero(hash, sizeof(hash));
return 0;
}
diff --git a/src/crypto/sha512-kdf.c b/src/crypto/sha512-kdf.c
index 8b71f9b..5bde664 100644
--- a/src/crypto/sha512-kdf.c
+++ b/src/crypto/sha512-kdf.c
@@ -69,7 +69,7 @@
if (iter == 255) {
os_memset(out, 0, outlen);
- os_memset(T, 0, SHA512_MAC_LEN);
+ forced_memzero(T, SHA512_MAC_LEN);
return -1;
}
iter++;
@@ -77,11 +77,11 @@
if (hmac_sha512_vector(secret, secret_len, 4, addr, len, T) < 0)
{
os_memset(out, 0, outlen);
- os_memset(T, 0, SHA512_MAC_LEN);
+ forced_memzero(T, SHA512_MAC_LEN);
return -1;
}
}
- os_memset(T, 0, SHA512_MAC_LEN);
+ forced_memzero(T, SHA512_MAC_LEN);
return 0;
}
diff --git a/src/crypto/sha512-prf.c b/src/crypto/sha512-prf.c
index 3b2ad88..e48cf5f 100644
--- a/src/crypto/sha512-prf.c
+++ b/src/crypto/sha512-prf.c
@@ -102,7 +102,7 @@
buf[pos - 1] &= mask;
}
- os_memset(hash, 0, sizeof(hash));
+ forced_memzero(hash, sizeof(hash));
return 0;
}
diff --git a/src/crypto/tls.h b/src/crypto/tls.h
index 8bdb91f..c8b1a82 100644
--- a/src/crypto/tls.h
+++ b/src/crypto/tls.h
@@ -48,6 +48,18 @@
#define TLS_MAX_ALT_SUBJECT 10
+struct tls_cert_data {
+ int depth;
+ const char *subject;
+ const struct wpabuf *cert;
+ const u8 *hash;
+ size_t hash_len;
+ const char *altsubject[TLS_MAX_ALT_SUBJECT];
+ int num_altsubject;
+ const char *serial_num;
+ int tod;
+};
+
union tls_event_data {
struct {
int depth;
@@ -57,16 +69,7 @@
const struct wpabuf *cert;
} cert_fail;
- struct {
- int depth;
- const char *subject;
- const struct wpabuf *cert;
- const u8 *hash;
- size_t hash_len;
- const char *altsubject[TLS_MAX_ALT_SUBJECT];
- int num_altsubject;
- const char *serial_num;
- } peer_cert;
+ struct tls_cert_data peer_cert;
struct {
int is_local;
@@ -108,6 +111,7 @@
#define TLS_CONN_ENABLE_TLSv1_0 BIT(14)
#define TLS_CONN_ENABLE_TLSv1_1 BIT(15)
#define TLS_CONN_ENABLE_TLSv1_2 BIT(16)
+#define TLS_CONN_TEAP_ANON_DH BIT(17)
/**
* struct tls_connection_params - Parameters for TLS connection
@@ -184,12 +188,15 @@
const char *suffix_match;
const char *domain_match;
const char *client_cert;
+ const char *client_cert2;
const u8 *client_cert_blob;
size_t client_cert_blob_len;
const char *private_key;
+ const char *private_key2;
const u8 *private_key_blob;
size_t private_key_blob_len;
const char *private_key_passwd;
+ const char *private_key_passwd2;
const char *dh_file;
const u8 *dh_blob;
size_t dh_blob_len;
@@ -643,4 +650,24 @@
void tls_connection_remove_session(struct tls_connection *conn);
+/**
+ * tls_get_tls_unique - Fetch "tls-unique" for channel binding
+ * @conn: Connection context data from tls_connection_init()
+ * @buf: Buffer for returning the value
+ * @max_len: Maximum length of the buffer in bytes
+ * Returns: Number of bytes written to buf or -1 on error
+ *
+ * This function can be used to fetch "tls-unique" (RFC 5929, Section 3) which
+ * is the first TLS Finished message sent in the most recent TLS handshake of
+ * the TLS connection.
+ */
+int tls_get_tls_unique(struct tls_connection *conn, u8 *buf, size_t max_len);
+
+/**
+ * tls_connection_get_cipher_suite - Get current TLS cipher suite
+ * @conn: Connection context data from tls_connection_init()
+ * Returns: TLS cipher suite of the current connection or 0 on error
+ */
+u16 tls_connection_get_cipher_suite(struct tls_connection *conn);
+
#endif /* TLS_H */
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 620254a..9718ceb 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -44,6 +44,13 @@
#define OPENSSL_NEED_EAP_FAST_PRF
#endif
+#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || \
+ defined(EAP_SERVER_FAST) || defined(EAP_TEAP) || \
+ defined(EAP_SERVER_TEAP)
+#define EAP_FAST_OR_TEAP
+#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;
@@ -1085,11 +1092,8 @@
}
#ifndef OPENSSL_NO_ENGINE
- wpa_printf(MSG_DEBUG, "ENGINE: Loading dynamic engine");
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
- ERR_load_ENGINE_strings();
- ENGINE_load_dynamic();
-#endif /* OPENSSL_VERSION_NUMBER */
+ wpa_printf(MSG_DEBUG, "ENGINE: Loading builtin engines");
+ ENGINE_load_builtin_engines();
if (conf &&
(conf->opensc_engine_path || conf->pkcs11_engine_path ||
@@ -1345,6 +1349,8 @@
return "heartbeat";
case 256:
return "TLS header info"; /* pseudo content type */
+ case 257:
+ return "inner content type"; /* pseudo content type */
default:
return "?";
}
@@ -1354,6 +1360,8 @@
static const char * openssl_handshake_type(int content_type, const u8 *buf,
size_t len)
{
+ if (content_type == 257 && buf && len == 1)
+ return openssl_content_type(buf[0]);
if (content_type != 22 || !buf || len == 0)
return "";
switch (buf[0]) {
@@ -1584,6 +1592,11 @@
options |= SSL_OP_NO_COMPRESSION;
#endif /* SSL_OP_NO_COMPRESSION */
SSL_set_options(conn->ssl, options);
+#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT
+ /* Hopefully there is no need for middlebox compatibility mechanisms
+ * when going through EAP authentication. */
+ SSL_clear_options(conn->ssl, SSL_OP_ENABLE_MIDDLEBOX_COMPAT);
+#endif
conn->ssl_in = BIO_new(BIO_s_mem());
if (!conn->ssl_in) {
@@ -2170,6 +2183,34 @@
}
+static int openssl_cert_tod(X509 *cert)
+{
+ CERTIFICATEPOLICIES *ext;
+ stack_index_t i;
+ char buf[100];
+ int res;
+ int tod = 0;
+
+ ext = X509_get_ext_d2i(cert, NID_certificate_policies, NULL, NULL);
+ if (!ext)
+ return 0;
+
+ for (i = 0; i < sk_POLICYINFO_num(ext); i++) {
+ POLICYINFO *policy;
+
+ policy = sk_POLICYINFO_value(ext, i);
+ res = OBJ_obj2txt(buf, sizeof(buf), policy->policyid, 0);
+ if (res < 0 || (size_t) res >= sizeof(buf))
+ continue;
+ wpa_printf(MSG_DEBUG, "OpenSSL: Certificate Policy %s", buf);
+ if (os_strcmp(buf, "1.3.6.1.4.1.40808.1.3.1") == 0)
+ tod = 1;
+ }
+
+ return tod;
+}
+
+
static void openssl_tls_cert_event(struct tls_connection *conn,
X509 *err_cert, int depth,
const char *subject)
@@ -2262,6 +2303,8 @@
ev.peer_cert.altsubject[alt] = altsubject[alt];
ev.peer_cert.num_altsubject = num_altsubject;
+ ev.peer_cert.tod = openssl_cert_tod(err_cert);
+
context->event_cb(context->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
wpabuf_free(cert);
for (alt = 0; alt < num_altsubject; alt++)
@@ -2366,7 +2409,30 @@
}
#endif /* CONFIG_SHA256 */
+ openssl_tls_cert_event(conn, err_cert, depth, buf);
+
if (!preverify_ok) {
+ if (depth > 0) {
+ /* Send cert event for the peer certificate so that
+ * the upper layers get information about it even if
+ * validation of a CA certificate fails. */
+ STACK_OF(X509) *chain;
+
+ chain = X509_STORE_CTX_get1_chain(x509_ctx);
+ if (chain && sk_X509_num(chain) > 0) {
+ char buf2[256];
+ X509 *cert;
+
+ cert = sk_X509_value(chain, 0);
+ X509_NAME_oneline(X509_get_subject_name(cert),
+ buf2, sizeof(buf2));
+
+ openssl_tls_cert_event(conn, cert, 0, buf2);
+ }
+ if (chain)
+ sk_X509_pop_free(chain, X509_free);
+ }
+
wpa_printf(MSG_WARNING, "TLS: Certificate verification failed,"
" error %d (%s) depth %d for '%s'", err, err_str,
depth, buf);
@@ -2422,8 +2488,7 @@
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);
+ }
if (conn->cert_probe && preverify_ok && depth == 0) {
wpa_printf(MSG_DEBUG, "OpenSSL: Reject server certificate "
@@ -2598,9 +2663,23 @@
(const unsigned char **) &ca_cert_blob,
ca_cert_blob_len);
if (cert == NULL) {
- tls_show_errors(MSG_WARNING, __func__,
- "Failed to parse ca_cert_blob");
- return -1;
+ BIO *bio = BIO_new_mem_buf(ca_cert_blob,
+ ca_cert_blob_len);
+
+ if (bio) {
+ cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+ BIO_free(bio);
+ }
+
+ if (!cert) {
+ tls_show_errors(MSG_WARNING, __func__,
+ "Failed to parse ca_cert_blob");
+ return -1;
+ }
+
+ while (ERR_get_error()) {
+ /* Ignore errors from DER conversion. */
+ }
}
if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(ssl_ctx),
@@ -3034,6 +3113,40 @@
}
#endif /* CONFIG_SUITEB */
+ if (flags & TLS_CONN_TEAP_ANON_DH) {
+#ifndef TEAP_DH_ANON_CS
+#define TEAP_DH_ANON_CS \
+ "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:" \
+ "ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:" \
+ "ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:" \
+ "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:" \
+ "DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:" \
+ "DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:" \
+ "ADH-AES256-GCM-SHA384:ADH-AES128-GCM-SHA256:" \
+ "ADH-AES256-SHA256:ADH-AES128-SHA256:ADH-AES256-SHA:ADH-AES128-SHA"
+#endif
+ static const char *cs = TEAP_DH_ANON_CS;
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
+ !defined(LIBRESSL_VERSION_NUMBER) && \
+ !defined(OPENSSL_IS_BORINGSSL)
+ /*
+ * Need to drop to security level 0 to allow anonymous
+ * cipher suites for EAP-TEAP.
+ */
+ SSL_set_security_level(conn->ssl, 0);
+#endif
+
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: Enable cipher suites for anonymous EAP-TEAP provisioning: %s",
+ cs);
+ if (SSL_set_cipher_list(conn->ssl, cs) != 1) {
+ tls_show_errors(MSG_INFO, __func__,
+ "Cipher suite configuration failed");
+ return -1;
+ }
+ }
+
return 0;
}
@@ -4020,7 +4133,7 @@
_out, skip + out_len) == 0) {
ret = 0;
}
- os_memset(master_key, 0, sizeof(master_key));
+ forced_memzero(master_key, sizeof(master_key));
os_free(rnd);
if (ret == 0)
os_memcpy(out, _out + skip, out_len);
@@ -4210,6 +4323,22 @@
wpa_printf(MSG_DEBUG,
"OpenSSL: Handshake finished - resumed=%d",
tls_connection_resumed(conn->ssl_ctx, conn));
+ if (conn->server) {
+ char *buf;
+ size_t buflen = 2000;
+
+ buf = os_malloc(buflen);
+ if (buf) {
+ if (SSL_get_shared_ciphers(conn->ssl, buf,
+ buflen)) {
+ buf[buflen - 1] = '\0';
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: Shared ciphers: %s",
+ buf);
+ }
+ os_free(buf);
+ }
+ }
if (appl_data && in_data)
*appl_data = openssl_get_appl_data(conn,
wpabuf_len(in_data));
@@ -4392,11 +4521,15 @@
c++;
}
+ if (!buf[0]) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: No ciphers listed");
+ return -1;
+ }
wpa_printf(MSG_DEBUG, "OpenSSL: cipher suites: %s", buf + 1);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
-#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
+#ifdef EAP_FAST_OR_TEAP
if (os_strstr(buf, ":ADH-")) {
/*
* Need to drop to security level 0 to allow anonymous
@@ -4407,7 +4540,7 @@
/* Force at least security level 1 */
SSL_set_security_level(conn->ssl, 1);
}
-#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
+#endif /* EAP_FAST_OR_TEAP */
#endif
if (SSL_set_cipher_list(conn->ssl, buf + 1) != 1) {
@@ -4461,7 +4594,7 @@
}
-#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
+#ifdef EAP_FAST_OR_TEAP
/* ClientHello TLS extensions require a patch to openssl, so this function is
* commented out unless explicitly needed for EAP-FAST in order to be able to
* build this file with unmodified openssl. */
@@ -4478,7 +4611,7 @@
return 0;
}
-#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
+#endif /* EAP_FAST_OR_TEAP */
int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
@@ -4687,6 +4820,7 @@
res = OCSP_resp_find_status(basic, id, &status, &reason, &produced_at,
&this_update, &next_update);
if (!res) {
+ OCSP_CERTID_free(id);
id = OCSP_cert_to_id(NULL, conn->peer_cert, conn->peer_issuer);
if (!id) {
wpa_printf(MSG_DEBUG,
@@ -4997,6 +5131,114 @@
}
+static void openssl_debug_dump_cipher_list(SSL_CTX *ssl_ctx)
+{
+ SSL *ssl;
+ int i;
+
+ ssl = SSL_new(ssl_ctx);
+ if (!ssl)
+ return;
+
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: Enabled cipher suites in priority order");
+ for (i = 0; ; i++) {
+ const char *cipher;
+
+ cipher = SSL_get_cipher_list(ssl, i);
+ if (!cipher)
+ break;
+ wpa_printf(MSG_DEBUG, "Cipher %d: %s", i, cipher);
+ }
+
+ SSL_free(ssl);
+}
+
+
+#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(BORINGSSL_API_VERSION)
+
+static const char * openssl_pkey_type_str(const EVP_PKEY *pkey)
+{
+ if (!pkey)
+ return "NULL";
+ switch (EVP_PKEY_type(EVP_PKEY_id(pkey))) {
+ case EVP_PKEY_RSA:
+ return "RSA";
+ case EVP_PKEY_DSA:
+ return "DSA";
+ case EVP_PKEY_DH:
+ return "DH";
+ case EVP_PKEY_EC:
+ return "EC";
+ }
+ return "?";
+}
+
+
+static void openssl_debug_dump_certificate(int i, X509 *cert)
+{
+ char buf[256];
+ EVP_PKEY *pkey;
+ ASN1_INTEGER *ser;
+ char serial_num[128];
+
+ X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
+
+ ser = X509_get_serialNumber(cert);
+ if (ser)
+ wpa_snprintf_hex_uppercase(serial_num, sizeof(serial_num),
+ ASN1_STRING_get0_data(ser),
+ ASN1_STRING_length(ser));
+ else
+ serial_num[0] = '\0';
+
+ pkey = X509_get_pubkey(cert);
+ wpa_printf(MSG_DEBUG, "%d: %s (%s) %s", i, buf,
+ openssl_pkey_type_str(pkey), serial_num);
+ EVP_PKEY_free(pkey);
+}
+
+
+static void openssl_debug_dump_certificates(SSL_CTX *ssl_ctx)
+{
+ STACK_OF(X509) *certs;
+
+ wpa_printf(MSG_DEBUG, "OpenSSL: Configured certificate chain");
+ if (SSL_CTX_get0_chain_certs(ssl_ctx, &certs) == 1) {
+ int i;
+
+ for (i = sk_X509_num(certs); i > 0; i--)
+ openssl_debug_dump_certificate(i, sk_X509_value(certs,
+ i - 1));
+ }
+ openssl_debug_dump_certificate(0, SSL_CTX_get0_certificate(ssl_ctx));
+}
+
+#endif
+
+
+static void openssl_debug_dump_certificate_chains(SSL_CTX *ssl_ctx)
+{
+#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(BORINGSSL_API_VERSION)
+ int res;
+
+ for (res = SSL_CTX_set_current_cert(ssl_ctx, SSL_CERT_SET_FIRST);
+ res == 1;
+ res = SSL_CTX_set_current_cert(ssl_ctx, SSL_CERT_SET_NEXT))
+ openssl_debug_dump_certificates(ssl_ctx);
+
+ SSL_CTX_set_current_cert(ssl_ctx, SSL_CERT_SET_FIRST);
+#endif
+}
+
+
+static void openssl_debug_dump_ctx(SSL_CTX *ssl_ctx)
+{
+ openssl_debug_dump_cipher_list(ssl_ctx);
+ openssl_debug_dump_certificate_chains(ssl_ctx);
+}
+
+
int tls_global_set_params(void *tls_ctx,
const struct tls_connection_params *params)
{
@@ -5022,6 +5264,9 @@
tls_global_client_cert(data, params->client_cert) ||
tls_global_private_key(data, params->private_key,
params->private_key_passwd) ||
+ tls_global_client_cert(data, params->client_cert2) ||
+ tls_global_private_key(data, params->private_key2,
+ params->private_key_passwd2) ||
tls_global_dh(data, params->dh_file)) {
wpa_printf(MSG_INFO, "TLS: Failed to set global parameters");
return -1;
@@ -5091,11 +5336,13 @@
tls_global->ocsp_stapling_response = NULL;
#endif /* HAVE_OCSP */
+ openssl_debug_dump_ctx(ssl_ctx);
+
return 0;
}
-#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
+#ifdef EAP_FAST_OR_TEAP
/* Pre-shared secred requires a patch to openssl, so this function is
* commented out unless explicitly needed for EAP-FAST in order to be able to
* build this file with unmodified openssl. */
@@ -5176,7 +5423,7 @@
return 1;
}
-#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
+#endif /* EAP_FAST_OR_TEAP */
int tls_connection_set_session_ticket_cb(void *tls_ctx,
@@ -5184,7 +5431,7 @@
tls_session_ticket_cb cb,
void *ctx)
{
-#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
+#ifdef EAP_FAST_OR_TEAP
conn->session_ticket_cb = cb;
conn->session_ticket_cb_ctx = ctx;
@@ -5201,9 +5448,9 @@
}
return 0;
-#else /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
+#else /* EAP_FAST_OR_TEAP */
return -1;
-#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
+#endif /* EAP_FAST_OR_TEAP */
}
@@ -5286,3 +5533,36 @@
wpa_printf(MSG_DEBUG,
"OpenSSL: Removed cached session to disable session resumption");
}
+
+
+int tls_get_tls_unique(struct tls_connection *conn, u8 *buf, size_t max_len)
+{
+ size_t len;
+ int reused;
+
+ reused = SSL_session_reused(conn->ssl);
+ if ((conn->server && !reused) || (!conn->server && reused))
+ len = SSL_get_peer_finished(conn->ssl, buf, max_len);
+ else
+ len = SSL_get_finished(conn->ssl, buf, max_len);
+
+ if (len == 0 || len > max_len)
+ return -1;
+
+ return len;
+}
+
+
+u16 tls_connection_get_cipher_suite(struct tls_connection *conn)
+{
+ const SSL_CIPHER *cipher;
+
+ cipher = SSL_get_current_cipher(conn->ssl);
+ if (!cipher)
+ return 0;
+#if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined(LIBRESSL_VERSION_NUMBER)
+ return SSL_CIPHER_get_protocol_id(cipher);
+#else
+ return SSL_CIPHER_get_id(cipher) & 0xFFFF;
+#endif
+}
diff --git a/src/crypto/tls_wolfssl.c b/src/crypto/tls_wolfssl.c
index e9cb425..83704ff 100644
--- a/src/crypto/tls_wolfssl.c
+++ b/src/crypto/tls_wolfssl.c
@@ -2044,7 +2044,7 @@
_out, skip + out_len);
}
- os_memset(master_key, 0, master_key_len);
+ forced_memzero(master_key, master_key_len);
if (ret == 0)
os_memcpy(out, _out + skip, out_len);
bin_clear_free(tmp_out, skip + out_len);