xref: /freebsd/contrib/wpa/src/crypto/tls_openssl.c (revision ec080394)
139beb93cSSam Leffler /*
2e28a4053SRui Paulo  * SSL/TLS interface functions for OpenSSL
3325151a3SRui Paulo  * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler  *
5f05cddf9SRui Paulo  * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo  * See README for more details.
739beb93cSSam Leffler  */
839beb93cSSam Leffler 
939beb93cSSam Leffler #include "includes.h"
1039beb93cSSam Leffler 
1139beb93cSSam Leffler #ifndef CONFIG_SMARTCARD
1239beb93cSSam Leffler #ifndef OPENSSL_NO_ENGINE
135b9c547cSRui Paulo #ifndef ANDROID
1439beb93cSSam Leffler #define OPENSSL_NO_ENGINE
1539beb93cSSam Leffler #endif
1639beb93cSSam Leffler #endif
175b9c547cSRui Paulo #endif
1839beb93cSSam Leffler 
1939beb93cSSam Leffler #include <openssl/ssl.h>
2039beb93cSSam Leffler #include <openssl/err.h>
21780fb4a2SCy Schubert #include <openssl/opensslv.h>
2239beb93cSSam Leffler #include <openssl/pkcs12.h>
2339beb93cSSam Leffler #include <openssl/x509v3.h>
2439beb93cSSam Leffler #ifndef OPENSSL_NO_ENGINE
2539beb93cSSam Leffler #include <openssl/engine.h>
2639beb93cSSam Leffler #endif /* OPENSSL_NO_ENGINE */
27325151a3SRui Paulo #ifndef OPENSSL_NO_DSA
28325151a3SRui Paulo #include <openssl/dsa.h>
29325151a3SRui Paulo #endif
30325151a3SRui Paulo #ifndef OPENSSL_NO_DH
31325151a3SRui Paulo #include <openssl/dh.h>
32325151a3SRui Paulo #endif
3339beb93cSSam Leffler 
3439beb93cSSam Leffler #include "common.h"
35e28a4053SRui Paulo #include "crypto.h"
36325151a3SRui Paulo #include "sha1.h"
37325151a3SRui Paulo #include "sha256.h"
3839beb93cSSam Leffler #include "tls.h"
39780fb4a2SCy Schubert #include "tls_openssl.h"
4039beb93cSSam Leffler 
41780fb4a2SCy Schubert #if !defined(CONFIG_FIPS) &&                             \
42780fb4a2SCy Schubert     (defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) ||   \
43780fb4a2SCy Schubert      defined(EAP_SERVER_FAST))
44780fb4a2SCy Schubert #define OPENSSL_NEED_EAP_FAST_PRF
4539beb93cSSam Leffler #endif
465b9c547cSRui Paulo 
47206b73d0SCy Schubert #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || \
48206b73d0SCy Schubert 	defined(EAP_SERVER_FAST) || defined(EAP_TEAP) || \
49206b73d0SCy Schubert 	defined(EAP_SERVER_TEAP)
50206b73d0SCy Schubert #define EAP_FAST_OR_TEAP
51206b73d0SCy Schubert #endif
52206b73d0SCy Schubert 
53206b73d0SCy Schubert 
545b9c547cSRui Paulo #if defined(OPENSSL_IS_BORINGSSL)
555b9c547cSRui Paulo /* stack_index_t is the return type of OpenSSL's sk_XXX_num() functions. */
565b9c547cSRui Paulo typedef size_t stack_index_t;
575b9c547cSRui Paulo #else
585b9c547cSRui Paulo typedef int stack_index_t;
5939beb93cSSam Leffler #endif
6039beb93cSSam Leffler 
615b9c547cSRui Paulo #ifdef SSL_set_tlsext_status_type
625b9c547cSRui Paulo #ifndef OPENSSL_NO_TLSEXT
635b9c547cSRui Paulo #define HAVE_OCSP
645b9c547cSRui Paulo #include <openssl/ocsp.h>
655b9c547cSRui Paulo #endif /* OPENSSL_NO_TLSEXT */
665b9c547cSRui Paulo #endif /* SSL_set_tlsext_status_type */
675b9c547cSRui Paulo 
68780fb4a2SCy Schubert #if (OPENSSL_VERSION_NUMBER < 0x10100000L || \
6985732ac8SCy Schubert      (defined(LIBRESSL_VERSION_NUMBER) && \
7085732ac8SCy Schubert       LIBRESSL_VERSION_NUMBER < 0x20700000L)) && \
71780fb4a2SCy Schubert     !defined(BORINGSSL_API_VERSION)
72780fb4a2SCy Schubert /*
73780fb4a2SCy Schubert  * SSL_get_client_random() and SSL_get_server_random() were added in OpenSSL
74780fb4a2SCy Schubert  * 1.1.0 and newer BoringSSL revisions. Provide compatibility wrappers for
75780fb4a2SCy Schubert  * older versions.
76780fb4a2SCy Schubert  */
77780fb4a2SCy Schubert 
SSL_get_client_random(const SSL * ssl,unsigned char * out,size_t outlen)78780fb4a2SCy Schubert static size_t SSL_get_client_random(const SSL *ssl, unsigned char *out,
79780fb4a2SCy Schubert 				    size_t outlen)
80780fb4a2SCy Schubert {
81780fb4a2SCy Schubert 	if (!ssl->s3 || outlen < SSL3_RANDOM_SIZE)
82780fb4a2SCy Schubert 		return 0;
83780fb4a2SCy Schubert 	os_memcpy(out, ssl->s3->client_random, SSL3_RANDOM_SIZE);
84780fb4a2SCy Schubert 	return SSL3_RANDOM_SIZE;
85780fb4a2SCy Schubert }
86780fb4a2SCy Schubert 
87780fb4a2SCy Schubert 
SSL_get_server_random(const SSL * ssl,unsigned char * out,size_t outlen)88780fb4a2SCy Schubert static size_t SSL_get_server_random(const SSL *ssl, unsigned char *out,
89780fb4a2SCy Schubert 				    size_t outlen)
90780fb4a2SCy Schubert {
91780fb4a2SCy Schubert 	if (!ssl->s3 || outlen < SSL3_RANDOM_SIZE)
92780fb4a2SCy Schubert 		return 0;
93780fb4a2SCy Schubert 	os_memcpy(out, ssl->s3->server_random, SSL3_RANDOM_SIZE);
94780fb4a2SCy Schubert 	return SSL3_RANDOM_SIZE;
95780fb4a2SCy Schubert }
96780fb4a2SCy Schubert 
97780fb4a2SCy Schubert 
98780fb4a2SCy Schubert #ifdef OPENSSL_NEED_EAP_FAST_PRF
SSL_SESSION_get_master_key(const SSL_SESSION * session,unsigned char * out,size_t outlen)99780fb4a2SCy Schubert static size_t SSL_SESSION_get_master_key(const SSL_SESSION *session,
100780fb4a2SCy Schubert 					 unsigned char *out, size_t outlen)
101780fb4a2SCy Schubert {
102780fb4a2SCy Schubert 	if (!session || session->master_key_length < 0 ||
103780fb4a2SCy Schubert 	    (size_t) session->master_key_length > outlen)
104780fb4a2SCy Schubert 		return 0;
105780fb4a2SCy Schubert 	if ((size_t) session->master_key_length < outlen)
106780fb4a2SCy Schubert 		outlen = session->master_key_length;
107780fb4a2SCy Schubert 	os_memcpy(out, session->master_key, outlen);
108780fb4a2SCy Schubert 	return outlen;
109780fb4a2SCy Schubert }
110780fb4a2SCy Schubert #endif /* OPENSSL_NEED_EAP_FAST_PRF */
111780fb4a2SCy Schubert 
112780fb4a2SCy Schubert #endif
113780fb4a2SCy Schubert 
1144bc52338SCy Schubert #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
1154bc52338SCy Schubert 	(defined(LIBRESSL_VERSION_NUMBER) && \
1164bc52338SCy Schubert 	 LIBRESSL_VERSION_NUMBER < 0x20700000L)
11785732ac8SCy Schubert #ifdef CONFIG_SUITEB
RSA_bits(const RSA * r)11885732ac8SCy Schubert static int RSA_bits(const RSA *r)
11985732ac8SCy Schubert {
12085732ac8SCy Schubert 	return BN_num_bits(r->n);
12185732ac8SCy Schubert }
12285732ac8SCy Schubert #endif /* CONFIG_SUITEB */
12385732ac8SCy Schubert 
12485732ac8SCy Schubert 
ASN1_STRING_get0_data(const ASN1_STRING * x)12585732ac8SCy Schubert static const unsigned char * ASN1_STRING_get0_data(const ASN1_STRING *x)
12685732ac8SCy Schubert {
12785732ac8SCy Schubert 	return ASN1_STRING_data((ASN1_STRING *) x);
12885732ac8SCy Schubert }
12985732ac8SCy Schubert #endif
13085732ac8SCy Schubert 
1315b9c547cSRui Paulo #ifdef ANDROID
1325b9c547cSRui Paulo #include <openssl/pem.h>
1335b9c547cSRui Paulo #include <keystore/keystore_get.h>
1345b9c547cSRui Paulo 
BIO_from_keystore(const char * key)1355b9c547cSRui Paulo static BIO * BIO_from_keystore(const char *key)
1365b9c547cSRui Paulo {
1375b9c547cSRui Paulo 	BIO *bio = NULL;
1385b9c547cSRui Paulo 	uint8_t *value = NULL;
1395b9c547cSRui Paulo 	int length = keystore_get(key, strlen(key), &value);
1405b9c547cSRui Paulo 	if (length != -1 && (bio = BIO_new(BIO_s_mem())) != NULL)
1415b9c547cSRui Paulo 		BIO_write(bio, value, length);
1425b9c547cSRui Paulo 	free(value);
1435b9c547cSRui Paulo 	return bio;
1445b9c547cSRui Paulo }
145780fb4a2SCy Schubert 
146780fb4a2SCy Schubert 
tls_add_ca_from_keystore(X509_STORE * ctx,const char * key_alias)147780fb4a2SCy Schubert static int tls_add_ca_from_keystore(X509_STORE *ctx, const char *key_alias)
148780fb4a2SCy Schubert {
149780fb4a2SCy Schubert 	BIO *bio = BIO_from_keystore(key_alias);
150780fb4a2SCy Schubert 	STACK_OF(X509_INFO) *stack = NULL;
151780fb4a2SCy Schubert 	stack_index_t i;
152780fb4a2SCy Schubert 
153780fb4a2SCy Schubert 	if (bio) {
154780fb4a2SCy Schubert 		stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
155780fb4a2SCy Schubert 		BIO_free(bio);
156780fb4a2SCy Schubert 	}
157780fb4a2SCy Schubert 
158780fb4a2SCy Schubert 	if (!stack) {
159780fb4a2SCy Schubert 		wpa_printf(MSG_WARNING, "TLS: Failed to parse certificate: %s",
160780fb4a2SCy Schubert 			   key_alias);
161780fb4a2SCy Schubert 		return -1;
162780fb4a2SCy Schubert 	}
163780fb4a2SCy Schubert 
164780fb4a2SCy Schubert 	for (i = 0; i < sk_X509_INFO_num(stack); ++i) {
165780fb4a2SCy Schubert 		X509_INFO *info = sk_X509_INFO_value(stack, i);
166780fb4a2SCy Schubert 
167780fb4a2SCy Schubert 		if (info->x509)
168780fb4a2SCy Schubert 			X509_STORE_add_cert(ctx, info->x509);
169780fb4a2SCy Schubert 		if (info->crl)
170780fb4a2SCy Schubert 			X509_STORE_add_crl(ctx, info->crl);
171780fb4a2SCy Schubert 	}
172780fb4a2SCy Schubert 
173780fb4a2SCy Schubert 	sk_X509_INFO_pop_free(stack, X509_INFO_free);
174780fb4a2SCy Schubert 
175780fb4a2SCy Schubert 	return 0;
176780fb4a2SCy Schubert }
177780fb4a2SCy Schubert 
178780fb4a2SCy Schubert 
tls_add_ca_from_keystore_encoded(X509_STORE * ctx,const char * encoded_key_alias)179780fb4a2SCy Schubert static int tls_add_ca_from_keystore_encoded(X509_STORE *ctx,
180780fb4a2SCy Schubert 					    const char *encoded_key_alias)
181780fb4a2SCy Schubert {
182780fb4a2SCy Schubert 	int rc = -1;
183780fb4a2SCy Schubert 	int len = os_strlen(encoded_key_alias);
184780fb4a2SCy Schubert 	unsigned char *decoded_alias;
185780fb4a2SCy Schubert 
186780fb4a2SCy Schubert 	if (len & 1) {
187780fb4a2SCy Schubert 		wpa_printf(MSG_WARNING, "Invalid hex-encoded alias: %s",
188780fb4a2SCy Schubert 			   encoded_key_alias);
189780fb4a2SCy Schubert 		return rc;
190780fb4a2SCy Schubert 	}
191780fb4a2SCy Schubert 
192780fb4a2SCy Schubert 	decoded_alias = os_malloc(len / 2 + 1);
193780fb4a2SCy Schubert 	if (decoded_alias) {
194780fb4a2SCy Schubert 		if (!hexstr2bin(encoded_key_alias, decoded_alias, len / 2)) {
195780fb4a2SCy Schubert 			decoded_alias[len / 2] = '\0';
196780fb4a2SCy Schubert 			rc = tls_add_ca_from_keystore(
197780fb4a2SCy Schubert 				ctx, (const char *) decoded_alias);
198780fb4a2SCy Schubert 		}
199780fb4a2SCy Schubert 		os_free(decoded_alias);
200780fb4a2SCy Schubert 	}
201780fb4a2SCy Schubert 
202780fb4a2SCy Schubert 	return rc;
203780fb4a2SCy Schubert }
204780fb4a2SCy Schubert 
2055b9c547cSRui Paulo #endif /* ANDROID */
2065b9c547cSRui Paulo 
20739beb93cSSam Leffler static int tls_openssl_ref_count = 0;
208325151a3SRui Paulo static int tls_ex_idx_session = -1;
20939beb93cSSam Leffler 
2105b9c547cSRui Paulo struct tls_context {
211e28a4053SRui Paulo 	void (*event_cb)(void *ctx, enum tls_event ev,
212e28a4053SRui Paulo 			 union tls_event_data *data);
213e28a4053SRui Paulo 	void *cb_ctx;
214f05cddf9SRui Paulo 	int cert_in_cb;
2155b9c547cSRui Paulo 	char *ocsp_stapling_response;
216e28a4053SRui Paulo };
217e28a4053SRui Paulo 
2185b9c547cSRui Paulo static struct tls_context *tls_global = NULL;
219e28a4053SRui Paulo 
220e28a4053SRui Paulo 
221325151a3SRui Paulo struct tls_data {
222325151a3SRui Paulo 	SSL_CTX *ssl;
223325151a3SRui Paulo 	unsigned int tls_session_lifetime;
2244bc52338SCy Schubert 	int check_crl;
2254bc52338SCy Schubert 	int check_crl_strict;
2264bc52338SCy Schubert 	char *ca_cert;
2274bc52338SCy Schubert 	unsigned int crl_reload_interval;
2284bc52338SCy Schubert 	struct os_reltime crl_last_reload;
2294bc52338SCy Schubert 	char *check_cert_subject;
230325151a3SRui Paulo };
231325151a3SRui Paulo 
23239beb93cSSam Leffler struct tls_connection {
2335b9c547cSRui Paulo 	struct tls_context *context;
2344bc52338SCy Schubert 	struct tls_data *data;
2355b9c547cSRui Paulo 	SSL_CTX *ssl_ctx;
23639beb93cSSam Leffler 	SSL *ssl;
23739beb93cSSam Leffler 	BIO *ssl_in, *ssl_out;
238780fb4a2SCy Schubert #if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE)
23939beb93cSSam Leffler 	ENGINE *engine;        /* functional reference to the engine */
24039beb93cSSam Leffler 	EVP_PKEY *private_key; /* the private key if using engine */
24139beb93cSSam Leffler #endif /* OPENSSL_NO_ENGINE */
2425b9c547cSRui Paulo 	char *subject_match, *altsubject_match, *suffix_match, *domain_match;
2434bc52338SCy Schubert 	char *check_cert_subject;
24439beb93cSSam Leffler 	int read_alerts, write_alerts, failed;
24539beb93cSSam Leffler 
24639beb93cSSam Leffler 	tls_session_ticket_cb session_ticket_cb;
24739beb93cSSam Leffler 	void *session_ticket_cb_ctx;
24839beb93cSSam Leffler 
24939beb93cSSam Leffler 	/* SessionTicket received from OpenSSL hello_extension_cb (server) */
25039beb93cSSam Leffler 	u8 *session_ticket;
25139beb93cSSam Leffler 	size_t session_ticket_len;
252e28a4053SRui Paulo 
253e28a4053SRui Paulo 	unsigned int ca_cert_verify:1;
254e28a4053SRui Paulo 	unsigned int cert_probe:1;
255e28a4053SRui Paulo 	unsigned int server_cert_only:1;
2565b9c547cSRui Paulo 	unsigned int invalid_hb_used:1;
257325151a3SRui Paulo 	unsigned int success_data:1;
25885732ac8SCy Schubert 	unsigned int client_hello_generated:1;
25985732ac8SCy Schubert 	unsigned int server:1;
260e28a4053SRui Paulo 
261e28a4053SRui Paulo 	u8 srv_cert_hash[32];
262f05cddf9SRui Paulo 
263f05cddf9SRui Paulo 	unsigned int flags;
2645b9c547cSRui Paulo 
2655b9c547cSRui Paulo 	X509 *peer_cert;
2665b9c547cSRui Paulo 	X509 *peer_issuer;
2675b9c547cSRui Paulo 	X509 *peer_issuer_issuer;
268c1d255d3SCy Schubert 	char *peer_subject; /* peer subject info for authenticated peer */
269325151a3SRui Paulo 
270325151a3SRui Paulo 	unsigned char client_random[SSL3_RANDOM_SIZE];
271325151a3SRui Paulo 	unsigned char server_random[SSL3_RANDOM_SIZE];
27285732ac8SCy Schubert 
27385732ac8SCy Schubert 	u16 cipher_suite;
27485732ac8SCy Schubert 	int server_dh_prime_len;
27539beb93cSSam Leffler };
27639beb93cSSam Leffler 
27739beb93cSSam Leffler 
tls_context_new(const struct tls_config * conf)2785b9c547cSRui Paulo static struct tls_context * tls_context_new(const struct tls_config *conf)
2795b9c547cSRui Paulo {
2805b9c547cSRui Paulo 	struct tls_context *context = os_zalloc(sizeof(*context));
2815b9c547cSRui Paulo 	if (context == NULL)
2825b9c547cSRui Paulo 		return NULL;
2835b9c547cSRui Paulo 	if (conf) {
2845b9c547cSRui Paulo 		context->event_cb = conf->event_cb;
2855b9c547cSRui Paulo 		context->cb_ctx = conf->cb_ctx;
2865b9c547cSRui Paulo 		context->cert_in_cb = conf->cert_in_cb;
2875b9c547cSRui Paulo 	}
2885b9c547cSRui Paulo 	return context;
2895b9c547cSRui Paulo }
2905b9c547cSRui Paulo 
2915b9c547cSRui Paulo 
29239beb93cSSam Leffler #ifdef CONFIG_NO_STDOUT_DEBUG
29339beb93cSSam Leffler 
_tls_show_errors(void)29439beb93cSSam Leffler static void _tls_show_errors(void)
29539beb93cSSam Leffler {
29639beb93cSSam Leffler 	unsigned long err;
29739beb93cSSam Leffler 
29839beb93cSSam Leffler 	while ((err = ERR_get_error())) {
29939beb93cSSam Leffler 		/* Just ignore the errors, since stdout is disabled */
30039beb93cSSam Leffler 	}
30139beb93cSSam Leffler }
30239beb93cSSam Leffler #define tls_show_errors(l, f, t) _tls_show_errors()
30339beb93cSSam Leffler 
30439beb93cSSam Leffler #else /* CONFIG_NO_STDOUT_DEBUG */
30539beb93cSSam Leffler 
tls_show_errors(int level,const char * func,const char * txt)30639beb93cSSam Leffler static void tls_show_errors(int level, const char *func, const char *txt)
30739beb93cSSam Leffler {
30839beb93cSSam Leffler 	unsigned long err;
30939beb93cSSam Leffler 
31039beb93cSSam Leffler 	wpa_printf(level, "OpenSSL: %s - %s %s",
31139beb93cSSam Leffler 		   func, txt, ERR_error_string(ERR_get_error(), NULL));
31239beb93cSSam Leffler 
31339beb93cSSam Leffler 	while ((err = ERR_get_error())) {
31439beb93cSSam Leffler 		wpa_printf(MSG_INFO, "OpenSSL: pending error: %s",
31539beb93cSSam Leffler 			   ERR_error_string(err, NULL));
31639beb93cSSam Leffler 	}
31739beb93cSSam Leffler }
31839beb93cSSam Leffler 
31939beb93cSSam Leffler #endif /* CONFIG_NO_STDOUT_DEBUG */
32039beb93cSSam Leffler 
32139beb93cSSam Leffler 
tls_crl_cert_reload(const char * ca_cert,int check_crl)3224bc52338SCy Schubert static X509_STORE * tls_crl_cert_reload(const char *ca_cert, int check_crl)
3234bc52338SCy Schubert {
3244bc52338SCy Schubert 	int flags;
3254bc52338SCy Schubert 	X509_STORE *store;
3264bc52338SCy Schubert 
3274bc52338SCy Schubert 	store = X509_STORE_new();
3284bc52338SCy Schubert 	if (!store) {
3294bc52338SCy Schubert 		wpa_printf(MSG_DEBUG,
3304bc52338SCy Schubert 			   "OpenSSL: %s - failed to allocate new certificate store",
3314bc52338SCy Schubert 			   __func__);
3324bc52338SCy Schubert 		return NULL;
3334bc52338SCy Schubert 	}
3344bc52338SCy Schubert 
3354bc52338SCy Schubert 	if (ca_cert && X509_STORE_load_locations(store, ca_cert, NULL) != 1) {
3364bc52338SCy Schubert 		tls_show_errors(MSG_WARNING, __func__,
3374bc52338SCy Schubert 				"Failed to load root certificates");
3384bc52338SCy Schubert 		X509_STORE_free(store);
3394bc52338SCy Schubert 		return NULL;
3404bc52338SCy Schubert 	}
3414bc52338SCy Schubert 
3424bc52338SCy Schubert 	flags = check_crl ? X509_V_FLAG_CRL_CHECK : 0;
3434bc52338SCy Schubert 	if (check_crl == 2)
3444bc52338SCy Schubert 		flags |= X509_V_FLAG_CRL_CHECK_ALL;
3454bc52338SCy Schubert 
3464bc52338SCy Schubert 	X509_STORE_set_flags(store, flags);
3474bc52338SCy Schubert 
3484bc52338SCy Schubert 	return store;
3494bc52338SCy Schubert }
3504bc52338SCy Schubert 
3514bc52338SCy Schubert 
35239beb93cSSam Leffler #ifdef CONFIG_NATIVE_WINDOWS
35339beb93cSSam Leffler 
35439beb93cSSam Leffler /* Windows CryptoAPI and access to certificate stores */
35539beb93cSSam Leffler #include <wincrypt.h>
35639beb93cSSam Leffler 
35739beb93cSSam Leffler #ifdef __MINGW32_VERSION
35839beb93cSSam Leffler /*
35939beb93cSSam Leffler  * MinGW does not yet include all the needed definitions for CryptoAPI, so
36039beb93cSSam Leffler  * define here whatever extra is needed.
36139beb93cSSam Leffler  */
36239beb93cSSam Leffler #define CERT_SYSTEM_STORE_CURRENT_USER (1 << 16)
36339beb93cSSam Leffler #define CERT_STORE_READONLY_FLAG 0x00008000
36439beb93cSSam Leffler #define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000
36539beb93cSSam Leffler 
36639beb93cSSam Leffler #endif /* __MINGW32_VERSION */
36739beb93cSSam Leffler 
36839beb93cSSam Leffler 
36939beb93cSSam Leffler struct cryptoapi_rsa_data {
37039beb93cSSam Leffler 	const CERT_CONTEXT *cert;
37139beb93cSSam Leffler 	HCRYPTPROV crypt_prov;
37239beb93cSSam Leffler 	DWORD key_spec;
37339beb93cSSam Leffler 	BOOL free_crypt_prov;
37439beb93cSSam Leffler };
37539beb93cSSam Leffler 
37639beb93cSSam Leffler 
cryptoapi_error(const char * msg)37739beb93cSSam Leffler static void cryptoapi_error(const char *msg)
37839beb93cSSam Leffler {
37939beb93cSSam Leffler 	wpa_printf(MSG_INFO, "CryptoAPI: %s; err=%u",
38039beb93cSSam Leffler 		   msg, (unsigned int) GetLastError());
38139beb93cSSam Leffler }
38239beb93cSSam Leffler 
38339beb93cSSam Leffler 
cryptoapi_rsa_pub_enc(int flen,const unsigned char * from,unsigned char * to,RSA * rsa,int padding)38439beb93cSSam Leffler static int cryptoapi_rsa_pub_enc(int flen, const unsigned char *from,
38539beb93cSSam Leffler 				 unsigned char *to, RSA *rsa, int padding)
38639beb93cSSam Leffler {
38739beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);
38839beb93cSSam Leffler 	return 0;
38939beb93cSSam Leffler }
39039beb93cSSam Leffler 
39139beb93cSSam Leffler 
cryptoapi_rsa_pub_dec(int flen,const unsigned char * from,unsigned char * to,RSA * rsa,int padding)39239beb93cSSam Leffler static int cryptoapi_rsa_pub_dec(int flen, const unsigned char *from,
39339beb93cSSam Leffler 				 unsigned char *to, RSA *rsa, int padding)
39439beb93cSSam Leffler {
39539beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);
39639beb93cSSam Leffler 	return 0;
39739beb93cSSam Leffler }
39839beb93cSSam Leffler 
39939beb93cSSam Leffler 
cryptoapi_rsa_priv_enc(int flen,const unsigned char * from,unsigned char * to,RSA * rsa,int padding)40039beb93cSSam Leffler static int cryptoapi_rsa_priv_enc(int flen, const unsigned char *from,
40139beb93cSSam Leffler 				  unsigned char *to, RSA *rsa, int padding)
40239beb93cSSam Leffler {
40339beb93cSSam Leffler 	struct cryptoapi_rsa_data *priv =
40439beb93cSSam Leffler 		(struct cryptoapi_rsa_data *) rsa->meth->app_data;
40539beb93cSSam Leffler 	HCRYPTHASH hash;
40639beb93cSSam Leffler 	DWORD hash_size, len, i;
40739beb93cSSam Leffler 	unsigned char *buf = NULL;
40839beb93cSSam Leffler 	int ret = 0;
40939beb93cSSam Leffler 
41039beb93cSSam Leffler 	if (priv == NULL) {
41139beb93cSSam Leffler 		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
41239beb93cSSam Leffler 		       ERR_R_PASSED_NULL_PARAMETER);
41339beb93cSSam Leffler 		return 0;
41439beb93cSSam Leffler 	}
41539beb93cSSam Leffler 
41639beb93cSSam Leffler 	if (padding != RSA_PKCS1_PADDING) {
41739beb93cSSam Leffler 		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
41839beb93cSSam Leffler 		       RSA_R_UNKNOWN_PADDING_TYPE);
41939beb93cSSam Leffler 		return 0;
42039beb93cSSam Leffler 	}
42139beb93cSSam Leffler 
42239beb93cSSam Leffler 	if (flen != 16 /* MD5 */ + 20 /* SHA-1 */) {
42339beb93cSSam Leffler 		wpa_printf(MSG_INFO, "%s - only MD5-SHA1 hash supported",
42439beb93cSSam Leffler 			   __func__);
42539beb93cSSam Leffler 		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
42639beb93cSSam Leffler 		       RSA_R_INVALID_MESSAGE_LENGTH);
42739beb93cSSam Leffler 		return 0;
42839beb93cSSam Leffler 	}
42939beb93cSSam Leffler 
43039beb93cSSam Leffler 	if (!CryptCreateHash(priv->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash))
43139beb93cSSam Leffler 	{
43239beb93cSSam Leffler 		cryptoapi_error("CryptCreateHash failed");
43339beb93cSSam Leffler 		return 0;
43439beb93cSSam Leffler 	}
43539beb93cSSam Leffler 
43639beb93cSSam Leffler 	len = sizeof(hash_size);
43739beb93cSSam Leffler 	if (!CryptGetHashParam(hash, HP_HASHSIZE, (BYTE *) &hash_size, &len,
43839beb93cSSam Leffler 			       0)) {
43939beb93cSSam Leffler 		cryptoapi_error("CryptGetHashParam failed");
44039beb93cSSam Leffler 		goto err;
44139beb93cSSam Leffler 	}
44239beb93cSSam Leffler 
44339beb93cSSam Leffler 	if ((int) hash_size != flen) {
44439beb93cSSam Leffler 		wpa_printf(MSG_INFO, "CryptoAPI: Invalid hash size (%u != %d)",
44539beb93cSSam Leffler 			   (unsigned) hash_size, flen);
44639beb93cSSam Leffler 		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
44739beb93cSSam Leffler 		       RSA_R_INVALID_MESSAGE_LENGTH);
44839beb93cSSam Leffler 		goto err;
44939beb93cSSam Leffler 	}
45039beb93cSSam Leffler 	if (!CryptSetHashParam(hash, HP_HASHVAL, (BYTE * ) from, 0)) {
45139beb93cSSam Leffler 		cryptoapi_error("CryptSetHashParam failed");
45239beb93cSSam Leffler 		goto err;
45339beb93cSSam Leffler 	}
45439beb93cSSam Leffler 
45539beb93cSSam Leffler 	len = RSA_size(rsa);
45639beb93cSSam Leffler 	buf = os_malloc(len);
45739beb93cSSam Leffler 	if (buf == NULL) {
45839beb93cSSam Leffler 		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
45939beb93cSSam Leffler 		goto err;
46039beb93cSSam Leffler 	}
46139beb93cSSam Leffler 
46239beb93cSSam Leffler 	if (!CryptSignHash(hash, priv->key_spec, NULL, 0, buf, &len)) {
46339beb93cSSam Leffler 		cryptoapi_error("CryptSignHash failed");
46439beb93cSSam Leffler 		goto err;
46539beb93cSSam Leffler 	}
46639beb93cSSam Leffler 
46739beb93cSSam Leffler 	for (i = 0; i < len; i++)
46839beb93cSSam Leffler 		to[i] = buf[len - i - 1];
46939beb93cSSam Leffler 	ret = len;
47039beb93cSSam Leffler 
47139beb93cSSam Leffler err:
47239beb93cSSam Leffler 	os_free(buf);
47339beb93cSSam Leffler 	CryptDestroyHash(hash);
47439beb93cSSam Leffler 
47539beb93cSSam Leffler 	return ret;
47639beb93cSSam Leffler }
47739beb93cSSam Leffler 
47839beb93cSSam Leffler 
cryptoapi_rsa_priv_dec(int flen,const unsigned char * from,unsigned char * to,RSA * rsa,int padding)47939beb93cSSam Leffler static int cryptoapi_rsa_priv_dec(int flen, const unsigned char *from,
48039beb93cSSam Leffler 				  unsigned char *to, RSA *rsa, int padding)
48139beb93cSSam Leffler {
48239beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);
48339beb93cSSam Leffler 	return 0;
48439beb93cSSam Leffler }
48539beb93cSSam Leffler 
48639beb93cSSam Leffler 
cryptoapi_free_data(struct cryptoapi_rsa_data * priv)48739beb93cSSam Leffler static void cryptoapi_free_data(struct cryptoapi_rsa_data *priv)
48839beb93cSSam Leffler {
48939beb93cSSam Leffler 	if (priv == NULL)
49039beb93cSSam Leffler 		return;
49139beb93cSSam Leffler 	if (priv->crypt_prov && priv->free_crypt_prov)
49239beb93cSSam Leffler 		CryptReleaseContext(priv->crypt_prov, 0);
49339beb93cSSam Leffler 	if (priv->cert)
49439beb93cSSam Leffler 		CertFreeCertificateContext(priv->cert);
49539beb93cSSam Leffler 	os_free(priv);
49639beb93cSSam Leffler }
49739beb93cSSam Leffler 
49839beb93cSSam Leffler 
cryptoapi_finish(RSA * rsa)49939beb93cSSam Leffler static int cryptoapi_finish(RSA *rsa)
50039beb93cSSam Leffler {
50139beb93cSSam Leffler 	cryptoapi_free_data((struct cryptoapi_rsa_data *) rsa->meth->app_data);
50239beb93cSSam Leffler 	os_free((void *) rsa->meth);
50339beb93cSSam Leffler 	rsa->meth = NULL;
50439beb93cSSam Leffler 	return 1;
50539beb93cSSam Leffler }
50639beb93cSSam Leffler 
50739beb93cSSam Leffler 
cryptoapi_find_cert(const char * name,DWORD store)50839beb93cSSam Leffler static const CERT_CONTEXT * cryptoapi_find_cert(const char *name, DWORD store)
50939beb93cSSam Leffler {
51039beb93cSSam Leffler 	HCERTSTORE cs;
51139beb93cSSam Leffler 	const CERT_CONTEXT *ret = NULL;
51239beb93cSSam Leffler 
51339beb93cSSam Leffler 	cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0,
51439beb93cSSam Leffler 			   store | CERT_STORE_OPEN_EXISTING_FLAG |
51539beb93cSSam Leffler 			   CERT_STORE_READONLY_FLAG, L"MY");
51639beb93cSSam Leffler 	if (cs == NULL) {
51739beb93cSSam Leffler 		cryptoapi_error("Failed to open 'My system store'");
51839beb93cSSam Leffler 		return NULL;
51939beb93cSSam Leffler 	}
52039beb93cSSam Leffler 
52139beb93cSSam Leffler 	if (strncmp(name, "cert://", 7) == 0) {
52239beb93cSSam Leffler 		unsigned short wbuf[255];
52339beb93cSSam Leffler 		MultiByteToWideChar(CP_ACP, 0, name + 7, -1, wbuf, 255);
52439beb93cSSam Leffler 		ret = CertFindCertificateInStore(cs, X509_ASN_ENCODING |
52539beb93cSSam Leffler 						 PKCS_7_ASN_ENCODING,
52639beb93cSSam Leffler 						 0, CERT_FIND_SUBJECT_STR,
52739beb93cSSam Leffler 						 wbuf, NULL);
52839beb93cSSam Leffler 	} else if (strncmp(name, "hash://", 7) == 0) {
52939beb93cSSam Leffler 		CRYPT_HASH_BLOB blob;
53039beb93cSSam Leffler 		int len;
53139beb93cSSam Leffler 		const char *hash = name + 7;
53239beb93cSSam Leffler 		unsigned char *buf;
53339beb93cSSam Leffler 
53439beb93cSSam Leffler 		len = os_strlen(hash) / 2;
53539beb93cSSam Leffler 		buf = os_malloc(len);
53639beb93cSSam Leffler 		if (buf && hexstr2bin(hash, buf, len) == 0) {
53739beb93cSSam Leffler 			blob.cbData = len;
53839beb93cSSam Leffler 			blob.pbData = buf;
53939beb93cSSam Leffler 			ret = CertFindCertificateInStore(cs,
54039beb93cSSam Leffler 							 X509_ASN_ENCODING |
54139beb93cSSam Leffler 							 PKCS_7_ASN_ENCODING,
54239beb93cSSam Leffler 							 0, CERT_FIND_HASH,
54339beb93cSSam Leffler 							 &blob, NULL);
54439beb93cSSam Leffler 		}
54539beb93cSSam Leffler 		os_free(buf);
54639beb93cSSam Leffler 	}
54739beb93cSSam Leffler 
54839beb93cSSam Leffler 	CertCloseStore(cs, 0);
54939beb93cSSam Leffler 
55039beb93cSSam Leffler 	return ret;
55139beb93cSSam Leffler }
55239beb93cSSam Leffler 
55339beb93cSSam Leffler 
tls_cryptoapi_cert(SSL * ssl,const char * name)55439beb93cSSam Leffler static int tls_cryptoapi_cert(SSL *ssl, const char *name)
55539beb93cSSam Leffler {
55639beb93cSSam Leffler 	X509 *cert = NULL;
55739beb93cSSam Leffler 	RSA *rsa = NULL, *pub_rsa;
55839beb93cSSam Leffler 	struct cryptoapi_rsa_data *priv;
55939beb93cSSam Leffler 	RSA_METHOD *rsa_meth;
56039beb93cSSam Leffler 
56139beb93cSSam Leffler 	if (name == NULL ||
56239beb93cSSam Leffler 	    (strncmp(name, "cert://", 7) != 0 &&
56339beb93cSSam Leffler 	     strncmp(name, "hash://", 7) != 0))
56439beb93cSSam Leffler 		return -1;
56539beb93cSSam Leffler 
56639beb93cSSam Leffler 	priv = os_zalloc(sizeof(*priv));
56739beb93cSSam Leffler 	rsa_meth = os_zalloc(sizeof(*rsa_meth));
56839beb93cSSam Leffler 	if (priv == NULL || rsa_meth == NULL) {
56939beb93cSSam Leffler 		wpa_printf(MSG_WARNING, "CryptoAPI: Failed to allocate memory "
57039beb93cSSam Leffler 			   "for CryptoAPI RSA method");
57139beb93cSSam Leffler 		os_free(priv);
57239beb93cSSam Leffler 		os_free(rsa_meth);
57339beb93cSSam Leffler 		return -1;
57439beb93cSSam Leffler 	}
57539beb93cSSam Leffler 
57639beb93cSSam Leffler 	priv->cert = cryptoapi_find_cert(name, CERT_SYSTEM_STORE_CURRENT_USER);
57739beb93cSSam Leffler 	if (priv->cert == NULL) {
57839beb93cSSam Leffler 		priv->cert = cryptoapi_find_cert(
57939beb93cSSam Leffler 			name, CERT_SYSTEM_STORE_LOCAL_MACHINE);
58039beb93cSSam Leffler 	}
58139beb93cSSam Leffler 	if (priv->cert == NULL) {
58239beb93cSSam Leffler 		wpa_printf(MSG_INFO, "CryptoAPI: Could not find certificate "
58339beb93cSSam Leffler 			   "'%s'", name);
58439beb93cSSam Leffler 		goto err;
58539beb93cSSam Leffler 	}
58639beb93cSSam Leffler 
5875b9c547cSRui Paulo 	cert = d2i_X509(NULL,
5885b9c547cSRui Paulo 			(const unsigned char **) &priv->cert->pbCertEncoded,
58939beb93cSSam Leffler 			priv->cert->cbCertEncoded);
59039beb93cSSam Leffler 	if (cert == NULL) {
59139beb93cSSam Leffler 		wpa_printf(MSG_INFO, "CryptoAPI: Could not process X509 DER "
59239beb93cSSam Leffler 			   "encoding");
59339beb93cSSam Leffler 		goto err;
59439beb93cSSam Leffler 	}
59539beb93cSSam Leffler 
59639beb93cSSam Leffler 	if (!CryptAcquireCertificatePrivateKey(priv->cert,
59739beb93cSSam Leffler 					       CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
59839beb93cSSam Leffler 					       NULL, &priv->crypt_prov,
59939beb93cSSam Leffler 					       &priv->key_spec,
60039beb93cSSam Leffler 					       &priv->free_crypt_prov)) {
60139beb93cSSam Leffler 		cryptoapi_error("Failed to acquire a private key for the "
60239beb93cSSam Leffler 				"certificate");
60339beb93cSSam Leffler 		goto err;
60439beb93cSSam Leffler 	}
60539beb93cSSam Leffler 
60639beb93cSSam Leffler 	rsa_meth->name = "Microsoft CryptoAPI RSA Method";
60739beb93cSSam Leffler 	rsa_meth->rsa_pub_enc = cryptoapi_rsa_pub_enc;
60839beb93cSSam Leffler 	rsa_meth->rsa_pub_dec = cryptoapi_rsa_pub_dec;
60939beb93cSSam Leffler 	rsa_meth->rsa_priv_enc = cryptoapi_rsa_priv_enc;
61039beb93cSSam Leffler 	rsa_meth->rsa_priv_dec = cryptoapi_rsa_priv_dec;
61139beb93cSSam Leffler 	rsa_meth->finish = cryptoapi_finish;
61239beb93cSSam Leffler 	rsa_meth->flags = RSA_METHOD_FLAG_NO_CHECK;
61339beb93cSSam Leffler 	rsa_meth->app_data = (char *) priv;
61439beb93cSSam Leffler 
61539beb93cSSam Leffler 	rsa = RSA_new();
61639beb93cSSam Leffler 	if (rsa == NULL) {
61739beb93cSSam Leffler 		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,
61839beb93cSSam Leffler 		       ERR_R_MALLOC_FAILURE);
61939beb93cSSam Leffler 		goto err;
62039beb93cSSam Leffler 	}
62139beb93cSSam Leffler 
62239beb93cSSam Leffler 	if (!SSL_use_certificate(ssl, cert)) {
62339beb93cSSam Leffler 		RSA_free(rsa);
62439beb93cSSam Leffler 		rsa = NULL;
62539beb93cSSam Leffler 		goto err;
62639beb93cSSam Leffler 	}
62739beb93cSSam Leffler 	pub_rsa = cert->cert_info->key->pkey->pkey.rsa;
62839beb93cSSam Leffler 	X509_free(cert);
62939beb93cSSam Leffler 	cert = NULL;
63039beb93cSSam Leffler 
63139beb93cSSam Leffler 	rsa->n = BN_dup(pub_rsa->n);
63239beb93cSSam Leffler 	rsa->e = BN_dup(pub_rsa->e);
63339beb93cSSam Leffler 	if (!RSA_set_method(rsa, rsa_meth))
63439beb93cSSam Leffler 		goto err;
63539beb93cSSam Leffler 
63639beb93cSSam Leffler 	if (!SSL_use_RSAPrivateKey(ssl, rsa))
63739beb93cSSam Leffler 		goto err;
63839beb93cSSam Leffler 	RSA_free(rsa);
63939beb93cSSam Leffler 
64039beb93cSSam Leffler 	return 0;
64139beb93cSSam Leffler 
64239beb93cSSam Leffler err:
64339beb93cSSam Leffler 	if (cert)
64439beb93cSSam Leffler 		X509_free(cert);
64539beb93cSSam Leffler 	if (rsa)
64639beb93cSSam Leffler 		RSA_free(rsa);
64739beb93cSSam Leffler 	else {
64839beb93cSSam Leffler 		os_free(rsa_meth);
64939beb93cSSam Leffler 		cryptoapi_free_data(priv);
65039beb93cSSam Leffler 	}
65139beb93cSSam Leffler 	return -1;
65239beb93cSSam Leffler }
65339beb93cSSam Leffler 
65439beb93cSSam Leffler 
tls_cryptoapi_ca_cert(SSL_CTX * ssl_ctx,SSL * ssl,const char * name)65539beb93cSSam Leffler static int tls_cryptoapi_ca_cert(SSL_CTX *ssl_ctx, SSL *ssl, const char *name)
65639beb93cSSam Leffler {
65739beb93cSSam Leffler 	HCERTSTORE cs;
65839beb93cSSam Leffler 	PCCERT_CONTEXT ctx = NULL;
65939beb93cSSam Leffler 	X509 *cert;
66039beb93cSSam Leffler 	char buf[128];
66139beb93cSSam Leffler 	const char *store;
66239beb93cSSam Leffler #ifdef UNICODE
66339beb93cSSam Leffler 	WCHAR *wstore;
66439beb93cSSam Leffler #endif /* UNICODE */
66539beb93cSSam Leffler 
66639beb93cSSam Leffler 	if (name == NULL || strncmp(name, "cert_store://", 13) != 0)
66739beb93cSSam Leffler 		return -1;
66839beb93cSSam Leffler 
66939beb93cSSam Leffler 	store = name + 13;
67039beb93cSSam Leffler #ifdef UNICODE
67139beb93cSSam Leffler 	wstore = os_malloc((os_strlen(store) + 1) * sizeof(WCHAR));
67239beb93cSSam Leffler 	if (wstore == NULL)
67339beb93cSSam Leffler 		return -1;
67439beb93cSSam Leffler 	wsprintf(wstore, L"%S", store);
67539beb93cSSam Leffler 	cs = CertOpenSystemStore(0, wstore);
67639beb93cSSam Leffler 	os_free(wstore);
67739beb93cSSam Leffler #else /* UNICODE */
67839beb93cSSam Leffler 	cs = CertOpenSystemStore(0, store);
67939beb93cSSam Leffler #endif /* UNICODE */
68039beb93cSSam Leffler 	if (cs == NULL) {
68139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "%s: failed to open system cert store "
68239beb93cSSam Leffler 			   "'%s': error=%d", __func__, store,
68339beb93cSSam Leffler 			   (int) GetLastError());
68439beb93cSSam Leffler 		return -1;
68539beb93cSSam Leffler 	}
68639beb93cSSam Leffler 
68739beb93cSSam Leffler 	while ((ctx = CertEnumCertificatesInStore(cs, ctx))) {
6885b9c547cSRui Paulo 		cert = d2i_X509(NULL,
6895b9c547cSRui Paulo 				(const unsigned char **) &ctx->pbCertEncoded,
69039beb93cSSam Leffler 				ctx->cbCertEncoded);
69139beb93cSSam Leffler 		if (cert == NULL) {
69239beb93cSSam Leffler 			wpa_printf(MSG_INFO, "CryptoAPI: Could not process "
69339beb93cSSam Leffler 				   "X509 DER encoding for CA cert");
69439beb93cSSam Leffler 			continue;
69539beb93cSSam Leffler 		}
69639beb93cSSam Leffler 
69739beb93cSSam Leffler 		X509_NAME_oneline(X509_get_subject_name(cert), buf,
69839beb93cSSam Leffler 				  sizeof(buf));
69939beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "OpenSSL: Loaded CA certificate for "
70039beb93cSSam Leffler 			   "system certificate store: subject='%s'", buf);
70139beb93cSSam Leffler 
702780fb4a2SCy Schubert 		if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(ssl_ctx),
703780fb4a2SCy Schubert 					 cert)) {
70439beb93cSSam Leffler 			tls_show_errors(MSG_WARNING, __func__,
70539beb93cSSam Leffler 					"Failed to add ca_cert to OpenSSL "
70639beb93cSSam Leffler 					"certificate store");
70739beb93cSSam Leffler 		}
70839beb93cSSam Leffler 
70939beb93cSSam Leffler 		X509_free(cert);
71039beb93cSSam Leffler 	}
71139beb93cSSam Leffler 
71239beb93cSSam Leffler 	if (!CertCloseStore(cs, 0)) {
71339beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "%s: failed to close system cert store "
71439beb93cSSam Leffler 			   "'%s': error=%d", __func__, name + 13,
71539beb93cSSam Leffler 			   (int) GetLastError());
71639beb93cSSam Leffler 	}
71739beb93cSSam Leffler 
71839beb93cSSam Leffler 	return 0;
71939beb93cSSam Leffler }
72039beb93cSSam Leffler 
72139beb93cSSam Leffler 
72239beb93cSSam Leffler #else /* CONFIG_NATIVE_WINDOWS */
72339beb93cSSam Leffler 
tls_cryptoapi_cert(SSL * ssl,const char * name)72439beb93cSSam Leffler static int tls_cryptoapi_cert(SSL *ssl, const char *name)
72539beb93cSSam Leffler {
72639beb93cSSam Leffler 	return -1;
72739beb93cSSam Leffler }
72839beb93cSSam Leffler 
72939beb93cSSam Leffler #endif /* CONFIG_NATIVE_WINDOWS */
73039beb93cSSam Leffler 
73139beb93cSSam Leffler 
ssl_info_cb(const SSL * ssl,int where,int ret)73239beb93cSSam Leffler static void ssl_info_cb(const SSL *ssl, int where, int ret)
73339beb93cSSam Leffler {
73439beb93cSSam Leffler 	const char *str;
73539beb93cSSam Leffler 	int w;
73639beb93cSSam Leffler 
73739beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "SSL: (where=0x%x ret=0x%x)", where, ret);
73839beb93cSSam Leffler 	w = where & ~SSL_ST_MASK;
73939beb93cSSam Leffler 	if (w & SSL_ST_CONNECT)
74039beb93cSSam Leffler 		str = "SSL_connect";
74139beb93cSSam Leffler 	else if (w & SSL_ST_ACCEPT)
74239beb93cSSam Leffler 		str = "SSL_accept";
74339beb93cSSam Leffler 	else
74439beb93cSSam Leffler 		str = "undefined";
74539beb93cSSam Leffler 
74639beb93cSSam Leffler 	if (where & SSL_CB_LOOP) {
74739beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "SSL: %s:%s",
74839beb93cSSam Leffler 			   str, SSL_state_string_long(ssl));
74939beb93cSSam Leffler 	} else if (where & SSL_CB_ALERT) {
7505b9c547cSRui Paulo 		struct tls_connection *conn = SSL_get_app_data((SSL *) ssl);
75139beb93cSSam Leffler 		wpa_printf(MSG_INFO, "SSL: SSL3 alert: %s:%s:%s",
75239beb93cSSam Leffler 			   where & SSL_CB_READ ?
75339beb93cSSam Leffler 			   "read (remote end reported an error)" :
75439beb93cSSam Leffler 			   "write (local SSL3 detected an error)",
75539beb93cSSam Leffler 			   SSL_alert_type_string_long(ret),
75639beb93cSSam Leffler 			   SSL_alert_desc_string_long(ret));
75739beb93cSSam Leffler 		if ((ret >> 8) == SSL3_AL_FATAL) {
75839beb93cSSam Leffler 			if (where & SSL_CB_READ)
75939beb93cSSam Leffler 				conn->read_alerts++;
76039beb93cSSam Leffler 			else
76139beb93cSSam Leffler 				conn->write_alerts++;
76239beb93cSSam Leffler 		}
7635b9c547cSRui Paulo 		if (conn->context->event_cb != NULL) {
764f05cddf9SRui Paulo 			union tls_event_data ev;
7655b9c547cSRui Paulo 			struct tls_context *context = conn->context;
766f05cddf9SRui Paulo 			os_memset(&ev, 0, sizeof(ev));
767f05cddf9SRui Paulo 			ev.alert.is_local = !(where & SSL_CB_READ);
768f05cddf9SRui Paulo 			ev.alert.type = SSL_alert_type_string_long(ret);
769f05cddf9SRui Paulo 			ev.alert.description = SSL_alert_desc_string_long(ret);
7705b9c547cSRui Paulo 			context->event_cb(context->cb_ctx, TLS_ALERT, &ev);
771f05cddf9SRui Paulo 		}
77239beb93cSSam Leffler 	} else if (where & SSL_CB_EXIT && ret <= 0) {
77339beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s",
77439beb93cSSam Leffler 			   str, ret == 0 ? "failed" : "error",
77539beb93cSSam Leffler 			   SSL_state_string_long(ssl));
77639beb93cSSam Leffler 	}
77739beb93cSSam Leffler }
77839beb93cSSam Leffler 
77939beb93cSSam Leffler 
78039beb93cSSam Leffler #ifndef OPENSSL_NO_ENGINE
78139beb93cSSam Leffler /**
78239beb93cSSam Leffler  * tls_engine_load_dynamic_generic - load any openssl engine
78339beb93cSSam Leffler  * @pre: an array of commands and values that load an engine initialized
78439beb93cSSam Leffler  *       in the engine specific function
78539beb93cSSam Leffler  * @post: an array of commands and values that initialize an already loaded
78639beb93cSSam Leffler  *        engine (or %NULL if not required)
78739beb93cSSam Leffler  * @id: the engine id of the engine to load (only required if post is not %NULL
78839beb93cSSam Leffler  *
78939beb93cSSam Leffler  * This function is a generic function that loads any openssl engine.
79039beb93cSSam Leffler  *
79139beb93cSSam Leffler  * Returns: 0 on success, -1 on failure
79239beb93cSSam Leffler  */
tls_engine_load_dynamic_generic(const char * pre[],const char * post[],const char * id)79339beb93cSSam Leffler static int tls_engine_load_dynamic_generic(const char *pre[],
79439beb93cSSam Leffler 					   const char *post[], const char *id)
79539beb93cSSam Leffler {
79639beb93cSSam Leffler 	ENGINE *engine;
79739beb93cSSam Leffler 	const char *dynamic_id = "dynamic";
79839beb93cSSam Leffler 
79939beb93cSSam Leffler 	engine = ENGINE_by_id(id);
80039beb93cSSam Leffler 	if (engine) {
80139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "ENGINE: engine '%s' is already "
80239beb93cSSam Leffler 			   "available", id);
803780fb4a2SCy Schubert 		/*
804780fb4a2SCy Schubert 		 * If it was auto-loaded by ENGINE_by_id() we might still
805780fb4a2SCy Schubert 		 * need to tell it which PKCS#11 module to use in legacy
806780fb4a2SCy Schubert 		 * (non-p11-kit) environments. Do so now; even if it was
807780fb4a2SCy Schubert 		 * properly initialised before, setting it again will be
808780fb4a2SCy Schubert 		 * harmless.
809780fb4a2SCy Schubert 		 */
810780fb4a2SCy Schubert 		goto found;
81139beb93cSSam Leffler 	}
81239beb93cSSam Leffler 	ERR_clear_error();
81339beb93cSSam Leffler 
81439beb93cSSam Leffler 	engine = ENGINE_by_id(dynamic_id);
81539beb93cSSam Leffler 	if (engine == NULL) {
81639beb93cSSam Leffler 		wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]",
81739beb93cSSam Leffler 			   dynamic_id,
81839beb93cSSam Leffler 			   ERR_error_string(ERR_get_error(), NULL));
81939beb93cSSam Leffler 		return -1;
82039beb93cSSam Leffler 	}
82139beb93cSSam Leffler 
82239beb93cSSam Leffler 	/* Perform the pre commands. This will load the engine. */
82339beb93cSSam Leffler 	while (pre && pre[0]) {
82439beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", pre[0], pre[1]);
82539beb93cSSam Leffler 		if (ENGINE_ctrl_cmd_string(engine, pre[0], pre[1], 0) == 0) {
82639beb93cSSam Leffler 			wpa_printf(MSG_INFO, "ENGINE: ctrl cmd_string failed: "
82739beb93cSSam Leffler 				   "%s %s [%s]", pre[0], pre[1],
82839beb93cSSam Leffler 				   ERR_error_string(ERR_get_error(), NULL));
82939beb93cSSam Leffler 			ENGINE_free(engine);
83039beb93cSSam Leffler 			return -1;
83139beb93cSSam Leffler 		}
83239beb93cSSam Leffler 		pre += 2;
83339beb93cSSam Leffler 	}
83439beb93cSSam Leffler 
83539beb93cSSam Leffler 	/*
83639beb93cSSam Leffler 	 * Free the reference to the "dynamic" engine. The loaded engine can
83739beb93cSSam Leffler 	 * now be looked up using ENGINE_by_id().
83839beb93cSSam Leffler 	 */
83939beb93cSSam Leffler 	ENGINE_free(engine);
84039beb93cSSam Leffler 
84139beb93cSSam Leffler 	engine = ENGINE_by_id(id);
84239beb93cSSam Leffler 	if (engine == NULL) {
84339beb93cSSam Leffler 		wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]",
84439beb93cSSam Leffler 			   id, ERR_error_string(ERR_get_error(), NULL));
84539beb93cSSam Leffler 		return -1;
84639beb93cSSam Leffler 	}
847780fb4a2SCy Schubert  found:
84839beb93cSSam Leffler 	while (post && post[0]) {
84939beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", post[0], post[1]);
85039beb93cSSam Leffler 		if (ENGINE_ctrl_cmd_string(engine, post[0], post[1], 0) == 0) {
85139beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "ENGINE: ctrl cmd_string failed:"
85239beb93cSSam Leffler 				" %s %s [%s]", post[0], post[1],
85339beb93cSSam Leffler 				   ERR_error_string(ERR_get_error(), NULL));
85439beb93cSSam Leffler 			ENGINE_remove(engine);
85539beb93cSSam Leffler 			ENGINE_free(engine);
85639beb93cSSam Leffler 			return -1;
85739beb93cSSam Leffler 		}
85839beb93cSSam Leffler 		post += 2;
85939beb93cSSam Leffler 	}
86039beb93cSSam Leffler 	ENGINE_free(engine);
86139beb93cSSam Leffler 
86239beb93cSSam Leffler 	return 0;
86339beb93cSSam Leffler }
86439beb93cSSam Leffler 
86539beb93cSSam Leffler 
86639beb93cSSam Leffler /**
86739beb93cSSam Leffler  * tls_engine_load_dynamic_pkcs11 - load the pkcs11 engine provided by opensc
86839beb93cSSam Leffler  * @pkcs11_so_path: pksc11_so_path from the configuration
86939beb93cSSam Leffler  * @pcks11_module_path: pkcs11_module_path from the configuration
87039beb93cSSam Leffler  */
tls_engine_load_dynamic_pkcs11(const char * pkcs11_so_path,const char * pkcs11_module_path)87139beb93cSSam Leffler static int tls_engine_load_dynamic_pkcs11(const char *pkcs11_so_path,
87239beb93cSSam Leffler 					  const char *pkcs11_module_path)
87339beb93cSSam Leffler {
87439beb93cSSam Leffler 	char *engine_id = "pkcs11";
87539beb93cSSam Leffler 	const char *pre_cmd[] = {
87639beb93cSSam Leffler 		"SO_PATH", NULL /* pkcs11_so_path */,
87739beb93cSSam Leffler 		"ID", NULL /* engine_id */,
87839beb93cSSam Leffler 		"LIST_ADD", "1",
87939beb93cSSam Leffler 		/* "NO_VCHECK", "1", */
88039beb93cSSam Leffler 		"LOAD", NULL,
88139beb93cSSam Leffler 		NULL, NULL
88239beb93cSSam Leffler 	};
88339beb93cSSam Leffler 	const char *post_cmd[] = {
88439beb93cSSam Leffler 		"MODULE_PATH", NULL /* pkcs11_module_path */,
88539beb93cSSam Leffler 		NULL, NULL
88639beb93cSSam Leffler 	};
88739beb93cSSam Leffler 
8885b9c547cSRui Paulo 	if (!pkcs11_so_path)
88939beb93cSSam Leffler 		return 0;
89039beb93cSSam Leffler 
89139beb93cSSam Leffler 	pre_cmd[1] = pkcs11_so_path;
89239beb93cSSam Leffler 	pre_cmd[3] = engine_id;
8935b9c547cSRui Paulo 	if (pkcs11_module_path)
89439beb93cSSam Leffler 		post_cmd[1] = pkcs11_module_path;
8955b9c547cSRui Paulo 	else
8965b9c547cSRui Paulo 		post_cmd[0] = NULL;
89739beb93cSSam Leffler 
89839beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "ENGINE: Loading pkcs11 Engine from %s",
89939beb93cSSam Leffler 		   pkcs11_so_path);
90039beb93cSSam Leffler 
90139beb93cSSam Leffler 	return tls_engine_load_dynamic_generic(pre_cmd, post_cmd, engine_id);
90239beb93cSSam Leffler }
90339beb93cSSam Leffler 
90439beb93cSSam Leffler 
90539beb93cSSam Leffler /**
90639beb93cSSam Leffler  * tls_engine_load_dynamic_opensc - load the opensc engine provided by opensc
90739beb93cSSam Leffler  * @opensc_so_path: opensc_so_path from the configuration
90839beb93cSSam Leffler  */
tls_engine_load_dynamic_opensc(const char * opensc_so_path)90939beb93cSSam Leffler static int tls_engine_load_dynamic_opensc(const char *opensc_so_path)
91039beb93cSSam Leffler {
91139beb93cSSam Leffler 	char *engine_id = "opensc";
91239beb93cSSam Leffler 	const char *pre_cmd[] = {
91339beb93cSSam Leffler 		"SO_PATH", NULL /* opensc_so_path */,
91439beb93cSSam Leffler 		"ID", NULL /* engine_id */,
91539beb93cSSam Leffler 		"LIST_ADD", "1",
91639beb93cSSam Leffler 		"LOAD", NULL,
91739beb93cSSam Leffler 		NULL, NULL
91839beb93cSSam Leffler 	};
91939beb93cSSam Leffler 
92039beb93cSSam Leffler 	if (!opensc_so_path)
92139beb93cSSam Leffler 		return 0;
92239beb93cSSam Leffler 
92339beb93cSSam Leffler 	pre_cmd[1] = opensc_so_path;
92439beb93cSSam Leffler 	pre_cmd[3] = engine_id;
92539beb93cSSam Leffler 
92639beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "ENGINE: Loading OpenSC Engine from %s",
92739beb93cSSam Leffler 		   opensc_so_path);
92839beb93cSSam Leffler 
92939beb93cSSam Leffler 	return tls_engine_load_dynamic_generic(pre_cmd, NULL, engine_id);
93039beb93cSSam Leffler }
93139beb93cSSam Leffler #endif /* OPENSSL_NO_ENGINE */
93239beb93cSSam Leffler 
93339beb93cSSam Leffler 
remove_session_cb(SSL_CTX * ctx,SSL_SESSION * sess)934325151a3SRui Paulo static void remove_session_cb(SSL_CTX *ctx, SSL_SESSION *sess)
935325151a3SRui Paulo {
936325151a3SRui Paulo 	struct wpabuf *buf;
937325151a3SRui Paulo 
938325151a3SRui Paulo 	if (tls_ex_idx_session < 0)
939325151a3SRui Paulo 		return;
940325151a3SRui Paulo 	buf = SSL_SESSION_get_ex_data(sess, tls_ex_idx_session);
941325151a3SRui Paulo 	if (!buf)
942325151a3SRui Paulo 		return;
943325151a3SRui Paulo 	wpa_printf(MSG_DEBUG,
944325151a3SRui Paulo 		   "OpenSSL: Free application session data %p (sess %p)",
945325151a3SRui Paulo 		   buf, sess);
946325151a3SRui Paulo 	wpabuf_free(buf);
947325151a3SRui Paulo 
948325151a3SRui Paulo 	SSL_SESSION_set_ex_data(sess, tls_ex_idx_session, NULL);
949325151a3SRui Paulo }
950325151a3SRui Paulo 
951325151a3SRui Paulo 
tls_init(const struct tls_config * conf)95239beb93cSSam Leffler void * tls_init(const struct tls_config *conf)
95339beb93cSSam Leffler {
954325151a3SRui Paulo 	struct tls_data *data;
95539beb93cSSam Leffler 	SSL_CTX *ssl;
9565b9c547cSRui Paulo 	struct tls_context *context;
9575b9c547cSRui Paulo 	const char *ciphers;
95839beb93cSSam Leffler 
95939beb93cSSam Leffler 	if (tls_openssl_ref_count == 0) {
960ec080394SCy Schubert 		void openssl_load_legacy_provider(void);
961ec080394SCy Schubert 
962ec080394SCy Schubert 		openssl_load_legacy_provider();
963ec080394SCy Schubert 
9645b9c547cSRui Paulo 		tls_global = context = tls_context_new(conf);
9655b9c547cSRui Paulo 		if (context == NULL)
966e28a4053SRui Paulo 			return NULL;
967e28a4053SRui Paulo #ifdef CONFIG_FIPS
968e28a4053SRui Paulo #ifdef OPENSSL_FIPS
969e28a4053SRui Paulo 		if (conf && conf->fips_mode) {
970325151a3SRui Paulo 			static int fips_enabled = 0;
971325151a3SRui Paulo 
972325151a3SRui Paulo 			if (!fips_enabled && !FIPS_mode_set(1)) {
973e28a4053SRui Paulo 				wpa_printf(MSG_ERROR, "Failed to enable FIPS "
974e28a4053SRui Paulo 					   "mode");
975e28a4053SRui Paulo 				ERR_load_crypto_strings();
976e28a4053SRui Paulo 				ERR_print_errors_fp(stderr);
977f05cddf9SRui Paulo 				os_free(tls_global);
978f05cddf9SRui Paulo 				tls_global = NULL;
979e28a4053SRui Paulo 				return NULL;
980325151a3SRui Paulo 			} else {
981e28a4053SRui Paulo 				wpa_printf(MSG_INFO, "Running in FIPS mode");
982325151a3SRui Paulo 				fips_enabled = 1;
983325151a3SRui Paulo 			}
984e28a4053SRui Paulo 		}
985e28a4053SRui Paulo #else /* OPENSSL_FIPS */
986e28a4053SRui Paulo 		if (conf && conf->fips_mode) {
987e28a4053SRui Paulo 			wpa_printf(MSG_ERROR, "FIPS mode requested, but not "
988e28a4053SRui Paulo 				   "supported");
989f05cddf9SRui Paulo 			os_free(tls_global);
990f05cddf9SRui Paulo 			tls_global = NULL;
991e28a4053SRui Paulo 			return NULL;
992e28a4053SRui Paulo 		}
993e28a4053SRui Paulo #endif /* OPENSSL_FIPS */
994e28a4053SRui Paulo #endif /* CONFIG_FIPS */
99585732ac8SCy Schubert #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
99685732ac8SCy Schubert 	(defined(LIBRESSL_VERSION_NUMBER) && \
99785732ac8SCy Schubert 	 LIBRESSL_VERSION_NUMBER < 0x20700000L)
99839beb93cSSam Leffler 		SSL_load_error_strings();
99939beb93cSSam Leffler 		SSL_library_init();
10005b9c547cSRui Paulo #ifndef OPENSSL_NO_SHA256
10013157ba21SRui Paulo 		EVP_add_digest(EVP_sha256());
10023157ba21SRui Paulo #endif /* OPENSSL_NO_SHA256 */
100339beb93cSSam Leffler 		/* TODO: if /dev/urandom is available, PRNG is seeded
100439beb93cSSam Leffler 		 * automatically. If this is not the case, random data should
100539beb93cSSam Leffler 		 * be added here. */
100639beb93cSSam Leffler 
100739beb93cSSam Leffler #ifdef PKCS12_FUNCS
10083157ba21SRui Paulo #ifndef OPENSSL_NO_RC2
10093157ba21SRui Paulo 		/*
10103157ba21SRui Paulo 		 * 40-bit RC2 is commonly used in PKCS#12 files, so enable it.
10113157ba21SRui Paulo 		 * This is enabled by PKCS12_PBE_add() in OpenSSL 0.9.8
10123157ba21SRui Paulo 		 * versions, but it looks like OpenSSL 1.0.0 does not do that
10133157ba21SRui Paulo 		 * anymore.
10143157ba21SRui Paulo 		 */
10153157ba21SRui Paulo 		EVP_add_cipher(EVP_rc2_40_cbc());
10163157ba21SRui Paulo #endif /* OPENSSL_NO_RC2 */
101739beb93cSSam Leffler 		PKCS12_PBE_add();
101839beb93cSSam Leffler #endif  /* PKCS12_FUNCS */
1019780fb4a2SCy Schubert #endif /* < 1.1.0 */
10205b9c547cSRui Paulo 	} else {
10215b9c547cSRui Paulo 		context = tls_context_new(conf);
10225b9c547cSRui Paulo 		if (context == NULL)
10235b9c547cSRui Paulo 			return NULL;
102439beb93cSSam Leffler 	}
102539beb93cSSam Leffler 	tls_openssl_ref_count++;
102639beb93cSSam Leffler 
1027325151a3SRui Paulo 	data = os_zalloc(sizeof(*data));
1028325151a3SRui Paulo 	if (data)
10295b9c547cSRui Paulo 		ssl = SSL_CTX_new(SSLv23_method());
1030325151a3SRui Paulo 	else
1031325151a3SRui Paulo 		ssl = NULL;
10325b9c547cSRui Paulo 	if (ssl == NULL) {
10335b9c547cSRui Paulo 		tls_openssl_ref_count--;
10345b9c547cSRui Paulo 		if (context != tls_global)
10355b9c547cSRui Paulo 			os_free(context);
10365b9c547cSRui Paulo 		if (tls_openssl_ref_count == 0) {
10375b9c547cSRui Paulo 			os_free(tls_global);
10385b9c547cSRui Paulo 			tls_global = NULL;
10395b9c547cSRui Paulo 		}
1040780fb4a2SCy Schubert 		os_free(data);
104139beb93cSSam Leffler 		return NULL;
10425b9c547cSRui Paulo 	}
1043325151a3SRui Paulo 	data->ssl = ssl;
10444bc52338SCy Schubert 	if (conf) {
1045325151a3SRui Paulo 		data->tls_session_lifetime = conf->tls_session_lifetime;
10464bc52338SCy Schubert 		data->crl_reload_interval = conf->crl_reload_interval;
10474bc52338SCy Schubert 	}
10485b9c547cSRui Paulo 
10495b9c547cSRui Paulo 	SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv2);
10505b9c547cSRui Paulo 	SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv3);
105139beb93cSSam Leffler 
1052c1d255d3SCy Schubert 	SSL_CTX_set_mode(ssl, SSL_MODE_AUTO_RETRY);
1053c1d255d3SCy Schubert 
105485732ac8SCy Schubert #ifdef SSL_MODE_NO_AUTO_CHAIN
105585732ac8SCy Schubert 	/* Number of deployed use cases assume the default OpenSSL behavior of
105685732ac8SCy Schubert 	 * auto chaining the local certificate is in use. BoringSSL removed this
105785732ac8SCy Schubert 	 * functionality by default, so we need to restore it here to avoid
105885732ac8SCy Schubert 	 * breaking existing use cases. */
105985732ac8SCy Schubert 	SSL_CTX_clear_mode(ssl, SSL_MODE_NO_AUTO_CHAIN);
106085732ac8SCy Schubert #endif /* SSL_MODE_NO_AUTO_CHAIN */
106185732ac8SCy Schubert 
106239beb93cSSam Leffler 	SSL_CTX_set_info_callback(ssl, ssl_info_cb);
10635b9c547cSRui Paulo 	SSL_CTX_set_app_data(ssl, context);
1064325151a3SRui Paulo 	if (data->tls_session_lifetime > 0) {
1065325151a3SRui Paulo 		SSL_CTX_set_quiet_shutdown(ssl, 1);
1066325151a3SRui Paulo 		/*
1067325151a3SRui Paulo 		 * Set default context here. In practice, this will be replaced
1068325151a3SRui Paulo 		 * by the per-EAP method context in tls_connection_set_verify().
1069325151a3SRui Paulo 		 */
1070325151a3SRui Paulo 		SSL_CTX_set_session_id_context(ssl, (u8 *) "hostapd", 7);
1071325151a3SRui Paulo 		SSL_CTX_set_session_cache_mode(ssl, SSL_SESS_CACHE_SERVER);
1072325151a3SRui Paulo 		SSL_CTX_set_timeout(ssl, data->tls_session_lifetime);
1073325151a3SRui Paulo 		SSL_CTX_sess_set_remove_cb(ssl, remove_session_cb);
1074325151a3SRui Paulo 	} else {
1075325151a3SRui Paulo 		SSL_CTX_set_session_cache_mode(ssl, SSL_SESS_CACHE_OFF);
1076325151a3SRui Paulo 	}
1077325151a3SRui Paulo 
1078325151a3SRui Paulo 	if (tls_ex_idx_session < 0) {
1079325151a3SRui Paulo 		tls_ex_idx_session = SSL_SESSION_get_ex_new_index(
1080325151a3SRui Paulo 			0, NULL, NULL, NULL, NULL);
1081325151a3SRui Paulo 		if (tls_ex_idx_session < 0) {
1082325151a3SRui Paulo 			tls_deinit(data);
1083325151a3SRui Paulo 			return NULL;
1084325151a3SRui Paulo 		}
1085325151a3SRui Paulo 	}
108639beb93cSSam Leffler 
108739beb93cSSam Leffler #ifndef OPENSSL_NO_ENGINE
1088206b73d0SCy Schubert 	wpa_printf(MSG_DEBUG, "ENGINE: Loading builtin engines");
1089206b73d0SCy Schubert 	ENGINE_load_builtin_engines();
109039beb93cSSam Leffler 
10915b9c547cSRui Paulo 	if (conf &&
10925b9c547cSRui Paulo 	    (conf->opensc_engine_path || conf->pkcs11_engine_path ||
10935b9c547cSRui Paulo 	     conf->pkcs11_module_path)) {
109439beb93cSSam Leffler 		if (tls_engine_load_dynamic_opensc(conf->opensc_engine_path) ||
109539beb93cSSam Leffler 		    tls_engine_load_dynamic_pkcs11(conf->pkcs11_engine_path,
109639beb93cSSam Leffler 						   conf->pkcs11_module_path)) {
1097325151a3SRui Paulo 			tls_deinit(data);
109839beb93cSSam Leffler 			return NULL;
109939beb93cSSam Leffler 		}
110039beb93cSSam Leffler 	}
110139beb93cSSam Leffler #endif /* OPENSSL_NO_ENGINE */
110239beb93cSSam Leffler 
11035b9c547cSRui Paulo 	if (conf && conf->openssl_ciphers)
11045b9c547cSRui Paulo 		ciphers = conf->openssl_ciphers;
11055b9c547cSRui Paulo 	else
110685732ac8SCy Schubert 		ciphers = TLS_DEFAULT_CIPHERS;
11075b9c547cSRui Paulo 	if (SSL_CTX_set_cipher_list(ssl, ciphers) != 1) {
11085b9c547cSRui Paulo 		wpa_printf(MSG_ERROR,
11095b9c547cSRui Paulo 			   "OpenSSL: Failed to set cipher string '%s'",
11105b9c547cSRui Paulo 			   ciphers);
1111325151a3SRui Paulo 		tls_deinit(data);
11125b9c547cSRui Paulo 		return NULL;
11135b9c547cSRui Paulo 	}
11145b9c547cSRui Paulo 
1115325151a3SRui Paulo 	return data;
111639beb93cSSam Leffler }
111739beb93cSSam Leffler 
111839beb93cSSam Leffler 
tls_deinit(void * ssl_ctx)111939beb93cSSam Leffler void tls_deinit(void *ssl_ctx)
112039beb93cSSam Leffler {
1121325151a3SRui Paulo 	struct tls_data *data = ssl_ctx;
1122325151a3SRui Paulo 	SSL_CTX *ssl = data->ssl;
11235b9c547cSRui Paulo 	struct tls_context *context = SSL_CTX_get_app_data(ssl);
11245b9c547cSRui Paulo 	if (context != tls_global)
11255b9c547cSRui Paulo 		os_free(context);
1126325151a3SRui Paulo 	if (data->tls_session_lifetime > 0)
1127325151a3SRui Paulo 		SSL_CTX_flush_sessions(ssl, 0);
11284bc52338SCy Schubert 	os_free(data->ca_cert);
112939beb93cSSam Leffler 	SSL_CTX_free(ssl);
113039beb93cSSam Leffler 
113139beb93cSSam Leffler 	tls_openssl_ref_count--;
113239beb93cSSam Leffler 	if (tls_openssl_ref_count == 0) {
113385732ac8SCy Schubert #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
113485732ac8SCy Schubert 	(defined(LIBRESSL_VERSION_NUMBER) && \
113585732ac8SCy Schubert 	 LIBRESSL_VERSION_NUMBER < 0x20700000L)
113639beb93cSSam Leffler #ifndef OPENSSL_NO_ENGINE
113739beb93cSSam Leffler 		ENGINE_cleanup();
113839beb93cSSam Leffler #endif /* OPENSSL_NO_ENGINE */
113939beb93cSSam Leffler 		CRYPTO_cleanup_all_ex_data();
11405b9c547cSRui Paulo 		ERR_remove_thread_state(NULL);
114139beb93cSSam Leffler 		ERR_free_strings();
114239beb93cSSam Leffler 		EVP_cleanup();
1143780fb4a2SCy Schubert #endif /* < 1.1.0 */
11445b9c547cSRui Paulo 		os_free(tls_global->ocsp_stapling_response);
11455b9c547cSRui Paulo 		tls_global->ocsp_stapling_response = NULL;
1146e28a4053SRui Paulo 		os_free(tls_global);
1147e28a4053SRui Paulo 		tls_global = NULL;
114839beb93cSSam Leffler 	}
1149325151a3SRui Paulo 
11504bc52338SCy Schubert 	os_free(data->check_cert_subject);
1151325151a3SRui Paulo 	os_free(data);
115239beb93cSSam Leffler }
115339beb93cSSam Leffler 
115439beb93cSSam Leffler 
1155325151a3SRui Paulo #ifndef OPENSSL_NO_ENGINE
1156325151a3SRui Paulo 
1157325151a3SRui Paulo /* Cryptoki return values */
1158325151a3SRui Paulo #define CKR_PIN_INCORRECT 0x000000a0
1159325151a3SRui Paulo #define CKR_PIN_INVALID 0x000000a1
1160325151a3SRui Paulo #define CKR_PIN_LEN_RANGE 0x000000a2
1161325151a3SRui Paulo 
1162325151a3SRui Paulo /* libp11 */
1163325151a3SRui Paulo #define ERR_LIB_PKCS11	ERR_LIB_USER
1164325151a3SRui Paulo 
tls_is_pin_error(unsigned int err)1165325151a3SRui Paulo static int tls_is_pin_error(unsigned int err)
1166325151a3SRui Paulo {
1167325151a3SRui Paulo 	return ERR_GET_LIB(err) == ERR_LIB_PKCS11 &&
1168325151a3SRui Paulo 		(ERR_GET_REASON(err) == CKR_PIN_INCORRECT ||
1169325151a3SRui Paulo 		 ERR_GET_REASON(err) == CKR_PIN_INVALID ||
1170325151a3SRui Paulo 		 ERR_GET_REASON(err) == CKR_PIN_LEN_RANGE);
1171325151a3SRui Paulo }
1172325151a3SRui Paulo 
1173325151a3SRui Paulo #endif /* OPENSSL_NO_ENGINE */
1174325151a3SRui Paulo 
1175325151a3SRui Paulo 
1176780fb4a2SCy Schubert #ifdef ANDROID
1177780fb4a2SCy Schubert /* EVP_PKEY_from_keystore comes from system/security/keystore-engine. */
1178780fb4a2SCy Schubert EVP_PKEY * EVP_PKEY_from_keystore(const char *key_id);
1179780fb4a2SCy Schubert #endif /* ANDROID */
1180780fb4a2SCy Schubert 
tls_engine_init(struct tls_connection * conn,const char * engine_id,const char * pin,const char * key_id,const char * cert_id,const char * ca_cert_id)118139beb93cSSam Leffler static int tls_engine_init(struct tls_connection *conn, const char *engine_id,
118239beb93cSSam Leffler 			   const char *pin, const char *key_id,
118339beb93cSSam Leffler 			   const char *cert_id, const char *ca_cert_id)
118439beb93cSSam Leffler {
1185780fb4a2SCy Schubert #if defined(ANDROID) && defined(OPENSSL_IS_BORINGSSL)
1186780fb4a2SCy Schubert #if !defined(OPENSSL_NO_ENGINE)
1187780fb4a2SCy Schubert #error "This code depends on OPENSSL_NO_ENGINE being defined by BoringSSL."
1188780fb4a2SCy Schubert #endif
1189780fb4a2SCy Schubert 	if (!key_id)
1190780fb4a2SCy Schubert 		return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
1191780fb4a2SCy Schubert 	conn->engine = NULL;
1192780fb4a2SCy Schubert 	conn->private_key = EVP_PKEY_from_keystore(key_id);
1193780fb4a2SCy Schubert 	if (!conn->private_key) {
1194780fb4a2SCy Schubert 		wpa_printf(MSG_ERROR,
1195780fb4a2SCy Schubert 			   "ENGINE: cannot load private key with id '%s' [%s]",
1196780fb4a2SCy Schubert 			   key_id,
1197780fb4a2SCy Schubert 			   ERR_error_string(ERR_get_error(), NULL));
1198780fb4a2SCy Schubert 		return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
1199780fb4a2SCy Schubert 	}
1200780fb4a2SCy Schubert #endif /* ANDROID && OPENSSL_IS_BORINGSSL */
1201780fb4a2SCy Schubert 
120239beb93cSSam Leffler #ifndef OPENSSL_NO_ENGINE
120339beb93cSSam Leffler 	int ret = -1;
120439beb93cSSam Leffler 	if (engine_id == NULL) {
120539beb93cSSam Leffler 		wpa_printf(MSG_ERROR, "ENGINE: Engine ID not set");
120639beb93cSSam Leffler 		return -1;
120739beb93cSSam Leffler 	}
120839beb93cSSam Leffler 
120939beb93cSSam Leffler 	ERR_clear_error();
12105b9c547cSRui Paulo #ifdef ANDROID
12115b9c547cSRui Paulo 	ENGINE_load_dynamic();
12125b9c547cSRui Paulo #endif
121339beb93cSSam Leffler 	conn->engine = ENGINE_by_id(engine_id);
121439beb93cSSam Leffler 	if (!conn->engine) {
121539beb93cSSam Leffler 		wpa_printf(MSG_ERROR, "ENGINE: engine %s not available [%s]",
121639beb93cSSam Leffler 			   engine_id, ERR_error_string(ERR_get_error(), NULL));
121739beb93cSSam Leffler 		goto err;
121839beb93cSSam Leffler 	}
121939beb93cSSam Leffler 	if (ENGINE_init(conn->engine) != 1) {
122039beb93cSSam Leffler 		wpa_printf(MSG_ERROR, "ENGINE: engine init failed "
122139beb93cSSam Leffler 			   "(engine: %s) [%s]", engine_id,
122239beb93cSSam Leffler 			   ERR_error_string(ERR_get_error(), NULL));
122339beb93cSSam Leffler 		goto err;
122439beb93cSSam Leffler 	}
122539beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "ENGINE: engine initialized");
122639beb93cSSam Leffler 
12275b9c547cSRui Paulo #ifndef ANDROID
12285b9c547cSRui Paulo 	if (pin && ENGINE_ctrl_cmd_string(conn->engine, "PIN", pin, 0) == 0) {
122939beb93cSSam Leffler 		wpa_printf(MSG_ERROR, "ENGINE: cannot set pin [%s]",
123039beb93cSSam Leffler 			   ERR_error_string(ERR_get_error(), NULL));
123139beb93cSSam Leffler 		goto err;
123239beb93cSSam Leffler 	}
12335b9c547cSRui Paulo #endif
12345b9c547cSRui Paulo 	if (key_id) {
12355b9c547cSRui Paulo 		/*
12365b9c547cSRui Paulo 		 * Ensure that the ENGINE does not attempt to use the OpenSSL
12375b9c547cSRui Paulo 		 * UI system to obtain a PIN, if we didn't provide one.
12385b9c547cSRui Paulo 		 */
12395b9c547cSRui Paulo 		struct {
12405b9c547cSRui Paulo 			const void *password;
12415b9c547cSRui Paulo 			const char *prompt_info;
12425b9c547cSRui Paulo 		} key_cb = { "", NULL };
12435b9c547cSRui Paulo 
124439beb93cSSam Leffler 		/* load private key first in-case PIN is required for cert */
124539beb93cSSam Leffler 		conn->private_key = ENGINE_load_private_key(conn->engine,
12465b9c547cSRui Paulo 							    key_id, NULL,
12475b9c547cSRui Paulo 							    &key_cb);
124839beb93cSSam Leffler 		if (!conn->private_key) {
1249325151a3SRui Paulo 			unsigned long err = ERR_get_error();
1250325151a3SRui Paulo 
12515b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
12525b9c547cSRui Paulo 				   "ENGINE: cannot load private key with id '%s' [%s]",
12535b9c547cSRui Paulo 				   key_id,
1254325151a3SRui Paulo 				   ERR_error_string(err, NULL));
1255325151a3SRui Paulo 			if (tls_is_pin_error(err))
1256325151a3SRui Paulo 				ret = TLS_SET_PARAMS_ENGINE_PRV_BAD_PIN;
1257325151a3SRui Paulo 			else
125839beb93cSSam Leffler 				ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
125939beb93cSSam Leffler 			goto err;
126039beb93cSSam Leffler 		}
12615b9c547cSRui Paulo 	}
126239beb93cSSam Leffler 
126339beb93cSSam Leffler 	/* handle a certificate and/or CA certificate */
126439beb93cSSam Leffler 	if (cert_id || ca_cert_id) {
126539beb93cSSam Leffler 		const char *cmd_name = "LOAD_CERT_CTRL";
126639beb93cSSam Leffler 
126739beb93cSSam Leffler 		/* test if the engine supports a LOAD_CERT_CTRL */
126839beb93cSSam Leffler 		if (!ENGINE_ctrl(conn->engine, ENGINE_CTRL_GET_CMD_FROM_NAME,
126939beb93cSSam Leffler 				 0, (void *)cmd_name, NULL)) {
127039beb93cSSam Leffler 			wpa_printf(MSG_ERROR, "ENGINE: engine does not support"
127139beb93cSSam Leffler 				   " loading certificates");
127239beb93cSSam Leffler 			ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
127339beb93cSSam Leffler 			goto err;
127439beb93cSSam Leffler 		}
127539beb93cSSam Leffler 	}
127639beb93cSSam Leffler 
127739beb93cSSam Leffler 	return 0;
127839beb93cSSam Leffler 
127939beb93cSSam Leffler err:
128039beb93cSSam Leffler 	if (conn->engine) {
128139beb93cSSam Leffler 		ENGINE_free(conn->engine);
128239beb93cSSam Leffler 		conn->engine = NULL;
128339beb93cSSam Leffler 	}
128439beb93cSSam Leffler 
128539beb93cSSam Leffler 	if (conn->private_key) {
128639beb93cSSam Leffler 		EVP_PKEY_free(conn->private_key);
128739beb93cSSam Leffler 		conn->private_key = NULL;
128839beb93cSSam Leffler 	}
128939beb93cSSam Leffler 
129039beb93cSSam Leffler 	return ret;
129139beb93cSSam Leffler #else /* OPENSSL_NO_ENGINE */
129239beb93cSSam Leffler 	return 0;
129339beb93cSSam Leffler #endif /* OPENSSL_NO_ENGINE */
129439beb93cSSam Leffler }
129539beb93cSSam Leffler 
129639beb93cSSam Leffler 
tls_engine_deinit(struct tls_connection * conn)129739beb93cSSam Leffler static void tls_engine_deinit(struct tls_connection *conn)
129839beb93cSSam Leffler {
1299780fb4a2SCy Schubert #if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE)
130039beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "ENGINE: engine deinit");
130139beb93cSSam Leffler 	if (conn->private_key) {
130239beb93cSSam Leffler 		EVP_PKEY_free(conn->private_key);
130339beb93cSSam Leffler 		conn->private_key = NULL;
130439beb93cSSam Leffler 	}
130539beb93cSSam Leffler 	if (conn->engine) {
1306780fb4a2SCy Schubert #if !defined(OPENSSL_IS_BORINGSSL)
130739beb93cSSam Leffler 		ENGINE_finish(conn->engine);
1308780fb4a2SCy Schubert #endif /* !OPENSSL_IS_BORINGSSL */
130939beb93cSSam Leffler 		conn->engine = NULL;
131039beb93cSSam Leffler 	}
1311780fb4a2SCy Schubert #endif /* ANDROID || !OPENSSL_NO_ENGINE */
131239beb93cSSam Leffler }
131339beb93cSSam Leffler 
131439beb93cSSam Leffler 
tls_get_errors(void * ssl_ctx)131539beb93cSSam Leffler int tls_get_errors(void *ssl_ctx)
131639beb93cSSam Leffler {
131739beb93cSSam Leffler 	int count = 0;
131839beb93cSSam Leffler 	unsigned long err;
131939beb93cSSam Leffler 
132039beb93cSSam Leffler 	while ((err = ERR_get_error())) {
132139beb93cSSam Leffler 		wpa_printf(MSG_INFO, "TLS - SSL error: %s",
132239beb93cSSam Leffler 			   ERR_error_string(err, NULL));
132339beb93cSSam Leffler 		count++;
132439beb93cSSam Leffler 	}
132539beb93cSSam Leffler 
132639beb93cSSam Leffler 	return count;
132739beb93cSSam Leffler }
132839beb93cSSam Leffler 
13295b9c547cSRui Paulo 
openssl_content_type(int content_type)1330780fb4a2SCy Schubert static const char * openssl_content_type(int content_type)
1331780fb4a2SCy Schubert {
1332780fb4a2SCy Schubert 	switch (content_type) {
1333780fb4a2SCy Schubert 	case 20:
1334780fb4a2SCy Schubert 		return "change cipher spec";
1335780fb4a2SCy Schubert 	case 21:
1336780fb4a2SCy Schubert 		return "alert";
1337780fb4a2SCy Schubert 	case 22:
1338780fb4a2SCy Schubert 		return "handshake";
1339780fb4a2SCy Schubert 	case 23:
1340780fb4a2SCy Schubert 		return "application data";
1341780fb4a2SCy Schubert 	case 24:
1342780fb4a2SCy Schubert 		return "heartbeat";
1343780fb4a2SCy Schubert 	case 256:
1344780fb4a2SCy Schubert 		return "TLS header info"; /* pseudo content type */
1345206b73d0SCy Schubert 	case 257:
1346206b73d0SCy Schubert 		return "inner content type"; /* pseudo content type */
1347780fb4a2SCy Schubert 	default:
1348780fb4a2SCy Schubert 		return "?";
1349780fb4a2SCy Schubert 	}
1350780fb4a2SCy Schubert }
1351780fb4a2SCy Schubert 
1352780fb4a2SCy Schubert 
openssl_handshake_type(int content_type,const u8 * buf,size_t len)1353780fb4a2SCy Schubert static const char * openssl_handshake_type(int content_type, const u8 *buf,
1354780fb4a2SCy Schubert 					   size_t len)
1355780fb4a2SCy Schubert {
1356206b73d0SCy Schubert 	if (content_type == 257 && buf && len == 1)
1357206b73d0SCy Schubert 		return openssl_content_type(buf[0]);
1358780fb4a2SCy Schubert 	if (content_type != 22 || !buf || len == 0)
1359780fb4a2SCy Schubert 		return "";
1360780fb4a2SCy Schubert 	switch (buf[0]) {
1361780fb4a2SCy Schubert 	case 0:
1362780fb4a2SCy Schubert 		return "hello request";
1363780fb4a2SCy Schubert 	case 1:
1364780fb4a2SCy Schubert 		return "client hello";
1365780fb4a2SCy Schubert 	case 2:
1366780fb4a2SCy Schubert 		return "server hello";
13674bc52338SCy Schubert 	case 3:
13684bc52338SCy Schubert 		return "hello verify request";
1369780fb4a2SCy Schubert 	case 4:
1370780fb4a2SCy Schubert 		return "new session ticket";
13714bc52338SCy Schubert 	case 5:
13724bc52338SCy Schubert 		return "end of early data";
13734bc52338SCy Schubert 	case 6:
13744bc52338SCy Schubert 		return "hello retry request";
13754bc52338SCy Schubert 	case 8:
13764bc52338SCy Schubert 		return "encrypted extensions";
1377780fb4a2SCy Schubert 	case 11:
1378780fb4a2SCy Schubert 		return "certificate";
1379780fb4a2SCy Schubert 	case 12:
1380780fb4a2SCy Schubert 		return "server key exchange";
1381780fb4a2SCy Schubert 	case 13:
1382780fb4a2SCy Schubert 		return "certificate request";
1383780fb4a2SCy Schubert 	case 14:
1384780fb4a2SCy Schubert 		return "server hello done";
1385780fb4a2SCy Schubert 	case 15:
1386780fb4a2SCy Schubert 		return "certificate verify";
1387780fb4a2SCy Schubert 	case 16:
1388780fb4a2SCy Schubert 		return "client key exchange";
1389780fb4a2SCy Schubert 	case 20:
1390780fb4a2SCy Schubert 		return "finished";
1391780fb4a2SCy Schubert 	case 21:
1392780fb4a2SCy Schubert 		return "certificate url";
1393780fb4a2SCy Schubert 	case 22:
1394780fb4a2SCy Schubert 		return "certificate status";
13954bc52338SCy Schubert 	case 23:
13964bc52338SCy Schubert 		return "supplemental data";
13974bc52338SCy Schubert 	case 24:
13984bc52338SCy Schubert 		return "key update";
13994bc52338SCy Schubert 	case 254:
14004bc52338SCy Schubert 		return "message hash";
1401780fb4a2SCy Schubert 	default:
1402780fb4a2SCy Schubert 		return "?";
1403780fb4a2SCy Schubert 	}
1404780fb4a2SCy Schubert }
1405780fb4a2SCy Schubert 
1406780fb4a2SCy Schubert 
140785732ac8SCy Schubert #ifdef CONFIG_SUITEB
140885732ac8SCy Schubert 
check_server_hello(struct tls_connection * conn,const u8 * pos,const u8 * end)140985732ac8SCy Schubert static void check_server_hello(struct tls_connection *conn,
141085732ac8SCy Schubert 			       const u8 *pos, const u8 *end)
141185732ac8SCy Schubert {
141285732ac8SCy Schubert 	size_t payload_len, id_len;
141385732ac8SCy Schubert 
141485732ac8SCy Schubert 	/*
141585732ac8SCy Schubert 	 * Parse ServerHello to get the selected cipher suite since OpenSSL does
141685732ac8SCy Schubert 	 * not make it cleanly available during handshake and we need to know
141785732ac8SCy Schubert 	 * whether DHE was selected.
141885732ac8SCy Schubert 	 */
141985732ac8SCy Schubert 
142085732ac8SCy Schubert 	if (end - pos < 3)
142185732ac8SCy Schubert 		return;
142285732ac8SCy Schubert 	payload_len = WPA_GET_BE24(pos);
142385732ac8SCy Schubert 	pos += 3;
142485732ac8SCy Schubert 
142585732ac8SCy Schubert 	if ((size_t) (end - pos) < payload_len)
142685732ac8SCy Schubert 		return;
142785732ac8SCy Schubert 	end = pos + payload_len;
142885732ac8SCy Schubert 
142985732ac8SCy Schubert 	/* Skip Version and Random */
143085732ac8SCy Schubert 	if (end - pos < 2 + SSL3_RANDOM_SIZE)
143185732ac8SCy Schubert 		return;
143285732ac8SCy Schubert 	pos += 2 + SSL3_RANDOM_SIZE;
143385732ac8SCy Schubert 
143485732ac8SCy Schubert 	/* Skip Session ID */
143585732ac8SCy Schubert 	if (end - pos < 1)
143685732ac8SCy Schubert 		return;
143785732ac8SCy Schubert 	id_len = *pos++;
143885732ac8SCy Schubert 	if ((size_t) (end - pos) < id_len)
143985732ac8SCy Schubert 		return;
144085732ac8SCy Schubert 	pos += id_len;
144185732ac8SCy Schubert 
144285732ac8SCy Schubert 	if (end - pos < 2)
144385732ac8SCy Schubert 		return;
144485732ac8SCy Schubert 	conn->cipher_suite = WPA_GET_BE16(pos);
144585732ac8SCy Schubert 	wpa_printf(MSG_DEBUG, "OpenSSL: Server selected cipher suite 0x%x",
144685732ac8SCy Schubert 		   conn->cipher_suite);
144785732ac8SCy Schubert }
144885732ac8SCy Schubert 
144985732ac8SCy Schubert 
check_server_key_exchange(SSL * ssl,struct tls_connection * conn,const u8 * pos,const u8 * end)145085732ac8SCy Schubert static void check_server_key_exchange(SSL *ssl, struct tls_connection *conn,
145185732ac8SCy Schubert 				      const u8 *pos, const u8 *end)
145285732ac8SCy Schubert {
145385732ac8SCy Schubert 	size_t payload_len;
145485732ac8SCy Schubert 	u16 dh_len;
145585732ac8SCy Schubert 	BIGNUM *p;
145685732ac8SCy Schubert 	int bits;
145785732ac8SCy Schubert 
145885732ac8SCy Schubert 	if (!(conn->flags & TLS_CONN_SUITEB))
145985732ac8SCy Schubert 		return;
146085732ac8SCy Schubert 
146185732ac8SCy Schubert 	/* DHE is enabled only with DHE-RSA-AES256-GCM-SHA384 */
146285732ac8SCy Schubert 	if (conn->cipher_suite != 0x9f)
146385732ac8SCy Schubert 		return;
146485732ac8SCy Schubert 
146585732ac8SCy Schubert 	if (end - pos < 3)
146685732ac8SCy Schubert 		return;
146785732ac8SCy Schubert 	payload_len = WPA_GET_BE24(pos);
146885732ac8SCy Schubert 	pos += 3;
146985732ac8SCy Schubert 
147085732ac8SCy Schubert 	if ((size_t) (end - pos) < payload_len)
147185732ac8SCy Schubert 		return;
147285732ac8SCy Schubert 	end = pos + payload_len;
147385732ac8SCy Schubert 
147485732ac8SCy Schubert 	if (end - pos < 2)
147585732ac8SCy Schubert 		return;
147685732ac8SCy Schubert 	dh_len = WPA_GET_BE16(pos);
147785732ac8SCy Schubert 	pos += 2;
147885732ac8SCy Schubert 
147985732ac8SCy Schubert 	if ((size_t) (end - pos) < dh_len)
148085732ac8SCy Schubert 		return;
148185732ac8SCy Schubert 	p = BN_bin2bn(pos, dh_len, NULL);
148285732ac8SCy Schubert 	if (!p)
148385732ac8SCy Schubert 		return;
148485732ac8SCy Schubert 
148585732ac8SCy Schubert 	bits = BN_num_bits(p);
148685732ac8SCy Schubert 	BN_free(p);
148785732ac8SCy Schubert 
148885732ac8SCy Schubert 	conn->server_dh_prime_len = bits;
148985732ac8SCy Schubert 	wpa_printf(MSG_DEBUG, "OpenSSL: Server DH prime length: %d bits",
149085732ac8SCy Schubert 		   conn->server_dh_prime_len);
149185732ac8SCy Schubert }
149285732ac8SCy Schubert 
149385732ac8SCy Schubert #endif /* CONFIG_SUITEB */
149485732ac8SCy Schubert 
149585732ac8SCy Schubert 
tls_msg_cb(int write_p,int version,int content_type,const void * buf,size_t len,SSL * ssl,void * arg)14965b9c547cSRui Paulo static void tls_msg_cb(int write_p, int version, int content_type,
14975b9c547cSRui Paulo 		       const void *buf, size_t len, SSL *ssl, void *arg)
14985b9c547cSRui Paulo {
14995b9c547cSRui Paulo 	struct tls_connection *conn = arg;
15005b9c547cSRui Paulo 	const u8 *pos = buf;
15015b9c547cSRui Paulo 
1502780fb4a2SCy Schubert 	if (write_p == 2) {
1503780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
1504780fb4a2SCy Schubert 			   "OpenSSL: session ver=0x%x content_type=%d",
1505780fb4a2SCy Schubert 			   version, content_type);
1506780fb4a2SCy Schubert 		wpa_hexdump_key(MSG_MSGDUMP, "OpenSSL: Data", buf, len);
1507780fb4a2SCy Schubert 		return;
1508780fb4a2SCy Schubert 	}
1509780fb4a2SCy Schubert 
1510780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "OpenSSL: %s ver=0x%x content_type=%d (%s/%s)",
1511780fb4a2SCy Schubert 		   write_p ? "TX" : "RX", version, content_type,
1512780fb4a2SCy Schubert 		   openssl_content_type(content_type),
1513780fb4a2SCy Schubert 		   openssl_handshake_type(content_type, buf, len));
15145b9c547cSRui Paulo 	wpa_hexdump_key(MSG_MSGDUMP, "OpenSSL: Message", buf, len);
15155b9c547cSRui Paulo 	if (content_type == 24 && len >= 3 && pos[0] == 1) {
15165b9c547cSRui Paulo 		size_t payload_len = WPA_GET_BE16(pos + 1);
15175b9c547cSRui Paulo 		if (payload_len + 3 > len) {
15185b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "OpenSSL: Heartbeat attack detected");
15195b9c547cSRui Paulo 			conn->invalid_hb_used = 1;
15205b9c547cSRui Paulo 		}
15215b9c547cSRui Paulo 	}
152285732ac8SCy Schubert 
152385732ac8SCy Schubert #ifdef CONFIG_SUITEB
152485732ac8SCy Schubert 	/*
152585732ac8SCy Schubert 	 * Need to parse these handshake messages to be able to check DH prime
152685732ac8SCy Schubert 	 * length since OpenSSL does not expose the new cipher suite and DH
152785732ac8SCy Schubert 	 * parameters during handshake (e.g., for cert_cb() callback).
152885732ac8SCy Schubert 	 */
152985732ac8SCy Schubert 	if (content_type == 22 && pos && len > 0 && pos[0] == 2)
153085732ac8SCy Schubert 		check_server_hello(conn, pos + 1, pos + len);
153185732ac8SCy Schubert 	if (content_type == 22 && pos && len > 0 && pos[0] == 12)
153285732ac8SCy Schubert 		check_server_key_exchange(ssl, conn, pos + 1, pos + len);
153385732ac8SCy Schubert #endif /* CONFIG_SUITEB */
15345b9c547cSRui Paulo }
15355b9c547cSRui Paulo 
15365b9c547cSRui Paulo 
tls_connection_init(void * ssl_ctx)153739beb93cSSam Leffler struct tls_connection * tls_connection_init(void *ssl_ctx)
153839beb93cSSam Leffler {
1539325151a3SRui Paulo 	struct tls_data *data = ssl_ctx;
1540325151a3SRui Paulo 	SSL_CTX *ssl = data->ssl;
154139beb93cSSam Leffler 	struct tls_connection *conn;
154239beb93cSSam Leffler 	long options;
15434bc52338SCy Schubert 	X509_STORE *new_cert_store;
15444bc52338SCy Schubert 	struct os_reltime now;
15455b9c547cSRui Paulo 	struct tls_context *context = SSL_CTX_get_app_data(ssl);
154639beb93cSSam Leffler 
15474bc52338SCy Schubert 	/* Replace X509 store if it is time to update CRL. */
15484bc52338SCy Schubert 	if (data->crl_reload_interval > 0 && os_get_reltime(&now) == 0 &&
15494bc52338SCy Schubert 	    os_reltime_expired(&now, &data->crl_last_reload,
15504bc52338SCy Schubert 			       data->crl_reload_interval)) {
15514bc52338SCy Schubert 		wpa_printf(MSG_INFO,
15524bc52338SCy Schubert 			   "OpenSSL: Flushing X509 store with ca_cert file");
15534bc52338SCy Schubert 		new_cert_store = tls_crl_cert_reload(data->ca_cert,
15544bc52338SCy Schubert 						     data->check_crl);
15554bc52338SCy Schubert 		if (!new_cert_store) {
15564bc52338SCy Schubert 			wpa_printf(MSG_ERROR,
15574bc52338SCy Schubert 				   "OpenSSL: Error replacing X509 store with ca_cert file");
15584bc52338SCy Schubert 		} else {
15594bc52338SCy Schubert 			/* Replace old store */
15604bc52338SCy Schubert 			SSL_CTX_set_cert_store(ssl, new_cert_store);
15614bc52338SCy Schubert 			data->crl_last_reload = now;
15624bc52338SCy Schubert 		}
15634bc52338SCy Schubert 	}
15644bc52338SCy Schubert 
156539beb93cSSam Leffler 	conn = os_zalloc(sizeof(*conn));
156639beb93cSSam Leffler 	if (conn == NULL)
156739beb93cSSam Leffler 		return NULL;
15684bc52338SCy Schubert 	conn->data = data;
1569325151a3SRui Paulo 	conn->ssl_ctx = ssl;
157039beb93cSSam Leffler 	conn->ssl = SSL_new(ssl);
157139beb93cSSam Leffler 	if (conn->ssl == NULL) {
157239beb93cSSam Leffler 		tls_show_errors(MSG_INFO, __func__,
157339beb93cSSam Leffler 				"Failed to initialize new SSL connection");
157439beb93cSSam Leffler 		os_free(conn);
157539beb93cSSam Leffler 		return NULL;
157639beb93cSSam Leffler 	}
157739beb93cSSam Leffler 
15785b9c547cSRui Paulo 	conn->context = context;
157939beb93cSSam Leffler 	SSL_set_app_data(conn->ssl, conn);
15805b9c547cSRui Paulo 	SSL_set_msg_callback(conn->ssl, tls_msg_cb);
15815b9c547cSRui Paulo 	SSL_set_msg_callback_arg(conn->ssl, conn);
158239beb93cSSam Leffler 	options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
158339beb93cSSam Leffler 		SSL_OP_SINGLE_DH_USE;
158439beb93cSSam Leffler #ifdef SSL_OP_NO_COMPRESSION
158539beb93cSSam Leffler 	options |= SSL_OP_NO_COMPRESSION;
158639beb93cSSam Leffler #endif /* SSL_OP_NO_COMPRESSION */
158739beb93cSSam Leffler 	SSL_set_options(conn->ssl, options);
1588206b73d0SCy Schubert #ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT
1589206b73d0SCy Schubert 	/* Hopefully there is no need for middlebox compatibility mechanisms
1590206b73d0SCy Schubert 	 * when going through EAP authentication. */
1591206b73d0SCy Schubert 	SSL_clear_options(conn->ssl, SSL_OP_ENABLE_MIDDLEBOX_COMPAT);
1592206b73d0SCy Schubert #endif
159339beb93cSSam Leffler 
159439beb93cSSam Leffler 	conn->ssl_in = BIO_new(BIO_s_mem());
159539beb93cSSam Leffler 	if (!conn->ssl_in) {
159639beb93cSSam Leffler 		tls_show_errors(MSG_INFO, __func__,
159739beb93cSSam Leffler 				"Failed to create a new BIO for ssl_in");
159839beb93cSSam Leffler 		SSL_free(conn->ssl);
159939beb93cSSam Leffler 		os_free(conn);
160039beb93cSSam Leffler 		return NULL;
160139beb93cSSam Leffler 	}
160239beb93cSSam Leffler 
160339beb93cSSam Leffler 	conn->ssl_out = BIO_new(BIO_s_mem());
160439beb93cSSam Leffler 	if (!conn->ssl_out) {
160539beb93cSSam Leffler 		tls_show_errors(MSG_INFO, __func__,
160639beb93cSSam Leffler 				"Failed to create a new BIO for ssl_out");
160739beb93cSSam Leffler 		SSL_free(conn->ssl);
160839beb93cSSam Leffler 		BIO_free(conn->ssl_in);
160939beb93cSSam Leffler 		os_free(conn);
161039beb93cSSam Leffler 		return NULL;
161139beb93cSSam Leffler 	}
161239beb93cSSam Leffler 
161339beb93cSSam Leffler 	SSL_set_bio(conn->ssl, conn->ssl_in, conn->ssl_out);
161439beb93cSSam Leffler 
161539beb93cSSam Leffler 	return conn;
161639beb93cSSam Leffler }
161739beb93cSSam Leffler 
161839beb93cSSam Leffler 
tls_connection_deinit(void * ssl_ctx,struct tls_connection * conn)161939beb93cSSam Leffler void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
162039beb93cSSam Leffler {
162139beb93cSSam Leffler 	if (conn == NULL)
162239beb93cSSam Leffler 		return;
1623325151a3SRui Paulo 	if (conn->success_data) {
1624325151a3SRui Paulo 		/*
1625325151a3SRui Paulo 		 * Make sure ssl_clear_bad_session() does not remove this
1626325151a3SRui Paulo 		 * session.
1627325151a3SRui Paulo 		 */
1628325151a3SRui Paulo 		SSL_set_quiet_shutdown(conn->ssl, 1);
1629325151a3SRui Paulo 		SSL_shutdown(conn->ssl);
1630325151a3SRui Paulo 	}
163139beb93cSSam Leffler 	SSL_free(conn->ssl);
163239beb93cSSam Leffler 	tls_engine_deinit(conn);
163339beb93cSSam Leffler 	os_free(conn->subject_match);
163439beb93cSSam Leffler 	os_free(conn->altsubject_match);
16355b9c547cSRui Paulo 	os_free(conn->suffix_match);
16365b9c547cSRui Paulo 	os_free(conn->domain_match);
16374bc52338SCy Schubert 	os_free(conn->check_cert_subject);
163839beb93cSSam Leffler 	os_free(conn->session_ticket);
1639c1d255d3SCy Schubert 	os_free(conn->peer_subject);
164039beb93cSSam Leffler 	os_free(conn);
164139beb93cSSam Leffler }
164239beb93cSSam Leffler 
164339beb93cSSam Leffler 
tls_connection_established(void * ssl_ctx,struct tls_connection * conn)164439beb93cSSam Leffler int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
164539beb93cSSam Leffler {
164639beb93cSSam Leffler 	return conn ? SSL_is_init_finished(conn->ssl) : 0;
164739beb93cSSam Leffler }
164839beb93cSSam Leffler 
164939beb93cSSam Leffler 
tls_connection_peer_serial_num(void * tls_ctx,struct tls_connection * conn)165085732ac8SCy Schubert char * tls_connection_peer_serial_num(void *tls_ctx,
165185732ac8SCy Schubert 				      struct tls_connection *conn)
165285732ac8SCy Schubert {
165385732ac8SCy Schubert 	ASN1_INTEGER *ser;
165485732ac8SCy Schubert 	char *serial_num;
165585732ac8SCy Schubert 	size_t len;
165685732ac8SCy Schubert 
165785732ac8SCy Schubert 	if (!conn->peer_cert)
165885732ac8SCy Schubert 		return NULL;
165985732ac8SCy Schubert 
166085732ac8SCy Schubert 	ser = X509_get_serialNumber(conn->peer_cert);
166185732ac8SCy Schubert 	if (!ser)
166285732ac8SCy Schubert 		return NULL;
166385732ac8SCy Schubert 
166485732ac8SCy Schubert 	len = ASN1_STRING_length(ser) * 2 + 1;
166585732ac8SCy Schubert 	serial_num = os_malloc(len);
166685732ac8SCy Schubert 	if (!serial_num)
166785732ac8SCy Schubert 		return NULL;
166885732ac8SCy Schubert 	wpa_snprintf_hex_uppercase(serial_num, len,
166985732ac8SCy Schubert 				   ASN1_STRING_get0_data(ser),
167085732ac8SCy Schubert 				   ASN1_STRING_length(ser));
167185732ac8SCy Schubert 	return serial_num;
167285732ac8SCy Schubert }
167385732ac8SCy Schubert 
167485732ac8SCy Schubert 
tls_connection_shutdown(void * ssl_ctx,struct tls_connection * conn)167539beb93cSSam Leffler int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
167639beb93cSSam Leffler {
167739beb93cSSam Leffler 	if (conn == NULL)
167839beb93cSSam Leffler 		return -1;
167939beb93cSSam Leffler 
168039beb93cSSam Leffler 	/* Shutdown previous TLS connection without notifying the peer
168139beb93cSSam Leffler 	 * because the connection was already terminated in practice
168239beb93cSSam Leffler 	 * and "close notify" shutdown alert would confuse AS. */
168339beb93cSSam Leffler 	SSL_set_quiet_shutdown(conn->ssl, 1);
168439beb93cSSam Leffler 	SSL_shutdown(conn->ssl);
1685325151a3SRui Paulo 	return SSL_clear(conn->ssl) == 1 ? 0 : -1;
168639beb93cSSam Leffler }
168739beb93cSSam Leffler 
168839beb93cSSam Leffler 
tls_match_altsubject_component(X509 * cert,int type,const char * value,size_t len)168939beb93cSSam Leffler static int tls_match_altsubject_component(X509 *cert, int type,
169039beb93cSSam Leffler 					  const char *value, size_t len)
169139beb93cSSam Leffler {
169239beb93cSSam Leffler 	GENERAL_NAME *gen;
169339beb93cSSam Leffler 	void *ext;
16945b9c547cSRui Paulo 	int found = 0;
16955b9c547cSRui Paulo 	stack_index_t i;
169639beb93cSSam Leffler 
169739beb93cSSam Leffler 	ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
169839beb93cSSam Leffler 
169939beb93cSSam Leffler 	for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
170039beb93cSSam Leffler 		gen = sk_GENERAL_NAME_value(ext, i);
170139beb93cSSam Leffler 		if (gen->type != type)
170239beb93cSSam Leffler 			continue;
170339beb93cSSam Leffler 		if (os_strlen((char *) gen->d.ia5->data) == len &&
170439beb93cSSam Leffler 		    os_memcmp(value, gen->d.ia5->data, len) == 0)
170539beb93cSSam Leffler 			found++;
170639beb93cSSam Leffler 	}
170739beb93cSSam Leffler 
1708780fb4a2SCy Schubert 	sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
1709780fb4a2SCy Schubert 
171039beb93cSSam Leffler 	return found;
171139beb93cSSam Leffler }
171239beb93cSSam Leffler 
171339beb93cSSam Leffler 
tls_match_altsubject(X509 * cert,const char * match)171439beb93cSSam Leffler static int tls_match_altsubject(X509 *cert, const char *match)
171539beb93cSSam Leffler {
171639beb93cSSam Leffler 	int type;
171739beb93cSSam Leffler 	const char *pos, *end;
171839beb93cSSam Leffler 	size_t len;
171939beb93cSSam Leffler 
172039beb93cSSam Leffler 	pos = match;
172139beb93cSSam Leffler 	do {
172239beb93cSSam Leffler 		if (os_strncmp(pos, "EMAIL:", 6) == 0) {
172339beb93cSSam Leffler 			type = GEN_EMAIL;
172439beb93cSSam Leffler 			pos += 6;
172539beb93cSSam Leffler 		} else if (os_strncmp(pos, "DNS:", 4) == 0) {
172639beb93cSSam Leffler 			type = GEN_DNS;
172739beb93cSSam Leffler 			pos += 4;
172839beb93cSSam Leffler 		} else if (os_strncmp(pos, "URI:", 4) == 0) {
172939beb93cSSam Leffler 			type = GEN_URI;
173039beb93cSSam Leffler 			pos += 4;
173139beb93cSSam Leffler 		} else {
173239beb93cSSam Leffler 			wpa_printf(MSG_INFO, "TLS: Invalid altSubjectName "
173339beb93cSSam Leffler 				   "match '%s'", pos);
173439beb93cSSam Leffler 			return 0;
173539beb93cSSam Leffler 		}
173639beb93cSSam Leffler 		end = os_strchr(pos, ';');
173739beb93cSSam Leffler 		while (end) {
173839beb93cSSam Leffler 			if (os_strncmp(end + 1, "EMAIL:", 6) == 0 ||
173939beb93cSSam Leffler 			    os_strncmp(end + 1, "DNS:", 4) == 0 ||
174039beb93cSSam Leffler 			    os_strncmp(end + 1, "URI:", 4) == 0)
174139beb93cSSam Leffler 				break;
174239beb93cSSam Leffler 			end = os_strchr(end + 1, ';');
174339beb93cSSam Leffler 		}
174439beb93cSSam Leffler 		if (end)
174539beb93cSSam Leffler 			len = end - pos;
174639beb93cSSam Leffler 		else
174739beb93cSSam Leffler 			len = os_strlen(pos);
174839beb93cSSam Leffler 		if (tls_match_altsubject_component(cert, type, pos, len) > 0)
174939beb93cSSam Leffler 			return 1;
175039beb93cSSam Leffler 		pos = end + 1;
175139beb93cSSam Leffler 	} while (end);
175239beb93cSSam Leffler 
175339beb93cSSam Leffler 	return 0;
175439beb93cSSam Leffler }
175539beb93cSSam Leffler 
175639beb93cSSam Leffler 
17575b9c547cSRui Paulo #ifndef CONFIG_NATIVE_WINDOWS
domain_suffix_match(const u8 * val,size_t len,const char * match,size_t match_len,int full)17585b9c547cSRui Paulo static int domain_suffix_match(const u8 *val, size_t len, const char *match,
17594bc52338SCy Schubert 			       size_t match_len, int full)
17605b9c547cSRui Paulo {
17614bc52338SCy Schubert 	size_t i;
17625b9c547cSRui Paulo 
17635b9c547cSRui Paulo 	/* Check for embedded nuls that could mess up suffix matching */
17645b9c547cSRui Paulo 	for (i = 0; i < len; i++) {
17655b9c547cSRui Paulo 		if (val[i] == '\0') {
17665b9c547cSRui Paulo 			wpa_printf(MSG_DEBUG, "TLS: Embedded null in a string - reject");
17675b9c547cSRui Paulo 			return 0;
17685b9c547cSRui Paulo 		}
17695b9c547cSRui Paulo 	}
17705b9c547cSRui Paulo 
17715b9c547cSRui Paulo 	if (match_len > len || (full && match_len != len))
17725b9c547cSRui Paulo 		return 0;
17735b9c547cSRui Paulo 
17745b9c547cSRui Paulo 	if (os_strncasecmp((const char *) val + len - match_len, match,
17755b9c547cSRui Paulo 			   match_len) != 0)
17765b9c547cSRui Paulo 		return 0; /* no match */
17775b9c547cSRui Paulo 
17785b9c547cSRui Paulo 	if (match_len == len)
17795b9c547cSRui Paulo 		return 1; /* exact match */
17805b9c547cSRui Paulo 
17815b9c547cSRui Paulo 	if (val[len - match_len - 1] == '.')
17825b9c547cSRui Paulo 		return 1; /* full label match completes suffix match */
17835b9c547cSRui Paulo 
17845b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "TLS: Reject due to incomplete label match");
17855b9c547cSRui Paulo 	return 0;
17865b9c547cSRui Paulo }
17875b9c547cSRui Paulo #endif /* CONFIG_NATIVE_WINDOWS */
17885b9c547cSRui Paulo 
17895b9c547cSRui Paulo 
17904bc52338SCy Schubert struct tls_dn_field_order_cnt {
17914bc52338SCy Schubert 	u8 cn;
17924bc52338SCy Schubert 	u8 c;
17934bc52338SCy Schubert 	u8 l;
17944bc52338SCy Schubert 	u8 st;
17954bc52338SCy Schubert 	u8 o;
17964bc52338SCy Schubert 	u8 ou;
17974bc52338SCy Schubert 	u8 email;
17984bc52338SCy Schubert };
17994bc52338SCy Schubert 
18004bc52338SCy Schubert 
get_dn_field_index(const struct tls_dn_field_order_cnt * dn_cnt,int nid)18014bc52338SCy Schubert static int get_dn_field_index(const struct tls_dn_field_order_cnt *dn_cnt,
18024bc52338SCy Schubert 			      int nid)
18035b9c547cSRui Paulo {
18044bc52338SCy Schubert 	switch (nid) {
18054bc52338SCy Schubert 	case NID_commonName:
18064bc52338SCy Schubert 		return dn_cnt->cn;
18074bc52338SCy Schubert 	case NID_countryName:
18084bc52338SCy Schubert 		return dn_cnt->c;
18094bc52338SCy Schubert 	case NID_localityName:
18104bc52338SCy Schubert 		return dn_cnt->l;
18114bc52338SCy Schubert 	case NID_stateOrProvinceName:
18124bc52338SCy Schubert 		return dn_cnt->st;
18134bc52338SCy Schubert 	case NID_organizationName:
18144bc52338SCy Schubert 		return dn_cnt->o;
18154bc52338SCy Schubert 	case NID_organizationalUnitName:
18164bc52338SCy Schubert 		return dn_cnt->ou;
18174bc52338SCy Schubert 	case NID_pkcs9_emailAddress:
18184bc52338SCy Schubert 		return dn_cnt->email;
18194bc52338SCy Schubert 	default:
18204bc52338SCy Schubert 		wpa_printf(MSG_ERROR,
18214bc52338SCy Schubert 			   "TLS: Unknown NID '%d' in check_cert_subject",
18224bc52338SCy Schubert 			   nid);
18235b9c547cSRui Paulo 		return -1;
18244bc52338SCy Schubert 	}
18254bc52338SCy Schubert }
18264bc52338SCy Schubert 
18274bc52338SCy Schubert 
18284bc52338SCy Schubert /**
18294bc52338SCy Schubert  * match_dn_field - Match configuration DN field against Certificate DN field
18304bc52338SCy Schubert  * @cert: Certificate
18314bc52338SCy Schubert  * @nid: NID of DN field
18324bc52338SCy Schubert  * @field: Field name
18334bc52338SCy Schubert  * @value DN field value which is passed from configuration
18344bc52338SCy Schubert  *	e.g., if configuration have C=US and this argument will point to US.
18354bc52338SCy Schubert  * @dn_cnt: DN matching context
18364bc52338SCy Schubert  * Returns: 1 on success and 0 on failure
18374bc52338SCy Schubert  */
match_dn_field(const X509 * cert,int nid,const char * field,const char * value,const struct tls_dn_field_order_cnt * dn_cnt)18384bc52338SCy Schubert static int match_dn_field(const X509 *cert, int nid, const char *field,
18394bc52338SCy Schubert 			  const char *value,
18404bc52338SCy Schubert 			  const struct tls_dn_field_order_cnt *dn_cnt)
18414bc52338SCy Schubert {
18424bc52338SCy Schubert 	int i, ret = 0, len, config_dn_field_index, match_index = 0;
18434bc52338SCy Schubert 	X509_NAME *name;
18444bc52338SCy Schubert 
18454bc52338SCy Schubert 	len = os_strlen(value);
18464bc52338SCy Schubert 	name = X509_get_subject_name((X509 *) cert);
18474bc52338SCy Schubert 
18484bc52338SCy Schubert 	/* Assign incremented cnt for every field of DN to check DN field in
18494bc52338SCy Schubert 	 * right order */
18504bc52338SCy Schubert 	config_dn_field_index = get_dn_field_index(dn_cnt, nid);
18514bc52338SCy Schubert 	if (config_dn_field_index < 0)
18524bc52338SCy Schubert 		return 0;
18534bc52338SCy Schubert 
18544bc52338SCy Schubert 	/* Fetch value based on NID */
18554bc52338SCy Schubert 	for (i = -1; (i = X509_NAME_get_index_by_NID(name, nid, i)) > -1;) {
18564bc52338SCy Schubert 		X509_NAME_ENTRY *e;
18574bc52338SCy Schubert 		ASN1_STRING *cn;
18584bc52338SCy Schubert 
18594bc52338SCy Schubert 		e = X509_NAME_get_entry(name, i);
18604bc52338SCy Schubert 		if (!e)
18614bc52338SCy Schubert 			continue;
18624bc52338SCy Schubert 
18634bc52338SCy Schubert 		cn = X509_NAME_ENTRY_get_data(e);
18644bc52338SCy Schubert 		if (!cn)
18654bc52338SCy Schubert 			continue;
18664bc52338SCy Schubert 
18674bc52338SCy Schubert 		match_index++;
18684bc52338SCy Schubert 
18694bc52338SCy Schubert 		/* check for more than one DN field with same name */
18704bc52338SCy Schubert 		if (match_index != config_dn_field_index)
18714bc52338SCy Schubert 			continue;
18724bc52338SCy Schubert 
18734bc52338SCy Schubert 		/* Check wildcard at the right end side */
18744bc52338SCy Schubert 		/* E.g., if OU=develop* mentioned in configuration, allow 'OU'
18754bc52338SCy Schubert 		 * of the subject in the client certificate to start with
18764bc52338SCy Schubert 		 * 'develop' */
18774bc52338SCy Schubert 		if (len > 0 && value[len - 1] == '*') {
18784bc52338SCy Schubert 			/* Compare actual certificate DN field value with
18794bc52338SCy Schubert 			 * configuration DN field value up to the specified
18804bc52338SCy Schubert 			 * length. */
18814bc52338SCy Schubert 			ret = ASN1_STRING_length(cn) >= len - 1 &&
18824bc52338SCy Schubert 				os_memcmp(ASN1_STRING_get0_data(cn), value,
18834bc52338SCy Schubert 					  len - 1) == 0;
18844bc52338SCy Schubert 		} else {
18854bc52338SCy Schubert 			/* Compare actual certificate DN field value with
18864bc52338SCy Schubert 			 * configuration DN field value */
18874bc52338SCy Schubert 			ret = ASN1_STRING_length(cn) == len &&
18884bc52338SCy Schubert 				os_memcmp(ASN1_STRING_get0_data(cn), value,
18894bc52338SCy Schubert 					  len) == 0;
18904bc52338SCy Schubert 		}
18914bc52338SCy Schubert 		if (!ret) {
18924bc52338SCy Schubert 			wpa_printf(MSG_ERROR,
18934bc52338SCy Schubert 				   "OpenSSL: Failed to match %s '%s' with certificate DN field value '%s'",
18944bc52338SCy Schubert 				   field, value, ASN1_STRING_get0_data(cn));
18954bc52338SCy Schubert 		}
18964bc52338SCy Schubert 		break;
18974bc52338SCy Schubert 	}
18984bc52338SCy Schubert 
18994bc52338SCy Schubert 	return ret;
19004bc52338SCy Schubert }
19014bc52338SCy Schubert 
19024bc52338SCy Schubert 
19034bc52338SCy Schubert /**
19044bc52338SCy Schubert  * get_value_from_field - Get value from DN field
19054bc52338SCy Schubert  * @cert: Certificate
19064bc52338SCy Schubert  * @field_str: DN field string which is passed from configuration file (e.g.,
19074bc52338SCy Schubert  *	 C=US)
19084bc52338SCy Schubert  * @dn_cnt: DN matching context
19094bc52338SCy Schubert  * Returns: 1 on success and 0 on failure
19104bc52338SCy Schubert  */
get_value_from_field(const X509 * cert,char * field_str,struct tls_dn_field_order_cnt * dn_cnt)19114bc52338SCy Schubert static int get_value_from_field(const X509 *cert, char *field_str,
19124bc52338SCy Schubert 				struct tls_dn_field_order_cnt *dn_cnt)
19134bc52338SCy Schubert {
19144bc52338SCy Schubert 	int nid;
19154bc52338SCy Schubert 	char *context = NULL, *name, *value;
19164bc52338SCy Schubert 
19174bc52338SCy Schubert 	if (os_strcmp(field_str, "*") == 0)
19184bc52338SCy Schubert 		return 1; /* wildcard matches everything */
19194bc52338SCy Schubert 
19204bc52338SCy Schubert 	name = str_token(field_str, "=", &context);
19214bc52338SCy Schubert 	if (!name)
19224bc52338SCy Schubert 		return 0;
19234bc52338SCy Schubert 
19244bc52338SCy Schubert 	/* Compare all configured DN fields and assign nid based on that to
19254bc52338SCy Schubert 	 * fetch correct value from certificate subject */
19264bc52338SCy Schubert 	if (os_strcmp(name, "CN") == 0) {
19274bc52338SCy Schubert 		nid = NID_commonName;
19284bc52338SCy Schubert 		dn_cnt->cn++;
19294bc52338SCy Schubert 	} else if(os_strcmp(name, "C") == 0) {
19304bc52338SCy Schubert 		nid = NID_countryName;
19314bc52338SCy Schubert 		dn_cnt->c++;
19324bc52338SCy Schubert 	} else if (os_strcmp(name, "L") == 0) {
19334bc52338SCy Schubert 		nid = NID_localityName;
19344bc52338SCy Schubert 		dn_cnt->l++;
19354bc52338SCy Schubert 	} else if (os_strcmp(name, "ST") == 0) {
19364bc52338SCy Schubert 		nid = NID_stateOrProvinceName;
19374bc52338SCy Schubert 		dn_cnt->st++;
19384bc52338SCy Schubert 	} else if (os_strcmp(name, "O") == 0) {
19394bc52338SCy Schubert 		nid = NID_organizationName;
19404bc52338SCy Schubert 		dn_cnt->o++;
19414bc52338SCy Schubert 	} else if (os_strcmp(name, "OU") == 0) {
19424bc52338SCy Schubert 		nid = NID_organizationalUnitName;
19434bc52338SCy Schubert 		dn_cnt->ou++;
19444bc52338SCy Schubert 	} else if (os_strcmp(name, "emailAddress") == 0) {
19454bc52338SCy Schubert 		nid = NID_pkcs9_emailAddress;
19464bc52338SCy Schubert 		dn_cnt->email++;
19474bc52338SCy Schubert 	} else {
19484bc52338SCy Schubert 		wpa_printf(MSG_ERROR,
19494bc52338SCy Schubert 			"TLS: Unknown field '%s' in check_cert_subject", name);
19504bc52338SCy Schubert 		return 0;
19514bc52338SCy Schubert 	}
19524bc52338SCy Schubert 
19534bc52338SCy Schubert 	value = str_token(field_str, "=", &context);
19544bc52338SCy Schubert 	if (!value) {
19554bc52338SCy Schubert 		wpa_printf(MSG_ERROR,
19564bc52338SCy Schubert 			   "TLS: Distinguished Name field '%s' value is not defined in check_cert_subject",
19574bc52338SCy Schubert 			   name);
19584bc52338SCy Schubert 		return 0;
19594bc52338SCy Schubert 	}
19604bc52338SCy Schubert 
19614bc52338SCy Schubert 	return match_dn_field(cert, nid, name, value, dn_cnt);
19624bc52338SCy Schubert }
19634bc52338SCy Schubert 
19644bc52338SCy Schubert 
19654bc52338SCy Schubert /**
19664bc52338SCy Schubert  * tls_match_dn_field - Match subject DN field with check_cert_subject
19674bc52338SCy Schubert  * @cert: Certificate
19684bc52338SCy Schubert  * @match: check_cert_subject string
19694bc52338SCy Schubert  * Returns: Return 1 on success and 0 on failure
19704bc52338SCy Schubert */
tls_match_dn_field(X509 * cert,const char * match)19714bc52338SCy Schubert static int tls_match_dn_field(X509 *cert, const char *match)
19724bc52338SCy Schubert {
19734bc52338SCy Schubert 	const char *token, *last = NULL;
19744bc52338SCy Schubert 	char field[256];
19754bc52338SCy Schubert 	struct tls_dn_field_order_cnt dn_cnt;
19764bc52338SCy Schubert 
19774bc52338SCy Schubert 	os_memset(&dn_cnt, 0, sizeof(dn_cnt));
19784bc52338SCy Schubert 
19794bc52338SCy Schubert 	/* Maximum length of each DN field is 255 characters */
19804bc52338SCy Schubert 
19814bc52338SCy Schubert 	/* Process each '/' delimited field */
19824bc52338SCy Schubert 	while ((token = cstr_token(match, "/", &last))) {
19834bc52338SCy Schubert 		if (last - token >= (int) sizeof(field)) {
19844bc52338SCy Schubert 			wpa_printf(MSG_ERROR,
19854bc52338SCy Schubert 				   "OpenSSL: Too long DN matching field value in '%s'",
19864bc52338SCy Schubert 				   match);
19874bc52338SCy Schubert 			return 0;
19884bc52338SCy Schubert 		}
19894bc52338SCy Schubert 		os_memcpy(field, token, last - token);
19904bc52338SCy Schubert 		field[last - token] = '\0';
19914bc52338SCy Schubert 
19924bc52338SCy Schubert 		if (!get_value_from_field(cert, field, &dn_cnt)) {
19934bc52338SCy Schubert 			wpa_printf(MSG_DEBUG, "OpenSSL: No match for DN '%s'",
19944bc52338SCy Schubert 				   field);
19954bc52338SCy Schubert 			return 0;
19964bc52338SCy Schubert 		}
19974bc52338SCy Schubert 	}
19984bc52338SCy Schubert 
19994bc52338SCy Schubert 	return 1;
20004bc52338SCy Schubert }
20014bc52338SCy Schubert 
20024bc52338SCy Schubert 
20034bc52338SCy Schubert #ifndef CONFIG_NATIVE_WINDOWS
tls_match_suffix_helper(X509 * cert,const char * match,size_t match_len,int full)20044bc52338SCy Schubert static int tls_match_suffix_helper(X509 *cert, const char *match,
20054bc52338SCy Schubert 				   size_t match_len, int full)
20064bc52338SCy Schubert {
20075b9c547cSRui Paulo 	GENERAL_NAME *gen;
20085b9c547cSRui Paulo 	void *ext;
20095b9c547cSRui Paulo 	int i;
20105b9c547cSRui Paulo 	stack_index_t j;
20115b9c547cSRui Paulo 	int dns_name = 0;
20125b9c547cSRui Paulo 	X509_NAME *name;
20135b9c547cSRui Paulo 
20145b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "TLS: Match domain against %s%s",
20155b9c547cSRui Paulo 		   full ? "": "suffix ", match);
20165b9c547cSRui Paulo 
20175b9c547cSRui Paulo 	ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
20185b9c547cSRui Paulo 
20195b9c547cSRui Paulo 	for (j = 0; ext && j < sk_GENERAL_NAME_num(ext); j++) {
20205b9c547cSRui Paulo 		gen = sk_GENERAL_NAME_value(ext, j);
20215b9c547cSRui Paulo 		if (gen->type != GEN_DNS)
20225b9c547cSRui Paulo 			continue;
20235b9c547cSRui Paulo 		dns_name++;
20245b9c547cSRui Paulo 		wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate dNSName",
20255b9c547cSRui Paulo 				  gen->d.dNSName->data,
20265b9c547cSRui Paulo 				  gen->d.dNSName->length);
20275b9c547cSRui Paulo 		if (domain_suffix_match(gen->d.dNSName->data,
20284bc52338SCy Schubert 					gen->d.dNSName->length,
20294bc52338SCy Schubert 					match, match_len, full) == 1) {
20305b9c547cSRui Paulo 			wpa_printf(MSG_DEBUG, "TLS: %s in dNSName found",
20315b9c547cSRui Paulo 				   full ? "Match" : "Suffix match");
2032780fb4a2SCy Schubert 			sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
20335b9c547cSRui Paulo 			return 1;
20345b9c547cSRui Paulo 		}
20355b9c547cSRui Paulo 	}
2036780fb4a2SCy Schubert 	sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
20375b9c547cSRui Paulo 
20385b9c547cSRui Paulo 	if (dns_name) {
20395b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "TLS: None of the dNSName(s) matched");
20405b9c547cSRui Paulo 		return 0;
20415b9c547cSRui Paulo 	}
20425b9c547cSRui Paulo 
20435b9c547cSRui Paulo 	name = X509_get_subject_name(cert);
20445b9c547cSRui Paulo 	i = -1;
20455b9c547cSRui Paulo 	for (;;) {
20465b9c547cSRui Paulo 		X509_NAME_ENTRY *e;
20475b9c547cSRui Paulo 		ASN1_STRING *cn;
20485b9c547cSRui Paulo 
20495b9c547cSRui Paulo 		i = X509_NAME_get_index_by_NID(name, NID_commonName, i);
20505b9c547cSRui Paulo 		if (i == -1)
20515b9c547cSRui Paulo 			break;
20525b9c547cSRui Paulo 		e = X509_NAME_get_entry(name, i);
20535b9c547cSRui Paulo 		if (e == NULL)
20545b9c547cSRui Paulo 			continue;
20555b9c547cSRui Paulo 		cn = X509_NAME_ENTRY_get_data(e);
20565b9c547cSRui Paulo 		if (cn == NULL)
20575b9c547cSRui Paulo 			continue;
20585b9c547cSRui Paulo 		wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate commonName",
20595b9c547cSRui Paulo 				  cn->data, cn->length);
20604bc52338SCy Schubert 		if (domain_suffix_match(cn->data, cn->length,
20614bc52338SCy Schubert 					match, match_len, full) == 1) {
20625b9c547cSRui Paulo 			wpa_printf(MSG_DEBUG, "TLS: %s in commonName found",
20635b9c547cSRui Paulo 				   full ? "Match" : "Suffix match");
20645b9c547cSRui Paulo 			return 1;
20655b9c547cSRui Paulo 		}
20665b9c547cSRui Paulo 	}
20675b9c547cSRui Paulo 
20685b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "TLS: No CommonName %smatch found",
20695b9c547cSRui Paulo 		   full ? "": "suffix ");
20705b9c547cSRui Paulo 	return 0;
20714bc52338SCy Schubert }
20724bc52338SCy Schubert #endif /* CONFIG_NATIVE_WINDOWS */
20734bc52338SCy Schubert 
20744bc52338SCy Schubert 
tls_match_suffix(X509 * cert,const char * match,int full)20754bc52338SCy Schubert static int tls_match_suffix(X509 *cert, const char *match, int full)
20764bc52338SCy Schubert {
20774bc52338SCy Schubert #ifdef CONFIG_NATIVE_WINDOWS
20784bc52338SCy Schubert 	/* wincrypt.h has conflicting X509_NAME definition */
20794bc52338SCy Schubert 	return -1;
20804bc52338SCy Schubert #else /* CONFIG_NATIVE_WINDOWS */
20814bc52338SCy Schubert 	const char *token, *last = NULL;
20824bc52338SCy Schubert 
20834bc52338SCy Schubert 	/* Process each match alternative separately until a match is found */
20844bc52338SCy Schubert 	while ((token = cstr_token(match, ";", &last))) {
20854bc52338SCy Schubert 		if (tls_match_suffix_helper(cert, token, last - token, full))
20864bc52338SCy Schubert 			return 1;
20874bc52338SCy Schubert 	}
20884bc52338SCy Schubert 
20894bc52338SCy Schubert 	return 0;
20905b9c547cSRui Paulo #endif /* CONFIG_NATIVE_WINDOWS */
20915b9c547cSRui Paulo }
20925b9c547cSRui Paulo 
20935b9c547cSRui Paulo 
openssl_tls_fail_reason(int err)2094e28a4053SRui Paulo static enum tls_fail_reason openssl_tls_fail_reason(int err)
2095e28a4053SRui Paulo {
2096e28a4053SRui Paulo 	switch (err) {
2097e28a4053SRui Paulo 	case X509_V_ERR_CERT_REVOKED:
2098e28a4053SRui Paulo 		return TLS_FAIL_REVOKED;
2099e28a4053SRui Paulo 	case X509_V_ERR_CERT_NOT_YET_VALID:
2100e28a4053SRui Paulo 	case X509_V_ERR_CRL_NOT_YET_VALID:
2101e28a4053SRui Paulo 		return TLS_FAIL_NOT_YET_VALID;
2102e28a4053SRui Paulo 	case X509_V_ERR_CERT_HAS_EXPIRED:
2103e28a4053SRui Paulo 	case X509_V_ERR_CRL_HAS_EXPIRED:
2104e28a4053SRui Paulo 		return TLS_FAIL_EXPIRED;
2105e28a4053SRui Paulo 	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
2106e28a4053SRui Paulo 	case X509_V_ERR_UNABLE_TO_GET_CRL:
2107e28a4053SRui Paulo 	case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
2108e28a4053SRui Paulo 	case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
2109e28a4053SRui Paulo 	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
2110e28a4053SRui Paulo 	case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
2111e28a4053SRui Paulo 	case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
2112e28a4053SRui Paulo 	case X509_V_ERR_CERT_CHAIN_TOO_LONG:
2113e28a4053SRui Paulo 	case X509_V_ERR_PATH_LENGTH_EXCEEDED:
2114e28a4053SRui Paulo 	case X509_V_ERR_INVALID_CA:
2115e28a4053SRui Paulo 		return TLS_FAIL_UNTRUSTED;
2116e28a4053SRui Paulo 	case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
2117e28a4053SRui Paulo 	case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
2118e28a4053SRui Paulo 	case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
2119e28a4053SRui Paulo 	case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
2120e28a4053SRui Paulo 	case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
2121e28a4053SRui Paulo 	case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
2122e28a4053SRui Paulo 	case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
2123e28a4053SRui Paulo 	case X509_V_ERR_CERT_UNTRUSTED:
2124e28a4053SRui Paulo 	case X509_V_ERR_CERT_REJECTED:
2125e28a4053SRui Paulo 		return TLS_FAIL_BAD_CERTIFICATE;
2126e28a4053SRui Paulo 	default:
2127e28a4053SRui Paulo 		return TLS_FAIL_UNSPECIFIED;
2128e28a4053SRui Paulo 	}
2129e28a4053SRui Paulo }
2130e28a4053SRui Paulo 
2131e28a4053SRui Paulo 
get_x509_cert(X509 * cert)2132e28a4053SRui Paulo static struct wpabuf * get_x509_cert(X509 *cert)
2133e28a4053SRui Paulo {
2134e28a4053SRui Paulo 	struct wpabuf *buf;
2135e28a4053SRui Paulo 	u8 *tmp;
2136e28a4053SRui Paulo 
2137e28a4053SRui Paulo 	int cert_len = i2d_X509(cert, NULL);
2138e28a4053SRui Paulo 	if (cert_len <= 0)
2139e28a4053SRui Paulo 		return NULL;
2140e28a4053SRui Paulo 
2141e28a4053SRui Paulo 	buf = wpabuf_alloc(cert_len);
2142e28a4053SRui Paulo 	if (buf == NULL)
2143e28a4053SRui Paulo 		return NULL;
2144e28a4053SRui Paulo 
2145e28a4053SRui Paulo 	tmp = wpabuf_put(buf, cert_len);
2146e28a4053SRui Paulo 	i2d_X509(cert, &tmp);
2147e28a4053SRui Paulo 	return buf;
2148e28a4053SRui Paulo }
2149e28a4053SRui Paulo 
2150e28a4053SRui Paulo 
openssl_tls_fail_event(struct tls_connection * conn,X509 * err_cert,int err,int depth,const char * subject,const char * err_str,enum tls_fail_reason reason)2151e28a4053SRui Paulo static void openssl_tls_fail_event(struct tls_connection *conn,
2152e28a4053SRui Paulo 				   X509 *err_cert, int err, int depth,
2153e28a4053SRui Paulo 				   const char *subject, const char *err_str,
2154e28a4053SRui Paulo 				   enum tls_fail_reason reason)
2155e28a4053SRui Paulo {
2156e28a4053SRui Paulo 	union tls_event_data ev;
2157e28a4053SRui Paulo 	struct wpabuf *cert = NULL;
21585b9c547cSRui Paulo 	struct tls_context *context = conn->context;
2159e28a4053SRui Paulo 
21605b9c547cSRui Paulo 	if (context->event_cb == NULL)
2161e28a4053SRui Paulo 		return;
2162e28a4053SRui Paulo 
2163e28a4053SRui Paulo 	cert = get_x509_cert(err_cert);
2164e28a4053SRui Paulo 	os_memset(&ev, 0, sizeof(ev));
2165e28a4053SRui Paulo 	ev.cert_fail.reason = reason != TLS_FAIL_UNSPECIFIED ?
2166e28a4053SRui Paulo 		reason : openssl_tls_fail_reason(err);
2167e28a4053SRui Paulo 	ev.cert_fail.depth = depth;
2168e28a4053SRui Paulo 	ev.cert_fail.subject = subject;
2169e28a4053SRui Paulo 	ev.cert_fail.reason_txt = err_str;
2170e28a4053SRui Paulo 	ev.cert_fail.cert = cert;
21715b9c547cSRui Paulo 	context->event_cb(context->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
2172e28a4053SRui Paulo 	wpabuf_free(cert);
2173e28a4053SRui Paulo }
2174e28a4053SRui Paulo 
2175e28a4053SRui Paulo 
openssl_cert_tod(X509 * cert)2176206b73d0SCy Schubert static int openssl_cert_tod(X509 *cert)
2177206b73d0SCy Schubert {
2178206b73d0SCy Schubert 	CERTIFICATEPOLICIES *ext;
2179206b73d0SCy Schubert 	stack_index_t i;
2180206b73d0SCy Schubert 	char buf[100];
2181206b73d0SCy Schubert 	int res;
2182206b73d0SCy Schubert 	int tod = 0;
2183206b73d0SCy Schubert 
2184206b73d0SCy Schubert 	ext = X509_get_ext_d2i(cert, NID_certificate_policies, NULL, NULL);
2185206b73d0SCy Schubert 	if (!ext)
2186206b73d0SCy Schubert 		return 0;
2187206b73d0SCy Schubert 
2188206b73d0SCy Schubert 	for (i = 0; i < sk_POLICYINFO_num(ext); i++) {
2189206b73d0SCy Schubert 		POLICYINFO *policy;
2190206b73d0SCy Schubert 
2191206b73d0SCy Schubert 		policy = sk_POLICYINFO_value(ext, i);
2192206b73d0SCy Schubert 		res = OBJ_obj2txt(buf, sizeof(buf), policy->policyid, 0);
2193206b73d0SCy Schubert 		if (res < 0 || (size_t) res >= sizeof(buf))
2194206b73d0SCy Schubert 			continue;
2195206b73d0SCy Schubert 		wpa_printf(MSG_DEBUG, "OpenSSL: Certificate Policy %s", buf);
2196206b73d0SCy Schubert 		if (os_strcmp(buf, "1.3.6.1.4.1.40808.1.3.1") == 0)
2197c1d255d3SCy Schubert 			tod = 1; /* TOD-STRICT */
2198c1d255d3SCy Schubert 		else if (os_strcmp(buf, "1.3.6.1.4.1.40808.1.3.2") == 0 && !tod)
2199c1d255d3SCy Schubert 			tod = 2; /* TOD-TOFU */
2200206b73d0SCy Schubert 	}
2201c1d255d3SCy Schubert 	sk_POLICYINFO_pop_free(ext, POLICYINFO_free);
2202206b73d0SCy Schubert 
2203206b73d0SCy Schubert 	return tod;
2204206b73d0SCy Schubert }
2205206b73d0SCy Schubert 
2206206b73d0SCy Schubert 
openssl_tls_cert_event(struct tls_connection * conn,X509 * err_cert,int depth,const char * subject)2207e28a4053SRui Paulo static void openssl_tls_cert_event(struct tls_connection *conn,
2208e28a4053SRui Paulo 				   X509 *err_cert, int depth,
2209e28a4053SRui Paulo 				   const char *subject)
2210e28a4053SRui Paulo {
2211e28a4053SRui Paulo 	struct wpabuf *cert = NULL;
2212e28a4053SRui Paulo 	union tls_event_data ev;
22135b9c547cSRui Paulo 	struct tls_context *context = conn->context;
22145b9c547cSRui Paulo 	char *altsubject[TLS_MAX_ALT_SUBJECT];
22155b9c547cSRui Paulo 	int alt, num_altsubject = 0;
22165b9c547cSRui Paulo 	GENERAL_NAME *gen;
22175b9c547cSRui Paulo 	void *ext;
22185b9c547cSRui Paulo 	stack_index_t i;
221985732ac8SCy Schubert 	ASN1_INTEGER *ser;
222085732ac8SCy Schubert 	char serial_num[128];
2221e28a4053SRui Paulo #ifdef CONFIG_SHA256
2222e28a4053SRui Paulo 	u8 hash[32];
2223e28a4053SRui Paulo #endif /* CONFIG_SHA256 */
2224e28a4053SRui Paulo 
22255b9c547cSRui Paulo 	if (context->event_cb == NULL)
2226e28a4053SRui Paulo 		return;
2227e28a4053SRui Paulo 
2228e28a4053SRui Paulo 	os_memset(&ev, 0, sizeof(ev));
2229780fb4a2SCy Schubert 	if (conn->cert_probe || (conn->flags & TLS_CONN_EXT_CERT_CHECK) ||
2230780fb4a2SCy Schubert 	    context->cert_in_cb) {
2231e28a4053SRui Paulo 		cert = get_x509_cert(err_cert);
2232e28a4053SRui Paulo 		ev.peer_cert.cert = cert;
2233e28a4053SRui Paulo 	}
2234e28a4053SRui Paulo #ifdef CONFIG_SHA256
2235e28a4053SRui Paulo 	if (cert) {
2236e28a4053SRui Paulo 		const u8 *addr[1];
2237e28a4053SRui Paulo 		size_t len[1];
2238e28a4053SRui Paulo 		addr[0] = wpabuf_head(cert);
2239e28a4053SRui Paulo 		len[0] = wpabuf_len(cert);
2240e28a4053SRui Paulo 		if (sha256_vector(1, addr, len, hash) == 0) {
2241e28a4053SRui Paulo 			ev.peer_cert.hash = hash;
2242e28a4053SRui Paulo 			ev.peer_cert.hash_len = sizeof(hash);
2243e28a4053SRui Paulo 		}
2244e28a4053SRui Paulo 	}
2245e28a4053SRui Paulo #endif /* CONFIG_SHA256 */
2246e28a4053SRui Paulo 	ev.peer_cert.depth = depth;
2247e28a4053SRui Paulo 	ev.peer_cert.subject = subject;
22485b9c547cSRui Paulo 
224985732ac8SCy Schubert 	ser = X509_get_serialNumber(err_cert);
225085732ac8SCy Schubert 	if (ser) {
225185732ac8SCy Schubert 		wpa_snprintf_hex_uppercase(serial_num, sizeof(serial_num),
225285732ac8SCy Schubert 					   ASN1_STRING_get0_data(ser),
225385732ac8SCy Schubert 					   ASN1_STRING_length(ser));
225485732ac8SCy Schubert 		ev.peer_cert.serial_num = serial_num;
225585732ac8SCy Schubert 	}
225685732ac8SCy Schubert 
22575b9c547cSRui Paulo 	ext = X509_get_ext_d2i(err_cert, NID_subject_alt_name, NULL, NULL);
22585b9c547cSRui Paulo 	for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
22595b9c547cSRui Paulo 		char *pos;
22605b9c547cSRui Paulo 
22615b9c547cSRui Paulo 		if (num_altsubject == TLS_MAX_ALT_SUBJECT)
22625b9c547cSRui Paulo 			break;
22635b9c547cSRui Paulo 		gen = sk_GENERAL_NAME_value(ext, i);
22645b9c547cSRui Paulo 		if (gen->type != GEN_EMAIL &&
22655b9c547cSRui Paulo 		    gen->type != GEN_DNS &&
22665b9c547cSRui Paulo 		    gen->type != GEN_URI)
22675b9c547cSRui Paulo 			continue;
22685b9c547cSRui Paulo 
22695b9c547cSRui Paulo 		pos = os_malloc(10 + gen->d.ia5->length + 1);
22705b9c547cSRui Paulo 		if (pos == NULL)
22715b9c547cSRui Paulo 			break;
22725b9c547cSRui Paulo 		altsubject[num_altsubject++] = pos;
22735b9c547cSRui Paulo 
22745b9c547cSRui Paulo 		switch (gen->type) {
22755b9c547cSRui Paulo 		case GEN_EMAIL:
22765b9c547cSRui Paulo 			os_memcpy(pos, "EMAIL:", 6);
22775b9c547cSRui Paulo 			pos += 6;
22785b9c547cSRui Paulo 			break;
22795b9c547cSRui Paulo 		case GEN_DNS:
22805b9c547cSRui Paulo 			os_memcpy(pos, "DNS:", 4);
22815b9c547cSRui Paulo 			pos += 4;
22825b9c547cSRui Paulo 			break;
22835b9c547cSRui Paulo 		case GEN_URI:
22845b9c547cSRui Paulo 			os_memcpy(pos, "URI:", 4);
22855b9c547cSRui Paulo 			pos += 4;
22865b9c547cSRui Paulo 			break;
22875b9c547cSRui Paulo 		}
22885b9c547cSRui Paulo 
22895b9c547cSRui Paulo 		os_memcpy(pos, gen->d.ia5->data, gen->d.ia5->length);
22905b9c547cSRui Paulo 		pos += gen->d.ia5->length;
22915b9c547cSRui Paulo 		*pos = '\0';
22925b9c547cSRui Paulo 	}
2293780fb4a2SCy Schubert 	sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
22945b9c547cSRui Paulo 
22955b9c547cSRui Paulo 	for (alt = 0; alt < num_altsubject; alt++)
22965b9c547cSRui Paulo 		ev.peer_cert.altsubject[alt] = altsubject[alt];
22975b9c547cSRui Paulo 	ev.peer_cert.num_altsubject = num_altsubject;
22985b9c547cSRui Paulo 
2299206b73d0SCy Schubert 	ev.peer_cert.tod = openssl_cert_tod(err_cert);
2300206b73d0SCy Schubert 
23015b9c547cSRui Paulo 	context->event_cb(context->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
2302e28a4053SRui Paulo 	wpabuf_free(cert);
23035b9c547cSRui Paulo 	for (alt = 0; alt < num_altsubject; alt++)
23045b9c547cSRui Paulo 		os_free(altsubject[alt]);
2305e28a4053SRui Paulo }
2306e28a4053SRui Paulo 
2307e28a4053SRui Paulo 
debug_print_cert(X509 * cert,const char * title)2308c1d255d3SCy Schubert static void debug_print_cert(X509 *cert, const char *title)
2309c1d255d3SCy Schubert {
2310c1d255d3SCy Schubert #ifndef CONFIG_NO_STDOUT_DEBUG
2311c1d255d3SCy Schubert 	BIO *out;
2312c1d255d3SCy Schubert 	size_t rlen;
2313c1d255d3SCy Schubert 	char *txt;
2314c1d255d3SCy Schubert 	int res;
2315c1d255d3SCy Schubert 
2316c1d255d3SCy Schubert 	if (wpa_debug_level > MSG_DEBUG)
2317c1d255d3SCy Schubert 		return;
2318c1d255d3SCy Schubert 
2319c1d255d3SCy Schubert 	out = BIO_new(BIO_s_mem());
2320c1d255d3SCy Schubert 	if (!out)
2321c1d255d3SCy Schubert 		return;
2322c1d255d3SCy Schubert 
2323c1d255d3SCy Schubert 	X509_print(out, cert);
2324c1d255d3SCy Schubert 	rlen = BIO_ctrl_pending(out);
2325c1d255d3SCy Schubert 	txt = os_malloc(rlen + 1);
2326c1d255d3SCy Schubert 	if (txt) {
2327c1d255d3SCy Schubert 		res = BIO_read(out, txt, rlen);
2328c1d255d3SCy Schubert 		if (res > 0) {
2329c1d255d3SCy Schubert 			txt[res] = '\0';
2330c1d255d3SCy Schubert 			wpa_printf(MSG_DEBUG, "OpenSSL: %s\n%s", title, txt);
2331c1d255d3SCy Schubert 		}
2332c1d255d3SCy Schubert 		os_free(txt);
2333c1d255d3SCy Schubert 	}
2334c1d255d3SCy Schubert 
2335c1d255d3SCy Schubert 	BIO_free(out);
2336c1d255d3SCy Schubert #endif /* CONFIG_NO_STDOUT_DEBUG */
2337c1d255d3SCy Schubert }
2338c1d255d3SCy Schubert 
2339c1d255d3SCy Schubert 
tls_verify_cb(int preverify_ok,X509_STORE_CTX * x509_ctx)234039beb93cSSam Leffler static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
234139beb93cSSam Leffler {
234239beb93cSSam Leffler 	char buf[256];
234339beb93cSSam Leffler 	X509 *err_cert;
234439beb93cSSam Leffler 	int err, depth;
234539beb93cSSam Leffler 	SSL *ssl;
234639beb93cSSam Leffler 	struct tls_connection *conn;
23475b9c547cSRui Paulo 	struct tls_context *context;
23485b9c547cSRui Paulo 	char *match, *altmatch, *suffix_match, *domain_match;
23494bc52338SCy Schubert 	const char *check_cert_subject;
2350e28a4053SRui Paulo 	const char *err_str;
235139beb93cSSam Leffler 
235239beb93cSSam Leffler 	err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
23535b9c547cSRui Paulo 	if (!err_cert)
23545b9c547cSRui Paulo 		return 0;
23555b9c547cSRui Paulo 
235639beb93cSSam Leffler 	err = X509_STORE_CTX_get_error(x509_ctx);
235739beb93cSSam Leffler 	depth = X509_STORE_CTX_get_error_depth(x509_ctx);
235839beb93cSSam Leffler 	ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
235939beb93cSSam Leffler 					 SSL_get_ex_data_X509_STORE_CTX_idx());
2360c1d255d3SCy Schubert 	os_snprintf(buf, sizeof(buf), "Peer certificate - depth %d", depth);
2361c1d255d3SCy Schubert 	debug_print_cert(err_cert, buf);
236239beb93cSSam Leffler 	X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
236339beb93cSSam Leffler 
236439beb93cSSam Leffler 	conn = SSL_get_app_data(ssl);
2365f05cddf9SRui Paulo 	if (conn == NULL)
2366f05cddf9SRui Paulo 		return 0;
23675b9c547cSRui Paulo 
23685b9c547cSRui Paulo 	if (depth == 0)
23695b9c547cSRui Paulo 		conn->peer_cert = err_cert;
23705b9c547cSRui Paulo 	else if (depth == 1)
23715b9c547cSRui Paulo 		conn->peer_issuer = err_cert;
23725b9c547cSRui Paulo 	else if (depth == 2)
23735b9c547cSRui Paulo 		conn->peer_issuer_issuer = err_cert;
23745b9c547cSRui Paulo 
23755b9c547cSRui Paulo 	context = conn->context;
2376f05cddf9SRui Paulo 	match = conn->subject_match;
2377f05cddf9SRui Paulo 	altmatch = conn->altsubject_match;
23785b9c547cSRui Paulo 	suffix_match = conn->suffix_match;
23795b9c547cSRui Paulo 	domain_match = conn->domain_match;
238039beb93cSSam Leffler 
2381e28a4053SRui Paulo 	if (!preverify_ok && !conn->ca_cert_verify)
2382e28a4053SRui Paulo 		preverify_ok = 1;
2383e28a4053SRui Paulo 	if (!preverify_ok && depth > 0 && conn->server_cert_only)
2384e28a4053SRui Paulo 		preverify_ok = 1;
2385f05cddf9SRui Paulo 	if (!preverify_ok && (conn->flags & TLS_CONN_DISABLE_TIME_CHECKS) &&
2386f05cddf9SRui Paulo 	    (err == X509_V_ERR_CERT_HAS_EXPIRED ||
2387f05cddf9SRui Paulo 	     err == X509_V_ERR_CERT_NOT_YET_VALID)) {
2388f05cddf9SRui Paulo 		wpa_printf(MSG_DEBUG, "OpenSSL: Ignore certificate validity "
2389f05cddf9SRui Paulo 			   "time mismatch");
2390f05cddf9SRui Paulo 		preverify_ok = 1;
2391f05cddf9SRui Paulo 	}
23924bc52338SCy Schubert 	if (!preverify_ok && !conn->data->check_crl_strict &&
23934bc52338SCy Schubert 	    (err == X509_V_ERR_CRL_HAS_EXPIRED ||
23944bc52338SCy Schubert 	     err == X509_V_ERR_CRL_NOT_YET_VALID)) {
23954bc52338SCy Schubert 		wpa_printf(MSG_DEBUG,
23964bc52338SCy Schubert 			   "OpenSSL: Ignore certificate validity CRL time mismatch");
23974bc52338SCy Schubert 		preverify_ok = 1;
23984bc52338SCy Schubert 	}
2399e28a4053SRui Paulo 
2400e28a4053SRui Paulo 	err_str = X509_verify_cert_error_string(err);
2401e28a4053SRui Paulo 
2402e28a4053SRui Paulo #ifdef CONFIG_SHA256
24035b9c547cSRui Paulo 	/*
24045b9c547cSRui Paulo 	 * Do not require preverify_ok so we can explicity allow otherwise
24055b9c547cSRui Paulo 	 * invalid pinned server certificates.
24065b9c547cSRui Paulo 	 */
24075b9c547cSRui Paulo 	if (depth == 0 && conn->server_cert_only) {
2408e28a4053SRui Paulo 		struct wpabuf *cert;
2409e28a4053SRui Paulo 		cert = get_x509_cert(err_cert);
2410e28a4053SRui Paulo 		if (!cert) {
2411e28a4053SRui Paulo 			wpa_printf(MSG_DEBUG, "OpenSSL: Could not fetch "
2412e28a4053SRui Paulo 				   "server certificate data");
2413e28a4053SRui Paulo 			preverify_ok = 0;
2414e28a4053SRui Paulo 		} else {
2415e28a4053SRui Paulo 			u8 hash[32];
2416e28a4053SRui Paulo 			const u8 *addr[1];
2417e28a4053SRui Paulo 			size_t len[1];
2418e28a4053SRui Paulo 			addr[0] = wpabuf_head(cert);
2419e28a4053SRui Paulo 			len[0] = wpabuf_len(cert);
2420e28a4053SRui Paulo 			if (sha256_vector(1, addr, len, hash) < 0 ||
2421e28a4053SRui Paulo 			    os_memcmp(conn->srv_cert_hash, hash, 32) != 0) {
2422e28a4053SRui Paulo 				err_str = "Server certificate mismatch";
2423e28a4053SRui Paulo 				err = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
2424e28a4053SRui Paulo 				preverify_ok = 0;
24255b9c547cSRui Paulo 			} else if (!preverify_ok) {
24265b9c547cSRui Paulo 				/*
24275b9c547cSRui Paulo 				 * Certificate matches pinned certificate, allow
24285b9c547cSRui Paulo 				 * regardless of other problems.
24295b9c547cSRui Paulo 				 */
24305b9c547cSRui Paulo 				wpa_printf(MSG_DEBUG,
24315b9c547cSRui Paulo 					   "OpenSSL: Ignore validation issues for a pinned server certificate");
24325b9c547cSRui Paulo 				preverify_ok = 1;
2433e28a4053SRui Paulo 			}
2434e28a4053SRui Paulo 			wpabuf_free(cert);
2435e28a4053SRui Paulo 		}
2436e28a4053SRui Paulo 	}
2437e28a4053SRui Paulo #endif /* CONFIG_SHA256 */
2438e28a4053SRui Paulo 
2439206b73d0SCy Schubert 	openssl_tls_cert_event(conn, err_cert, depth, buf);
2440206b73d0SCy Schubert 
244139beb93cSSam Leffler 	if (!preverify_ok) {
2442206b73d0SCy Schubert 		if (depth > 0) {
2443206b73d0SCy Schubert 			/* Send cert event for the peer certificate so that
2444206b73d0SCy Schubert 			 * the upper layers get information about it even if
2445206b73d0SCy Schubert 			 * validation of a CA certificate fails. */
2446206b73d0SCy Schubert 			STACK_OF(X509) *chain;
2447206b73d0SCy Schubert 
2448206b73d0SCy Schubert 			chain = X509_STORE_CTX_get1_chain(x509_ctx);
2449206b73d0SCy Schubert 			if (chain && sk_X509_num(chain) > 0) {
2450206b73d0SCy Schubert 				char buf2[256];
2451206b73d0SCy Schubert 				X509 *cert;
2452206b73d0SCy Schubert 
2453206b73d0SCy Schubert 				cert = sk_X509_value(chain, 0);
2454206b73d0SCy Schubert 				X509_NAME_oneline(X509_get_subject_name(cert),
2455206b73d0SCy Schubert 						  buf2, sizeof(buf2));
2456206b73d0SCy Schubert 
2457206b73d0SCy Schubert 				openssl_tls_cert_event(conn, cert, 0, buf2);
2458206b73d0SCy Schubert 			}
2459206b73d0SCy Schubert 			if (chain)
2460206b73d0SCy Schubert 				sk_X509_pop_free(chain, X509_free);
2461206b73d0SCy Schubert 		}
2462206b73d0SCy Schubert 
246339beb93cSSam Leffler 		wpa_printf(MSG_WARNING, "TLS: Certificate verification failed,"
2464e28a4053SRui Paulo 			   " error %d (%s) depth %d for '%s'", err, err_str,
2465e28a4053SRui Paulo 			   depth, buf);
2466e28a4053SRui Paulo 		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2467e28a4053SRui Paulo 				       err_str, TLS_FAIL_UNSPECIFIED);
2468e28a4053SRui Paulo 		return preverify_ok;
2469e28a4053SRui Paulo 	}
2470e28a4053SRui Paulo 
2471e28a4053SRui Paulo 	wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - preverify_ok=%d "
2472e28a4053SRui Paulo 		   "err=%d (%s) ca_cert_verify=%d depth=%d buf='%s'",
2473e28a4053SRui Paulo 		   preverify_ok, err, err_str,
2474e28a4053SRui Paulo 		   conn->ca_cert_verify, depth, buf);
24754bc52338SCy Schubert 	check_cert_subject = conn->check_cert_subject;
24764bc52338SCy Schubert 	if (!check_cert_subject)
24774bc52338SCy Schubert 		check_cert_subject = conn->data->check_cert_subject;
24784bc52338SCy Schubert 	if (check_cert_subject) {
24794bc52338SCy Schubert 		if (depth == 0 &&
24804bc52338SCy Schubert 		    !tls_match_dn_field(err_cert, check_cert_subject)) {
24814bc52338SCy Schubert 			preverify_ok = 0;
24824bc52338SCy Schubert 			openssl_tls_fail_event(conn, err_cert, err, depth, buf,
24834bc52338SCy Schubert 					       "Distinguished Name",
24844bc52338SCy Schubert 					       TLS_FAIL_DN_MISMATCH);
24854bc52338SCy Schubert 		}
24864bc52338SCy Schubert 	}
248739beb93cSSam Leffler 	if (depth == 0 && match && os_strstr(buf, match) == NULL) {
248839beb93cSSam Leffler 		wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
248939beb93cSSam Leffler 			   "match with '%s'", buf, match);
249039beb93cSSam Leffler 		preverify_ok = 0;
2491e28a4053SRui Paulo 		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2492e28a4053SRui Paulo 				       "Subject mismatch",
2493e28a4053SRui Paulo 				       TLS_FAIL_SUBJECT_MISMATCH);
249439beb93cSSam Leffler 	} else if (depth == 0 && altmatch &&
249539beb93cSSam Leffler 		   !tls_match_altsubject(err_cert, altmatch)) {
249639beb93cSSam Leffler 		wpa_printf(MSG_WARNING, "TLS: altSubjectName match "
249739beb93cSSam Leffler 			   "'%s' not found", altmatch);
249839beb93cSSam Leffler 		preverify_ok = 0;
2499e28a4053SRui Paulo 		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2500e28a4053SRui Paulo 				       "AltSubject mismatch",
2501e28a4053SRui Paulo 				       TLS_FAIL_ALTSUBJECT_MISMATCH);
25025b9c547cSRui Paulo 	} else if (depth == 0 && suffix_match &&
25035b9c547cSRui Paulo 		   !tls_match_suffix(err_cert, suffix_match, 0)) {
25045b9c547cSRui Paulo 		wpa_printf(MSG_WARNING, "TLS: Domain suffix match '%s' not found",
25055b9c547cSRui Paulo 			   suffix_match);
25065b9c547cSRui Paulo 		preverify_ok = 0;
25075b9c547cSRui Paulo 		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
25085b9c547cSRui Paulo 				       "Domain suffix mismatch",
25095b9c547cSRui Paulo 				       TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
25105b9c547cSRui Paulo 	} else if (depth == 0 && domain_match &&
25115b9c547cSRui Paulo 		   !tls_match_suffix(err_cert, domain_match, 1)) {
25125b9c547cSRui Paulo 		wpa_printf(MSG_WARNING, "TLS: Domain match '%s' not found",
25135b9c547cSRui Paulo 			   domain_match);
25145b9c547cSRui Paulo 		preverify_ok = 0;
25155b9c547cSRui Paulo 		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
25165b9c547cSRui Paulo 				       "Domain mismatch",
25175b9c547cSRui Paulo 				       TLS_FAIL_DOMAIN_MISMATCH);
2518206b73d0SCy Schubert 	}
2519e28a4053SRui Paulo 
2520e28a4053SRui Paulo 	if (conn->cert_probe && preverify_ok && depth == 0) {
2521e28a4053SRui Paulo 		wpa_printf(MSG_DEBUG, "OpenSSL: Reject server certificate "
2522e28a4053SRui Paulo 			   "on probe-only run");
2523e28a4053SRui Paulo 		preverify_ok = 0;
2524e28a4053SRui Paulo 		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2525e28a4053SRui Paulo 				       "Server certificate chain probe",
2526e28a4053SRui Paulo 				       TLS_FAIL_SERVER_CHAIN_PROBE);
252739beb93cSSam Leffler 	}
252839beb93cSSam Leffler 
252985732ac8SCy Schubert #ifdef CONFIG_SUITEB
253085732ac8SCy Schubert 	if (conn->flags & TLS_CONN_SUITEB) {
253185732ac8SCy Schubert 		EVP_PKEY *pk;
253285732ac8SCy Schubert 		RSA *rsa;
253385732ac8SCy Schubert 		int len = -1;
253485732ac8SCy Schubert 
253585732ac8SCy Schubert 		pk = X509_get_pubkey(err_cert);
253685732ac8SCy Schubert 		if (pk) {
253785732ac8SCy Schubert 			rsa = EVP_PKEY_get1_RSA(pk);
253885732ac8SCy Schubert 			if (rsa) {
253985732ac8SCy Schubert 				len = RSA_bits(rsa);
254085732ac8SCy Schubert 				RSA_free(rsa);
254185732ac8SCy Schubert 			}
254285732ac8SCy Schubert 			EVP_PKEY_free(pk);
254385732ac8SCy Schubert 		}
254485732ac8SCy Schubert 
254585732ac8SCy Schubert 		if (len >= 0) {
254685732ac8SCy Schubert 			wpa_printf(MSG_DEBUG,
254785732ac8SCy Schubert 				   "OpenSSL: RSA modulus size: %d bits", len);
254885732ac8SCy Schubert 			if (len < 3072) {
254985732ac8SCy Schubert 				preverify_ok = 0;
255085732ac8SCy Schubert 				openssl_tls_fail_event(
255185732ac8SCy Schubert 					conn, err_cert, err,
255285732ac8SCy Schubert 					depth, buf,
255385732ac8SCy Schubert 					"Insufficient RSA modulus size",
255485732ac8SCy Schubert 					TLS_FAIL_INSUFFICIENT_KEY_LEN);
255585732ac8SCy Schubert 			}
255685732ac8SCy Schubert 		}
255785732ac8SCy Schubert 	}
255885732ac8SCy Schubert #endif /* CONFIG_SUITEB */
255985732ac8SCy Schubert 
2560780fb4a2SCy Schubert #ifdef OPENSSL_IS_BORINGSSL
2561780fb4a2SCy Schubert 	if (depth == 0 && (conn->flags & TLS_CONN_REQUEST_OCSP) &&
2562780fb4a2SCy Schubert 	    preverify_ok) {
2563780fb4a2SCy Schubert 		enum ocsp_result res;
2564780fb4a2SCy Schubert 
2565780fb4a2SCy Schubert 		res = check_ocsp_resp(conn->ssl_ctx, conn->ssl, err_cert,
2566780fb4a2SCy Schubert 				      conn->peer_issuer,
2567780fb4a2SCy Schubert 				      conn->peer_issuer_issuer);
2568780fb4a2SCy Schubert 		if (res == OCSP_REVOKED) {
2569780fb4a2SCy Schubert 			preverify_ok = 0;
2570780fb4a2SCy Schubert 			openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2571780fb4a2SCy Schubert 					       "certificate revoked",
2572780fb4a2SCy Schubert 					       TLS_FAIL_REVOKED);
2573780fb4a2SCy Schubert 			if (err == X509_V_OK)
2574780fb4a2SCy Schubert 				X509_STORE_CTX_set_error(
2575780fb4a2SCy Schubert 					x509_ctx, X509_V_ERR_CERT_REVOKED);
2576780fb4a2SCy Schubert 		} else if (res != OCSP_GOOD &&
2577780fb4a2SCy Schubert 			   (conn->flags & TLS_CONN_REQUIRE_OCSP)) {
2578780fb4a2SCy Schubert 			preverify_ok = 0;
2579780fb4a2SCy Schubert 			openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2580780fb4a2SCy Schubert 					       "bad certificate status response",
2581780fb4a2SCy Schubert 					       TLS_FAIL_UNSPECIFIED);
2582780fb4a2SCy Schubert 		}
2583780fb4a2SCy Schubert 	}
2584780fb4a2SCy Schubert #endif /* OPENSSL_IS_BORINGSSL */
2585780fb4a2SCy Schubert 
2586780fb4a2SCy Schubert 	if (depth == 0 && preverify_ok && context->event_cb != NULL)
25875b9c547cSRui Paulo 		context->event_cb(context->cb_ctx,
2588f05cddf9SRui Paulo 				  TLS_CERT_CHAIN_SUCCESS, NULL);
2589f05cddf9SRui Paulo 
2590c1d255d3SCy Schubert 	if (depth == 0 && preverify_ok) {
2591c1d255d3SCy Schubert 		os_free(conn->peer_subject);
2592c1d255d3SCy Schubert 		conn->peer_subject = os_strdup(buf);
2593c1d255d3SCy Schubert 	}
2594c1d255d3SCy Schubert 
259539beb93cSSam Leffler 	return preverify_ok;
259639beb93cSSam Leffler }
259739beb93cSSam Leffler 
259839beb93cSSam Leffler 
259939beb93cSSam Leffler #ifndef OPENSSL_NO_STDIO
tls_load_ca_der(struct tls_data * data,const char * ca_cert)2600325151a3SRui Paulo static int tls_load_ca_der(struct tls_data *data, const char *ca_cert)
260139beb93cSSam Leffler {
2602325151a3SRui Paulo 	SSL_CTX *ssl_ctx = data->ssl;
260339beb93cSSam Leffler 	X509_LOOKUP *lookup;
260439beb93cSSam Leffler 	int ret = 0;
260539beb93cSSam Leffler 
26065b9c547cSRui Paulo 	lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(ssl_ctx),
260739beb93cSSam Leffler 				       X509_LOOKUP_file());
260839beb93cSSam Leffler 	if (lookup == NULL) {
260939beb93cSSam Leffler 		tls_show_errors(MSG_WARNING, __func__,
261039beb93cSSam Leffler 				"Failed add lookup for X509 store");
261139beb93cSSam Leffler 		return -1;
261239beb93cSSam Leffler 	}
261339beb93cSSam Leffler 
261439beb93cSSam Leffler 	if (!X509_LOOKUP_load_file(lookup, ca_cert, X509_FILETYPE_ASN1)) {
261539beb93cSSam Leffler 		unsigned long err = ERR_peek_error();
261639beb93cSSam Leffler 		tls_show_errors(MSG_WARNING, __func__,
261739beb93cSSam Leffler 				"Failed load CA in DER format");
261839beb93cSSam Leffler 		if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
261939beb93cSSam Leffler 		    ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) {
262039beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring "
262139beb93cSSam Leffler 				   "cert already in hash table error",
262239beb93cSSam Leffler 				   __func__);
262339beb93cSSam Leffler 		} else
262439beb93cSSam Leffler 			ret = -1;
262539beb93cSSam Leffler 	}
262639beb93cSSam Leffler 
262739beb93cSSam Leffler 	return ret;
262839beb93cSSam Leffler }
262939beb93cSSam Leffler #endif /* OPENSSL_NO_STDIO */
263039beb93cSSam Leffler 
263139beb93cSSam Leffler 
tls_connection_ca_cert(struct tls_data * data,struct tls_connection * conn,const char * ca_cert,const u8 * ca_cert_blob,size_t ca_cert_blob_len,const char * ca_path)2632325151a3SRui Paulo static int tls_connection_ca_cert(struct tls_data *data,
2633325151a3SRui Paulo 				  struct tls_connection *conn,
263439beb93cSSam Leffler 				  const char *ca_cert, const u8 *ca_cert_blob,
263539beb93cSSam Leffler 				  size_t ca_cert_blob_len, const char *ca_path)
263639beb93cSSam Leffler {
2637325151a3SRui Paulo 	SSL_CTX *ssl_ctx = data->ssl;
26385b9c547cSRui Paulo 	X509_STORE *store;
263939beb93cSSam Leffler 
264039beb93cSSam Leffler 	/*
264139beb93cSSam Leffler 	 * Remove previously configured trusted CA certificates before adding
264239beb93cSSam Leffler 	 * new ones.
264339beb93cSSam Leffler 	 */
26445b9c547cSRui Paulo 	store = X509_STORE_new();
26455b9c547cSRui Paulo 	if (store == NULL) {
264639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new "
264739beb93cSSam Leffler 			   "certificate store", __func__);
264839beb93cSSam Leffler 		return -1;
264939beb93cSSam Leffler 	}
26505b9c547cSRui Paulo 	SSL_CTX_set_cert_store(ssl_ctx, store);
265139beb93cSSam Leffler 
2652e28a4053SRui Paulo 	SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
2653e28a4053SRui Paulo 	conn->ca_cert_verify = 1;
2654e28a4053SRui Paulo 
2655e28a4053SRui Paulo 	if (ca_cert && os_strncmp(ca_cert, "probe://", 8) == 0) {
2656e28a4053SRui Paulo 		wpa_printf(MSG_DEBUG, "OpenSSL: Probe for server certificate "
2657e28a4053SRui Paulo 			   "chain");
2658e28a4053SRui Paulo 		conn->cert_probe = 1;
2659e28a4053SRui Paulo 		conn->ca_cert_verify = 0;
2660e28a4053SRui Paulo 		return 0;
2661e28a4053SRui Paulo 	}
2662e28a4053SRui Paulo 
2663e28a4053SRui Paulo 	if (ca_cert && os_strncmp(ca_cert, "hash://", 7) == 0) {
2664e28a4053SRui Paulo #ifdef CONFIG_SHA256
2665e28a4053SRui Paulo 		const char *pos = ca_cert + 7;
2666e28a4053SRui Paulo 		if (os_strncmp(pos, "server/sha256/", 14) != 0) {
2667e28a4053SRui Paulo 			wpa_printf(MSG_DEBUG, "OpenSSL: Unsupported ca_cert "
2668e28a4053SRui Paulo 				   "hash value '%s'", ca_cert);
2669e28a4053SRui Paulo 			return -1;
2670e28a4053SRui Paulo 		}
2671e28a4053SRui Paulo 		pos += 14;
2672e28a4053SRui Paulo 		if (os_strlen(pos) != 32 * 2) {
2673e28a4053SRui Paulo 			wpa_printf(MSG_DEBUG, "OpenSSL: Unexpected SHA256 "
2674e28a4053SRui Paulo 				   "hash length in ca_cert '%s'", ca_cert);
2675e28a4053SRui Paulo 			return -1;
2676e28a4053SRui Paulo 		}
2677e28a4053SRui Paulo 		if (hexstr2bin(pos, conn->srv_cert_hash, 32) < 0) {
2678e28a4053SRui Paulo 			wpa_printf(MSG_DEBUG, "OpenSSL: Invalid SHA256 hash "
2679e28a4053SRui Paulo 				   "value in ca_cert '%s'", ca_cert);
2680e28a4053SRui Paulo 			return -1;
2681e28a4053SRui Paulo 		}
2682e28a4053SRui Paulo 		conn->server_cert_only = 1;
2683e28a4053SRui Paulo 		wpa_printf(MSG_DEBUG, "OpenSSL: Checking only server "
2684e28a4053SRui Paulo 			   "certificate match");
2685e28a4053SRui Paulo 		return 0;
2686e28a4053SRui Paulo #else /* CONFIG_SHA256 */
2687e28a4053SRui Paulo 		wpa_printf(MSG_INFO, "No SHA256 included in the build - "
2688e28a4053SRui Paulo 			   "cannot validate server certificate hash");
2689e28a4053SRui Paulo 		return -1;
2690e28a4053SRui Paulo #endif /* CONFIG_SHA256 */
2691e28a4053SRui Paulo 	}
2692e28a4053SRui Paulo 
269339beb93cSSam Leffler 	if (ca_cert_blob) {
26945b9c547cSRui Paulo 		X509 *cert = d2i_X509(NULL,
26955b9c547cSRui Paulo 				      (const unsigned char **) &ca_cert_blob,
269639beb93cSSam Leffler 				      ca_cert_blob_len);
269739beb93cSSam Leffler 		if (cert == NULL) {
2698206b73d0SCy Schubert 			BIO *bio = BIO_new_mem_buf(ca_cert_blob,
2699206b73d0SCy Schubert 						   ca_cert_blob_len);
2700206b73d0SCy Schubert 
2701206b73d0SCy Schubert 			if (bio) {
2702206b73d0SCy Schubert 				cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
2703206b73d0SCy Schubert 				BIO_free(bio);
2704206b73d0SCy Schubert 			}
2705206b73d0SCy Schubert 
2706206b73d0SCy Schubert 			if (!cert) {
270739beb93cSSam Leffler 				tls_show_errors(MSG_WARNING, __func__,
270839beb93cSSam Leffler 						"Failed to parse ca_cert_blob");
270939beb93cSSam Leffler 				return -1;
271039beb93cSSam Leffler 			}
271139beb93cSSam Leffler 
2712206b73d0SCy Schubert 			while (ERR_get_error()) {
2713206b73d0SCy Schubert 				/* Ignore errors from DER conversion. */
2714206b73d0SCy Schubert 			}
2715206b73d0SCy Schubert 		}
2716206b73d0SCy Schubert 
27175b9c547cSRui Paulo 		if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(ssl_ctx),
27185b9c547cSRui Paulo 					 cert)) {
271939beb93cSSam Leffler 			unsigned long err = ERR_peek_error();
272039beb93cSSam Leffler 			tls_show_errors(MSG_WARNING, __func__,
272139beb93cSSam Leffler 					"Failed to add ca_cert_blob to "
272239beb93cSSam Leffler 					"certificate store");
272339beb93cSSam Leffler 			if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
272439beb93cSSam Leffler 			    ERR_GET_REASON(err) ==
272539beb93cSSam Leffler 			    X509_R_CERT_ALREADY_IN_HASH_TABLE) {
272639beb93cSSam Leffler 				wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring "
272739beb93cSSam Leffler 					   "cert already in hash table error",
272839beb93cSSam Leffler 					   __func__);
272939beb93cSSam Leffler 			} else {
273039beb93cSSam Leffler 				X509_free(cert);
273139beb93cSSam Leffler 				return -1;
273239beb93cSSam Leffler 			}
273339beb93cSSam Leffler 		}
273439beb93cSSam Leffler 		X509_free(cert);
273539beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "OpenSSL: %s - added ca_cert_blob "
273639beb93cSSam Leffler 			   "to certificate store", __func__);
273739beb93cSSam Leffler 		return 0;
273839beb93cSSam Leffler 	}
273939beb93cSSam Leffler 
2740f05cddf9SRui Paulo #ifdef ANDROID
2741780fb4a2SCy Schubert 	/* Single alias */
2742f05cddf9SRui Paulo 	if (ca_cert && os_strncmp("keystore://", ca_cert, 11) == 0) {
2743780fb4a2SCy Schubert 		if (tls_add_ca_from_keystore(SSL_CTX_get_cert_store(ssl_ctx),
2744780fb4a2SCy Schubert 					     &ca_cert[11]) < 0)
2745f05cddf9SRui Paulo 			return -1;
2746780fb4a2SCy Schubert 		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
2747780fb4a2SCy Schubert 		return 0;
2748780fb4a2SCy Schubert 	}
2749f05cddf9SRui Paulo 
2750780fb4a2SCy Schubert 	/* Multiple aliases separated by space */
2751780fb4a2SCy Schubert 	if (ca_cert && os_strncmp("keystores://", ca_cert, 12) == 0) {
2752780fb4a2SCy Schubert 		char *aliases = os_strdup(&ca_cert[12]);
2753780fb4a2SCy Schubert 		const char *delim = " ";
2754780fb4a2SCy Schubert 		int rc = 0;
2755780fb4a2SCy Schubert 		char *savedptr;
2756780fb4a2SCy Schubert 		char *alias;
2757780fb4a2SCy Schubert 
2758780fb4a2SCy Schubert 		if (!aliases)
2759780fb4a2SCy Schubert 			return -1;
2760780fb4a2SCy Schubert 		alias = strtok_r(aliases, delim, &savedptr);
2761780fb4a2SCy Schubert 		for (; alias; alias = strtok_r(NULL, delim, &savedptr)) {
2762780fb4a2SCy Schubert 			if (tls_add_ca_from_keystore_encoded(
2763780fb4a2SCy Schubert 				    SSL_CTX_get_cert_store(ssl_ctx), alias)) {
2764780fb4a2SCy Schubert 				wpa_printf(MSG_WARNING,
2765780fb4a2SCy Schubert 					   "OpenSSL: %s - Failed to add ca_cert %s from keystore",
2766780fb4a2SCy Schubert 					   __func__, alias);
2767780fb4a2SCy Schubert 				rc = -1;
2768780fb4a2SCy Schubert 				break;
2769f05cddf9SRui Paulo 			}
2770f05cddf9SRui Paulo 		}
2771780fb4a2SCy Schubert 		os_free(aliases);
2772780fb4a2SCy Schubert 		if (rc)
2773780fb4a2SCy Schubert 			return rc;
2774780fb4a2SCy Schubert 
2775f05cddf9SRui Paulo 		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
2776f05cddf9SRui Paulo 		return 0;
2777f05cddf9SRui Paulo 	}
2778f05cddf9SRui Paulo #endif /* ANDROID */
2779f05cddf9SRui Paulo 
278039beb93cSSam Leffler #ifdef CONFIG_NATIVE_WINDOWS
278139beb93cSSam Leffler 	if (ca_cert && tls_cryptoapi_ca_cert(ssl_ctx, conn->ssl, ca_cert) ==
278239beb93cSSam Leffler 	    0) {
278339beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "OpenSSL: Added CA certificates from "
278439beb93cSSam Leffler 			   "system certificate store");
278539beb93cSSam Leffler 		return 0;
278639beb93cSSam Leffler 	}
278739beb93cSSam Leffler #endif /* CONFIG_NATIVE_WINDOWS */
278839beb93cSSam Leffler 
278939beb93cSSam Leffler 	if (ca_cert || ca_path) {
279039beb93cSSam Leffler #ifndef OPENSSL_NO_STDIO
279139beb93cSSam Leffler 		if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, ca_path) !=
279239beb93cSSam Leffler 		    1) {
279339beb93cSSam Leffler 			tls_show_errors(MSG_WARNING, __func__,
279439beb93cSSam Leffler 					"Failed to load root certificates");
279539beb93cSSam Leffler 			if (ca_cert &&
2796325151a3SRui Paulo 			    tls_load_ca_der(data, ca_cert) == 0) {
279739beb93cSSam Leffler 				wpa_printf(MSG_DEBUG, "OpenSSL: %s - loaded "
279839beb93cSSam Leffler 					   "DER format CA certificate",
279939beb93cSSam Leffler 					   __func__);
280039beb93cSSam Leffler 			} else
280139beb93cSSam Leffler 				return -1;
280239beb93cSSam Leffler 		} else {
280339beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLS: Trusted root "
280439beb93cSSam Leffler 				   "certificate(s) loaded");
2805325151a3SRui Paulo 			tls_get_errors(data);
280639beb93cSSam Leffler 		}
280739beb93cSSam Leffler #else /* OPENSSL_NO_STDIO */
280839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO",
280939beb93cSSam Leffler 			   __func__);
281039beb93cSSam Leffler 		return -1;
281139beb93cSSam Leffler #endif /* OPENSSL_NO_STDIO */
281239beb93cSSam Leffler 	} else {
281339beb93cSSam Leffler 		/* No ca_cert configured - do not try to verify server
281439beb93cSSam Leffler 		 * certificate */
2815e28a4053SRui Paulo 		conn->ca_cert_verify = 0;
281639beb93cSSam Leffler 	}
281739beb93cSSam Leffler 
281839beb93cSSam Leffler 	return 0;
281939beb93cSSam Leffler }
282039beb93cSSam Leffler 
282139beb93cSSam Leffler 
tls_global_ca_cert(struct tls_data * data,const char * ca_cert)2822325151a3SRui Paulo static int tls_global_ca_cert(struct tls_data *data, const char *ca_cert)
282339beb93cSSam Leffler {
2824325151a3SRui Paulo 	SSL_CTX *ssl_ctx = data->ssl;
2825325151a3SRui Paulo 
282639beb93cSSam Leffler 	if (ca_cert) {
282739beb93cSSam Leffler 		if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, NULL) != 1)
282839beb93cSSam Leffler 		{
282939beb93cSSam Leffler 			tls_show_errors(MSG_WARNING, __func__,
283039beb93cSSam Leffler 					"Failed to load root certificates");
283139beb93cSSam Leffler 			return -1;
283239beb93cSSam Leffler 		}
283339beb93cSSam Leffler 
283439beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLS: Trusted root "
283539beb93cSSam Leffler 			   "certificate(s) loaded");
283639beb93cSSam Leffler 
283739beb93cSSam Leffler #ifndef OPENSSL_NO_STDIO
283839beb93cSSam Leffler 		/* Add the same CAs to the client certificate requests */
283939beb93cSSam Leffler 		SSL_CTX_set_client_CA_list(ssl_ctx,
284039beb93cSSam Leffler 					   SSL_load_client_CA_file(ca_cert));
284139beb93cSSam Leffler #endif /* OPENSSL_NO_STDIO */
28424bc52338SCy Schubert 
28434bc52338SCy Schubert 		os_free(data->ca_cert);
28444bc52338SCy Schubert 		data->ca_cert = os_strdup(ca_cert);
284539beb93cSSam Leffler 	}
284639beb93cSSam Leffler 
284739beb93cSSam Leffler 	return 0;
284839beb93cSSam Leffler }
284939beb93cSSam Leffler 
285039beb93cSSam Leffler 
tls_global_set_verify(void * ssl_ctx,int check_crl,int strict)28514bc52338SCy Schubert int tls_global_set_verify(void *ssl_ctx, int check_crl, int strict)
285239beb93cSSam Leffler {
285339beb93cSSam Leffler 	int flags;
285439beb93cSSam Leffler 
285539beb93cSSam Leffler 	if (check_crl) {
2856325151a3SRui Paulo 		struct tls_data *data = ssl_ctx;
2857325151a3SRui Paulo 		X509_STORE *cs = SSL_CTX_get_cert_store(data->ssl);
285839beb93cSSam Leffler 		if (cs == NULL) {
285939beb93cSSam Leffler 			tls_show_errors(MSG_INFO, __func__, "Failed to get "
286039beb93cSSam Leffler 					"certificate store when enabling "
286139beb93cSSam Leffler 					"check_crl");
286239beb93cSSam Leffler 			return -1;
286339beb93cSSam Leffler 		}
286439beb93cSSam Leffler 		flags = X509_V_FLAG_CRL_CHECK;
286539beb93cSSam Leffler 		if (check_crl == 2)
286639beb93cSSam Leffler 			flags |= X509_V_FLAG_CRL_CHECK_ALL;
286739beb93cSSam Leffler 		X509_STORE_set_flags(cs, flags);
28684bc52338SCy Schubert 
28694bc52338SCy Schubert 		data->check_crl = check_crl;
28704bc52338SCy Schubert 		data->check_crl_strict = strict;
28714bc52338SCy Schubert 		os_get_reltime(&data->crl_last_reload);
287239beb93cSSam Leffler 	}
287339beb93cSSam Leffler 	return 0;
287439beb93cSSam Leffler }
287539beb93cSSam Leffler 
287639beb93cSSam Leffler 
tls_connection_set_subject_match(struct tls_connection * conn,const char * subject_match,const char * altsubject_match,const char * suffix_match,const char * domain_match,const char * check_cert_subject)287739beb93cSSam Leffler static int tls_connection_set_subject_match(struct tls_connection *conn,
287839beb93cSSam Leffler 					    const char *subject_match,
28795b9c547cSRui Paulo 					    const char *altsubject_match,
28805b9c547cSRui Paulo 					    const char *suffix_match,
28814bc52338SCy Schubert 					    const char *domain_match,
28824bc52338SCy Schubert 					    const char *check_cert_subject)
288339beb93cSSam Leffler {
288439beb93cSSam Leffler 	os_free(conn->subject_match);
288539beb93cSSam Leffler 	conn->subject_match = NULL;
288639beb93cSSam Leffler 	if (subject_match) {
288739beb93cSSam Leffler 		conn->subject_match = os_strdup(subject_match);
288839beb93cSSam Leffler 		if (conn->subject_match == NULL)
288939beb93cSSam Leffler 			return -1;
289039beb93cSSam Leffler 	}
289139beb93cSSam Leffler 
289239beb93cSSam Leffler 	os_free(conn->altsubject_match);
289339beb93cSSam Leffler 	conn->altsubject_match = NULL;
289439beb93cSSam Leffler 	if (altsubject_match) {
289539beb93cSSam Leffler 		conn->altsubject_match = os_strdup(altsubject_match);
289639beb93cSSam Leffler 		if (conn->altsubject_match == NULL)
289739beb93cSSam Leffler 			return -1;
289839beb93cSSam Leffler 	}
289939beb93cSSam Leffler 
29005b9c547cSRui Paulo 	os_free(conn->suffix_match);
29015b9c547cSRui Paulo 	conn->suffix_match = NULL;
29025b9c547cSRui Paulo 	if (suffix_match) {
29035b9c547cSRui Paulo 		conn->suffix_match = os_strdup(suffix_match);
29045b9c547cSRui Paulo 		if (conn->suffix_match == NULL)
29055b9c547cSRui Paulo 			return -1;
29065b9c547cSRui Paulo 	}
29075b9c547cSRui Paulo 
29085b9c547cSRui Paulo 	os_free(conn->domain_match);
29095b9c547cSRui Paulo 	conn->domain_match = NULL;
29105b9c547cSRui Paulo 	if (domain_match) {
29115b9c547cSRui Paulo 		conn->domain_match = os_strdup(domain_match);
29125b9c547cSRui Paulo 		if (conn->domain_match == NULL)
29135b9c547cSRui Paulo 			return -1;
29145b9c547cSRui Paulo 	}
29155b9c547cSRui Paulo 
29164bc52338SCy Schubert 	os_free(conn->check_cert_subject);
29174bc52338SCy Schubert 	conn->check_cert_subject = NULL;
29184bc52338SCy Schubert 	if (check_cert_subject) {
29194bc52338SCy Schubert 		conn->check_cert_subject = os_strdup(check_cert_subject);
29204bc52338SCy Schubert 		if (!conn->check_cert_subject)
29214bc52338SCy Schubert 			return -1;
29224bc52338SCy Schubert 	}
29234bc52338SCy Schubert 
292439beb93cSSam Leffler 	return 0;
292539beb93cSSam Leffler }
292639beb93cSSam Leffler 
292739beb93cSSam Leffler 
292885732ac8SCy Schubert #ifdef CONFIG_SUITEB
292985732ac8SCy Schubert #if OPENSSL_VERSION_NUMBER >= 0x10002000L
suiteb_cert_cb(SSL * ssl,void * arg)293085732ac8SCy Schubert static int suiteb_cert_cb(SSL *ssl, void *arg)
2931325151a3SRui Paulo {
293285732ac8SCy Schubert 	struct tls_connection *conn = arg;
293385732ac8SCy Schubert 
293485732ac8SCy Schubert 	/*
293585732ac8SCy Schubert 	 * This cert_cb() is not really the best location for doing a
293685732ac8SCy Schubert 	 * constraint check for the ServerKeyExchange message, but this seems to
293785732ac8SCy Schubert 	 * be the only place where the current OpenSSL sequence can be
293885732ac8SCy Schubert 	 * terminated cleanly with an TLS alert going out to the server.
293985732ac8SCy Schubert 	 */
294085732ac8SCy Schubert 
294185732ac8SCy Schubert 	if (!(conn->flags & TLS_CONN_SUITEB))
294285732ac8SCy Schubert 		return 1;
294385732ac8SCy Schubert 
294485732ac8SCy Schubert 	/* DHE is enabled only with DHE-RSA-AES256-GCM-SHA384 */
294585732ac8SCy Schubert 	if (conn->cipher_suite != 0x9f)
294685732ac8SCy Schubert 		return 1;
294785732ac8SCy Schubert 
294885732ac8SCy Schubert 	if (conn->server_dh_prime_len >= 3072)
294985732ac8SCy Schubert 		return 1;
295085732ac8SCy Schubert 
295185732ac8SCy Schubert 	wpa_printf(MSG_DEBUG,
295285732ac8SCy Schubert 		   "OpenSSL: Server DH prime length (%d bits) not sufficient for Suite B RSA - reject handshake",
295385732ac8SCy Schubert 		   conn->server_dh_prime_len);
295485732ac8SCy Schubert 	return 0;
295585732ac8SCy Schubert }
295685732ac8SCy Schubert #endif /* OPENSSL_VERSION_NUMBER */
295785732ac8SCy Schubert #endif /* CONFIG_SUITEB */
295885732ac8SCy Schubert 
295985732ac8SCy Schubert 
tls_set_conn_flags(struct tls_connection * conn,unsigned int flags,const char * openssl_ciphers)296085732ac8SCy Schubert static int tls_set_conn_flags(struct tls_connection *conn, unsigned int flags,
296185732ac8SCy Schubert 			      const char *openssl_ciphers)
296285732ac8SCy Schubert {
296385732ac8SCy Schubert 	SSL *ssl = conn->ssl;
296485732ac8SCy Schubert 
2965325151a3SRui Paulo #ifdef SSL_OP_NO_TICKET
2966325151a3SRui Paulo 	if (flags & TLS_CONN_DISABLE_SESSION_TICKET)
2967325151a3SRui Paulo 		SSL_set_options(ssl, SSL_OP_NO_TICKET);
2968325151a3SRui Paulo 	else
2969325151a3SRui Paulo 		SSL_clear_options(ssl, SSL_OP_NO_TICKET);
2970325151a3SRui Paulo #endif /* SSL_OP_NO_TICKET */
2971325151a3SRui Paulo 
2972325151a3SRui Paulo #ifdef SSL_OP_NO_TLSv1
2973325151a3SRui Paulo 	if (flags & TLS_CONN_DISABLE_TLSv1_0)
2974325151a3SRui Paulo 		SSL_set_options(ssl, SSL_OP_NO_TLSv1);
2975325151a3SRui Paulo 	else
2976325151a3SRui Paulo 		SSL_clear_options(ssl, SSL_OP_NO_TLSv1);
2977325151a3SRui Paulo #endif /* SSL_OP_NO_TLSv1 */
2978325151a3SRui Paulo #ifdef SSL_OP_NO_TLSv1_1
2979325151a3SRui Paulo 	if (flags & TLS_CONN_DISABLE_TLSv1_1)
2980325151a3SRui Paulo 		SSL_set_options(ssl, SSL_OP_NO_TLSv1_1);
2981325151a3SRui Paulo 	else
2982325151a3SRui Paulo 		SSL_clear_options(ssl, SSL_OP_NO_TLSv1_1);
2983325151a3SRui Paulo #endif /* SSL_OP_NO_TLSv1_1 */
2984325151a3SRui Paulo #ifdef SSL_OP_NO_TLSv1_2
2985325151a3SRui Paulo 	if (flags & TLS_CONN_DISABLE_TLSv1_2)
2986325151a3SRui Paulo 		SSL_set_options(ssl, SSL_OP_NO_TLSv1_2);
2987325151a3SRui Paulo 	else
2988325151a3SRui Paulo 		SSL_clear_options(ssl, SSL_OP_NO_TLSv1_2);
2989325151a3SRui Paulo #endif /* SSL_OP_NO_TLSv1_2 */
299085732ac8SCy Schubert #ifdef SSL_OP_NO_TLSv1_3
299185732ac8SCy Schubert 	if (flags & TLS_CONN_DISABLE_TLSv1_3)
299285732ac8SCy Schubert 		SSL_set_options(ssl, SSL_OP_NO_TLSv1_3);
299385732ac8SCy Schubert 	else
299485732ac8SCy Schubert 		SSL_clear_options(ssl, SSL_OP_NO_TLSv1_3);
299585732ac8SCy Schubert #endif /* SSL_OP_NO_TLSv1_3 */
29964bc52338SCy Schubert #if OPENSSL_VERSION_NUMBER >= 0x10100000L
29974bc52338SCy Schubert 	if (flags & (TLS_CONN_ENABLE_TLSv1_0 |
29984bc52338SCy Schubert 		     TLS_CONN_ENABLE_TLSv1_1 |
29994bc52338SCy Schubert 		     TLS_CONN_ENABLE_TLSv1_2)) {
30004bc52338SCy Schubert 		int version = 0;
30014bc52338SCy Schubert 
30024bc52338SCy Schubert 		/* Explicit request to enable TLS versions even if needing to
30034bc52338SCy Schubert 		 * override systemwide policies. */
3004c1d255d3SCy Schubert 		if (flags & TLS_CONN_ENABLE_TLSv1_0)
30054bc52338SCy Schubert 			version = TLS1_VERSION;
3006c1d255d3SCy Schubert 		else if (flags & TLS_CONN_ENABLE_TLSv1_1)
30074bc52338SCy Schubert 			version = TLS1_1_VERSION;
3008c1d255d3SCy Schubert 		else if (flags & TLS_CONN_ENABLE_TLSv1_2)
30094bc52338SCy Schubert 			version = TLS1_2_VERSION;
30104bc52338SCy Schubert 		if (!version) {
30114bc52338SCy Schubert 			wpa_printf(MSG_DEBUG,
30124bc52338SCy Schubert 				   "OpenSSL: Invalid TLS version configuration");
30134bc52338SCy Schubert 			return -1;
30144bc52338SCy Schubert 		}
30154bc52338SCy Schubert 
30164bc52338SCy Schubert 		if (SSL_set_min_proto_version(ssl, version) != 1) {
30174bc52338SCy Schubert 			wpa_printf(MSG_DEBUG,
30184bc52338SCy Schubert 				   "OpenSSL: Failed to set minimum TLS version");
30194bc52338SCy Schubert 			return -1;
30204bc52338SCy Schubert 		}
30214bc52338SCy Schubert 	}
30224bc52338SCy Schubert #endif /* >= 1.1.0 */
3023c1d255d3SCy Schubert #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
3024c1d255d3SCy Schubert 	!defined(LIBRESSL_VERSION_NUMBER) && \
3025c1d255d3SCy Schubert 	!defined(OPENSSL_IS_BORINGSSL)
3026ec080394SCy Schubert 	{
3027ec080394SCy Schubert #if OPENSSL_VERSION_NUMBER >= 0x30000000L
3028ec080394SCy Schubert 		int need_level = 0;
3029ec080394SCy Schubert #else
3030ec080394SCy Schubert 		int need_level = 1;
3031ec080394SCy Schubert #endif
3032ec080394SCy Schubert 
3033ec080394SCy Schubert 		if ((flags &
3034ec080394SCy Schubert 		     (TLS_CONN_ENABLE_TLSv1_0 | TLS_CONN_ENABLE_TLSv1_1)) &&
3035ec080394SCy Schubert 		    SSL_get_security_level(ssl) > need_level) {
3036c1d255d3SCy Schubert 			/*
3037ec080394SCy Schubert 			 * Need to drop to security level 1 (or 0  with OpenSSL
3038ec080394SCy Schubert 			 * 3.0) to allow TLS versions older than 1.2 to be used
3039ec080394SCy Schubert 			 * when explicitly enabled in configuration.
3040c1d255d3SCy Schubert 			 */
3041ec080394SCy Schubert 			SSL_set_security_level(conn->ssl, need_level);
3042ec080394SCy Schubert 		}
3043c1d255d3SCy Schubert 	}
3044c1d255d3SCy Schubert #endif
30454bc52338SCy Schubert 
304685732ac8SCy Schubert #ifdef CONFIG_SUITEB
304785732ac8SCy Schubert #ifdef OPENSSL_IS_BORINGSSL
304885732ac8SCy Schubert 	/* Start with defaults from BoringSSL */
304985732ac8SCy Schubert 	SSL_CTX_set_verify_algorithm_prefs(conn->ssl_ctx, NULL, 0);
305085732ac8SCy Schubert #endif /* OPENSSL_IS_BORINGSSL */
305185732ac8SCy Schubert #if OPENSSL_VERSION_NUMBER >= 0x10002000L
305285732ac8SCy Schubert 	if (flags & TLS_CONN_SUITEB_NO_ECDH) {
305385732ac8SCy Schubert 		const char *ciphers = "DHE-RSA-AES256-GCM-SHA384";
305485732ac8SCy Schubert 
305585732ac8SCy Schubert 		if (openssl_ciphers) {
305685732ac8SCy Schubert 			wpa_printf(MSG_DEBUG,
305785732ac8SCy Schubert 				   "OpenSSL: Override ciphers for Suite B (no ECDH): %s",
305885732ac8SCy Schubert 				   openssl_ciphers);
305985732ac8SCy Schubert 			ciphers = openssl_ciphers;
306085732ac8SCy Schubert 		}
306185732ac8SCy Schubert 		if (SSL_set_cipher_list(ssl, ciphers) != 1) {
306285732ac8SCy Schubert 			wpa_printf(MSG_INFO,
306385732ac8SCy Schubert 				   "OpenSSL: Failed to set Suite B ciphers");
306485732ac8SCy Schubert 			return -1;
306585732ac8SCy Schubert 		}
306685732ac8SCy Schubert 	} else if (flags & TLS_CONN_SUITEB) {
306785732ac8SCy Schubert 		EC_KEY *ecdh;
306885732ac8SCy Schubert 		const char *ciphers =
306985732ac8SCy Schubert 			"ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384";
307085732ac8SCy Schubert 		int nid[1] = { NID_secp384r1 };
307185732ac8SCy Schubert 
307285732ac8SCy Schubert 		if (openssl_ciphers) {
307385732ac8SCy Schubert 			wpa_printf(MSG_DEBUG,
307485732ac8SCy Schubert 				   "OpenSSL: Override ciphers for Suite B: %s",
307585732ac8SCy Schubert 				   openssl_ciphers);
307685732ac8SCy Schubert 			ciphers = openssl_ciphers;
307785732ac8SCy Schubert 		}
307885732ac8SCy Schubert 		if (SSL_set_cipher_list(ssl, ciphers) != 1) {
307985732ac8SCy Schubert 			wpa_printf(MSG_INFO,
308085732ac8SCy Schubert 				   "OpenSSL: Failed to set Suite B ciphers");
308185732ac8SCy Schubert 			return -1;
308285732ac8SCy Schubert 		}
308385732ac8SCy Schubert 
308485732ac8SCy Schubert 		if (SSL_set1_curves(ssl, nid, 1) != 1) {
308585732ac8SCy Schubert 			wpa_printf(MSG_INFO,
308685732ac8SCy Schubert 				   "OpenSSL: Failed to set Suite B curves");
308785732ac8SCy Schubert 			return -1;
308885732ac8SCy Schubert 		}
308985732ac8SCy Schubert 
309085732ac8SCy Schubert 		ecdh = EC_KEY_new_by_curve_name(NID_secp384r1);
309185732ac8SCy Schubert 		if (!ecdh || SSL_set_tmp_ecdh(ssl, ecdh) != 1) {
309285732ac8SCy Schubert 			EC_KEY_free(ecdh);
309385732ac8SCy Schubert 			wpa_printf(MSG_INFO,
309485732ac8SCy Schubert 				   "OpenSSL: Failed to set ECDH parameter");
309585732ac8SCy Schubert 			return -1;
309685732ac8SCy Schubert 		}
309785732ac8SCy Schubert 		EC_KEY_free(ecdh);
309885732ac8SCy Schubert 	}
309985732ac8SCy Schubert 	if (flags & (TLS_CONN_SUITEB | TLS_CONN_SUITEB_NO_ECDH)) {
310085732ac8SCy Schubert #ifdef OPENSSL_IS_BORINGSSL
310185732ac8SCy Schubert 		uint16_t sigalgs[1] = { SSL_SIGN_RSA_PKCS1_SHA384 };
310285732ac8SCy Schubert 
310385732ac8SCy Schubert 		if (SSL_CTX_set_verify_algorithm_prefs(conn->ssl_ctx, sigalgs,
310485732ac8SCy Schubert 						       1) != 1) {
310585732ac8SCy Schubert 			wpa_printf(MSG_INFO,
310685732ac8SCy Schubert 				   "OpenSSL: Failed to set Suite B sigalgs");
310785732ac8SCy Schubert 			return -1;
310885732ac8SCy Schubert 		}
310985732ac8SCy Schubert #else /* OPENSSL_IS_BORINGSSL */
311085732ac8SCy Schubert 		/* ECDSA+SHA384 if need to add EC support here */
311185732ac8SCy Schubert 		if (SSL_set1_sigalgs_list(ssl, "RSA+SHA384") != 1) {
311285732ac8SCy Schubert 			wpa_printf(MSG_INFO,
311385732ac8SCy Schubert 				   "OpenSSL: Failed to set Suite B sigalgs");
311485732ac8SCy Schubert 			return -1;
311585732ac8SCy Schubert 		}
311685732ac8SCy Schubert #endif /* OPENSSL_IS_BORINGSSL */
311785732ac8SCy Schubert 
311885732ac8SCy Schubert 		SSL_set_options(ssl, SSL_OP_NO_TLSv1);
311985732ac8SCy Schubert 		SSL_set_options(ssl, SSL_OP_NO_TLSv1_1);
312085732ac8SCy Schubert 		SSL_set_cert_cb(ssl, suiteb_cert_cb, conn);
312185732ac8SCy Schubert 	}
312285732ac8SCy Schubert #else /* OPENSSL_VERSION_NUMBER < 0x10002000L */
312385732ac8SCy Schubert 	if (flags & (TLS_CONN_SUITEB | TLS_CONN_SUITEB_NO_ECDH)) {
312485732ac8SCy Schubert 		wpa_printf(MSG_ERROR,
312585732ac8SCy Schubert 			   "OpenSSL: Suite B RSA case not supported with this OpenSSL version");
312685732ac8SCy Schubert 		return -1;
312785732ac8SCy Schubert 	}
312885732ac8SCy Schubert #endif /* OPENSSL_VERSION_NUMBER */
312985732ac8SCy Schubert 
313085732ac8SCy Schubert #ifdef OPENSSL_IS_BORINGSSL
313185732ac8SCy Schubert 	if (openssl_ciphers && os_strcmp(openssl_ciphers, "SUITEB192") == 0) {
313285732ac8SCy Schubert 		uint16_t sigalgs[1] = { SSL_SIGN_ECDSA_SECP384R1_SHA384 };
313385732ac8SCy Schubert 		int nid[1] = { NID_secp384r1 };
313485732ac8SCy Schubert 
313585732ac8SCy Schubert 		if (SSL_set1_curves(ssl, nid, 1) != 1) {
313685732ac8SCy Schubert 			wpa_printf(MSG_INFO,
313785732ac8SCy Schubert 				   "OpenSSL: Failed to set Suite B curves");
313885732ac8SCy Schubert 			return -1;
313985732ac8SCy Schubert 		}
314085732ac8SCy Schubert 
314185732ac8SCy Schubert 		if (SSL_CTX_set_verify_algorithm_prefs(conn->ssl_ctx, sigalgs,
314285732ac8SCy Schubert 						       1) != 1) {
314385732ac8SCy Schubert 			wpa_printf(MSG_INFO,
314485732ac8SCy Schubert 				   "OpenSSL: Failed to set Suite B sigalgs");
314585732ac8SCy Schubert 			return -1;
314685732ac8SCy Schubert 		}
314785732ac8SCy Schubert 	}
31484bc52338SCy Schubert #else /* OPENSSL_IS_BORINGSSL */
31494bc52338SCy Schubert 	if (!(flags & (TLS_CONN_SUITEB | TLS_CONN_SUITEB_NO_ECDH)) &&
31504bc52338SCy Schubert 	    openssl_ciphers && SSL_set_cipher_list(ssl, openssl_ciphers) != 1) {
31514bc52338SCy Schubert 		wpa_printf(MSG_INFO,
31524bc52338SCy Schubert 			   "OpenSSL: Failed to set openssl_ciphers '%s'",
31534bc52338SCy Schubert 			   openssl_ciphers);
31544bc52338SCy Schubert 		return -1;
31554bc52338SCy Schubert 	}
315685732ac8SCy Schubert #endif /* OPENSSL_IS_BORINGSSL */
31574bc52338SCy Schubert #else /* CONFIG_SUITEB */
31584bc52338SCy Schubert 	if (openssl_ciphers && SSL_set_cipher_list(ssl, openssl_ciphers) != 1) {
31594bc52338SCy Schubert 		wpa_printf(MSG_INFO,
31604bc52338SCy Schubert 			   "OpenSSL: Failed to set openssl_ciphers '%s'",
31614bc52338SCy Schubert 			   openssl_ciphers);
31624bc52338SCy Schubert 		return -1;
31634bc52338SCy Schubert 	}
316485732ac8SCy Schubert #endif /* CONFIG_SUITEB */
316585732ac8SCy Schubert 
3166206b73d0SCy Schubert 	if (flags & TLS_CONN_TEAP_ANON_DH) {
3167206b73d0SCy Schubert #ifndef TEAP_DH_ANON_CS
3168206b73d0SCy Schubert #define TEAP_DH_ANON_CS \
3169206b73d0SCy Schubert 	"ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:" \
3170206b73d0SCy Schubert 	"ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:" \
3171206b73d0SCy Schubert 	"ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:" \
3172206b73d0SCy Schubert 	"DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:" \
3173206b73d0SCy Schubert 	"DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:" \
3174206b73d0SCy Schubert 	"DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:" \
3175206b73d0SCy Schubert 	"ADH-AES256-GCM-SHA384:ADH-AES128-GCM-SHA256:" \
3176206b73d0SCy Schubert 	"ADH-AES256-SHA256:ADH-AES128-SHA256:ADH-AES256-SHA:ADH-AES128-SHA"
3177206b73d0SCy Schubert #endif
3178206b73d0SCy Schubert 		static const char *cs = TEAP_DH_ANON_CS;
3179206b73d0SCy Schubert 
3180206b73d0SCy Schubert #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
3181206b73d0SCy Schubert 	!defined(LIBRESSL_VERSION_NUMBER) && \
3182206b73d0SCy Schubert 	!defined(OPENSSL_IS_BORINGSSL)
3183206b73d0SCy Schubert 		/*
3184206b73d0SCy Schubert 		 * Need to drop to security level 0 to allow anonymous
3185206b73d0SCy Schubert 		 * cipher suites for EAP-TEAP.
3186206b73d0SCy Schubert 		 */
3187206b73d0SCy Schubert 		SSL_set_security_level(conn->ssl, 0);
3188206b73d0SCy Schubert #endif
3189206b73d0SCy Schubert 
3190206b73d0SCy Schubert 		wpa_printf(MSG_DEBUG,
3191206b73d0SCy Schubert 			   "OpenSSL: Enable cipher suites for anonymous EAP-TEAP provisioning: %s",
3192206b73d0SCy Schubert 			   cs);
3193206b73d0SCy Schubert 		if (SSL_set_cipher_list(conn->ssl, cs) != 1) {
3194206b73d0SCy Schubert 			tls_show_errors(MSG_INFO, __func__,
3195206b73d0SCy Schubert 					"Cipher suite configuration failed");
3196206b73d0SCy Schubert 			return -1;
3197206b73d0SCy Schubert 		}
3198206b73d0SCy Schubert 	}
3199206b73d0SCy Schubert 
320085732ac8SCy Schubert 	return 0;
3201325151a3SRui Paulo }
3202325151a3SRui Paulo 
3203325151a3SRui Paulo 
tls_connection_set_verify(void * ssl_ctx,struct tls_connection * conn,int verify_peer,unsigned int flags,const u8 * session_ctx,size_t session_ctx_len)320439beb93cSSam Leffler int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
3205325151a3SRui Paulo 			      int verify_peer, unsigned int flags,
3206325151a3SRui Paulo 			      const u8 *session_ctx, size_t session_ctx_len)
320739beb93cSSam Leffler {
320839beb93cSSam Leffler 	static int counter = 0;
3209325151a3SRui Paulo 	struct tls_data *data = ssl_ctx;
321039beb93cSSam Leffler 
321139beb93cSSam Leffler 	if (conn == NULL)
321239beb93cSSam Leffler 		return -1;
321339beb93cSSam Leffler 
3214c1d255d3SCy Schubert 	if (verify_peer == 2) {
3215c1d255d3SCy Schubert 		conn->ca_cert_verify = 1;
3216c1d255d3SCy Schubert 		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER |
3217c1d255d3SCy Schubert 			       SSL_VERIFY_CLIENT_ONCE, tls_verify_cb);
3218c1d255d3SCy Schubert 	} else if (verify_peer) {
3219e28a4053SRui Paulo 		conn->ca_cert_verify = 1;
322039beb93cSSam Leffler 		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER |
322139beb93cSSam Leffler 			       SSL_VERIFY_FAIL_IF_NO_PEER_CERT |
322239beb93cSSam Leffler 			       SSL_VERIFY_CLIENT_ONCE, tls_verify_cb);
322339beb93cSSam Leffler 	} else {
3224e28a4053SRui Paulo 		conn->ca_cert_verify = 0;
322539beb93cSSam Leffler 		SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
322639beb93cSSam Leffler 	}
322739beb93cSSam Leffler 
322885732ac8SCy Schubert 	if (tls_set_conn_flags(conn, flags, NULL) < 0)
322985732ac8SCy Schubert 		return -1;
3230325151a3SRui Paulo 	conn->flags = flags;
3231325151a3SRui Paulo 
323239beb93cSSam Leffler 	SSL_set_accept_state(conn->ssl);
323339beb93cSSam Leffler 
3234325151a3SRui Paulo 	if (data->tls_session_lifetime == 0) {
323539beb93cSSam Leffler 		/*
3236325151a3SRui Paulo 		 * Set session id context to a unique value to make sure
3237325151a3SRui Paulo 		 * session resumption cannot be used either through session
3238325151a3SRui Paulo 		 * caching or TLS ticket extension.
323939beb93cSSam Leffler 		 */
324039beb93cSSam Leffler 		counter++;
324139beb93cSSam Leffler 		SSL_set_session_id_context(conn->ssl,
324239beb93cSSam Leffler 					   (const unsigned char *) &counter,
324339beb93cSSam Leffler 					   sizeof(counter));
3244325151a3SRui Paulo 	} else if (session_ctx) {
3245325151a3SRui Paulo 		SSL_set_session_id_context(conn->ssl, session_ctx,
3246325151a3SRui Paulo 					   session_ctx_len);
3247325151a3SRui Paulo 	}
324839beb93cSSam Leffler 
324939beb93cSSam Leffler 	return 0;
325039beb93cSSam Leffler }
325139beb93cSSam Leffler 
325239beb93cSSam Leffler 
tls_connection_client_cert(struct tls_connection * conn,const char * client_cert,const u8 * client_cert_blob,size_t client_cert_blob_len)325339beb93cSSam Leffler static int tls_connection_client_cert(struct tls_connection *conn,
325439beb93cSSam Leffler 				      const char *client_cert,
325539beb93cSSam Leffler 				      const u8 *client_cert_blob,
325639beb93cSSam Leffler 				      size_t client_cert_blob_len)
325739beb93cSSam Leffler {
325839beb93cSSam Leffler 	if (client_cert == NULL && client_cert_blob == NULL)
325939beb93cSSam Leffler 		return 0;
326039beb93cSSam Leffler 
3261780fb4a2SCy Schubert #ifdef PKCS12_FUNCS
326285732ac8SCy Schubert #if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER)
3263780fb4a2SCy Schubert 	/*
3264780fb4a2SCy Schubert 	 * Clear previously set extra chain certificates, if any, from PKCS#12
3265780fb4a2SCy Schubert 	 * processing in tls_parse_pkcs12() to allow OpenSSL to build a new
3266780fb4a2SCy Schubert 	 * chain properly.
3267780fb4a2SCy Schubert 	 */
3268780fb4a2SCy Schubert 	SSL_CTX_clear_extra_chain_certs(conn->ssl_ctx);
3269780fb4a2SCy Schubert #endif /* OPENSSL_VERSION_NUMBER < 0x10002000L */
3270780fb4a2SCy Schubert #endif /* PKCS12_FUNCS */
3271780fb4a2SCy Schubert 
327239beb93cSSam Leffler 	if (client_cert_blob &&
327339beb93cSSam Leffler 	    SSL_use_certificate_ASN1(conn->ssl, (u8 *) client_cert_blob,
327439beb93cSSam Leffler 				     client_cert_blob_len) == 1) {
327539beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_ASN1 --> "
327639beb93cSSam Leffler 			   "OK");
327739beb93cSSam Leffler 		return 0;
327839beb93cSSam Leffler 	} else if (client_cert_blob) {
3279c1d255d3SCy Schubert #if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20901000L
328039beb93cSSam Leffler 		tls_show_errors(MSG_DEBUG, __func__,
328139beb93cSSam Leffler 				"SSL_use_certificate_ASN1 failed");
3282c1d255d3SCy Schubert #else
3283c1d255d3SCy Schubert 		BIO *bio;
3284c1d255d3SCy Schubert 		X509 *x509;
3285c1d255d3SCy Schubert 
3286c1d255d3SCy Schubert 		tls_show_errors(MSG_DEBUG, __func__,
3287c1d255d3SCy Schubert 				"SSL_use_certificate_ASN1 failed");
3288c1d255d3SCy Schubert 		bio = BIO_new(BIO_s_mem());
3289c1d255d3SCy Schubert 		if (!bio)
3290c1d255d3SCy Schubert 			return -1;
3291c1d255d3SCy Schubert 		BIO_write(bio, client_cert_blob, client_cert_blob_len);
3292c1d255d3SCy Schubert 		x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
3293c1d255d3SCy Schubert 		if (!x509 || SSL_use_certificate(conn->ssl, x509) != 1) {
3294c1d255d3SCy Schubert 			X509_free(x509);
3295c1d255d3SCy Schubert 			BIO_free(bio);
3296c1d255d3SCy Schubert 			return -1;
3297c1d255d3SCy Schubert 		}
3298c1d255d3SCy Schubert 		X509_free(x509);
3299c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
3300c1d255d3SCy Schubert 			   "OpenSSL: Found PEM encoded certificate from blob");
3301c1d255d3SCy Schubert 		while ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL))) {
3302c1d255d3SCy Schubert 			wpa_printf(MSG_DEBUG,
3303c1d255d3SCy Schubert 				   "OpenSSL: Added an additional certificate into the chain");
3304c1d255d3SCy Schubert 			SSL_add0_chain_cert(conn->ssl, x509);
3305c1d255d3SCy Schubert 		}
3306c1d255d3SCy Schubert 		BIO_free(bio);
3307c1d255d3SCy Schubert 		return 0;
3308c1d255d3SCy Schubert #endif
330939beb93cSSam Leffler 	}
331039beb93cSSam Leffler 
331139beb93cSSam Leffler 	if (client_cert == NULL)
331239beb93cSSam Leffler 		return -1;
331339beb93cSSam Leffler 
3314f05cddf9SRui Paulo #ifdef ANDROID
3315f05cddf9SRui Paulo 	if (os_strncmp("keystore://", client_cert, 11) == 0) {
3316f05cddf9SRui Paulo 		BIO *bio = BIO_from_keystore(&client_cert[11]);
3317f05cddf9SRui Paulo 		X509 *x509 = NULL;
3318f05cddf9SRui Paulo 		int ret = -1;
3319f05cddf9SRui Paulo 		if (bio) {
3320f05cddf9SRui Paulo 			x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
3321f05cddf9SRui Paulo 		}
3322f05cddf9SRui Paulo 		if (x509) {
3323f05cddf9SRui Paulo 			if (SSL_use_certificate(conn->ssl, x509) == 1)
3324f05cddf9SRui Paulo 				ret = 0;
3325f05cddf9SRui Paulo 			X509_free(x509);
3326f05cddf9SRui Paulo 		}
332785732ac8SCy Schubert 
332885732ac8SCy Schubert 		/* Read additional certificates into the chain. */
332985732ac8SCy Schubert 		while (bio) {
333085732ac8SCy Schubert 			x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
333185732ac8SCy Schubert 			if (x509) {
333285732ac8SCy Schubert 				/* Takes ownership of x509 */
333385732ac8SCy Schubert 				SSL_add0_chain_cert(conn->ssl, x509);
333485732ac8SCy Schubert 			} else {
333585732ac8SCy Schubert 				BIO_free(bio);
333685732ac8SCy Schubert 				bio = NULL;
333785732ac8SCy Schubert 			}
333885732ac8SCy Schubert 		}
3339f05cddf9SRui Paulo 		return ret;
3340f05cddf9SRui Paulo 	}
3341f05cddf9SRui Paulo #endif /* ANDROID */
3342f05cddf9SRui Paulo 
334339beb93cSSam Leffler #ifndef OPENSSL_NO_STDIO
334439beb93cSSam Leffler 	if (SSL_use_certificate_file(conn->ssl, client_cert,
334539beb93cSSam Leffler 				     SSL_FILETYPE_ASN1) == 1) {
334639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (DER)"
334739beb93cSSam Leffler 			   " --> OK");
334839beb93cSSam Leffler 		return 0;
334939beb93cSSam Leffler 	}
335039beb93cSSam Leffler 
33514bc52338SCy Schubert #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
33524bc52338SCy Schubert 	!defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL)
33534bc52338SCy Schubert 	if (SSL_use_certificate_chain_file(conn->ssl, client_cert) == 1) {
33544bc52338SCy Schubert 		ERR_clear_error();
33554bc52338SCy Schubert 		wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_chain_file"
33564bc52338SCy Schubert 			   " --> OK");
33574bc52338SCy Schubert 		return 0;
33584bc52338SCy Schubert 	}
33594bc52338SCy Schubert #else
336039beb93cSSam Leffler 	if (SSL_use_certificate_file(conn->ssl, client_cert,
336139beb93cSSam Leffler 				     SSL_FILETYPE_PEM) == 1) {
3362f05cddf9SRui Paulo 		ERR_clear_error();
336339beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (PEM)"
336439beb93cSSam Leffler 			   " --> OK");
336539beb93cSSam Leffler 		return 0;
336639beb93cSSam Leffler 	}
33674bc52338SCy Schubert #endif
3368f05cddf9SRui Paulo 
3369f05cddf9SRui Paulo 	tls_show_errors(MSG_DEBUG, __func__,
3370f05cddf9SRui Paulo 			"SSL_use_certificate_file failed");
337139beb93cSSam Leffler #else /* OPENSSL_NO_STDIO */
337239beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__);
337339beb93cSSam Leffler #endif /* OPENSSL_NO_STDIO */
337439beb93cSSam Leffler 
337539beb93cSSam Leffler 	return -1;
337639beb93cSSam Leffler }
337739beb93cSSam Leffler 
337839beb93cSSam Leffler 
tls_global_client_cert(struct tls_data * data,const char * client_cert)3379325151a3SRui Paulo static int tls_global_client_cert(struct tls_data *data,
3380325151a3SRui Paulo 				  const char *client_cert)
338139beb93cSSam Leffler {
338239beb93cSSam Leffler #ifndef OPENSSL_NO_STDIO
3383325151a3SRui Paulo 	SSL_CTX *ssl_ctx = data->ssl;
3384325151a3SRui Paulo 
338539beb93cSSam Leffler 	if (client_cert == NULL)
338639beb93cSSam Leffler 		return 0;
338739beb93cSSam Leffler 
338839beb93cSSam Leffler 	if (SSL_CTX_use_certificate_file(ssl_ctx, client_cert,
338939beb93cSSam Leffler 					 SSL_FILETYPE_ASN1) != 1 &&
3390f05cddf9SRui Paulo 	    SSL_CTX_use_certificate_chain_file(ssl_ctx, client_cert) != 1 &&
339139beb93cSSam Leffler 	    SSL_CTX_use_certificate_file(ssl_ctx, client_cert,
339239beb93cSSam Leffler 					 SSL_FILETYPE_PEM) != 1) {
339339beb93cSSam Leffler 		tls_show_errors(MSG_INFO, __func__,
339439beb93cSSam Leffler 				"Failed to load client certificate");
339539beb93cSSam Leffler 		return -1;
339639beb93cSSam Leffler 	}
339739beb93cSSam Leffler 	return 0;
339839beb93cSSam Leffler #else /* OPENSSL_NO_STDIO */
339939beb93cSSam Leffler 	if (client_cert == NULL)
340039beb93cSSam Leffler 		return 0;
340139beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__);
340239beb93cSSam Leffler 	return -1;
340339beb93cSSam Leffler #endif /* OPENSSL_NO_STDIO */
340439beb93cSSam Leffler }
340539beb93cSSam Leffler 
340639beb93cSSam Leffler 
340739beb93cSSam Leffler #ifdef PKCS12_FUNCS
tls_parse_pkcs12(struct tls_data * data,SSL * ssl,PKCS12 * p12,const char * passwd)3408325151a3SRui Paulo static int tls_parse_pkcs12(struct tls_data *data, SSL *ssl, PKCS12 *p12,
340939beb93cSSam Leffler 			    const char *passwd)
341039beb93cSSam Leffler {
341139beb93cSSam Leffler 	EVP_PKEY *pkey;
341239beb93cSSam Leffler 	X509 *cert;
341339beb93cSSam Leffler 	STACK_OF(X509) *certs;
341439beb93cSSam Leffler 	int res = 0;
341539beb93cSSam Leffler 	char buf[256];
341639beb93cSSam Leffler 
341739beb93cSSam Leffler 	pkey = NULL;
341839beb93cSSam Leffler 	cert = NULL;
341939beb93cSSam Leffler 	certs = NULL;
3420325151a3SRui Paulo 	if (!passwd)
3421325151a3SRui Paulo 		passwd = "";
342239beb93cSSam Leffler 	if (!PKCS12_parse(p12, passwd, &pkey, &cert, &certs)) {
342339beb93cSSam Leffler 		tls_show_errors(MSG_DEBUG, __func__,
342439beb93cSSam Leffler 				"Failed to parse PKCS12 file");
342539beb93cSSam Leffler 		PKCS12_free(p12);
342639beb93cSSam Leffler 		return -1;
342739beb93cSSam Leffler 	}
342839beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLS: Successfully parsed PKCS12 data");
342939beb93cSSam Leffler 
343039beb93cSSam Leffler 	if (cert) {
343139beb93cSSam Leffler 		X509_NAME_oneline(X509_get_subject_name(cert), buf,
343239beb93cSSam Leffler 				  sizeof(buf));
343339beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLS: Got certificate from PKCS12: "
343439beb93cSSam Leffler 			   "subject='%s'", buf);
343539beb93cSSam Leffler 		if (ssl) {
343639beb93cSSam Leffler 			if (SSL_use_certificate(ssl, cert) != 1)
343739beb93cSSam Leffler 				res = -1;
343839beb93cSSam Leffler 		} else {
3439325151a3SRui Paulo 			if (SSL_CTX_use_certificate(data->ssl, cert) != 1)
344039beb93cSSam Leffler 				res = -1;
344139beb93cSSam Leffler 		}
344239beb93cSSam Leffler 		X509_free(cert);
344339beb93cSSam Leffler 	}
344439beb93cSSam Leffler 
344539beb93cSSam Leffler 	if (pkey) {
344639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLS: Got private key from PKCS12");
344739beb93cSSam Leffler 		if (ssl) {
344839beb93cSSam Leffler 			if (SSL_use_PrivateKey(ssl, pkey) != 1)
344939beb93cSSam Leffler 				res = -1;
345039beb93cSSam Leffler 		} else {
3451325151a3SRui Paulo 			if (SSL_CTX_use_PrivateKey(data->ssl, pkey) != 1)
345239beb93cSSam Leffler 				res = -1;
345339beb93cSSam Leffler 		}
345439beb93cSSam Leffler 		EVP_PKEY_free(pkey);
345539beb93cSSam Leffler 	}
345639beb93cSSam Leffler 
345739beb93cSSam Leffler 	if (certs) {
3458780fb4a2SCy Schubert #if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
3459780fb4a2SCy Schubert 		if (ssl)
3460325151a3SRui Paulo 			SSL_clear_chain_certs(ssl);
3461780fb4a2SCy Schubert 		else
3462780fb4a2SCy Schubert 			SSL_CTX_clear_chain_certs(data->ssl);
3463325151a3SRui Paulo 		while ((cert = sk_X509_pop(certs)) != NULL) {
3464325151a3SRui Paulo 			X509_NAME_oneline(X509_get_subject_name(cert), buf,
3465325151a3SRui Paulo 					  sizeof(buf));
3466325151a3SRui Paulo 			wpa_printf(MSG_DEBUG, "TLS: additional certificate"
3467325151a3SRui Paulo 				   " from PKCS12: subject='%s'", buf);
3468780fb4a2SCy Schubert 			if ((ssl && SSL_add1_chain_cert(ssl, cert) != 1) ||
3469780fb4a2SCy Schubert 			    (!ssl && SSL_CTX_add1_chain_cert(data->ssl,
3470780fb4a2SCy Schubert 							     cert) != 1)) {
3471325151a3SRui Paulo 				tls_show_errors(MSG_DEBUG, __func__,
3472325151a3SRui Paulo 						"Failed to add additional certificate");
3473325151a3SRui Paulo 				res = -1;
3474780fb4a2SCy Schubert 				X509_free(cert);
3475325151a3SRui Paulo 				break;
3476325151a3SRui Paulo 			}
3477780fb4a2SCy Schubert 			X509_free(cert);
3478325151a3SRui Paulo 		}
3479325151a3SRui Paulo 		if (!res) {
3480325151a3SRui Paulo 			/* Try to continue anyway */
3481325151a3SRui Paulo 		}
3482780fb4a2SCy Schubert 		sk_X509_pop_free(certs, X509_free);
3483325151a3SRui Paulo #ifndef OPENSSL_IS_BORINGSSL
3484780fb4a2SCy Schubert 		if (ssl)
3485780fb4a2SCy Schubert 			res = SSL_build_cert_chain(
3486780fb4a2SCy Schubert 				ssl,
3487780fb4a2SCy Schubert 				SSL_BUILD_CHAIN_FLAG_CHECK |
3488780fb4a2SCy Schubert 				SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR);
3489780fb4a2SCy Schubert 		else
3490780fb4a2SCy Schubert 			res = SSL_CTX_build_cert_chain(
3491780fb4a2SCy Schubert 				data->ssl,
3492325151a3SRui Paulo 				SSL_BUILD_CHAIN_FLAG_CHECK |
3493325151a3SRui Paulo 				SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR);
3494325151a3SRui Paulo 		if (!res) {
3495325151a3SRui Paulo 			tls_show_errors(MSG_DEBUG, __func__,
3496325151a3SRui Paulo 					"Failed to build certificate chain");
3497325151a3SRui Paulo 		} else if (res == 2) {
3498325151a3SRui Paulo 			wpa_printf(MSG_DEBUG,
3499325151a3SRui Paulo 				   "TLS: Ignore certificate chain verification error when building chain with PKCS#12 extra certificates");
3500325151a3SRui Paulo 		}
3501325151a3SRui Paulo #endif /* OPENSSL_IS_BORINGSSL */
3502325151a3SRui Paulo 		/*
3503325151a3SRui Paulo 		 * Try to continue regardless of result since it is possible for
3504325151a3SRui Paulo 		 * the extra certificates not to be required.
3505325151a3SRui Paulo 		 */
3506325151a3SRui Paulo 		res = 0;
3507325151a3SRui Paulo #else /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
3508325151a3SRui Paulo 		SSL_CTX_clear_extra_chain_certs(data->ssl);
350939beb93cSSam Leffler 		while ((cert = sk_X509_pop(certs)) != NULL) {
351039beb93cSSam Leffler 			X509_NAME_oneline(X509_get_subject_name(cert), buf,
351139beb93cSSam Leffler 					  sizeof(buf));
351239beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLS: additional certificate"
351339beb93cSSam Leffler 				   " from PKCS12: subject='%s'", buf);
351439beb93cSSam Leffler 			/*
351539beb93cSSam Leffler 			 * There is no SSL equivalent for the chain cert - so
351639beb93cSSam Leffler 			 * always add it to the context...
351739beb93cSSam Leffler 			 */
3518325151a3SRui Paulo 			if (SSL_CTX_add_extra_chain_cert(data->ssl, cert) != 1)
3519325151a3SRui Paulo 			{
3520780fb4a2SCy Schubert 				X509_free(cert);
352139beb93cSSam Leffler 				res = -1;
352239beb93cSSam Leffler 				break;
352339beb93cSSam Leffler 			}
352439beb93cSSam Leffler 		}
3525780fb4a2SCy Schubert 		sk_X509_pop_free(certs, X509_free);
3526325151a3SRui Paulo #endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
352739beb93cSSam Leffler 	}
352839beb93cSSam Leffler 
352939beb93cSSam Leffler 	PKCS12_free(p12);
353039beb93cSSam Leffler 
353139beb93cSSam Leffler 	if (res < 0)
3532325151a3SRui Paulo 		tls_get_errors(data);
353339beb93cSSam Leffler 
353439beb93cSSam Leffler 	return res;
353539beb93cSSam Leffler }
353639beb93cSSam Leffler #endif  /* PKCS12_FUNCS */
353739beb93cSSam Leffler 
353839beb93cSSam Leffler 
tls_read_pkcs12(struct tls_data * data,SSL * ssl,const char * private_key,const char * passwd)3539325151a3SRui Paulo static int tls_read_pkcs12(struct tls_data *data, SSL *ssl,
3540325151a3SRui Paulo 			   const char *private_key, const char *passwd)
354139beb93cSSam Leffler {
354239beb93cSSam Leffler #ifdef PKCS12_FUNCS
354339beb93cSSam Leffler 	FILE *f;
354439beb93cSSam Leffler 	PKCS12 *p12;
354539beb93cSSam Leffler 
354639beb93cSSam Leffler 	f = fopen(private_key, "rb");
354739beb93cSSam Leffler 	if (f == NULL)
354839beb93cSSam Leffler 		return -1;
354939beb93cSSam Leffler 
355039beb93cSSam Leffler 	p12 = d2i_PKCS12_fp(f, NULL);
355139beb93cSSam Leffler 	fclose(f);
355239beb93cSSam Leffler 
355339beb93cSSam Leffler 	if (p12 == NULL) {
355439beb93cSSam Leffler 		tls_show_errors(MSG_INFO, __func__,
355539beb93cSSam Leffler 				"Failed to use PKCS#12 file");
355639beb93cSSam Leffler 		return -1;
355739beb93cSSam Leffler 	}
355839beb93cSSam Leffler 
3559325151a3SRui Paulo 	return tls_parse_pkcs12(data, ssl, p12, passwd);
356039beb93cSSam Leffler 
356139beb93cSSam Leffler #else /* PKCS12_FUNCS */
356239beb93cSSam Leffler 	wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot read "
356339beb93cSSam Leffler 		   "p12/pfx files");
356439beb93cSSam Leffler 	return -1;
356539beb93cSSam Leffler #endif  /* PKCS12_FUNCS */
356639beb93cSSam Leffler }
356739beb93cSSam Leffler 
356839beb93cSSam Leffler 
tls_read_pkcs12_blob(struct tls_data * data,SSL * ssl,const u8 * blob,size_t len,const char * passwd)3569325151a3SRui Paulo static int tls_read_pkcs12_blob(struct tls_data *data, SSL *ssl,
357039beb93cSSam Leffler 				const u8 *blob, size_t len, const char *passwd)
357139beb93cSSam Leffler {
357239beb93cSSam Leffler #ifdef PKCS12_FUNCS
357339beb93cSSam Leffler 	PKCS12 *p12;
357439beb93cSSam Leffler 
35755b9c547cSRui Paulo 	p12 = d2i_PKCS12(NULL, (const unsigned char **) &blob, len);
357639beb93cSSam Leffler 	if (p12 == NULL) {
357739beb93cSSam Leffler 		tls_show_errors(MSG_INFO, __func__,
357839beb93cSSam Leffler 				"Failed to use PKCS#12 blob");
357939beb93cSSam Leffler 		return -1;
358039beb93cSSam Leffler 	}
358139beb93cSSam Leffler 
3582325151a3SRui Paulo 	return tls_parse_pkcs12(data, ssl, p12, passwd);
358339beb93cSSam Leffler 
358439beb93cSSam Leffler #else /* PKCS12_FUNCS */
358539beb93cSSam Leffler 	wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot parse "
358639beb93cSSam Leffler 		   "p12/pfx blobs");
358739beb93cSSam Leffler 	return -1;
358839beb93cSSam Leffler #endif  /* PKCS12_FUNCS */
358939beb93cSSam Leffler }
359039beb93cSSam Leffler 
359139beb93cSSam Leffler 
359239beb93cSSam Leffler #ifndef OPENSSL_NO_ENGINE
tls_engine_get_cert(struct tls_connection * conn,const char * cert_id,X509 ** cert)359339beb93cSSam Leffler static int tls_engine_get_cert(struct tls_connection *conn,
359439beb93cSSam Leffler 			       const char *cert_id,
359539beb93cSSam Leffler 			       X509 **cert)
359639beb93cSSam Leffler {
359739beb93cSSam Leffler 	/* this runs after the private key is loaded so no PIN is required */
359839beb93cSSam Leffler 	struct {
359939beb93cSSam Leffler 		const char *cert_id;
360039beb93cSSam Leffler 		X509 *cert;
360139beb93cSSam Leffler 	} params;
360239beb93cSSam Leffler 	params.cert_id = cert_id;
360339beb93cSSam Leffler 	params.cert = NULL;
360439beb93cSSam Leffler 
360539beb93cSSam Leffler 	if (!ENGINE_ctrl_cmd(conn->engine, "LOAD_CERT_CTRL",
360639beb93cSSam Leffler 			     0, &params, NULL, 1)) {
3607325151a3SRui Paulo 		unsigned long err = ERR_get_error();
3608325151a3SRui Paulo 
360939beb93cSSam Leffler 		wpa_printf(MSG_ERROR, "ENGINE: cannot load client cert with id"
361039beb93cSSam Leffler 			   " '%s' [%s]", cert_id,
3611325151a3SRui Paulo 			   ERR_error_string(err, NULL));
3612325151a3SRui Paulo 		if (tls_is_pin_error(err))
3613325151a3SRui Paulo 			return TLS_SET_PARAMS_ENGINE_PRV_BAD_PIN;
361439beb93cSSam Leffler 		return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
361539beb93cSSam Leffler 	}
361639beb93cSSam Leffler 	if (!params.cert) {
361739beb93cSSam Leffler 		wpa_printf(MSG_ERROR, "ENGINE: did not properly cert with id"
361839beb93cSSam Leffler 			   " '%s'", cert_id);
361939beb93cSSam Leffler 		return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
362039beb93cSSam Leffler 	}
362139beb93cSSam Leffler 	*cert = params.cert;
362239beb93cSSam Leffler 	return 0;
362339beb93cSSam Leffler }
362439beb93cSSam Leffler #endif /* OPENSSL_NO_ENGINE */
362539beb93cSSam Leffler 
362639beb93cSSam Leffler 
tls_connection_engine_client_cert(struct tls_connection * conn,const char * cert_id)362739beb93cSSam Leffler static int tls_connection_engine_client_cert(struct tls_connection *conn,
362839beb93cSSam Leffler 					     const char *cert_id)
362939beb93cSSam Leffler {
363039beb93cSSam Leffler #ifndef OPENSSL_NO_ENGINE
363139beb93cSSam Leffler 	X509 *cert;
363239beb93cSSam Leffler 
363339beb93cSSam Leffler 	if (tls_engine_get_cert(conn, cert_id, &cert))
363439beb93cSSam Leffler 		return -1;
363539beb93cSSam Leffler 
363639beb93cSSam Leffler 	if (!SSL_use_certificate(conn->ssl, cert)) {
363739beb93cSSam Leffler 		tls_show_errors(MSG_ERROR, __func__,
363839beb93cSSam Leffler 				"SSL_use_certificate failed");
363939beb93cSSam Leffler                 X509_free(cert);
364039beb93cSSam Leffler 		return -1;
364139beb93cSSam Leffler 	}
364239beb93cSSam Leffler 	X509_free(cert);
364339beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "ENGINE: SSL_use_certificate --> "
364439beb93cSSam Leffler 		   "OK");
364539beb93cSSam Leffler 	return 0;
364639beb93cSSam Leffler 
364739beb93cSSam Leffler #else /* OPENSSL_NO_ENGINE */
364839beb93cSSam Leffler 	return -1;
364939beb93cSSam Leffler #endif /* OPENSSL_NO_ENGINE */
365039beb93cSSam Leffler }
365139beb93cSSam Leffler 
365239beb93cSSam Leffler 
tls_connection_engine_ca_cert(struct tls_data * data,struct tls_connection * conn,const char * ca_cert_id)3653325151a3SRui Paulo static int tls_connection_engine_ca_cert(struct tls_data *data,
365439beb93cSSam Leffler 					 struct tls_connection *conn,
365539beb93cSSam Leffler 					 const char *ca_cert_id)
365639beb93cSSam Leffler {
365739beb93cSSam Leffler #ifndef OPENSSL_NO_ENGINE
365839beb93cSSam Leffler 	X509 *cert;
3659325151a3SRui Paulo 	SSL_CTX *ssl_ctx = data->ssl;
36605b9c547cSRui Paulo 	X509_STORE *store;
366139beb93cSSam Leffler 
366239beb93cSSam Leffler 	if (tls_engine_get_cert(conn, ca_cert_id, &cert))
366339beb93cSSam Leffler 		return -1;
366439beb93cSSam Leffler 
366539beb93cSSam Leffler 	/* start off the same as tls_connection_ca_cert */
36665b9c547cSRui Paulo 	store = X509_STORE_new();
36675b9c547cSRui Paulo 	if (store == NULL) {
366839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new "
366939beb93cSSam Leffler 			   "certificate store", __func__);
367039beb93cSSam Leffler 		X509_free(cert);
367139beb93cSSam Leffler 		return -1;
367239beb93cSSam Leffler 	}
36735b9c547cSRui Paulo 	SSL_CTX_set_cert_store(ssl_ctx, store);
36745b9c547cSRui Paulo 	if (!X509_STORE_add_cert(store, cert)) {
367539beb93cSSam Leffler 		unsigned long err = ERR_peek_error();
367639beb93cSSam Leffler 		tls_show_errors(MSG_WARNING, __func__,
367739beb93cSSam Leffler 				"Failed to add CA certificate from engine "
367839beb93cSSam Leffler 				"to certificate store");
367939beb93cSSam Leffler 		if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
368039beb93cSSam Leffler 		    ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) {
368139beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring cert"
368239beb93cSSam Leffler 				   " already in hash table error",
368339beb93cSSam Leffler 				   __func__);
368439beb93cSSam Leffler 		} else {
368539beb93cSSam Leffler 			X509_free(cert);
368639beb93cSSam Leffler 			return -1;
368739beb93cSSam Leffler 		}
368839beb93cSSam Leffler 	}
368939beb93cSSam Leffler 	X509_free(cert);
369039beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "OpenSSL: %s - added CA certificate from engine "
369139beb93cSSam Leffler 		   "to certificate store", __func__);
369239beb93cSSam Leffler 	SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
3693f05cddf9SRui Paulo 	conn->ca_cert_verify = 1;
3694f05cddf9SRui Paulo 
369539beb93cSSam Leffler 	return 0;
369639beb93cSSam Leffler 
369739beb93cSSam Leffler #else /* OPENSSL_NO_ENGINE */
369839beb93cSSam Leffler 	return -1;
369939beb93cSSam Leffler #endif /* OPENSSL_NO_ENGINE */
370039beb93cSSam Leffler }
370139beb93cSSam Leffler 
370239beb93cSSam Leffler 
tls_connection_engine_private_key(struct tls_connection * conn)370339beb93cSSam Leffler static int tls_connection_engine_private_key(struct tls_connection *conn)
370439beb93cSSam Leffler {
3705780fb4a2SCy Schubert #if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE)
370639beb93cSSam Leffler 	if (SSL_use_PrivateKey(conn->ssl, conn->private_key) != 1) {
370739beb93cSSam Leffler 		tls_show_errors(MSG_ERROR, __func__,
370839beb93cSSam Leffler 				"ENGINE: cannot use private key for TLS");
370939beb93cSSam Leffler 		return -1;
371039beb93cSSam Leffler 	}
371139beb93cSSam Leffler 	if (!SSL_check_private_key(conn->ssl)) {
371239beb93cSSam Leffler 		tls_show_errors(MSG_INFO, __func__,
371339beb93cSSam Leffler 				"Private key failed verification");
371439beb93cSSam Leffler 		return -1;
371539beb93cSSam Leffler 	}
371639beb93cSSam Leffler 	return 0;
371739beb93cSSam Leffler #else /* OPENSSL_NO_ENGINE */
371839beb93cSSam Leffler 	wpa_printf(MSG_ERROR, "SSL: Configuration uses engine, but "
371939beb93cSSam Leffler 		   "engine support was not compiled in");
372039beb93cSSam Leffler 	return -1;
372139beb93cSSam Leffler #endif /* OPENSSL_NO_ENGINE */
372239beb93cSSam Leffler }
372339beb93cSSam Leffler 
372439beb93cSSam Leffler 
372585732ac8SCy Schubert #ifndef OPENSSL_NO_STDIO
tls_passwd_cb(char * buf,int size,int rwflag,void * password)372685732ac8SCy Schubert static int tls_passwd_cb(char *buf, int size, int rwflag, void *password)
372785732ac8SCy Schubert {
372885732ac8SCy Schubert 	if (!password)
372985732ac8SCy Schubert 		return 0;
373085732ac8SCy Schubert 	os_strlcpy(buf, (const char *) password, size);
373185732ac8SCy Schubert 	return os_strlen(buf);
373285732ac8SCy Schubert }
373385732ac8SCy Schubert #endif /* OPENSSL_NO_STDIO */
373485732ac8SCy Schubert 
373585732ac8SCy Schubert 
tls_use_private_key_file(struct tls_data * data,SSL * ssl,const char * private_key,const char * private_key_passwd)373685732ac8SCy Schubert static int tls_use_private_key_file(struct tls_data *data, SSL *ssl,
373785732ac8SCy Schubert 				    const char *private_key,
373885732ac8SCy Schubert 				    const char *private_key_passwd)
373985732ac8SCy Schubert {
374085732ac8SCy Schubert #ifndef OPENSSL_NO_STDIO
374185732ac8SCy Schubert 	BIO *bio;
374285732ac8SCy Schubert 	EVP_PKEY *pkey;
374385732ac8SCy Schubert 	int ret;
374485732ac8SCy Schubert 
374585732ac8SCy Schubert 	/* First try ASN.1 (DER). */
374685732ac8SCy Schubert 	bio = BIO_new_file(private_key, "r");
374785732ac8SCy Schubert 	if (!bio)
374885732ac8SCy Schubert 		return -1;
374985732ac8SCy Schubert 	pkey = d2i_PrivateKey_bio(bio, NULL);
375085732ac8SCy Schubert 	BIO_free(bio);
375185732ac8SCy Schubert 
375285732ac8SCy Schubert 	if (pkey) {
375385732ac8SCy Schubert 		wpa_printf(MSG_DEBUG, "OpenSSL: %s (DER) --> loaded", __func__);
375485732ac8SCy Schubert 	} else {
375585732ac8SCy Schubert 		/* Try PEM with the provided password. */
375685732ac8SCy Schubert 		bio = BIO_new_file(private_key, "r");
375785732ac8SCy Schubert 		if (!bio)
375885732ac8SCy Schubert 			return -1;
375985732ac8SCy Schubert 		pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_passwd_cb,
376085732ac8SCy Schubert 					       (void *) private_key_passwd);
376185732ac8SCy Schubert 		BIO_free(bio);
376285732ac8SCy Schubert 		if (!pkey)
376385732ac8SCy Schubert 			return -1;
376485732ac8SCy Schubert 		wpa_printf(MSG_DEBUG, "OpenSSL: %s (PEM) --> loaded", __func__);
376585732ac8SCy Schubert 		/* Clear errors from the previous failed load. */
376685732ac8SCy Schubert 		ERR_clear_error();
376785732ac8SCy Schubert 	}
376885732ac8SCy Schubert 
376985732ac8SCy Schubert 	if (ssl)
377085732ac8SCy Schubert 		ret = SSL_use_PrivateKey(ssl, pkey);
377185732ac8SCy Schubert 	else
377285732ac8SCy Schubert 		ret = SSL_CTX_use_PrivateKey(data->ssl, pkey);
377385732ac8SCy Schubert 
377485732ac8SCy Schubert 	EVP_PKEY_free(pkey);
377585732ac8SCy Schubert 	return ret == 1 ? 0 : -1;
377685732ac8SCy Schubert #else /* OPENSSL_NO_STDIO */
377785732ac8SCy Schubert 	wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__);
377885732ac8SCy Schubert 	return -1;
377985732ac8SCy Schubert #endif /* OPENSSL_NO_STDIO */
378085732ac8SCy Schubert }
378185732ac8SCy Schubert 
378285732ac8SCy Schubert 
tls_connection_private_key(struct tls_data * data,struct tls_connection * conn,const char * private_key,const char * private_key_passwd,const u8 * private_key_blob,size_t private_key_blob_len)3783325151a3SRui Paulo static int tls_connection_private_key(struct tls_data *data,
378439beb93cSSam Leffler 				      struct tls_connection *conn,
378539beb93cSSam Leffler 				      const char *private_key,
378639beb93cSSam Leffler 				      const char *private_key_passwd,
378739beb93cSSam Leffler 				      const u8 *private_key_blob,
378839beb93cSSam Leffler 				      size_t private_key_blob_len)
378939beb93cSSam Leffler {
37904b72b91aSCy Schubert 	BIO *bio;
379139beb93cSSam Leffler 	int ok;
379239beb93cSSam Leffler 
379339beb93cSSam Leffler 	if (private_key == NULL && private_key_blob == NULL)
379439beb93cSSam Leffler 		return 0;
379539beb93cSSam Leffler 
379639beb93cSSam Leffler 	ok = 0;
379739beb93cSSam Leffler 	while (private_key_blob) {
379839beb93cSSam Leffler 		if (SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA, conn->ssl,
379939beb93cSSam Leffler 					    (u8 *) private_key_blob,
380039beb93cSSam Leffler 					    private_key_blob_len) == 1) {
380139beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_"
380239beb93cSSam Leffler 				   "ASN1(EVP_PKEY_RSA) --> OK");
380339beb93cSSam Leffler 			ok = 1;
380439beb93cSSam Leffler 			break;
380539beb93cSSam Leffler 		}
380639beb93cSSam Leffler 
380739beb93cSSam Leffler 		if (SSL_use_PrivateKey_ASN1(EVP_PKEY_DSA, conn->ssl,
380839beb93cSSam Leffler 					    (u8 *) private_key_blob,
380939beb93cSSam Leffler 					    private_key_blob_len) == 1) {
381039beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_"
381139beb93cSSam Leffler 				   "ASN1(EVP_PKEY_DSA) --> OK");
381239beb93cSSam Leffler 			ok = 1;
381339beb93cSSam Leffler 			break;
381439beb93cSSam Leffler 		}
381539beb93cSSam Leffler 
3816c1d255d3SCy Schubert #ifndef OPENSSL_NO_EC
3817c1d255d3SCy Schubert 		if (SSL_use_PrivateKey_ASN1(EVP_PKEY_EC, conn->ssl,
3818c1d255d3SCy Schubert 					    (u8 *) private_key_blob,
3819c1d255d3SCy Schubert 					    private_key_blob_len) == 1) {
3820c1d255d3SCy Schubert 			wpa_printf(MSG_DEBUG,
3821c1d255d3SCy Schubert 				   "OpenSSL: SSL_use_PrivateKey_ASN1(EVP_PKEY_EC) --> OK");
3822c1d255d3SCy Schubert 			ok = 1;
3823c1d255d3SCy Schubert 			break;
3824c1d255d3SCy Schubert 		}
3825c1d255d3SCy Schubert #endif /* OPENSSL_NO_EC */
3826c1d255d3SCy Schubert 
382739beb93cSSam Leffler 		if (SSL_use_RSAPrivateKey_ASN1(conn->ssl,
382839beb93cSSam Leffler 					       (u8 *) private_key_blob,
382939beb93cSSam Leffler 					       private_key_blob_len) == 1) {
383039beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "OpenSSL: "
383139beb93cSSam Leffler 				   "SSL_use_RSAPrivateKey_ASN1 --> OK");
383239beb93cSSam Leffler 			ok = 1;
383339beb93cSSam Leffler 			break;
383439beb93cSSam Leffler 		}
383539beb93cSSam Leffler 
38364b72b91aSCy Schubert 		bio = BIO_new_mem_buf((u8 *) private_key_blob,
38374b72b91aSCy Schubert 				      private_key_blob_len);
38384b72b91aSCy Schubert 		if (bio) {
38394b72b91aSCy Schubert 			EVP_PKEY *pkey;
38404b72b91aSCy Schubert 
38414b72b91aSCy Schubert 			pkey = PEM_read_bio_PrivateKey(
38424b72b91aSCy Schubert 				bio, NULL, tls_passwd_cb,
38434b72b91aSCy Schubert 				(void *) private_key_passwd);
38444b72b91aSCy Schubert 			if (pkey) {
38454b72b91aSCy Schubert 				if (SSL_use_PrivateKey(conn->ssl, pkey) == 1) {
38464b72b91aSCy Schubert 					wpa_printf(MSG_DEBUG,
38474b72b91aSCy Schubert 						   "OpenSSL: SSL_use_PrivateKey --> OK");
38484b72b91aSCy Schubert 					ok = 1;
38494b72b91aSCy Schubert 					EVP_PKEY_free(pkey);
38504b72b91aSCy Schubert 					BIO_free(bio);
38514b72b91aSCy Schubert 					break;
38524b72b91aSCy Schubert 				}
38534b72b91aSCy Schubert 				EVP_PKEY_free(pkey);
38544b72b91aSCy Schubert 			}
38554b72b91aSCy Schubert 			BIO_free(bio);
38564b72b91aSCy Schubert 		}
38574b72b91aSCy Schubert 
3858325151a3SRui Paulo 		if (tls_read_pkcs12_blob(data, conn->ssl, private_key_blob,
385985732ac8SCy Schubert 					 private_key_blob_len,
386085732ac8SCy Schubert 					 private_key_passwd) == 0) {
386139beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "OpenSSL: PKCS#12 as blob --> "
386239beb93cSSam Leffler 				   "OK");
386339beb93cSSam Leffler 			ok = 1;
386439beb93cSSam Leffler 			break;
386539beb93cSSam Leffler 		}
386639beb93cSSam Leffler 
386739beb93cSSam Leffler 		break;
386839beb93cSSam Leffler 	}
386939beb93cSSam Leffler 
387039beb93cSSam Leffler 	while (!ok && private_key) {
387185732ac8SCy Schubert 		if (tls_use_private_key_file(data, conn->ssl, private_key,
387285732ac8SCy Schubert 					     private_key_passwd) == 0) {
387339beb93cSSam Leffler 			ok = 1;
387439beb93cSSam Leffler 			break;
387539beb93cSSam Leffler 		}
387639beb93cSSam Leffler 
387785732ac8SCy Schubert 		if (tls_read_pkcs12(data, conn->ssl, private_key,
387885732ac8SCy Schubert 				    private_key_passwd) == 0) {
387939beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "OpenSSL: Reading PKCS#12 file "
388039beb93cSSam Leffler 				   "--> OK");
388139beb93cSSam Leffler 			ok = 1;
388239beb93cSSam Leffler 			break;
388339beb93cSSam Leffler 		}
388439beb93cSSam Leffler 
388539beb93cSSam Leffler 		if (tls_cryptoapi_cert(conn->ssl, private_key) == 0) {
388639beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "OpenSSL: Using CryptoAPI to "
388739beb93cSSam Leffler 				   "access certificate store --> OK");
388839beb93cSSam Leffler 			ok = 1;
388939beb93cSSam Leffler 			break;
389039beb93cSSam Leffler 		}
389139beb93cSSam Leffler 
389239beb93cSSam Leffler 		break;
389339beb93cSSam Leffler 	}
389439beb93cSSam Leffler 
389539beb93cSSam Leffler 	if (!ok) {
3896f05cddf9SRui Paulo 		tls_show_errors(MSG_INFO, __func__,
3897f05cddf9SRui Paulo 				"Failed to load private key");
389839beb93cSSam Leffler 		return -1;
389939beb93cSSam Leffler 	}
390039beb93cSSam Leffler 	ERR_clear_error();
390139beb93cSSam Leffler 
390239beb93cSSam Leffler 	if (!SSL_check_private_key(conn->ssl)) {
390339beb93cSSam Leffler 		tls_show_errors(MSG_INFO, __func__, "Private key failed "
390439beb93cSSam Leffler 				"verification");
390539beb93cSSam Leffler 		return -1;
390639beb93cSSam Leffler 	}
390739beb93cSSam Leffler 
390839beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "SSL: Private key loaded successfully");
390939beb93cSSam Leffler 	return 0;
391039beb93cSSam Leffler }
391139beb93cSSam Leffler 
391239beb93cSSam Leffler 
tls_global_private_key(struct tls_data * data,const char * private_key,const char * private_key_passwd)3913325151a3SRui Paulo static int tls_global_private_key(struct tls_data *data,
3914325151a3SRui Paulo 				  const char *private_key,
391539beb93cSSam Leffler 				  const char *private_key_passwd)
391639beb93cSSam Leffler {
3917325151a3SRui Paulo 	SSL_CTX *ssl_ctx = data->ssl;
391839beb93cSSam Leffler 
391939beb93cSSam Leffler 	if (private_key == NULL)
392039beb93cSSam Leffler 		return 0;
392139beb93cSSam Leffler 
392285732ac8SCy Schubert 	if (tls_use_private_key_file(data, NULL, private_key,
392385732ac8SCy Schubert 				     private_key_passwd) &&
392485732ac8SCy Schubert 	    tls_read_pkcs12(data, NULL, private_key, private_key_passwd)) {
392539beb93cSSam Leffler 		tls_show_errors(MSG_INFO, __func__,
392639beb93cSSam Leffler 				"Failed to load private key");
392739beb93cSSam Leffler 		ERR_clear_error();
392839beb93cSSam Leffler 		return -1;
392939beb93cSSam Leffler 	}
393039beb93cSSam Leffler 	ERR_clear_error();
393139beb93cSSam Leffler 
393239beb93cSSam Leffler 	if (!SSL_CTX_check_private_key(ssl_ctx)) {
393339beb93cSSam Leffler 		tls_show_errors(MSG_INFO, __func__,
393439beb93cSSam Leffler 				"Private key failed verification");
393539beb93cSSam Leffler 		return -1;
393639beb93cSSam Leffler 	}
393739beb93cSSam Leffler 
393839beb93cSSam Leffler 	return 0;
393939beb93cSSam Leffler }
394039beb93cSSam Leffler 
394139beb93cSSam Leffler 
tls_connection_dh(struct tls_connection * conn,const char * dh_file)394239beb93cSSam Leffler static int tls_connection_dh(struct tls_connection *conn, const char *dh_file)
394339beb93cSSam Leffler {
394439beb93cSSam Leffler #ifdef OPENSSL_NO_DH
394539beb93cSSam Leffler 	if (dh_file == NULL)
394639beb93cSSam Leffler 		return 0;
394739beb93cSSam Leffler 	wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but "
394839beb93cSSam Leffler 		   "dh_file specified");
394939beb93cSSam Leffler 	return -1;
395039beb93cSSam Leffler #else /* OPENSSL_NO_DH */
395139beb93cSSam Leffler 	DH *dh;
395239beb93cSSam Leffler 	BIO *bio;
395339beb93cSSam Leffler 
395439beb93cSSam Leffler 	/* TODO: add support for dh_blob */
395539beb93cSSam Leffler 	if (dh_file == NULL)
395639beb93cSSam Leffler 		return 0;
395739beb93cSSam Leffler 	if (conn == NULL)
395839beb93cSSam Leffler 		return -1;
395939beb93cSSam Leffler 
396039beb93cSSam Leffler 	bio = BIO_new_file(dh_file, "r");
396139beb93cSSam Leffler 	if (bio == NULL) {
396239beb93cSSam Leffler 		wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s",
396339beb93cSSam Leffler 			   dh_file, ERR_error_string(ERR_get_error(), NULL));
396439beb93cSSam Leffler 		return -1;
396539beb93cSSam Leffler 	}
396639beb93cSSam Leffler 	dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
396739beb93cSSam Leffler 	BIO_free(bio);
396839beb93cSSam Leffler #ifndef OPENSSL_NO_DSA
396939beb93cSSam Leffler 	while (dh == NULL) {
397039beb93cSSam Leffler 		DSA *dsa;
397139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -"
397239beb93cSSam Leffler 			   " trying to parse as DSA params", dh_file,
397339beb93cSSam Leffler 			   ERR_error_string(ERR_get_error(), NULL));
397439beb93cSSam Leffler 		bio = BIO_new_file(dh_file, "r");
397539beb93cSSam Leffler 		if (bio == NULL)
397639beb93cSSam Leffler 			break;
397739beb93cSSam Leffler 		dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL);
397839beb93cSSam Leffler 		BIO_free(bio);
397939beb93cSSam Leffler 		if (!dsa) {
398039beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file "
398139beb93cSSam Leffler 				   "'%s': %s", dh_file,
398239beb93cSSam Leffler 				   ERR_error_string(ERR_get_error(), NULL));
398339beb93cSSam Leffler 			break;
398439beb93cSSam Leffler 		}
398539beb93cSSam Leffler 
398639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format");
398739beb93cSSam Leffler 		dh = DSA_dup_DH(dsa);
398839beb93cSSam Leffler 		DSA_free(dsa);
398939beb93cSSam Leffler 		if (dh == NULL) {
399039beb93cSSam Leffler 			wpa_printf(MSG_INFO, "TLS: Failed to convert DSA "
399139beb93cSSam Leffler 				   "params into DH params");
399239beb93cSSam Leffler 			break;
399339beb93cSSam Leffler 		}
399439beb93cSSam Leffler 		break;
399539beb93cSSam Leffler 	}
399639beb93cSSam Leffler #endif /* !OPENSSL_NO_DSA */
399739beb93cSSam Leffler 	if (dh == NULL) {
399839beb93cSSam Leffler 		wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file "
399939beb93cSSam Leffler 			   "'%s'", dh_file);
400039beb93cSSam Leffler 		return -1;
400139beb93cSSam Leffler 	}
400239beb93cSSam Leffler 
400339beb93cSSam Leffler 	if (SSL_set_tmp_dh(conn->ssl, dh) != 1) {
400439beb93cSSam Leffler 		wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': "
400539beb93cSSam Leffler 			   "%s", dh_file,
400639beb93cSSam Leffler 			   ERR_error_string(ERR_get_error(), NULL));
400739beb93cSSam Leffler 		DH_free(dh);
400839beb93cSSam Leffler 		return -1;
400939beb93cSSam Leffler 	}
401039beb93cSSam Leffler 	DH_free(dh);
401139beb93cSSam Leffler 	return 0;
401239beb93cSSam Leffler #endif /* OPENSSL_NO_DH */
401339beb93cSSam Leffler }
401439beb93cSSam Leffler 
401539beb93cSSam Leffler 
tls_global_dh(struct tls_data * data,const char * dh_file)4016325151a3SRui Paulo static int tls_global_dh(struct tls_data *data, const char *dh_file)
401739beb93cSSam Leffler {
401839beb93cSSam Leffler #ifdef OPENSSL_NO_DH
401939beb93cSSam Leffler 	if (dh_file == NULL)
402039beb93cSSam Leffler 		return 0;
402139beb93cSSam Leffler 	wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but "
402239beb93cSSam Leffler 		   "dh_file specified");
402339beb93cSSam Leffler 	return -1;
402439beb93cSSam Leffler #else /* OPENSSL_NO_DH */
4025325151a3SRui Paulo 	SSL_CTX *ssl_ctx = data->ssl;
402639beb93cSSam Leffler 	DH *dh;
402739beb93cSSam Leffler 	BIO *bio;
402839beb93cSSam Leffler 
402939beb93cSSam Leffler 	/* TODO: add support for dh_blob */
403039beb93cSSam Leffler 	if (dh_file == NULL)
403139beb93cSSam Leffler 		return 0;
403239beb93cSSam Leffler 	if (ssl_ctx == NULL)
403339beb93cSSam Leffler 		return -1;
403439beb93cSSam Leffler 
403539beb93cSSam Leffler 	bio = BIO_new_file(dh_file, "r");
403639beb93cSSam Leffler 	if (bio == NULL) {
403739beb93cSSam Leffler 		wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s",
403839beb93cSSam Leffler 			   dh_file, ERR_error_string(ERR_get_error(), NULL));
403939beb93cSSam Leffler 		return -1;
404039beb93cSSam Leffler 	}
404139beb93cSSam Leffler 	dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
404239beb93cSSam Leffler 	BIO_free(bio);
404339beb93cSSam Leffler #ifndef OPENSSL_NO_DSA
404439beb93cSSam Leffler 	while (dh == NULL) {
404539beb93cSSam Leffler 		DSA *dsa;
404639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -"
404739beb93cSSam Leffler 			   " trying to parse as DSA params", dh_file,
404839beb93cSSam Leffler 			   ERR_error_string(ERR_get_error(), NULL));
404939beb93cSSam Leffler 		bio = BIO_new_file(dh_file, "r");
405039beb93cSSam Leffler 		if (bio == NULL)
405139beb93cSSam Leffler 			break;
405239beb93cSSam Leffler 		dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL);
405339beb93cSSam Leffler 		BIO_free(bio);
405439beb93cSSam Leffler 		if (!dsa) {
405539beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file "
405639beb93cSSam Leffler 				   "'%s': %s", dh_file,
405739beb93cSSam Leffler 				   ERR_error_string(ERR_get_error(), NULL));
405839beb93cSSam Leffler 			break;
405939beb93cSSam Leffler 		}
406039beb93cSSam Leffler 
406139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format");
406239beb93cSSam Leffler 		dh = DSA_dup_DH(dsa);
406339beb93cSSam Leffler 		DSA_free(dsa);
406439beb93cSSam Leffler 		if (dh == NULL) {
406539beb93cSSam Leffler 			wpa_printf(MSG_INFO, "TLS: Failed to convert DSA "
406639beb93cSSam Leffler 				   "params into DH params");
406739beb93cSSam Leffler 			break;
406839beb93cSSam Leffler 		}
406939beb93cSSam Leffler 		break;
407039beb93cSSam Leffler 	}
407139beb93cSSam Leffler #endif /* !OPENSSL_NO_DSA */
407239beb93cSSam Leffler 	if (dh == NULL) {
407339beb93cSSam Leffler 		wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file "
407439beb93cSSam Leffler 			   "'%s'", dh_file);
407539beb93cSSam Leffler 		return -1;
407639beb93cSSam Leffler 	}
407739beb93cSSam Leffler 
407839beb93cSSam Leffler 	if (SSL_CTX_set_tmp_dh(ssl_ctx, dh) != 1) {
407939beb93cSSam Leffler 		wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': "
408039beb93cSSam Leffler 			   "%s", dh_file,
408139beb93cSSam Leffler 			   ERR_error_string(ERR_get_error(), NULL));
408239beb93cSSam Leffler 		DH_free(dh);
408339beb93cSSam Leffler 		return -1;
408439beb93cSSam Leffler 	}
408539beb93cSSam Leffler 	DH_free(dh);
408639beb93cSSam Leffler 	return 0;
408739beb93cSSam Leffler #endif /* OPENSSL_NO_DH */
408839beb93cSSam Leffler }
408939beb93cSSam Leffler 
409039beb93cSSam Leffler 
tls_connection_get_random(void * ssl_ctx,struct tls_connection * conn,struct tls_random * keys)4091325151a3SRui Paulo int tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn,
4092325151a3SRui Paulo 			      struct tls_random *keys)
4093325151a3SRui Paulo {
4094325151a3SRui Paulo 	SSL *ssl;
4095325151a3SRui Paulo 
4096325151a3SRui Paulo 	if (conn == NULL || keys == NULL)
4097325151a3SRui Paulo 		return -1;
4098325151a3SRui Paulo 	ssl = conn->ssl;
4099325151a3SRui Paulo 	if (ssl == NULL)
4100325151a3SRui Paulo 		return -1;
4101325151a3SRui Paulo 
4102325151a3SRui Paulo 	os_memset(keys, 0, sizeof(*keys));
4103325151a3SRui Paulo 	keys->client_random = conn->client_random;
4104325151a3SRui Paulo 	keys->client_random_len = SSL_get_client_random(
4105325151a3SRui Paulo 		ssl, conn->client_random, sizeof(conn->client_random));
4106325151a3SRui Paulo 	keys->server_random = conn->server_random;
4107325151a3SRui Paulo 	keys->server_random_len = SSL_get_server_random(
4108325151a3SRui Paulo 		ssl, conn->server_random, sizeof(conn->server_random));
4109325151a3SRui Paulo 
4110325151a3SRui Paulo 	return 0;
4111325151a3SRui Paulo }
4112325151a3SRui Paulo 
4113325151a3SRui Paulo 
4114780fb4a2SCy Schubert #ifdef OPENSSL_NEED_EAP_FAST_PRF
openssl_get_keyblock_size(SSL * ssl)4115325151a3SRui Paulo static int openssl_get_keyblock_size(SSL *ssl)
4116325151a3SRui Paulo {
411785732ac8SCy Schubert #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
411885732ac8SCy Schubert 	(defined(LIBRESSL_VERSION_NUMBER) && \
411985732ac8SCy Schubert 	 LIBRESSL_VERSION_NUMBER < 0x20700000L)
4120325151a3SRui Paulo 	const EVP_CIPHER *c;
4121325151a3SRui Paulo 	const EVP_MD *h;
4122325151a3SRui Paulo 	int md_size;
4123325151a3SRui Paulo 
4124325151a3SRui Paulo 	if (ssl->enc_read_ctx == NULL || ssl->enc_read_ctx->cipher == NULL ||
4125325151a3SRui Paulo 	    ssl->read_hash == NULL)
4126325151a3SRui Paulo 		return -1;
4127325151a3SRui Paulo 
4128325151a3SRui Paulo 	c = ssl->enc_read_ctx->cipher;
4129325151a3SRui Paulo 	h = EVP_MD_CTX_md(ssl->read_hash);
4130325151a3SRui Paulo 	if (h)
4131325151a3SRui Paulo 		md_size = EVP_MD_size(h);
4132325151a3SRui Paulo 	else if (ssl->s3)
4133325151a3SRui Paulo 		md_size = ssl->s3->tmp.new_mac_secret_size;
4134325151a3SRui Paulo 	else
4135325151a3SRui Paulo 		return -1;
4136325151a3SRui Paulo 
4137325151a3SRui Paulo 	wpa_printf(MSG_DEBUG, "OpenSSL: keyblock size: key_len=%d MD_size=%d "
4138325151a3SRui Paulo 		   "IV_len=%d", EVP_CIPHER_key_length(c), md_size,
4139325151a3SRui Paulo 		   EVP_CIPHER_iv_length(c));
4140325151a3SRui Paulo 	return 2 * (EVP_CIPHER_key_length(c) +
4141325151a3SRui Paulo 		    md_size +
4142325151a3SRui Paulo 		    EVP_CIPHER_iv_length(c));
4143325151a3SRui Paulo #else
4144325151a3SRui Paulo 	const SSL_CIPHER *ssl_cipher;
4145325151a3SRui Paulo 	int cipher, digest;
4146325151a3SRui Paulo 	const EVP_CIPHER *c;
4147325151a3SRui Paulo 	const EVP_MD *h;
4148c1d255d3SCy Schubert 	int mac_key_len, enc_key_len, fixed_iv_len;
4149325151a3SRui Paulo 
4150325151a3SRui Paulo 	ssl_cipher = SSL_get_current_cipher(ssl);
4151325151a3SRui Paulo 	if (!ssl_cipher)
4152325151a3SRui Paulo 		return -1;
4153325151a3SRui Paulo 	cipher = SSL_CIPHER_get_cipher_nid(ssl_cipher);
4154325151a3SRui Paulo 	digest = SSL_CIPHER_get_digest_nid(ssl_cipher);
4155325151a3SRui Paulo 	wpa_printf(MSG_DEBUG, "OpenSSL: cipher nid %d digest nid %d",
4156325151a3SRui Paulo 		   cipher, digest);
4157325151a3SRui Paulo 	if (cipher < 0 || digest < 0)
4158325151a3SRui Paulo 		return -1;
4159c1d255d3SCy Schubert 	if (cipher == NID_undef) {
4160c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "OpenSSL: no cipher in use?!");
4161325151a3SRui Paulo 		return -1;
4162c1d255d3SCy Schubert 	}
4163c1d255d3SCy Schubert 	c = EVP_get_cipherbynid(cipher);
4164c1d255d3SCy Schubert 	if (!c)
4165c1d255d3SCy Schubert 		return -1;
4166c1d255d3SCy Schubert 	enc_key_len = EVP_CIPHER_key_length(c);
4167c1d255d3SCy Schubert 	if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE ||
4168c1d255d3SCy Schubert 	    EVP_CIPHER_mode(c) == EVP_CIPH_CCM_MODE)
4169c1d255d3SCy Schubert 		fixed_iv_len = 4; /* only part of IV from PRF */
4170c1d255d3SCy Schubert 	else
4171c1d255d3SCy Schubert 		fixed_iv_len = EVP_CIPHER_iv_length(c);
4172c1d255d3SCy Schubert 	if (digest == NID_undef) {
4173c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "OpenSSL: no digest in use (e.g., AEAD)");
4174c1d255d3SCy Schubert 		mac_key_len = 0;
4175c1d255d3SCy Schubert 	} else {
4176c1d255d3SCy Schubert 		h = EVP_get_digestbynid(digest);
4177c1d255d3SCy Schubert 		if (!h)
4178c1d255d3SCy Schubert 			return -1;
4179c1d255d3SCy Schubert 		mac_key_len = EVP_MD_size(h);
4180c1d255d3SCy Schubert 	}
4181325151a3SRui Paulo 
4182325151a3SRui Paulo 	wpa_printf(MSG_DEBUG,
4183c1d255d3SCy Schubert 		   "OpenSSL: keyblock size: mac_key_len=%d enc_key_len=%d fixed_iv_len=%d",
4184c1d255d3SCy Schubert 		   mac_key_len, enc_key_len, fixed_iv_len);
4185c1d255d3SCy Schubert 	return 2 * (mac_key_len + enc_key_len + fixed_iv_len);
4186325151a3SRui Paulo #endif
4187325151a3SRui Paulo }
4188780fb4a2SCy Schubert #endif /* OPENSSL_NEED_EAP_FAST_PRF */
4189325151a3SRui Paulo 
4190325151a3SRui Paulo 
tls_connection_export_key(void * tls_ctx,struct tls_connection * conn,const char * label,const u8 * context,size_t context_len,u8 * out,size_t out_len)4191780fb4a2SCy Schubert int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
41924bc52338SCy Schubert 			      const char *label, const u8 *context,
41934bc52338SCy Schubert 			      size_t context_len, u8 *out, size_t out_len)
419439beb93cSSam Leffler {
4195780fb4a2SCy Schubert 	if (!conn ||
4196780fb4a2SCy Schubert 	    SSL_export_keying_material(conn->ssl, out, out_len, label,
41974bc52338SCy Schubert 				       os_strlen(label), context, context_len,
41984bc52338SCy Schubert 				       context != NULL) != 1)
4199f05cddf9SRui Paulo 		return -1;
4200780fb4a2SCy Schubert 	return 0;
4201325151a3SRui Paulo }
4202325151a3SRui Paulo 
4203325151a3SRui Paulo 
tls_connection_get_eap_fast_key(void * tls_ctx,struct tls_connection * conn,u8 * out,size_t out_len)4204780fb4a2SCy Schubert int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
4205780fb4a2SCy Schubert 				    u8 *out, size_t out_len)
4206780fb4a2SCy Schubert {
4207780fb4a2SCy Schubert #ifdef OPENSSL_NEED_EAP_FAST_PRF
4208325151a3SRui Paulo 	SSL *ssl;
4209325151a3SRui Paulo 	SSL_SESSION *sess;
4210325151a3SRui Paulo 	u8 *rnd;
4211325151a3SRui Paulo 	int ret = -1;
4212325151a3SRui Paulo 	int skip = 0;
4213325151a3SRui Paulo 	u8 *tmp_out = NULL;
4214325151a3SRui Paulo 	u8 *_out = out;
4215325151a3SRui Paulo 	unsigned char client_random[SSL3_RANDOM_SIZE];
4216325151a3SRui Paulo 	unsigned char server_random[SSL3_RANDOM_SIZE];
4217325151a3SRui Paulo 	unsigned char master_key[64];
4218325151a3SRui Paulo 	size_t master_key_len;
4219325151a3SRui Paulo 	const char *ver;
4220325151a3SRui Paulo 
4221325151a3SRui Paulo 	/*
4222780fb4a2SCy Schubert 	 * TLS library did not support EAP-FAST key generation, so get the
4223780fb4a2SCy Schubert 	 * needed TLS session parameters and use an internal implementation of
4224780fb4a2SCy Schubert 	 * TLS PRF to derive the key.
4225325151a3SRui Paulo 	 */
4226325151a3SRui Paulo 
4227325151a3SRui Paulo 	if (conn == NULL)
4228325151a3SRui Paulo 		return -1;
4229325151a3SRui Paulo 	ssl = conn->ssl;
4230325151a3SRui Paulo 	if (ssl == NULL)
4231325151a3SRui Paulo 		return -1;
4232325151a3SRui Paulo 	ver = SSL_get_version(ssl);
4233325151a3SRui Paulo 	sess = SSL_get_session(ssl);
4234325151a3SRui Paulo 	if (!ver || !sess)
423539beb93cSSam Leffler 		return -1;
423639beb93cSSam Leffler 
4237325151a3SRui Paulo 	skip = openssl_get_keyblock_size(ssl);
4238325151a3SRui Paulo 	if (skip < 0)
4239325151a3SRui Paulo 		return -1;
4240325151a3SRui Paulo 	tmp_out = os_malloc(skip + out_len);
4241325151a3SRui Paulo 	if (!tmp_out)
4242325151a3SRui Paulo 		return -1;
4243325151a3SRui Paulo 	_out = tmp_out;
424439beb93cSSam Leffler 
4245325151a3SRui Paulo 	rnd = os_malloc(2 * SSL3_RANDOM_SIZE);
4246325151a3SRui Paulo 	if (!rnd) {
4247325151a3SRui Paulo 		os_free(tmp_out);
4248325151a3SRui Paulo 		return -1;
4249325151a3SRui Paulo 	}
4250325151a3SRui Paulo 
4251325151a3SRui Paulo 	SSL_get_client_random(ssl, client_random, sizeof(client_random));
4252325151a3SRui Paulo 	SSL_get_server_random(ssl, server_random, sizeof(server_random));
4253325151a3SRui Paulo 	master_key_len = SSL_SESSION_get_master_key(sess, master_key,
4254325151a3SRui Paulo 						    sizeof(master_key));
4255325151a3SRui Paulo 
4256325151a3SRui Paulo 	os_memcpy(rnd, server_random, SSL3_RANDOM_SIZE);
4257780fb4a2SCy Schubert 	os_memcpy(rnd + SSL3_RANDOM_SIZE, client_random, SSL3_RANDOM_SIZE);
4258325151a3SRui Paulo 
4259325151a3SRui Paulo 	if (os_strcmp(ver, "TLSv1.2") == 0) {
4260325151a3SRui Paulo 		tls_prf_sha256(master_key, master_key_len,
4261780fb4a2SCy Schubert 			       "key expansion", rnd, 2 * SSL3_RANDOM_SIZE,
4262325151a3SRui Paulo 			       _out, skip + out_len);
4263325151a3SRui Paulo 		ret = 0;
4264325151a3SRui Paulo 	} else if (tls_prf_sha1_md5(master_key, master_key_len,
4265780fb4a2SCy Schubert 				    "key expansion", rnd, 2 * SSL3_RANDOM_SIZE,
4266325151a3SRui Paulo 				    _out, skip + out_len) == 0) {
4267325151a3SRui Paulo 		ret = 0;
4268325151a3SRui Paulo 	}
4269206b73d0SCy Schubert 	forced_memzero(master_key, sizeof(master_key));
4270325151a3SRui Paulo 	os_free(rnd);
4271780fb4a2SCy Schubert 	if (ret == 0)
4272325151a3SRui Paulo 		os_memcpy(out, _out + skip, out_len);
4273325151a3SRui Paulo 	bin_clear_free(tmp_out, skip);
4274325151a3SRui Paulo 
4275325151a3SRui Paulo 	return ret;
4276780fb4a2SCy Schubert #else /* OPENSSL_NEED_EAP_FAST_PRF */
4277780fb4a2SCy Schubert 	wpa_printf(MSG_ERROR,
4278780fb4a2SCy Schubert 		   "OpenSSL: EAP-FAST keys cannot be exported in FIPS mode");
4279f05cddf9SRui Paulo 	return -1;
4280780fb4a2SCy Schubert #endif /* OPENSSL_NEED_EAP_FAST_PRF */
428139beb93cSSam Leffler }
428239beb93cSSam Leffler 
428339beb93cSSam Leffler 
4284e28a4053SRui Paulo static struct wpabuf *
openssl_handshake(struct tls_connection * conn,const struct wpabuf * in_data)428585732ac8SCy Schubert openssl_handshake(struct tls_connection *conn, const struct wpabuf *in_data)
428639beb93cSSam Leffler {
428739beb93cSSam Leffler 	int res;
4288e28a4053SRui Paulo 	struct wpabuf *out_data;
428939beb93cSSam Leffler 
429039beb93cSSam Leffler 	/*
429139beb93cSSam Leffler 	 * Give TLS handshake data from the server (if available) to OpenSSL
429239beb93cSSam Leffler 	 * for processing.
429339beb93cSSam Leffler 	 */
4294325151a3SRui Paulo 	if (in_data && wpabuf_len(in_data) > 0 &&
4295e28a4053SRui Paulo 	    BIO_write(conn->ssl_in, wpabuf_head(in_data), wpabuf_len(in_data))
4296e28a4053SRui Paulo 	    < 0) {
429739beb93cSSam Leffler 		tls_show_errors(MSG_INFO, __func__,
429839beb93cSSam Leffler 				"Handshake failed - BIO_write");
429939beb93cSSam Leffler 		return NULL;
430039beb93cSSam Leffler 	}
430139beb93cSSam Leffler 
430239beb93cSSam Leffler 	/* Initiate TLS handshake or continue the existing handshake */
430385732ac8SCy Schubert 	if (conn->server)
4304e28a4053SRui Paulo 		res = SSL_accept(conn->ssl);
4305e28a4053SRui Paulo 	else
430639beb93cSSam Leffler 		res = SSL_connect(conn->ssl);
430739beb93cSSam Leffler 	if (res != 1) {
430839beb93cSSam Leffler 		int err = SSL_get_error(conn->ssl, res);
430939beb93cSSam Leffler 		if (err == SSL_ERROR_WANT_READ)
431039beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want "
431139beb93cSSam Leffler 				   "more data");
431239beb93cSSam Leffler 		else if (err == SSL_ERROR_WANT_WRITE)
431339beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want to "
431439beb93cSSam Leffler 				   "write");
431539beb93cSSam Leffler 		else {
431639beb93cSSam Leffler 			tls_show_errors(MSG_INFO, __func__, "SSL_connect");
431739beb93cSSam Leffler 			conn->failed++;
431885732ac8SCy Schubert 			if (!conn->server && !conn->client_hello_generated) {
431985732ac8SCy Schubert 				/* The server would not understand TLS Alert
432085732ac8SCy Schubert 				 * before ClientHello, so simply terminate
432185732ac8SCy Schubert 				 * handshake on this type of error case caused
432285732ac8SCy Schubert 				 * by a likely internal error like no ciphers
432385732ac8SCy Schubert 				 * available. */
432485732ac8SCy Schubert 				wpa_printf(MSG_DEBUG,
432585732ac8SCy Schubert 					   "OpenSSL: Could not generate ClientHello");
432685732ac8SCy Schubert 				conn->write_alerts++;
432785732ac8SCy Schubert 				return NULL;
432839beb93cSSam Leffler 			}
432939beb93cSSam Leffler 		}
433085732ac8SCy Schubert 	}
433185732ac8SCy Schubert 
433285732ac8SCy Schubert 	if (!conn->server && !conn->failed)
433385732ac8SCy Schubert 		conn->client_hello_generated = 1;
433485732ac8SCy Schubert 
433585732ac8SCy Schubert #ifdef CONFIG_SUITEB
433685732ac8SCy Schubert 	if ((conn->flags & TLS_CONN_SUITEB) && !conn->server &&
433785732ac8SCy Schubert 	    os_strncmp(SSL_get_cipher(conn->ssl), "DHE-", 4) == 0 &&
433885732ac8SCy Schubert 	    conn->server_dh_prime_len < 3072) {
433985732ac8SCy Schubert 		struct tls_context *context = conn->context;
434085732ac8SCy Schubert 
434185732ac8SCy Schubert 		/*
434285732ac8SCy Schubert 		 * This should not be reached since earlier cert_cb should have
434385732ac8SCy Schubert 		 * terminated the handshake. Keep this check here for extra
434485732ac8SCy Schubert 		 * protection if anything goes wrong with the more low-level
434585732ac8SCy Schubert 		 * checks based on having to parse the TLS handshake messages.
434685732ac8SCy Schubert 		 */
434785732ac8SCy Schubert 		wpa_printf(MSG_DEBUG,
434885732ac8SCy Schubert 			   "OpenSSL: Server DH prime length: %d bits",
434985732ac8SCy Schubert 			   conn->server_dh_prime_len);
435085732ac8SCy Schubert 
435185732ac8SCy Schubert 		if (context->event_cb) {
435285732ac8SCy Schubert 			union tls_event_data ev;
435385732ac8SCy Schubert 
435485732ac8SCy Schubert 			os_memset(&ev, 0, sizeof(ev));
435585732ac8SCy Schubert 			ev.alert.is_local = 1;
435685732ac8SCy Schubert 			ev.alert.type = "fatal";
435785732ac8SCy Schubert 			ev.alert.description = "insufficient security";
435885732ac8SCy Schubert 			context->event_cb(context->cb_ctx, TLS_ALERT, &ev);
435985732ac8SCy Schubert 		}
436085732ac8SCy Schubert 		/*
436185732ac8SCy Schubert 		 * Could send a TLS Alert to the server, but for now, simply
436285732ac8SCy Schubert 		 * terminate handshake.
436385732ac8SCy Schubert 		 */
436485732ac8SCy Schubert 		conn->failed++;
436585732ac8SCy Schubert 		conn->write_alerts++;
436685732ac8SCy Schubert 		return NULL;
436785732ac8SCy Schubert 	}
436885732ac8SCy Schubert #endif /* CONFIG_SUITEB */
436939beb93cSSam Leffler 
437039beb93cSSam Leffler 	/* Get the TLS handshake data to be sent to the server */
437139beb93cSSam Leffler 	res = BIO_ctrl_pending(conn->ssl_out);
437239beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res);
4373e28a4053SRui Paulo 	out_data = wpabuf_alloc(res);
437439beb93cSSam Leffler 	if (out_data == NULL) {
437539beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for "
437639beb93cSSam Leffler 			   "handshake output (%d bytes)", res);
437739beb93cSSam Leffler 		if (BIO_reset(conn->ssl_out) < 0) {
437839beb93cSSam Leffler 			tls_show_errors(MSG_INFO, __func__,
437939beb93cSSam Leffler 					"BIO_reset failed");
438039beb93cSSam Leffler 		}
438139beb93cSSam Leffler 		return NULL;
438239beb93cSSam Leffler 	}
4383e28a4053SRui Paulo 	res = res == 0 ? 0 : BIO_read(conn->ssl_out, wpabuf_mhead(out_data),
4384e28a4053SRui Paulo 				      res);
438539beb93cSSam Leffler 	if (res < 0) {
438639beb93cSSam Leffler 		tls_show_errors(MSG_INFO, __func__,
438739beb93cSSam Leffler 				"Handshake failed - BIO_read");
438839beb93cSSam Leffler 		if (BIO_reset(conn->ssl_out) < 0) {
438939beb93cSSam Leffler 			tls_show_errors(MSG_INFO, __func__,
439039beb93cSSam Leffler 					"BIO_reset failed");
439139beb93cSSam Leffler 		}
4392e28a4053SRui Paulo 		wpabuf_free(out_data);
439339beb93cSSam Leffler 		return NULL;
439439beb93cSSam Leffler 	}
4395e28a4053SRui Paulo 	wpabuf_put(out_data, res);
439639beb93cSSam Leffler 
4397e28a4053SRui Paulo 	return out_data;
4398e28a4053SRui Paulo }
4399e28a4053SRui Paulo 
4400e28a4053SRui Paulo 
4401e28a4053SRui Paulo static struct wpabuf *
openssl_get_appl_data(struct tls_connection * conn,size_t max_len)4402e28a4053SRui Paulo openssl_get_appl_data(struct tls_connection *conn, size_t max_len)
4403e28a4053SRui Paulo {
4404e28a4053SRui Paulo 	struct wpabuf *appl_data;
4405e28a4053SRui Paulo 	int res;
4406e28a4053SRui Paulo 
4407e28a4053SRui Paulo 	appl_data = wpabuf_alloc(max_len + 100);
4408e28a4053SRui Paulo 	if (appl_data == NULL)
4409e28a4053SRui Paulo 		return NULL;
4410e28a4053SRui Paulo 
4411e28a4053SRui Paulo 	res = SSL_read(conn->ssl, wpabuf_mhead(appl_data),
4412e28a4053SRui Paulo 		       wpabuf_size(appl_data));
441339beb93cSSam Leffler 	if (res < 0) {
44143157ba21SRui Paulo 		int err = SSL_get_error(conn->ssl, res);
44153157ba21SRui Paulo 		if (err == SSL_ERROR_WANT_READ ||
44163157ba21SRui Paulo 		    err == SSL_ERROR_WANT_WRITE) {
4417e28a4053SRui Paulo 			wpa_printf(MSG_DEBUG, "SSL: No Application Data "
44183157ba21SRui Paulo 				   "included");
44193157ba21SRui Paulo 		} else {
442039beb93cSSam Leffler 			tls_show_errors(MSG_INFO, __func__,
4421e28a4053SRui Paulo 					"Failed to read possible "
442239beb93cSSam Leffler 					"Application Data");
44233157ba21SRui Paulo 		}
4424e28a4053SRui Paulo 		wpabuf_free(appl_data);
4425e28a4053SRui Paulo 		return NULL;
4426e28a4053SRui Paulo 	}
4427e28a4053SRui Paulo 
4428e28a4053SRui Paulo 	wpabuf_put(appl_data, res);
4429e28a4053SRui Paulo 	wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application Data in Finished "
4430e28a4053SRui Paulo 			    "message", appl_data);
4431e28a4053SRui Paulo 
4432e28a4053SRui Paulo 	return appl_data;
4433e28a4053SRui Paulo }
4434e28a4053SRui Paulo 
4435e28a4053SRui Paulo 
4436e28a4053SRui Paulo static struct wpabuf *
openssl_connection_handshake(struct tls_connection * conn,const struct wpabuf * in_data,struct wpabuf ** appl_data)4437e28a4053SRui Paulo openssl_connection_handshake(struct tls_connection *conn,
4438e28a4053SRui Paulo 			     const struct wpabuf *in_data,
443985732ac8SCy Schubert 			     struct wpabuf **appl_data)
4440e28a4053SRui Paulo {
4441e28a4053SRui Paulo 	struct wpabuf *out_data;
4442e28a4053SRui Paulo 
4443e28a4053SRui Paulo 	if (appl_data)
444439beb93cSSam Leffler 		*appl_data = NULL;
4445e28a4053SRui Paulo 
444685732ac8SCy Schubert 	out_data = openssl_handshake(conn, in_data);
4447e28a4053SRui Paulo 	if (out_data == NULL)
4448e28a4053SRui Paulo 		return NULL;
44495b9c547cSRui Paulo 	if (conn->invalid_hb_used) {
44505b9c547cSRui Paulo 		wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response");
44515b9c547cSRui Paulo 		wpabuf_free(out_data);
44525b9c547cSRui Paulo 		return NULL;
44535b9c547cSRui Paulo 	}
4454e28a4053SRui Paulo 
4455325151a3SRui Paulo 	if (SSL_is_init_finished(conn->ssl)) {
4456325151a3SRui Paulo 		wpa_printf(MSG_DEBUG,
4457325151a3SRui Paulo 			   "OpenSSL: Handshake finished - resumed=%d",
4458325151a3SRui Paulo 			   tls_connection_resumed(conn->ssl_ctx, conn));
4459206b73d0SCy Schubert 		if (conn->server) {
4460206b73d0SCy Schubert 			char *buf;
4461206b73d0SCy Schubert 			size_t buflen = 2000;
4462206b73d0SCy Schubert 
4463206b73d0SCy Schubert 			buf = os_malloc(buflen);
4464206b73d0SCy Schubert 			if (buf) {
4465206b73d0SCy Schubert 				if (SSL_get_shared_ciphers(conn->ssl, buf,
4466206b73d0SCy Schubert 							   buflen)) {
4467206b73d0SCy Schubert 					buf[buflen - 1] = '\0';
4468206b73d0SCy Schubert 					wpa_printf(MSG_DEBUG,
4469206b73d0SCy Schubert 						   "OpenSSL: Shared ciphers: %s",
4470206b73d0SCy Schubert 						   buf);
4471206b73d0SCy Schubert 				}
4472206b73d0SCy Schubert 				os_free(buf);
4473206b73d0SCy Schubert 			}
4474206b73d0SCy Schubert 		}
4475325151a3SRui Paulo 		if (appl_data && in_data)
4476325151a3SRui Paulo 			*appl_data = openssl_get_appl_data(conn,
4477325151a3SRui Paulo 							   wpabuf_len(in_data));
4478325151a3SRui Paulo 	}
447939beb93cSSam Leffler 
44805b9c547cSRui Paulo 	if (conn->invalid_hb_used) {
44815b9c547cSRui Paulo 		wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response");
44825b9c547cSRui Paulo 		if (appl_data) {
44835b9c547cSRui Paulo 			wpabuf_free(*appl_data);
44845b9c547cSRui Paulo 			*appl_data = NULL;
44855b9c547cSRui Paulo 		}
44865b9c547cSRui Paulo 		wpabuf_free(out_data);
44875b9c547cSRui Paulo 		return NULL;
44885b9c547cSRui Paulo 	}
44895b9c547cSRui Paulo 
449039beb93cSSam Leffler 	return out_data;
449139beb93cSSam Leffler }
449239beb93cSSam Leffler 
449339beb93cSSam Leffler 
4494e28a4053SRui Paulo struct wpabuf *
tls_connection_handshake(void * ssl_ctx,struct tls_connection * conn,const struct wpabuf * in_data,struct wpabuf ** appl_data)4495e28a4053SRui Paulo tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
4496e28a4053SRui Paulo 			 const struct wpabuf *in_data,
4497e28a4053SRui Paulo 			 struct wpabuf **appl_data)
4498e28a4053SRui Paulo {
449985732ac8SCy Schubert 	return openssl_connection_handshake(conn, in_data, appl_data);
4500e28a4053SRui Paulo }
4501e28a4053SRui Paulo 
4502e28a4053SRui Paulo 
tls_connection_server_handshake(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data,struct wpabuf ** appl_data)4503e28a4053SRui Paulo struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
450439beb93cSSam Leffler 						struct tls_connection *conn,
4505e28a4053SRui Paulo 						const struct wpabuf *in_data,
4506e28a4053SRui Paulo 						struct wpabuf **appl_data)
4507e28a4053SRui Paulo {
450885732ac8SCy Schubert 	conn->server = 1;
450985732ac8SCy Schubert 	return openssl_connection_handshake(conn, in_data, appl_data);
4510e28a4053SRui Paulo }
4511e28a4053SRui Paulo 
4512e28a4053SRui Paulo 
tls_connection_encrypt(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data)4513e28a4053SRui Paulo struct wpabuf * tls_connection_encrypt(void *tls_ctx,
4514e28a4053SRui Paulo 				       struct tls_connection *conn,
4515e28a4053SRui Paulo 				       const struct wpabuf *in_data)
451639beb93cSSam Leffler {
451739beb93cSSam Leffler 	int res;
4518e28a4053SRui Paulo 	struct wpabuf *buf;
451939beb93cSSam Leffler 
452039beb93cSSam Leffler 	if (conn == NULL)
4521e28a4053SRui Paulo 		return NULL;
452239beb93cSSam Leffler 
452339beb93cSSam Leffler 	/* Give plaintext data for OpenSSL to encrypt into the TLS tunnel. */
452439beb93cSSam Leffler 	if ((res = BIO_reset(conn->ssl_in)) < 0 ||
452539beb93cSSam Leffler 	    (res = BIO_reset(conn->ssl_out)) < 0) {
452639beb93cSSam Leffler 		tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
4527e28a4053SRui Paulo 		return NULL;
452839beb93cSSam Leffler 	}
4529e28a4053SRui Paulo 	res = SSL_write(conn->ssl, wpabuf_head(in_data), wpabuf_len(in_data));
453039beb93cSSam Leffler 	if (res < 0) {
453139beb93cSSam Leffler 		tls_show_errors(MSG_INFO, __func__,
453239beb93cSSam Leffler 				"Encryption failed - SSL_write");
4533e28a4053SRui Paulo 		return NULL;
453439beb93cSSam Leffler 	}
453539beb93cSSam Leffler 
453639beb93cSSam Leffler 	/* Read encrypted data to be sent to the server */
4537e28a4053SRui Paulo 	buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
4538e28a4053SRui Paulo 	if (buf == NULL)
4539e28a4053SRui Paulo 		return NULL;
4540e28a4053SRui Paulo 	res = BIO_read(conn->ssl_out, wpabuf_mhead(buf), wpabuf_size(buf));
454139beb93cSSam Leffler 	if (res < 0) {
454239beb93cSSam Leffler 		tls_show_errors(MSG_INFO, __func__,
454339beb93cSSam Leffler 				"Encryption failed - BIO_read");
4544e28a4053SRui Paulo 		wpabuf_free(buf);
4545e28a4053SRui Paulo 		return NULL;
454639beb93cSSam Leffler 	}
4547e28a4053SRui Paulo 	wpabuf_put(buf, res);
454839beb93cSSam Leffler 
4549e28a4053SRui Paulo 	return buf;
455039beb93cSSam Leffler }
455139beb93cSSam Leffler 
455239beb93cSSam Leffler 
tls_connection_decrypt(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data)4553e28a4053SRui Paulo struct wpabuf * tls_connection_decrypt(void *tls_ctx,
4554e28a4053SRui Paulo 				       struct tls_connection *conn,
4555e28a4053SRui Paulo 				       const struct wpabuf *in_data)
455639beb93cSSam Leffler {
455739beb93cSSam Leffler 	int res;
4558e28a4053SRui Paulo 	struct wpabuf *buf;
455939beb93cSSam Leffler 
456039beb93cSSam Leffler 	/* Give encrypted data from TLS tunnel for OpenSSL to decrypt. */
4561e28a4053SRui Paulo 	res = BIO_write(conn->ssl_in, wpabuf_head(in_data),
4562e28a4053SRui Paulo 			wpabuf_len(in_data));
456339beb93cSSam Leffler 	if (res < 0) {
456439beb93cSSam Leffler 		tls_show_errors(MSG_INFO, __func__,
456539beb93cSSam Leffler 				"Decryption failed - BIO_write");
4566e28a4053SRui Paulo 		return NULL;
456739beb93cSSam Leffler 	}
456839beb93cSSam Leffler 	if (BIO_reset(conn->ssl_out) < 0) {
456939beb93cSSam Leffler 		tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
4570e28a4053SRui Paulo 		return NULL;
457139beb93cSSam Leffler 	}
457239beb93cSSam Leffler 
457339beb93cSSam Leffler 	/* Read decrypted data for further processing */
4574e28a4053SRui Paulo 	/*
4575e28a4053SRui Paulo 	 * Even though we try to disable TLS compression, it is possible that
4576e28a4053SRui Paulo 	 * this cannot be done with all TLS libraries. Add extra buffer space
4577e28a4053SRui Paulo 	 * to handle the possibility of the decrypted data being longer than
4578e28a4053SRui Paulo 	 * input data.
4579e28a4053SRui Paulo 	 */
4580e28a4053SRui Paulo 	buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
4581e28a4053SRui Paulo 	if (buf == NULL)
4582e28a4053SRui Paulo 		return NULL;
4583e28a4053SRui Paulo 	res = SSL_read(conn->ssl, wpabuf_mhead(buf), wpabuf_size(buf));
458439beb93cSSam Leffler 	if (res < 0) {
4585c1d255d3SCy Schubert 		int err = SSL_get_error(conn->ssl, res);
4586c1d255d3SCy Schubert 
4587c1d255d3SCy Schubert 		if (err == SSL_ERROR_WANT_READ) {
4588c1d255d3SCy Schubert 			wpa_printf(MSG_DEBUG,
4589c1d255d3SCy Schubert 				   "SSL: SSL_connect - want more data");
4590c1d255d3SCy Schubert 			res = 0;
4591c1d255d3SCy Schubert 		} else {
459239beb93cSSam Leffler 			tls_show_errors(MSG_INFO, __func__,
459339beb93cSSam Leffler 					"Decryption failed - SSL_read");
4594e28a4053SRui Paulo 			wpabuf_free(buf);
4595e28a4053SRui Paulo 			return NULL;
459639beb93cSSam Leffler 		}
4597c1d255d3SCy Schubert 	}
4598e28a4053SRui Paulo 	wpabuf_put(buf, res);
459939beb93cSSam Leffler 
46005b9c547cSRui Paulo 	if (conn->invalid_hb_used) {
46015b9c547cSRui Paulo 		wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response");
46025b9c547cSRui Paulo 		wpabuf_free(buf);
46035b9c547cSRui Paulo 		return NULL;
46045b9c547cSRui Paulo 	}
46055b9c547cSRui Paulo 
4606e28a4053SRui Paulo 	return buf;
460739beb93cSSam Leffler }
460839beb93cSSam Leffler 
460939beb93cSSam Leffler 
tls_connection_resumed(void * ssl_ctx,struct tls_connection * conn)461039beb93cSSam Leffler int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
461139beb93cSSam Leffler {
461285732ac8SCy Schubert 	return conn ? SSL_session_reused(conn->ssl) : 0;
461339beb93cSSam Leffler }
461439beb93cSSam Leffler 
461539beb93cSSam Leffler 
tls_connection_set_cipher_list(void * tls_ctx,struct tls_connection * conn,u8 * ciphers)461639beb93cSSam Leffler int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
461739beb93cSSam Leffler 				   u8 *ciphers)
461839beb93cSSam Leffler {
4619780fb4a2SCy Schubert 	char buf[500], *pos, *end;
462039beb93cSSam Leffler 	u8 *c;
462139beb93cSSam Leffler 	int ret;
462239beb93cSSam Leffler 
462339beb93cSSam Leffler 	if (conn == NULL || conn->ssl == NULL || ciphers == NULL)
462439beb93cSSam Leffler 		return -1;
462539beb93cSSam Leffler 
462639beb93cSSam Leffler 	buf[0] = '\0';
462739beb93cSSam Leffler 	pos = buf;
462839beb93cSSam Leffler 	end = pos + sizeof(buf);
462939beb93cSSam Leffler 
463039beb93cSSam Leffler 	c = ciphers;
463139beb93cSSam Leffler 	while (*c != TLS_CIPHER_NONE) {
463239beb93cSSam Leffler 		const char *suite;
463339beb93cSSam Leffler 
463439beb93cSSam Leffler 		switch (*c) {
463539beb93cSSam Leffler 		case TLS_CIPHER_RC4_SHA:
463639beb93cSSam Leffler 			suite = "RC4-SHA";
463739beb93cSSam Leffler 			break;
463839beb93cSSam Leffler 		case TLS_CIPHER_AES128_SHA:
463939beb93cSSam Leffler 			suite = "AES128-SHA";
464039beb93cSSam Leffler 			break;
464139beb93cSSam Leffler 		case TLS_CIPHER_RSA_DHE_AES128_SHA:
464239beb93cSSam Leffler 			suite = "DHE-RSA-AES128-SHA";
464339beb93cSSam Leffler 			break;
464439beb93cSSam Leffler 		case TLS_CIPHER_ANON_DH_AES128_SHA:
464539beb93cSSam Leffler 			suite = "ADH-AES128-SHA";
464639beb93cSSam Leffler 			break;
4647780fb4a2SCy Schubert 		case TLS_CIPHER_RSA_DHE_AES256_SHA:
4648780fb4a2SCy Schubert 			suite = "DHE-RSA-AES256-SHA";
4649780fb4a2SCy Schubert 			break;
4650780fb4a2SCy Schubert 		case TLS_CIPHER_AES256_SHA:
4651780fb4a2SCy Schubert 			suite = "AES256-SHA";
4652780fb4a2SCy Schubert 			break;
465339beb93cSSam Leffler 		default:
465439beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLS: Unsupported "
465539beb93cSSam Leffler 				   "cipher selection: %d", *c);
465639beb93cSSam Leffler 			return -1;
465739beb93cSSam Leffler 		}
465839beb93cSSam Leffler 		ret = os_snprintf(pos, end - pos, ":%s", suite);
46595b9c547cSRui Paulo 		if (os_snprintf_error(end - pos, ret))
466039beb93cSSam Leffler 			break;
466139beb93cSSam Leffler 		pos += ret;
466239beb93cSSam Leffler 
466339beb93cSSam Leffler 		c++;
466439beb93cSSam Leffler 	}
4665206b73d0SCy Schubert 	if (!buf[0]) {
4666206b73d0SCy Schubert 		wpa_printf(MSG_DEBUG, "OpenSSL: No ciphers listed");
4667206b73d0SCy Schubert 		return -1;
4668206b73d0SCy Schubert 	}
466939beb93cSSam Leffler 
467039beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "OpenSSL: cipher suites: %s", buf + 1);
467139beb93cSSam Leffler 
4672780fb4a2SCy Schubert #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
4673206b73d0SCy Schubert #ifdef EAP_FAST_OR_TEAP
4674325151a3SRui Paulo 	if (os_strstr(buf, ":ADH-")) {
4675325151a3SRui Paulo 		/*
4676325151a3SRui Paulo 		 * Need to drop to security level 0 to allow anonymous
4677325151a3SRui Paulo 		 * cipher suites for EAP-FAST.
4678325151a3SRui Paulo 		 */
4679325151a3SRui Paulo 		SSL_set_security_level(conn->ssl, 0);
4680325151a3SRui Paulo 	} else if (SSL_get_security_level(conn->ssl) == 0) {
4681325151a3SRui Paulo 		/* Force at least security level 1 */
4682325151a3SRui Paulo 		SSL_set_security_level(conn->ssl, 1);
4683325151a3SRui Paulo 	}
4684206b73d0SCy Schubert #endif /* EAP_FAST_OR_TEAP */
4685325151a3SRui Paulo #endif
4686325151a3SRui Paulo 
468739beb93cSSam Leffler 	if (SSL_set_cipher_list(conn->ssl, buf + 1) != 1) {
468839beb93cSSam Leffler 		tls_show_errors(MSG_INFO, __func__,
468939beb93cSSam Leffler 				"Cipher suite configuration failed");
469039beb93cSSam Leffler 		return -1;
469139beb93cSSam Leffler 	}
469239beb93cSSam Leffler 
469339beb93cSSam Leffler 	return 0;
469439beb93cSSam Leffler }
469539beb93cSSam Leffler 
469639beb93cSSam Leffler 
tls_get_version(void * ssl_ctx,struct tls_connection * conn,char * buf,size_t buflen)4697325151a3SRui Paulo int tls_get_version(void *ssl_ctx, struct tls_connection *conn,
4698325151a3SRui Paulo 		    char *buf, size_t buflen)
4699325151a3SRui Paulo {
4700325151a3SRui Paulo 	const char *name;
4701325151a3SRui Paulo 	if (conn == NULL || conn->ssl == NULL)
4702325151a3SRui Paulo 		return -1;
4703325151a3SRui Paulo 
4704325151a3SRui Paulo 	name = SSL_get_version(conn->ssl);
4705325151a3SRui Paulo 	if (name == NULL)
4706325151a3SRui Paulo 		return -1;
4707325151a3SRui Paulo 
4708325151a3SRui Paulo 	os_strlcpy(buf, name, buflen);
4709325151a3SRui Paulo 	return 0;
4710325151a3SRui Paulo }
4711325151a3SRui Paulo 
4712325151a3SRui Paulo 
tls_get_cipher(void * ssl_ctx,struct tls_connection * conn,char * buf,size_t buflen)471339beb93cSSam Leffler int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
471439beb93cSSam Leffler 		   char *buf, size_t buflen)
471539beb93cSSam Leffler {
471639beb93cSSam Leffler 	const char *name;
471739beb93cSSam Leffler 	if (conn == NULL || conn->ssl == NULL)
471839beb93cSSam Leffler 		return -1;
471939beb93cSSam Leffler 
472039beb93cSSam Leffler 	name = SSL_get_cipher(conn->ssl);
472139beb93cSSam Leffler 	if (name == NULL)
472239beb93cSSam Leffler 		return -1;
472339beb93cSSam Leffler 
472439beb93cSSam Leffler 	os_strlcpy(buf, name, buflen);
472539beb93cSSam Leffler 	return 0;
472639beb93cSSam Leffler }
472739beb93cSSam Leffler 
472839beb93cSSam Leffler 
tls_connection_enable_workaround(void * ssl_ctx,struct tls_connection * conn)472939beb93cSSam Leffler int tls_connection_enable_workaround(void *ssl_ctx,
473039beb93cSSam Leffler 				     struct tls_connection *conn)
473139beb93cSSam Leffler {
473239beb93cSSam Leffler 	SSL_set_options(conn->ssl, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
473339beb93cSSam Leffler 
473439beb93cSSam Leffler 	return 0;
473539beb93cSSam Leffler }
473639beb93cSSam Leffler 
473739beb93cSSam Leffler 
4738206b73d0SCy Schubert #ifdef EAP_FAST_OR_TEAP
473939beb93cSSam Leffler /* ClientHello TLS extensions require a patch to openssl, so this function is
474039beb93cSSam Leffler  * commented out unless explicitly needed for EAP-FAST in order to be able to
474139beb93cSSam Leffler  * build this file with unmodified openssl. */
tls_connection_client_hello_ext(void * ssl_ctx,struct tls_connection * conn,int ext_type,const u8 * data,size_t data_len)474239beb93cSSam Leffler int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
474339beb93cSSam Leffler 				    int ext_type, const u8 *data,
474439beb93cSSam Leffler 				    size_t data_len)
474539beb93cSSam Leffler {
474639beb93cSSam Leffler 	if (conn == NULL || conn->ssl == NULL || ext_type != 35)
474739beb93cSSam Leffler 		return -1;
474839beb93cSSam Leffler 
474939beb93cSSam Leffler 	if (SSL_set_session_ticket_ext(conn->ssl, (void *) data,
475039beb93cSSam Leffler 				       data_len) != 1)
475139beb93cSSam Leffler 		return -1;
475239beb93cSSam Leffler 
475339beb93cSSam Leffler 	return 0;
475439beb93cSSam Leffler }
4755206b73d0SCy Schubert #endif /* EAP_FAST_OR_TEAP */
475639beb93cSSam Leffler 
475739beb93cSSam Leffler 
tls_connection_get_failed(void * ssl_ctx,struct tls_connection * conn)475839beb93cSSam Leffler int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
475939beb93cSSam Leffler {
476039beb93cSSam Leffler 	if (conn == NULL)
476139beb93cSSam Leffler 		return -1;
476239beb93cSSam Leffler 	return conn->failed;
476339beb93cSSam Leffler }
476439beb93cSSam Leffler 
476539beb93cSSam Leffler 
tls_connection_get_read_alerts(void * ssl_ctx,struct tls_connection * conn)476639beb93cSSam Leffler int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
476739beb93cSSam Leffler {
476839beb93cSSam Leffler 	if (conn == NULL)
476939beb93cSSam Leffler 		return -1;
477039beb93cSSam Leffler 	return conn->read_alerts;
477139beb93cSSam Leffler }
477239beb93cSSam Leffler 
477339beb93cSSam Leffler 
tls_connection_get_write_alerts(void * ssl_ctx,struct tls_connection * conn)477439beb93cSSam Leffler int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
477539beb93cSSam Leffler {
477639beb93cSSam Leffler 	if (conn == NULL)
477739beb93cSSam Leffler 		return -1;
477839beb93cSSam Leffler 	return conn->write_alerts;
477939beb93cSSam Leffler }
478039beb93cSSam Leffler 
478139beb93cSSam Leffler 
47825b9c547cSRui Paulo #ifdef HAVE_OCSP
47835b9c547cSRui Paulo 
ocsp_debug_print_resp(OCSP_RESPONSE * rsp)47845b9c547cSRui Paulo static void ocsp_debug_print_resp(OCSP_RESPONSE *rsp)
47855b9c547cSRui Paulo {
47865b9c547cSRui Paulo #ifndef CONFIG_NO_STDOUT_DEBUG
47875b9c547cSRui Paulo 	BIO *out;
47885b9c547cSRui Paulo 	size_t rlen;
47895b9c547cSRui Paulo 	char *txt;
47905b9c547cSRui Paulo 	int res;
47915b9c547cSRui Paulo 
47925b9c547cSRui Paulo 	if (wpa_debug_level > MSG_DEBUG)
47935b9c547cSRui Paulo 		return;
47945b9c547cSRui Paulo 
47955b9c547cSRui Paulo 	out = BIO_new(BIO_s_mem());
47965b9c547cSRui Paulo 	if (!out)
47975b9c547cSRui Paulo 		return;
47985b9c547cSRui Paulo 
47995b9c547cSRui Paulo 	OCSP_RESPONSE_print(out, rsp, 0);
48005b9c547cSRui Paulo 	rlen = BIO_ctrl_pending(out);
48015b9c547cSRui Paulo 	txt = os_malloc(rlen + 1);
48025b9c547cSRui Paulo 	if (!txt) {
48035b9c547cSRui Paulo 		BIO_free(out);
48045b9c547cSRui Paulo 		return;
48055b9c547cSRui Paulo 	}
48065b9c547cSRui Paulo 
48075b9c547cSRui Paulo 	res = BIO_read(out, txt, rlen);
48085b9c547cSRui Paulo 	if (res > 0) {
48095b9c547cSRui Paulo 		txt[res] = '\0';
48105b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP Response\n%s", txt);
48115b9c547cSRui Paulo 	}
48125b9c547cSRui Paulo 	os_free(txt);
48135b9c547cSRui Paulo 	BIO_free(out);
48145b9c547cSRui Paulo #endif /* CONFIG_NO_STDOUT_DEBUG */
48155b9c547cSRui Paulo }
48165b9c547cSRui Paulo 
48175b9c547cSRui Paulo 
ocsp_resp_cb(SSL * s,void * arg)48185b9c547cSRui Paulo static int ocsp_resp_cb(SSL *s, void *arg)
48195b9c547cSRui Paulo {
48205b9c547cSRui Paulo 	struct tls_connection *conn = arg;
48215b9c547cSRui Paulo 	const unsigned char *p;
482285732ac8SCy Schubert 	int len, status, reason, res;
48235b9c547cSRui Paulo 	OCSP_RESPONSE *rsp;
48245b9c547cSRui Paulo 	OCSP_BASICRESP *basic;
48255b9c547cSRui Paulo 	OCSP_CERTID *id;
48265b9c547cSRui Paulo 	ASN1_GENERALIZEDTIME *produced_at, *this_update, *next_update;
48275b9c547cSRui Paulo 	X509_STORE *store;
48285b9c547cSRui Paulo 	STACK_OF(X509) *certs = NULL;
48295b9c547cSRui Paulo 
48305b9c547cSRui Paulo 	len = SSL_get_tlsext_status_ocsp_resp(s, &p);
48315b9c547cSRui Paulo 	if (!p) {
48325b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "OpenSSL: No OCSP response received");
48335b9c547cSRui Paulo 		return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1;
48345b9c547cSRui Paulo 	}
48355b9c547cSRui Paulo 
48365b9c547cSRui Paulo 	wpa_hexdump(MSG_DEBUG, "OpenSSL: OCSP response", p, len);
48375b9c547cSRui Paulo 
48385b9c547cSRui Paulo 	rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
48395b9c547cSRui Paulo 	if (!rsp) {
48405b9c547cSRui Paulo 		wpa_printf(MSG_INFO, "OpenSSL: Failed to parse OCSP response");
48415b9c547cSRui Paulo 		return 0;
48425b9c547cSRui Paulo 	}
48435b9c547cSRui Paulo 
48445b9c547cSRui Paulo 	ocsp_debug_print_resp(rsp);
48455b9c547cSRui Paulo 
48465b9c547cSRui Paulo 	status = OCSP_response_status(rsp);
48475b9c547cSRui Paulo 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
48485b9c547cSRui Paulo 		wpa_printf(MSG_INFO, "OpenSSL: OCSP responder error %d (%s)",
48495b9c547cSRui Paulo 			   status, OCSP_response_status_str(status));
48505b9c547cSRui Paulo 		return 0;
48515b9c547cSRui Paulo 	}
48525b9c547cSRui Paulo 
48535b9c547cSRui Paulo 	basic = OCSP_response_get1_basic(rsp);
48545b9c547cSRui Paulo 	if (!basic) {
48555b9c547cSRui Paulo 		wpa_printf(MSG_INFO, "OpenSSL: Could not find BasicOCSPResponse");
48565b9c547cSRui Paulo 		return 0;
48575b9c547cSRui Paulo 	}
48585b9c547cSRui Paulo 
48595b9c547cSRui Paulo 	store = SSL_CTX_get_cert_store(conn->ssl_ctx);
48605b9c547cSRui Paulo 	if (conn->peer_issuer) {
48615b9c547cSRui Paulo 		debug_print_cert(conn->peer_issuer, "Add OCSP issuer");
48625b9c547cSRui Paulo 
48635b9c547cSRui Paulo 		if (X509_STORE_add_cert(store, conn->peer_issuer) != 1) {
48645b9c547cSRui Paulo 			tls_show_errors(MSG_INFO, __func__,
48655b9c547cSRui Paulo 					"OpenSSL: Could not add issuer to certificate store");
48665b9c547cSRui Paulo 		}
48675b9c547cSRui Paulo 		certs = sk_X509_new_null();
48685b9c547cSRui Paulo 		if (certs) {
48695b9c547cSRui Paulo 			X509 *cert;
48705b9c547cSRui Paulo 			cert = X509_dup(conn->peer_issuer);
48715b9c547cSRui Paulo 			if (cert && !sk_X509_push(certs, cert)) {
48725b9c547cSRui Paulo 				tls_show_errors(
48735b9c547cSRui Paulo 					MSG_INFO, __func__,
48745b9c547cSRui Paulo 					"OpenSSL: Could not add issuer to OCSP responder trust store");
48755b9c547cSRui Paulo 				X509_free(cert);
48765b9c547cSRui Paulo 				sk_X509_free(certs);
48775b9c547cSRui Paulo 				certs = NULL;
48785b9c547cSRui Paulo 			}
48795b9c547cSRui Paulo 			if (certs && conn->peer_issuer_issuer) {
48805b9c547cSRui Paulo 				cert = X509_dup(conn->peer_issuer_issuer);
48815b9c547cSRui Paulo 				if (cert && !sk_X509_push(certs, cert)) {
48825b9c547cSRui Paulo 					tls_show_errors(
48835b9c547cSRui Paulo 						MSG_INFO, __func__,
48845b9c547cSRui Paulo 						"OpenSSL: Could not add issuer's issuer to OCSP responder trust store");
48855b9c547cSRui Paulo 					X509_free(cert);
48865b9c547cSRui Paulo 				}
48875b9c547cSRui Paulo 			}
48885b9c547cSRui Paulo 		}
48895b9c547cSRui Paulo 	}
48905b9c547cSRui Paulo 
48915b9c547cSRui Paulo 	status = OCSP_basic_verify(basic, certs, store, OCSP_TRUSTOTHER);
48925b9c547cSRui Paulo 	sk_X509_pop_free(certs, X509_free);
48935b9c547cSRui Paulo 	if (status <= 0) {
48945b9c547cSRui Paulo 		tls_show_errors(MSG_INFO, __func__,
48955b9c547cSRui Paulo 				"OpenSSL: OCSP response failed verification");
48965b9c547cSRui Paulo 		OCSP_BASICRESP_free(basic);
48975b9c547cSRui Paulo 		OCSP_RESPONSE_free(rsp);
48985b9c547cSRui Paulo 		return 0;
48995b9c547cSRui Paulo 	}
49005b9c547cSRui Paulo 
49015b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP response verification succeeded");
49025b9c547cSRui Paulo 
49035b9c547cSRui Paulo 	if (!conn->peer_cert) {
49045b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "OpenSSL: Peer certificate not available for OCSP status check");
49055b9c547cSRui Paulo 		OCSP_BASICRESP_free(basic);
49065b9c547cSRui Paulo 		OCSP_RESPONSE_free(rsp);
49075b9c547cSRui Paulo 		return 0;
49085b9c547cSRui Paulo 	}
49095b9c547cSRui Paulo 
49105b9c547cSRui Paulo 	if (!conn->peer_issuer) {
49115b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "OpenSSL: Peer issuer certificate not available for OCSP status check");
49125b9c547cSRui Paulo 		OCSP_BASICRESP_free(basic);
49135b9c547cSRui Paulo 		OCSP_RESPONSE_free(rsp);
49145b9c547cSRui Paulo 		return 0;
49155b9c547cSRui Paulo 	}
49165b9c547cSRui Paulo 
491785732ac8SCy Schubert 	id = OCSP_cert_to_id(EVP_sha256(), conn->peer_cert, conn->peer_issuer);
49185b9c547cSRui Paulo 	if (!id) {
491985732ac8SCy Schubert 		wpa_printf(MSG_DEBUG,
492085732ac8SCy Schubert 			   "OpenSSL: Could not create OCSP certificate identifier (SHA256)");
49215b9c547cSRui Paulo 		OCSP_BASICRESP_free(basic);
49225b9c547cSRui Paulo 		OCSP_RESPONSE_free(rsp);
49235b9c547cSRui Paulo 		return 0;
49245b9c547cSRui Paulo 	}
49255b9c547cSRui Paulo 
492685732ac8SCy Schubert 	res = OCSP_resp_find_status(basic, id, &status, &reason, &produced_at,
492785732ac8SCy Schubert 				    &this_update, &next_update);
492885732ac8SCy Schubert 	if (!res) {
4929206b73d0SCy Schubert 		OCSP_CERTID_free(id);
493085732ac8SCy Schubert 		id = OCSP_cert_to_id(NULL, conn->peer_cert, conn->peer_issuer);
493185732ac8SCy Schubert 		if (!id) {
493285732ac8SCy Schubert 			wpa_printf(MSG_DEBUG,
493385732ac8SCy Schubert 				   "OpenSSL: Could not create OCSP certificate identifier (SHA1)");
493485732ac8SCy Schubert 			OCSP_BASICRESP_free(basic);
493585732ac8SCy Schubert 			OCSP_RESPONSE_free(rsp);
493685732ac8SCy Schubert 			return 0;
493785732ac8SCy Schubert 		}
493885732ac8SCy Schubert 
493985732ac8SCy Schubert 		res = OCSP_resp_find_status(basic, id, &status, &reason,
494085732ac8SCy Schubert 					    &produced_at, &this_update,
494185732ac8SCy Schubert 					    &next_update);
494285732ac8SCy Schubert 	}
494385732ac8SCy Schubert 
494485732ac8SCy Schubert 	if (!res) {
49455b9c547cSRui Paulo 		wpa_printf(MSG_INFO, "OpenSSL: Could not find current server certificate from OCSP response%s",
49465b9c547cSRui Paulo 			   (conn->flags & TLS_CONN_REQUIRE_OCSP) ? "" :
49475b9c547cSRui Paulo 			   " (OCSP not required)");
4948780fb4a2SCy Schubert 		OCSP_CERTID_free(id);
49495b9c547cSRui Paulo 		OCSP_BASICRESP_free(basic);
49505b9c547cSRui Paulo 		OCSP_RESPONSE_free(rsp);
49515b9c547cSRui Paulo 		return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1;
49525b9c547cSRui Paulo 	}
4953780fb4a2SCy Schubert 	OCSP_CERTID_free(id);
49545b9c547cSRui Paulo 
49555b9c547cSRui Paulo 	if (!OCSP_check_validity(this_update, next_update, 5 * 60, -1)) {
49565b9c547cSRui Paulo 		tls_show_errors(MSG_INFO, __func__,
49575b9c547cSRui Paulo 				"OpenSSL: OCSP status times invalid");
49585b9c547cSRui Paulo 		OCSP_BASICRESP_free(basic);
49595b9c547cSRui Paulo 		OCSP_RESPONSE_free(rsp);
49605b9c547cSRui Paulo 		return 0;
49615b9c547cSRui Paulo 	}
49625b9c547cSRui Paulo 
49635b9c547cSRui Paulo 	OCSP_BASICRESP_free(basic);
49645b9c547cSRui Paulo 	OCSP_RESPONSE_free(rsp);
49655b9c547cSRui Paulo 
49665b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status for server certificate: %s",
49675b9c547cSRui Paulo 		   OCSP_cert_status_str(status));
49685b9c547cSRui Paulo 
49695b9c547cSRui Paulo 	if (status == V_OCSP_CERTSTATUS_GOOD)
49705b9c547cSRui Paulo 		return 1;
49715b9c547cSRui Paulo 	if (status == V_OCSP_CERTSTATUS_REVOKED)
49725b9c547cSRui Paulo 		return 0;
49735b9c547cSRui Paulo 	if (conn->flags & TLS_CONN_REQUIRE_OCSP) {
49745b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP required");
49755b9c547cSRui Paulo 		return 0;
49765b9c547cSRui Paulo 	}
49775b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP was not required, so allow connection to continue");
49785b9c547cSRui Paulo 	return 1;
49795b9c547cSRui Paulo }
49805b9c547cSRui Paulo 
49815b9c547cSRui Paulo 
ocsp_status_cb(SSL * s,void * arg)49825b9c547cSRui Paulo static int ocsp_status_cb(SSL *s, void *arg)
49835b9c547cSRui Paulo {
49845b9c547cSRui Paulo 	char *tmp;
49855b9c547cSRui Paulo 	char *resp;
49865b9c547cSRui Paulo 	size_t len;
49875b9c547cSRui Paulo 
49885b9c547cSRui Paulo 	if (tls_global->ocsp_stapling_response == NULL) {
49895b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - no response configured");
49905b9c547cSRui Paulo 		return SSL_TLSEXT_ERR_OK;
49915b9c547cSRui Paulo 	}
49925b9c547cSRui Paulo 
49935b9c547cSRui Paulo 	resp = os_readfile(tls_global->ocsp_stapling_response, &len);
49945b9c547cSRui Paulo 	if (resp == NULL) {
49955b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - could not read response file");
49965b9c547cSRui Paulo 		/* TODO: Build OCSPResponse with responseStatus = internalError
49975b9c547cSRui Paulo 		 */
49985b9c547cSRui Paulo 		return SSL_TLSEXT_ERR_OK;
49995b9c547cSRui Paulo 	}
50005b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - send cached response");
50015b9c547cSRui Paulo 	tmp = OPENSSL_malloc(len);
50025b9c547cSRui Paulo 	if (tmp == NULL) {
50035b9c547cSRui Paulo 		os_free(resp);
50045b9c547cSRui Paulo 		return SSL_TLSEXT_ERR_ALERT_FATAL;
50055b9c547cSRui Paulo 	}
50065b9c547cSRui Paulo 
50075b9c547cSRui Paulo 	os_memcpy(tmp, resp, len);
50085b9c547cSRui Paulo 	os_free(resp);
50095b9c547cSRui Paulo 	SSL_set_tlsext_status_ocsp_resp(s, tmp, len);
50105b9c547cSRui Paulo 
50115b9c547cSRui Paulo 	return SSL_TLSEXT_ERR_OK;
50125b9c547cSRui Paulo }
50135b9c547cSRui Paulo 
50145b9c547cSRui Paulo #endif /* HAVE_OCSP */
50155b9c547cSRui Paulo 
50165b9c547cSRui Paulo 
max_str_len(const char ** lines)5017c1d255d3SCy Schubert static size_t max_str_len(const char **lines)
5018c1d255d3SCy Schubert {
5019c1d255d3SCy Schubert 	const char **p;
5020c1d255d3SCy Schubert 	size_t max_len = 0;
5021c1d255d3SCy Schubert 
5022c1d255d3SCy Schubert 	for (p = lines; *p; p++) {
5023c1d255d3SCy Schubert 		size_t len = os_strlen(*p);
5024c1d255d3SCy Schubert 
5025c1d255d3SCy Schubert 		if (len > max_len)
5026c1d255d3SCy Schubert 			max_len = len;
5027c1d255d3SCy Schubert 	}
5028c1d255d3SCy Schubert 
5029c1d255d3SCy Schubert 	return max_len;
5030c1d255d3SCy Schubert }
5031c1d255d3SCy Schubert 
5032c1d255d3SCy Schubert 
match_lines_in_file(const char * path,const char ** lines)5033c1d255d3SCy Schubert static int match_lines_in_file(const char *path, const char **lines)
5034c1d255d3SCy Schubert {
5035c1d255d3SCy Schubert 	FILE *f;
5036c1d255d3SCy Schubert 	char *buf;
5037c1d255d3SCy Schubert 	size_t bufsize;
5038c1d255d3SCy Schubert 	int found = 0, is_linestart = 1;
5039c1d255d3SCy Schubert 
5040c1d255d3SCy Schubert 	bufsize = max_str_len(lines) + sizeof("\r\n");
5041c1d255d3SCy Schubert 	buf = os_malloc(bufsize);
5042c1d255d3SCy Schubert 	if (!buf)
5043c1d255d3SCy Schubert 		return 0;
5044c1d255d3SCy Schubert 
5045c1d255d3SCy Schubert 	f = fopen(path, "r");
5046c1d255d3SCy Schubert 	if (!f) {
5047c1d255d3SCy Schubert 		os_free(buf);
5048c1d255d3SCy Schubert 		return 0;
5049c1d255d3SCy Schubert 	}
5050c1d255d3SCy Schubert 
5051c1d255d3SCy Schubert 	while (!found && fgets(buf, bufsize, f)) {
5052c1d255d3SCy Schubert 		int is_lineend;
5053c1d255d3SCy Schubert 		size_t len;
5054c1d255d3SCy Schubert 		const char **p;
5055c1d255d3SCy Schubert 
5056c1d255d3SCy Schubert 		len = strcspn(buf, "\r\n");
5057c1d255d3SCy Schubert 		is_lineend = buf[len] != '\0';
5058c1d255d3SCy Schubert 		buf[len] = '\0';
5059c1d255d3SCy Schubert 
5060c1d255d3SCy Schubert 		if (is_linestart && is_lineend) {
5061c1d255d3SCy Schubert 			for (p = lines; !found && *p; p++)
5062c1d255d3SCy Schubert 				found = os_strcmp(buf, *p) == 0;
5063c1d255d3SCy Schubert 		}
5064c1d255d3SCy Schubert 		is_linestart = is_lineend;
5065c1d255d3SCy Schubert 	}
5066c1d255d3SCy Schubert 
5067c1d255d3SCy Schubert 	fclose(f);
5068c1d255d3SCy Schubert 	bin_clear_free(buf, bufsize);
5069c1d255d3SCy Schubert 
5070c1d255d3SCy Schubert 	return found;
5071c1d255d3SCy Schubert }
5072c1d255d3SCy Schubert 
5073c1d255d3SCy Schubert 
is_tpm2_key(const char * path)5074c1d255d3SCy Schubert static int is_tpm2_key(const char *path)
5075c1d255d3SCy Schubert {
5076c1d255d3SCy Schubert 	/* Check both new and old format of TPM2 PEM guard tag */
5077c1d255d3SCy Schubert 	static const char *tpm2_tags[] = {
5078c1d255d3SCy Schubert 		"-----BEGIN TSS2 PRIVATE KEY-----",
5079c1d255d3SCy Schubert 		"-----BEGIN TSS2 KEY BLOB-----",
5080c1d255d3SCy Schubert 		NULL
5081c1d255d3SCy Schubert 	};
5082c1d255d3SCy Schubert 
5083c1d255d3SCy Schubert 	return match_lines_in_file(path, tpm2_tags);
5084c1d255d3SCy Schubert }
5085c1d255d3SCy Schubert 
5086c1d255d3SCy Schubert 
tls_connection_set_params(void * tls_ctx,struct tls_connection * conn,const struct tls_connection_params * params)508739beb93cSSam Leffler int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
508839beb93cSSam Leffler 			      const struct tls_connection_params *params)
508939beb93cSSam Leffler {
5090325151a3SRui Paulo 	struct tls_data *data = tls_ctx;
509139beb93cSSam Leffler 	int ret;
509239beb93cSSam Leffler 	unsigned long err;
50935b9c547cSRui Paulo 	int can_pkcs11 = 0;
50945b9c547cSRui Paulo 	const char *key_id = params->key_id;
50955b9c547cSRui Paulo 	const char *cert_id = params->cert_id;
50965b9c547cSRui Paulo 	const char *ca_cert_id = params->ca_cert_id;
50975b9c547cSRui Paulo 	const char *engine_id = params->engine ? params->engine_id : NULL;
509885732ac8SCy Schubert 	const char *ciphers;
509939beb93cSSam Leffler 
510039beb93cSSam Leffler 	if (conn == NULL)
510139beb93cSSam Leffler 		return -1;
510239beb93cSSam Leffler 
5103780fb4a2SCy Schubert 	if (params->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
5104780fb4a2SCy Schubert 		wpa_printf(MSG_INFO,
5105780fb4a2SCy Schubert 			   "OpenSSL: ocsp=3 not supported");
5106780fb4a2SCy Schubert 		return -1;
5107780fb4a2SCy Schubert 	}
5108780fb4a2SCy Schubert 
51095b9c547cSRui Paulo 	/*
51105b9c547cSRui Paulo 	 * If the engine isn't explicitly configured, and any of the
51115b9c547cSRui Paulo 	 * cert/key fields are actually PKCS#11 URIs, then automatically
51125b9c547cSRui Paulo 	 * use the PKCS#11 ENGINE.
51135b9c547cSRui Paulo 	 */
51145b9c547cSRui Paulo 	if (!engine_id || os_strcmp(engine_id, "pkcs11") == 0)
51155b9c547cSRui Paulo 		can_pkcs11 = 1;
51165b9c547cSRui Paulo 
51175b9c547cSRui Paulo 	if (!key_id && params->private_key && can_pkcs11 &&
51185b9c547cSRui Paulo 	    os_strncmp(params->private_key, "pkcs11:", 7) == 0) {
51195b9c547cSRui Paulo 		can_pkcs11 = 2;
51205b9c547cSRui Paulo 		key_id = params->private_key;
51215b9c547cSRui Paulo 	}
51225b9c547cSRui Paulo 
51235b9c547cSRui Paulo 	if (!cert_id && params->client_cert && can_pkcs11 &&
51245b9c547cSRui Paulo 	    os_strncmp(params->client_cert, "pkcs11:", 7) == 0) {
51255b9c547cSRui Paulo 		can_pkcs11 = 2;
51265b9c547cSRui Paulo 		cert_id = params->client_cert;
51275b9c547cSRui Paulo 	}
51285b9c547cSRui Paulo 
51295b9c547cSRui Paulo 	if (!ca_cert_id && params->ca_cert && can_pkcs11 &&
51305b9c547cSRui Paulo 	    os_strncmp(params->ca_cert, "pkcs11:", 7) == 0) {
51315b9c547cSRui Paulo 		can_pkcs11 = 2;
51325b9c547cSRui Paulo 		ca_cert_id = params->ca_cert;
51335b9c547cSRui Paulo 	}
51345b9c547cSRui Paulo 
51355b9c547cSRui Paulo 	/* If we need to automatically enable the PKCS#11 ENGINE, do so. */
51365b9c547cSRui Paulo 	if (can_pkcs11 == 2 && !engine_id)
51375b9c547cSRui Paulo 		engine_id = "pkcs11";
51385b9c547cSRui Paulo 
5139c1d255d3SCy Schubert 	/* If private_key points to a TPM2-wrapped key, automatically enable
5140c1d255d3SCy Schubert 	 * tpm2 engine and use it to unwrap the key. */
5141c1d255d3SCy Schubert 	if (params->private_key &&
5142c1d255d3SCy Schubert 	    (!engine_id || os_strcmp(engine_id, "tpm2") == 0) &&
5143c1d255d3SCy Schubert 	    is_tpm2_key(params->private_key)) {
5144c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "OpenSSL: Found TPM2 wrapped key %s",
5145c1d255d3SCy Schubert 			   params->private_key);
5146c1d255d3SCy Schubert 		key_id = key_id ? key_id : params->private_key;
5147c1d255d3SCy Schubert 		engine_id = engine_id ? engine_id : "tpm2";
5148c1d255d3SCy Schubert 	}
5149c1d255d3SCy Schubert 
5150325151a3SRui Paulo #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
515185732ac8SCy Schubert #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
51525b9c547cSRui Paulo 	if (params->flags & TLS_CONN_EAP_FAST) {
51535b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG,
51545b9c547cSRui Paulo 			   "OpenSSL: Use TLSv1_method() for EAP-FAST");
51555b9c547cSRui Paulo 		if (SSL_set_ssl_method(conn->ssl, TLSv1_method()) != 1) {
51565b9c547cSRui Paulo 			tls_show_errors(MSG_INFO, __func__,
51575b9c547cSRui Paulo 					"Failed to set TLSv1_method() for EAP-FAST");
51585b9c547cSRui Paulo 			return -1;
51595b9c547cSRui Paulo 		}
51605b9c547cSRui Paulo 	}
5161325151a3SRui Paulo #endif
516285732ac8SCy Schubert #if OPENSSL_VERSION_NUMBER >= 0x10101000L
516385732ac8SCy Schubert #ifdef SSL_OP_NO_TLSv1_3
516485732ac8SCy Schubert 	if (params->flags & TLS_CONN_EAP_FAST) {
516585732ac8SCy Schubert 		/* Need to disable TLS v1.3 at least for now since OpenSSL 1.1.1
516685732ac8SCy Schubert 		 * refuses to start the handshake with the modified ciphersuite
516785732ac8SCy Schubert 		 * list (no TLS v1.3 ciphersuites included) for EAP-FAST. */
516885732ac8SCy Schubert 		wpa_printf(MSG_DEBUG, "OpenSSL: Disable TLSv1.3 for EAP-FAST");
516985732ac8SCy Schubert 		SSL_set_options(conn->ssl, SSL_OP_NO_TLSv1_3);
517085732ac8SCy Schubert 	}
517185732ac8SCy Schubert #endif /* SSL_OP_NO_TLSv1_3 */
517285732ac8SCy Schubert #endif
5173325151a3SRui Paulo #endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
51745b9c547cSRui Paulo 
517539beb93cSSam Leffler 	while ((err = ERR_get_error())) {
517639beb93cSSam Leffler 		wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s",
517739beb93cSSam Leffler 			   __func__, ERR_error_string(err, NULL));
517839beb93cSSam Leffler 	}
517939beb93cSSam Leffler 
51805b9c547cSRui Paulo 	if (engine_id) {
5181c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine %s",
5182c1d255d3SCy Schubert 			   engine_id);
51835b9c547cSRui Paulo 		ret = tls_engine_init(conn, engine_id, params->pin,
51845b9c547cSRui Paulo 				      key_id, cert_id, ca_cert_id);
518539beb93cSSam Leffler 		if (ret)
518639beb93cSSam Leffler 			return ret;
518739beb93cSSam Leffler 	}
518839beb93cSSam Leffler 	if (tls_connection_set_subject_match(conn,
518939beb93cSSam Leffler 					     params->subject_match,
51905b9c547cSRui Paulo 					     params->altsubject_match,
51915b9c547cSRui Paulo 					     params->suffix_match,
51924bc52338SCy Schubert 					     params->domain_match,
51934bc52338SCy Schubert 					     params->check_cert_subject))
519439beb93cSSam Leffler 		return -1;
519539beb93cSSam Leffler 
51965b9c547cSRui Paulo 	if (engine_id && ca_cert_id) {
5197325151a3SRui Paulo 		if (tls_connection_engine_ca_cert(data, conn, ca_cert_id))
519839beb93cSSam Leffler 			return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
5199325151a3SRui Paulo 	} else if (tls_connection_ca_cert(data, conn, params->ca_cert,
520039beb93cSSam Leffler 					  params->ca_cert_blob,
520139beb93cSSam Leffler 					  params->ca_cert_blob_len,
520239beb93cSSam Leffler 					  params->ca_path))
520339beb93cSSam Leffler 		return -1;
520439beb93cSSam Leffler 
52055b9c547cSRui Paulo 	if (engine_id && cert_id) {
52065b9c547cSRui Paulo 		if (tls_connection_engine_client_cert(conn, cert_id))
520739beb93cSSam Leffler 			return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
520839beb93cSSam Leffler 	} else if (tls_connection_client_cert(conn, params->client_cert,
520939beb93cSSam Leffler 					      params->client_cert_blob,
521039beb93cSSam Leffler 					      params->client_cert_blob_len))
521139beb93cSSam Leffler 		return -1;
521239beb93cSSam Leffler 
52135b9c547cSRui Paulo 	if (engine_id && key_id) {
521439beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLS: Using private key from engine");
521539beb93cSSam Leffler 		if (tls_connection_engine_private_key(conn))
521639beb93cSSam Leffler 			return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
5217325151a3SRui Paulo 	} else if (tls_connection_private_key(data, conn,
521839beb93cSSam Leffler 					      params->private_key,
521939beb93cSSam Leffler 					      params->private_key_passwd,
522039beb93cSSam Leffler 					      params->private_key_blob,
522139beb93cSSam Leffler 					      params->private_key_blob_len)) {
522239beb93cSSam Leffler 		wpa_printf(MSG_INFO, "TLS: Failed to load private key '%s'",
522339beb93cSSam Leffler 			   params->private_key);
522439beb93cSSam Leffler 		return -1;
522539beb93cSSam Leffler 	}
522639beb93cSSam Leffler 
522739beb93cSSam Leffler 	if (tls_connection_dh(conn, params->dh_file)) {
522839beb93cSSam Leffler 		wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'",
522939beb93cSSam Leffler 			   params->dh_file);
523039beb93cSSam Leffler 		return -1;
523139beb93cSSam Leffler 	}
523239beb93cSSam Leffler 
523385732ac8SCy Schubert 	ciphers = params->openssl_ciphers;
523485732ac8SCy Schubert #ifdef CONFIG_SUITEB
523585732ac8SCy Schubert #ifdef OPENSSL_IS_BORINGSSL
523685732ac8SCy Schubert 	if (ciphers && os_strcmp(ciphers, "SUITEB192") == 0) {
523785732ac8SCy Schubert 		/* BoringSSL removed support for SUITEB192, so need to handle
523885732ac8SCy Schubert 		 * this with hardcoded ciphersuite and additional checks for
523985732ac8SCy Schubert 		 * other parameters. */
524085732ac8SCy Schubert 		ciphers = "ECDHE-ECDSA-AES256-GCM-SHA384";
524185732ac8SCy Schubert 	}
524285732ac8SCy Schubert #endif /* OPENSSL_IS_BORINGSSL */
524385732ac8SCy Schubert #endif /* CONFIG_SUITEB */
524485732ac8SCy Schubert 	if (ciphers && SSL_set_cipher_list(conn->ssl, ciphers) != 1) {
52455b9c547cSRui Paulo 		wpa_printf(MSG_INFO,
52465b9c547cSRui Paulo 			   "OpenSSL: Failed to set cipher string '%s'",
524785732ac8SCy Schubert 			   ciphers);
52485b9c547cSRui Paulo 		return -1;
52495b9c547cSRui Paulo 	}
52505b9c547cSRui Paulo 
52514bc52338SCy Schubert 	if (!params->openssl_ecdh_curves) {
52524bc52338SCy Schubert #ifndef OPENSSL_IS_BORINGSSL
52534bc52338SCy Schubert #ifndef OPENSSL_NO_EC
52544bc52338SCy Schubert #if (OPENSSL_VERSION_NUMBER >= 0x10002000L) && \
52554bc52338SCy Schubert 	(OPENSSL_VERSION_NUMBER < 0x10100000L)
52564bc52338SCy Schubert 		if (SSL_set_ecdh_auto(conn->ssl, 1) != 1) {
52574bc52338SCy Schubert 			wpa_printf(MSG_INFO,
52584bc52338SCy Schubert 				   "OpenSSL: Failed to set ECDH curves to auto");
52594bc52338SCy Schubert 			return -1;
52604bc52338SCy Schubert 		}
52614bc52338SCy Schubert #endif /* >= 1.0.2 && < 1.1.0 */
52624bc52338SCy Schubert #endif /* OPENSSL_NO_EC */
52634bc52338SCy Schubert #endif /* OPENSSL_IS_BORINGSSL */
52644bc52338SCy Schubert 	} else if (params->openssl_ecdh_curves[0]) {
52654bc52338SCy Schubert #if defined(OPENSSL_IS_BORINGSSL) || (OPENSSL_VERSION_NUMBER < 0x10002000L)
52664bc52338SCy Schubert 		wpa_printf(MSG_INFO,
52674bc52338SCy Schubert 			"OpenSSL: ECDH configuration nnot supported");
52684bc52338SCy Schubert 		return -1;
52694bc52338SCy Schubert #else /* OPENSSL_IS_BORINGSSL || < 1.0.2 */
52704bc52338SCy Schubert #ifndef OPENSSL_NO_EC
52714bc52338SCy Schubert 		if (SSL_set1_curves_list(conn->ssl,
52724bc52338SCy Schubert 					 params->openssl_ecdh_curves) != 1) {
52734bc52338SCy Schubert 			wpa_printf(MSG_INFO,
52744bc52338SCy Schubert 				   "OpenSSL: Failed to set ECDH curves '%s'",
52754bc52338SCy Schubert 				   params->openssl_ecdh_curves);
52764bc52338SCy Schubert 			return -1;
52774bc52338SCy Schubert 		}
52784bc52338SCy Schubert #else /* OPENSSL_NO_EC */
52794bc52338SCy Schubert 		wpa_printf(MSG_INFO, "OpenSSL: ECDH not supported");
52804bc52338SCy Schubert 		return -1;
52814bc52338SCy Schubert #endif /* OPENSSL_NO_EC */
52824bc52338SCy Schubert #endif /* OPENSSL_IS_BORINGSSL */
52834bc52338SCy Schubert 	}
52844bc52338SCy Schubert 
528585732ac8SCy Schubert 	if (tls_set_conn_flags(conn, params->flags,
528685732ac8SCy Schubert 			       params->openssl_ciphers) < 0)
528785732ac8SCy Schubert 		return -1;
52885b9c547cSRui Paulo 
5289780fb4a2SCy Schubert #ifdef OPENSSL_IS_BORINGSSL
5290780fb4a2SCy Schubert 	if (params->flags & TLS_CONN_REQUEST_OCSP) {
5291780fb4a2SCy Schubert 		SSL_enable_ocsp_stapling(conn->ssl);
5292780fb4a2SCy Schubert 	}
5293780fb4a2SCy Schubert #else /* OPENSSL_IS_BORINGSSL */
52945b9c547cSRui Paulo #ifdef HAVE_OCSP
52955b9c547cSRui Paulo 	if (params->flags & TLS_CONN_REQUEST_OCSP) {
5296325151a3SRui Paulo 		SSL_CTX *ssl_ctx = data->ssl;
52975b9c547cSRui Paulo 		SSL_set_tlsext_status_type(conn->ssl, TLSEXT_STATUSTYPE_ocsp);
52985b9c547cSRui Paulo 		SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_resp_cb);
52995b9c547cSRui Paulo 		SSL_CTX_set_tlsext_status_arg(ssl_ctx, conn);
53005b9c547cSRui Paulo 	}
5301325151a3SRui Paulo #else /* HAVE_OCSP */
5302325151a3SRui Paulo 	if (params->flags & TLS_CONN_REQUIRE_OCSP) {
5303325151a3SRui Paulo 		wpa_printf(MSG_INFO,
5304325151a3SRui Paulo 			   "OpenSSL: No OCSP support included - reject configuration");
5305325151a3SRui Paulo 		return -1;
5306325151a3SRui Paulo 	}
5307325151a3SRui Paulo 	if (params->flags & TLS_CONN_REQUEST_OCSP) {
5308325151a3SRui Paulo 		wpa_printf(MSG_DEBUG,
5309325151a3SRui Paulo 			   "OpenSSL: No OCSP support included - allow optional OCSP case to continue");
5310325151a3SRui Paulo 	}
53115b9c547cSRui Paulo #endif /* HAVE_OCSP */
5312780fb4a2SCy Schubert #endif /* OPENSSL_IS_BORINGSSL */
53135b9c547cSRui Paulo 
5314f05cddf9SRui Paulo 	conn->flags = params->flags;
5315f05cddf9SRui Paulo 
5316325151a3SRui Paulo 	tls_get_errors(data);
531739beb93cSSam Leffler 
531839beb93cSSam Leffler 	return 0;
531939beb93cSSam Leffler }
532039beb93cSSam Leffler 
532139beb93cSSam Leffler 
openssl_debug_dump_cipher_list(SSL_CTX * ssl_ctx)5322206b73d0SCy Schubert static void openssl_debug_dump_cipher_list(SSL_CTX *ssl_ctx)
5323206b73d0SCy Schubert {
5324206b73d0SCy Schubert 	SSL *ssl;
5325206b73d0SCy Schubert 	int i;
5326206b73d0SCy Schubert 
5327206b73d0SCy Schubert 	ssl = SSL_new(ssl_ctx);
5328206b73d0SCy Schubert 	if (!ssl)
5329206b73d0SCy Schubert 		return;
5330206b73d0SCy Schubert 
5331206b73d0SCy Schubert 	wpa_printf(MSG_DEBUG,
5332206b73d0SCy Schubert 		   "OpenSSL: Enabled cipher suites in priority order");
5333206b73d0SCy Schubert 	for (i = 0; ; i++) {
5334206b73d0SCy Schubert 		const char *cipher;
5335206b73d0SCy Schubert 
5336206b73d0SCy Schubert 		cipher = SSL_get_cipher_list(ssl, i);
5337206b73d0SCy Schubert 		if (!cipher)
5338206b73d0SCy Schubert 			break;
5339206b73d0SCy Schubert 		wpa_printf(MSG_DEBUG, "Cipher %d: %s", i, cipher);
5340206b73d0SCy Schubert 	}
5341206b73d0SCy Schubert 
5342206b73d0SCy Schubert 	SSL_free(ssl);
5343206b73d0SCy Schubert }
5344206b73d0SCy Schubert 
5345206b73d0SCy Schubert 
5346206b73d0SCy Schubert #if !defined(LIBRESSL_VERSION_NUMBER) && !defined(BORINGSSL_API_VERSION)
5347206b73d0SCy Schubert 
openssl_pkey_type_str(const EVP_PKEY * pkey)5348206b73d0SCy Schubert static const char * openssl_pkey_type_str(const EVP_PKEY *pkey)
5349206b73d0SCy Schubert {
5350206b73d0SCy Schubert 	if (!pkey)
5351206b73d0SCy Schubert 		return "NULL";
5352206b73d0SCy Schubert 	switch (EVP_PKEY_type(EVP_PKEY_id(pkey))) {
5353206b73d0SCy Schubert 	case EVP_PKEY_RSA:
5354206b73d0SCy Schubert 		return "RSA";
5355206b73d0SCy Schubert 	case EVP_PKEY_DSA:
5356206b73d0SCy Schubert 		return "DSA";
5357206b73d0SCy Schubert 	case EVP_PKEY_DH:
5358206b73d0SCy Schubert 		return "DH";
5359206b73d0SCy Schubert 	case EVP_PKEY_EC:
5360206b73d0SCy Schubert 		return "EC";
5361206b73d0SCy Schubert 	}
5362206b73d0SCy Schubert 	return "?";
5363206b73d0SCy Schubert }
5364206b73d0SCy Schubert 
5365206b73d0SCy Schubert 
openssl_debug_dump_certificate(int i,X509 * cert)5366206b73d0SCy Schubert static void openssl_debug_dump_certificate(int i, X509 *cert)
5367206b73d0SCy Schubert {
5368206b73d0SCy Schubert 	char buf[256];
5369206b73d0SCy Schubert 	EVP_PKEY *pkey;
5370206b73d0SCy Schubert 	ASN1_INTEGER *ser;
5371206b73d0SCy Schubert 	char serial_num[128];
5372206b73d0SCy Schubert 
5373c1d255d3SCy Schubert 	if (!cert)
5374c1d255d3SCy Schubert 		return;
5375c1d255d3SCy Schubert 
5376206b73d0SCy Schubert 	X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
5377206b73d0SCy Schubert 
5378206b73d0SCy Schubert 	ser = X509_get_serialNumber(cert);
5379206b73d0SCy Schubert 	if (ser)
5380206b73d0SCy Schubert 		wpa_snprintf_hex_uppercase(serial_num, sizeof(serial_num),
5381206b73d0SCy Schubert 					   ASN1_STRING_get0_data(ser),
5382206b73d0SCy Schubert 					   ASN1_STRING_length(ser));
5383206b73d0SCy Schubert 	else
5384206b73d0SCy Schubert 		serial_num[0] = '\0';
5385206b73d0SCy Schubert 
5386206b73d0SCy Schubert 	pkey = X509_get_pubkey(cert);
5387206b73d0SCy Schubert 	wpa_printf(MSG_DEBUG, "%d: %s (%s) %s", i, buf,
5388206b73d0SCy Schubert 		   openssl_pkey_type_str(pkey), serial_num);
5389206b73d0SCy Schubert 	EVP_PKEY_free(pkey);
5390206b73d0SCy Schubert }
5391206b73d0SCy Schubert 
5392206b73d0SCy Schubert 
openssl_debug_dump_certificates(SSL_CTX * ssl_ctx)5393206b73d0SCy Schubert static void openssl_debug_dump_certificates(SSL_CTX *ssl_ctx)
5394206b73d0SCy Schubert {
5395206b73d0SCy Schubert 	STACK_OF(X509) *certs;
5396206b73d0SCy Schubert 
5397206b73d0SCy Schubert 	wpa_printf(MSG_DEBUG, "OpenSSL: Configured certificate chain");
5398206b73d0SCy Schubert 	if (SSL_CTX_get0_chain_certs(ssl_ctx, &certs) == 1) {
5399206b73d0SCy Schubert 		int i;
5400206b73d0SCy Schubert 
5401206b73d0SCy Schubert 		for (i = sk_X509_num(certs); i > 0; i--)
5402206b73d0SCy Schubert 			openssl_debug_dump_certificate(i, sk_X509_value(certs,
5403206b73d0SCy Schubert 									i - 1));
5404206b73d0SCy Schubert 	}
5405206b73d0SCy Schubert 	openssl_debug_dump_certificate(0, SSL_CTX_get0_certificate(ssl_ctx));
5406206b73d0SCy Schubert }
5407206b73d0SCy Schubert 
5408206b73d0SCy Schubert #endif
5409206b73d0SCy Schubert 
5410206b73d0SCy Schubert 
openssl_debug_dump_certificate_chains(SSL_CTX * ssl_ctx)5411206b73d0SCy Schubert static void openssl_debug_dump_certificate_chains(SSL_CTX *ssl_ctx)
5412206b73d0SCy Schubert {
5413206b73d0SCy Schubert #if !defined(LIBRESSL_VERSION_NUMBER) && !defined(BORINGSSL_API_VERSION)
5414206b73d0SCy Schubert 	int res;
5415206b73d0SCy Schubert 
5416206b73d0SCy Schubert 	for (res = SSL_CTX_set_current_cert(ssl_ctx, SSL_CERT_SET_FIRST);
5417206b73d0SCy Schubert 	     res == 1;
5418206b73d0SCy Schubert 	     res = SSL_CTX_set_current_cert(ssl_ctx, SSL_CERT_SET_NEXT))
5419206b73d0SCy Schubert 		openssl_debug_dump_certificates(ssl_ctx);
5420206b73d0SCy Schubert 
5421206b73d0SCy Schubert 	SSL_CTX_set_current_cert(ssl_ctx, SSL_CERT_SET_FIRST);
5422206b73d0SCy Schubert #endif
5423206b73d0SCy Schubert }
5424206b73d0SCy Schubert 
5425206b73d0SCy Schubert 
openssl_debug_dump_ctx(SSL_CTX * ssl_ctx)5426206b73d0SCy Schubert static void openssl_debug_dump_ctx(SSL_CTX *ssl_ctx)
5427206b73d0SCy Schubert {
5428206b73d0SCy Schubert 	openssl_debug_dump_cipher_list(ssl_ctx);
5429206b73d0SCy Schubert 	openssl_debug_dump_certificate_chains(ssl_ctx);
5430206b73d0SCy Schubert }
5431206b73d0SCy Schubert 
5432206b73d0SCy Schubert 
tls_global_set_params(void * tls_ctx,const struct tls_connection_params * params)543339beb93cSSam Leffler int tls_global_set_params(void *tls_ctx,
543439beb93cSSam Leffler 			  const struct tls_connection_params *params)
543539beb93cSSam Leffler {
5436325151a3SRui Paulo 	struct tls_data *data = tls_ctx;
5437325151a3SRui Paulo 	SSL_CTX *ssl_ctx = data->ssl;
543839beb93cSSam Leffler 	unsigned long err;
543939beb93cSSam Leffler 
544039beb93cSSam Leffler 	while ((err = ERR_get_error())) {
544139beb93cSSam Leffler 		wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s",
544239beb93cSSam Leffler 			   __func__, ERR_error_string(err, NULL));
544339beb93cSSam Leffler 	}
544439beb93cSSam Leffler 
54454bc52338SCy Schubert 	os_free(data->check_cert_subject);
54464bc52338SCy Schubert 	data->check_cert_subject = NULL;
54474bc52338SCy Schubert 	if (params->check_cert_subject) {
54484bc52338SCy Schubert 		data->check_cert_subject =
54494bc52338SCy Schubert 			os_strdup(params->check_cert_subject);
54504bc52338SCy Schubert 		if (!data->check_cert_subject)
54514bc52338SCy Schubert 			return -1;
54524bc52338SCy Schubert 	}
54534bc52338SCy Schubert 
5454325151a3SRui Paulo 	if (tls_global_ca_cert(data, params->ca_cert) ||
5455325151a3SRui Paulo 	    tls_global_client_cert(data, params->client_cert) ||
5456325151a3SRui Paulo 	    tls_global_private_key(data, params->private_key,
5457325151a3SRui Paulo 				   params->private_key_passwd) ||
5458206b73d0SCy Schubert 	    tls_global_client_cert(data, params->client_cert2) ||
5459206b73d0SCy Schubert 	    tls_global_private_key(data, params->private_key2,
5460206b73d0SCy Schubert 				   params->private_key_passwd2) ||
5461325151a3SRui Paulo 	    tls_global_dh(data, params->dh_file)) {
5462325151a3SRui Paulo 		wpa_printf(MSG_INFO, "TLS: Failed to set global parameters");
546339beb93cSSam Leffler 		return -1;
546439beb93cSSam Leffler 	}
546539beb93cSSam Leffler 
54665b9c547cSRui Paulo 	if (params->openssl_ciphers &&
54675b9c547cSRui Paulo 	    SSL_CTX_set_cipher_list(ssl_ctx, params->openssl_ciphers) != 1) {
54685b9c547cSRui Paulo 		wpa_printf(MSG_INFO,
54695b9c547cSRui Paulo 			   "OpenSSL: Failed to set cipher string '%s'",
54705b9c547cSRui Paulo 			   params->openssl_ciphers);
54715b9c547cSRui Paulo 		return -1;
54725b9c547cSRui Paulo 	}
54735b9c547cSRui Paulo 
54744bc52338SCy Schubert 	if (!params->openssl_ecdh_curves) {
54754bc52338SCy Schubert #ifndef OPENSSL_IS_BORINGSSL
54764bc52338SCy Schubert #ifndef OPENSSL_NO_EC
54774bc52338SCy Schubert #if (OPENSSL_VERSION_NUMBER >= 0x10002000L) && \
54784bc52338SCy Schubert 	(OPENSSL_VERSION_NUMBER < 0x10100000L)
54794bc52338SCy Schubert 		if (SSL_CTX_set_ecdh_auto(ssl_ctx, 1) != 1) {
54804bc52338SCy Schubert 			wpa_printf(MSG_INFO,
54814bc52338SCy Schubert 				   "OpenSSL: Failed to set ECDH curves to auto");
54824bc52338SCy Schubert 			return -1;
54834bc52338SCy Schubert 		}
54844bc52338SCy Schubert #endif /* >= 1.0.2 && < 1.1.0 */
54854bc52338SCy Schubert #endif /* OPENSSL_NO_EC */
54864bc52338SCy Schubert #endif /* OPENSSL_IS_BORINGSSL */
54874bc52338SCy Schubert 	} else if (params->openssl_ecdh_curves[0]) {
54884bc52338SCy Schubert #if defined(OPENSSL_IS_BORINGSSL) || (OPENSSL_VERSION_NUMBER < 0x10002000L)
54894bc52338SCy Schubert 		wpa_printf(MSG_INFO,
54904bc52338SCy Schubert 			"OpenSSL: ECDH configuration nnot supported");
54914bc52338SCy Schubert 		return -1;
54924bc52338SCy Schubert #else /* OPENSSL_IS_BORINGSSL || < 1.0.2 */
54934bc52338SCy Schubert #ifndef OPENSSL_NO_EC
54944bc52338SCy Schubert #if OPENSSL_VERSION_NUMBER < 0x10100000L
54954bc52338SCy Schubert 		SSL_CTX_set_ecdh_auto(ssl_ctx, 1);
54964bc52338SCy Schubert #endif
54974bc52338SCy Schubert 		if (SSL_CTX_set1_curves_list(ssl_ctx,
54984bc52338SCy Schubert 					     params->openssl_ecdh_curves) !=
54994bc52338SCy Schubert 		    1) {
55004bc52338SCy Schubert 			wpa_printf(MSG_INFO,
55014bc52338SCy Schubert 				   "OpenSSL: Failed to set ECDH curves '%s'",
55024bc52338SCy Schubert 				   params->openssl_ecdh_curves);
55034bc52338SCy Schubert 			return -1;
55044bc52338SCy Schubert 		}
55054bc52338SCy Schubert #else /* OPENSSL_NO_EC */
55064bc52338SCy Schubert 		wpa_printf(MSG_INFO, "OpenSSL: ECDH not supported");
55074bc52338SCy Schubert 		return -1;
55084bc52338SCy Schubert #endif /* OPENSSL_NO_EC */
55094bc52338SCy Schubert #endif /* OPENSSL_IS_BORINGSSL */
55104bc52338SCy Schubert 	}
55114bc52338SCy Schubert 
5512f05cddf9SRui Paulo #ifdef SSL_OP_NO_TICKET
5513f05cddf9SRui Paulo 	if (params->flags & TLS_CONN_DISABLE_SESSION_TICKET)
5514f05cddf9SRui Paulo 		SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TICKET);
5515f05cddf9SRui Paulo 	else
5516f05cddf9SRui Paulo 		SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TICKET);
5517f05cddf9SRui Paulo #endif /*  SSL_OP_NO_TICKET */
5518f05cddf9SRui Paulo 
55195b9c547cSRui Paulo #ifdef HAVE_OCSP
55205b9c547cSRui Paulo 	SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_status_cb);
55215b9c547cSRui Paulo 	SSL_CTX_set_tlsext_status_arg(ssl_ctx, ssl_ctx);
55225b9c547cSRui Paulo 	os_free(tls_global->ocsp_stapling_response);
55235b9c547cSRui Paulo 	if (params->ocsp_stapling_response)
55245b9c547cSRui Paulo 		tls_global->ocsp_stapling_response =
55255b9c547cSRui Paulo 			os_strdup(params->ocsp_stapling_response);
55265b9c547cSRui Paulo 	else
55275b9c547cSRui Paulo 		tls_global->ocsp_stapling_response = NULL;
55285b9c547cSRui Paulo #endif /* HAVE_OCSP */
55295b9c547cSRui Paulo 
5530206b73d0SCy Schubert 	openssl_debug_dump_ctx(ssl_ctx);
5531206b73d0SCy Schubert 
553239beb93cSSam Leffler 	return 0;
553339beb93cSSam Leffler }
553439beb93cSSam Leffler 
553539beb93cSSam Leffler 
5536206b73d0SCy Schubert #ifdef EAP_FAST_OR_TEAP
553739beb93cSSam Leffler /* Pre-shared secred requires a patch to openssl, so this function is
553839beb93cSSam Leffler  * commented out unless explicitly needed for EAP-FAST in order to be able to
553939beb93cSSam Leffler  * build this file with unmodified openssl. */
554039beb93cSSam Leffler 
5541780fb4a2SCy Schubert #if (defined(OPENSSL_IS_BORINGSSL) || OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
tls_sess_sec_cb(SSL * s,void * secret,int * secret_len,STACK_OF (SSL_CIPHER)* peer_ciphers,const SSL_CIPHER ** cipher,void * arg)55425b9c547cSRui Paulo static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
55435b9c547cSRui Paulo 			   STACK_OF(SSL_CIPHER) *peer_ciphers,
55445b9c547cSRui Paulo 			   const SSL_CIPHER **cipher, void *arg)
55455b9c547cSRui Paulo #else /* OPENSSL_IS_BORINGSSL */
554639beb93cSSam Leffler static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
554739beb93cSSam Leffler 			   STACK_OF(SSL_CIPHER) *peer_ciphers,
554839beb93cSSam Leffler 			   SSL_CIPHER **cipher, void *arg)
55495b9c547cSRui Paulo #endif /* OPENSSL_IS_BORINGSSL */
555039beb93cSSam Leffler {
555139beb93cSSam Leffler 	struct tls_connection *conn = arg;
555239beb93cSSam Leffler 	int ret;
555339beb93cSSam Leffler 
555485732ac8SCy Schubert #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
555585732ac8SCy Schubert 	(defined(LIBRESSL_VERSION_NUMBER) && \
555685732ac8SCy Schubert 	 LIBRESSL_VERSION_NUMBER < 0x20700000L)
555739beb93cSSam Leffler 	if (conn == NULL || conn->session_ticket_cb == NULL)
555839beb93cSSam Leffler 		return 0;
555939beb93cSSam Leffler 
556039beb93cSSam Leffler 	ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx,
556139beb93cSSam Leffler 				      conn->session_ticket,
556239beb93cSSam Leffler 				      conn->session_ticket_len,
556339beb93cSSam Leffler 				      s->s3->client_random,
556439beb93cSSam Leffler 				      s->s3->server_random, secret);
5565325151a3SRui Paulo #else
5566325151a3SRui Paulo 	unsigned char client_random[SSL3_RANDOM_SIZE];
5567325151a3SRui Paulo 	unsigned char server_random[SSL3_RANDOM_SIZE];
5568325151a3SRui Paulo 
5569325151a3SRui Paulo 	if (conn == NULL || conn->session_ticket_cb == NULL)
5570325151a3SRui Paulo 		return 0;
5571325151a3SRui Paulo 
5572325151a3SRui Paulo 	SSL_get_client_random(s, client_random, sizeof(client_random));
5573325151a3SRui Paulo 	SSL_get_server_random(s, server_random, sizeof(server_random));
5574325151a3SRui Paulo 
5575325151a3SRui Paulo 	ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx,
5576325151a3SRui Paulo 				      conn->session_ticket,
5577325151a3SRui Paulo 				      conn->session_ticket_len,
5578325151a3SRui Paulo 				      client_random,
5579325151a3SRui Paulo 				      server_random, secret);
5580325151a3SRui Paulo #endif
5581325151a3SRui Paulo 
558239beb93cSSam Leffler 	os_free(conn->session_ticket);
558339beb93cSSam Leffler 	conn->session_ticket = NULL;
558439beb93cSSam Leffler 
558539beb93cSSam Leffler 	if (ret <= 0)
558639beb93cSSam Leffler 		return 0;
558739beb93cSSam Leffler 
558839beb93cSSam Leffler 	*secret_len = SSL_MAX_MASTER_KEY_LENGTH;
558939beb93cSSam Leffler 	return 1;
559039beb93cSSam Leffler }
559139beb93cSSam Leffler 
559239beb93cSSam Leffler 
tls_session_ticket_ext_cb(SSL * s,const unsigned char * data,int len,void * arg)559339beb93cSSam Leffler static int tls_session_ticket_ext_cb(SSL *s, const unsigned char *data,
559439beb93cSSam Leffler 				     int len, void *arg)
559539beb93cSSam Leffler {
559639beb93cSSam Leffler 	struct tls_connection *conn = arg;
559739beb93cSSam Leffler 
559839beb93cSSam Leffler 	if (conn == NULL || conn->session_ticket_cb == NULL)
559939beb93cSSam Leffler 		return 0;
560039beb93cSSam Leffler 
560139beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "OpenSSL: %s: length=%d", __func__, len);
560239beb93cSSam Leffler 
560339beb93cSSam Leffler 	os_free(conn->session_ticket);
560439beb93cSSam Leffler 	conn->session_ticket = NULL;
560539beb93cSSam Leffler 
560639beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket "
560739beb93cSSam Leffler 		    "extension", data, len);
560839beb93cSSam Leffler 
560985732ac8SCy Schubert 	conn->session_ticket = os_memdup(data, len);
561039beb93cSSam Leffler 	if (conn->session_ticket == NULL)
561139beb93cSSam Leffler 		return 0;
561239beb93cSSam Leffler 
561339beb93cSSam Leffler 	conn->session_ticket_len = len;
561439beb93cSSam Leffler 
561539beb93cSSam Leffler 	return 1;
561639beb93cSSam Leffler }
5617206b73d0SCy Schubert #endif /* EAP_FAST_OR_TEAP */
561839beb93cSSam Leffler 
561939beb93cSSam Leffler 
tls_connection_set_session_ticket_cb(void * tls_ctx,struct tls_connection * conn,tls_session_ticket_cb cb,void * ctx)562039beb93cSSam Leffler int tls_connection_set_session_ticket_cb(void *tls_ctx,
562139beb93cSSam Leffler 					 struct tls_connection *conn,
562239beb93cSSam Leffler 					 tls_session_ticket_cb cb,
562339beb93cSSam Leffler 					 void *ctx)
562439beb93cSSam Leffler {
5625206b73d0SCy Schubert #ifdef EAP_FAST_OR_TEAP
562639beb93cSSam Leffler 	conn->session_ticket_cb = cb;
562739beb93cSSam Leffler 	conn->session_ticket_cb_ctx = ctx;
562839beb93cSSam Leffler 
562939beb93cSSam Leffler 	if (cb) {
563039beb93cSSam Leffler 		if (SSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb,
563139beb93cSSam Leffler 					      conn) != 1)
563239beb93cSSam Leffler 			return -1;
563339beb93cSSam Leffler 		SSL_set_session_ticket_ext_cb(conn->ssl,
563439beb93cSSam Leffler 					      tls_session_ticket_ext_cb, conn);
563539beb93cSSam Leffler 	} else {
563639beb93cSSam Leffler 		if (SSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1)
563739beb93cSSam Leffler 			return -1;
563839beb93cSSam Leffler 		SSL_set_session_ticket_ext_cb(conn->ssl, NULL, NULL);
563939beb93cSSam Leffler 	}
564039beb93cSSam Leffler 
564139beb93cSSam Leffler 	return 0;
5642206b73d0SCy Schubert #else /* EAP_FAST_OR_TEAP */
564339beb93cSSam Leffler 	return -1;
5644206b73d0SCy Schubert #endif /* EAP_FAST_OR_TEAP */
564539beb93cSSam Leffler }
56465b9c547cSRui Paulo 
56475b9c547cSRui Paulo 
tls_get_library_version(char * buf,size_t buf_len)56485b9c547cSRui Paulo int tls_get_library_version(char *buf, size_t buf_len)
56495b9c547cSRui Paulo {
5650780fb4a2SCy Schubert #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
5651780fb4a2SCy Schubert 	return os_snprintf(buf, buf_len, "OpenSSL build=%s run=%s",
5652780fb4a2SCy Schubert 			   OPENSSL_VERSION_TEXT,
5653780fb4a2SCy Schubert 			   OpenSSL_version(OPENSSL_VERSION));
5654780fb4a2SCy Schubert #else
56555b9c547cSRui Paulo 	return os_snprintf(buf, buf_len, "OpenSSL build=%s run=%s",
56565b9c547cSRui Paulo 			   OPENSSL_VERSION_TEXT,
56575b9c547cSRui Paulo 			   SSLeay_version(SSLEAY_VERSION));
5658780fb4a2SCy Schubert #endif
56595b9c547cSRui Paulo }
5660325151a3SRui Paulo 
5661325151a3SRui Paulo 
tls_connection_set_success_data(struct tls_connection * conn,struct wpabuf * data)5662325151a3SRui Paulo void tls_connection_set_success_data(struct tls_connection *conn,
5663325151a3SRui Paulo 				     struct wpabuf *data)
5664325151a3SRui Paulo {
5665325151a3SRui Paulo 	SSL_SESSION *sess;
5666325151a3SRui Paulo 	struct wpabuf *old;
5667325151a3SRui Paulo 
5668325151a3SRui Paulo 	if (tls_ex_idx_session < 0)
5669325151a3SRui Paulo 		goto fail;
5670325151a3SRui Paulo 	sess = SSL_get_session(conn->ssl);
5671325151a3SRui Paulo 	if (!sess)
5672325151a3SRui Paulo 		goto fail;
5673325151a3SRui Paulo 	old = SSL_SESSION_get_ex_data(sess, tls_ex_idx_session);
5674325151a3SRui Paulo 	if (old) {
5675325151a3SRui Paulo 		wpa_printf(MSG_DEBUG, "OpenSSL: Replacing old success data %p",
5676325151a3SRui Paulo 			   old);
5677325151a3SRui Paulo 		wpabuf_free(old);
5678325151a3SRui Paulo 	}
5679325151a3SRui Paulo 	if (SSL_SESSION_set_ex_data(sess, tls_ex_idx_session, data) != 1)
5680325151a3SRui Paulo 		goto fail;
5681325151a3SRui Paulo 
5682325151a3SRui Paulo 	wpa_printf(MSG_DEBUG, "OpenSSL: Stored success data %p", data);
5683325151a3SRui Paulo 	conn->success_data = 1;
5684325151a3SRui Paulo 	return;
5685325151a3SRui Paulo 
5686325151a3SRui Paulo fail:
5687325151a3SRui Paulo 	wpa_printf(MSG_INFO, "OpenSSL: Failed to store success data");
5688325151a3SRui Paulo 	wpabuf_free(data);
5689325151a3SRui Paulo }
5690325151a3SRui Paulo 
5691325151a3SRui Paulo 
tls_connection_set_success_data_resumed(struct tls_connection * conn)5692325151a3SRui Paulo void tls_connection_set_success_data_resumed(struct tls_connection *conn)
5693325151a3SRui Paulo {
5694325151a3SRui Paulo 	wpa_printf(MSG_DEBUG,
5695325151a3SRui Paulo 		   "OpenSSL: Success data accepted for resumed session");
5696325151a3SRui Paulo 	conn->success_data = 1;
5697325151a3SRui Paulo }
5698325151a3SRui Paulo 
5699325151a3SRui Paulo 
5700325151a3SRui Paulo const struct wpabuf *
tls_connection_get_success_data(struct tls_connection * conn)5701325151a3SRui Paulo tls_connection_get_success_data(struct tls_connection *conn)
5702325151a3SRui Paulo {
5703325151a3SRui Paulo 	SSL_SESSION *sess;
5704325151a3SRui Paulo 
5705325151a3SRui Paulo 	if (tls_ex_idx_session < 0 ||
5706325151a3SRui Paulo 	    !(sess = SSL_get_session(conn->ssl)))
5707325151a3SRui Paulo 		return NULL;
5708325151a3SRui Paulo 	return SSL_SESSION_get_ex_data(sess, tls_ex_idx_session);
5709325151a3SRui Paulo }
5710325151a3SRui Paulo 
5711325151a3SRui Paulo 
tls_connection_remove_session(struct tls_connection * conn)5712325151a3SRui Paulo void tls_connection_remove_session(struct tls_connection *conn)
5713325151a3SRui Paulo {
5714325151a3SRui Paulo 	SSL_SESSION *sess;
5715325151a3SRui Paulo 
5716325151a3SRui Paulo 	sess = SSL_get_session(conn->ssl);
5717325151a3SRui Paulo 	if (!sess)
5718325151a3SRui Paulo 		return;
5719325151a3SRui Paulo 
5720325151a3SRui Paulo 	if (SSL_CTX_remove_session(conn->ssl_ctx, sess) != 1)
5721325151a3SRui Paulo 		wpa_printf(MSG_DEBUG,
5722325151a3SRui Paulo 			   "OpenSSL: Session was not cached");
5723325151a3SRui Paulo 	else
5724325151a3SRui Paulo 		wpa_printf(MSG_DEBUG,
5725325151a3SRui Paulo 			   "OpenSSL: Removed cached session to disable session resumption");
5726325151a3SRui Paulo }
5727206b73d0SCy Schubert 
5728206b73d0SCy Schubert 
tls_get_tls_unique(struct tls_connection * conn,u8 * buf,size_t max_len)5729206b73d0SCy Schubert int tls_get_tls_unique(struct tls_connection *conn, u8 *buf, size_t max_len)
5730206b73d0SCy Schubert {
5731206b73d0SCy Schubert 	size_t len;
5732206b73d0SCy Schubert 	int reused;
5733206b73d0SCy Schubert 
5734206b73d0SCy Schubert 	reused = SSL_session_reused(conn->ssl);
5735206b73d0SCy Schubert 	if ((conn->server && !reused) || (!conn->server && reused))
5736206b73d0SCy Schubert 		len = SSL_get_peer_finished(conn->ssl, buf, max_len);
5737206b73d0SCy Schubert 	else
5738206b73d0SCy Schubert 		len = SSL_get_finished(conn->ssl, buf, max_len);
5739206b73d0SCy Schubert 
5740206b73d0SCy Schubert 	if (len == 0 || len > max_len)
5741206b73d0SCy Schubert 		return -1;
5742206b73d0SCy Schubert 
5743206b73d0SCy Schubert 	return len;
5744206b73d0SCy Schubert }
5745206b73d0SCy Schubert 
5746206b73d0SCy Schubert 
tls_connection_get_cipher_suite(struct tls_connection * conn)5747206b73d0SCy Schubert u16 tls_connection_get_cipher_suite(struct tls_connection *conn)
5748206b73d0SCy Schubert {
5749206b73d0SCy Schubert 	const SSL_CIPHER *cipher;
5750206b73d0SCy Schubert 
5751206b73d0SCy Schubert 	cipher = SSL_get_current_cipher(conn->ssl);
5752206b73d0SCy Schubert 	if (!cipher)
5753206b73d0SCy Schubert 		return 0;
5754206b73d0SCy Schubert #if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined(LIBRESSL_VERSION_NUMBER)
5755206b73d0SCy Schubert 	return SSL_CIPHER_get_protocol_id(cipher);
5756206b73d0SCy Schubert #else
5757206b73d0SCy Schubert 	return SSL_CIPHER_get_id(cipher) & 0xFFFF;
5758206b73d0SCy Schubert #endif
5759206b73d0SCy Schubert }
5760c1d255d3SCy Schubert 
5761c1d255d3SCy Schubert 
tls_connection_get_peer_subject(struct tls_connection * conn)5762c1d255d3SCy Schubert const char * tls_connection_get_peer_subject(struct tls_connection *conn)
5763c1d255d3SCy Schubert {
5764c1d255d3SCy Schubert 	if (conn)
5765c1d255d3SCy Schubert 		return conn->peer_subject;
5766c1d255d3SCy Schubert 	return NULL;
5767c1d255d3SCy Schubert }
5768c1d255d3SCy Schubert 
5769c1d255d3SCy Schubert 
tls_connection_get_own_cert_used(struct tls_connection * conn)5770c1d255d3SCy Schubert bool tls_connection_get_own_cert_used(struct tls_connection *conn)
5771c1d255d3SCy Schubert {
5772c1d255d3SCy Schubert 	if (conn)
5773c1d255d3SCy Schubert 		return SSL_get_certificate(conn->ssl) != NULL;
5774c1d255d3SCy Schubert 	return false;
5775c1d255d3SCy Schubert }
5776