1e5b75505Sopenharmony_ci/*
2e5b75505Sopenharmony_ci * SSL/TLS interface functions for OpenSSL
3e5b75505Sopenharmony_ci * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
4e5b75505Sopenharmony_ci *
5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license.
6e5b75505Sopenharmony_ci * See README for more details.
7e5b75505Sopenharmony_ci */
8e5b75505Sopenharmony_ci
9e5b75505Sopenharmony_ci#include "includes.h"
10e5b75505Sopenharmony_ci
11e5b75505Sopenharmony_ci#ifndef CONFIG_SMARTCARD
12e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
13e5b75505Sopenharmony_ci#ifndef ANDROID
14e5b75505Sopenharmony_ci#define OPENSSL_NO_ENGINE
15e5b75505Sopenharmony_ci#endif
16e5b75505Sopenharmony_ci#endif
17e5b75505Sopenharmony_ci#endif
18e5b75505Sopenharmony_ci
19e5b75505Sopenharmony_ci#include <openssl/ssl.h>
20e5b75505Sopenharmony_ci#include <openssl/err.h>
21e5b75505Sopenharmony_ci#include <openssl/opensslv.h>
22e5b75505Sopenharmony_ci#include <openssl/pkcs12.h>
23e5b75505Sopenharmony_ci#include <openssl/x509v3.h>
24e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
25e5b75505Sopenharmony_ci#include <openssl/engine.h>
26e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_ENGINE */
27e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_DSA
28e5b75505Sopenharmony_ci#include <openssl/dsa.h>
29e5b75505Sopenharmony_ci#endif
30e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_DH
31e5b75505Sopenharmony_ci#include <openssl/dh.h>
32e5b75505Sopenharmony_ci#endif
33e5b75505Sopenharmony_ci
34e5b75505Sopenharmony_ci#include "common.h"
35e5b75505Sopenharmony_ci#include "crypto.h"
36e5b75505Sopenharmony_ci#include "sha1.h"
37e5b75505Sopenharmony_ci#include "sha256.h"
38e5b75505Sopenharmony_ci#include "tls.h"
39e5b75505Sopenharmony_ci#include "tls_openssl.h"
40e5b75505Sopenharmony_ci
41e5b75505Sopenharmony_ci#if !defined(CONFIG_FIPS) &&                             \
42e5b75505Sopenharmony_ci    (defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) ||   \
43e5b75505Sopenharmony_ci     defined(EAP_SERVER_FAST))
44e5b75505Sopenharmony_ci#define OPENSSL_NEED_EAP_FAST_PRF
45e5b75505Sopenharmony_ci#endif
46e5b75505Sopenharmony_ci
47e5b75505Sopenharmony_ci#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || \
48e5b75505Sopenharmony_ci	defined(EAP_SERVER_FAST) || defined(EAP_TEAP) || \
49e5b75505Sopenharmony_ci	defined(EAP_SERVER_TEAP)
50e5b75505Sopenharmony_ci#define EAP_FAST_OR_TEAP
51e5b75505Sopenharmony_ci#endif
52e5b75505Sopenharmony_ci
53e5b75505Sopenharmony_ci
54e5b75505Sopenharmony_ci#if defined(OPENSSL_IS_BORINGSSL)
55e5b75505Sopenharmony_ci/* stack_index_t is the return type of OpenSSL's sk_XXX_num() functions. */
56e5b75505Sopenharmony_citypedef size_t stack_index_t;
57e5b75505Sopenharmony_ci#else
58e5b75505Sopenharmony_citypedef int stack_index_t;
59e5b75505Sopenharmony_ci#endif
60e5b75505Sopenharmony_ci
61e5b75505Sopenharmony_ci#ifdef SSL_set_tlsext_status_type
62e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_TLSEXT
63e5b75505Sopenharmony_ci#define HAVE_OCSP
64e5b75505Sopenharmony_ci#include <openssl/ocsp.h>
65e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_TLSEXT */
66e5b75505Sopenharmony_ci#endif /* SSL_set_tlsext_status_type */
67e5b75505Sopenharmony_ci
68e5b75505Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER < 0x10100000L || \
69e5b75505Sopenharmony_ci     (defined(LIBRESSL_VERSION_NUMBER) && \
70e5b75505Sopenharmony_ci      LIBRESSL_VERSION_NUMBER < 0x20700000L)) && \
71e5b75505Sopenharmony_ci    !defined(BORINGSSL_API_VERSION)
72e5b75505Sopenharmony_ci/*
73e5b75505Sopenharmony_ci * SSL_get_client_random() and SSL_get_server_random() were added in OpenSSL
74e5b75505Sopenharmony_ci * 1.1.0 and newer BoringSSL revisions. Provide compatibility wrappers for
75e5b75505Sopenharmony_ci * older versions.
76e5b75505Sopenharmony_ci */
77e5b75505Sopenharmony_ci
78e5b75505Sopenharmony_cistatic size_t SSL_get_client_random(const SSL *ssl, unsigned char *out,
79e5b75505Sopenharmony_ci				    size_t outlen)
80e5b75505Sopenharmony_ci{
81e5b75505Sopenharmony_ci	if (!ssl->s3 || outlen < SSL3_RANDOM_SIZE)
82e5b75505Sopenharmony_ci		return 0;
83e5b75505Sopenharmony_ci	os_memcpy(out, ssl->s3->client_random, SSL3_RANDOM_SIZE);
84e5b75505Sopenharmony_ci	return SSL3_RANDOM_SIZE;
85e5b75505Sopenharmony_ci}
86e5b75505Sopenharmony_ci
87e5b75505Sopenharmony_ci
88e5b75505Sopenharmony_cistatic size_t SSL_get_server_random(const SSL *ssl, unsigned char *out,
89e5b75505Sopenharmony_ci				    size_t outlen)
90e5b75505Sopenharmony_ci{
91e5b75505Sopenharmony_ci	if (!ssl->s3 || outlen < SSL3_RANDOM_SIZE)
92e5b75505Sopenharmony_ci		return 0;
93e5b75505Sopenharmony_ci	os_memcpy(out, ssl->s3->server_random, SSL3_RANDOM_SIZE);
94e5b75505Sopenharmony_ci	return SSL3_RANDOM_SIZE;
95e5b75505Sopenharmony_ci}
96e5b75505Sopenharmony_ci
97e5b75505Sopenharmony_ci
98e5b75505Sopenharmony_ci#ifdef OPENSSL_NEED_EAP_FAST_PRF
99e5b75505Sopenharmony_cistatic size_t SSL_SESSION_get_master_key(const SSL_SESSION *session,
100e5b75505Sopenharmony_ci					 unsigned char *out, size_t outlen)
101e5b75505Sopenharmony_ci{
102e5b75505Sopenharmony_ci	if (!session || session->master_key_length < 0 ||
103e5b75505Sopenharmony_ci	    (size_t) session->master_key_length > outlen)
104e5b75505Sopenharmony_ci		return 0;
105e5b75505Sopenharmony_ci	if ((size_t) session->master_key_length < outlen)
106e5b75505Sopenharmony_ci		outlen = session->master_key_length;
107e5b75505Sopenharmony_ci	os_memcpy(out, session->master_key, outlen);
108e5b75505Sopenharmony_ci	return outlen;
109e5b75505Sopenharmony_ci}
110e5b75505Sopenharmony_ci#endif /* OPENSSL_NEED_EAP_FAST_PRF */
111e5b75505Sopenharmony_ci
112e5b75505Sopenharmony_ci#endif
113e5b75505Sopenharmony_ci
114e5b75505Sopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
115e5b75505Sopenharmony_ci	(defined(LIBRESSL_VERSION_NUMBER) && \
116e5b75505Sopenharmony_ci	 LIBRESSL_VERSION_NUMBER < 0x20700000L)
117e5b75505Sopenharmony_ci#ifdef CONFIG_SUITEB
118e5b75505Sopenharmony_cistatic int RSA_bits(const RSA *r)
119e5b75505Sopenharmony_ci{
120e5b75505Sopenharmony_ci	return BN_num_bits(r->n);
121e5b75505Sopenharmony_ci}
122e5b75505Sopenharmony_ci#endif /* CONFIG_SUITEB */
123e5b75505Sopenharmony_ci
124e5b75505Sopenharmony_ci
125e5b75505Sopenharmony_cistatic const unsigned char * ASN1_STRING_get0_data(const ASN1_STRING *x)
126e5b75505Sopenharmony_ci{
127e5b75505Sopenharmony_ci	return ASN1_STRING_data((ASN1_STRING *) x);
128e5b75505Sopenharmony_ci}
129e5b75505Sopenharmony_ci#endif
130e5b75505Sopenharmony_ci
131e5b75505Sopenharmony_ci#ifdef ANDROID
132e5b75505Sopenharmony_ci#include <openssl/pem.h>
133e5b75505Sopenharmony_ci#include <keystore/keystore_get.h>
134e5b75505Sopenharmony_ci
135e5b75505Sopenharmony_cistatic BIO * BIO_from_keystore(const char *key)
136e5b75505Sopenharmony_ci{
137e5b75505Sopenharmony_ci	BIO *bio = NULL;
138e5b75505Sopenharmony_ci	uint8_t *value = NULL;
139e5b75505Sopenharmony_ci	int length = keystore_get(key, strlen(key), &value);
140e5b75505Sopenharmony_ci	if (length != -1 && (bio = BIO_new(BIO_s_mem())) != NULL)
141e5b75505Sopenharmony_ci		BIO_write(bio, value, length);
142e5b75505Sopenharmony_ci	free(value);
143e5b75505Sopenharmony_ci	return bio;
144e5b75505Sopenharmony_ci}
145e5b75505Sopenharmony_ci
146e5b75505Sopenharmony_ci
147e5b75505Sopenharmony_cistatic int tls_add_ca_from_keystore(X509_STORE *ctx, const char *key_alias)
148e5b75505Sopenharmony_ci{
149e5b75505Sopenharmony_ci	BIO *bio = BIO_from_keystore(key_alias);
150e5b75505Sopenharmony_ci	STACK_OF(X509_INFO) *stack = NULL;
151e5b75505Sopenharmony_ci	stack_index_t i;
152e5b75505Sopenharmony_ci
153e5b75505Sopenharmony_ci	if (bio) {
154e5b75505Sopenharmony_ci		stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
155e5b75505Sopenharmony_ci		BIO_free(bio);
156e5b75505Sopenharmony_ci	}
157e5b75505Sopenharmony_ci
158e5b75505Sopenharmony_ci	if (!stack) {
159e5b75505Sopenharmony_ci		wpa_printf(MSG_WARNING, "TLS: Failed to parse certificate: %s",
160e5b75505Sopenharmony_ci			   key_alias);
161e5b75505Sopenharmony_ci		return -1;
162e5b75505Sopenharmony_ci	}
163e5b75505Sopenharmony_ci
164e5b75505Sopenharmony_ci	for (i = 0; i < sk_X509_INFO_num(stack); ++i) {
165e5b75505Sopenharmony_ci		X509_INFO *info = sk_X509_INFO_value(stack, i);
166e5b75505Sopenharmony_ci
167e5b75505Sopenharmony_ci		if (info->x509)
168e5b75505Sopenharmony_ci			X509_STORE_add_cert(ctx, info->x509);
169e5b75505Sopenharmony_ci		if (info->crl)
170e5b75505Sopenharmony_ci			X509_STORE_add_crl(ctx, info->crl);
171e5b75505Sopenharmony_ci	}
172e5b75505Sopenharmony_ci
173e5b75505Sopenharmony_ci	sk_X509_INFO_pop_free(stack, X509_INFO_free);
174e5b75505Sopenharmony_ci
175e5b75505Sopenharmony_ci	return 0;
176e5b75505Sopenharmony_ci}
177e5b75505Sopenharmony_ci
178e5b75505Sopenharmony_ci
179e5b75505Sopenharmony_cistatic int tls_add_ca_from_keystore_encoded(X509_STORE *ctx,
180e5b75505Sopenharmony_ci					    const char *encoded_key_alias)
181e5b75505Sopenharmony_ci{
182e5b75505Sopenharmony_ci	int rc = -1;
183e5b75505Sopenharmony_ci	int len = os_strlen(encoded_key_alias);
184e5b75505Sopenharmony_ci	unsigned char *decoded_alias;
185e5b75505Sopenharmony_ci
186e5b75505Sopenharmony_ci	if (len & 1) {
187e5b75505Sopenharmony_ci		wpa_printf(MSG_WARNING, "Invalid hex-encoded alias: %s",
188e5b75505Sopenharmony_ci			   encoded_key_alias);
189e5b75505Sopenharmony_ci		return rc;
190e5b75505Sopenharmony_ci	}
191e5b75505Sopenharmony_ci
192e5b75505Sopenharmony_ci	decoded_alias = os_malloc(len / 2 + 1);
193e5b75505Sopenharmony_ci	if (decoded_alias) {
194e5b75505Sopenharmony_ci		if (!hexstr2bin(encoded_key_alias, decoded_alias, len / 2)) {
195e5b75505Sopenharmony_ci			decoded_alias[len / 2] = '\0';
196e5b75505Sopenharmony_ci			rc = tls_add_ca_from_keystore(
197e5b75505Sopenharmony_ci				ctx, (const char *) decoded_alias);
198e5b75505Sopenharmony_ci		}
199e5b75505Sopenharmony_ci		os_free(decoded_alias);
200e5b75505Sopenharmony_ci	}
201e5b75505Sopenharmony_ci
202e5b75505Sopenharmony_ci	return rc;
203e5b75505Sopenharmony_ci}
204e5b75505Sopenharmony_ci
205e5b75505Sopenharmony_ci#endif /* ANDROID */
206e5b75505Sopenharmony_ci
207e5b75505Sopenharmony_cistatic int tls_openssl_ref_count = 0;
208e5b75505Sopenharmony_cistatic int tls_ex_idx_session = -1;
209e5b75505Sopenharmony_ci
210e5b75505Sopenharmony_cistruct tls_context {
211e5b75505Sopenharmony_ci	void (*event_cb)(void *ctx, enum tls_event ev,
212e5b75505Sopenharmony_ci			 union tls_event_data *data);
213e5b75505Sopenharmony_ci	void *cb_ctx;
214e5b75505Sopenharmony_ci	int cert_in_cb;
215e5b75505Sopenharmony_ci	char *ocsp_stapling_response;
216e5b75505Sopenharmony_ci};
217e5b75505Sopenharmony_ci
218e5b75505Sopenharmony_cistatic struct tls_context *tls_global = NULL;
219e5b75505Sopenharmony_ci
220e5b75505Sopenharmony_ci
221e5b75505Sopenharmony_cistruct tls_data {
222e5b75505Sopenharmony_ci	SSL_CTX *ssl;
223e5b75505Sopenharmony_ci	unsigned int tls_session_lifetime;
224e5b75505Sopenharmony_ci	int check_crl;
225e5b75505Sopenharmony_ci	int check_crl_strict;
226e5b75505Sopenharmony_ci	char *ca_cert;
227e5b75505Sopenharmony_ci	unsigned int crl_reload_interval;
228e5b75505Sopenharmony_ci	struct os_reltime crl_last_reload;
229e5b75505Sopenharmony_ci	char *check_cert_subject;
230e5b75505Sopenharmony_ci};
231e5b75505Sopenharmony_ci
232e5b75505Sopenharmony_cistruct tls_connection {
233e5b75505Sopenharmony_ci	struct tls_context *context;
234e5b75505Sopenharmony_ci	struct tls_data *data;
235e5b75505Sopenharmony_ci	SSL_CTX *ssl_ctx;
236e5b75505Sopenharmony_ci	SSL *ssl;
237e5b75505Sopenharmony_ci	BIO *ssl_in, *ssl_out;
238e5b75505Sopenharmony_ci#if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE)
239e5b75505Sopenharmony_ci	ENGINE *engine;        /* functional reference to the engine */
240e5b75505Sopenharmony_ci	EVP_PKEY *private_key; /* the private key if using engine */
241e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_ENGINE */
242e5b75505Sopenharmony_ci	char *subject_match, *altsubject_match, *suffix_match, *domain_match;
243e5b75505Sopenharmony_ci	char *check_cert_subject;
244e5b75505Sopenharmony_ci	int read_alerts, write_alerts, failed;
245e5b75505Sopenharmony_ci
246e5b75505Sopenharmony_ci	tls_session_ticket_cb session_ticket_cb;
247e5b75505Sopenharmony_ci	void *session_ticket_cb_ctx;
248e5b75505Sopenharmony_ci
249e5b75505Sopenharmony_ci	/* SessionTicket received from OpenSSL hello_extension_cb (server) */
250e5b75505Sopenharmony_ci	u8 *session_ticket;
251e5b75505Sopenharmony_ci	size_t session_ticket_len;
252e5b75505Sopenharmony_ci
253e5b75505Sopenharmony_ci	unsigned int ca_cert_verify:1;
254e5b75505Sopenharmony_ci	unsigned int cert_probe:1;
255e5b75505Sopenharmony_ci	unsigned int server_cert_only:1;
256e5b75505Sopenharmony_ci	unsigned int invalid_hb_used:1;
257e5b75505Sopenharmony_ci	unsigned int success_data:1;
258e5b75505Sopenharmony_ci	unsigned int client_hello_generated:1;
259e5b75505Sopenharmony_ci	unsigned int server:1;
260e5b75505Sopenharmony_ci
261e5b75505Sopenharmony_ci	u8 srv_cert_hash[32];
262e5b75505Sopenharmony_ci
263e5b75505Sopenharmony_ci	unsigned int flags;
264e5b75505Sopenharmony_ci
265e5b75505Sopenharmony_ci	X509 *peer_cert;
266e5b75505Sopenharmony_ci	X509 *peer_issuer;
267e5b75505Sopenharmony_ci	X509 *peer_issuer_issuer;
268e5b75505Sopenharmony_ci
269e5b75505Sopenharmony_ci	unsigned char client_random[SSL3_RANDOM_SIZE];
270e5b75505Sopenharmony_ci	unsigned char server_random[SSL3_RANDOM_SIZE];
271e5b75505Sopenharmony_ci
272e5b75505Sopenharmony_ci	u16 cipher_suite;
273e5b75505Sopenharmony_ci	int server_dh_prime_len;
274e5b75505Sopenharmony_ci};
275e5b75505Sopenharmony_ci
276e5b75505Sopenharmony_ci
277e5b75505Sopenharmony_cistatic struct tls_context * tls_context_new(const struct tls_config *conf)
278e5b75505Sopenharmony_ci{
279e5b75505Sopenharmony_ci	struct tls_context *context = os_zalloc(sizeof(*context));
280e5b75505Sopenharmony_ci	if (context == NULL)
281e5b75505Sopenharmony_ci		return NULL;
282e5b75505Sopenharmony_ci	if (conf) {
283e5b75505Sopenharmony_ci		context->event_cb = conf->event_cb;
284e5b75505Sopenharmony_ci		context->cb_ctx = conf->cb_ctx;
285e5b75505Sopenharmony_ci		context->cert_in_cb = conf->cert_in_cb;
286e5b75505Sopenharmony_ci	}
287e5b75505Sopenharmony_ci	return context;
288e5b75505Sopenharmony_ci}
289e5b75505Sopenharmony_ci
290e5b75505Sopenharmony_ci
291e5b75505Sopenharmony_ci#ifdef CONFIG_NO_STDOUT_DEBUG
292e5b75505Sopenharmony_ci
293e5b75505Sopenharmony_cistatic void _tls_show_errors(void)
294e5b75505Sopenharmony_ci{
295e5b75505Sopenharmony_ci	unsigned long err;
296e5b75505Sopenharmony_ci
297e5b75505Sopenharmony_ci	while ((err = ERR_get_error())) {
298e5b75505Sopenharmony_ci		/* Just ignore the errors, since stdout is disabled */
299e5b75505Sopenharmony_ci	}
300e5b75505Sopenharmony_ci}
301e5b75505Sopenharmony_ci#define tls_show_errors(l, f, t) _tls_show_errors()
302e5b75505Sopenharmony_ci
303e5b75505Sopenharmony_ci#else /* CONFIG_NO_STDOUT_DEBUG */
304e5b75505Sopenharmony_ci
305e5b75505Sopenharmony_cistatic void tls_show_errors(int level, const char *func, const char *txt)
306e5b75505Sopenharmony_ci{
307e5b75505Sopenharmony_ci	unsigned long err;
308e5b75505Sopenharmony_ci
309e5b75505Sopenharmony_ci	wpa_printf(level, "OpenSSL: %s - %s %s",
310e5b75505Sopenharmony_ci		   func, txt, ERR_error_string(ERR_get_error(), NULL));
311e5b75505Sopenharmony_ci
312e5b75505Sopenharmony_ci	while ((err = ERR_get_error())) {
313e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "OpenSSL: pending error: %s",
314e5b75505Sopenharmony_ci			   ERR_error_string(err, NULL));
315e5b75505Sopenharmony_ci	}
316e5b75505Sopenharmony_ci}
317e5b75505Sopenharmony_ci
318e5b75505Sopenharmony_ci#endif /* CONFIG_NO_STDOUT_DEBUG */
319e5b75505Sopenharmony_ci
320e5b75505Sopenharmony_ci
321e5b75505Sopenharmony_cistatic X509_STORE * tls_crl_cert_reload(const char *ca_cert, int check_crl)
322e5b75505Sopenharmony_ci{
323e5b75505Sopenharmony_ci	int flags;
324e5b75505Sopenharmony_ci	X509_STORE *store;
325e5b75505Sopenharmony_ci
326e5b75505Sopenharmony_ci	store = X509_STORE_new();
327e5b75505Sopenharmony_ci	if (!store) {
328e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
329e5b75505Sopenharmony_ci			   "OpenSSL: %s - failed to allocate new certificate store",
330e5b75505Sopenharmony_ci			   __func__);
331e5b75505Sopenharmony_ci		return NULL;
332e5b75505Sopenharmony_ci	}
333e5b75505Sopenharmony_ci
334e5b75505Sopenharmony_ci	if (ca_cert && X509_STORE_load_locations(store, ca_cert, NULL) != 1) {
335e5b75505Sopenharmony_ci		tls_show_errors(MSG_WARNING, __func__,
336e5b75505Sopenharmony_ci				"Failed to load root certificates");
337e5b75505Sopenharmony_ci		X509_STORE_free(store);
338e5b75505Sopenharmony_ci		return NULL;
339e5b75505Sopenharmony_ci	}
340e5b75505Sopenharmony_ci
341e5b75505Sopenharmony_ci	flags = check_crl ? X509_V_FLAG_CRL_CHECK : 0;
342e5b75505Sopenharmony_ci	if (check_crl == 2)
343e5b75505Sopenharmony_ci		flags |= X509_V_FLAG_CRL_CHECK_ALL;
344e5b75505Sopenharmony_ci
345e5b75505Sopenharmony_ci	X509_STORE_set_flags(store, flags);
346e5b75505Sopenharmony_ci
347e5b75505Sopenharmony_ci	return store;
348e5b75505Sopenharmony_ci}
349e5b75505Sopenharmony_ci
350e5b75505Sopenharmony_ci
351e5b75505Sopenharmony_ci#ifdef CONFIG_NATIVE_WINDOWS
352e5b75505Sopenharmony_ci
353e5b75505Sopenharmony_ci/* Windows CryptoAPI and access to certificate stores */
354e5b75505Sopenharmony_ci#include <wincrypt.h>
355e5b75505Sopenharmony_ci
356e5b75505Sopenharmony_ci#ifdef __MINGW32_VERSION
357e5b75505Sopenharmony_ci/*
358e5b75505Sopenharmony_ci * MinGW does not yet include all the needed definitions for CryptoAPI, so
359e5b75505Sopenharmony_ci * define here whatever extra is needed.
360e5b75505Sopenharmony_ci */
361e5b75505Sopenharmony_ci#define CERT_SYSTEM_STORE_CURRENT_USER (1 << 16)
362e5b75505Sopenharmony_ci#define CERT_STORE_READONLY_FLAG 0x00008000
363e5b75505Sopenharmony_ci#define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000
364e5b75505Sopenharmony_ci
365e5b75505Sopenharmony_ci#endif /* __MINGW32_VERSION */
366e5b75505Sopenharmony_ci
367e5b75505Sopenharmony_ci
368e5b75505Sopenharmony_cistruct cryptoapi_rsa_data {
369e5b75505Sopenharmony_ci	const CERT_CONTEXT *cert;
370e5b75505Sopenharmony_ci	HCRYPTPROV crypt_prov;
371e5b75505Sopenharmony_ci	DWORD key_spec;
372e5b75505Sopenharmony_ci	BOOL free_crypt_prov;
373e5b75505Sopenharmony_ci};
374e5b75505Sopenharmony_ci
375e5b75505Sopenharmony_ci
376e5b75505Sopenharmony_cistatic void cryptoapi_error(const char *msg)
377e5b75505Sopenharmony_ci{
378e5b75505Sopenharmony_ci	wpa_printf(MSG_INFO, "CryptoAPI: %s; err=%u",
379e5b75505Sopenharmony_ci		   msg, (unsigned int) GetLastError());
380e5b75505Sopenharmony_ci}
381e5b75505Sopenharmony_ci
382e5b75505Sopenharmony_ci
383e5b75505Sopenharmony_cistatic int cryptoapi_rsa_pub_enc(int flen, const unsigned char *from,
384e5b75505Sopenharmony_ci				 unsigned char *to, RSA *rsa, int padding)
385e5b75505Sopenharmony_ci{
386e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);
387e5b75505Sopenharmony_ci	return 0;
388e5b75505Sopenharmony_ci}
389e5b75505Sopenharmony_ci
390e5b75505Sopenharmony_ci
391e5b75505Sopenharmony_cistatic int cryptoapi_rsa_pub_dec(int flen, const unsigned char *from,
392e5b75505Sopenharmony_ci				 unsigned char *to, RSA *rsa, int padding)
393e5b75505Sopenharmony_ci{
394e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);
395e5b75505Sopenharmony_ci	return 0;
396e5b75505Sopenharmony_ci}
397e5b75505Sopenharmony_ci
398e5b75505Sopenharmony_ci
399e5b75505Sopenharmony_cistatic int cryptoapi_rsa_priv_enc(int flen, const unsigned char *from,
400e5b75505Sopenharmony_ci				  unsigned char *to, RSA *rsa, int padding)
401e5b75505Sopenharmony_ci{
402e5b75505Sopenharmony_ci	struct cryptoapi_rsa_data *priv =
403e5b75505Sopenharmony_ci		(struct cryptoapi_rsa_data *) rsa->meth->app_data;
404e5b75505Sopenharmony_ci	HCRYPTHASH hash;
405e5b75505Sopenharmony_ci	DWORD hash_size, len, i;
406e5b75505Sopenharmony_ci	unsigned char *buf = NULL;
407e5b75505Sopenharmony_ci	int ret = 0;
408e5b75505Sopenharmony_ci
409e5b75505Sopenharmony_ci	if (priv == NULL) {
410e5b75505Sopenharmony_ci		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
411e5b75505Sopenharmony_ci		       ERR_R_PASSED_NULL_PARAMETER);
412e5b75505Sopenharmony_ci		return 0;
413e5b75505Sopenharmony_ci	}
414e5b75505Sopenharmony_ci
415e5b75505Sopenharmony_ci	if (padding != RSA_PKCS1_PADDING) {
416e5b75505Sopenharmony_ci		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
417e5b75505Sopenharmony_ci		       RSA_R_UNKNOWN_PADDING_TYPE);
418e5b75505Sopenharmony_ci		return 0;
419e5b75505Sopenharmony_ci	}
420e5b75505Sopenharmony_ci
421e5b75505Sopenharmony_ci	if (flen != 16 /* MD5 */ + 20 /* SHA-1 */) {
422e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "%s - only MD5-SHA1 hash supported",
423e5b75505Sopenharmony_ci			   __func__);
424e5b75505Sopenharmony_ci		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
425e5b75505Sopenharmony_ci		       RSA_R_INVALID_MESSAGE_LENGTH);
426e5b75505Sopenharmony_ci		return 0;
427e5b75505Sopenharmony_ci	}
428e5b75505Sopenharmony_ci
429e5b75505Sopenharmony_ci	if (!CryptCreateHash(priv->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash))
430e5b75505Sopenharmony_ci	{
431e5b75505Sopenharmony_ci		cryptoapi_error("CryptCreateHash failed");
432e5b75505Sopenharmony_ci		return 0;
433e5b75505Sopenharmony_ci	}
434e5b75505Sopenharmony_ci
435e5b75505Sopenharmony_ci	len = sizeof(hash_size);
436e5b75505Sopenharmony_ci	if (!CryptGetHashParam(hash, HP_HASHSIZE, (BYTE *) &hash_size, &len,
437e5b75505Sopenharmony_ci			       0)) {
438e5b75505Sopenharmony_ci		cryptoapi_error("CryptGetHashParam failed");
439e5b75505Sopenharmony_ci		goto err;
440e5b75505Sopenharmony_ci	}
441e5b75505Sopenharmony_ci
442e5b75505Sopenharmony_ci	if ((int) hash_size != flen) {
443e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "CryptoAPI: Invalid hash size (%u != %d)",
444e5b75505Sopenharmony_ci			   (unsigned) hash_size, flen);
445e5b75505Sopenharmony_ci		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
446e5b75505Sopenharmony_ci		       RSA_R_INVALID_MESSAGE_LENGTH);
447e5b75505Sopenharmony_ci		goto err;
448e5b75505Sopenharmony_ci	}
449e5b75505Sopenharmony_ci	if (!CryptSetHashParam(hash, HP_HASHVAL, (BYTE * ) from, 0)) {
450e5b75505Sopenharmony_ci		cryptoapi_error("CryptSetHashParam failed");
451e5b75505Sopenharmony_ci		goto err;
452e5b75505Sopenharmony_ci	}
453e5b75505Sopenharmony_ci
454e5b75505Sopenharmony_ci	len = RSA_size(rsa);
455e5b75505Sopenharmony_ci	buf = os_malloc(len);
456e5b75505Sopenharmony_ci	if (buf == NULL) {
457e5b75505Sopenharmony_ci		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
458e5b75505Sopenharmony_ci		goto err;
459e5b75505Sopenharmony_ci	}
460e5b75505Sopenharmony_ci
461e5b75505Sopenharmony_ci	if (!CryptSignHash(hash, priv->key_spec, NULL, 0, buf, &len)) {
462e5b75505Sopenharmony_ci		cryptoapi_error("CryptSignHash failed");
463e5b75505Sopenharmony_ci		goto err;
464e5b75505Sopenharmony_ci	}
465e5b75505Sopenharmony_ci
466e5b75505Sopenharmony_ci	for (i = 0; i < len; i++)
467e5b75505Sopenharmony_ci		to[i] = buf[len - i - 1];
468e5b75505Sopenharmony_ci	ret = len;
469e5b75505Sopenharmony_ci
470e5b75505Sopenharmony_cierr:
471e5b75505Sopenharmony_ci	os_free(buf);
472e5b75505Sopenharmony_ci	CryptDestroyHash(hash);
473e5b75505Sopenharmony_ci
474e5b75505Sopenharmony_ci	return ret;
475e5b75505Sopenharmony_ci}
476e5b75505Sopenharmony_ci
477e5b75505Sopenharmony_ci
478e5b75505Sopenharmony_cistatic int cryptoapi_rsa_priv_dec(int flen, const unsigned char *from,
479e5b75505Sopenharmony_ci				  unsigned char *to, RSA *rsa, int padding)
480e5b75505Sopenharmony_ci{
481e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);
482e5b75505Sopenharmony_ci	return 0;
483e5b75505Sopenharmony_ci}
484e5b75505Sopenharmony_ci
485e5b75505Sopenharmony_ci
486e5b75505Sopenharmony_cistatic void cryptoapi_free_data(struct cryptoapi_rsa_data *priv)
487e5b75505Sopenharmony_ci{
488e5b75505Sopenharmony_ci	if (priv == NULL)
489e5b75505Sopenharmony_ci		return;
490e5b75505Sopenharmony_ci	if (priv->crypt_prov && priv->free_crypt_prov)
491e5b75505Sopenharmony_ci		CryptReleaseContext(priv->crypt_prov, 0);
492e5b75505Sopenharmony_ci	if (priv->cert)
493e5b75505Sopenharmony_ci		CertFreeCertificateContext(priv->cert);
494e5b75505Sopenharmony_ci	os_free(priv);
495e5b75505Sopenharmony_ci}
496e5b75505Sopenharmony_ci
497e5b75505Sopenharmony_ci
498e5b75505Sopenharmony_cistatic int cryptoapi_finish(RSA *rsa)
499e5b75505Sopenharmony_ci{
500e5b75505Sopenharmony_ci	cryptoapi_free_data((struct cryptoapi_rsa_data *) rsa->meth->app_data);
501e5b75505Sopenharmony_ci	os_free((void *) rsa->meth);
502e5b75505Sopenharmony_ci	rsa->meth = NULL;
503e5b75505Sopenharmony_ci	return 1;
504e5b75505Sopenharmony_ci}
505e5b75505Sopenharmony_ci
506e5b75505Sopenharmony_ci
507e5b75505Sopenharmony_cistatic const CERT_CONTEXT * cryptoapi_find_cert(const char *name, DWORD store)
508e5b75505Sopenharmony_ci{
509e5b75505Sopenharmony_ci	HCERTSTORE cs;
510e5b75505Sopenharmony_ci	const CERT_CONTEXT *ret = NULL;
511e5b75505Sopenharmony_ci
512e5b75505Sopenharmony_ci	cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0,
513e5b75505Sopenharmony_ci			   store | CERT_STORE_OPEN_EXISTING_FLAG |
514e5b75505Sopenharmony_ci			   CERT_STORE_READONLY_FLAG, L"MY");
515e5b75505Sopenharmony_ci	if (cs == NULL) {
516e5b75505Sopenharmony_ci		cryptoapi_error("Failed to open 'My system store'");
517e5b75505Sopenharmony_ci		return NULL;
518e5b75505Sopenharmony_ci	}
519e5b75505Sopenharmony_ci
520e5b75505Sopenharmony_ci	if (strncmp(name, "cert://", 7) == 0) {
521e5b75505Sopenharmony_ci		unsigned short wbuf[255];
522e5b75505Sopenharmony_ci		MultiByteToWideChar(CP_ACP, 0, name + 7, -1, wbuf, 255);
523e5b75505Sopenharmony_ci		ret = CertFindCertificateInStore(cs, X509_ASN_ENCODING |
524e5b75505Sopenharmony_ci						 PKCS_7_ASN_ENCODING,
525e5b75505Sopenharmony_ci						 0, CERT_FIND_SUBJECT_STR,
526e5b75505Sopenharmony_ci						 wbuf, NULL);
527e5b75505Sopenharmony_ci	} else if (strncmp(name, "hash://", 7) == 0) {
528e5b75505Sopenharmony_ci		CRYPT_HASH_BLOB blob;
529e5b75505Sopenharmony_ci		int len;
530e5b75505Sopenharmony_ci		const char *hash = name + 7;
531e5b75505Sopenharmony_ci		unsigned char *buf;
532e5b75505Sopenharmony_ci
533e5b75505Sopenharmony_ci		len = os_strlen(hash) / 2;
534e5b75505Sopenharmony_ci		buf = os_malloc(len);
535e5b75505Sopenharmony_ci		if (buf && hexstr2bin(hash, buf, len) == 0) {
536e5b75505Sopenharmony_ci			blob.cbData = len;
537e5b75505Sopenharmony_ci			blob.pbData = buf;
538e5b75505Sopenharmony_ci			ret = CertFindCertificateInStore(cs,
539e5b75505Sopenharmony_ci							 X509_ASN_ENCODING |
540e5b75505Sopenharmony_ci							 PKCS_7_ASN_ENCODING,
541e5b75505Sopenharmony_ci							 0, CERT_FIND_HASH,
542e5b75505Sopenharmony_ci							 &blob, NULL);
543e5b75505Sopenharmony_ci		}
544e5b75505Sopenharmony_ci		os_free(buf);
545e5b75505Sopenharmony_ci	}
546e5b75505Sopenharmony_ci
547e5b75505Sopenharmony_ci	CertCloseStore(cs, 0);
548e5b75505Sopenharmony_ci
549e5b75505Sopenharmony_ci	return ret;
550e5b75505Sopenharmony_ci}
551e5b75505Sopenharmony_ci
552e5b75505Sopenharmony_ci
553e5b75505Sopenharmony_cistatic int tls_cryptoapi_cert(SSL *ssl, const char *name)
554e5b75505Sopenharmony_ci{
555e5b75505Sopenharmony_ci	X509 *cert = NULL;
556e5b75505Sopenharmony_ci	RSA *rsa = NULL, *pub_rsa;
557e5b75505Sopenharmony_ci	struct cryptoapi_rsa_data *priv;
558e5b75505Sopenharmony_ci	RSA_METHOD *rsa_meth;
559e5b75505Sopenharmony_ci
560e5b75505Sopenharmony_ci	if (name == NULL ||
561e5b75505Sopenharmony_ci	    (strncmp(name, "cert://", 7) != 0 &&
562e5b75505Sopenharmony_ci	     strncmp(name, "hash://", 7) != 0))
563e5b75505Sopenharmony_ci		return -1;
564e5b75505Sopenharmony_ci
565e5b75505Sopenharmony_ci	priv = os_zalloc(sizeof(*priv));
566e5b75505Sopenharmony_ci	rsa_meth = os_zalloc(sizeof(*rsa_meth));
567e5b75505Sopenharmony_ci	if (priv == NULL || rsa_meth == NULL) {
568e5b75505Sopenharmony_ci		wpa_printf(MSG_WARNING, "CryptoAPI: Failed to allocate memory "
569e5b75505Sopenharmony_ci			   "for CryptoAPI RSA method");
570e5b75505Sopenharmony_ci		os_free(priv);
571e5b75505Sopenharmony_ci		os_free(rsa_meth);
572e5b75505Sopenharmony_ci		return -1;
573e5b75505Sopenharmony_ci	}
574e5b75505Sopenharmony_ci
575e5b75505Sopenharmony_ci	priv->cert = cryptoapi_find_cert(name, CERT_SYSTEM_STORE_CURRENT_USER);
576e5b75505Sopenharmony_ci	if (priv->cert == NULL) {
577e5b75505Sopenharmony_ci		priv->cert = cryptoapi_find_cert(
578e5b75505Sopenharmony_ci			name, CERT_SYSTEM_STORE_LOCAL_MACHINE);
579e5b75505Sopenharmony_ci	}
580e5b75505Sopenharmony_ci	if (priv->cert == NULL) {
581e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "CryptoAPI: Could not find certificate "
582e5b75505Sopenharmony_ci			   "'%s'", name);
583e5b75505Sopenharmony_ci		goto err;
584e5b75505Sopenharmony_ci	}
585e5b75505Sopenharmony_ci
586e5b75505Sopenharmony_ci	cert = d2i_X509(NULL,
587e5b75505Sopenharmony_ci			(const unsigned char **) &priv->cert->pbCertEncoded,
588e5b75505Sopenharmony_ci			priv->cert->cbCertEncoded);
589e5b75505Sopenharmony_ci	if (cert == NULL) {
590e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "CryptoAPI: Could not process X509 DER "
591e5b75505Sopenharmony_ci			   "encoding");
592e5b75505Sopenharmony_ci		goto err;
593e5b75505Sopenharmony_ci	}
594e5b75505Sopenharmony_ci
595e5b75505Sopenharmony_ci	if (!CryptAcquireCertificatePrivateKey(priv->cert,
596e5b75505Sopenharmony_ci					       CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
597e5b75505Sopenharmony_ci					       NULL, &priv->crypt_prov,
598e5b75505Sopenharmony_ci					       &priv->key_spec,
599e5b75505Sopenharmony_ci					       &priv->free_crypt_prov)) {
600e5b75505Sopenharmony_ci		cryptoapi_error("Failed to acquire a private key for the "
601e5b75505Sopenharmony_ci				"certificate");
602e5b75505Sopenharmony_ci		goto err;
603e5b75505Sopenharmony_ci	}
604e5b75505Sopenharmony_ci
605e5b75505Sopenharmony_ci	rsa_meth->name = "Microsoft CryptoAPI RSA Method";
606e5b75505Sopenharmony_ci	rsa_meth->rsa_pub_enc = cryptoapi_rsa_pub_enc;
607e5b75505Sopenharmony_ci	rsa_meth->rsa_pub_dec = cryptoapi_rsa_pub_dec;
608e5b75505Sopenharmony_ci	rsa_meth->rsa_priv_enc = cryptoapi_rsa_priv_enc;
609e5b75505Sopenharmony_ci	rsa_meth->rsa_priv_dec = cryptoapi_rsa_priv_dec;
610e5b75505Sopenharmony_ci	rsa_meth->finish = cryptoapi_finish;
611e5b75505Sopenharmony_ci	rsa_meth->flags = RSA_METHOD_FLAG_NO_CHECK;
612e5b75505Sopenharmony_ci	rsa_meth->app_data = (char *) priv;
613e5b75505Sopenharmony_ci
614e5b75505Sopenharmony_ci	rsa = RSA_new();
615e5b75505Sopenharmony_ci	if (rsa == NULL) {
616e5b75505Sopenharmony_ci		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,
617e5b75505Sopenharmony_ci		       ERR_R_MALLOC_FAILURE);
618e5b75505Sopenharmony_ci		goto err;
619e5b75505Sopenharmony_ci	}
620e5b75505Sopenharmony_ci
621e5b75505Sopenharmony_ci	if (!SSL_use_certificate(ssl, cert)) {
622e5b75505Sopenharmony_ci		RSA_free(rsa);
623e5b75505Sopenharmony_ci		rsa = NULL;
624e5b75505Sopenharmony_ci		goto err;
625e5b75505Sopenharmony_ci	}
626e5b75505Sopenharmony_ci	pub_rsa = cert->cert_info->key->pkey->pkey.rsa;
627e5b75505Sopenharmony_ci	X509_free(cert);
628e5b75505Sopenharmony_ci	cert = NULL;
629e5b75505Sopenharmony_ci
630e5b75505Sopenharmony_ci	rsa->n = BN_dup(pub_rsa->n);
631e5b75505Sopenharmony_ci	rsa->e = BN_dup(pub_rsa->e);
632e5b75505Sopenharmony_ci	if (!RSA_set_method(rsa, rsa_meth))
633e5b75505Sopenharmony_ci		goto err;
634e5b75505Sopenharmony_ci
635e5b75505Sopenharmony_ci	if (!SSL_use_RSAPrivateKey(ssl, rsa))
636e5b75505Sopenharmony_ci		goto err;
637e5b75505Sopenharmony_ci	RSA_free(rsa);
638e5b75505Sopenharmony_ci
639e5b75505Sopenharmony_ci	return 0;
640e5b75505Sopenharmony_ci
641e5b75505Sopenharmony_cierr:
642e5b75505Sopenharmony_ci	if (cert)
643e5b75505Sopenharmony_ci		X509_free(cert);
644e5b75505Sopenharmony_ci	if (rsa)
645e5b75505Sopenharmony_ci		RSA_free(rsa);
646e5b75505Sopenharmony_ci	else {
647e5b75505Sopenharmony_ci		os_free(rsa_meth);
648e5b75505Sopenharmony_ci		cryptoapi_free_data(priv);
649e5b75505Sopenharmony_ci	}
650e5b75505Sopenharmony_ci	return -1;
651e5b75505Sopenharmony_ci}
652e5b75505Sopenharmony_ci
653e5b75505Sopenharmony_ci
654e5b75505Sopenharmony_cistatic int tls_cryptoapi_ca_cert(SSL_CTX *ssl_ctx, SSL *ssl, const char *name)
655e5b75505Sopenharmony_ci{
656e5b75505Sopenharmony_ci	HCERTSTORE cs;
657e5b75505Sopenharmony_ci	PCCERT_CONTEXT ctx = NULL;
658e5b75505Sopenharmony_ci	X509 *cert;
659e5b75505Sopenharmony_ci	char buf[128];
660e5b75505Sopenharmony_ci	const char *store;
661e5b75505Sopenharmony_ci#ifdef UNICODE
662e5b75505Sopenharmony_ci	WCHAR *wstore;
663e5b75505Sopenharmony_ci#endif /* UNICODE */
664e5b75505Sopenharmony_ci
665e5b75505Sopenharmony_ci	if (name == NULL || strncmp(name, "cert_store://", 13) != 0)
666e5b75505Sopenharmony_ci		return -1;
667e5b75505Sopenharmony_ci
668e5b75505Sopenharmony_ci	store = name + 13;
669e5b75505Sopenharmony_ci#ifdef UNICODE
670e5b75505Sopenharmony_ci	wstore = os_malloc((os_strlen(store) + 1) * sizeof(WCHAR));
671e5b75505Sopenharmony_ci	if (wstore == NULL)
672e5b75505Sopenharmony_ci		return -1;
673e5b75505Sopenharmony_ci	wsprintf(wstore, L"%S", store);
674e5b75505Sopenharmony_ci	cs = CertOpenSystemStore(0, wstore);
675e5b75505Sopenharmony_ci	os_free(wstore);
676e5b75505Sopenharmony_ci#else /* UNICODE */
677e5b75505Sopenharmony_ci	cs = CertOpenSystemStore(0, store);
678e5b75505Sopenharmony_ci#endif /* UNICODE */
679e5b75505Sopenharmony_ci	if (cs == NULL) {
680e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "%s: failed to open system cert store "
681e5b75505Sopenharmony_ci			   "'%s': error=%d", __func__, store,
682e5b75505Sopenharmony_ci			   (int) GetLastError());
683e5b75505Sopenharmony_ci		return -1;
684e5b75505Sopenharmony_ci	}
685e5b75505Sopenharmony_ci
686e5b75505Sopenharmony_ci	while ((ctx = CertEnumCertificatesInStore(cs, ctx))) {
687e5b75505Sopenharmony_ci		cert = d2i_X509(NULL,
688e5b75505Sopenharmony_ci				(const unsigned char **) &ctx->pbCertEncoded,
689e5b75505Sopenharmony_ci				ctx->cbCertEncoded);
690e5b75505Sopenharmony_ci		if (cert == NULL) {
691e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO, "CryptoAPI: Could not process "
692e5b75505Sopenharmony_ci				   "X509 DER encoding for CA cert");
693e5b75505Sopenharmony_ci			continue;
694e5b75505Sopenharmony_ci		}
695e5b75505Sopenharmony_ci
696e5b75505Sopenharmony_ci		X509_NAME_oneline(X509_get_subject_name(cert), buf,
697e5b75505Sopenharmony_ci				  sizeof(buf));
698e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: Loaded CA certificate for "
699e5b75505Sopenharmony_ci			   "system certificate store: subject='%s'", buf);
700e5b75505Sopenharmony_ci
701e5b75505Sopenharmony_ci		if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(ssl_ctx),
702e5b75505Sopenharmony_ci					 cert)) {
703e5b75505Sopenharmony_ci			tls_show_errors(MSG_WARNING, __func__,
704e5b75505Sopenharmony_ci					"Failed to add ca_cert to OpenSSL "
705e5b75505Sopenharmony_ci					"certificate store");
706e5b75505Sopenharmony_ci		}
707e5b75505Sopenharmony_ci
708e5b75505Sopenharmony_ci		X509_free(cert);
709e5b75505Sopenharmony_ci	}
710e5b75505Sopenharmony_ci
711e5b75505Sopenharmony_ci	if (!CertCloseStore(cs, 0)) {
712e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "%s: failed to close system cert store "
713e5b75505Sopenharmony_ci			   "'%s': error=%d", __func__, name + 13,
714e5b75505Sopenharmony_ci			   (int) GetLastError());
715e5b75505Sopenharmony_ci	}
716e5b75505Sopenharmony_ci
717e5b75505Sopenharmony_ci	return 0;
718e5b75505Sopenharmony_ci}
719e5b75505Sopenharmony_ci
720e5b75505Sopenharmony_ci
721e5b75505Sopenharmony_ci#else /* CONFIG_NATIVE_WINDOWS */
722e5b75505Sopenharmony_ci
723e5b75505Sopenharmony_cistatic int tls_cryptoapi_cert(SSL *ssl, const char *name)
724e5b75505Sopenharmony_ci{
725e5b75505Sopenharmony_ci	return -1;
726e5b75505Sopenharmony_ci}
727e5b75505Sopenharmony_ci
728e5b75505Sopenharmony_ci#endif /* CONFIG_NATIVE_WINDOWS */
729e5b75505Sopenharmony_ci
730e5b75505Sopenharmony_ci
731e5b75505Sopenharmony_cistatic void ssl_info_cb(const SSL *ssl, int where, int ret)
732e5b75505Sopenharmony_ci{
733e5b75505Sopenharmony_ci	const char *str;
734e5b75505Sopenharmony_ci	int w;
735e5b75505Sopenharmony_ci
736e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "SSL: (where=0x%x ret=0x%x)", where, ret);
737e5b75505Sopenharmony_ci	w = where & ~SSL_ST_MASK;
738e5b75505Sopenharmony_ci	if (w & SSL_ST_CONNECT)
739e5b75505Sopenharmony_ci		str = "SSL_connect";
740e5b75505Sopenharmony_ci	else if (w & SSL_ST_ACCEPT)
741e5b75505Sopenharmony_ci		str = "SSL_accept";
742e5b75505Sopenharmony_ci	else
743e5b75505Sopenharmony_ci		str = "undefined";
744e5b75505Sopenharmony_ci
745e5b75505Sopenharmony_ci	if (where & SSL_CB_LOOP) {
746e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "SSL: %s:%s",
747e5b75505Sopenharmony_ci			   str, SSL_state_string_long(ssl));
748e5b75505Sopenharmony_ci	} else if (where & SSL_CB_ALERT) {
749e5b75505Sopenharmony_ci		struct tls_connection *conn = SSL_get_app_data((SSL *) ssl);
750e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "SSL: SSL3 alert: %s:%s:%s",
751e5b75505Sopenharmony_ci			   where & SSL_CB_READ ?
752e5b75505Sopenharmony_ci			   "read (remote end reported an error)" :
753e5b75505Sopenharmony_ci			   "write (local SSL3 detected an error)",
754e5b75505Sopenharmony_ci			   SSL_alert_type_string_long(ret),
755e5b75505Sopenharmony_ci			   SSL_alert_desc_string_long(ret));
756e5b75505Sopenharmony_ci		if ((ret >> 8) == SSL3_AL_FATAL) {
757e5b75505Sopenharmony_ci			if (where & SSL_CB_READ)
758e5b75505Sopenharmony_ci				conn->read_alerts++;
759e5b75505Sopenharmony_ci			else
760e5b75505Sopenharmony_ci				conn->write_alerts++;
761e5b75505Sopenharmony_ci		}
762e5b75505Sopenharmony_ci		if (conn->context->event_cb != NULL) {
763e5b75505Sopenharmony_ci			union tls_event_data ev;
764e5b75505Sopenharmony_ci			struct tls_context *context = conn->context;
765e5b75505Sopenharmony_ci			os_memset(&ev, 0, sizeof(ev));
766e5b75505Sopenharmony_ci			ev.alert.is_local = !(where & SSL_CB_READ);
767e5b75505Sopenharmony_ci			ev.alert.type = SSL_alert_type_string_long(ret);
768e5b75505Sopenharmony_ci			ev.alert.description = SSL_alert_desc_string_long(ret);
769e5b75505Sopenharmony_ci			context->event_cb(context->cb_ctx, TLS_ALERT, &ev);
770e5b75505Sopenharmony_ci		}
771e5b75505Sopenharmony_ci	} else if (where & SSL_CB_EXIT && ret <= 0) {
772e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s",
773e5b75505Sopenharmony_ci			   str, ret == 0 ? "failed" : "error",
774e5b75505Sopenharmony_ci			   SSL_state_string_long(ssl));
775e5b75505Sopenharmony_ci	}
776e5b75505Sopenharmony_ci}
777e5b75505Sopenharmony_ci
778e5b75505Sopenharmony_ci
779e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
780e5b75505Sopenharmony_ci/**
781e5b75505Sopenharmony_ci * tls_engine_load_dynamic_generic - load any openssl engine
782e5b75505Sopenharmony_ci * @pre: an array of commands and values that load an engine initialized
783e5b75505Sopenharmony_ci *       in the engine specific function
784e5b75505Sopenharmony_ci * @post: an array of commands and values that initialize an already loaded
785e5b75505Sopenharmony_ci *        engine (or %NULL if not required)
786e5b75505Sopenharmony_ci * @id: the engine id of the engine to load (only required if post is not %NULL
787e5b75505Sopenharmony_ci *
788e5b75505Sopenharmony_ci * This function is a generic function that loads any openssl engine.
789e5b75505Sopenharmony_ci *
790e5b75505Sopenharmony_ci * Returns: 0 on success, -1 on failure
791e5b75505Sopenharmony_ci */
792e5b75505Sopenharmony_cistatic int tls_engine_load_dynamic_generic(const char *pre[],
793e5b75505Sopenharmony_ci					   const char *post[], const char *id)
794e5b75505Sopenharmony_ci{
795e5b75505Sopenharmony_ci	ENGINE *engine;
796e5b75505Sopenharmony_ci	const char *dynamic_id = "dynamic";
797e5b75505Sopenharmony_ci
798e5b75505Sopenharmony_ci	engine = ENGINE_by_id(id);
799e5b75505Sopenharmony_ci	if (engine) {
800e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "ENGINE: engine '%s' is already "
801e5b75505Sopenharmony_ci			   "available", id);
802e5b75505Sopenharmony_ci		/*
803e5b75505Sopenharmony_ci		 * If it was auto-loaded by ENGINE_by_id() we might still
804e5b75505Sopenharmony_ci		 * need to tell it which PKCS#11 module to use in legacy
805e5b75505Sopenharmony_ci		 * (non-p11-kit) environments. Do so now; even if it was
806e5b75505Sopenharmony_ci		 * properly initialised before, setting it again will be
807e5b75505Sopenharmony_ci		 * harmless.
808e5b75505Sopenharmony_ci		 */
809e5b75505Sopenharmony_ci		goto found;
810e5b75505Sopenharmony_ci	}
811e5b75505Sopenharmony_ci	ERR_clear_error();
812e5b75505Sopenharmony_ci
813e5b75505Sopenharmony_ci	engine = ENGINE_by_id(dynamic_id);
814e5b75505Sopenharmony_ci	if (engine == NULL) {
815e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]",
816e5b75505Sopenharmony_ci			   dynamic_id,
817e5b75505Sopenharmony_ci			   ERR_error_string(ERR_get_error(), NULL));
818e5b75505Sopenharmony_ci		return -1;
819e5b75505Sopenharmony_ci	}
820e5b75505Sopenharmony_ci
821e5b75505Sopenharmony_ci	/* Perform the pre commands. This will load the engine. */
822e5b75505Sopenharmony_ci	while (pre && pre[0]) {
823e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", pre[0], pre[1]);
824e5b75505Sopenharmony_ci		if (ENGINE_ctrl_cmd_string(engine, pre[0], pre[1], 0) == 0) {
825e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO, "ENGINE: ctrl cmd_string failed: "
826e5b75505Sopenharmony_ci				   "%s %s [%s]", pre[0], pre[1],
827e5b75505Sopenharmony_ci				   ERR_error_string(ERR_get_error(), NULL));
828e5b75505Sopenharmony_ci			ENGINE_free(engine);
829e5b75505Sopenharmony_ci			return -1;
830e5b75505Sopenharmony_ci		}
831e5b75505Sopenharmony_ci		pre += 2;
832e5b75505Sopenharmony_ci	}
833e5b75505Sopenharmony_ci
834e5b75505Sopenharmony_ci	/*
835e5b75505Sopenharmony_ci	 * Free the reference to the "dynamic" engine. The loaded engine can
836e5b75505Sopenharmony_ci	 * now be looked up using ENGINE_by_id().
837e5b75505Sopenharmony_ci	 */
838e5b75505Sopenharmony_ci	ENGINE_free(engine);
839e5b75505Sopenharmony_ci
840e5b75505Sopenharmony_ci	engine = ENGINE_by_id(id);
841e5b75505Sopenharmony_ci	if (engine == NULL) {
842e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]",
843e5b75505Sopenharmony_ci			   id, ERR_error_string(ERR_get_error(), NULL));
844e5b75505Sopenharmony_ci		return -1;
845e5b75505Sopenharmony_ci	}
846e5b75505Sopenharmony_ci found:
847e5b75505Sopenharmony_ci	while (post && post[0]) {
848e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", post[0], post[1]);
849e5b75505Sopenharmony_ci		if (ENGINE_ctrl_cmd_string(engine, post[0], post[1], 0) == 0) {
850e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "ENGINE: ctrl cmd_string failed:"
851e5b75505Sopenharmony_ci				" %s %s [%s]", post[0], post[1],
852e5b75505Sopenharmony_ci				   ERR_error_string(ERR_get_error(), NULL));
853e5b75505Sopenharmony_ci			ENGINE_remove(engine);
854e5b75505Sopenharmony_ci			ENGINE_free(engine);
855e5b75505Sopenharmony_ci			return -1;
856e5b75505Sopenharmony_ci		}
857e5b75505Sopenharmony_ci		post += 2;
858e5b75505Sopenharmony_ci	}
859e5b75505Sopenharmony_ci	ENGINE_free(engine);
860e5b75505Sopenharmony_ci
861e5b75505Sopenharmony_ci	return 0;
862e5b75505Sopenharmony_ci}
863e5b75505Sopenharmony_ci
864e5b75505Sopenharmony_ci
865e5b75505Sopenharmony_ci/**
866e5b75505Sopenharmony_ci * tls_engine_load_dynamic_pkcs11 - load the pkcs11 engine provided by opensc
867e5b75505Sopenharmony_ci * @pkcs11_so_path: pksc11_so_path from the configuration
868e5b75505Sopenharmony_ci * @pcks11_module_path: pkcs11_module_path from the configuration
869e5b75505Sopenharmony_ci */
870e5b75505Sopenharmony_cistatic int tls_engine_load_dynamic_pkcs11(const char *pkcs11_so_path,
871e5b75505Sopenharmony_ci					  const char *pkcs11_module_path)
872e5b75505Sopenharmony_ci{
873e5b75505Sopenharmony_ci	char *engine_id = "pkcs11";
874e5b75505Sopenharmony_ci	const char *pre_cmd[] = {
875e5b75505Sopenharmony_ci		"SO_PATH", NULL /* pkcs11_so_path */,
876e5b75505Sopenharmony_ci		"ID", NULL /* engine_id */,
877e5b75505Sopenharmony_ci		"LIST_ADD", "1",
878e5b75505Sopenharmony_ci		/* "NO_VCHECK", "1", */
879e5b75505Sopenharmony_ci		"LOAD", NULL,
880e5b75505Sopenharmony_ci		NULL, NULL
881e5b75505Sopenharmony_ci	};
882e5b75505Sopenharmony_ci	const char *post_cmd[] = {
883e5b75505Sopenharmony_ci		"MODULE_PATH", NULL /* pkcs11_module_path */,
884e5b75505Sopenharmony_ci		NULL, NULL
885e5b75505Sopenharmony_ci	};
886e5b75505Sopenharmony_ci
887e5b75505Sopenharmony_ci	if (!pkcs11_so_path)
888e5b75505Sopenharmony_ci		return 0;
889e5b75505Sopenharmony_ci
890e5b75505Sopenharmony_ci	pre_cmd[1] = pkcs11_so_path;
891e5b75505Sopenharmony_ci	pre_cmd[3] = engine_id;
892e5b75505Sopenharmony_ci	if (pkcs11_module_path)
893e5b75505Sopenharmony_ci		post_cmd[1] = pkcs11_module_path;
894e5b75505Sopenharmony_ci	else
895e5b75505Sopenharmony_ci		post_cmd[0] = NULL;
896e5b75505Sopenharmony_ci
897e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "ENGINE: Loading pkcs11 Engine from %s",
898e5b75505Sopenharmony_ci		   pkcs11_so_path);
899e5b75505Sopenharmony_ci
900e5b75505Sopenharmony_ci	return tls_engine_load_dynamic_generic(pre_cmd, post_cmd, engine_id);
901e5b75505Sopenharmony_ci}
902e5b75505Sopenharmony_ci
903e5b75505Sopenharmony_ci
904e5b75505Sopenharmony_ci/**
905e5b75505Sopenharmony_ci * tls_engine_load_dynamic_opensc - load the opensc engine provided by opensc
906e5b75505Sopenharmony_ci * @opensc_so_path: opensc_so_path from the configuration
907e5b75505Sopenharmony_ci */
908e5b75505Sopenharmony_cistatic int tls_engine_load_dynamic_opensc(const char *opensc_so_path)
909e5b75505Sopenharmony_ci{
910e5b75505Sopenharmony_ci	char *engine_id = "opensc";
911e5b75505Sopenharmony_ci	const char *pre_cmd[] = {
912e5b75505Sopenharmony_ci		"SO_PATH", NULL /* opensc_so_path */,
913e5b75505Sopenharmony_ci		"ID", NULL /* engine_id */,
914e5b75505Sopenharmony_ci		"LIST_ADD", "1",
915e5b75505Sopenharmony_ci		"LOAD", NULL,
916e5b75505Sopenharmony_ci		NULL, NULL
917e5b75505Sopenharmony_ci	};
918e5b75505Sopenharmony_ci
919e5b75505Sopenharmony_ci	if (!opensc_so_path)
920e5b75505Sopenharmony_ci		return 0;
921e5b75505Sopenharmony_ci
922e5b75505Sopenharmony_ci	pre_cmd[1] = opensc_so_path;
923e5b75505Sopenharmony_ci	pre_cmd[3] = engine_id;
924e5b75505Sopenharmony_ci
925e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "ENGINE: Loading OpenSC Engine from %s",
926e5b75505Sopenharmony_ci		   opensc_so_path);
927e5b75505Sopenharmony_ci
928e5b75505Sopenharmony_ci	return tls_engine_load_dynamic_generic(pre_cmd, NULL, engine_id);
929e5b75505Sopenharmony_ci}
930e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_ENGINE */
931e5b75505Sopenharmony_ci
932e5b75505Sopenharmony_ci
933e5b75505Sopenharmony_cistatic void remove_session_cb(SSL_CTX *ctx, SSL_SESSION *sess)
934e5b75505Sopenharmony_ci{
935e5b75505Sopenharmony_ci	struct wpabuf *buf;
936e5b75505Sopenharmony_ci
937e5b75505Sopenharmony_ci	if (tls_ex_idx_session < 0)
938e5b75505Sopenharmony_ci		return;
939e5b75505Sopenharmony_ci	buf = SSL_SESSION_get_ex_data(sess, tls_ex_idx_session);
940e5b75505Sopenharmony_ci	if (!buf)
941e5b75505Sopenharmony_ci		return;
942e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG,
943e5b75505Sopenharmony_ci		   "OpenSSL: Free application session data %p (sess %p)",
944e5b75505Sopenharmony_ci		   buf, sess);
945e5b75505Sopenharmony_ci	wpabuf_free(buf);
946e5b75505Sopenharmony_ci
947e5b75505Sopenharmony_ci	SSL_SESSION_set_ex_data(sess, tls_ex_idx_session, NULL);
948e5b75505Sopenharmony_ci}
949e5b75505Sopenharmony_ci
950e5b75505Sopenharmony_ci
951e5b75505Sopenharmony_civoid * tls_init(const struct tls_config *conf)
952e5b75505Sopenharmony_ci{
953e5b75505Sopenharmony_ci	struct tls_data *data;
954e5b75505Sopenharmony_ci	SSL_CTX *ssl;
955e5b75505Sopenharmony_ci	struct tls_context *context;
956e5b75505Sopenharmony_ci	const char *ciphers;
957e5b75505Sopenharmony_ci
958e5b75505Sopenharmony_ci	if (tls_openssl_ref_count == 0) {
959e5b75505Sopenharmony_ci		tls_global = context = tls_context_new(conf);
960e5b75505Sopenharmony_ci		if (context == NULL)
961e5b75505Sopenharmony_ci			return NULL;
962e5b75505Sopenharmony_ci#ifdef CONFIG_FIPS
963e5b75505Sopenharmony_ci#ifdef OPENSSL_FIPS
964e5b75505Sopenharmony_ci		if (conf && conf->fips_mode) {
965e5b75505Sopenharmony_ci			static int fips_enabled = 0;
966e5b75505Sopenharmony_ci
967e5b75505Sopenharmony_ci			if (!fips_enabled && !FIPS_mode_set(1)) {
968e5b75505Sopenharmony_ci				wpa_printf(MSG_ERROR, "Failed to enable FIPS "
969e5b75505Sopenharmony_ci					   "mode");
970e5b75505Sopenharmony_ci				ERR_load_crypto_strings();
971e5b75505Sopenharmony_ci				ERR_print_errors_fp(stderr);
972e5b75505Sopenharmony_ci				os_free(tls_global);
973e5b75505Sopenharmony_ci				tls_global = NULL;
974e5b75505Sopenharmony_ci				return NULL;
975e5b75505Sopenharmony_ci			} else {
976e5b75505Sopenharmony_ci				wpa_printf(MSG_INFO, "Running in FIPS mode");
977e5b75505Sopenharmony_ci				fips_enabled = 1;
978e5b75505Sopenharmony_ci			}
979e5b75505Sopenharmony_ci		}
980e5b75505Sopenharmony_ci#else /* OPENSSL_FIPS */
981e5b75505Sopenharmony_ci		if (conf && conf->fips_mode) {
982e5b75505Sopenharmony_ci			wpa_printf(MSG_ERROR, "FIPS mode requested, but not "
983e5b75505Sopenharmony_ci				   "supported");
984e5b75505Sopenharmony_ci			os_free(tls_global);
985e5b75505Sopenharmony_ci			tls_global = NULL;
986e5b75505Sopenharmony_ci			return NULL;
987e5b75505Sopenharmony_ci		}
988e5b75505Sopenharmony_ci#endif /* OPENSSL_FIPS */
989e5b75505Sopenharmony_ci#endif /* CONFIG_FIPS */
990e5b75505Sopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
991e5b75505Sopenharmony_ci	(defined(LIBRESSL_VERSION_NUMBER) && \
992e5b75505Sopenharmony_ci	 LIBRESSL_VERSION_NUMBER < 0x20700000L)
993e5b75505Sopenharmony_ci		SSL_load_error_strings();
994e5b75505Sopenharmony_ci		SSL_library_init();
995e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_SHA256
996e5b75505Sopenharmony_ci		EVP_add_digest(EVP_sha256());
997e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_SHA256 */
998e5b75505Sopenharmony_ci		/* TODO: if /dev/urandom is available, PRNG is seeded
999e5b75505Sopenharmony_ci		 * automatically. If this is not the case, random data should
1000e5b75505Sopenharmony_ci		 * be added here. */
1001e5b75505Sopenharmony_ci
1002e5b75505Sopenharmony_ci#ifdef PKCS12_FUNCS
1003e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_RC2
1004e5b75505Sopenharmony_ci		/*
1005e5b75505Sopenharmony_ci		 * 40-bit RC2 is commonly used in PKCS#12 files, so enable it.
1006e5b75505Sopenharmony_ci		 * This is enabled by PKCS12_PBE_add() in OpenSSL 0.9.8
1007e5b75505Sopenharmony_ci		 * versions, but it looks like OpenSSL 1.0.0 does not do that
1008e5b75505Sopenharmony_ci		 * anymore.
1009e5b75505Sopenharmony_ci		 */
1010e5b75505Sopenharmony_ci		EVP_add_cipher(EVP_rc2_40_cbc());
1011e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_RC2 */
1012e5b75505Sopenharmony_ci		PKCS12_PBE_add();
1013e5b75505Sopenharmony_ci#endif  /* PKCS12_FUNCS */
1014e5b75505Sopenharmony_ci#endif /* < 1.1.0 */
1015e5b75505Sopenharmony_ci	} else {
1016e5b75505Sopenharmony_ci		context = tls_context_new(conf);
1017e5b75505Sopenharmony_ci		if (context == NULL)
1018e5b75505Sopenharmony_ci			return NULL;
1019e5b75505Sopenharmony_ci	}
1020e5b75505Sopenharmony_ci	tls_openssl_ref_count++;
1021e5b75505Sopenharmony_ci
1022e5b75505Sopenharmony_ci	data = os_zalloc(sizeof(*data));
1023e5b75505Sopenharmony_ci	if (data)
1024e5b75505Sopenharmony_ci		ssl = SSL_CTX_new(SSLv23_method());
1025e5b75505Sopenharmony_ci	else
1026e5b75505Sopenharmony_ci		ssl = NULL;
1027e5b75505Sopenharmony_ci	if (ssl == NULL) {
1028e5b75505Sopenharmony_ci		tls_openssl_ref_count--;
1029e5b75505Sopenharmony_ci		if (context != tls_global)
1030e5b75505Sopenharmony_ci			os_free(context);
1031e5b75505Sopenharmony_ci		if (tls_openssl_ref_count == 0) {
1032e5b75505Sopenharmony_ci			os_free(tls_global);
1033e5b75505Sopenharmony_ci			tls_global = NULL;
1034e5b75505Sopenharmony_ci		}
1035e5b75505Sopenharmony_ci		os_free(data);
1036e5b75505Sopenharmony_ci		return NULL;
1037e5b75505Sopenharmony_ci	}
1038e5b75505Sopenharmony_ci	data->ssl = ssl;
1039e5b75505Sopenharmony_ci	if (conf) {
1040e5b75505Sopenharmony_ci		data->tls_session_lifetime = conf->tls_session_lifetime;
1041e5b75505Sopenharmony_ci		data->crl_reload_interval = conf->crl_reload_interval;
1042e5b75505Sopenharmony_ci	}
1043e5b75505Sopenharmony_ci
1044e5b75505Sopenharmony_ci	SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv2);
1045e5b75505Sopenharmony_ci	SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv3);
1046e5b75505Sopenharmony_ci
1047e5b75505Sopenharmony_ci#ifdef SSL_MODE_NO_AUTO_CHAIN
1048e5b75505Sopenharmony_ci	/* Number of deployed use cases assume the default OpenSSL behavior of
1049e5b75505Sopenharmony_ci	 * auto chaining the local certificate is in use. BoringSSL removed this
1050e5b75505Sopenharmony_ci	 * functionality by default, so we need to restore it here to avoid
1051e5b75505Sopenharmony_ci	 * breaking existing use cases. */
1052e5b75505Sopenharmony_ci	SSL_CTX_clear_mode(ssl, SSL_MODE_NO_AUTO_CHAIN);
1053e5b75505Sopenharmony_ci#endif /* SSL_MODE_NO_AUTO_CHAIN */
1054e5b75505Sopenharmony_ci
1055e5b75505Sopenharmony_ci	SSL_CTX_set_info_callback(ssl, ssl_info_cb);
1056e5b75505Sopenharmony_ci	SSL_CTX_set_app_data(ssl, context);
1057e5b75505Sopenharmony_ci	if (data->tls_session_lifetime > 0) {
1058e5b75505Sopenharmony_ci		SSL_CTX_set_quiet_shutdown(ssl, 1);
1059e5b75505Sopenharmony_ci		/*
1060e5b75505Sopenharmony_ci		 * Set default context here. In practice, this will be replaced
1061e5b75505Sopenharmony_ci		 * by the per-EAP method context in tls_connection_set_verify().
1062e5b75505Sopenharmony_ci		 */
1063e5b75505Sopenharmony_ci		SSL_CTX_set_session_id_context(ssl, (u8 *) "hostapd", 7);
1064e5b75505Sopenharmony_ci		SSL_CTX_set_session_cache_mode(ssl, SSL_SESS_CACHE_SERVER);
1065e5b75505Sopenharmony_ci		SSL_CTX_set_timeout(ssl, data->tls_session_lifetime);
1066e5b75505Sopenharmony_ci		SSL_CTX_sess_set_remove_cb(ssl, remove_session_cb);
1067e5b75505Sopenharmony_ci	} else {
1068e5b75505Sopenharmony_ci		SSL_CTX_set_session_cache_mode(ssl, SSL_SESS_CACHE_OFF);
1069e5b75505Sopenharmony_ci	}
1070e5b75505Sopenharmony_ci
1071e5b75505Sopenharmony_ci	if (tls_ex_idx_session < 0) {
1072e5b75505Sopenharmony_ci		tls_ex_idx_session = SSL_SESSION_get_ex_new_index(
1073e5b75505Sopenharmony_ci			0, NULL, NULL, NULL, NULL);
1074e5b75505Sopenharmony_ci		if (tls_ex_idx_session < 0) {
1075e5b75505Sopenharmony_ci			tls_deinit(data);
1076e5b75505Sopenharmony_ci			return NULL;
1077e5b75505Sopenharmony_ci		}
1078e5b75505Sopenharmony_ci	}
1079e5b75505Sopenharmony_ci
1080e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
1081e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "ENGINE: Loading builtin engines");
1082e5b75505Sopenharmony_ci	ENGINE_load_builtin_engines();
1083e5b75505Sopenharmony_ci
1084e5b75505Sopenharmony_ci	if (conf &&
1085e5b75505Sopenharmony_ci	    (conf->opensc_engine_path || conf->pkcs11_engine_path ||
1086e5b75505Sopenharmony_ci	     conf->pkcs11_module_path)) {
1087e5b75505Sopenharmony_ci		if (tls_engine_load_dynamic_opensc(conf->opensc_engine_path) ||
1088e5b75505Sopenharmony_ci		    tls_engine_load_dynamic_pkcs11(conf->pkcs11_engine_path,
1089e5b75505Sopenharmony_ci						   conf->pkcs11_module_path)) {
1090e5b75505Sopenharmony_ci			tls_deinit(data);
1091e5b75505Sopenharmony_ci			return NULL;
1092e5b75505Sopenharmony_ci		}
1093e5b75505Sopenharmony_ci	}
1094e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_ENGINE */
1095e5b75505Sopenharmony_ci
1096e5b75505Sopenharmony_ci	if (conf && conf->openssl_ciphers)
1097e5b75505Sopenharmony_ci		ciphers = conf->openssl_ciphers;
1098e5b75505Sopenharmony_ci	else
1099e5b75505Sopenharmony_ci		ciphers = TLS_DEFAULT_CIPHERS;
1100e5b75505Sopenharmony_ci	if (SSL_CTX_set_cipher_list(ssl, ciphers) != 1) {
1101e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR,
1102e5b75505Sopenharmony_ci			   "OpenSSL: Failed to set cipher string '%s'",
1103e5b75505Sopenharmony_ci			   ciphers);
1104e5b75505Sopenharmony_ci		tls_deinit(data);
1105e5b75505Sopenharmony_ci		return NULL;
1106e5b75505Sopenharmony_ci	}
1107e5b75505Sopenharmony_ci
1108e5b75505Sopenharmony_ci	return data;
1109e5b75505Sopenharmony_ci}
1110e5b75505Sopenharmony_ci
1111e5b75505Sopenharmony_ci
1112e5b75505Sopenharmony_civoid tls_deinit(void *ssl_ctx)
1113e5b75505Sopenharmony_ci{
1114e5b75505Sopenharmony_ci	struct tls_data *data = ssl_ctx;
1115e5b75505Sopenharmony_ci	SSL_CTX *ssl = data->ssl;
1116e5b75505Sopenharmony_ci	struct tls_context *context = SSL_CTX_get_app_data(ssl);
1117e5b75505Sopenharmony_ci	if (context != tls_global)
1118e5b75505Sopenharmony_ci		os_free(context);
1119e5b75505Sopenharmony_ci	if (data->tls_session_lifetime > 0)
1120e5b75505Sopenharmony_ci		SSL_CTX_flush_sessions(ssl, 0);
1121e5b75505Sopenharmony_ci	os_free(data->ca_cert);
1122e5b75505Sopenharmony_ci	SSL_CTX_free(ssl);
1123e5b75505Sopenharmony_ci
1124e5b75505Sopenharmony_ci	tls_openssl_ref_count--;
1125e5b75505Sopenharmony_ci	if (tls_openssl_ref_count == 0) {
1126e5b75505Sopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
1127e5b75505Sopenharmony_ci	(defined(LIBRESSL_VERSION_NUMBER) && \
1128e5b75505Sopenharmony_ci	 LIBRESSL_VERSION_NUMBER < 0x20700000L)
1129e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
1130e5b75505Sopenharmony_ci		ENGINE_cleanup();
1131e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_ENGINE */
1132e5b75505Sopenharmony_ci		CRYPTO_cleanup_all_ex_data();
1133e5b75505Sopenharmony_ci		ERR_remove_thread_state(NULL);
1134e5b75505Sopenharmony_ci		ERR_free_strings();
1135e5b75505Sopenharmony_ci		EVP_cleanup();
1136e5b75505Sopenharmony_ci#endif /* < 1.1.0 */
1137e5b75505Sopenharmony_ci		os_free(tls_global->ocsp_stapling_response);
1138e5b75505Sopenharmony_ci		tls_global->ocsp_stapling_response = NULL;
1139e5b75505Sopenharmony_ci		os_free(tls_global);
1140e5b75505Sopenharmony_ci		tls_global = NULL;
1141e5b75505Sopenharmony_ci	}
1142e5b75505Sopenharmony_ci
1143e5b75505Sopenharmony_ci	os_free(data->check_cert_subject);
1144e5b75505Sopenharmony_ci	os_free(data);
1145e5b75505Sopenharmony_ci}
1146e5b75505Sopenharmony_ci
1147e5b75505Sopenharmony_ci
1148e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
1149e5b75505Sopenharmony_ci
1150e5b75505Sopenharmony_ci/* Cryptoki return values */
1151e5b75505Sopenharmony_ci#define CKR_PIN_INCORRECT 0x000000a0
1152e5b75505Sopenharmony_ci#define CKR_PIN_INVALID 0x000000a1
1153e5b75505Sopenharmony_ci#define CKR_PIN_LEN_RANGE 0x000000a2
1154e5b75505Sopenharmony_ci
1155e5b75505Sopenharmony_ci/* libp11 */
1156e5b75505Sopenharmony_ci#define ERR_LIB_PKCS11	ERR_LIB_USER
1157e5b75505Sopenharmony_ci
1158e5b75505Sopenharmony_cistatic int tls_is_pin_error(unsigned int err)
1159e5b75505Sopenharmony_ci{
1160e5b75505Sopenharmony_ci	return ERR_GET_LIB(err) == ERR_LIB_PKCS11 &&
1161e5b75505Sopenharmony_ci		(ERR_GET_REASON(err) == CKR_PIN_INCORRECT ||
1162e5b75505Sopenharmony_ci		 ERR_GET_REASON(err) == CKR_PIN_INVALID ||
1163e5b75505Sopenharmony_ci		 ERR_GET_REASON(err) == CKR_PIN_LEN_RANGE);
1164e5b75505Sopenharmony_ci}
1165e5b75505Sopenharmony_ci
1166e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_ENGINE */
1167e5b75505Sopenharmony_ci
1168e5b75505Sopenharmony_ci
1169e5b75505Sopenharmony_ci#ifdef ANDROID
1170e5b75505Sopenharmony_ci/* EVP_PKEY_from_keystore comes from system/security/keystore-engine. */
1171e5b75505Sopenharmony_ciEVP_PKEY * EVP_PKEY_from_keystore(const char *key_id);
1172e5b75505Sopenharmony_ci#endif /* ANDROID */
1173e5b75505Sopenharmony_ci
1174e5b75505Sopenharmony_cistatic int tls_engine_init(struct tls_connection *conn, const char *engine_id,
1175e5b75505Sopenharmony_ci			   const char *pin, const char *key_id,
1176e5b75505Sopenharmony_ci			   const char *cert_id, const char *ca_cert_id)
1177e5b75505Sopenharmony_ci{
1178e5b75505Sopenharmony_ci#if defined(ANDROID) && defined(OPENSSL_IS_BORINGSSL)
1179e5b75505Sopenharmony_ci#if !defined(OPENSSL_NO_ENGINE)
1180e5b75505Sopenharmony_ci#error "This code depends on OPENSSL_NO_ENGINE being defined by BoringSSL."
1181e5b75505Sopenharmony_ci#endif
1182e5b75505Sopenharmony_ci	if (!key_id)
1183e5b75505Sopenharmony_ci		return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
1184e5b75505Sopenharmony_ci	conn->engine = NULL;
1185e5b75505Sopenharmony_ci	conn->private_key = EVP_PKEY_from_keystore(key_id);
1186e5b75505Sopenharmony_ci	if (!conn->private_key) {
1187e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR,
1188e5b75505Sopenharmony_ci			   "ENGINE: cannot load private key with id '%s' [%s]",
1189e5b75505Sopenharmony_ci			   key_id,
1190e5b75505Sopenharmony_ci			   ERR_error_string(ERR_get_error(), NULL));
1191e5b75505Sopenharmony_ci		return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
1192e5b75505Sopenharmony_ci	}
1193e5b75505Sopenharmony_ci#endif /* ANDROID && OPENSSL_IS_BORINGSSL */
1194e5b75505Sopenharmony_ci
1195e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
1196e5b75505Sopenharmony_ci	int ret = -1;
1197e5b75505Sopenharmony_ci	if (engine_id == NULL) {
1198e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR, "ENGINE: Engine ID not set");
1199e5b75505Sopenharmony_ci		return -1;
1200e5b75505Sopenharmony_ci	}
1201e5b75505Sopenharmony_ci
1202e5b75505Sopenharmony_ci	ERR_clear_error();
1203e5b75505Sopenharmony_ci#ifdef ANDROID
1204e5b75505Sopenharmony_ci	ENGINE_load_dynamic();
1205e5b75505Sopenharmony_ci#endif
1206e5b75505Sopenharmony_ci	conn->engine = ENGINE_by_id(engine_id);
1207e5b75505Sopenharmony_ci	if (!conn->engine) {
1208e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR, "ENGINE: engine %s not available [%s]",
1209e5b75505Sopenharmony_ci			   engine_id, ERR_error_string(ERR_get_error(), NULL));
1210e5b75505Sopenharmony_ci		goto err;
1211e5b75505Sopenharmony_ci	}
1212e5b75505Sopenharmony_ci	if (ENGINE_init(conn->engine) != 1) {
1213e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR, "ENGINE: engine init failed "
1214e5b75505Sopenharmony_ci			   "(engine: %s) [%s]", engine_id,
1215e5b75505Sopenharmony_ci			   ERR_error_string(ERR_get_error(), NULL));
1216e5b75505Sopenharmony_ci		goto err;
1217e5b75505Sopenharmony_ci	}
1218e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "ENGINE: engine initialized");
1219e5b75505Sopenharmony_ci
1220e5b75505Sopenharmony_ci#ifndef ANDROID
1221e5b75505Sopenharmony_ci	if (pin && ENGINE_ctrl_cmd_string(conn->engine, "PIN", pin, 0) == 0) {
1222e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR, "ENGINE: cannot set pin [%s]",
1223e5b75505Sopenharmony_ci			   ERR_error_string(ERR_get_error(), NULL));
1224e5b75505Sopenharmony_ci		goto err;
1225e5b75505Sopenharmony_ci	}
1226e5b75505Sopenharmony_ci#endif
1227e5b75505Sopenharmony_ci	if (key_id) {
1228e5b75505Sopenharmony_ci		/*
1229e5b75505Sopenharmony_ci		 * Ensure that the ENGINE does not attempt to use the OpenSSL
1230e5b75505Sopenharmony_ci		 * UI system to obtain a PIN, if we didn't provide one.
1231e5b75505Sopenharmony_ci		 */
1232e5b75505Sopenharmony_ci		struct {
1233e5b75505Sopenharmony_ci			const void *password;
1234e5b75505Sopenharmony_ci			const char *prompt_info;
1235e5b75505Sopenharmony_ci		} key_cb = { "", NULL };
1236e5b75505Sopenharmony_ci
1237e5b75505Sopenharmony_ci		/* load private key first in-case PIN is required for cert */
1238e5b75505Sopenharmony_ci		conn->private_key = ENGINE_load_private_key(conn->engine,
1239e5b75505Sopenharmony_ci							    key_id, NULL,
1240e5b75505Sopenharmony_ci							    &key_cb);
1241e5b75505Sopenharmony_ci		if (!conn->private_key) {
1242e5b75505Sopenharmony_ci			unsigned long err = ERR_get_error();
1243e5b75505Sopenharmony_ci
1244e5b75505Sopenharmony_ci			wpa_printf(MSG_ERROR,
1245e5b75505Sopenharmony_ci				   "ENGINE: cannot load private key with id '%s' [%s]",
1246e5b75505Sopenharmony_ci				   key_id,
1247e5b75505Sopenharmony_ci				   ERR_error_string(err, NULL));
1248e5b75505Sopenharmony_ci			if (tls_is_pin_error(err))
1249e5b75505Sopenharmony_ci				ret = TLS_SET_PARAMS_ENGINE_PRV_BAD_PIN;
1250e5b75505Sopenharmony_ci			else
1251e5b75505Sopenharmony_ci				ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
1252e5b75505Sopenharmony_ci			goto err;
1253e5b75505Sopenharmony_ci		}
1254e5b75505Sopenharmony_ci	}
1255e5b75505Sopenharmony_ci
1256e5b75505Sopenharmony_ci	/* handle a certificate and/or CA certificate */
1257e5b75505Sopenharmony_ci	if (cert_id || ca_cert_id) {
1258e5b75505Sopenharmony_ci		const char *cmd_name = "LOAD_CERT_CTRL";
1259e5b75505Sopenharmony_ci
1260e5b75505Sopenharmony_ci		/* test if the engine supports a LOAD_CERT_CTRL */
1261e5b75505Sopenharmony_ci		if (!ENGINE_ctrl(conn->engine, ENGINE_CTRL_GET_CMD_FROM_NAME,
1262e5b75505Sopenharmony_ci				 0, (void *)cmd_name, NULL)) {
1263e5b75505Sopenharmony_ci			wpa_printf(MSG_ERROR, "ENGINE: engine does not support"
1264e5b75505Sopenharmony_ci				   " loading certificates");
1265e5b75505Sopenharmony_ci			ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
1266e5b75505Sopenharmony_ci			goto err;
1267e5b75505Sopenharmony_ci		}
1268e5b75505Sopenharmony_ci	}
1269e5b75505Sopenharmony_ci
1270e5b75505Sopenharmony_ci	return 0;
1271e5b75505Sopenharmony_ci
1272e5b75505Sopenharmony_cierr:
1273e5b75505Sopenharmony_ci	if (conn->engine) {
1274e5b75505Sopenharmony_ci		ENGINE_free(conn->engine);
1275e5b75505Sopenharmony_ci		conn->engine = NULL;
1276e5b75505Sopenharmony_ci	}
1277e5b75505Sopenharmony_ci
1278e5b75505Sopenharmony_ci	if (conn->private_key) {
1279e5b75505Sopenharmony_ci		EVP_PKEY_free(conn->private_key);
1280e5b75505Sopenharmony_ci		conn->private_key = NULL;
1281e5b75505Sopenharmony_ci	}
1282e5b75505Sopenharmony_ci
1283e5b75505Sopenharmony_ci	return ret;
1284e5b75505Sopenharmony_ci#else /* OPENSSL_NO_ENGINE */
1285e5b75505Sopenharmony_ci	return 0;
1286e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_ENGINE */
1287e5b75505Sopenharmony_ci}
1288e5b75505Sopenharmony_ci
1289e5b75505Sopenharmony_ci
1290e5b75505Sopenharmony_cistatic void tls_engine_deinit(struct tls_connection *conn)
1291e5b75505Sopenharmony_ci{
1292e5b75505Sopenharmony_ci#if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE)
1293e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "ENGINE: engine deinit");
1294e5b75505Sopenharmony_ci	if (conn->private_key) {
1295e5b75505Sopenharmony_ci		EVP_PKEY_free(conn->private_key);
1296e5b75505Sopenharmony_ci		conn->private_key = NULL;
1297e5b75505Sopenharmony_ci	}
1298e5b75505Sopenharmony_ci	if (conn->engine) {
1299e5b75505Sopenharmony_ci#if !defined(OPENSSL_IS_BORINGSSL)
1300e5b75505Sopenharmony_ci		ENGINE_finish(conn->engine);
1301e5b75505Sopenharmony_ci#endif /* !OPENSSL_IS_BORINGSSL */
1302e5b75505Sopenharmony_ci		conn->engine = NULL;
1303e5b75505Sopenharmony_ci	}
1304e5b75505Sopenharmony_ci#endif /* ANDROID || !OPENSSL_NO_ENGINE */
1305e5b75505Sopenharmony_ci}
1306e5b75505Sopenharmony_ci
1307e5b75505Sopenharmony_ci
1308e5b75505Sopenharmony_ciint tls_get_errors(void *ssl_ctx)
1309e5b75505Sopenharmony_ci{
1310e5b75505Sopenharmony_ci	int count = 0;
1311e5b75505Sopenharmony_ci	unsigned long err;
1312e5b75505Sopenharmony_ci
1313e5b75505Sopenharmony_ci	while ((err = ERR_get_error())) {
1314e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "TLS - SSL error: %s",
1315e5b75505Sopenharmony_ci			   ERR_error_string(err, NULL));
1316e5b75505Sopenharmony_ci		count++;
1317e5b75505Sopenharmony_ci	}
1318e5b75505Sopenharmony_ci
1319e5b75505Sopenharmony_ci	return count;
1320e5b75505Sopenharmony_ci}
1321e5b75505Sopenharmony_ci
1322e5b75505Sopenharmony_ci
1323e5b75505Sopenharmony_cistatic const char * openssl_content_type(int content_type)
1324e5b75505Sopenharmony_ci{
1325e5b75505Sopenharmony_ci	switch (content_type) {
1326e5b75505Sopenharmony_ci	case 20:
1327e5b75505Sopenharmony_ci		return "change cipher spec";
1328e5b75505Sopenharmony_ci	case 21:
1329e5b75505Sopenharmony_ci		return "alert";
1330e5b75505Sopenharmony_ci	case 22:
1331e5b75505Sopenharmony_ci		return "handshake";
1332e5b75505Sopenharmony_ci	case 23:
1333e5b75505Sopenharmony_ci		return "application data";
1334e5b75505Sopenharmony_ci	case 24:
1335e5b75505Sopenharmony_ci		return "heartbeat";
1336e5b75505Sopenharmony_ci	case 256:
1337e5b75505Sopenharmony_ci		return "TLS header info"; /* pseudo content type */
1338e5b75505Sopenharmony_ci	case 257:
1339e5b75505Sopenharmony_ci		return "inner content type"; /* pseudo content type */
1340e5b75505Sopenharmony_ci	default:
1341e5b75505Sopenharmony_ci		return "?";
1342e5b75505Sopenharmony_ci	}
1343e5b75505Sopenharmony_ci}
1344e5b75505Sopenharmony_ci
1345e5b75505Sopenharmony_ci
1346e5b75505Sopenharmony_cistatic const char * openssl_handshake_type(int content_type, const u8 *buf,
1347e5b75505Sopenharmony_ci					   size_t len)
1348e5b75505Sopenharmony_ci{
1349e5b75505Sopenharmony_ci	if (content_type == 257 && buf && len == 1)
1350e5b75505Sopenharmony_ci		return openssl_content_type(buf[0]);
1351e5b75505Sopenharmony_ci	if (content_type != 22 || !buf || len == 0)
1352e5b75505Sopenharmony_ci		return "";
1353e5b75505Sopenharmony_ci	switch (buf[0]) {
1354e5b75505Sopenharmony_ci	case 0:
1355e5b75505Sopenharmony_ci		return "hello request";
1356e5b75505Sopenharmony_ci	case 1:
1357e5b75505Sopenharmony_ci		return "client hello";
1358e5b75505Sopenharmony_ci	case 2:
1359e5b75505Sopenharmony_ci		return "server hello";
1360e5b75505Sopenharmony_ci	case 3:
1361e5b75505Sopenharmony_ci		return "hello verify request";
1362e5b75505Sopenharmony_ci	case 4:
1363e5b75505Sopenharmony_ci		return "new session ticket";
1364e5b75505Sopenharmony_ci	case 5:
1365e5b75505Sopenharmony_ci		return "end of early data";
1366e5b75505Sopenharmony_ci	case 6:
1367e5b75505Sopenharmony_ci		return "hello retry request";
1368e5b75505Sopenharmony_ci	case 8:
1369e5b75505Sopenharmony_ci		return "encrypted extensions";
1370e5b75505Sopenharmony_ci	case 11:
1371e5b75505Sopenharmony_ci		return "certificate";
1372e5b75505Sopenharmony_ci	case 12:
1373e5b75505Sopenharmony_ci		return "server key exchange";
1374e5b75505Sopenharmony_ci	case 13:
1375e5b75505Sopenharmony_ci		return "certificate request";
1376e5b75505Sopenharmony_ci	case 14:
1377e5b75505Sopenharmony_ci		return "server hello done";
1378e5b75505Sopenharmony_ci	case 15:
1379e5b75505Sopenharmony_ci		return "certificate verify";
1380e5b75505Sopenharmony_ci	case 16:
1381e5b75505Sopenharmony_ci		return "client key exchange";
1382e5b75505Sopenharmony_ci	case 20:
1383e5b75505Sopenharmony_ci		return "finished";
1384e5b75505Sopenharmony_ci	case 21:
1385e5b75505Sopenharmony_ci		return "certificate url";
1386e5b75505Sopenharmony_ci	case 22:
1387e5b75505Sopenharmony_ci		return "certificate status";
1388e5b75505Sopenharmony_ci	case 23:
1389e5b75505Sopenharmony_ci		return "supplemental data";
1390e5b75505Sopenharmony_ci	case 24:
1391e5b75505Sopenharmony_ci		return "key update";
1392e5b75505Sopenharmony_ci	case 254:
1393e5b75505Sopenharmony_ci		return "message hash";
1394e5b75505Sopenharmony_ci	default:
1395e5b75505Sopenharmony_ci		return "?";
1396e5b75505Sopenharmony_ci	}
1397e5b75505Sopenharmony_ci}
1398e5b75505Sopenharmony_ci
1399e5b75505Sopenharmony_ci
1400e5b75505Sopenharmony_ci#ifdef CONFIG_SUITEB
1401e5b75505Sopenharmony_ci
1402e5b75505Sopenharmony_cistatic void check_server_hello(struct tls_connection *conn,
1403e5b75505Sopenharmony_ci			       const u8 *pos, const u8 *end)
1404e5b75505Sopenharmony_ci{
1405e5b75505Sopenharmony_ci	size_t payload_len, id_len;
1406e5b75505Sopenharmony_ci
1407e5b75505Sopenharmony_ci	/*
1408e5b75505Sopenharmony_ci	 * Parse ServerHello to get the selected cipher suite since OpenSSL does
1409e5b75505Sopenharmony_ci	 * not make it cleanly available during handshake and we need to know
1410e5b75505Sopenharmony_ci	 * whether DHE was selected.
1411e5b75505Sopenharmony_ci	 */
1412e5b75505Sopenharmony_ci
1413e5b75505Sopenharmony_ci	if (end - pos < 3)
1414e5b75505Sopenharmony_ci		return;
1415e5b75505Sopenharmony_ci	payload_len = WPA_GET_BE24(pos);
1416e5b75505Sopenharmony_ci	pos += 3;
1417e5b75505Sopenharmony_ci
1418e5b75505Sopenharmony_ci	if ((size_t) (end - pos) < payload_len)
1419e5b75505Sopenharmony_ci		return;
1420e5b75505Sopenharmony_ci	end = pos + payload_len;
1421e5b75505Sopenharmony_ci
1422e5b75505Sopenharmony_ci	/* Skip Version and Random */
1423e5b75505Sopenharmony_ci	if (end - pos < 2 + SSL3_RANDOM_SIZE)
1424e5b75505Sopenharmony_ci		return;
1425e5b75505Sopenharmony_ci	pos += 2 + SSL3_RANDOM_SIZE;
1426e5b75505Sopenharmony_ci
1427e5b75505Sopenharmony_ci	/* Skip Session ID */
1428e5b75505Sopenharmony_ci	if (end - pos < 1)
1429e5b75505Sopenharmony_ci		return;
1430e5b75505Sopenharmony_ci	id_len = *pos++;
1431e5b75505Sopenharmony_ci	if ((size_t) (end - pos) < id_len)
1432e5b75505Sopenharmony_ci		return;
1433e5b75505Sopenharmony_ci	pos += id_len;
1434e5b75505Sopenharmony_ci
1435e5b75505Sopenharmony_ci	if (end - pos < 2)
1436e5b75505Sopenharmony_ci		return;
1437e5b75505Sopenharmony_ci	conn->cipher_suite = WPA_GET_BE16(pos);
1438e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "OpenSSL: Server selected cipher suite 0x%x",
1439e5b75505Sopenharmony_ci		   conn->cipher_suite);
1440e5b75505Sopenharmony_ci}
1441e5b75505Sopenharmony_ci
1442e5b75505Sopenharmony_ci
1443e5b75505Sopenharmony_cistatic void check_server_key_exchange(SSL *ssl, struct tls_connection *conn,
1444e5b75505Sopenharmony_ci				      const u8 *pos, const u8 *end)
1445e5b75505Sopenharmony_ci{
1446e5b75505Sopenharmony_ci	size_t payload_len;
1447e5b75505Sopenharmony_ci	u16 dh_len;
1448e5b75505Sopenharmony_ci	BIGNUM *p;
1449e5b75505Sopenharmony_ci	int bits;
1450e5b75505Sopenharmony_ci
1451e5b75505Sopenharmony_ci	if (!(conn->flags & TLS_CONN_SUITEB))
1452e5b75505Sopenharmony_ci		return;
1453e5b75505Sopenharmony_ci
1454e5b75505Sopenharmony_ci	/* DHE is enabled only with DHE-RSA-AES256-GCM-SHA384 */
1455e5b75505Sopenharmony_ci	if (conn->cipher_suite != 0x9f)
1456e5b75505Sopenharmony_ci		return;
1457e5b75505Sopenharmony_ci
1458e5b75505Sopenharmony_ci	if (end - pos < 3)
1459e5b75505Sopenharmony_ci		return;
1460e5b75505Sopenharmony_ci	payload_len = WPA_GET_BE24(pos);
1461e5b75505Sopenharmony_ci	pos += 3;
1462e5b75505Sopenharmony_ci
1463e5b75505Sopenharmony_ci	if ((size_t) (end - pos) < payload_len)
1464e5b75505Sopenharmony_ci		return;
1465e5b75505Sopenharmony_ci	end = pos + payload_len;
1466e5b75505Sopenharmony_ci
1467e5b75505Sopenharmony_ci	if (end - pos < 2)
1468e5b75505Sopenharmony_ci		return;
1469e5b75505Sopenharmony_ci	dh_len = WPA_GET_BE16(pos);
1470e5b75505Sopenharmony_ci	pos += 2;
1471e5b75505Sopenharmony_ci
1472e5b75505Sopenharmony_ci	if ((size_t) (end - pos) < dh_len)
1473e5b75505Sopenharmony_ci		return;
1474e5b75505Sopenharmony_ci	p = BN_bin2bn(pos, dh_len, NULL);
1475e5b75505Sopenharmony_ci	if (!p)
1476e5b75505Sopenharmony_ci		return;
1477e5b75505Sopenharmony_ci
1478e5b75505Sopenharmony_ci	bits = BN_num_bits(p);
1479e5b75505Sopenharmony_ci	BN_free(p);
1480e5b75505Sopenharmony_ci
1481e5b75505Sopenharmony_ci	conn->server_dh_prime_len = bits;
1482e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "OpenSSL: Server DH prime length: %d bits",
1483e5b75505Sopenharmony_ci		   conn->server_dh_prime_len);
1484e5b75505Sopenharmony_ci}
1485e5b75505Sopenharmony_ci
1486e5b75505Sopenharmony_ci#endif /* CONFIG_SUITEB */
1487e5b75505Sopenharmony_ci
1488e5b75505Sopenharmony_ci
1489e5b75505Sopenharmony_cistatic void tls_msg_cb(int write_p, int version, int content_type,
1490e5b75505Sopenharmony_ci		       const void *buf, size_t len, SSL *ssl, void *arg)
1491e5b75505Sopenharmony_ci{
1492e5b75505Sopenharmony_ci	struct tls_connection *conn = arg;
1493e5b75505Sopenharmony_ci	const u8 *pos = buf;
1494e5b75505Sopenharmony_ci
1495e5b75505Sopenharmony_ci	if (write_p == 2) {
1496e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
1497e5b75505Sopenharmony_ci			   "OpenSSL: session ver=0x%x content_type=%d",
1498e5b75505Sopenharmony_ci			   version, content_type);
1499e5b75505Sopenharmony_ci		wpa_hexdump_key(MSG_MSGDUMP, "OpenSSL: Data", buf, len);
1500e5b75505Sopenharmony_ci		return;
1501e5b75505Sopenharmony_ci	}
1502e5b75505Sopenharmony_ci
1503e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "OpenSSL: %s ver=0x%x content_type=%d (%s/%s)",
1504e5b75505Sopenharmony_ci		   write_p ? "TX" : "RX", version, content_type,
1505e5b75505Sopenharmony_ci		   openssl_content_type(content_type),
1506e5b75505Sopenharmony_ci		   openssl_handshake_type(content_type, buf, len));
1507e5b75505Sopenharmony_ci	wpa_hexdump_key(MSG_MSGDUMP, "OpenSSL: Message", buf, len);
1508e5b75505Sopenharmony_ci	if (content_type == 24 && len >= 3 && pos[0] == 1) {
1509e5b75505Sopenharmony_ci		size_t payload_len = WPA_GET_BE16(pos + 1);
1510e5b75505Sopenharmony_ci		if (payload_len + 3 > len) {
1511e5b75505Sopenharmony_ci			wpa_printf(MSG_ERROR, "OpenSSL: Heartbeat attack detected");
1512e5b75505Sopenharmony_ci			conn->invalid_hb_used = 1;
1513e5b75505Sopenharmony_ci		}
1514e5b75505Sopenharmony_ci	}
1515e5b75505Sopenharmony_ci
1516e5b75505Sopenharmony_ci#ifdef CONFIG_SUITEB
1517e5b75505Sopenharmony_ci	/*
1518e5b75505Sopenharmony_ci	 * Need to parse these handshake messages to be able to check DH prime
1519e5b75505Sopenharmony_ci	 * length since OpenSSL does not expose the new cipher suite and DH
1520e5b75505Sopenharmony_ci	 * parameters during handshake (e.g., for cert_cb() callback).
1521e5b75505Sopenharmony_ci	 */
1522e5b75505Sopenharmony_ci	if (content_type == 22 && pos && len > 0 && pos[0] == 2)
1523e5b75505Sopenharmony_ci		check_server_hello(conn, pos + 1, pos + len);
1524e5b75505Sopenharmony_ci	if (content_type == 22 && pos && len > 0 && pos[0] == 12)
1525e5b75505Sopenharmony_ci		check_server_key_exchange(ssl, conn, pos + 1, pos + len);
1526e5b75505Sopenharmony_ci#endif /* CONFIG_SUITEB */
1527e5b75505Sopenharmony_ci}
1528e5b75505Sopenharmony_ci
1529e5b75505Sopenharmony_ci
1530e5b75505Sopenharmony_cistruct tls_connection * tls_connection_init(void *ssl_ctx)
1531e5b75505Sopenharmony_ci{
1532e5b75505Sopenharmony_ci	struct tls_data *data = ssl_ctx;
1533e5b75505Sopenharmony_ci	SSL_CTX *ssl = data->ssl;
1534e5b75505Sopenharmony_ci	struct tls_connection *conn;
1535e5b75505Sopenharmony_ci	long options;
1536e5b75505Sopenharmony_ci	X509_STORE *new_cert_store;
1537e5b75505Sopenharmony_ci	struct os_reltime now;
1538e5b75505Sopenharmony_ci	struct tls_context *context = SSL_CTX_get_app_data(ssl);
1539e5b75505Sopenharmony_ci
1540e5b75505Sopenharmony_ci	/* Replace X509 store if it is time to update CRL. */
1541e5b75505Sopenharmony_ci	if (data->crl_reload_interval > 0 && os_get_reltime(&now) == 0 &&
1542e5b75505Sopenharmony_ci	    os_reltime_expired(&now, &data->crl_last_reload,
1543e5b75505Sopenharmony_ci			       data->crl_reload_interval)) {
1544e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO,
1545e5b75505Sopenharmony_ci			   "OpenSSL: Flushing X509 store with ca_cert file");
1546e5b75505Sopenharmony_ci		new_cert_store = tls_crl_cert_reload(data->ca_cert,
1547e5b75505Sopenharmony_ci						     data->check_crl);
1548e5b75505Sopenharmony_ci		if (!new_cert_store) {
1549e5b75505Sopenharmony_ci			wpa_printf(MSG_ERROR,
1550e5b75505Sopenharmony_ci				   "OpenSSL: Error replacing X509 store with ca_cert file");
1551e5b75505Sopenharmony_ci		} else {
1552e5b75505Sopenharmony_ci			/* Replace old store */
1553e5b75505Sopenharmony_ci			SSL_CTX_set_cert_store(ssl, new_cert_store);
1554e5b75505Sopenharmony_ci			data->crl_last_reload = now;
1555e5b75505Sopenharmony_ci		}
1556e5b75505Sopenharmony_ci	}
1557e5b75505Sopenharmony_ci
1558e5b75505Sopenharmony_ci	conn = os_zalloc(sizeof(*conn));
1559e5b75505Sopenharmony_ci	if (conn == NULL)
1560e5b75505Sopenharmony_ci		return NULL;
1561e5b75505Sopenharmony_ci	conn->data = data;
1562e5b75505Sopenharmony_ci	conn->ssl_ctx = ssl;
1563e5b75505Sopenharmony_ci	conn->ssl = SSL_new(ssl);
1564e5b75505Sopenharmony_ci	if (conn->ssl == NULL) {
1565e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__,
1566e5b75505Sopenharmony_ci				"Failed to initialize new SSL connection");
1567e5b75505Sopenharmony_ci		os_free(conn);
1568e5b75505Sopenharmony_ci		return NULL;
1569e5b75505Sopenharmony_ci	}
1570e5b75505Sopenharmony_ci
1571e5b75505Sopenharmony_ci	conn->context = context;
1572e5b75505Sopenharmony_ci	SSL_set_app_data(conn->ssl, conn);
1573e5b75505Sopenharmony_ci	SSL_set_msg_callback(conn->ssl, tls_msg_cb);
1574e5b75505Sopenharmony_ci	SSL_set_msg_callback_arg(conn->ssl, conn);
1575e5b75505Sopenharmony_ci	options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
1576e5b75505Sopenharmony_ci		SSL_OP_SINGLE_DH_USE;
1577e5b75505Sopenharmony_ci#ifdef SSL_OP_NO_COMPRESSION
1578e5b75505Sopenharmony_ci	options |= SSL_OP_NO_COMPRESSION;
1579e5b75505Sopenharmony_ci#endif /* SSL_OP_NO_COMPRESSION */
1580e5b75505Sopenharmony_ci	SSL_set_options(conn->ssl, options);
1581e5b75505Sopenharmony_ci#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT
1582e5b75505Sopenharmony_ci	/* Hopefully there is no need for middlebox compatibility mechanisms
1583e5b75505Sopenharmony_ci	 * when going through EAP authentication. */
1584e5b75505Sopenharmony_ci	SSL_clear_options(conn->ssl, SSL_OP_ENABLE_MIDDLEBOX_COMPAT);
1585e5b75505Sopenharmony_ci#endif
1586e5b75505Sopenharmony_ci
1587e5b75505Sopenharmony_ci	conn->ssl_in = BIO_new(BIO_s_mem());
1588e5b75505Sopenharmony_ci	if (!conn->ssl_in) {
1589e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__,
1590e5b75505Sopenharmony_ci				"Failed to create a new BIO for ssl_in");
1591e5b75505Sopenharmony_ci		SSL_free(conn->ssl);
1592e5b75505Sopenharmony_ci		os_free(conn);
1593e5b75505Sopenharmony_ci		return NULL;
1594e5b75505Sopenharmony_ci	}
1595e5b75505Sopenharmony_ci
1596e5b75505Sopenharmony_ci	conn->ssl_out = BIO_new(BIO_s_mem());
1597e5b75505Sopenharmony_ci	if (!conn->ssl_out) {
1598e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__,
1599e5b75505Sopenharmony_ci				"Failed to create a new BIO for ssl_out");
1600e5b75505Sopenharmony_ci		SSL_free(conn->ssl);
1601e5b75505Sopenharmony_ci		BIO_free(conn->ssl_in);
1602e5b75505Sopenharmony_ci		os_free(conn);
1603e5b75505Sopenharmony_ci		return NULL;
1604e5b75505Sopenharmony_ci	}
1605e5b75505Sopenharmony_ci
1606e5b75505Sopenharmony_ci	SSL_set_bio(conn->ssl, conn->ssl_in, conn->ssl_out);
1607e5b75505Sopenharmony_ci
1608e5b75505Sopenharmony_ci	return conn;
1609e5b75505Sopenharmony_ci}
1610e5b75505Sopenharmony_ci
1611e5b75505Sopenharmony_ci
1612e5b75505Sopenharmony_civoid tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
1613e5b75505Sopenharmony_ci{
1614e5b75505Sopenharmony_ci	if (conn == NULL)
1615e5b75505Sopenharmony_ci		return;
1616e5b75505Sopenharmony_ci	if (conn->success_data) {
1617e5b75505Sopenharmony_ci		/*
1618e5b75505Sopenharmony_ci		 * Make sure ssl_clear_bad_session() does not remove this
1619e5b75505Sopenharmony_ci		 * session.
1620e5b75505Sopenharmony_ci		 */
1621e5b75505Sopenharmony_ci		SSL_set_quiet_shutdown(conn->ssl, 1);
1622e5b75505Sopenharmony_ci		SSL_shutdown(conn->ssl);
1623e5b75505Sopenharmony_ci	}
1624e5b75505Sopenharmony_ci	SSL_free(conn->ssl);
1625e5b75505Sopenharmony_ci	tls_engine_deinit(conn);
1626e5b75505Sopenharmony_ci	os_free(conn->subject_match);
1627e5b75505Sopenharmony_ci	os_free(conn->altsubject_match);
1628e5b75505Sopenharmony_ci	os_free(conn->suffix_match);
1629e5b75505Sopenharmony_ci	os_free(conn->domain_match);
1630e5b75505Sopenharmony_ci	os_free(conn->check_cert_subject);
1631e5b75505Sopenharmony_ci	os_free(conn->session_ticket);
1632e5b75505Sopenharmony_ci	os_free(conn);
1633e5b75505Sopenharmony_ci}
1634e5b75505Sopenharmony_ci
1635e5b75505Sopenharmony_ci
1636e5b75505Sopenharmony_ciint tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
1637e5b75505Sopenharmony_ci{
1638e5b75505Sopenharmony_ci	return conn ? SSL_is_init_finished(conn->ssl) : 0;
1639e5b75505Sopenharmony_ci}
1640e5b75505Sopenharmony_ci
1641e5b75505Sopenharmony_ci
1642e5b75505Sopenharmony_cichar * tls_connection_peer_serial_num(void *tls_ctx,
1643e5b75505Sopenharmony_ci				      struct tls_connection *conn)
1644e5b75505Sopenharmony_ci{
1645e5b75505Sopenharmony_ci	ASN1_INTEGER *ser;
1646e5b75505Sopenharmony_ci	char *serial_num;
1647e5b75505Sopenharmony_ci	size_t len;
1648e5b75505Sopenharmony_ci
1649e5b75505Sopenharmony_ci	if (!conn->peer_cert)
1650e5b75505Sopenharmony_ci		return NULL;
1651e5b75505Sopenharmony_ci
1652e5b75505Sopenharmony_ci	ser = X509_get_serialNumber(conn->peer_cert);
1653e5b75505Sopenharmony_ci	if (!ser)
1654e5b75505Sopenharmony_ci		return NULL;
1655e5b75505Sopenharmony_ci
1656e5b75505Sopenharmony_ci	len = ASN1_STRING_length(ser) * 2 + 1;
1657e5b75505Sopenharmony_ci	serial_num = os_malloc(len);
1658e5b75505Sopenharmony_ci	if (!serial_num)
1659e5b75505Sopenharmony_ci		return NULL;
1660e5b75505Sopenharmony_ci	wpa_snprintf_hex_uppercase(serial_num, len,
1661e5b75505Sopenharmony_ci				   ASN1_STRING_get0_data(ser),
1662e5b75505Sopenharmony_ci				   ASN1_STRING_length(ser));
1663e5b75505Sopenharmony_ci	return serial_num;
1664e5b75505Sopenharmony_ci}
1665e5b75505Sopenharmony_ci
1666e5b75505Sopenharmony_ci
1667e5b75505Sopenharmony_ciint tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
1668e5b75505Sopenharmony_ci{
1669e5b75505Sopenharmony_ci	if (conn == NULL)
1670e5b75505Sopenharmony_ci		return -1;
1671e5b75505Sopenharmony_ci
1672e5b75505Sopenharmony_ci	/* Shutdown previous TLS connection without notifying the peer
1673e5b75505Sopenharmony_ci	 * because the connection was already terminated in practice
1674e5b75505Sopenharmony_ci	 * and "close notify" shutdown alert would confuse AS. */
1675e5b75505Sopenharmony_ci	SSL_set_quiet_shutdown(conn->ssl, 1);
1676e5b75505Sopenharmony_ci	SSL_shutdown(conn->ssl);
1677e5b75505Sopenharmony_ci	return SSL_clear(conn->ssl) == 1 ? 0 : -1;
1678e5b75505Sopenharmony_ci}
1679e5b75505Sopenharmony_ci
1680e5b75505Sopenharmony_ci
1681e5b75505Sopenharmony_cistatic int tls_match_altsubject_component(X509 *cert, int type,
1682e5b75505Sopenharmony_ci					  const char *value, size_t len)
1683e5b75505Sopenharmony_ci{
1684e5b75505Sopenharmony_ci	GENERAL_NAME *gen;
1685e5b75505Sopenharmony_ci	void *ext;
1686e5b75505Sopenharmony_ci	int found = 0;
1687e5b75505Sopenharmony_ci	stack_index_t i;
1688e5b75505Sopenharmony_ci
1689e5b75505Sopenharmony_ci	ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
1690e5b75505Sopenharmony_ci
1691e5b75505Sopenharmony_ci	for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
1692e5b75505Sopenharmony_ci		gen = sk_GENERAL_NAME_value(ext, i);
1693e5b75505Sopenharmony_ci		if (gen->type != type)
1694e5b75505Sopenharmony_ci			continue;
1695e5b75505Sopenharmony_ci		if (os_strlen((char *) gen->d.ia5->data) == len &&
1696e5b75505Sopenharmony_ci		    os_memcmp(value, gen->d.ia5->data, len) == 0)
1697e5b75505Sopenharmony_ci			found++;
1698e5b75505Sopenharmony_ci	}
1699e5b75505Sopenharmony_ci
1700e5b75505Sopenharmony_ci	sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
1701e5b75505Sopenharmony_ci
1702e5b75505Sopenharmony_ci	return found;
1703e5b75505Sopenharmony_ci}
1704e5b75505Sopenharmony_ci
1705e5b75505Sopenharmony_ci
1706e5b75505Sopenharmony_cistatic int tls_match_altsubject(X509 *cert, const char *match)
1707e5b75505Sopenharmony_ci{
1708e5b75505Sopenharmony_ci	int type;
1709e5b75505Sopenharmony_ci	const char *pos, *end;
1710e5b75505Sopenharmony_ci	size_t len;
1711e5b75505Sopenharmony_ci
1712e5b75505Sopenharmony_ci	pos = match;
1713e5b75505Sopenharmony_ci	do {
1714e5b75505Sopenharmony_ci		if (os_strncmp(pos, "EMAIL:", 6) == 0) {
1715e5b75505Sopenharmony_ci			type = GEN_EMAIL;
1716e5b75505Sopenharmony_ci			pos += 6;
1717e5b75505Sopenharmony_ci		} else if (os_strncmp(pos, "DNS:", 4) == 0) {
1718e5b75505Sopenharmony_ci			type = GEN_DNS;
1719e5b75505Sopenharmony_ci			pos += 4;
1720e5b75505Sopenharmony_ci		} else if (os_strncmp(pos, "URI:", 4) == 0) {
1721e5b75505Sopenharmony_ci			type = GEN_URI;
1722e5b75505Sopenharmony_ci			pos += 4;
1723e5b75505Sopenharmony_ci		} else {
1724e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO, "TLS: Invalid altSubjectName "
1725e5b75505Sopenharmony_ci				   "match '%s'", pos);
1726e5b75505Sopenharmony_ci			return 0;
1727e5b75505Sopenharmony_ci		}
1728e5b75505Sopenharmony_ci		end = os_strchr(pos, ';');
1729e5b75505Sopenharmony_ci		while (end) {
1730e5b75505Sopenharmony_ci			if (os_strncmp(end + 1, "EMAIL:", 6) == 0 ||
1731e5b75505Sopenharmony_ci			    os_strncmp(end + 1, "DNS:", 4) == 0 ||
1732e5b75505Sopenharmony_ci			    os_strncmp(end + 1, "URI:", 4) == 0)
1733e5b75505Sopenharmony_ci				break;
1734e5b75505Sopenharmony_ci			end = os_strchr(end + 1, ';');
1735e5b75505Sopenharmony_ci		}
1736e5b75505Sopenharmony_ci		if (end)
1737e5b75505Sopenharmony_ci			len = end - pos;
1738e5b75505Sopenharmony_ci		else
1739e5b75505Sopenharmony_ci			len = os_strlen(pos);
1740e5b75505Sopenharmony_ci		if (tls_match_altsubject_component(cert, type, pos, len) > 0)
1741e5b75505Sopenharmony_ci			return 1;
1742e5b75505Sopenharmony_ci		pos = end + 1;
1743e5b75505Sopenharmony_ci	} while (end);
1744e5b75505Sopenharmony_ci
1745e5b75505Sopenharmony_ci	return 0;
1746e5b75505Sopenharmony_ci}
1747e5b75505Sopenharmony_ci
1748e5b75505Sopenharmony_ci
1749e5b75505Sopenharmony_ci#ifndef CONFIG_NATIVE_WINDOWS
1750e5b75505Sopenharmony_cistatic int domain_suffix_match(const u8 *val, size_t len, const char *match,
1751e5b75505Sopenharmony_ci			       size_t match_len, int full)
1752e5b75505Sopenharmony_ci{
1753e5b75505Sopenharmony_ci	size_t i;
1754e5b75505Sopenharmony_ci
1755e5b75505Sopenharmony_ci	/* Check for embedded nuls that could mess up suffix matching */
1756e5b75505Sopenharmony_ci	for (i = 0; i < len; i++) {
1757e5b75505Sopenharmony_ci		if (val[i] == '\0') {
1758e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "TLS: Embedded null in a string - reject");
1759e5b75505Sopenharmony_ci			return 0;
1760e5b75505Sopenharmony_ci		}
1761e5b75505Sopenharmony_ci	}
1762e5b75505Sopenharmony_ci
1763e5b75505Sopenharmony_ci	if (match_len > len || (full && match_len != len))
1764e5b75505Sopenharmony_ci		return 0;
1765e5b75505Sopenharmony_ci
1766e5b75505Sopenharmony_ci	if (os_strncasecmp((const char *) val + len - match_len, match,
1767e5b75505Sopenharmony_ci			   match_len) != 0)
1768e5b75505Sopenharmony_ci		return 0; /* no match */
1769e5b75505Sopenharmony_ci
1770e5b75505Sopenharmony_ci	if (match_len == len)
1771e5b75505Sopenharmony_ci		return 1; /* exact match */
1772e5b75505Sopenharmony_ci
1773e5b75505Sopenharmony_ci	if (val[len - match_len - 1] == '.')
1774e5b75505Sopenharmony_ci		return 1; /* full label match completes suffix match */
1775e5b75505Sopenharmony_ci
1776e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "TLS: Reject due to incomplete label match");
1777e5b75505Sopenharmony_ci	return 0;
1778e5b75505Sopenharmony_ci}
1779e5b75505Sopenharmony_ci#endif /* CONFIG_NATIVE_WINDOWS */
1780e5b75505Sopenharmony_ci
1781e5b75505Sopenharmony_ci
1782e5b75505Sopenharmony_cistruct tls_dn_field_order_cnt {
1783e5b75505Sopenharmony_ci	u8 cn;
1784e5b75505Sopenharmony_ci	u8 c;
1785e5b75505Sopenharmony_ci	u8 l;
1786e5b75505Sopenharmony_ci	u8 st;
1787e5b75505Sopenharmony_ci	u8 o;
1788e5b75505Sopenharmony_ci	u8 ou;
1789e5b75505Sopenharmony_ci	u8 email;
1790e5b75505Sopenharmony_ci};
1791e5b75505Sopenharmony_ci
1792e5b75505Sopenharmony_ci
1793e5b75505Sopenharmony_cistatic int get_dn_field_index(const struct tls_dn_field_order_cnt *dn_cnt,
1794e5b75505Sopenharmony_ci			      int nid)
1795e5b75505Sopenharmony_ci{
1796e5b75505Sopenharmony_ci	switch (nid) {
1797e5b75505Sopenharmony_ci	case NID_commonName:
1798e5b75505Sopenharmony_ci		return dn_cnt->cn;
1799e5b75505Sopenharmony_ci	case NID_countryName:
1800e5b75505Sopenharmony_ci		return dn_cnt->c;
1801e5b75505Sopenharmony_ci	case NID_localityName:
1802e5b75505Sopenharmony_ci		return dn_cnt->l;
1803e5b75505Sopenharmony_ci	case NID_stateOrProvinceName:
1804e5b75505Sopenharmony_ci		return dn_cnt->st;
1805e5b75505Sopenharmony_ci	case NID_organizationName:
1806e5b75505Sopenharmony_ci		return dn_cnt->o;
1807e5b75505Sopenharmony_ci	case NID_organizationalUnitName:
1808e5b75505Sopenharmony_ci		return dn_cnt->ou;
1809e5b75505Sopenharmony_ci	case NID_pkcs9_emailAddress:
1810e5b75505Sopenharmony_ci		return dn_cnt->email;
1811e5b75505Sopenharmony_ci	default:
1812e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR,
1813e5b75505Sopenharmony_ci			   "TLS: Unknown NID '%d' in check_cert_subject",
1814e5b75505Sopenharmony_ci			   nid);
1815e5b75505Sopenharmony_ci		return -1;
1816e5b75505Sopenharmony_ci	}
1817e5b75505Sopenharmony_ci}
1818e5b75505Sopenharmony_ci
1819e5b75505Sopenharmony_ci
1820e5b75505Sopenharmony_ci/**
1821e5b75505Sopenharmony_ci * match_dn_field - Match configuration DN field against Certificate DN field
1822e5b75505Sopenharmony_ci * @cert: Certificate
1823e5b75505Sopenharmony_ci * @nid: NID of DN field
1824e5b75505Sopenharmony_ci * @field: Field name
1825e5b75505Sopenharmony_ci * @value DN field value which is passed from configuration
1826e5b75505Sopenharmony_ci *	e.g., if configuration have C=US and this argument will point to US.
1827e5b75505Sopenharmony_ci * @dn_cnt: DN matching context
1828e5b75505Sopenharmony_ci * Returns: 1 on success and 0 on failure
1829e5b75505Sopenharmony_ci */
1830e5b75505Sopenharmony_cistatic int match_dn_field(const X509 *cert, int nid, const char *field,
1831e5b75505Sopenharmony_ci			  const char *value,
1832e5b75505Sopenharmony_ci			  const struct tls_dn_field_order_cnt *dn_cnt)
1833e5b75505Sopenharmony_ci{
1834e5b75505Sopenharmony_ci	int i, ret = 0, len, config_dn_field_index, match_index = 0;
1835e5b75505Sopenharmony_ci	X509_NAME *name;
1836e5b75505Sopenharmony_ci
1837e5b75505Sopenharmony_ci	len = os_strlen(value);
1838e5b75505Sopenharmony_ci	name = X509_get_subject_name((X509 *) cert);
1839e5b75505Sopenharmony_ci
1840e5b75505Sopenharmony_ci	/* Assign incremented cnt for every field of DN to check DN field in
1841e5b75505Sopenharmony_ci	 * right order */
1842e5b75505Sopenharmony_ci	config_dn_field_index = get_dn_field_index(dn_cnt, nid);
1843e5b75505Sopenharmony_ci	if (config_dn_field_index < 0)
1844e5b75505Sopenharmony_ci		return 0;
1845e5b75505Sopenharmony_ci
1846e5b75505Sopenharmony_ci	/* Fetch value based on NID */
1847e5b75505Sopenharmony_ci	for (i = -1; (i = X509_NAME_get_index_by_NID(name, nid, i)) > -1;) {
1848e5b75505Sopenharmony_ci		X509_NAME_ENTRY *e;
1849e5b75505Sopenharmony_ci		ASN1_STRING *cn;
1850e5b75505Sopenharmony_ci
1851e5b75505Sopenharmony_ci		e = X509_NAME_get_entry(name, i);
1852e5b75505Sopenharmony_ci		if (!e)
1853e5b75505Sopenharmony_ci			continue;
1854e5b75505Sopenharmony_ci
1855e5b75505Sopenharmony_ci		cn = X509_NAME_ENTRY_get_data(e);
1856e5b75505Sopenharmony_ci		if (!cn)
1857e5b75505Sopenharmony_ci			continue;
1858e5b75505Sopenharmony_ci
1859e5b75505Sopenharmony_ci		match_index++;
1860e5b75505Sopenharmony_ci
1861e5b75505Sopenharmony_ci		/* check for more than one DN field with same name */
1862e5b75505Sopenharmony_ci		if (match_index != config_dn_field_index)
1863e5b75505Sopenharmony_ci			continue;
1864e5b75505Sopenharmony_ci
1865e5b75505Sopenharmony_ci		/* Check wildcard at the right end side */
1866e5b75505Sopenharmony_ci		/* E.g., if OU=develop* mentioned in configuration, allow 'OU'
1867e5b75505Sopenharmony_ci		 * of the subject in the client certificate to start with
1868e5b75505Sopenharmony_ci		 * 'develop' */
1869e5b75505Sopenharmony_ci		if (len > 0 && value[len - 1] == '*') {
1870e5b75505Sopenharmony_ci			/* Compare actual certificate DN field value with
1871e5b75505Sopenharmony_ci			 * configuration DN field value up to the specified
1872e5b75505Sopenharmony_ci			 * length. */
1873e5b75505Sopenharmony_ci			ret = ASN1_STRING_length(cn) >= len - 1 &&
1874e5b75505Sopenharmony_ci				os_memcmp(ASN1_STRING_get0_data(cn), value,
1875e5b75505Sopenharmony_ci					  len - 1) == 0;
1876e5b75505Sopenharmony_ci		} else {
1877e5b75505Sopenharmony_ci			/* Compare actual certificate DN field value with
1878e5b75505Sopenharmony_ci			 * configuration DN field value */
1879e5b75505Sopenharmony_ci			ret = ASN1_STRING_length(cn) == len &&
1880e5b75505Sopenharmony_ci				os_memcmp(ASN1_STRING_get0_data(cn), value,
1881e5b75505Sopenharmony_ci					  len) == 0;
1882e5b75505Sopenharmony_ci		}
1883e5b75505Sopenharmony_ci		if (!ret) {
1884e5b75505Sopenharmony_ci			wpa_printf(MSG_ERROR,
1885e5b75505Sopenharmony_ci				   "OpenSSL: Failed to match %s '%s' with certificate DN field value '%s'",
1886e5b75505Sopenharmony_ci				   field, value, ASN1_STRING_get0_data(cn));
1887e5b75505Sopenharmony_ci		}
1888e5b75505Sopenharmony_ci		break;
1889e5b75505Sopenharmony_ci	}
1890e5b75505Sopenharmony_ci
1891e5b75505Sopenharmony_ci	return ret;
1892e5b75505Sopenharmony_ci}
1893e5b75505Sopenharmony_ci
1894e5b75505Sopenharmony_ci
1895e5b75505Sopenharmony_ci/**
1896e5b75505Sopenharmony_ci * get_value_from_field - Get value from DN field
1897e5b75505Sopenharmony_ci * @cert: Certificate
1898e5b75505Sopenharmony_ci * @field_str: DN field string which is passed from configuration file (e.g.,
1899e5b75505Sopenharmony_ci *	 C=US)
1900e5b75505Sopenharmony_ci * @dn_cnt: DN matching context
1901e5b75505Sopenharmony_ci * Returns: 1 on success and 0 on failure
1902e5b75505Sopenharmony_ci */
1903e5b75505Sopenharmony_cistatic int get_value_from_field(const X509 *cert, char *field_str,
1904e5b75505Sopenharmony_ci				struct tls_dn_field_order_cnt *dn_cnt)
1905e5b75505Sopenharmony_ci{
1906e5b75505Sopenharmony_ci	int nid;
1907e5b75505Sopenharmony_ci	char *context = NULL, *name, *value;
1908e5b75505Sopenharmony_ci
1909e5b75505Sopenharmony_ci	if (os_strcmp(field_str, "*") == 0)
1910e5b75505Sopenharmony_ci		return 1; /* wildcard matches everything */
1911e5b75505Sopenharmony_ci
1912e5b75505Sopenharmony_ci	name = str_token(field_str, "=", &context);
1913e5b75505Sopenharmony_ci	if (!name)
1914e5b75505Sopenharmony_ci		return 0;
1915e5b75505Sopenharmony_ci
1916e5b75505Sopenharmony_ci	/* Compare all configured DN fields and assign nid based on that to
1917e5b75505Sopenharmony_ci	 * fetch correct value from certificate subject */
1918e5b75505Sopenharmony_ci	if (os_strcmp(name, "CN") == 0) {
1919e5b75505Sopenharmony_ci		nid = NID_commonName;
1920e5b75505Sopenharmony_ci		dn_cnt->cn++;
1921e5b75505Sopenharmony_ci	} else if(os_strcmp(name, "C") == 0) {
1922e5b75505Sopenharmony_ci		nid = NID_countryName;
1923e5b75505Sopenharmony_ci		dn_cnt->c++;
1924e5b75505Sopenharmony_ci	} else if (os_strcmp(name, "L") == 0) {
1925e5b75505Sopenharmony_ci		nid = NID_localityName;
1926e5b75505Sopenharmony_ci		dn_cnt->l++;
1927e5b75505Sopenharmony_ci	} else if (os_strcmp(name, "ST") == 0) {
1928e5b75505Sopenharmony_ci		nid = NID_stateOrProvinceName;
1929e5b75505Sopenharmony_ci		dn_cnt->st++;
1930e5b75505Sopenharmony_ci	} else if (os_strcmp(name, "O") == 0) {
1931e5b75505Sopenharmony_ci		nid = NID_organizationName;
1932e5b75505Sopenharmony_ci		dn_cnt->o++;
1933e5b75505Sopenharmony_ci	} else if (os_strcmp(name, "OU") == 0) {
1934e5b75505Sopenharmony_ci		nid = NID_organizationalUnitName;
1935e5b75505Sopenharmony_ci		dn_cnt->ou++;
1936e5b75505Sopenharmony_ci	} else if (os_strcmp(name, "emailAddress") == 0) {
1937e5b75505Sopenharmony_ci		nid = NID_pkcs9_emailAddress;
1938e5b75505Sopenharmony_ci		dn_cnt->email++;
1939e5b75505Sopenharmony_ci	} else {
1940e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR,
1941e5b75505Sopenharmony_ci			"TLS: Unknown field '%s' in check_cert_subject", name);
1942e5b75505Sopenharmony_ci		return 0;
1943e5b75505Sopenharmony_ci	}
1944e5b75505Sopenharmony_ci
1945e5b75505Sopenharmony_ci	value = str_token(field_str, "=", &context);
1946e5b75505Sopenharmony_ci	if (!value) {
1947e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR,
1948e5b75505Sopenharmony_ci			   "TLS: Distinguished Name field '%s' value is not defined in check_cert_subject",
1949e5b75505Sopenharmony_ci			   name);
1950e5b75505Sopenharmony_ci		return 0;
1951e5b75505Sopenharmony_ci	}
1952e5b75505Sopenharmony_ci
1953e5b75505Sopenharmony_ci	return match_dn_field(cert, nid, name, value, dn_cnt);
1954e5b75505Sopenharmony_ci}
1955e5b75505Sopenharmony_ci
1956e5b75505Sopenharmony_ci
1957e5b75505Sopenharmony_ci/**
1958e5b75505Sopenharmony_ci * tls_match_dn_field - Match subject DN field with check_cert_subject
1959e5b75505Sopenharmony_ci * @cert: Certificate
1960e5b75505Sopenharmony_ci * @match: check_cert_subject string
1961e5b75505Sopenharmony_ci * Returns: Return 1 on success and 0 on failure
1962e5b75505Sopenharmony_ci*/
1963e5b75505Sopenharmony_cistatic int tls_match_dn_field(X509 *cert, const char *match)
1964e5b75505Sopenharmony_ci{
1965e5b75505Sopenharmony_ci	const char *token, *last = NULL;
1966e5b75505Sopenharmony_ci	char field[256];
1967e5b75505Sopenharmony_ci	struct tls_dn_field_order_cnt dn_cnt;
1968e5b75505Sopenharmony_ci
1969e5b75505Sopenharmony_ci	os_memset(&dn_cnt, 0, sizeof(dn_cnt));
1970e5b75505Sopenharmony_ci
1971e5b75505Sopenharmony_ci	/* Maximum length of each DN field is 255 characters */
1972e5b75505Sopenharmony_ci
1973e5b75505Sopenharmony_ci	/* Process each '/' delimited field */
1974e5b75505Sopenharmony_ci	while ((token = cstr_token(match, "/", &last))) {
1975e5b75505Sopenharmony_ci		if (last - token >= (int) sizeof(field)) {
1976e5b75505Sopenharmony_ci			wpa_printf(MSG_ERROR,
1977e5b75505Sopenharmony_ci				   "OpenSSL: Too long DN matching field value in '%s'",
1978e5b75505Sopenharmony_ci				   match);
1979e5b75505Sopenharmony_ci			return 0;
1980e5b75505Sopenharmony_ci		}
1981e5b75505Sopenharmony_ci		os_memcpy(field, token, last - token);
1982e5b75505Sopenharmony_ci		field[last - token] = '\0';
1983e5b75505Sopenharmony_ci
1984e5b75505Sopenharmony_ci		if (!get_value_from_field(cert, field, &dn_cnt)) {
1985e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "OpenSSL: No match for DN '%s'",
1986e5b75505Sopenharmony_ci				   field);
1987e5b75505Sopenharmony_ci			return 0;
1988e5b75505Sopenharmony_ci		}
1989e5b75505Sopenharmony_ci	}
1990e5b75505Sopenharmony_ci
1991e5b75505Sopenharmony_ci	return 1;
1992e5b75505Sopenharmony_ci}
1993e5b75505Sopenharmony_ci
1994e5b75505Sopenharmony_ci
1995e5b75505Sopenharmony_ci#ifndef CONFIG_NATIVE_WINDOWS
1996e5b75505Sopenharmony_cistatic int tls_match_suffix_helper(X509 *cert, const char *match,
1997e5b75505Sopenharmony_ci				   size_t match_len, int full)
1998e5b75505Sopenharmony_ci{
1999e5b75505Sopenharmony_ci	GENERAL_NAME *gen;
2000e5b75505Sopenharmony_ci	void *ext;
2001e5b75505Sopenharmony_ci	int i;
2002e5b75505Sopenharmony_ci	stack_index_t j;
2003e5b75505Sopenharmony_ci	int dns_name = 0;
2004e5b75505Sopenharmony_ci	X509_NAME *name;
2005e5b75505Sopenharmony_ci
2006e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "TLS: Match domain against %s%s",
2007e5b75505Sopenharmony_ci		   full ? "": "suffix ", match);
2008e5b75505Sopenharmony_ci
2009e5b75505Sopenharmony_ci	ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
2010e5b75505Sopenharmony_ci
2011e5b75505Sopenharmony_ci	for (j = 0; ext && j < sk_GENERAL_NAME_num(ext); j++) {
2012e5b75505Sopenharmony_ci		gen = sk_GENERAL_NAME_value(ext, j);
2013e5b75505Sopenharmony_ci		if (gen->type != GEN_DNS)
2014e5b75505Sopenharmony_ci			continue;
2015e5b75505Sopenharmony_ci		dns_name++;
2016e5b75505Sopenharmony_ci		wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate dNSName",
2017e5b75505Sopenharmony_ci				  gen->d.dNSName->data,
2018e5b75505Sopenharmony_ci				  gen->d.dNSName->length);
2019e5b75505Sopenharmony_ci		if (domain_suffix_match(gen->d.dNSName->data,
2020e5b75505Sopenharmony_ci					gen->d.dNSName->length,
2021e5b75505Sopenharmony_ci					match, match_len, full) == 1) {
2022e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "TLS: %s in dNSName found",
2023e5b75505Sopenharmony_ci				   full ? "Match" : "Suffix match");
2024e5b75505Sopenharmony_ci			sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
2025e5b75505Sopenharmony_ci			return 1;
2026e5b75505Sopenharmony_ci		}
2027e5b75505Sopenharmony_ci	}
2028e5b75505Sopenharmony_ci	sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
2029e5b75505Sopenharmony_ci
2030e5b75505Sopenharmony_ci	if (dns_name) {
2031e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "TLS: None of the dNSName(s) matched");
2032e5b75505Sopenharmony_ci		return 0;
2033e5b75505Sopenharmony_ci	}
2034e5b75505Sopenharmony_ci
2035e5b75505Sopenharmony_ci	name = X509_get_subject_name(cert);
2036e5b75505Sopenharmony_ci	i = -1;
2037e5b75505Sopenharmony_ci	for (;;) {
2038e5b75505Sopenharmony_ci		X509_NAME_ENTRY *e;
2039e5b75505Sopenharmony_ci		ASN1_STRING *cn;
2040e5b75505Sopenharmony_ci
2041e5b75505Sopenharmony_ci		i = X509_NAME_get_index_by_NID(name, NID_commonName, i);
2042e5b75505Sopenharmony_ci		if (i == -1)
2043e5b75505Sopenharmony_ci			break;
2044e5b75505Sopenharmony_ci		e = X509_NAME_get_entry(name, i);
2045e5b75505Sopenharmony_ci		if (e == NULL)
2046e5b75505Sopenharmony_ci			continue;
2047e5b75505Sopenharmony_ci		cn = X509_NAME_ENTRY_get_data(e);
2048e5b75505Sopenharmony_ci		if (cn == NULL)
2049e5b75505Sopenharmony_ci			continue;
2050e5b75505Sopenharmony_ci		wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate commonName",
2051e5b75505Sopenharmony_ci				  cn->data, cn->length);
2052e5b75505Sopenharmony_ci		if (domain_suffix_match(cn->data, cn->length,
2053e5b75505Sopenharmony_ci					match, match_len, full) == 1) {
2054e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "TLS: %s in commonName found",
2055e5b75505Sopenharmony_ci				   full ? "Match" : "Suffix match");
2056e5b75505Sopenharmony_ci			return 1;
2057e5b75505Sopenharmony_ci		}
2058e5b75505Sopenharmony_ci	}
2059e5b75505Sopenharmony_ci
2060e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "TLS: No CommonName %smatch found",
2061e5b75505Sopenharmony_ci		   full ? "": "suffix ");
2062e5b75505Sopenharmony_ci	return 0;
2063e5b75505Sopenharmony_ci}
2064e5b75505Sopenharmony_ci#endif /* CONFIG_NATIVE_WINDOWS */
2065e5b75505Sopenharmony_ci
2066e5b75505Sopenharmony_ci
2067e5b75505Sopenharmony_cistatic int tls_match_suffix(X509 *cert, const char *match, int full)
2068e5b75505Sopenharmony_ci{
2069e5b75505Sopenharmony_ci#ifdef CONFIG_NATIVE_WINDOWS
2070e5b75505Sopenharmony_ci	/* wincrypt.h has conflicting X509_NAME definition */
2071e5b75505Sopenharmony_ci	return -1;
2072e5b75505Sopenharmony_ci#else /* CONFIG_NATIVE_WINDOWS */
2073e5b75505Sopenharmony_ci	const char *token, *last = NULL;
2074e5b75505Sopenharmony_ci
2075e5b75505Sopenharmony_ci	/* Process each match alternative separately until a match is found */
2076e5b75505Sopenharmony_ci	while ((token = cstr_token(match, ";", &last))) {
2077e5b75505Sopenharmony_ci		if (tls_match_suffix_helper(cert, token, last - token, full))
2078e5b75505Sopenharmony_ci			return 1;
2079e5b75505Sopenharmony_ci	}
2080e5b75505Sopenharmony_ci
2081e5b75505Sopenharmony_ci	return 0;
2082e5b75505Sopenharmony_ci#endif /* CONFIG_NATIVE_WINDOWS */
2083e5b75505Sopenharmony_ci}
2084e5b75505Sopenharmony_ci
2085e5b75505Sopenharmony_ci
2086e5b75505Sopenharmony_cistatic enum tls_fail_reason openssl_tls_fail_reason(int err)
2087e5b75505Sopenharmony_ci{
2088e5b75505Sopenharmony_ci	switch (err) {
2089e5b75505Sopenharmony_ci	case X509_V_ERR_CERT_REVOKED:
2090e5b75505Sopenharmony_ci		return TLS_FAIL_REVOKED;
2091e5b75505Sopenharmony_ci	case X509_V_ERR_CERT_NOT_YET_VALID:
2092e5b75505Sopenharmony_ci	case X509_V_ERR_CRL_NOT_YET_VALID:
2093e5b75505Sopenharmony_ci		return TLS_FAIL_NOT_YET_VALID;
2094e5b75505Sopenharmony_ci	case X509_V_ERR_CERT_HAS_EXPIRED:
2095e5b75505Sopenharmony_ci	case X509_V_ERR_CRL_HAS_EXPIRED:
2096e5b75505Sopenharmony_ci		return TLS_FAIL_EXPIRED;
2097e5b75505Sopenharmony_ci	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
2098e5b75505Sopenharmony_ci	case X509_V_ERR_UNABLE_TO_GET_CRL:
2099e5b75505Sopenharmony_ci	case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
2100e5b75505Sopenharmony_ci	case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
2101e5b75505Sopenharmony_ci	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
2102e5b75505Sopenharmony_ci	case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
2103e5b75505Sopenharmony_ci	case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
2104e5b75505Sopenharmony_ci	case X509_V_ERR_CERT_CHAIN_TOO_LONG:
2105e5b75505Sopenharmony_ci	case X509_V_ERR_PATH_LENGTH_EXCEEDED:
2106e5b75505Sopenharmony_ci	case X509_V_ERR_INVALID_CA:
2107e5b75505Sopenharmony_ci		return TLS_FAIL_UNTRUSTED;
2108e5b75505Sopenharmony_ci	case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
2109e5b75505Sopenharmony_ci	case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
2110e5b75505Sopenharmony_ci	case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
2111e5b75505Sopenharmony_ci	case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
2112e5b75505Sopenharmony_ci	case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
2113e5b75505Sopenharmony_ci	case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
2114e5b75505Sopenharmony_ci	case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
2115e5b75505Sopenharmony_ci	case X509_V_ERR_CERT_UNTRUSTED:
2116e5b75505Sopenharmony_ci	case X509_V_ERR_CERT_REJECTED:
2117e5b75505Sopenharmony_ci		return TLS_FAIL_BAD_CERTIFICATE;
2118e5b75505Sopenharmony_ci	default:
2119e5b75505Sopenharmony_ci		return TLS_FAIL_UNSPECIFIED;
2120e5b75505Sopenharmony_ci	}
2121e5b75505Sopenharmony_ci}
2122e5b75505Sopenharmony_ci
2123e5b75505Sopenharmony_ci
2124e5b75505Sopenharmony_cistatic struct wpabuf * get_x509_cert(X509 *cert)
2125e5b75505Sopenharmony_ci{
2126e5b75505Sopenharmony_ci	struct wpabuf *buf;
2127e5b75505Sopenharmony_ci	u8 *tmp;
2128e5b75505Sopenharmony_ci
2129e5b75505Sopenharmony_ci	int cert_len = i2d_X509(cert, NULL);
2130e5b75505Sopenharmony_ci	if (cert_len <= 0)
2131e5b75505Sopenharmony_ci		return NULL;
2132e5b75505Sopenharmony_ci
2133e5b75505Sopenharmony_ci	buf = wpabuf_alloc(cert_len);
2134e5b75505Sopenharmony_ci	if (buf == NULL)
2135e5b75505Sopenharmony_ci		return NULL;
2136e5b75505Sopenharmony_ci
2137e5b75505Sopenharmony_ci	tmp = wpabuf_put(buf, cert_len);
2138e5b75505Sopenharmony_ci	i2d_X509(cert, &tmp);
2139e5b75505Sopenharmony_ci	return buf;
2140e5b75505Sopenharmony_ci}
2141e5b75505Sopenharmony_ci
2142e5b75505Sopenharmony_ci
2143e5b75505Sopenharmony_cistatic void openssl_tls_fail_event(struct tls_connection *conn,
2144e5b75505Sopenharmony_ci				   X509 *err_cert, int err, int depth,
2145e5b75505Sopenharmony_ci				   const char *subject, const char *err_str,
2146e5b75505Sopenharmony_ci				   enum tls_fail_reason reason)
2147e5b75505Sopenharmony_ci{
2148e5b75505Sopenharmony_ci	union tls_event_data ev;
2149e5b75505Sopenharmony_ci	struct wpabuf *cert = NULL;
2150e5b75505Sopenharmony_ci	struct tls_context *context = conn->context;
2151e5b75505Sopenharmony_ci
2152e5b75505Sopenharmony_ci	if (context->event_cb == NULL)
2153e5b75505Sopenharmony_ci		return;
2154e5b75505Sopenharmony_ci
2155e5b75505Sopenharmony_ci	cert = get_x509_cert(err_cert);
2156e5b75505Sopenharmony_ci	os_memset(&ev, 0, sizeof(ev));
2157e5b75505Sopenharmony_ci	ev.cert_fail.reason = reason != TLS_FAIL_UNSPECIFIED ?
2158e5b75505Sopenharmony_ci		reason : openssl_tls_fail_reason(err);
2159e5b75505Sopenharmony_ci	ev.cert_fail.depth = depth;
2160e5b75505Sopenharmony_ci	ev.cert_fail.subject = subject;
2161e5b75505Sopenharmony_ci	ev.cert_fail.reason_txt = err_str;
2162e5b75505Sopenharmony_ci	ev.cert_fail.cert = cert;
2163e5b75505Sopenharmony_ci	context->event_cb(context->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
2164e5b75505Sopenharmony_ci	wpabuf_free(cert);
2165e5b75505Sopenharmony_ci}
2166e5b75505Sopenharmony_ci
2167e5b75505Sopenharmony_ci
2168e5b75505Sopenharmony_cistatic int openssl_cert_tod(X509 *cert)
2169e5b75505Sopenharmony_ci{
2170e5b75505Sopenharmony_ci	CERTIFICATEPOLICIES *ext;
2171e5b75505Sopenharmony_ci	stack_index_t i;
2172e5b75505Sopenharmony_ci	char buf[100];
2173e5b75505Sopenharmony_ci	int res;
2174e5b75505Sopenharmony_ci	int tod = 0;
2175e5b75505Sopenharmony_ci
2176e5b75505Sopenharmony_ci	ext = X509_get_ext_d2i(cert, NID_certificate_policies, NULL, NULL);
2177e5b75505Sopenharmony_ci	if (!ext)
2178e5b75505Sopenharmony_ci		return 0;
2179e5b75505Sopenharmony_ci
2180e5b75505Sopenharmony_ci	for (i = 0; i < sk_POLICYINFO_num(ext); i++) {
2181e5b75505Sopenharmony_ci		POLICYINFO *policy;
2182e5b75505Sopenharmony_ci
2183e5b75505Sopenharmony_ci		policy = sk_POLICYINFO_value(ext, i);
2184e5b75505Sopenharmony_ci		res = OBJ_obj2txt(buf, sizeof(buf), policy->policyid, 0);
2185e5b75505Sopenharmony_ci		if (res < 0 || (size_t) res >= sizeof(buf))
2186e5b75505Sopenharmony_ci			continue;
2187e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: Certificate Policy %s", buf);
2188e5b75505Sopenharmony_ci		if (os_strcmp(buf, "1.3.6.1.4.1.40808.1.3.1") == 0)
2189e5b75505Sopenharmony_ci			tod = 1;
2190e5b75505Sopenharmony_ci	}
2191e5b75505Sopenharmony_ci
2192e5b75505Sopenharmony_ci	return tod;
2193e5b75505Sopenharmony_ci}
2194e5b75505Sopenharmony_ci
2195e5b75505Sopenharmony_ci
2196e5b75505Sopenharmony_cistatic void openssl_tls_cert_event(struct tls_connection *conn,
2197e5b75505Sopenharmony_ci				   X509 *err_cert, int depth,
2198e5b75505Sopenharmony_ci				   const char *subject)
2199e5b75505Sopenharmony_ci{
2200e5b75505Sopenharmony_ci	struct wpabuf *cert = NULL;
2201e5b75505Sopenharmony_ci	union tls_event_data ev;
2202e5b75505Sopenharmony_ci	struct tls_context *context = conn->context;
2203e5b75505Sopenharmony_ci	char *altsubject[TLS_MAX_ALT_SUBJECT];
2204e5b75505Sopenharmony_ci	int alt, num_altsubject = 0;
2205e5b75505Sopenharmony_ci	GENERAL_NAME *gen;
2206e5b75505Sopenharmony_ci	void *ext;
2207e5b75505Sopenharmony_ci	stack_index_t i;
2208e5b75505Sopenharmony_ci	ASN1_INTEGER *ser;
2209e5b75505Sopenharmony_ci	char serial_num[128];
2210e5b75505Sopenharmony_ci#ifdef CONFIG_SHA256
2211e5b75505Sopenharmony_ci	u8 hash[32];
2212e5b75505Sopenharmony_ci#endif /* CONFIG_SHA256 */
2213e5b75505Sopenharmony_ci
2214e5b75505Sopenharmony_ci	if (context->event_cb == NULL)
2215e5b75505Sopenharmony_ci		return;
2216e5b75505Sopenharmony_ci
2217e5b75505Sopenharmony_ci	os_memset(&ev, 0, sizeof(ev));
2218e5b75505Sopenharmony_ci	if (conn->cert_probe || (conn->flags & TLS_CONN_EXT_CERT_CHECK) ||
2219e5b75505Sopenharmony_ci	    context->cert_in_cb) {
2220e5b75505Sopenharmony_ci		cert = get_x509_cert(err_cert);
2221e5b75505Sopenharmony_ci		ev.peer_cert.cert = cert;
2222e5b75505Sopenharmony_ci	}
2223e5b75505Sopenharmony_ci#ifdef CONFIG_SHA256
2224e5b75505Sopenharmony_ci	if (cert) {
2225e5b75505Sopenharmony_ci		const u8 *addr[1];
2226e5b75505Sopenharmony_ci		size_t len[1];
2227e5b75505Sopenharmony_ci		addr[0] = wpabuf_head(cert);
2228e5b75505Sopenharmony_ci		len[0] = wpabuf_len(cert);
2229e5b75505Sopenharmony_ci		if (sha256_vector(1, addr, len, hash) == 0) {
2230e5b75505Sopenharmony_ci			ev.peer_cert.hash = hash;
2231e5b75505Sopenharmony_ci			ev.peer_cert.hash_len = sizeof(hash);
2232e5b75505Sopenharmony_ci		}
2233e5b75505Sopenharmony_ci	}
2234e5b75505Sopenharmony_ci#endif /* CONFIG_SHA256 */
2235e5b75505Sopenharmony_ci	ev.peer_cert.depth = depth;
2236e5b75505Sopenharmony_ci	ev.peer_cert.subject = subject;
2237e5b75505Sopenharmony_ci
2238e5b75505Sopenharmony_ci	ser = X509_get_serialNumber(err_cert);
2239e5b75505Sopenharmony_ci	if (ser) {
2240e5b75505Sopenharmony_ci		wpa_snprintf_hex_uppercase(serial_num, sizeof(serial_num),
2241e5b75505Sopenharmony_ci					   ASN1_STRING_get0_data(ser),
2242e5b75505Sopenharmony_ci					   ASN1_STRING_length(ser));
2243e5b75505Sopenharmony_ci		ev.peer_cert.serial_num = serial_num;
2244e5b75505Sopenharmony_ci	}
2245e5b75505Sopenharmony_ci
2246e5b75505Sopenharmony_ci	ext = X509_get_ext_d2i(err_cert, NID_subject_alt_name, NULL, NULL);
2247e5b75505Sopenharmony_ci	for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
2248e5b75505Sopenharmony_ci		char *pos;
2249e5b75505Sopenharmony_ci
2250e5b75505Sopenharmony_ci		if (num_altsubject == TLS_MAX_ALT_SUBJECT)
2251e5b75505Sopenharmony_ci			break;
2252e5b75505Sopenharmony_ci		gen = sk_GENERAL_NAME_value(ext, i);
2253e5b75505Sopenharmony_ci		if (gen->type != GEN_EMAIL &&
2254e5b75505Sopenharmony_ci		    gen->type != GEN_DNS &&
2255e5b75505Sopenharmony_ci		    gen->type != GEN_URI)
2256e5b75505Sopenharmony_ci			continue;
2257e5b75505Sopenharmony_ci
2258e5b75505Sopenharmony_ci		pos = os_malloc(10 + gen->d.ia5->length + 1);
2259e5b75505Sopenharmony_ci		if (pos == NULL)
2260e5b75505Sopenharmony_ci			break;
2261e5b75505Sopenharmony_ci		altsubject[num_altsubject++] = pos;
2262e5b75505Sopenharmony_ci
2263e5b75505Sopenharmony_ci		switch (gen->type) {
2264e5b75505Sopenharmony_ci		case GEN_EMAIL:
2265e5b75505Sopenharmony_ci			os_memcpy(pos, "EMAIL:", 6);
2266e5b75505Sopenharmony_ci			pos += 6;
2267e5b75505Sopenharmony_ci			break;
2268e5b75505Sopenharmony_ci		case GEN_DNS:
2269e5b75505Sopenharmony_ci			os_memcpy(pos, "DNS:", 4);
2270e5b75505Sopenharmony_ci			pos += 4;
2271e5b75505Sopenharmony_ci			break;
2272e5b75505Sopenharmony_ci		case GEN_URI:
2273e5b75505Sopenharmony_ci			os_memcpy(pos, "URI:", 4);
2274e5b75505Sopenharmony_ci			pos += 4;
2275e5b75505Sopenharmony_ci			break;
2276e5b75505Sopenharmony_ci		}
2277e5b75505Sopenharmony_ci
2278e5b75505Sopenharmony_ci		os_memcpy(pos, gen->d.ia5->data, gen->d.ia5->length);
2279e5b75505Sopenharmony_ci		pos += gen->d.ia5->length;
2280e5b75505Sopenharmony_ci		*pos = '\0';
2281e5b75505Sopenharmony_ci	}
2282e5b75505Sopenharmony_ci	sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
2283e5b75505Sopenharmony_ci
2284e5b75505Sopenharmony_ci	for (alt = 0; alt < num_altsubject; alt++)
2285e5b75505Sopenharmony_ci		ev.peer_cert.altsubject[alt] = altsubject[alt];
2286e5b75505Sopenharmony_ci	ev.peer_cert.num_altsubject = num_altsubject;
2287e5b75505Sopenharmony_ci
2288e5b75505Sopenharmony_ci	ev.peer_cert.tod = openssl_cert_tod(err_cert);
2289e5b75505Sopenharmony_ci
2290e5b75505Sopenharmony_ci	context->event_cb(context->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
2291e5b75505Sopenharmony_ci	wpabuf_free(cert);
2292e5b75505Sopenharmony_ci	for (alt = 0; alt < num_altsubject; alt++)
2293e5b75505Sopenharmony_ci		os_free(altsubject[alt]);
2294e5b75505Sopenharmony_ci}
2295e5b75505Sopenharmony_ci
2296e5b75505Sopenharmony_ci
2297e5b75505Sopenharmony_cistatic int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
2298e5b75505Sopenharmony_ci{
2299e5b75505Sopenharmony_ci	char buf[256];
2300e5b75505Sopenharmony_ci	X509 *err_cert;
2301e5b75505Sopenharmony_ci	int err, depth;
2302e5b75505Sopenharmony_ci	SSL *ssl;
2303e5b75505Sopenharmony_ci	struct tls_connection *conn;
2304e5b75505Sopenharmony_ci	struct tls_context *context;
2305e5b75505Sopenharmony_ci	char *match, *altmatch, *suffix_match, *domain_match;
2306e5b75505Sopenharmony_ci	const char *check_cert_subject;
2307e5b75505Sopenharmony_ci	const char *err_str;
2308e5b75505Sopenharmony_ci
2309e5b75505Sopenharmony_ci	err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
2310e5b75505Sopenharmony_ci	if (!err_cert)
2311e5b75505Sopenharmony_ci		return 0;
2312e5b75505Sopenharmony_ci
2313e5b75505Sopenharmony_ci	err = X509_STORE_CTX_get_error(x509_ctx);
2314e5b75505Sopenharmony_ci	depth = X509_STORE_CTX_get_error_depth(x509_ctx);
2315e5b75505Sopenharmony_ci	ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
2316e5b75505Sopenharmony_ci					 SSL_get_ex_data_X509_STORE_CTX_idx());
2317e5b75505Sopenharmony_ci	X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
2318e5b75505Sopenharmony_ci
2319e5b75505Sopenharmony_ci	conn = SSL_get_app_data(ssl);
2320e5b75505Sopenharmony_ci	if (conn == NULL)
2321e5b75505Sopenharmony_ci		return 0;
2322e5b75505Sopenharmony_ci
2323e5b75505Sopenharmony_ci	if (depth == 0)
2324e5b75505Sopenharmony_ci		conn->peer_cert = err_cert;
2325e5b75505Sopenharmony_ci	else if (depth == 1)
2326e5b75505Sopenharmony_ci		conn->peer_issuer = err_cert;
2327e5b75505Sopenharmony_ci	else if (depth == 2)
2328e5b75505Sopenharmony_ci		conn->peer_issuer_issuer = err_cert;
2329e5b75505Sopenharmony_ci
2330e5b75505Sopenharmony_ci	context = conn->context;
2331e5b75505Sopenharmony_ci	match = conn->subject_match;
2332e5b75505Sopenharmony_ci	altmatch = conn->altsubject_match;
2333e5b75505Sopenharmony_ci	suffix_match = conn->suffix_match;
2334e5b75505Sopenharmony_ci	domain_match = conn->domain_match;
2335e5b75505Sopenharmony_ci
2336e5b75505Sopenharmony_ci	if (!preverify_ok && !conn->ca_cert_verify)
2337e5b75505Sopenharmony_ci		preverify_ok = 1;
2338e5b75505Sopenharmony_ci	if (!preverify_ok && depth > 0 && conn->server_cert_only)
2339e5b75505Sopenharmony_ci		preverify_ok = 1;
2340e5b75505Sopenharmony_ci	if (!preverify_ok && (conn->flags & TLS_CONN_DISABLE_TIME_CHECKS) &&
2341e5b75505Sopenharmony_ci	    (err == X509_V_ERR_CERT_HAS_EXPIRED ||
2342e5b75505Sopenharmony_ci	     err == X509_V_ERR_CERT_NOT_YET_VALID)) {
2343e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: Ignore certificate validity "
2344e5b75505Sopenharmony_ci			   "time mismatch");
2345e5b75505Sopenharmony_ci		preverify_ok = 1;
2346e5b75505Sopenharmony_ci	}
2347e5b75505Sopenharmony_ci	if (!preverify_ok && !conn->data->check_crl_strict &&
2348e5b75505Sopenharmony_ci	    (err == X509_V_ERR_CRL_HAS_EXPIRED ||
2349e5b75505Sopenharmony_ci	     err == X509_V_ERR_CRL_NOT_YET_VALID)) {
2350e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
2351e5b75505Sopenharmony_ci			   "OpenSSL: Ignore certificate validity CRL time mismatch");
2352e5b75505Sopenharmony_ci		preverify_ok = 1;
2353e5b75505Sopenharmony_ci	}
2354e5b75505Sopenharmony_ci
2355e5b75505Sopenharmony_ci	err_str = X509_verify_cert_error_string(err);
2356e5b75505Sopenharmony_ci
2357e5b75505Sopenharmony_ci#ifdef CONFIG_SHA256
2358e5b75505Sopenharmony_ci	/*
2359e5b75505Sopenharmony_ci	 * Do not require preverify_ok so we can explicity allow otherwise
2360e5b75505Sopenharmony_ci	 * invalid pinned server certificates.
2361e5b75505Sopenharmony_ci	 */
2362e5b75505Sopenharmony_ci	if (depth == 0 && conn->server_cert_only) {
2363e5b75505Sopenharmony_ci		struct wpabuf *cert;
2364e5b75505Sopenharmony_ci		cert = get_x509_cert(err_cert);
2365e5b75505Sopenharmony_ci		if (!cert) {
2366e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "OpenSSL: Could not fetch "
2367e5b75505Sopenharmony_ci				   "server certificate data");
2368e5b75505Sopenharmony_ci			preverify_ok = 0;
2369e5b75505Sopenharmony_ci		} else {
2370e5b75505Sopenharmony_ci			u8 hash[32];
2371e5b75505Sopenharmony_ci			const u8 *addr[1];
2372e5b75505Sopenharmony_ci			size_t len[1];
2373e5b75505Sopenharmony_ci			addr[0] = wpabuf_head(cert);
2374e5b75505Sopenharmony_ci			len[0] = wpabuf_len(cert);
2375e5b75505Sopenharmony_ci			if (sha256_vector(1, addr, len, hash) < 0 ||
2376e5b75505Sopenharmony_ci			    os_memcmp(conn->srv_cert_hash, hash, 32) != 0) {
2377e5b75505Sopenharmony_ci				err_str = "Server certificate mismatch";
2378e5b75505Sopenharmony_ci				err = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
2379e5b75505Sopenharmony_ci				preverify_ok = 0;
2380e5b75505Sopenharmony_ci			} else if (!preverify_ok) {
2381e5b75505Sopenharmony_ci				/*
2382e5b75505Sopenharmony_ci				 * Certificate matches pinned certificate, allow
2383e5b75505Sopenharmony_ci				 * regardless of other problems.
2384e5b75505Sopenharmony_ci				 */
2385e5b75505Sopenharmony_ci				wpa_printf(MSG_DEBUG,
2386e5b75505Sopenharmony_ci					   "OpenSSL: Ignore validation issues for a pinned server certificate");
2387e5b75505Sopenharmony_ci				preverify_ok = 1;
2388e5b75505Sopenharmony_ci			}
2389e5b75505Sopenharmony_ci			wpabuf_free(cert);
2390e5b75505Sopenharmony_ci		}
2391e5b75505Sopenharmony_ci	}
2392e5b75505Sopenharmony_ci#endif /* CONFIG_SHA256 */
2393e5b75505Sopenharmony_ci
2394e5b75505Sopenharmony_ci	openssl_tls_cert_event(conn, err_cert, depth, buf);
2395e5b75505Sopenharmony_ci
2396e5b75505Sopenharmony_ci	if (!preverify_ok) {
2397e5b75505Sopenharmony_ci		if (depth > 0) {
2398e5b75505Sopenharmony_ci			/* Send cert event for the peer certificate so that
2399e5b75505Sopenharmony_ci			 * the upper layers get information about it even if
2400e5b75505Sopenharmony_ci			 * validation of a CA certificate fails. */
2401e5b75505Sopenharmony_ci			STACK_OF(X509) *chain;
2402e5b75505Sopenharmony_ci
2403e5b75505Sopenharmony_ci			chain = X509_STORE_CTX_get1_chain(x509_ctx);
2404e5b75505Sopenharmony_ci			if (chain && sk_X509_num(chain) > 0) {
2405e5b75505Sopenharmony_ci				char buf2[256];
2406e5b75505Sopenharmony_ci				X509 *cert;
2407e5b75505Sopenharmony_ci
2408e5b75505Sopenharmony_ci				cert = sk_X509_value(chain, 0);
2409e5b75505Sopenharmony_ci				X509_NAME_oneline(X509_get_subject_name(cert),
2410e5b75505Sopenharmony_ci						  buf2, sizeof(buf2));
2411e5b75505Sopenharmony_ci
2412e5b75505Sopenharmony_ci				openssl_tls_cert_event(conn, cert, 0, buf2);
2413e5b75505Sopenharmony_ci			}
2414e5b75505Sopenharmony_ci			if (chain)
2415e5b75505Sopenharmony_ci				sk_X509_pop_free(chain, X509_free);
2416e5b75505Sopenharmony_ci		}
2417e5b75505Sopenharmony_ci
2418e5b75505Sopenharmony_ci		wpa_printf(MSG_WARNING, "TLS: Certificate verification failed,"
2419e5b75505Sopenharmony_ci			   " error %d (%s) depth %d for '%s'", err, err_str,
2420e5b75505Sopenharmony_ci			   depth, buf);
2421e5b75505Sopenharmony_ci		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2422e5b75505Sopenharmony_ci				       err_str, TLS_FAIL_UNSPECIFIED);
2423e5b75505Sopenharmony_ci		return preverify_ok;
2424e5b75505Sopenharmony_ci	}
2425e5b75505Sopenharmony_ci
2426e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - preverify_ok=%d "
2427e5b75505Sopenharmony_ci		   "err=%d (%s) ca_cert_verify=%d depth=%d buf='%s'",
2428e5b75505Sopenharmony_ci		   preverify_ok, err, err_str,
2429e5b75505Sopenharmony_ci		   conn->ca_cert_verify, depth, buf);
2430e5b75505Sopenharmony_ci	check_cert_subject = conn->check_cert_subject;
2431e5b75505Sopenharmony_ci	if (!check_cert_subject)
2432e5b75505Sopenharmony_ci		check_cert_subject = conn->data->check_cert_subject;
2433e5b75505Sopenharmony_ci	if (check_cert_subject) {
2434e5b75505Sopenharmony_ci		if (depth == 0 &&
2435e5b75505Sopenharmony_ci		    !tls_match_dn_field(err_cert, check_cert_subject)) {
2436e5b75505Sopenharmony_ci			preverify_ok = 0;
2437e5b75505Sopenharmony_ci			openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2438e5b75505Sopenharmony_ci					       "Distinguished Name",
2439e5b75505Sopenharmony_ci					       TLS_FAIL_DN_MISMATCH);
2440e5b75505Sopenharmony_ci		}
2441e5b75505Sopenharmony_ci	}
2442e5b75505Sopenharmony_ci	if (depth == 0 && match && os_strstr(buf, match) == NULL) {
2443e5b75505Sopenharmony_ci		wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
2444e5b75505Sopenharmony_ci			   "match with '%s'", buf, match);
2445e5b75505Sopenharmony_ci		preverify_ok = 0;
2446e5b75505Sopenharmony_ci		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2447e5b75505Sopenharmony_ci				       "Subject mismatch",
2448e5b75505Sopenharmony_ci				       TLS_FAIL_SUBJECT_MISMATCH);
2449e5b75505Sopenharmony_ci	} else if (depth == 0 && altmatch &&
2450e5b75505Sopenharmony_ci		   !tls_match_altsubject(err_cert, altmatch)) {
2451e5b75505Sopenharmony_ci		wpa_printf(MSG_WARNING, "TLS: altSubjectName match "
2452e5b75505Sopenharmony_ci			   "'%s' not found", altmatch);
2453e5b75505Sopenharmony_ci		preverify_ok = 0;
2454e5b75505Sopenharmony_ci		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2455e5b75505Sopenharmony_ci				       "AltSubject mismatch",
2456e5b75505Sopenharmony_ci				       TLS_FAIL_ALTSUBJECT_MISMATCH);
2457e5b75505Sopenharmony_ci	} else if (depth == 0 && suffix_match &&
2458e5b75505Sopenharmony_ci		   !tls_match_suffix(err_cert, suffix_match, 0)) {
2459e5b75505Sopenharmony_ci		wpa_printf(MSG_WARNING, "TLS: Domain suffix match '%s' not found",
2460e5b75505Sopenharmony_ci			   suffix_match);
2461e5b75505Sopenharmony_ci		preverify_ok = 0;
2462e5b75505Sopenharmony_ci		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2463e5b75505Sopenharmony_ci				       "Domain suffix mismatch",
2464e5b75505Sopenharmony_ci				       TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
2465e5b75505Sopenharmony_ci	} else if (depth == 0 && domain_match &&
2466e5b75505Sopenharmony_ci		   !tls_match_suffix(err_cert, domain_match, 1)) {
2467e5b75505Sopenharmony_ci		wpa_printf(MSG_WARNING, "TLS: Domain match '%s' not found",
2468e5b75505Sopenharmony_ci			   domain_match);
2469e5b75505Sopenharmony_ci		preverify_ok = 0;
2470e5b75505Sopenharmony_ci		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2471e5b75505Sopenharmony_ci				       "Domain mismatch",
2472e5b75505Sopenharmony_ci				       TLS_FAIL_DOMAIN_MISMATCH);
2473e5b75505Sopenharmony_ci	}
2474e5b75505Sopenharmony_ci
2475e5b75505Sopenharmony_ci	if (conn->cert_probe && preverify_ok && depth == 0) {
2476e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: Reject server certificate "
2477e5b75505Sopenharmony_ci			   "on probe-only run");
2478e5b75505Sopenharmony_ci		preverify_ok = 0;
2479e5b75505Sopenharmony_ci		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2480e5b75505Sopenharmony_ci				       "Server certificate chain probe",
2481e5b75505Sopenharmony_ci				       TLS_FAIL_SERVER_CHAIN_PROBE);
2482e5b75505Sopenharmony_ci	}
2483e5b75505Sopenharmony_ci
2484e5b75505Sopenharmony_ci#ifdef CONFIG_SUITEB
2485e5b75505Sopenharmony_ci	if (conn->flags & TLS_CONN_SUITEB) {
2486e5b75505Sopenharmony_ci		EVP_PKEY *pk;
2487e5b75505Sopenharmony_ci		RSA *rsa;
2488e5b75505Sopenharmony_ci		int len = -1;
2489e5b75505Sopenharmony_ci
2490e5b75505Sopenharmony_ci		pk = X509_get_pubkey(err_cert);
2491e5b75505Sopenharmony_ci		if (pk) {
2492e5b75505Sopenharmony_ci			rsa = EVP_PKEY_get1_RSA(pk);
2493e5b75505Sopenharmony_ci			if (rsa) {
2494e5b75505Sopenharmony_ci				len = RSA_bits(rsa);
2495e5b75505Sopenharmony_ci				RSA_free(rsa);
2496e5b75505Sopenharmony_ci			}
2497e5b75505Sopenharmony_ci			EVP_PKEY_free(pk);
2498e5b75505Sopenharmony_ci		}
2499e5b75505Sopenharmony_ci
2500e5b75505Sopenharmony_ci		if (len >= 0) {
2501e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
2502e5b75505Sopenharmony_ci				   "OpenSSL: RSA modulus size: %d bits", len);
2503e5b75505Sopenharmony_ci			if (len < 3072) {
2504e5b75505Sopenharmony_ci				preverify_ok = 0;
2505e5b75505Sopenharmony_ci				openssl_tls_fail_event(
2506e5b75505Sopenharmony_ci					conn, err_cert, err,
2507e5b75505Sopenharmony_ci					depth, buf,
2508e5b75505Sopenharmony_ci					"Insufficient RSA modulus size",
2509e5b75505Sopenharmony_ci					TLS_FAIL_INSUFFICIENT_KEY_LEN);
2510e5b75505Sopenharmony_ci			}
2511e5b75505Sopenharmony_ci		}
2512e5b75505Sopenharmony_ci	}
2513e5b75505Sopenharmony_ci#endif /* CONFIG_SUITEB */
2514e5b75505Sopenharmony_ci
2515e5b75505Sopenharmony_ci#ifdef OPENSSL_IS_BORINGSSL
2516e5b75505Sopenharmony_ci	if (depth == 0 && (conn->flags & TLS_CONN_REQUEST_OCSP) &&
2517e5b75505Sopenharmony_ci	    preverify_ok) {
2518e5b75505Sopenharmony_ci		enum ocsp_result res;
2519e5b75505Sopenharmony_ci
2520e5b75505Sopenharmony_ci		res = check_ocsp_resp(conn->ssl_ctx, conn->ssl, err_cert,
2521e5b75505Sopenharmony_ci				      conn->peer_issuer,
2522e5b75505Sopenharmony_ci				      conn->peer_issuer_issuer);
2523e5b75505Sopenharmony_ci		if (res == OCSP_REVOKED) {
2524e5b75505Sopenharmony_ci			preverify_ok = 0;
2525e5b75505Sopenharmony_ci			openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2526e5b75505Sopenharmony_ci					       "certificate revoked",
2527e5b75505Sopenharmony_ci					       TLS_FAIL_REVOKED);
2528e5b75505Sopenharmony_ci			if (err == X509_V_OK)
2529e5b75505Sopenharmony_ci				X509_STORE_CTX_set_error(
2530e5b75505Sopenharmony_ci					x509_ctx, X509_V_ERR_CERT_REVOKED);
2531e5b75505Sopenharmony_ci		} else if (res != OCSP_GOOD &&
2532e5b75505Sopenharmony_ci			   (conn->flags & TLS_CONN_REQUIRE_OCSP)) {
2533e5b75505Sopenharmony_ci			preverify_ok = 0;
2534e5b75505Sopenharmony_ci			openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2535e5b75505Sopenharmony_ci					       "bad certificate status response",
2536e5b75505Sopenharmony_ci					       TLS_FAIL_UNSPECIFIED);
2537e5b75505Sopenharmony_ci		}
2538e5b75505Sopenharmony_ci	}
2539e5b75505Sopenharmony_ci#endif /* OPENSSL_IS_BORINGSSL */
2540e5b75505Sopenharmony_ci
2541e5b75505Sopenharmony_ci	if (depth == 0 && preverify_ok && context->event_cb != NULL)
2542e5b75505Sopenharmony_ci		context->event_cb(context->cb_ctx,
2543e5b75505Sopenharmony_ci				  TLS_CERT_CHAIN_SUCCESS, NULL);
2544e5b75505Sopenharmony_ci
2545e5b75505Sopenharmony_ci	return preverify_ok;
2546e5b75505Sopenharmony_ci}
2547e5b75505Sopenharmony_ci
2548e5b75505Sopenharmony_ci
2549e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_STDIO
2550e5b75505Sopenharmony_cistatic int tls_load_ca_der(struct tls_data *data, const char *ca_cert)
2551e5b75505Sopenharmony_ci{
2552e5b75505Sopenharmony_ci	SSL_CTX *ssl_ctx = data->ssl;
2553e5b75505Sopenharmony_ci	X509_LOOKUP *lookup;
2554e5b75505Sopenharmony_ci	int ret = 0;
2555e5b75505Sopenharmony_ci
2556e5b75505Sopenharmony_ci	lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(ssl_ctx),
2557e5b75505Sopenharmony_ci				       X509_LOOKUP_file());
2558e5b75505Sopenharmony_ci	if (lookup == NULL) {
2559e5b75505Sopenharmony_ci		tls_show_errors(MSG_WARNING, __func__,
2560e5b75505Sopenharmony_ci				"Failed add lookup for X509 store");
2561e5b75505Sopenharmony_ci		return -1;
2562e5b75505Sopenharmony_ci	}
2563e5b75505Sopenharmony_ci
2564e5b75505Sopenharmony_ci	if (!X509_LOOKUP_load_file(lookup, ca_cert, X509_FILETYPE_ASN1)) {
2565e5b75505Sopenharmony_ci		unsigned long err = ERR_peek_error();
2566e5b75505Sopenharmony_ci		tls_show_errors(MSG_WARNING, __func__,
2567e5b75505Sopenharmony_ci				"Failed load CA in DER format");
2568e5b75505Sopenharmony_ci		if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
2569e5b75505Sopenharmony_ci		    ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) {
2570e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring "
2571e5b75505Sopenharmony_ci				   "cert already in hash table error",
2572e5b75505Sopenharmony_ci				   __func__);
2573e5b75505Sopenharmony_ci		} else
2574e5b75505Sopenharmony_ci			ret = -1;
2575e5b75505Sopenharmony_ci	}
2576e5b75505Sopenharmony_ci
2577e5b75505Sopenharmony_ci	return ret;
2578e5b75505Sopenharmony_ci}
2579e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_STDIO */
2580e5b75505Sopenharmony_ci
2581e5b75505Sopenharmony_ci
2582e5b75505Sopenharmony_cistatic int tls_connection_ca_cert(struct tls_data *data,
2583e5b75505Sopenharmony_ci				  struct tls_connection *conn,
2584e5b75505Sopenharmony_ci				  const char *ca_cert, const u8 *ca_cert_blob,
2585e5b75505Sopenharmony_ci				  size_t ca_cert_blob_len, const char *ca_path)
2586e5b75505Sopenharmony_ci{
2587e5b75505Sopenharmony_ci	SSL_CTX *ssl_ctx = data->ssl;
2588e5b75505Sopenharmony_ci	X509_STORE *store;
2589e5b75505Sopenharmony_ci
2590e5b75505Sopenharmony_ci	/*
2591e5b75505Sopenharmony_ci	 * Remove previously configured trusted CA certificates before adding
2592e5b75505Sopenharmony_ci	 * new ones.
2593e5b75505Sopenharmony_ci	 */
2594e5b75505Sopenharmony_ci	store = X509_STORE_new();
2595e5b75505Sopenharmony_ci	if (store == NULL) {
2596e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new "
2597e5b75505Sopenharmony_ci			   "certificate store", __func__);
2598e5b75505Sopenharmony_ci		return -1;
2599e5b75505Sopenharmony_ci	}
2600e5b75505Sopenharmony_ci	SSL_CTX_set_cert_store(ssl_ctx, store);
2601e5b75505Sopenharmony_ci
2602e5b75505Sopenharmony_ci	SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
2603e5b75505Sopenharmony_ci	conn->ca_cert_verify = 1;
2604e5b75505Sopenharmony_ci
2605e5b75505Sopenharmony_ci	if (ca_cert && os_strncmp(ca_cert, "probe://", 8) == 0) {
2606e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: Probe for server certificate "
2607e5b75505Sopenharmony_ci			   "chain");
2608e5b75505Sopenharmony_ci		conn->cert_probe = 1;
2609e5b75505Sopenharmony_ci		conn->ca_cert_verify = 0;
2610e5b75505Sopenharmony_ci		return 0;
2611e5b75505Sopenharmony_ci	}
2612e5b75505Sopenharmony_ci
2613e5b75505Sopenharmony_ci	if (ca_cert && os_strncmp(ca_cert, "hash://", 7) == 0) {
2614e5b75505Sopenharmony_ci#ifdef CONFIG_SHA256
2615e5b75505Sopenharmony_ci		const char *pos = ca_cert + 7;
2616e5b75505Sopenharmony_ci		if (os_strncmp(pos, "server/sha256/", 14) != 0) {
2617e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "OpenSSL: Unsupported ca_cert "
2618e5b75505Sopenharmony_ci				   "hash value '%s'", ca_cert);
2619e5b75505Sopenharmony_ci			return -1;
2620e5b75505Sopenharmony_ci		}
2621e5b75505Sopenharmony_ci		pos += 14;
2622e5b75505Sopenharmony_ci		if (os_strlen(pos) != 32 * 2) {
2623e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "OpenSSL: Unexpected SHA256 "
2624e5b75505Sopenharmony_ci				   "hash length in ca_cert '%s'", ca_cert);
2625e5b75505Sopenharmony_ci			return -1;
2626e5b75505Sopenharmony_ci		}
2627e5b75505Sopenharmony_ci		if (hexstr2bin(pos, conn->srv_cert_hash, 32) < 0) {
2628e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "OpenSSL: Invalid SHA256 hash "
2629e5b75505Sopenharmony_ci				   "value in ca_cert '%s'", ca_cert);
2630e5b75505Sopenharmony_ci			return -1;
2631e5b75505Sopenharmony_ci		}
2632e5b75505Sopenharmony_ci		conn->server_cert_only = 1;
2633e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: Checking only server "
2634e5b75505Sopenharmony_ci			   "certificate match");
2635e5b75505Sopenharmony_ci		return 0;
2636e5b75505Sopenharmony_ci#else /* CONFIG_SHA256 */
2637e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "No SHA256 included in the build - "
2638e5b75505Sopenharmony_ci			   "cannot validate server certificate hash");
2639e5b75505Sopenharmony_ci		return -1;
2640e5b75505Sopenharmony_ci#endif /* CONFIG_SHA256 */
2641e5b75505Sopenharmony_ci	}
2642e5b75505Sopenharmony_ci
2643e5b75505Sopenharmony_ci	if (ca_cert_blob) {
2644e5b75505Sopenharmony_ci		X509 *cert = d2i_X509(NULL,
2645e5b75505Sopenharmony_ci				      (const unsigned char **) &ca_cert_blob,
2646e5b75505Sopenharmony_ci				      ca_cert_blob_len);
2647e5b75505Sopenharmony_ci		if (cert == NULL) {
2648e5b75505Sopenharmony_ci			BIO *bio = BIO_new_mem_buf(ca_cert_blob,
2649e5b75505Sopenharmony_ci						   ca_cert_blob_len);
2650e5b75505Sopenharmony_ci
2651e5b75505Sopenharmony_ci			if (bio) {
2652e5b75505Sopenharmony_ci				cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
2653e5b75505Sopenharmony_ci				BIO_free(bio);
2654e5b75505Sopenharmony_ci			}
2655e5b75505Sopenharmony_ci
2656e5b75505Sopenharmony_ci			if (!cert) {
2657e5b75505Sopenharmony_ci				tls_show_errors(MSG_WARNING, __func__,
2658e5b75505Sopenharmony_ci						"Failed to parse ca_cert_blob");
2659e5b75505Sopenharmony_ci				return -1;
2660e5b75505Sopenharmony_ci			}
2661e5b75505Sopenharmony_ci
2662e5b75505Sopenharmony_ci			while (ERR_get_error()) {
2663e5b75505Sopenharmony_ci				/* Ignore errors from DER conversion. */
2664e5b75505Sopenharmony_ci			}
2665e5b75505Sopenharmony_ci		}
2666e5b75505Sopenharmony_ci
2667e5b75505Sopenharmony_ci		if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(ssl_ctx),
2668e5b75505Sopenharmony_ci					 cert)) {
2669e5b75505Sopenharmony_ci			unsigned long err = ERR_peek_error();
2670e5b75505Sopenharmony_ci			tls_show_errors(MSG_WARNING, __func__,
2671e5b75505Sopenharmony_ci					"Failed to add ca_cert_blob to "
2672e5b75505Sopenharmony_ci					"certificate store");
2673e5b75505Sopenharmony_ci			if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
2674e5b75505Sopenharmony_ci			    ERR_GET_REASON(err) ==
2675e5b75505Sopenharmony_ci			    X509_R_CERT_ALREADY_IN_HASH_TABLE) {
2676e5b75505Sopenharmony_ci				wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring "
2677e5b75505Sopenharmony_ci					   "cert already in hash table error",
2678e5b75505Sopenharmony_ci					   __func__);
2679e5b75505Sopenharmony_ci			} else {
2680e5b75505Sopenharmony_ci				X509_free(cert);
2681e5b75505Sopenharmony_ci				return -1;
2682e5b75505Sopenharmony_ci			}
2683e5b75505Sopenharmony_ci		}
2684e5b75505Sopenharmony_ci		X509_free(cert);
2685e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: %s - added ca_cert_blob "
2686e5b75505Sopenharmony_ci			   "to certificate store", __func__);
2687e5b75505Sopenharmony_ci		return 0;
2688e5b75505Sopenharmony_ci	}
2689e5b75505Sopenharmony_ci
2690e5b75505Sopenharmony_ci#ifdef ANDROID
2691e5b75505Sopenharmony_ci	/* Single alias */
2692e5b75505Sopenharmony_ci	if (ca_cert && os_strncmp("keystore://", ca_cert, 11) == 0) {
2693e5b75505Sopenharmony_ci		if (tls_add_ca_from_keystore(SSL_CTX_get_cert_store(ssl_ctx),
2694e5b75505Sopenharmony_ci					     &ca_cert[11]) < 0)
2695e5b75505Sopenharmony_ci			return -1;
2696e5b75505Sopenharmony_ci		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
2697e5b75505Sopenharmony_ci		return 0;
2698e5b75505Sopenharmony_ci	}
2699e5b75505Sopenharmony_ci
2700e5b75505Sopenharmony_ci	/* Multiple aliases separated by space */
2701e5b75505Sopenharmony_ci	if (ca_cert && os_strncmp("keystores://", ca_cert, 12) == 0) {
2702e5b75505Sopenharmony_ci		char *aliases = os_strdup(&ca_cert[12]);
2703e5b75505Sopenharmony_ci		const char *delim = " ";
2704e5b75505Sopenharmony_ci		int rc = 0;
2705e5b75505Sopenharmony_ci		char *savedptr;
2706e5b75505Sopenharmony_ci		char *alias;
2707e5b75505Sopenharmony_ci
2708e5b75505Sopenharmony_ci		if (!aliases)
2709e5b75505Sopenharmony_ci			return -1;
2710e5b75505Sopenharmony_ci		alias = strtok_r(aliases, delim, &savedptr);
2711e5b75505Sopenharmony_ci		for (; alias; alias = strtok_r(NULL, delim, &savedptr)) {
2712e5b75505Sopenharmony_ci			if (tls_add_ca_from_keystore_encoded(
2713e5b75505Sopenharmony_ci				    SSL_CTX_get_cert_store(ssl_ctx), alias)) {
2714e5b75505Sopenharmony_ci				wpa_printf(MSG_WARNING,
2715e5b75505Sopenharmony_ci					   "OpenSSL: %s - Failed to add ca_cert %s from keystore",
2716e5b75505Sopenharmony_ci					   __func__, alias);
2717e5b75505Sopenharmony_ci				rc = -1;
2718e5b75505Sopenharmony_ci				break;
2719e5b75505Sopenharmony_ci			}
2720e5b75505Sopenharmony_ci		}
2721e5b75505Sopenharmony_ci		os_free(aliases);
2722e5b75505Sopenharmony_ci		if (rc)
2723e5b75505Sopenharmony_ci			return rc;
2724e5b75505Sopenharmony_ci
2725e5b75505Sopenharmony_ci		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
2726e5b75505Sopenharmony_ci		return 0;
2727e5b75505Sopenharmony_ci	}
2728e5b75505Sopenharmony_ci#endif /* ANDROID */
2729e5b75505Sopenharmony_ci
2730e5b75505Sopenharmony_ci#ifdef CONFIG_NATIVE_WINDOWS
2731e5b75505Sopenharmony_ci	if (ca_cert && tls_cryptoapi_ca_cert(ssl_ctx, conn->ssl, ca_cert) ==
2732e5b75505Sopenharmony_ci	    0) {
2733e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: Added CA certificates from "
2734e5b75505Sopenharmony_ci			   "system certificate store");
2735e5b75505Sopenharmony_ci		return 0;
2736e5b75505Sopenharmony_ci	}
2737e5b75505Sopenharmony_ci#endif /* CONFIG_NATIVE_WINDOWS */
2738e5b75505Sopenharmony_ci
2739e5b75505Sopenharmony_ci	if (ca_cert || ca_path) {
2740e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_STDIO
2741e5b75505Sopenharmony_ci		if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, ca_path) !=
2742e5b75505Sopenharmony_ci		    1) {
2743e5b75505Sopenharmony_ci			tls_show_errors(MSG_WARNING, __func__,
2744e5b75505Sopenharmony_ci					"Failed to load root certificates");
2745e5b75505Sopenharmony_ci			if (ca_cert &&
2746e5b75505Sopenharmony_ci			    tls_load_ca_der(data, ca_cert) == 0) {
2747e5b75505Sopenharmony_ci				wpa_printf(MSG_DEBUG, "OpenSSL: %s - loaded "
2748e5b75505Sopenharmony_ci					   "DER format CA certificate",
2749e5b75505Sopenharmony_ci					   __func__);
2750e5b75505Sopenharmony_ci			} else
2751e5b75505Sopenharmony_ci				return -1;
2752e5b75505Sopenharmony_ci		} else {
2753e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "TLS: Trusted root "
2754e5b75505Sopenharmony_ci				   "certificate(s) loaded");
2755e5b75505Sopenharmony_ci			tls_get_errors(data);
2756e5b75505Sopenharmony_ci		}
2757e5b75505Sopenharmony_ci#else /* OPENSSL_NO_STDIO */
2758e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO",
2759e5b75505Sopenharmony_ci			   __func__);
2760e5b75505Sopenharmony_ci		return -1;
2761e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_STDIO */
2762e5b75505Sopenharmony_ci	} else {
2763e5b75505Sopenharmony_ci		/* No ca_cert configured - do not try to verify server
2764e5b75505Sopenharmony_ci		 * certificate */
2765e5b75505Sopenharmony_ci		conn->ca_cert_verify = 0;
2766e5b75505Sopenharmony_ci	}
2767e5b75505Sopenharmony_ci
2768e5b75505Sopenharmony_ci	return 0;
2769e5b75505Sopenharmony_ci}
2770e5b75505Sopenharmony_ci
2771e5b75505Sopenharmony_ci
2772e5b75505Sopenharmony_cistatic int tls_global_ca_cert(struct tls_data *data, const char *ca_cert)
2773e5b75505Sopenharmony_ci{
2774e5b75505Sopenharmony_ci	SSL_CTX *ssl_ctx = data->ssl;
2775e5b75505Sopenharmony_ci
2776e5b75505Sopenharmony_ci	if (ca_cert) {
2777e5b75505Sopenharmony_ci		if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, NULL) != 1)
2778e5b75505Sopenharmony_ci		{
2779e5b75505Sopenharmony_ci			tls_show_errors(MSG_WARNING, __func__,
2780e5b75505Sopenharmony_ci					"Failed to load root certificates");
2781e5b75505Sopenharmony_ci			return -1;
2782e5b75505Sopenharmony_ci		}
2783e5b75505Sopenharmony_ci
2784e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "TLS: Trusted root "
2785e5b75505Sopenharmony_ci			   "certificate(s) loaded");
2786e5b75505Sopenharmony_ci
2787e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_STDIO
2788e5b75505Sopenharmony_ci		/* Add the same CAs to the client certificate requests */
2789e5b75505Sopenharmony_ci		SSL_CTX_set_client_CA_list(ssl_ctx,
2790e5b75505Sopenharmony_ci					   SSL_load_client_CA_file(ca_cert));
2791e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_STDIO */
2792e5b75505Sopenharmony_ci
2793e5b75505Sopenharmony_ci		os_free(data->ca_cert);
2794e5b75505Sopenharmony_ci		data->ca_cert = os_strdup(ca_cert);
2795e5b75505Sopenharmony_ci	}
2796e5b75505Sopenharmony_ci
2797e5b75505Sopenharmony_ci	return 0;
2798e5b75505Sopenharmony_ci}
2799e5b75505Sopenharmony_ci
2800e5b75505Sopenharmony_ci
2801e5b75505Sopenharmony_ciint tls_global_set_verify(void *ssl_ctx, int check_crl, int strict)
2802e5b75505Sopenharmony_ci{
2803e5b75505Sopenharmony_ci	int flags;
2804e5b75505Sopenharmony_ci
2805e5b75505Sopenharmony_ci	if (check_crl) {
2806e5b75505Sopenharmony_ci		struct tls_data *data = ssl_ctx;
2807e5b75505Sopenharmony_ci		X509_STORE *cs = SSL_CTX_get_cert_store(data->ssl);
2808e5b75505Sopenharmony_ci		if (cs == NULL) {
2809e5b75505Sopenharmony_ci			tls_show_errors(MSG_INFO, __func__, "Failed to get "
2810e5b75505Sopenharmony_ci					"certificate store when enabling "
2811e5b75505Sopenharmony_ci					"check_crl");
2812e5b75505Sopenharmony_ci			return -1;
2813e5b75505Sopenharmony_ci		}
2814e5b75505Sopenharmony_ci		flags = X509_V_FLAG_CRL_CHECK;
2815e5b75505Sopenharmony_ci		if (check_crl == 2)
2816e5b75505Sopenharmony_ci			flags |= X509_V_FLAG_CRL_CHECK_ALL;
2817e5b75505Sopenharmony_ci		X509_STORE_set_flags(cs, flags);
2818e5b75505Sopenharmony_ci
2819e5b75505Sopenharmony_ci		data->check_crl = check_crl;
2820e5b75505Sopenharmony_ci		data->check_crl_strict = strict;
2821e5b75505Sopenharmony_ci		os_get_reltime(&data->crl_last_reload);
2822e5b75505Sopenharmony_ci	}
2823e5b75505Sopenharmony_ci	return 0;
2824e5b75505Sopenharmony_ci}
2825e5b75505Sopenharmony_ci
2826e5b75505Sopenharmony_ci
2827e5b75505Sopenharmony_cistatic int tls_connection_set_subject_match(struct tls_connection *conn,
2828e5b75505Sopenharmony_ci					    const char *subject_match,
2829e5b75505Sopenharmony_ci					    const char *altsubject_match,
2830e5b75505Sopenharmony_ci					    const char *suffix_match,
2831e5b75505Sopenharmony_ci					    const char *domain_match,
2832e5b75505Sopenharmony_ci					    const char *check_cert_subject)
2833e5b75505Sopenharmony_ci{
2834e5b75505Sopenharmony_ci	os_free(conn->subject_match);
2835e5b75505Sopenharmony_ci	conn->subject_match = NULL;
2836e5b75505Sopenharmony_ci	if (subject_match) {
2837e5b75505Sopenharmony_ci		conn->subject_match = os_strdup(subject_match);
2838e5b75505Sopenharmony_ci		if (conn->subject_match == NULL)
2839e5b75505Sopenharmony_ci			return -1;
2840e5b75505Sopenharmony_ci	}
2841e5b75505Sopenharmony_ci
2842e5b75505Sopenharmony_ci	os_free(conn->altsubject_match);
2843e5b75505Sopenharmony_ci	conn->altsubject_match = NULL;
2844e5b75505Sopenharmony_ci	if (altsubject_match) {
2845e5b75505Sopenharmony_ci		conn->altsubject_match = os_strdup(altsubject_match);
2846e5b75505Sopenharmony_ci		if (conn->altsubject_match == NULL)
2847e5b75505Sopenharmony_ci			return -1;
2848e5b75505Sopenharmony_ci	}
2849e5b75505Sopenharmony_ci
2850e5b75505Sopenharmony_ci	os_free(conn->suffix_match);
2851e5b75505Sopenharmony_ci	conn->suffix_match = NULL;
2852e5b75505Sopenharmony_ci	if (suffix_match) {
2853e5b75505Sopenharmony_ci		conn->suffix_match = os_strdup(suffix_match);
2854e5b75505Sopenharmony_ci		if (conn->suffix_match == NULL)
2855e5b75505Sopenharmony_ci			return -1;
2856e5b75505Sopenharmony_ci	}
2857e5b75505Sopenharmony_ci
2858e5b75505Sopenharmony_ci	os_free(conn->domain_match);
2859e5b75505Sopenharmony_ci	conn->domain_match = NULL;
2860e5b75505Sopenharmony_ci	if (domain_match) {
2861e5b75505Sopenharmony_ci		conn->domain_match = os_strdup(domain_match);
2862e5b75505Sopenharmony_ci		if (conn->domain_match == NULL)
2863e5b75505Sopenharmony_ci			return -1;
2864e5b75505Sopenharmony_ci	}
2865e5b75505Sopenharmony_ci
2866e5b75505Sopenharmony_ci	os_free(conn->check_cert_subject);
2867e5b75505Sopenharmony_ci	conn->check_cert_subject = NULL;
2868e5b75505Sopenharmony_ci	if (check_cert_subject) {
2869e5b75505Sopenharmony_ci		conn->check_cert_subject = os_strdup(check_cert_subject);
2870e5b75505Sopenharmony_ci		if (!conn->check_cert_subject)
2871e5b75505Sopenharmony_ci			return -1;
2872e5b75505Sopenharmony_ci	}
2873e5b75505Sopenharmony_ci
2874e5b75505Sopenharmony_ci	return 0;
2875e5b75505Sopenharmony_ci}
2876e5b75505Sopenharmony_ci
2877e5b75505Sopenharmony_ci
2878e5b75505Sopenharmony_ci#ifdef CONFIG_SUITEB
2879e5b75505Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10002000L
2880e5b75505Sopenharmony_cistatic int suiteb_cert_cb(SSL *ssl, void *arg)
2881e5b75505Sopenharmony_ci{
2882e5b75505Sopenharmony_ci	struct tls_connection *conn = arg;
2883e5b75505Sopenharmony_ci
2884e5b75505Sopenharmony_ci	/*
2885e5b75505Sopenharmony_ci	 * This cert_cb() is not really the best location for doing a
2886e5b75505Sopenharmony_ci	 * constraint check for the ServerKeyExchange message, but this seems to
2887e5b75505Sopenharmony_ci	 * be the only place where the current OpenSSL sequence can be
2888e5b75505Sopenharmony_ci	 * terminated cleanly with an TLS alert going out to the server.
2889e5b75505Sopenharmony_ci	 */
2890e5b75505Sopenharmony_ci
2891e5b75505Sopenharmony_ci	if (!(conn->flags & TLS_CONN_SUITEB))
2892e5b75505Sopenharmony_ci		return 1;
2893e5b75505Sopenharmony_ci
2894e5b75505Sopenharmony_ci	/* DHE is enabled only with DHE-RSA-AES256-GCM-SHA384 */
2895e5b75505Sopenharmony_ci	if (conn->cipher_suite != 0x9f)
2896e5b75505Sopenharmony_ci		return 1;
2897e5b75505Sopenharmony_ci
2898e5b75505Sopenharmony_ci	if (conn->server_dh_prime_len >= 3072)
2899e5b75505Sopenharmony_ci		return 1;
2900e5b75505Sopenharmony_ci
2901e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG,
2902e5b75505Sopenharmony_ci		   "OpenSSL: Server DH prime length (%d bits) not sufficient for Suite B RSA - reject handshake",
2903e5b75505Sopenharmony_ci		   conn->server_dh_prime_len);
2904e5b75505Sopenharmony_ci	return 0;
2905e5b75505Sopenharmony_ci}
2906e5b75505Sopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER */
2907e5b75505Sopenharmony_ci#endif /* CONFIG_SUITEB */
2908e5b75505Sopenharmony_ci
2909e5b75505Sopenharmony_ci
2910e5b75505Sopenharmony_cistatic int tls_set_conn_flags(struct tls_connection *conn, unsigned int flags,
2911e5b75505Sopenharmony_ci			      const char *openssl_ciphers)
2912e5b75505Sopenharmony_ci{
2913e5b75505Sopenharmony_ci	SSL *ssl = conn->ssl;
2914e5b75505Sopenharmony_ci
2915e5b75505Sopenharmony_ci#ifdef SSL_OP_NO_TICKET
2916e5b75505Sopenharmony_ci	if (flags & TLS_CONN_DISABLE_SESSION_TICKET)
2917e5b75505Sopenharmony_ci		SSL_set_options(ssl, SSL_OP_NO_TICKET);
2918e5b75505Sopenharmony_ci	else
2919e5b75505Sopenharmony_ci		SSL_clear_options(ssl, SSL_OP_NO_TICKET);
2920e5b75505Sopenharmony_ci#endif /* SSL_OP_NO_TICKET */
2921e5b75505Sopenharmony_ci
2922e5b75505Sopenharmony_ci#ifdef SSL_OP_NO_TLSv1
2923e5b75505Sopenharmony_ci	if (flags & TLS_CONN_DISABLE_TLSv1_0)
2924e5b75505Sopenharmony_ci		SSL_set_options(ssl, SSL_OP_NO_TLSv1);
2925e5b75505Sopenharmony_ci	else
2926e5b75505Sopenharmony_ci		SSL_clear_options(ssl, SSL_OP_NO_TLSv1);
2927e5b75505Sopenharmony_ci#endif /* SSL_OP_NO_TLSv1 */
2928e5b75505Sopenharmony_ci#ifdef SSL_OP_NO_TLSv1_1
2929e5b75505Sopenharmony_ci	if (flags & TLS_CONN_DISABLE_TLSv1_1)
2930e5b75505Sopenharmony_ci		SSL_set_options(ssl, SSL_OP_NO_TLSv1_1);
2931e5b75505Sopenharmony_ci	else
2932e5b75505Sopenharmony_ci		SSL_clear_options(ssl, SSL_OP_NO_TLSv1_1);
2933e5b75505Sopenharmony_ci#endif /* SSL_OP_NO_TLSv1_1 */
2934e5b75505Sopenharmony_ci#ifdef SSL_OP_NO_TLSv1_2
2935e5b75505Sopenharmony_ci	if (flags & TLS_CONN_DISABLE_TLSv1_2)
2936e5b75505Sopenharmony_ci		SSL_set_options(ssl, SSL_OP_NO_TLSv1_2);
2937e5b75505Sopenharmony_ci	else
2938e5b75505Sopenharmony_ci		SSL_clear_options(ssl, SSL_OP_NO_TLSv1_2);
2939e5b75505Sopenharmony_ci#endif /* SSL_OP_NO_TLSv1_2 */
2940e5b75505Sopenharmony_ci#ifdef SSL_OP_NO_TLSv1_3
2941e5b75505Sopenharmony_ci	if (flags & TLS_CONN_DISABLE_TLSv1_3)
2942e5b75505Sopenharmony_ci		SSL_set_options(ssl, SSL_OP_NO_TLSv1_3);
2943e5b75505Sopenharmony_ci	else
2944e5b75505Sopenharmony_ci		SSL_clear_options(ssl, SSL_OP_NO_TLSv1_3);
2945e5b75505Sopenharmony_ci#endif /* SSL_OP_NO_TLSv1_3 */
2946e5b75505Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10100000L
2947e5b75505Sopenharmony_ci	if (flags & (TLS_CONN_ENABLE_TLSv1_0 |
2948e5b75505Sopenharmony_ci		     TLS_CONN_ENABLE_TLSv1_1 |
2949e5b75505Sopenharmony_ci		     TLS_CONN_ENABLE_TLSv1_2)) {
2950e5b75505Sopenharmony_ci		int version = 0;
2951e5b75505Sopenharmony_ci
2952e5b75505Sopenharmony_ci		/* Explicit request to enable TLS versions even if needing to
2953e5b75505Sopenharmony_ci		 * override systemwide policies. */
2954e5b75505Sopenharmony_ci		if (flags & TLS_CONN_ENABLE_TLSv1_0) {
2955e5b75505Sopenharmony_ci			version = TLS1_VERSION;
2956e5b75505Sopenharmony_ci		} else if (flags & TLS_CONN_ENABLE_TLSv1_1) {
2957e5b75505Sopenharmony_ci			if (!(flags & TLS_CONN_DISABLE_TLSv1_0))
2958e5b75505Sopenharmony_ci				version = TLS1_1_VERSION;
2959e5b75505Sopenharmony_ci		} else if (flags & TLS_CONN_ENABLE_TLSv1_2) {
2960e5b75505Sopenharmony_ci			if (!(flags & (TLS_CONN_DISABLE_TLSv1_0 |
2961e5b75505Sopenharmony_ci				       TLS_CONN_DISABLE_TLSv1_1)))
2962e5b75505Sopenharmony_ci				version = TLS1_2_VERSION;
2963e5b75505Sopenharmony_ci		}
2964e5b75505Sopenharmony_ci		if (!version) {
2965e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
2966e5b75505Sopenharmony_ci				   "OpenSSL: Invalid TLS version configuration");
2967e5b75505Sopenharmony_ci			return -1;
2968e5b75505Sopenharmony_ci		}
2969e5b75505Sopenharmony_ci
2970e5b75505Sopenharmony_ci		if (SSL_set_min_proto_version(ssl, version) != 1) {
2971e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
2972e5b75505Sopenharmony_ci				   "OpenSSL: Failed to set minimum TLS version");
2973e5b75505Sopenharmony_ci			return -1;
2974e5b75505Sopenharmony_ci		}
2975e5b75505Sopenharmony_ci	}
2976e5b75505Sopenharmony_ci#endif /* >= 1.1.0 */
2977e5b75505Sopenharmony_ci
2978e5b75505Sopenharmony_ci#ifdef CONFIG_SUITEB
2979e5b75505Sopenharmony_ci#ifdef OPENSSL_IS_BORINGSSL
2980e5b75505Sopenharmony_ci	/* Start with defaults from BoringSSL */
2981e5b75505Sopenharmony_ci	SSL_CTX_set_verify_algorithm_prefs(conn->ssl_ctx, NULL, 0);
2982e5b75505Sopenharmony_ci#endif /* OPENSSL_IS_BORINGSSL */
2983e5b75505Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10002000L
2984e5b75505Sopenharmony_ci	if (flags & TLS_CONN_SUITEB_NO_ECDH) {
2985e5b75505Sopenharmony_ci		const char *ciphers = "DHE-RSA-AES256-GCM-SHA384";
2986e5b75505Sopenharmony_ci
2987e5b75505Sopenharmony_ci		if (openssl_ciphers) {
2988e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
2989e5b75505Sopenharmony_ci				   "OpenSSL: Override ciphers for Suite B (no ECDH): %s",
2990e5b75505Sopenharmony_ci				   openssl_ciphers);
2991e5b75505Sopenharmony_ci			ciphers = openssl_ciphers;
2992e5b75505Sopenharmony_ci		}
2993e5b75505Sopenharmony_ci		if (SSL_set_cipher_list(ssl, ciphers) != 1) {
2994e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
2995e5b75505Sopenharmony_ci				   "OpenSSL: Failed to set Suite B ciphers");
2996e5b75505Sopenharmony_ci			return -1;
2997e5b75505Sopenharmony_ci		}
2998e5b75505Sopenharmony_ci	} else if (flags & TLS_CONN_SUITEB) {
2999e5b75505Sopenharmony_ci		EC_KEY *ecdh;
3000e5b75505Sopenharmony_ci		const char *ciphers =
3001e5b75505Sopenharmony_ci			"ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384";
3002e5b75505Sopenharmony_ci		int nid[1] = { NID_secp384r1 };
3003e5b75505Sopenharmony_ci
3004e5b75505Sopenharmony_ci		if (openssl_ciphers) {
3005e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
3006e5b75505Sopenharmony_ci				   "OpenSSL: Override ciphers for Suite B: %s",
3007e5b75505Sopenharmony_ci				   openssl_ciphers);
3008e5b75505Sopenharmony_ci			ciphers = openssl_ciphers;
3009e5b75505Sopenharmony_ci		}
3010e5b75505Sopenharmony_ci		if (SSL_set_cipher_list(ssl, ciphers) != 1) {
3011e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
3012e5b75505Sopenharmony_ci				   "OpenSSL: Failed to set Suite B ciphers");
3013e5b75505Sopenharmony_ci			return -1;
3014e5b75505Sopenharmony_ci		}
3015e5b75505Sopenharmony_ci
3016e5b75505Sopenharmony_ci		if (SSL_set1_curves(ssl, nid, 1) != 1) {
3017e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
3018e5b75505Sopenharmony_ci				   "OpenSSL: Failed to set Suite B curves");
3019e5b75505Sopenharmony_ci			return -1;
3020e5b75505Sopenharmony_ci		}
3021e5b75505Sopenharmony_ci
3022e5b75505Sopenharmony_ci		ecdh = EC_KEY_new_by_curve_name(NID_secp384r1);
3023e5b75505Sopenharmony_ci		if (!ecdh || SSL_set_tmp_ecdh(ssl, ecdh) != 1) {
3024e5b75505Sopenharmony_ci			EC_KEY_free(ecdh);
3025e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
3026e5b75505Sopenharmony_ci				   "OpenSSL: Failed to set ECDH parameter");
3027e5b75505Sopenharmony_ci			return -1;
3028e5b75505Sopenharmony_ci		}
3029e5b75505Sopenharmony_ci		EC_KEY_free(ecdh);
3030e5b75505Sopenharmony_ci	}
3031e5b75505Sopenharmony_ci	if (flags & (TLS_CONN_SUITEB | TLS_CONN_SUITEB_NO_ECDH)) {
3032e5b75505Sopenharmony_ci#ifdef OPENSSL_IS_BORINGSSL
3033e5b75505Sopenharmony_ci		uint16_t sigalgs[1] = { SSL_SIGN_RSA_PKCS1_SHA384 };
3034e5b75505Sopenharmony_ci
3035e5b75505Sopenharmony_ci		if (SSL_CTX_set_verify_algorithm_prefs(conn->ssl_ctx, sigalgs,
3036e5b75505Sopenharmony_ci						       1) != 1) {
3037e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
3038e5b75505Sopenharmony_ci				   "OpenSSL: Failed to set Suite B sigalgs");
3039e5b75505Sopenharmony_ci			return -1;
3040e5b75505Sopenharmony_ci		}
3041e5b75505Sopenharmony_ci#else /* OPENSSL_IS_BORINGSSL */
3042e5b75505Sopenharmony_ci		/* ECDSA+SHA384 if need to add EC support here */
3043e5b75505Sopenharmony_ci		if (SSL_set1_sigalgs_list(ssl, "RSA+SHA384") != 1) {
3044e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
3045e5b75505Sopenharmony_ci				   "OpenSSL: Failed to set Suite B sigalgs");
3046e5b75505Sopenharmony_ci			return -1;
3047e5b75505Sopenharmony_ci		}
3048e5b75505Sopenharmony_ci#endif /* OPENSSL_IS_BORINGSSL */
3049e5b75505Sopenharmony_ci
3050e5b75505Sopenharmony_ci		SSL_set_options(ssl, SSL_OP_NO_TLSv1);
3051e5b75505Sopenharmony_ci		SSL_set_options(ssl, SSL_OP_NO_TLSv1_1);
3052e5b75505Sopenharmony_ci		SSL_set_cert_cb(ssl, suiteb_cert_cb, conn);
3053e5b75505Sopenharmony_ci	}
3054e5b75505Sopenharmony_ci#else /* OPENSSL_VERSION_NUMBER < 0x10002000L */
3055e5b75505Sopenharmony_ci	if (flags & (TLS_CONN_SUITEB | TLS_CONN_SUITEB_NO_ECDH)) {
3056e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR,
3057e5b75505Sopenharmony_ci			   "OpenSSL: Suite B RSA case not supported with this OpenSSL version");
3058e5b75505Sopenharmony_ci		return -1;
3059e5b75505Sopenharmony_ci	}
3060e5b75505Sopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER */
3061e5b75505Sopenharmony_ci
3062e5b75505Sopenharmony_ci#ifdef OPENSSL_IS_BORINGSSL
3063e5b75505Sopenharmony_ci	if (openssl_ciphers && os_strcmp(openssl_ciphers, "SUITEB192") == 0) {
3064e5b75505Sopenharmony_ci		uint16_t sigalgs[1] = { SSL_SIGN_ECDSA_SECP384R1_SHA384 };
3065e5b75505Sopenharmony_ci		int nid[1] = { NID_secp384r1 };
3066e5b75505Sopenharmony_ci
3067e5b75505Sopenharmony_ci		if (SSL_set1_curves(ssl, nid, 1) != 1) {
3068e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
3069e5b75505Sopenharmony_ci				   "OpenSSL: Failed to set Suite B curves");
3070e5b75505Sopenharmony_ci			return -1;
3071e5b75505Sopenharmony_ci		}
3072e5b75505Sopenharmony_ci
3073e5b75505Sopenharmony_ci		if (SSL_CTX_set_verify_algorithm_prefs(conn->ssl_ctx, sigalgs,
3074e5b75505Sopenharmony_ci						       1) != 1) {
3075e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
3076e5b75505Sopenharmony_ci				   "OpenSSL: Failed to set Suite B sigalgs");
3077e5b75505Sopenharmony_ci			return -1;
3078e5b75505Sopenharmony_ci		}
3079e5b75505Sopenharmony_ci	}
3080e5b75505Sopenharmony_ci#else /* OPENSSL_IS_BORINGSSL */
3081e5b75505Sopenharmony_ci	if (!(flags & (TLS_CONN_SUITEB | TLS_CONN_SUITEB_NO_ECDH)) &&
3082e5b75505Sopenharmony_ci	    openssl_ciphers && SSL_set_cipher_list(ssl, openssl_ciphers) != 1) {
3083e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO,
3084e5b75505Sopenharmony_ci			   "OpenSSL: Failed to set openssl_ciphers '%s'",
3085e5b75505Sopenharmony_ci			   openssl_ciphers);
3086e5b75505Sopenharmony_ci		return -1;
3087e5b75505Sopenharmony_ci	}
3088e5b75505Sopenharmony_ci#endif /* OPENSSL_IS_BORINGSSL */
3089e5b75505Sopenharmony_ci#else /* CONFIG_SUITEB */
3090e5b75505Sopenharmony_ci	if (openssl_ciphers && SSL_set_cipher_list(ssl, openssl_ciphers) != 1) {
3091e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO,
3092e5b75505Sopenharmony_ci			   "OpenSSL: Failed to set openssl_ciphers '%s'",
3093e5b75505Sopenharmony_ci			   openssl_ciphers);
3094e5b75505Sopenharmony_ci		return -1;
3095e5b75505Sopenharmony_ci	}
3096e5b75505Sopenharmony_ci#endif /* CONFIG_SUITEB */
3097e5b75505Sopenharmony_ci
3098e5b75505Sopenharmony_ci	if (flags & TLS_CONN_TEAP_ANON_DH) {
3099e5b75505Sopenharmony_ci#ifndef TEAP_DH_ANON_CS
3100e5b75505Sopenharmony_ci#define TEAP_DH_ANON_CS \
3101e5b75505Sopenharmony_ci	"ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:" \
3102e5b75505Sopenharmony_ci	"ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:" \
3103e5b75505Sopenharmony_ci	"ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:" \
3104e5b75505Sopenharmony_ci	"DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:" \
3105e5b75505Sopenharmony_ci	"DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:" \
3106e5b75505Sopenharmony_ci	"DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:" \
3107e5b75505Sopenharmony_ci	"ADH-AES256-GCM-SHA384:ADH-AES128-GCM-SHA256:" \
3108e5b75505Sopenharmony_ci	"ADH-AES256-SHA256:ADH-AES128-SHA256:ADH-AES256-SHA:ADH-AES128-SHA"
3109e5b75505Sopenharmony_ci#endif
3110e5b75505Sopenharmony_ci		static const char *cs = TEAP_DH_ANON_CS;
3111e5b75505Sopenharmony_ci
3112e5b75505Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
3113e5b75505Sopenharmony_ci	!defined(LIBRESSL_VERSION_NUMBER) && \
3114e5b75505Sopenharmony_ci	!defined(OPENSSL_IS_BORINGSSL)
3115e5b75505Sopenharmony_ci		/*
3116e5b75505Sopenharmony_ci		 * Need to drop to security level 0 to allow anonymous
3117e5b75505Sopenharmony_ci		 * cipher suites for EAP-TEAP.
3118e5b75505Sopenharmony_ci		 */
3119e5b75505Sopenharmony_ci		SSL_set_security_level(conn->ssl, 0);
3120e5b75505Sopenharmony_ci#endif
3121e5b75505Sopenharmony_ci
3122e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
3123e5b75505Sopenharmony_ci			   "OpenSSL: Enable cipher suites for anonymous EAP-TEAP provisioning: %s",
3124e5b75505Sopenharmony_ci			   cs);
3125e5b75505Sopenharmony_ci		if (SSL_set_cipher_list(conn->ssl, cs) != 1) {
3126e5b75505Sopenharmony_ci			tls_show_errors(MSG_INFO, __func__,
3127e5b75505Sopenharmony_ci					"Cipher suite configuration failed");
3128e5b75505Sopenharmony_ci			return -1;
3129e5b75505Sopenharmony_ci		}
3130e5b75505Sopenharmony_ci	}
3131e5b75505Sopenharmony_ci
3132e5b75505Sopenharmony_ci	return 0;
3133e5b75505Sopenharmony_ci}
3134e5b75505Sopenharmony_ci
3135e5b75505Sopenharmony_ci
3136e5b75505Sopenharmony_ciint tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
3137e5b75505Sopenharmony_ci			      int verify_peer, unsigned int flags,
3138e5b75505Sopenharmony_ci			      const u8 *session_ctx, size_t session_ctx_len)
3139e5b75505Sopenharmony_ci{
3140e5b75505Sopenharmony_ci	static int counter = 0;
3141e5b75505Sopenharmony_ci	struct tls_data *data = ssl_ctx;
3142e5b75505Sopenharmony_ci
3143e5b75505Sopenharmony_ci	if (conn == NULL)
3144e5b75505Sopenharmony_ci		return -1;
3145e5b75505Sopenharmony_ci
3146e5b75505Sopenharmony_ci	if (verify_peer) {
3147e5b75505Sopenharmony_ci		conn->ca_cert_verify = 1;
3148e5b75505Sopenharmony_ci		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER |
3149e5b75505Sopenharmony_ci			       SSL_VERIFY_FAIL_IF_NO_PEER_CERT |
3150e5b75505Sopenharmony_ci			       SSL_VERIFY_CLIENT_ONCE, tls_verify_cb);
3151e5b75505Sopenharmony_ci	} else {
3152e5b75505Sopenharmony_ci		conn->ca_cert_verify = 0;
3153e5b75505Sopenharmony_ci		SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
3154e5b75505Sopenharmony_ci	}
3155e5b75505Sopenharmony_ci
3156e5b75505Sopenharmony_ci	if (tls_set_conn_flags(conn, flags, NULL) < 0)
3157e5b75505Sopenharmony_ci		return -1;
3158e5b75505Sopenharmony_ci	conn->flags = flags;
3159e5b75505Sopenharmony_ci
3160e5b75505Sopenharmony_ci	SSL_set_accept_state(conn->ssl);
3161e5b75505Sopenharmony_ci
3162e5b75505Sopenharmony_ci	if (data->tls_session_lifetime == 0) {
3163e5b75505Sopenharmony_ci		/*
3164e5b75505Sopenharmony_ci		 * Set session id context to a unique value to make sure
3165e5b75505Sopenharmony_ci		 * session resumption cannot be used either through session
3166e5b75505Sopenharmony_ci		 * caching or TLS ticket extension.
3167e5b75505Sopenharmony_ci		 */
3168e5b75505Sopenharmony_ci		counter++;
3169e5b75505Sopenharmony_ci		SSL_set_session_id_context(conn->ssl,
3170e5b75505Sopenharmony_ci					   (const unsigned char *) &counter,
3171e5b75505Sopenharmony_ci					   sizeof(counter));
3172e5b75505Sopenharmony_ci	} else if (session_ctx) {
3173e5b75505Sopenharmony_ci		SSL_set_session_id_context(conn->ssl, session_ctx,
3174e5b75505Sopenharmony_ci					   session_ctx_len);
3175e5b75505Sopenharmony_ci	}
3176e5b75505Sopenharmony_ci
3177e5b75505Sopenharmony_ci	return 0;
3178e5b75505Sopenharmony_ci}
3179e5b75505Sopenharmony_ci
3180e5b75505Sopenharmony_ci
3181e5b75505Sopenharmony_cistatic int tls_connection_client_cert(struct tls_connection *conn,
3182e5b75505Sopenharmony_ci				      const char *client_cert,
3183e5b75505Sopenharmony_ci				      const u8 *client_cert_blob,
3184e5b75505Sopenharmony_ci				      size_t client_cert_blob_len)
3185e5b75505Sopenharmony_ci{
3186e5b75505Sopenharmony_ci	if (client_cert == NULL && client_cert_blob == NULL)
3187e5b75505Sopenharmony_ci		return 0;
3188e5b75505Sopenharmony_ci
3189e5b75505Sopenharmony_ci#ifdef PKCS12_FUNCS
3190e5b75505Sopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER)
3191e5b75505Sopenharmony_ci	/*
3192e5b75505Sopenharmony_ci	 * Clear previously set extra chain certificates, if any, from PKCS#12
3193e5b75505Sopenharmony_ci	 * processing in tls_parse_pkcs12() to allow OpenSSL to build a new
3194e5b75505Sopenharmony_ci	 * chain properly.
3195e5b75505Sopenharmony_ci	 */
3196e5b75505Sopenharmony_ci	SSL_CTX_clear_extra_chain_certs(conn->ssl_ctx);
3197e5b75505Sopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER < 0x10002000L */
3198e5b75505Sopenharmony_ci#endif /* PKCS12_FUNCS */
3199e5b75505Sopenharmony_ci
3200e5b75505Sopenharmony_ci	if (client_cert_blob &&
3201e5b75505Sopenharmony_ci	    SSL_use_certificate_ASN1(conn->ssl, (u8 *) client_cert_blob,
3202e5b75505Sopenharmony_ci				     client_cert_blob_len) == 1) {
3203e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_ASN1 --> "
3204e5b75505Sopenharmony_ci			   "OK");
3205e5b75505Sopenharmony_ci		return 0;
3206e5b75505Sopenharmony_ci	} else if (client_cert_blob) {
3207e5b75505Sopenharmony_ci		tls_show_errors(MSG_DEBUG, __func__,
3208e5b75505Sopenharmony_ci				"SSL_use_certificate_ASN1 failed");
3209e5b75505Sopenharmony_ci	}
3210e5b75505Sopenharmony_ci
3211e5b75505Sopenharmony_ci	if (client_cert == NULL)
3212e5b75505Sopenharmony_ci		return -1;
3213e5b75505Sopenharmony_ci
3214e5b75505Sopenharmony_ci#ifdef ANDROID
3215e5b75505Sopenharmony_ci	if (os_strncmp("keystore://", client_cert, 11) == 0) {
3216e5b75505Sopenharmony_ci		BIO *bio = BIO_from_keystore(&client_cert[11]);
3217e5b75505Sopenharmony_ci		X509 *x509 = NULL;
3218e5b75505Sopenharmony_ci		int ret = -1;
3219e5b75505Sopenharmony_ci		if (bio) {
3220e5b75505Sopenharmony_ci			x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
3221e5b75505Sopenharmony_ci		}
3222e5b75505Sopenharmony_ci		if (x509) {
3223e5b75505Sopenharmony_ci			if (SSL_use_certificate(conn->ssl, x509) == 1)
3224e5b75505Sopenharmony_ci				ret = 0;
3225e5b75505Sopenharmony_ci			X509_free(x509);
3226e5b75505Sopenharmony_ci		}
3227e5b75505Sopenharmony_ci
3228e5b75505Sopenharmony_ci		/* Read additional certificates into the chain. */
3229e5b75505Sopenharmony_ci		while (bio) {
3230e5b75505Sopenharmony_ci			x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
3231e5b75505Sopenharmony_ci			if (x509) {
3232e5b75505Sopenharmony_ci				/* Takes ownership of x509 */
3233e5b75505Sopenharmony_ci				SSL_add0_chain_cert(conn->ssl, x509);
3234e5b75505Sopenharmony_ci			} else {
3235e5b75505Sopenharmony_ci				BIO_free(bio);
3236e5b75505Sopenharmony_ci				bio = NULL;
3237e5b75505Sopenharmony_ci			}
3238e5b75505Sopenharmony_ci		}
3239e5b75505Sopenharmony_ci		return ret;
3240e5b75505Sopenharmony_ci	}
3241e5b75505Sopenharmony_ci#endif /* ANDROID */
3242e5b75505Sopenharmony_ci
3243e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_STDIO
3244e5b75505Sopenharmony_ci	if (SSL_use_certificate_file(conn->ssl, client_cert,
3245e5b75505Sopenharmony_ci				     SSL_FILETYPE_ASN1) == 1) {
3246e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (DER)"
3247e5b75505Sopenharmony_ci			   " --> OK");
3248e5b75505Sopenharmony_ci		return 0;
3249e5b75505Sopenharmony_ci	}
3250e5b75505Sopenharmony_ci
3251e5b75505Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
3252e5b75505Sopenharmony_ci	!defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL)
3253e5b75505Sopenharmony_ci	if (SSL_use_certificate_chain_file(conn->ssl, client_cert) == 1) {
3254e5b75505Sopenharmony_ci		ERR_clear_error();
3255e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_chain_file"
3256e5b75505Sopenharmony_ci			   " --> OK");
3257e5b75505Sopenharmony_ci		return 0;
3258e5b75505Sopenharmony_ci	}
3259e5b75505Sopenharmony_ci#else
3260e5b75505Sopenharmony_ci	if (SSL_use_certificate_file(conn->ssl, client_cert,
3261e5b75505Sopenharmony_ci				     SSL_FILETYPE_PEM) == 1) {
3262e5b75505Sopenharmony_ci		ERR_clear_error();
3263e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (PEM)"
3264e5b75505Sopenharmony_ci			   " --> OK");
3265e5b75505Sopenharmony_ci		return 0;
3266e5b75505Sopenharmony_ci	}
3267e5b75505Sopenharmony_ci#endif
3268e5b75505Sopenharmony_ci
3269e5b75505Sopenharmony_ci	tls_show_errors(MSG_DEBUG, __func__,
3270e5b75505Sopenharmony_ci			"SSL_use_certificate_file failed");
3271e5b75505Sopenharmony_ci#else /* OPENSSL_NO_STDIO */
3272e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__);
3273e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_STDIO */
3274e5b75505Sopenharmony_ci
3275e5b75505Sopenharmony_ci	return -1;
3276e5b75505Sopenharmony_ci}
3277e5b75505Sopenharmony_ci
3278e5b75505Sopenharmony_ci
3279e5b75505Sopenharmony_cistatic int tls_global_client_cert(struct tls_data *data,
3280e5b75505Sopenharmony_ci				  const char *client_cert)
3281e5b75505Sopenharmony_ci{
3282e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_STDIO
3283e5b75505Sopenharmony_ci	SSL_CTX *ssl_ctx = data->ssl;
3284e5b75505Sopenharmony_ci
3285e5b75505Sopenharmony_ci	if (client_cert == NULL)
3286e5b75505Sopenharmony_ci		return 0;
3287e5b75505Sopenharmony_ci
3288e5b75505Sopenharmony_ci	if (SSL_CTX_use_certificate_file(ssl_ctx, client_cert,
3289e5b75505Sopenharmony_ci					 SSL_FILETYPE_ASN1) != 1 &&
3290e5b75505Sopenharmony_ci	    SSL_CTX_use_certificate_chain_file(ssl_ctx, client_cert) != 1 &&
3291e5b75505Sopenharmony_ci	    SSL_CTX_use_certificate_file(ssl_ctx, client_cert,
3292e5b75505Sopenharmony_ci					 SSL_FILETYPE_PEM) != 1) {
3293e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__,
3294e5b75505Sopenharmony_ci				"Failed to load client certificate");
3295e5b75505Sopenharmony_ci		return -1;
3296e5b75505Sopenharmony_ci	}
3297e5b75505Sopenharmony_ci	return 0;
3298e5b75505Sopenharmony_ci#else /* OPENSSL_NO_STDIO */
3299e5b75505Sopenharmony_ci	if (client_cert == NULL)
3300e5b75505Sopenharmony_ci		return 0;
3301e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__);
3302e5b75505Sopenharmony_ci	return -1;
3303e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_STDIO */
3304e5b75505Sopenharmony_ci}
3305e5b75505Sopenharmony_ci
3306e5b75505Sopenharmony_ci
3307e5b75505Sopenharmony_ci#ifdef PKCS12_FUNCS
3308e5b75505Sopenharmony_cistatic int tls_parse_pkcs12(struct tls_data *data, SSL *ssl, PKCS12 *p12,
3309e5b75505Sopenharmony_ci			    const char *passwd)
3310e5b75505Sopenharmony_ci{
3311e5b75505Sopenharmony_ci	EVP_PKEY *pkey;
3312e5b75505Sopenharmony_ci	X509 *cert;
3313e5b75505Sopenharmony_ci	STACK_OF(X509) *certs;
3314e5b75505Sopenharmony_ci	int res = 0;
3315e5b75505Sopenharmony_ci	char buf[256];
3316e5b75505Sopenharmony_ci
3317e5b75505Sopenharmony_ci	pkey = NULL;
3318e5b75505Sopenharmony_ci	cert = NULL;
3319e5b75505Sopenharmony_ci	certs = NULL;
3320e5b75505Sopenharmony_ci	if (!passwd)
3321e5b75505Sopenharmony_ci		passwd = "";
3322e5b75505Sopenharmony_ci	if (!PKCS12_parse(p12, passwd, &pkey, &cert, &certs)) {
3323e5b75505Sopenharmony_ci		tls_show_errors(MSG_DEBUG, __func__,
3324e5b75505Sopenharmony_ci				"Failed to parse PKCS12 file");
3325e5b75505Sopenharmony_ci		PKCS12_free(p12);
3326e5b75505Sopenharmony_ci		return -1;
3327e5b75505Sopenharmony_ci	}
3328e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "TLS: Successfully parsed PKCS12 data");
3329e5b75505Sopenharmony_ci
3330e5b75505Sopenharmony_ci	if (cert) {
3331e5b75505Sopenharmony_ci		X509_NAME_oneline(X509_get_subject_name(cert), buf,
3332e5b75505Sopenharmony_ci				  sizeof(buf));
3333e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "TLS: Got certificate from PKCS12: "
3334e5b75505Sopenharmony_ci			   "subject='%s'", buf);
3335e5b75505Sopenharmony_ci		if (ssl) {
3336e5b75505Sopenharmony_ci			if (SSL_use_certificate(ssl, cert) != 1)
3337e5b75505Sopenharmony_ci				res = -1;
3338e5b75505Sopenharmony_ci		} else {
3339e5b75505Sopenharmony_ci			if (SSL_CTX_use_certificate(data->ssl, cert) != 1)
3340e5b75505Sopenharmony_ci				res = -1;
3341e5b75505Sopenharmony_ci		}
3342e5b75505Sopenharmony_ci		X509_free(cert);
3343e5b75505Sopenharmony_ci	}
3344e5b75505Sopenharmony_ci
3345e5b75505Sopenharmony_ci	if (pkey) {
3346e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "TLS: Got private key from PKCS12");
3347e5b75505Sopenharmony_ci		if (ssl) {
3348e5b75505Sopenharmony_ci			if (SSL_use_PrivateKey(ssl, pkey) != 1)
3349e5b75505Sopenharmony_ci				res = -1;
3350e5b75505Sopenharmony_ci		} else {
3351e5b75505Sopenharmony_ci			if (SSL_CTX_use_PrivateKey(data->ssl, pkey) != 1)
3352e5b75505Sopenharmony_ci				res = -1;
3353e5b75505Sopenharmony_ci		}
3354e5b75505Sopenharmony_ci		EVP_PKEY_free(pkey);
3355e5b75505Sopenharmony_ci	}
3356e5b75505Sopenharmony_ci
3357e5b75505Sopenharmony_ci	if (certs) {
3358e5b75505Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
3359e5b75505Sopenharmony_ci		if (ssl)
3360e5b75505Sopenharmony_ci			SSL_clear_chain_certs(ssl);
3361e5b75505Sopenharmony_ci		else
3362e5b75505Sopenharmony_ci			SSL_CTX_clear_chain_certs(data->ssl);
3363e5b75505Sopenharmony_ci		while ((cert = sk_X509_pop(certs)) != NULL) {
3364e5b75505Sopenharmony_ci			X509_NAME_oneline(X509_get_subject_name(cert), buf,
3365e5b75505Sopenharmony_ci					  sizeof(buf));
3366e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "TLS: additional certificate"
3367e5b75505Sopenharmony_ci				   " from PKCS12: subject='%s'", buf);
3368e5b75505Sopenharmony_ci			if ((ssl && SSL_add1_chain_cert(ssl, cert) != 1) ||
3369e5b75505Sopenharmony_ci			    (!ssl && SSL_CTX_add1_chain_cert(data->ssl,
3370e5b75505Sopenharmony_ci							     cert) != 1)) {
3371e5b75505Sopenharmony_ci				tls_show_errors(MSG_DEBUG, __func__,
3372e5b75505Sopenharmony_ci						"Failed to add additional certificate");
3373e5b75505Sopenharmony_ci				res = -1;
3374e5b75505Sopenharmony_ci				X509_free(cert);
3375e5b75505Sopenharmony_ci				break;
3376e5b75505Sopenharmony_ci			}
3377e5b75505Sopenharmony_ci			X509_free(cert);
3378e5b75505Sopenharmony_ci		}
3379e5b75505Sopenharmony_ci		if (!res) {
3380e5b75505Sopenharmony_ci			/* Try to continue anyway */
3381e5b75505Sopenharmony_ci		}
3382e5b75505Sopenharmony_ci		sk_X509_pop_free(certs, X509_free);
3383e5b75505Sopenharmony_ci#ifndef OPENSSL_IS_BORINGSSL
3384e5b75505Sopenharmony_ci		if (ssl)
3385e5b75505Sopenharmony_ci			res = SSL_build_cert_chain(
3386e5b75505Sopenharmony_ci				ssl,
3387e5b75505Sopenharmony_ci				SSL_BUILD_CHAIN_FLAG_CHECK |
3388e5b75505Sopenharmony_ci				SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR);
3389e5b75505Sopenharmony_ci		else
3390e5b75505Sopenharmony_ci			res = SSL_CTX_build_cert_chain(
3391e5b75505Sopenharmony_ci				data->ssl,
3392e5b75505Sopenharmony_ci				SSL_BUILD_CHAIN_FLAG_CHECK |
3393e5b75505Sopenharmony_ci				SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR);
3394e5b75505Sopenharmony_ci		if (!res) {
3395e5b75505Sopenharmony_ci			tls_show_errors(MSG_DEBUG, __func__,
3396e5b75505Sopenharmony_ci					"Failed to build certificate chain");
3397e5b75505Sopenharmony_ci		} else if (res == 2) {
3398e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
3399e5b75505Sopenharmony_ci				   "TLS: Ignore certificate chain verification error when building chain with PKCS#12 extra certificates");
3400e5b75505Sopenharmony_ci		}
3401e5b75505Sopenharmony_ci#endif /* OPENSSL_IS_BORINGSSL */
3402e5b75505Sopenharmony_ci		/*
3403e5b75505Sopenharmony_ci		 * Try to continue regardless of result since it is possible for
3404e5b75505Sopenharmony_ci		 * the extra certificates not to be required.
3405e5b75505Sopenharmony_ci		 */
3406e5b75505Sopenharmony_ci		res = 0;
3407e5b75505Sopenharmony_ci#else /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
3408e5b75505Sopenharmony_ci		SSL_CTX_clear_extra_chain_certs(data->ssl);
3409e5b75505Sopenharmony_ci		while ((cert = sk_X509_pop(certs)) != NULL) {
3410e5b75505Sopenharmony_ci			X509_NAME_oneline(X509_get_subject_name(cert), buf,
3411e5b75505Sopenharmony_ci					  sizeof(buf));
3412e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "TLS: additional certificate"
3413e5b75505Sopenharmony_ci				   " from PKCS12: subject='%s'", buf);
3414e5b75505Sopenharmony_ci			/*
3415e5b75505Sopenharmony_ci			 * There is no SSL equivalent for the chain cert - so
3416e5b75505Sopenharmony_ci			 * always add it to the context...
3417e5b75505Sopenharmony_ci			 */
3418e5b75505Sopenharmony_ci			if (SSL_CTX_add_extra_chain_cert(data->ssl, cert) != 1)
3419e5b75505Sopenharmony_ci			{
3420e5b75505Sopenharmony_ci				X509_free(cert);
3421e5b75505Sopenharmony_ci				res = -1;
3422e5b75505Sopenharmony_ci				break;
3423e5b75505Sopenharmony_ci			}
3424e5b75505Sopenharmony_ci		}
3425e5b75505Sopenharmony_ci		sk_X509_pop_free(certs, X509_free);
3426e5b75505Sopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
3427e5b75505Sopenharmony_ci	}
3428e5b75505Sopenharmony_ci
3429e5b75505Sopenharmony_ci	PKCS12_free(p12);
3430e5b75505Sopenharmony_ci
3431e5b75505Sopenharmony_ci	if (res < 0)
3432e5b75505Sopenharmony_ci		tls_get_errors(data);
3433e5b75505Sopenharmony_ci
3434e5b75505Sopenharmony_ci	return res;
3435e5b75505Sopenharmony_ci}
3436e5b75505Sopenharmony_ci#endif  /* PKCS12_FUNCS */
3437e5b75505Sopenharmony_ci
3438e5b75505Sopenharmony_ci
3439e5b75505Sopenharmony_cistatic int tls_read_pkcs12(struct tls_data *data, SSL *ssl,
3440e5b75505Sopenharmony_ci			   const char *private_key, const char *passwd)
3441e5b75505Sopenharmony_ci{
3442e5b75505Sopenharmony_ci#ifdef PKCS12_FUNCS
3443e5b75505Sopenharmony_ci	FILE *f;
3444e5b75505Sopenharmony_ci	PKCS12 *p12;
3445e5b75505Sopenharmony_ci
3446e5b75505Sopenharmony_ci	f = fopen(private_key, "rb");
3447e5b75505Sopenharmony_ci	if (f == NULL)
3448e5b75505Sopenharmony_ci		return -1;
3449e5b75505Sopenharmony_ci
3450e5b75505Sopenharmony_ci	p12 = d2i_PKCS12_fp(f, NULL);
3451e5b75505Sopenharmony_ci	fclose(f);
3452e5b75505Sopenharmony_ci
3453e5b75505Sopenharmony_ci	if (p12 == NULL) {
3454e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__,
3455e5b75505Sopenharmony_ci				"Failed to use PKCS#12 file");
3456e5b75505Sopenharmony_ci		return -1;
3457e5b75505Sopenharmony_ci	}
3458e5b75505Sopenharmony_ci
3459e5b75505Sopenharmony_ci	return tls_parse_pkcs12(data, ssl, p12, passwd);
3460e5b75505Sopenharmony_ci
3461e5b75505Sopenharmony_ci#else /* PKCS12_FUNCS */
3462e5b75505Sopenharmony_ci	wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot read "
3463e5b75505Sopenharmony_ci		   "p12/pfx files");
3464e5b75505Sopenharmony_ci	return -1;
3465e5b75505Sopenharmony_ci#endif  /* PKCS12_FUNCS */
3466e5b75505Sopenharmony_ci}
3467e5b75505Sopenharmony_ci
3468e5b75505Sopenharmony_ci
3469e5b75505Sopenharmony_cistatic int tls_read_pkcs12_blob(struct tls_data *data, SSL *ssl,
3470e5b75505Sopenharmony_ci				const u8 *blob, size_t len, const char *passwd)
3471e5b75505Sopenharmony_ci{
3472e5b75505Sopenharmony_ci#ifdef PKCS12_FUNCS
3473e5b75505Sopenharmony_ci	PKCS12 *p12;
3474e5b75505Sopenharmony_ci
3475e5b75505Sopenharmony_ci	p12 = d2i_PKCS12(NULL, (const unsigned char **) &blob, len);
3476e5b75505Sopenharmony_ci	if (p12 == NULL) {
3477e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__,
3478e5b75505Sopenharmony_ci				"Failed to use PKCS#12 blob");
3479e5b75505Sopenharmony_ci		return -1;
3480e5b75505Sopenharmony_ci	}
3481e5b75505Sopenharmony_ci
3482e5b75505Sopenharmony_ci	return tls_parse_pkcs12(data, ssl, p12, passwd);
3483e5b75505Sopenharmony_ci
3484e5b75505Sopenharmony_ci#else /* PKCS12_FUNCS */
3485e5b75505Sopenharmony_ci	wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot parse "
3486e5b75505Sopenharmony_ci		   "p12/pfx blobs");
3487e5b75505Sopenharmony_ci	return -1;
3488e5b75505Sopenharmony_ci#endif  /* PKCS12_FUNCS */
3489e5b75505Sopenharmony_ci}
3490e5b75505Sopenharmony_ci
3491e5b75505Sopenharmony_ci
3492e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
3493e5b75505Sopenharmony_cistatic int tls_engine_get_cert(struct tls_connection *conn,
3494e5b75505Sopenharmony_ci			       const char *cert_id,
3495e5b75505Sopenharmony_ci			       X509 **cert)
3496e5b75505Sopenharmony_ci{
3497e5b75505Sopenharmony_ci	/* this runs after the private key is loaded so no PIN is required */
3498e5b75505Sopenharmony_ci	struct {
3499e5b75505Sopenharmony_ci		const char *cert_id;
3500e5b75505Sopenharmony_ci		X509 *cert;
3501e5b75505Sopenharmony_ci	} params;
3502e5b75505Sopenharmony_ci	params.cert_id = cert_id;
3503e5b75505Sopenharmony_ci	params.cert = NULL;
3504e5b75505Sopenharmony_ci
3505e5b75505Sopenharmony_ci	if (!ENGINE_ctrl_cmd(conn->engine, "LOAD_CERT_CTRL",
3506e5b75505Sopenharmony_ci			     0, &params, NULL, 1)) {
3507e5b75505Sopenharmony_ci		unsigned long err = ERR_get_error();
3508e5b75505Sopenharmony_ci
3509e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR, "ENGINE: cannot load client cert with id"
3510e5b75505Sopenharmony_ci			   " '%s' [%s]", cert_id,
3511e5b75505Sopenharmony_ci			   ERR_error_string(err, NULL));
3512e5b75505Sopenharmony_ci		if (tls_is_pin_error(err))
3513e5b75505Sopenharmony_ci			return TLS_SET_PARAMS_ENGINE_PRV_BAD_PIN;
3514e5b75505Sopenharmony_ci		return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
3515e5b75505Sopenharmony_ci	}
3516e5b75505Sopenharmony_ci	if (!params.cert) {
3517e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR, "ENGINE: did not properly cert with id"
3518e5b75505Sopenharmony_ci			   " '%s'", cert_id);
3519e5b75505Sopenharmony_ci		return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
3520e5b75505Sopenharmony_ci	}
3521e5b75505Sopenharmony_ci	*cert = params.cert;
3522e5b75505Sopenharmony_ci	return 0;
3523e5b75505Sopenharmony_ci}
3524e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_ENGINE */
3525e5b75505Sopenharmony_ci
3526e5b75505Sopenharmony_ci
3527e5b75505Sopenharmony_cistatic int tls_connection_engine_client_cert(struct tls_connection *conn,
3528e5b75505Sopenharmony_ci					     const char *cert_id)
3529e5b75505Sopenharmony_ci{
3530e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
3531e5b75505Sopenharmony_ci	X509 *cert;
3532e5b75505Sopenharmony_ci
3533e5b75505Sopenharmony_ci	if (tls_engine_get_cert(conn, cert_id, &cert))
3534e5b75505Sopenharmony_ci		return -1;
3535e5b75505Sopenharmony_ci
3536e5b75505Sopenharmony_ci	if (!SSL_use_certificate(conn->ssl, cert)) {
3537e5b75505Sopenharmony_ci		tls_show_errors(MSG_ERROR, __func__,
3538e5b75505Sopenharmony_ci				"SSL_use_certificate failed");
3539e5b75505Sopenharmony_ci                X509_free(cert);
3540e5b75505Sopenharmony_ci		return -1;
3541e5b75505Sopenharmony_ci	}
3542e5b75505Sopenharmony_ci	X509_free(cert);
3543e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "ENGINE: SSL_use_certificate --> "
3544e5b75505Sopenharmony_ci		   "OK");
3545e5b75505Sopenharmony_ci	return 0;
3546e5b75505Sopenharmony_ci
3547e5b75505Sopenharmony_ci#else /* OPENSSL_NO_ENGINE */
3548e5b75505Sopenharmony_ci	return -1;
3549e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_ENGINE */
3550e5b75505Sopenharmony_ci}
3551e5b75505Sopenharmony_ci
3552e5b75505Sopenharmony_ci
3553e5b75505Sopenharmony_cistatic int tls_connection_engine_ca_cert(struct tls_data *data,
3554e5b75505Sopenharmony_ci					 struct tls_connection *conn,
3555e5b75505Sopenharmony_ci					 const char *ca_cert_id)
3556e5b75505Sopenharmony_ci{
3557e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
3558e5b75505Sopenharmony_ci	X509 *cert;
3559e5b75505Sopenharmony_ci	SSL_CTX *ssl_ctx = data->ssl;
3560e5b75505Sopenharmony_ci	X509_STORE *store;
3561e5b75505Sopenharmony_ci
3562e5b75505Sopenharmony_ci	if (tls_engine_get_cert(conn, ca_cert_id, &cert))
3563e5b75505Sopenharmony_ci		return -1;
3564e5b75505Sopenharmony_ci
3565e5b75505Sopenharmony_ci	/* start off the same as tls_connection_ca_cert */
3566e5b75505Sopenharmony_ci	store = X509_STORE_new();
3567e5b75505Sopenharmony_ci	if (store == NULL) {
3568e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new "
3569e5b75505Sopenharmony_ci			   "certificate store", __func__);
3570e5b75505Sopenharmony_ci		X509_free(cert);
3571e5b75505Sopenharmony_ci		return -1;
3572e5b75505Sopenharmony_ci	}
3573e5b75505Sopenharmony_ci	SSL_CTX_set_cert_store(ssl_ctx, store);
3574e5b75505Sopenharmony_ci	if (!X509_STORE_add_cert(store, cert)) {
3575e5b75505Sopenharmony_ci		unsigned long err = ERR_peek_error();
3576e5b75505Sopenharmony_ci		tls_show_errors(MSG_WARNING, __func__,
3577e5b75505Sopenharmony_ci				"Failed to add CA certificate from engine "
3578e5b75505Sopenharmony_ci				"to certificate store");
3579e5b75505Sopenharmony_ci		if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
3580e5b75505Sopenharmony_ci		    ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) {
3581e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring cert"
3582e5b75505Sopenharmony_ci				   " already in hash table error",
3583e5b75505Sopenharmony_ci				   __func__);
3584e5b75505Sopenharmony_ci		} else {
3585e5b75505Sopenharmony_ci			X509_free(cert);
3586e5b75505Sopenharmony_ci			return -1;
3587e5b75505Sopenharmony_ci		}
3588e5b75505Sopenharmony_ci	}
3589e5b75505Sopenharmony_ci	X509_free(cert);
3590e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "OpenSSL: %s - added CA certificate from engine "
3591e5b75505Sopenharmony_ci		   "to certificate store", __func__);
3592e5b75505Sopenharmony_ci	SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
3593e5b75505Sopenharmony_ci	conn->ca_cert_verify = 1;
3594e5b75505Sopenharmony_ci
3595e5b75505Sopenharmony_ci	return 0;
3596e5b75505Sopenharmony_ci
3597e5b75505Sopenharmony_ci#else /* OPENSSL_NO_ENGINE */
3598e5b75505Sopenharmony_ci	return -1;
3599e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_ENGINE */
3600e5b75505Sopenharmony_ci}
3601e5b75505Sopenharmony_ci
3602e5b75505Sopenharmony_ci
3603e5b75505Sopenharmony_cistatic int tls_connection_engine_private_key(struct tls_connection *conn)
3604e5b75505Sopenharmony_ci{
3605e5b75505Sopenharmony_ci#if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE)
3606e5b75505Sopenharmony_ci	if (SSL_use_PrivateKey(conn->ssl, conn->private_key) != 1) {
3607e5b75505Sopenharmony_ci		tls_show_errors(MSG_ERROR, __func__,
3608e5b75505Sopenharmony_ci				"ENGINE: cannot use private key for TLS");
3609e5b75505Sopenharmony_ci		return -1;
3610e5b75505Sopenharmony_ci	}
3611e5b75505Sopenharmony_ci	if (!SSL_check_private_key(conn->ssl)) {
3612e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__,
3613e5b75505Sopenharmony_ci				"Private key failed verification");
3614e5b75505Sopenharmony_ci		return -1;
3615e5b75505Sopenharmony_ci	}
3616e5b75505Sopenharmony_ci	return 0;
3617e5b75505Sopenharmony_ci#else /* OPENSSL_NO_ENGINE */
3618e5b75505Sopenharmony_ci	wpa_printf(MSG_ERROR, "SSL: Configuration uses engine, but "
3619e5b75505Sopenharmony_ci		   "engine support was not compiled in");
3620e5b75505Sopenharmony_ci	return -1;
3621e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_ENGINE */
3622e5b75505Sopenharmony_ci}
3623e5b75505Sopenharmony_ci
3624e5b75505Sopenharmony_ci
3625e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_STDIO
3626e5b75505Sopenharmony_cistatic int tls_passwd_cb(char *buf, int size, int rwflag, void *password)
3627e5b75505Sopenharmony_ci{
3628e5b75505Sopenharmony_ci	if (!password)
3629e5b75505Sopenharmony_ci		return 0;
3630e5b75505Sopenharmony_ci	os_strlcpy(buf, (const char *) password, size);
3631e5b75505Sopenharmony_ci	return os_strlen(buf);
3632e5b75505Sopenharmony_ci}
3633e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_STDIO */
3634e5b75505Sopenharmony_ci
3635e5b75505Sopenharmony_ci
3636e5b75505Sopenharmony_cistatic int tls_use_private_key_file(struct tls_data *data, SSL *ssl,
3637e5b75505Sopenharmony_ci				    const char *private_key,
3638e5b75505Sopenharmony_ci				    const char *private_key_passwd)
3639e5b75505Sopenharmony_ci{
3640e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_STDIO
3641e5b75505Sopenharmony_ci	BIO *bio;
3642e5b75505Sopenharmony_ci	EVP_PKEY *pkey;
3643e5b75505Sopenharmony_ci	int ret;
3644e5b75505Sopenharmony_ci
3645e5b75505Sopenharmony_ci	/* First try ASN.1 (DER). */
3646e5b75505Sopenharmony_ci	bio = BIO_new_file(private_key, "r");
3647e5b75505Sopenharmony_ci	if (!bio)
3648e5b75505Sopenharmony_ci		return -1;
3649e5b75505Sopenharmony_ci	pkey = d2i_PrivateKey_bio(bio, NULL);
3650e5b75505Sopenharmony_ci	BIO_free(bio);
3651e5b75505Sopenharmony_ci
3652e5b75505Sopenharmony_ci	if (pkey) {
3653e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: %s (DER) --> loaded", __func__);
3654e5b75505Sopenharmony_ci	} else {
3655e5b75505Sopenharmony_ci		/* Try PEM with the provided password. */
3656e5b75505Sopenharmony_ci		bio = BIO_new_file(private_key, "r");
3657e5b75505Sopenharmony_ci		if (!bio)
3658e5b75505Sopenharmony_ci			return -1;
3659e5b75505Sopenharmony_ci		pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_passwd_cb,
3660e5b75505Sopenharmony_ci					       (void *) private_key_passwd);
3661e5b75505Sopenharmony_ci		BIO_free(bio);
3662e5b75505Sopenharmony_ci		if (!pkey)
3663e5b75505Sopenharmony_ci			return -1;
3664e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: %s (PEM) --> loaded", __func__);
3665e5b75505Sopenharmony_ci		/* Clear errors from the previous failed load. */
3666e5b75505Sopenharmony_ci		ERR_clear_error();
3667e5b75505Sopenharmony_ci	}
3668e5b75505Sopenharmony_ci
3669e5b75505Sopenharmony_ci	if (ssl)
3670e5b75505Sopenharmony_ci		ret = SSL_use_PrivateKey(ssl, pkey);
3671e5b75505Sopenharmony_ci	else
3672e5b75505Sopenharmony_ci		ret = SSL_CTX_use_PrivateKey(data->ssl, pkey);
3673e5b75505Sopenharmony_ci
3674e5b75505Sopenharmony_ci	EVP_PKEY_free(pkey);
3675e5b75505Sopenharmony_ci	return ret == 1 ? 0 : -1;
3676e5b75505Sopenharmony_ci#else /* OPENSSL_NO_STDIO */
3677e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__);
3678e5b75505Sopenharmony_ci	return -1;
3679e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_STDIO */
3680e5b75505Sopenharmony_ci}
3681e5b75505Sopenharmony_ci
3682e5b75505Sopenharmony_ci
3683e5b75505Sopenharmony_cistatic int tls_connection_private_key(struct tls_data *data,
3684e5b75505Sopenharmony_ci				      struct tls_connection *conn,
3685e5b75505Sopenharmony_ci				      const char *private_key,
3686e5b75505Sopenharmony_ci				      const char *private_key_passwd,
3687e5b75505Sopenharmony_ci				      const u8 *private_key_blob,
3688e5b75505Sopenharmony_ci				      size_t private_key_blob_len)
3689e5b75505Sopenharmony_ci{
3690e5b75505Sopenharmony_ci	int ok;
3691e5b75505Sopenharmony_ci
3692e5b75505Sopenharmony_ci	if (private_key == NULL && private_key_blob == NULL)
3693e5b75505Sopenharmony_ci		return 0;
3694e5b75505Sopenharmony_ci
3695e5b75505Sopenharmony_ci	ok = 0;
3696e5b75505Sopenharmony_ci	while (private_key_blob) {
3697e5b75505Sopenharmony_ci		if (SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA, conn->ssl,
3698e5b75505Sopenharmony_ci					    (u8 *) private_key_blob,
3699e5b75505Sopenharmony_ci					    private_key_blob_len) == 1) {
3700e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_"
3701e5b75505Sopenharmony_ci				   "ASN1(EVP_PKEY_RSA) --> OK");
3702e5b75505Sopenharmony_ci			ok = 1;
3703e5b75505Sopenharmony_ci			break;
3704e5b75505Sopenharmony_ci		}
3705e5b75505Sopenharmony_ci
3706e5b75505Sopenharmony_ci		if (SSL_use_PrivateKey_ASN1(EVP_PKEY_DSA, conn->ssl,
3707e5b75505Sopenharmony_ci					    (u8 *) private_key_blob,
3708e5b75505Sopenharmony_ci					    private_key_blob_len) == 1) {
3709e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_"
3710e5b75505Sopenharmony_ci				   "ASN1(EVP_PKEY_DSA) --> OK");
3711e5b75505Sopenharmony_ci			ok = 1;
3712e5b75505Sopenharmony_ci			break;
3713e5b75505Sopenharmony_ci		}
3714e5b75505Sopenharmony_ci
3715e5b75505Sopenharmony_ci		if (SSL_use_RSAPrivateKey_ASN1(conn->ssl,
3716e5b75505Sopenharmony_ci					       (u8 *) private_key_blob,
3717e5b75505Sopenharmony_ci					       private_key_blob_len) == 1) {
3718e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "OpenSSL: "
3719e5b75505Sopenharmony_ci				   "SSL_use_RSAPrivateKey_ASN1 --> OK");
3720e5b75505Sopenharmony_ci			ok = 1;
3721e5b75505Sopenharmony_ci			break;
3722e5b75505Sopenharmony_ci		}
3723e5b75505Sopenharmony_ci
3724e5b75505Sopenharmony_ci		if (tls_read_pkcs12_blob(data, conn->ssl, private_key_blob,
3725e5b75505Sopenharmony_ci					 private_key_blob_len,
3726e5b75505Sopenharmony_ci					 private_key_passwd) == 0) {
3727e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "OpenSSL: PKCS#12 as blob --> "
3728e5b75505Sopenharmony_ci				   "OK");
3729e5b75505Sopenharmony_ci			ok = 1;
3730e5b75505Sopenharmony_ci			break;
3731e5b75505Sopenharmony_ci		}
3732e5b75505Sopenharmony_ci
3733e5b75505Sopenharmony_ci		break;
3734e5b75505Sopenharmony_ci	}
3735e5b75505Sopenharmony_ci
3736e5b75505Sopenharmony_ci	while (!ok && private_key) {
3737e5b75505Sopenharmony_ci		if (tls_use_private_key_file(data, conn->ssl, private_key,
3738e5b75505Sopenharmony_ci					     private_key_passwd) == 0) {
3739e5b75505Sopenharmony_ci			ok = 1;
3740e5b75505Sopenharmony_ci			break;
3741e5b75505Sopenharmony_ci		}
3742e5b75505Sopenharmony_ci
3743e5b75505Sopenharmony_ci		if (tls_read_pkcs12(data, conn->ssl, private_key,
3744e5b75505Sopenharmony_ci				    private_key_passwd) == 0) {
3745e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "OpenSSL: Reading PKCS#12 file "
3746e5b75505Sopenharmony_ci				   "--> OK");
3747e5b75505Sopenharmony_ci			ok = 1;
3748e5b75505Sopenharmony_ci			break;
3749e5b75505Sopenharmony_ci		}
3750e5b75505Sopenharmony_ci
3751e5b75505Sopenharmony_ci		if (tls_cryptoapi_cert(conn->ssl, private_key) == 0) {
3752e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "OpenSSL: Using CryptoAPI to "
3753e5b75505Sopenharmony_ci				   "access certificate store --> OK");
3754e5b75505Sopenharmony_ci			ok = 1;
3755e5b75505Sopenharmony_ci			break;
3756e5b75505Sopenharmony_ci		}
3757e5b75505Sopenharmony_ci
3758e5b75505Sopenharmony_ci		break;
3759e5b75505Sopenharmony_ci	}
3760e5b75505Sopenharmony_ci
3761e5b75505Sopenharmony_ci	if (!ok) {
3762e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__,
3763e5b75505Sopenharmony_ci				"Failed to load private key");
3764e5b75505Sopenharmony_ci		return -1;
3765e5b75505Sopenharmony_ci	}
3766e5b75505Sopenharmony_ci	ERR_clear_error();
3767e5b75505Sopenharmony_ci
3768e5b75505Sopenharmony_ci	if (!SSL_check_private_key(conn->ssl)) {
3769e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__, "Private key failed "
3770e5b75505Sopenharmony_ci				"verification");
3771e5b75505Sopenharmony_ci		return -1;
3772e5b75505Sopenharmony_ci	}
3773e5b75505Sopenharmony_ci
3774e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "SSL: Private key loaded successfully");
3775e5b75505Sopenharmony_ci	return 0;
3776e5b75505Sopenharmony_ci}
3777e5b75505Sopenharmony_ci
3778e5b75505Sopenharmony_ci
3779e5b75505Sopenharmony_cistatic int tls_global_private_key(struct tls_data *data,
3780e5b75505Sopenharmony_ci				  const char *private_key,
3781e5b75505Sopenharmony_ci				  const char *private_key_passwd)
3782e5b75505Sopenharmony_ci{
3783e5b75505Sopenharmony_ci	SSL_CTX *ssl_ctx = data->ssl;
3784e5b75505Sopenharmony_ci
3785e5b75505Sopenharmony_ci	if (private_key == NULL)
3786e5b75505Sopenharmony_ci		return 0;
3787e5b75505Sopenharmony_ci
3788e5b75505Sopenharmony_ci	if (tls_use_private_key_file(data, NULL, private_key,
3789e5b75505Sopenharmony_ci				     private_key_passwd) &&
3790e5b75505Sopenharmony_ci	    tls_read_pkcs12(data, NULL, private_key, private_key_passwd)) {
3791e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__,
3792e5b75505Sopenharmony_ci				"Failed to load private key");
3793e5b75505Sopenharmony_ci		ERR_clear_error();
3794e5b75505Sopenharmony_ci		return -1;
3795e5b75505Sopenharmony_ci	}
3796e5b75505Sopenharmony_ci	ERR_clear_error();
3797e5b75505Sopenharmony_ci
3798e5b75505Sopenharmony_ci	if (!SSL_CTX_check_private_key(ssl_ctx)) {
3799e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__,
3800e5b75505Sopenharmony_ci				"Private key failed verification");
3801e5b75505Sopenharmony_ci		return -1;
3802e5b75505Sopenharmony_ci	}
3803e5b75505Sopenharmony_ci
3804e5b75505Sopenharmony_ci	return 0;
3805e5b75505Sopenharmony_ci}
3806e5b75505Sopenharmony_ci
3807e5b75505Sopenharmony_ci
3808e5b75505Sopenharmony_cistatic int tls_connection_dh(struct tls_connection *conn, const char *dh_file)
3809e5b75505Sopenharmony_ci{
3810e5b75505Sopenharmony_ci#ifdef OPENSSL_NO_DH
3811e5b75505Sopenharmony_ci	if (dh_file == NULL)
3812e5b75505Sopenharmony_ci		return 0;
3813e5b75505Sopenharmony_ci	wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but "
3814e5b75505Sopenharmony_ci		   "dh_file specified");
3815e5b75505Sopenharmony_ci	return -1;
3816e5b75505Sopenharmony_ci#else /* OPENSSL_NO_DH */
3817e5b75505Sopenharmony_ci	DH *dh;
3818e5b75505Sopenharmony_ci	BIO *bio;
3819e5b75505Sopenharmony_ci
3820e5b75505Sopenharmony_ci	/* TODO: add support for dh_blob */
3821e5b75505Sopenharmony_ci	if (dh_file == NULL)
3822e5b75505Sopenharmony_ci		return 0;
3823e5b75505Sopenharmony_ci	if (conn == NULL)
3824e5b75505Sopenharmony_ci		return -1;
3825e5b75505Sopenharmony_ci
3826e5b75505Sopenharmony_ci	bio = BIO_new_file(dh_file, "r");
3827e5b75505Sopenharmony_ci	if (bio == NULL) {
3828e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s",
3829e5b75505Sopenharmony_ci			   dh_file, ERR_error_string(ERR_get_error(), NULL));
3830e5b75505Sopenharmony_ci		return -1;
3831e5b75505Sopenharmony_ci	}
3832e5b75505Sopenharmony_ci	dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
3833e5b75505Sopenharmony_ci	BIO_free(bio);
3834e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_DSA
3835e5b75505Sopenharmony_ci	while (dh == NULL) {
3836e5b75505Sopenharmony_ci		DSA *dsa;
3837e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -"
3838e5b75505Sopenharmony_ci			   " trying to parse as DSA params", dh_file,
3839e5b75505Sopenharmony_ci			   ERR_error_string(ERR_get_error(), NULL));
3840e5b75505Sopenharmony_ci		bio = BIO_new_file(dh_file, "r");
3841e5b75505Sopenharmony_ci		if (bio == NULL)
3842e5b75505Sopenharmony_ci			break;
3843e5b75505Sopenharmony_ci		dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL);
3844e5b75505Sopenharmony_ci		BIO_free(bio);
3845e5b75505Sopenharmony_ci		if (!dsa) {
3846e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file "
3847e5b75505Sopenharmony_ci				   "'%s': %s", dh_file,
3848e5b75505Sopenharmony_ci				   ERR_error_string(ERR_get_error(), NULL));
3849e5b75505Sopenharmony_ci			break;
3850e5b75505Sopenharmony_ci		}
3851e5b75505Sopenharmony_ci
3852e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format");
3853e5b75505Sopenharmony_ci		dh = DSA_dup_DH(dsa);
3854e5b75505Sopenharmony_ci		DSA_free(dsa);
3855e5b75505Sopenharmony_ci		if (dh == NULL) {
3856e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO, "TLS: Failed to convert DSA "
3857e5b75505Sopenharmony_ci				   "params into DH params");
3858e5b75505Sopenharmony_ci			break;
3859e5b75505Sopenharmony_ci		}
3860e5b75505Sopenharmony_ci		break;
3861e5b75505Sopenharmony_ci	}
3862e5b75505Sopenharmony_ci#endif /* !OPENSSL_NO_DSA */
3863e5b75505Sopenharmony_ci	if (dh == NULL) {
3864e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file "
3865e5b75505Sopenharmony_ci			   "'%s'", dh_file);
3866e5b75505Sopenharmony_ci		return -1;
3867e5b75505Sopenharmony_ci	}
3868e5b75505Sopenharmony_ci
3869e5b75505Sopenharmony_ci	if (SSL_set_tmp_dh(conn->ssl, dh) != 1) {
3870e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': "
3871e5b75505Sopenharmony_ci			   "%s", dh_file,
3872e5b75505Sopenharmony_ci			   ERR_error_string(ERR_get_error(), NULL));
3873e5b75505Sopenharmony_ci		DH_free(dh);
3874e5b75505Sopenharmony_ci		return -1;
3875e5b75505Sopenharmony_ci	}
3876e5b75505Sopenharmony_ci	DH_free(dh);
3877e5b75505Sopenharmony_ci	return 0;
3878e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_DH */
3879e5b75505Sopenharmony_ci}
3880e5b75505Sopenharmony_ci
3881e5b75505Sopenharmony_ci
3882e5b75505Sopenharmony_cistatic int tls_global_dh(struct tls_data *data, const char *dh_file)
3883e5b75505Sopenharmony_ci{
3884e5b75505Sopenharmony_ci#ifdef OPENSSL_NO_DH
3885e5b75505Sopenharmony_ci	if (dh_file == NULL)
3886e5b75505Sopenharmony_ci		return 0;
3887e5b75505Sopenharmony_ci	wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but "
3888e5b75505Sopenharmony_ci		   "dh_file specified");
3889e5b75505Sopenharmony_ci	return -1;
3890e5b75505Sopenharmony_ci#else /* OPENSSL_NO_DH */
3891e5b75505Sopenharmony_ci	SSL_CTX *ssl_ctx = data->ssl;
3892e5b75505Sopenharmony_ci	DH *dh;
3893e5b75505Sopenharmony_ci	BIO *bio;
3894e5b75505Sopenharmony_ci
3895e5b75505Sopenharmony_ci	/* TODO: add support for dh_blob */
3896e5b75505Sopenharmony_ci	if (dh_file == NULL)
3897e5b75505Sopenharmony_ci		return 0;
3898e5b75505Sopenharmony_ci	if (ssl_ctx == NULL)
3899e5b75505Sopenharmony_ci		return -1;
3900e5b75505Sopenharmony_ci
3901e5b75505Sopenharmony_ci	bio = BIO_new_file(dh_file, "r");
3902e5b75505Sopenharmony_ci	if (bio == NULL) {
3903e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s",
3904e5b75505Sopenharmony_ci			   dh_file, ERR_error_string(ERR_get_error(), NULL));
3905e5b75505Sopenharmony_ci		return -1;
3906e5b75505Sopenharmony_ci	}
3907e5b75505Sopenharmony_ci	dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
3908e5b75505Sopenharmony_ci	BIO_free(bio);
3909e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_DSA
3910e5b75505Sopenharmony_ci	while (dh == NULL) {
3911e5b75505Sopenharmony_ci		DSA *dsa;
3912e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -"
3913e5b75505Sopenharmony_ci			   " trying to parse as DSA params", dh_file,
3914e5b75505Sopenharmony_ci			   ERR_error_string(ERR_get_error(), NULL));
3915e5b75505Sopenharmony_ci		bio = BIO_new_file(dh_file, "r");
3916e5b75505Sopenharmony_ci		if (bio == NULL)
3917e5b75505Sopenharmony_ci			break;
3918e5b75505Sopenharmony_ci		dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL);
3919e5b75505Sopenharmony_ci		BIO_free(bio);
3920e5b75505Sopenharmony_ci		if (!dsa) {
3921e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file "
3922e5b75505Sopenharmony_ci				   "'%s': %s", dh_file,
3923e5b75505Sopenharmony_ci				   ERR_error_string(ERR_get_error(), NULL));
3924e5b75505Sopenharmony_ci			break;
3925e5b75505Sopenharmony_ci		}
3926e5b75505Sopenharmony_ci
3927e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format");
3928e5b75505Sopenharmony_ci		dh = DSA_dup_DH(dsa);
3929e5b75505Sopenharmony_ci		DSA_free(dsa);
3930e5b75505Sopenharmony_ci		if (dh == NULL) {
3931e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO, "TLS: Failed to convert DSA "
3932e5b75505Sopenharmony_ci				   "params into DH params");
3933e5b75505Sopenharmony_ci			break;
3934e5b75505Sopenharmony_ci		}
3935e5b75505Sopenharmony_ci		break;
3936e5b75505Sopenharmony_ci	}
3937e5b75505Sopenharmony_ci#endif /* !OPENSSL_NO_DSA */
3938e5b75505Sopenharmony_ci	if (dh == NULL) {
3939e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file "
3940e5b75505Sopenharmony_ci			   "'%s'", dh_file);
3941e5b75505Sopenharmony_ci		return -1;
3942e5b75505Sopenharmony_ci	}
3943e5b75505Sopenharmony_ci
3944e5b75505Sopenharmony_ci	if (SSL_CTX_set_tmp_dh(ssl_ctx, dh) != 1) {
3945e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': "
3946e5b75505Sopenharmony_ci			   "%s", dh_file,
3947e5b75505Sopenharmony_ci			   ERR_error_string(ERR_get_error(), NULL));
3948e5b75505Sopenharmony_ci		DH_free(dh);
3949e5b75505Sopenharmony_ci		return -1;
3950e5b75505Sopenharmony_ci	}
3951e5b75505Sopenharmony_ci	DH_free(dh);
3952e5b75505Sopenharmony_ci	return 0;
3953e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_DH */
3954e5b75505Sopenharmony_ci}
3955e5b75505Sopenharmony_ci
3956e5b75505Sopenharmony_ci
3957e5b75505Sopenharmony_ciint tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn,
3958e5b75505Sopenharmony_ci			      struct tls_random *keys)
3959e5b75505Sopenharmony_ci{
3960e5b75505Sopenharmony_ci	SSL *ssl;
3961e5b75505Sopenharmony_ci
3962e5b75505Sopenharmony_ci	if (conn == NULL || keys == NULL)
3963e5b75505Sopenharmony_ci		return -1;
3964e5b75505Sopenharmony_ci	ssl = conn->ssl;
3965e5b75505Sopenharmony_ci	if (ssl == NULL)
3966e5b75505Sopenharmony_ci		return -1;
3967e5b75505Sopenharmony_ci
3968e5b75505Sopenharmony_ci	os_memset(keys, 0, sizeof(*keys));
3969e5b75505Sopenharmony_ci	keys->client_random = conn->client_random;
3970e5b75505Sopenharmony_ci	keys->client_random_len = SSL_get_client_random(
3971e5b75505Sopenharmony_ci		ssl, conn->client_random, sizeof(conn->client_random));
3972e5b75505Sopenharmony_ci	keys->server_random = conn->server_random;
3973e5b75505Sopenharmony_ci	keys->server_random_len = SSL_get_server_random(
3974e5b75505Sopenharmony_ci		ssl, conn->server_random, sizeof(conn->server_random));
3975e5b75505Sopenharmony_ci
3976e5b75505Sopenharmony_ci	return 0;
3977e5b75505Sopenharmony_ci}
3978e5b75505Sopenharmony_ci
3979e5b75505Sopenharmony_ci
3980e5b75505Sopenharmony_ci#ifdef OPENSSL_NEED_EAP_FAST_PRF
3981e5b75505Sopenharmony_cistatic int openssl_get_keyblock_size(SSL *ssl)
3982e5b75505Sopenharmony_ci{
3983e5b75505Sopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
3984e5b75505Sopenharmony_ci	(defined(LIBRESSL_VERSION_NUMBER) && \
3985e5b75505Sopenharmony_ci	 LIBRESSL_VERSION_NUMBER < 0x20700000L)
3986e5b75505Sopenharmony_ci	const EVP_CIPHER *c;
3987e5b75505Sopenharmony_ci	const EVP_MD *h;
3988e5b75505Sopenharmony_ci	int md_size;
3989e5b75505Sopenharmony_ci
3990e5b75505Sopenharmony_ci	if (ssl->enc_read_ctx == NULL || ssl->enc_read_ctx->cipher == NULL ||
3991e5b75505Sopenharmony_ci	    ssl->read_hash == NULL)
3992e5b75505Sopenharmony_ci		return -1;
3993e5b75505Sopenharmony_ci
3994e5b75505Sopenharmony_ci	c = ssl->enc_read_ctx->cipher;
3995e5b75505Sopenharmony_ci	h = EVP_MD_CTX_md(ssl->read_hash);
3996e5b75505Sopenharmony_ci	if (h)
3997e5b75505Sopenharmony_ci		md_size = EVP_MD_size(h);
3998e5b75505Sopenharmony_ci	else if (ssl->s3)
3999e5b75505Sopenharmony_ci		md_size = ssl->s3->tmp.new_mac_secret_size;
4000e5b75505Sopenharmony_ci	else
4001e5b75505Sopenharmony_ci		return -1;
4002e5b75505Sopenharmony_ci
4003e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "OpenSSL: keyblock size: key_len=%d MD_size=%d "
4004e5b75505Sopenharmony_ci		   "IV_len=%d", EVP_CIPHER_key_length(c), md_size,
4005e5b75505Sopenharmony_ci		   EVP_CIPHER_iv_length(c));
4006e5b75505Sopenharmony_ci	return 2 * (EVP_CIPHER_key_length(c) +
4007e5b75505Sopenharmony_ci		    md_size +
4008e5b75505Sopenharmony_ci		    EVP_CIPHER_iv_length(c));
4009e5b75505Sopenharmony_ci#else
4010e5b75505Sopenharmony_ci	const SSL_CIPHER *ssl_cipher;
4011e5b75505Sopenharmony_ci	int cipher, digest;
4012e5b75505Sopenharmony_ci	const EVP_CIPHER *c;
4013e5b75505Sopenharmony_ci	const EVP_MD *h;
4014e5b75505Sopenharmony_ci
4015e5b75505Sopenharmony_ci	ssl_cipher = SSL_get_current_cipher(ssl);
4016e5b75505Sopenharmony_ci	if (!ssl_cipher)
4017e5b75505Sopenharmony_ci		return -1;
4018e5b75505Sopenharmony_ci	cipher = SSL_CIPHER_get_cipher_nid(ssl_cipher);
4019e5b75505Sopenharmony_ci	digest = SSL_CIPHER_get_digest_nid(ssl_cipher);
4020e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "OpenSSL: cipher nid %d digest nid %d",
4021e5b75505Sopenharmony_ci		   cipher, digest);
4022e5b75505Sopenharmony_ci	if (cipher < 0 || digest < 0)
4023e5b75505Sopenharmony_ci		return -1;
4024e5b75505Sopenharmony_ci	c = EVP_get_cipherbynid(cipher);
4025e5b75505Sopenharmony_ci	h = EVP_get_digestbynid(digest);
4026e5b75505Sopenharmony_ci	if (!c || !h)
4027e5b75505Sopenharmony_ci		return -1;
4028e5b75505Sopenharmony_ci
4029e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG,
4030e5b75505Sopenharmony_ci		   "OpenSSL: keyblock size: key_len=%d MD_size=%d IV_len=%d",
4031e5b75505Sopenharmony_ci		   EVP_CIPHER_key_length(c), EVP_MD_size(h),
4032e5b75505Sopenharmony_ci		   EVP_CIPHER_iv_length(c));
4033e5b75505Sopenharmony_ci	return 2 * (EVP_CIPHER_key_length(c) + EVP_MD_size(h) +
4034e5b75505Sopenharmony_ci		    EVP_CIPHER_iv_length(c));
4035e5b75505Sopenharmony_ci#endif
4036e5b75505Sopenharmony_ci}
4037e5b75505Sopenharmony_ci#endif /* OPENSSL_NEED_EAP_FAST_PRF */
4038e5b75505Sopenharmony_ci
4039e5b75505Sopenharmony_ci
4040e5b75505Sopenharmony_ciint tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
4041e5b75505Sopenharmony_ci			      const char *label, const u8 *context,
4042e5b75505Sopenharmony_ci			      size_t context_len, u8 *out, size_t out_len)
4043e5b75505Sopenharmony_ci{
4044e5b75505Sopenharmony_ci	if (!conn ||
4045e5b75505Sopenharmony_ci	    SSL_export_keying_material(conn->ssl, out, out_len, label,
4046e5b75505Sopenharmony_ci				       os_strlen(label), context, context_len,
4047e5b75505Sopenharmony_ci				       context != NULL) != 1)
4048e5b75505Sopenharmony_ci		return -1;
4049e5b75505Sopenharmony_ci	return 0;
4050e5b75505Sopenharmony_ci}
4051e5b75505Sopenharmony_ci
4052e5b75505Sopenharmony_ci
4053e5b75505Sopenharmony_ciint tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
4054e5b75505Sopenharmony_ci				    u8 *out, size_t out_len)
4055e5b75505Sopenharmony_ci{
4056e5b75505Sopenharmony_ci#ifdef OPENSSL_NEED_EAP_FAST_PRF
4057e5b75505Sopenharmony_ci	SSL *ssl;
4058e5b75505Sopenharmony_ci	SSL_SESSION *sess;
4059e5b75505Sopenharmony_ci	u8 *rnd;
4060e5b75505Sopenharmony_ci	int ret = -1;
4061e5b75505Sopenharmony_ci	int skip = 0;
4062e5b75505Sopenharmony_ci	u8 *tmp_out = NULL;
4063e5b75505Sopenharmony_ci	u8 *_out = out;
4064e5b75505Sopenharmony_ci	unsigned char client_random[SSL3_RANDOM_SIZE];
4065e5b75505Sopenharmony_ci	unsigned char server_random[SSL3_RANDOM_SIZE];
4066e5b75505Sopenharmony_ci	unsigned char master_key[64];
4067e5b75505Sopenharmony_ci	size_t master_key_len;
4068e5b75505Sopenharmony_ci	const char *ver;
4069e5b75505Sopenharmony_ci
4070e5b75505Sopenharmony_ci	/*
4071e5b75505Sopenharmony_ci	 * TLS library did not support EAP-FAST key generation, so get the
4072e5b75505Sopenharmony_ci	 * needed TLS session parameters and use an internal implementation of
4073e5b75505Sopenharmony_ci	 * TLS PRF to derive the key.
4074e5b75505Sopenharmony_ci	 */
4075e5b75505Sopenharmony_ci
4076e5b75505Sopenharmony_ci	if (conn == NULL)
4077e5b75505Sopenharmony_ci		return -1;
4078e5b75505Sopenharmony_ci	ssl = conn->ssl;
4079e5b75505Sopenharmony_ci	if (ssl == NULL)
4080e5b75505Sopenharmony_ci		return -1;
4081e5b75505Sopenharmony_ci	ver = SSL_get_version(ssl);
4082e5b75505Sopenharmony_ci	sess = SSL_get_session(ssl);
4083e5b75505Sopenharmony_ci	if (!ver || !sess)
4084e5b75505Sopenharmony_ci		return -1;
4085e5b75505Sopenharmony_ci
4086e5b75505Sopenharmony_ci	skip = openssl_get_keyblock_size(ssl);
4087e5b75505Sopenharmony_ci	if (skip < 0)
4088e5b75505Sopenharmony_ci		return -1;
4089e5b75505Sopenharmony_ci	tmp_out = os_malloc(skip + out_len);
4090e5b75505Sopenharmony_ci	if (!tmp_out)
4091e5b75505Sopenharmony_ci		return -1;
4092e5b75505Sopenharmony_ci	_out = tmp_out;
4093e5b75505Sopenharmony_ci
4094e5b75505Sopenharmony_ci	rnd = os_malloc(2 * SSL3_RANDOM_SIZE);
4095e5b75505Sopenharmony_ci	if (!rnd) {
4096e5b75505Sopenharmony_ci		os_free(tmp_out);
4097e5b75505Sopenharmony_ci		return -1;
4098e5b75505Sopenharmony_ci	}
4099e5b75505Sopenharmony_ci
4100e5b75505Sopenharmony_ci	SSL_get_client_random(ssl, client_random, sizeof(client_random));
4101e5b75505Sopenharmony_ci	SSL_get_server_random(ssl, server_random, sizeof(server_random));
4102e5b75505Sopenharmony_ci	master_key_len = SSL_SESSION_get_master_key(sess, master_key,
4103e5b75505Sopenharmony_ci						    sizeof(master_key));
4104e5b75505Sopenharmony_ci
4105e5b75505Sopenharmony_ci	os_memcpy(rnd, server_random, SSL3_RANDOM_SIZE);
4106e5b75505Sopenharmony_ci	os_memcpy(rnd + SSL3_RANDOM_SIZE, client_random, SSL3_RANDOM_SIZE);
4107e5b75505Sopenharmony_ci
4108e5b75505Sopenharmony_ci	if (os_strcmp(ver, "TLSv1.2") == 0) {
4109e5b75505Sopenharmony_ci		tls_prf_sha256(master_key, master_key_len,
4110e5b75505Sopenharmony_ci			       "key expansion", rnd, 2 * SSL3_RANDOM_SIZE,
4111e5b75505Sopenharmony_ci			       _out, skip + out_len);
4112e5b75505Sopenharmony_ci		ret = 0;
4113e5b75505Sopenharmony_ci	} else if (tls_prf_sha1_md5(master_key, master_key_len,
4114e5b75505Sopenharmony_ci				    "key expansion", rnd, 2 * SSL3_RANDOM_SIZE,
4115e5b75505Sopenharmony_ci				    _out, skip + out_len) == 0) {
4116e5b75505Sopenharmony_ci		ret = 0;
4117e5b75505Sopenharmony_ci	}
4118e5b75505Sopenharmony_ci	forced_memzero(master_key, sizeof(master_key));
4119e5b75505Sopenharmony_ci	os_free(rnd);
4120e5b75505Sopenharmony_ci	if (ret == 0)
4121e5b75505Sopenharmony_ci		os_memcpy(out, _out + skip, out_len);
4122e5b75505Sopenharmony_ci	bin_clear_free(tmp_out, skip);
4123e5b75505Sopenharmony_ci
4124e5b75505Sopenharmony_ci	return ret;
4125e5b75505Sopenharmony_ci#else /* OPENSSL_NEED_EAP_FAST_PRF */
4126e5b75505Sopenharmony_ci	wpa_printf(MSG_ERROR,
4127e5b75505Sopenharmony_ci		   "OpenSSL: EAP-FAST keys cannot be exported in FIPS mode");
4128e5b75505Sopenharmony_ci	return -1;
4129e5b75505Sopenharmony_ci#endif /* OPENSSL_NEED_EAP_FAST_PRF */
4130e5b75505Sopenharmony_ci}
4131e5b75505Sopenharmony_ci
4132e5b75505Sopenharmony_ci
4133e5b75505Sopenharmony_cistatic struct wpabuf *
4134e5b75505Sopenharmony_ciopenssl_handshake(struct tls_connection *conn, const struct wpabuf *in_data)
4135e5b75505Sopenharmony_ci{
4136e5b75505Sopenharmony_ci	int res;
4137e5b75505Sopenharmony_ci	struct wpabuf *out_data;
4138e5b75505Sopenharmony_ci
4139e5b75505Sopenharmony_ci	/*
4140e5b75505Sopenharmony_ci	 * Give TLS handshake data from the server (if available) to OpenSSL
4141e5b75505Sopenharmony_ci	 * for processing.
4142e5b75505Sopenharmony_ci	 */
4143e5b75505Sopenharmony_ci	if (in_data && wpabuf_len(in_data) > 0 &&
4144e5b75505Sopenharmony_ci	    BIO_write(conn->ssl_in, wpabuf_head(in_data), wpabuf_len(in_data))
4145e5b75505Sopenharmony_ci	    < 0) {
4146e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__,
4147e5b75505Sopenharmony_ci				"Handshake failed - BIO_write");
4148e5b75505Sopenharmony_ci		return NULL;
4149e5b75505Sopenharmony_ci	}
4150e5b75505Sopenharmony_ci
4151e5b75505Sopenharmony_ci	/* Initiate TLS handshake or continue the existing handshake */
4152e5b75505Sopenharmony_ci	if (conn->server)
4153e5b75505Sopenharmony_ci		res = SSL_accept(conn->ssl);
4154e5b75505Sopenharmony_ci	else
4155e5b75505Sopenharmony_ci		res = SSL_connect(conn->ssl);
4156e5b75505Sopenharmony_ci	if (res != 1) {
4157e5b75505Sopenharmony_ci		int err = SSL_get_error(conn->ssl, res);
4158e5b75505Sopenharmony_ci		if (err == SSL_ERROR_WANT_READ)
4159e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want "
4160e5b75505Sopenharmony_ci				   "more data");
4161e5b75505Sopenharmony_ci		else if (err == SSL_ERROR_WANT_WRITE)
4162e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want to "
4163e5b75505Sopenharmony_ci				   "write");
4164e5b75505Sopenharmony_ci		else {
4165e5b75505Sopenharmony_ci			tls_show_errors(MSG_INFO, __func__, "SSL_connect");
4166e5b75505Sopenharmony_ci			conn->failed++;
4167e5b75505Sopenharmony_ci			if (!conn->server && !conn->client_hello_generated) {
4168e5b75505Sopenharmony_ci				/* The server would not understand TLS Alert
4169e5b75505Sopenharmony_ci				 * before ClientHello, so simply terminate
4170e5b75505Sopenharmony_ci				 * handshake on this type of error case caused
4171e5b75505Sopenharmony_ci				 * by a likely internal error like no ciphers
4172e5b75505Sopenharmony_ci				 * available. */
4173e5b75505Sopenharmony_ci				wpa_printf(MSG_DEBUG,
4174e5b75505Sopenharmony_ci					   "OpenSSL: Could not generate ClientHello");
4175e5b75505Sopenharmony_ci				conn->write_alerts++;
4176e5b75505Sopenharmony_ci				return NULL;
4177e5b75505Sopenharmony_ci			}
4178e5b75505Sopenharmony_ci		}
4179e5b75505Sopenharmony_ci	}
4180e5b75505Sopenharmony_ci
4181e5b75505Sopenharmony_ci	if (!conn->server && !conn->failed)
4182e5b75505Sopenharmony_ci		conn->client_hello_generated = 1;
4183e5b75505Sopenharmony_ci
4184e5b75505Sopenharmony_ci#ifdef CONFIG_SUITEB
4185e5b75505Sopenharmony_ci	if ((conn->flags & TLS_CONN_SUITEB) && !conn->server &&
4186e5b75505Sopenharmony_ci	    os_strncmp(SSL_get_cipher(conn->ssl), "DHE-", 4) == 0 &&
4187e5b75505Sopenharmony_ci	    conn->server_dh_prime_len < 3072) {
4188e5b75505Sopenharmony_ci		struct tls_context *context = conn->context;
4189e5b75505Sopenharmony_ci
4190e5b75505Sopenharmony_ci		/*
4191e5b75505Sopenharmony_ci		 * This should not be reached since earlier cert_cb should have
4192e5b75505Sopenharmony_ci		 * terminated the handshake. Keep this check here for extra
4193e5b75505Sopenharmony_ci		 * protection if anything goes wrong with the more low-level
4194e5b75505Sopenharmony_ci		 * checks based on having to parse the TLS handshake messages.
4195e5b75505Sopenharmony_ci		 */
4196e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
4197e5b75505Sopenharmony_ci			   "OpenSSL: Server DH prime length: %d bits",
4198e5b75505Sopenharmony_ci			   conn->server_dh_prime_len);
4199e5b75505Sopenharmony_ci
4200e5b75505Sopenharmony_ci		if (context->event_cb) {
4201e5b75505Sopenharmony_ci			union tls_event_data ev;
4202e5b75505Sopenharmony_ci
4203e5b75505Sopenharmony_ci			os_memset(&ev, 0, sizeof(ev));
4204e5b75505Sopenharmony_ci			ev.alert.is_local = 1;
4205e5b75505Sopenharmony_ci			ev.alert.type = "fatal";
4206e5b75505Sopenharmony_ci			ev.alert.description = "insufficient security";
4207e5b75505Sopenharmony_ci			context->event_cb(context->cb_ctx, TLS_ALERT, &ev);
4208e5b75505Sopenharmony_ci		}
4209e5b75505Sopenharmony_ci		/*
4210e5b75505Sopenharmony_ci		 * Could send a TLS Alert to the server, but for now, simply
4211e5b75505Sopenharmony_ci		 * terminate handshake.
4212e5b75505Sopenharmony_ci		 */
4213e5b75505Sopenharmony_ci		conn->failed++;
4214e5b75505Sopenharmony_ci		conn->write_alerts++;
4215e5b75505Sopenharmony_ci		return NULL;
4216e5b75505Sopenharmony_ci	}
4217e5b75505Sopenharmony_ci#endif /* CONFIG_SUITEB */
4218e5b75505Sopenharmony_ci
4219e5b75505Sopenharmony_ci	/* Get the TLS handshake data to be sent to the server */
4220e5b75505Sopenharmony_ci	res = BIO_ctrl_pending(conn->ssl_out);
4221e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res);
4222e5b75505Sopenharmony_ci	out_data = wpabuf_alloc(res);
4223e5b75505Sopenharmony_ci	if (out_data == NULL) {
4224e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for "
4225e5b75505Sopenharmony_ci			   "handshake output (%d bytes)", res);
4226e5b75505Sopenharmony_ci		if (BIO_reset(conn->ssl_out) < 0) {
4227e5b75505Sopenharmony_ci			tls_show_errors(MSG_INFO, __func__,
4228e5b75505Sopenharmony_ci					"BIO_reset failed");
4229e5b75505Sopenharmony_ci		}
4230e5b75505Sopenharmony_ci		return NULL;
4231e5b75505Sopenharmony_ci	}
4232e5b75505Sopenharmony_ci	res = res == 0 ? 0 : BIO_read(conn->ssl_out, wpabuf_mhead(out_data),
4233e5b75505Sopenharmony_ci				      res);
4234e5b75505Sopenharmony_ci	if (res < 0) {
4235e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__,
4236e5b75505Sopenharmony_ci				"Handshake failed - BIO_read");
4237e5b75505Sopenharmony_ci		if (BIO_reset(conn->ssl_out) < 0) {
4238e5b75505Sopenharmony_ci			tls_show_errors(MSG_INFO, __func__,
4239e5b75505Sopenharmony_ci					"BIO_reset failed");
4240e5b75505Sopenharmony_ci		}
4241e5b75505Sopenharmony_ci		wpabuf_free(out_data);
4242e5b75505Sopenharmony_ci		return NULL;
4243e5b75505Sopenharmony_ci	}
4244e5b75505Sopenharmony_ci	wpabuf_put(out_data, res);
4245e5b75505Sopenharmony_ci
4246e5b75505Sopenharmony_ci	return out_data;
4247e5b75505Sopenharmony_ci}
4248e5b75505Sopenharmony_ci
4249e5b75505Sopenharmony_ci
4250e5b75505Sopenharmony_cistatic struct wpabuf *
4251e5b75505Sopenharmony_ciopenssl_get_appl_data(struct tls_connection *conn, size_t max_len)
4252e5b75505Sopenharmony_ci{
4253e5b75505Sopenharmony_ci	struct wpabuf *appl_data;
4254e5b75505Sopenharmony_ci	int res;
4255e5b75505Sopenharmony_ci
4256e5b75505Sopenharmony_ci	appl_data = wpabuf_alloc(max_len + 100);
4257e5b75505Sopenharmony_ci	if (appl_data == NULL)
4258e5b75505Sopenharmony_ci		return NULL;
4259e5b75505Sopenharmony_ci
4260e5b75505Sopenharmony_ci	res = SSL_read(conn->ssl, wpabuf_mhead(appl_data),
4261e5b75505Sopenharmony_ci		       wpabuf_size(appl_data));
4262e5b75505Sopenharmony_ci	if (res < 0) {
4263e5b75505Sopenharmony_ci		int err = SSL_get_error(conn->ssl, res);
4264e5b75505Sopenharmony_ci		if (err == SSL_ERROR_WANT_READ ||
4265e5b75505Sopenharmony_ci		    err == SSL_ERROR_WANT_WRITE) {
4266e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "SSL: No Application Data "
4267e5b75505Sopenharmony_ci				   "included");
4268e5b75505Sopenharmony_ci		} else {
4269e5b75505Sopenharmony_ci			tls_show_errors(MSG_INFO, __func__,
4270e5b75505Sopenharmony_ci					"Failed to read possible "
4271e5b75505Sopenharmony_ci					"Application Data");
4272e5b75505Sopenharmony_ci		}
4273e5b75505Sopenharmony_ci		wpabuf_free(appl_data);
4274e5b75505Sopenharmony_ci		return NULL;
4275e5b75505Sopenharmony_ci	}
4276e5b75505Sopenharmony_ci
4277e5b75505Sopenharmony_ci	wpabuf_put(appl_data, res);
4278e5b75505Sopenharmony_ci	wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application Data in Finished "
4279e5b75505Sopenharmony_ci			    "message", appl_data);
4280e5b75505Sopenharmony_ci
4281e5b75505Sopenharmony_ci	return appl_data;
4282e5b75505Sopenharmony_ci}
4283e5b75505Sopenharmony_ci
4284e5b75505Sopenharmony_ci
4285e5b75505Sopenharmony_cistatic struct wpabuf *
4286e5b75505Sopenharmony_ciopenssl_connection_handshake(struct tls_connection *conn,
4287e5b75505Sopenharmony_ci			     const struct wpabuf *in_data,
4288e5b75505Sopenharmony_ci			     struct wpabuf **appl_data)
4289e5b75505Sopenharmony_ci{
4290e5b75505Sopenharmony_ci	struct wpabuf *out_data;
4291e5b75505Sopenharmony_ci
4292e5b75505Sopenharmony_ci	if (appl_data)
4293e5b75505Sopenharmony_ci		*appl_data = NULL;
4294e5b75505Sopenharmony_ci
4295e5b75505Sopenharmony_ci	out_data = openssl_handshake(conn, in_data);
4296e5b75505Sopenharmony_ci	if (out_data == NULL)
4297e5b75505Sopenharmony_ci		return NULL;
4298e5b75505Sopenharmony_ci	if (conn->invalid_hb_used) {
4299e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response");
4300e5b75505Sopenharmony_ci		wpabuf_free(out_data);
4301e5b75505Sopenharmony_ci		return NULL;
4302e5b75505Sopenharmony_ci	}
4303e5b75505Sopenharmony_ci
4304e5b75505Sopenharmony_ci	if (SSL_is_init_finished(conn->ssl)) {
4305e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
4306e5b75505Sopenharmony_ci			   "OpenSSL: Handshake finished - resumed=%d",
4307e5b75505Sopenharmony_ci			   tls_connection_resumed(conn->ssl_ctx, conn));
4308e5b75505Sopenharmony_ci		if (conn->server) {
4309e5b75505Sopenharmony_ci			char *buf;
4310e5b75505Sopenharmony_ci			size_t buflen = 2000;
4311e5b75505Sopenharmony_ci
4312e5b75505Sopenharmony_ci			buf = os_malloc(buflen);
4313e5b75505Sopenharmony_ci			if (buf) {
4314e5b75505Sopenharmony_ci				if (SSL_get_shared_ciphers(conn->ssl, buf,
4315e5b75505Sopenharmony_ci							   buflen)) {
4316e5b75505Sopenharmony_ci					buf[buflen - 1] = '\0';
4317e5b75505Sopenharmony_ci					wpa_printf(MSG_DEBUG,
4318e5b75505Sopenharmony_ci						   "OpenSSL: Shared ciphers: %s",
4319e5b75505Sopenharmony_ci						   buf);
4320e5b75505Sopenharmony_ci				}
4321e5b75505Sopenharmony_ci				os_free(buf);
4322e5b75505Sopenharmony_ci			}
4323e5b75505Sopenharmony_ci		}
4324e5b75505Sopenharmony_ci		if (appl_data && in_data)
4325e5b75505Sopenharmony_ci			*appl_data = openssl_get_appl_data(conn,
4326e5b75505Sopenharmony_ci							   wpabuf_len(in_data));
4327e5b75505Sopenharmony_ci	}
4328e5b75505Sopenharmony_ci
4329e5b75505Sopenharmony_ci	if (conn->invalid_hb_used) {
4330e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response");
4331e5b75505Sopenharmony_ci		if (appl_data) {
4332e5b75505Sopenharmony_ci			wpabuf_free(*appl_data);
4333e5b75505Sopenharmony_ci			*appl_data = NULL;
4334e5b75505Sopenharmony_ci		}
4335e5b75505Sopenharmony_ci		wpabuf_free(out_data);
4336e5b75505Sopenharmony_ci		return NULL;
4337e5b75505Sopenharmony_ci	}
4338e5b75505Sopenharmony_ci
4339e5b75505Sopenharmony_ci	return out_data;
4340e5b75505Sopenharmony_ci}
4341e5b75505Sopenharmony_ci
4342e5b75505Sopenharmony_ci
4343e5b75505Sopenharmony_cistruct wpabuf *
4344e5b75505Sopenharmony_citls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
4345e5b75505Sopenharmony_ci			 const struct wpabuf *in_data,
4346e5b75505Sopenharmony_ci			 struct wpabuf **appl_data)
4347e5b75505Sopenharmony_ci{
4348e5b75505Sopenharmony_ci	return openssl_connection_handshake(conn, in_data, appl_data);
4349e5b75505Sopenharmony_ci}
4350e5b75505Sopenharmony_ci
4351e5b75505Sopenharmony_ci
4352e5b75505Sopenharmony_cistruct wpabuf * tls_connection_server_handshake(void *tls_ctx,
4353e5b75505Sopenharmony_ci						struct tls_connection *conn,
4354e5b75505Sopenharmony_ci						const struct wpabuf *in_data,
4355e5b75505Sopenharmony_ci						struct wpabuf **appl_data)
4356e5b75505Sopenharmony_ci{
4357e5b75505Sopenharmony_ci	conn->server = 1;
4358e5b75505Sopenharmony_ci	return openssl_connection_handshake(conn, in_data, appl_data);
4359e5b75505Sopenharmony_ci}
4360e5b75505Sopenharmony_ci
4361e5b75505Sopenharmony_ci
4362e5b75505Sopenharmony_cistruct wpabuf * tls_connection_encrypt(void *tls_ctx,
4363e5b75505Sopenharmony_ci				       struct tls_connection *conn,
4364e5b75505Sopenharmony_ci				       const struct wpabuf *in_data)
4365e5b75505Sopenharmony_ci{
4366e5b75505Sopenharmony_ci	int res;
4367e5b75505Sopenharmony_ci	struct wpabuf *buf;
4368e5b75505Sopenharmony_ci
4369e5b75505Sopenharmony_ci	if (conn == NULL)
4370e5b75505Sopenharmony_ci		return NULL;
4371e5b75505Sopenharmony_ci
4372e5b75505Sopenharmony_ci	/* Give plaintext data for OpenSSL to encrypt into the TLS tunnel. */
4373e5b75505Sopenharmony_ci	if ((res = BIO_reset(conn->ssl_in)) < 0 ||
4374e5b75505Sopenharmony_ci	    (res = BIO_reset(conn->ssl_out)) < 0) {
4375e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
4376e5b75505Sopenharmony_ci		return NULL;
4377e5b75505Sopenharmony_ci	}
4378e5b75505Sopenharmony_ci	res = SSL_write(conn->ssl, wpabuf_head(in_data), wpabuf_len(in_data));
4379e5b75505Sopenharmony_ci	if (res < 0) {
4380e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__,
4381e5b75505Sopenharmony_ci				"Encryption failed - SSL_write");
4382e5b75505Sopenharmony_ci		return NULL;
4383e5b75505Sopenharmony_ci	}
4384e5b75505Sopenharmony_ci
4385e5b75505Sopenharmony_ci	/* Read encrypted data to be sent to the server */
4386e5b75505Sopenharmony_ci	buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
4387e5b75505Sopenharmony_ci	if (buf == NULL)
4388e5b75505Sopenharmony_ci		return NULL;
4389e5b75505Sopenharmony_ci	res = BIO_read(conn->ssl_out, wpabuf_mhead(buf), wpabuf_size(buf));
4390e5b75505Sopenharmony_ci	if (res < 0) {
4391e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__,
4392e5b75505Sopenharmony_ci				"Encryption failed - BIO_read");
4393e5b75505Sopenharmony_ci		wpabuf_free(buf);
4394e5b75505Sopenharmony_ci		return NULL;
4395e5b75505Sopenharmony_ci	}
4396e5b75505Sopenharmony_ci	wpabuf_put(buf, res);
4397e5b75505Sopenharmony_ci
4398e5b75505Sopenharmony_ci	return buf;
4399e5b75505Sopenharmony_ci}
4400e5b75505Sopenharmony_ci
4401e5b75505Sopenharmony_ci
4402e5b75505Sopenharmony_cistruct wpabuf * tls_connection_decrypt(void *tls_ctx,
4403e5b75505Sopenharmony_ci				       struct tls_connection *conn,
4404e5b75505Sopenharmony_ci				       const struct wpabuf *in_data)
4405e5b75505Sopenharmony_ci{
4406e5b75505Sopenharmony_ci	int res;
4407e5b75505Sopenharmony_ci	struct wpabuf *buf;
4408e5b75505Sopenharmony_ci
4409e5b75505Sopenharmony_ci	/* Give encrypted data from TLS tunnel for OpenSSL to decrypt. */
4410e5b75505Sopenharmony_ci	res = BIO_write(conn->ssl_in, wpabuf_head(in_data),
4411e5b75505Sopenharmony_ci			wpabuf_len(in_data));
4412e5b75505Sopenharmony_ci	if (res < 0) {
4413e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__,
4414e5b75505Sopenharmony_ci				"Decryption failed - BIO_write");
4415e5b75505Sopenharmony_ci		return NULL;
4416e5b75505Sopenharmony_ci	}
4417e5b75505Sopenharmony_ci	if (BIO_reset(conn->ssl_out) < 0) {
4418e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
4419e5b75505Sopenharmony_ci		return NULL;
4420e5b75505Sopenharmony_ci	}
4421e5b75505Sopenharmony_ci
4422e5b75505Sopenharmony_ci	/* Read decrypted data for further processing */
4423e5b75505Sopenharmony_ci	/*
4424e5b75505Sopenharmony_ci	 * Even though we try to disable TLS compression, it is possible that
4425e5b75505Sopenharmony_ci	 * this cannot be done with all TLS libraries. Add extra buffer space
4426e5b75505Sopenharmony_ci	 * to handle the possibility of the decrypted data being longer than
4427e5b75505Sopenharmony_ci	 * input data.
4428e5b75505Sopenharmony_ci	 */
4429e5b75505Sopenharmony_ci	buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
4430e5b75505Sopenharmony_ci	if (buf == NULL)
4431e5b75505Sopenharmony_ci		return NULL;
4432e5b75505Sopenharmony_ci	res = SSL_read(conn->ssl, wpabuf_mhead(buf), wpabuf_size(buf));
4433e5b75505Sopenharmony_ci	if (res < 0) {
4434e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__,
4435e5b75505Sopenharmony_ci				"Decryption failed - SSL_read");
4436e5b75505Sopenharmony_ci		wpabuf_free(buf);
4437e5b75505Sopenharmony_ci		return NULL;
4438e5b75505Sopenharmony_ci	}
4439e5b75505Sopenharmony_ci	wpabuf_put(buf, res);
4440e5b75505Sopenharmony_ci
4441e5b75505Sopenharmony_ci	if (conn->invalid_hb_used) {
4442e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response");
4443e5b75505Sopenharmony_ci		wpabuf_free(buf);
4444e5b75505Sopenharmony_ci		return NULL;
4445e5b75505Sopenharmony_ci	}
4446e5b75505Sopenharmony_ci
4447e5b75505Sopenharmony_ci	return buf;
4448e5b75505Sopenharmony_ci}
4449e5b75505Sopenharmony_ci
4450e5b75505Sopenharmony_ci
4451e5b75505Sopenharmony_ciint tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
4452e5b75505Sopenharmony_ci{
4453e5b75505Sopenharmony_ci	return conn ? SSL_session_reused(conn->ssl) : 0;
4454e5b75505Sopenharmony_ci}
4455e5b75505Sopenharmony_ci
4456e5b75505Sopenharmony_ci
4457e5b75505Sopenharmony_ciint tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
4458e5b75505Sopenharmony_ci				   u8 *ciphers)
4459e5b75505Sopenharmony_ci{
4460e5b75505Sopenharmony_ci	char buf[500], *pos, *end;
4461e5b75505Sopenharmony_ci	u8 *c;
4462e5b75505Sopenharmony_ci	int ret;
4463e5b75505Sopenharmony_ci
4464e5b75505Sopenharmony_ci	if (conn == NULL || conn->ssl == NULL || ciphers == NULL)
4465e5b75505Sopenharmony_ci		return -1;
4466e5b75505Sopenharmony_ci
4467e5b75505Sopenharmony_ci	buf[0] = '\0';
4468e5b75505Sopenharmony_ci	pos = buf;
4469e5b75505Sopenharmony_ci	end = pos + sizeof(buf);
4470e5b75505Sopenharmony_ci
4471e5b75505Sopenharmony_ci	c = ciphers;
4472e5b75505Sopenharmony_ci	while (*c != TLS_CIPHER_NONE) {
4473e5b75505Sopenharmony_ci		const char *suite;
4474e5b75505Sopenharmony_ci
4475e5b75505Sopenharmony_ci		switch (*c) {
4476e5b75505Sopenharmony_ci		case TLS_CIPHER_RC4_SHA:
4477e5b75505Sopenharmony_ci			suite = "RC4-SHA";
4478e5b75505Sopenharmony_ci			break;
4479e5b75505Sopenharmony_ci		case TLS_CIPHER_AES128_SHA:
4480e5b75505Sopenharmony_ci			suite = "AES128-SHA";
4481e5b75505Sopenharmony_ci			break;
4482e5b75505Sopenharmony_ci		case TLS_CIPHER_RSA_DHE_AES128_SHA:
4483e5b75505Sopenharmony_ci			suite = "DHE-RSA-AES128-SHA";
4484e5b75505Sopenharmony_ci			break;
4485e5b75505Sopenharmony_ci		case TLS_CIPHER_ANON_DH_AES128_SHA:
4486e5b75505Sopenharmony_ci			suite = "ADH-AES128-SHA";
4487e5b75505Sopenharmony_ci			break;
4488e5b75505Sopenharmony_ci		case TLS_CIPHER_RSA_DHE_AES256_SHA:
4489e5b75505Sopenharmony_ci			suite = "DHE-RSA-AES256-SHA";
4490e5b75505Sopenharmony_ci			break;
4491e5b75505Sopenharmony_ci		case TLS_CIPHER_AES256_SHA:
4492e5b75505Sopenharmony_ci			suite = "AES256-SHA";
4493e5b75505Sopenharmony_ci			break;
4494e5b75505Sopenharmony_ci		default:
4495e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "TLS: Unsupported "
4496e5b75505Sopenharmony_ci				   "cipher selection: %d", *c);
4497e5b75505Sopenharmony_ci			return -1;
4498e5b75505Sopenharmony_ci		}
4499e5b75505Sopenharmony_ci		ret = os_snprintf(pos, end - pos, ":%s", suite);
4500e5b75505Sopenharmony_ci		if (os_snprintf_error(end - pos, ret))
4501e5b75505Sopenharmony_ci			break;
4502e5b75505Sopenharmony_ci		pos += ret;
4503e5b75505Sopenharmony_ci
4504e5b75505Sopenharmony_ci		c++;
4505e5b75505Sopenharmony_ci	}
4506e5b75505Sopenharmony_ci	if (!buf[0]) {
4507e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: No ciphers listed");
4508e5b75505Sopenharmony_ci		return -1;
4509e5b75505Sopenharmony_ci	}
4510e5b75505Sopenharmony_ci
4511e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "OpenSSL: cipher suites: %s", buf + 1);
4512e5b75505Sopenharmony_ci
4513e5b75505Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
4514e5b75505Sopenharmony_ci#ifdef EAP_FAST_OR_TEAP
4515e5b75505Sopenharmony_ci	if (os_strstr(buf, ":ADH-")) {
4516e5b75505Sopenharmony_ci		/*
4517e5b75505Sopenharmony_ci		 * Need to drop to security level 0 to allow anonymous
4518e5b75505Sopenharmony_ci		 * cipher suites for EAP-FAST.
4519e5b75505Sopenharmony_ci		 */
4520e5b75505Sopenharmony_ci		SSL_set_security_level(conn->ssl, 0);
4521e5b75505Sopenharmony_ci	} else if (SSL_get_security_level(conn->ssl) == 0) {
4522e5b75505Sopenharmony_ci		/* Force at least security level 1 */
4523e5b75505Sopenharmony_ci		SSL_set_security_level(conn->ssl, 1);
4524e5b75505Sopenharmony_ci	}
4525e5b75505Sopenharmony_ci#endif /* EAP_FAST_OR_TEAP */
4526e5b75505Sopenharmony_ci#endif
4527e5b75505Sopenharmony_ci
4528e5b75505Sopenharmony_ci	if (SSL_set_cipher_list(conn->ssl, buf + 1) != 1) {
4529e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__,
4530e5b75505Sopenharmony_ci				"Cipher suite configuration failed");
4531e5b75505Sopenharmony_ci		return -1;
4532e5b75505Sopenharmony_ci	}
4533e5b75505Sopenharmony_ci
4534e5b75505Sopenharmony_ci	return 0;
4535e5b75505Sopenharmony_ci}
4536e5b75505Sopenharmony_ci
4537e5b75505Sopenharmony_ci
4538e5b75505Sopenharmony_ciint tls_get_version(void *ssl_ctx, struct tls_connection *conn,
4539e5b75505Sopenharmony_ci		    char *buf, size_t buflen)
4540e5b75505Sopenharmony_ci{
4541e5b75505Sopenharmony_ci	const char *name;
4542e5b75505Sopenharmony_ci	if (conn == NULL || conn->ssl == NULL)
4543e5b75505Sopenharmony_ci		return -1;
4544e5b75505Sopenharmony_ci
4545e5b75505Sopenharmony_ci	name = SSL_get_version(conn->ssl);
4546e5b75505Sopenharmony_ci	if (name == NULL)
4547e5b75505Sopenharmony_ci		return -1;
4548e5b75505Sopenharmony_ci
4549e5b75505Sopenharmony_ci	os_strlcpy(buf, name, buflen);
4550e5b75505Sopenharmony_ci	return 0;
4551e5b75505Sopenharmony_ci}
4552e5b75505Sopenharmony_ci
4553e5b75505Sopenharmony_ci
4554e5b75505Sopenharmony_ciint tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
4555e5b75505Sopenharmony_ci		   char *buf, size_t buflen)
4556e5b75505Sopenharmony_ci{
4557e5b75505Sopenharmony_ci	const char *name;
4558e5b75505Sopenharmony_ci	if (conn == NULL || conn->ssl == NULL)
4559e5b75505Sopenharmony_ci		return -1;
4560e5b75505Sopenharmony_ci
4561e5b75505Sopenharmony_ci	name = SSL_get_cipher(conn->ssl);
4562e5b75505Sopenharmony_ci	if (name == NULL)
4563e5b75505Sopenharmony_ci		return -1;
4564e5b75505Sopenharmony_ci
4565e5b75505Sopenharmony_ci	os_strlcpy(buf, name, buflen);
4566e5b75505Sopenharmony_ci	return 0;
4567e5b75505Sopenharmony_ci}
4568e5b75505Sopenharmony_ci
4569e5b75505Sopenharmony_ci
4570e5b75505Sopenharmony_ciint tls_connection_enable_workaround(void *ssl_ctx,
4571e5b75505Sopenharmony_ci				     struct tls_connection *conn)
4572e5b75505Sopenharmony_ci{
4573e5b75505Sopenharmony_ci	SSL_set_options(conn->ssl, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
4574e5b75505Sopenharmony_ci
4575e5b75505Sopenharmony_ci	return 0;
4576e5b75505Sopenharmony_ci}
4577e5b75505Sopenharmony_ci
4578e5b75505Sopenharmony_ci
4579e5b75505Sopenharmony_ci#ifdef EAP_FAST_OR_TEAP
4580e5b75505Sopenharmony_ci/* ClientHello TLS extensions require a patch to openssl, so this function is
4581e5b75505Sopenharmony_ci * commented out unless explicitly needed for EAP-FAST in order to be able to
4582e5b75505Sopenharmony_ci * build this file with unmodified openssl. */
4583e5b75505Sopenharmony_ciint tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
4584e5b75505Sopenharmony_ci				    int ext_type, const u8 *data,
4585e5b75505Sopenharmony_ci				    size_t data_len)
4586e5b75505Sopenharmony_ci{
4587e5b75505Sopenharmony_ci	if (conn == NULL || conn->ssl == NULL || ext_type != 35)
4588e5b75505Sopenharmony_ci		return -1;
4589e5b75505Sopenharmony_ci
4590e5b75505Sopenharmony_ci	if (SSL_set_session_ticket_ext(conn->ssl, (void *) data,
4591e5b75505Sopenharmony_ci				       data_len) != 1)
4592e5b75505Sopenharmony_ci		return -1;
4593e5b75505Sopenharmony_ci
4594e5b75505Sopenharmony_ci	return 0;
4595e5b75505Sopenharmony_ci}
4596e5b75505Sopenharmony_ci#endif /* EAP_FAST_OR_TEAP */
4597e5b75505Sopenharmony_ci
4598e5b75505Sopenharmony_ci
4599e5b75505Sopenharmony_ciint tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
4600e5b75505Sopenharmony_ci{
4601e5b75505Sopenharmony_ci	if (conn == NULL)
4602e5b75505Sopenharmony_ci		return -1;
4603e5b75505Sopenharmony_ci	return conn->failed;
4604e5b75505Sopenharmony_ci}
4605e5b75505Sopenharmony_ci
4606e5b75505Sopenharmony_ci
4607e5b75505Sopenharmony_ciint tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
4608e5b75505Sopenharmony_ci{
4609e5b75505Sopenharmony_ci	if (conn == NULL)
4610e5b75505Sopenharmony_ci		return -1;
4611e5b75505Sopenharmony_ci	return conn->read_alerts;
4612e5b75505Sopenharmony_ci}
4613e5b75505Sopenharmony_ci
4614e5b75505Sopenharmony_ci
4615e5b75505Sopenharmony_ciint tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
4616e5b75505Sopenharmony_ci{
4617e5b75505Sopenharmony_ci	if (conn == NULL)
4618e5b75505Sopenharmony_ci		return -1;
4619e5b75505Sopenharmony_ci	return conn->write_alerts;
4620e5b75505Sopenharmony_ci}
4621e5b75505Sopenharmony_ci
4622e5b75505Sopenharmony_ci
4623e5b75505Sopenharmony_ci#ifdef HAVE_OCSP
4624e5b75505Sopenharmony_ci
4625e5b75505Sopenharmony_cistatic void ocsp_debug_print_resp(OCSP_RESPONSE *rsp)
4626e5b75505Sopenharmony_ci{
4627e5b75505Sopenharmony_ci#ifndef CONFIG_NO_STDOUT_DEBUG
4628e5b75505Sopenharmony_ci	BIO *out;
4629e5b75505Sopenharmony_ci	size_t rlen;
4630e5b75505Sopenharmony_ci	char *txt;
4631e5b75505Sopenharmony_ci	int res;
4632e5b75505Sopenharmony_ci
4633e5b75505Sopenharmony_ci	if (wpa_debug_level > MSG_DEBUG)
4634e5b75505Sopenharmony_ci		return;
4635e5b75505Sopenharmony_ci
4636e5b75505Sopenharmony_ci	out = BIO_new(BIO_s_mem());
4637e5b75505Sopenharmony_ci	if (!out)
4638e5b75505Sopenharmony_ci		return;
4639e5b75505Sopenharmony_ci
4640e5b75505Sopenharmony_ci	OCSP_RESPONSE_print(out, rsp, 0);
4641e5b75505Sopenharmony_ci	rlen = BIO_ctrl_pending(out);
4642e5b75505Sopenharmony_ci	txt = os_malloc(rlen + 1);
4643e5b75505Sopenharmony_ci	if (!txt) {
4644e5b75505Sopenharmony_ci		BIO_free(out);
4645e5b75505Sopenharmony_ci		return;
4646e5b75505Sopenharmony_ci	}
4647e5b75505Sopenharmony_ci
4648e5b75505Sopenharmony_ci	res = BIO_read(out, txt, rlen);
4649e5b75505Sopenharmony_ci	if (res > 0) {
4650e5b75505Sopenharmony_ci		txt[res] = '\0';
4651e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP Response\n%s", txt);
4652e5b75505Sopenharmony_ci	}
4653e5b75505Sopenharmony_ci	os_free(txt);
4654e5b75505Sopenharmony_ci	BIO_free(out);
4655e5b75505Sopenharmony_ci#endif /* CONFIG_NO_STDOUT_DEBUG */
4656e5b75505Sopenharmony_ci}
4657e5b75505Sopenharmony_ci
4658e5b75505Sopenharmony_ci
4659e5b75505Sopenharmony_cistatic void debug_print_cert(X509 *cert, const char *title)
4660e5b75505Sopenharmony_ci{
4661e5b75505Sopenharmony_ci#ifndef CONFIG_NO_STDOUT_DEBUG
4662e5b75505Sopenharmony_ci	BIO *out;
4663e5b75505Sopenharmony_ci	size_t rlen;
4664e5b75505Sopenharmony_ci	char *txt;
4665e5b75505Sopenharmony_ci	int res;
4666e5b75505Sopenharmony_ci
4667e5b75505Sopenharmony_ci	if (wpa_debug_level > MSG_DEBUG)
4668e5b75505Sopenharmony_ci		return;
4669e5b75505Sopenharmony_ci
4670e5b75505Sopenharmony_ci	out = BIO_new(BIO_s_mem());
4671e5b75505Sopenharmony_ci	if (!out)
4672e5b75505Sopenharmony_ci		return;
4673e5b75505Sopenharmony_ci
4674e5b75505Sopenharmony_ci	X509_print(out, cert);
4675e5b75505Sopenharmony_ci	rlen = BIO_ctrl_pending(out);
4676e5b75505Sopenharmony_ci	txt = os_malloc(rlen + 1);
4677e5b75505Sopenharmony_ci	if (!txt) {
4678e5b75505Sopenharmony_ci		BIO_free(out);
4679e5b75505Sopenharmony_ci		return;
4680e5b75505Sopenharmony_ci	}
4681e5b75505Sopenharmony_ci
4682e5b75505Sopenharmony_ci	res = BIO_read(out, txt, rlen);
4683e5b75505Sopenharmony_ci	if (res > 0) {
4684e5b75505Sopenharmony_ci		txt[res] = '\0';
4685e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: %s\n%s", title, txt);
4686e5b75505Sopenharmony_ci	}
4687e5b75505Sopenharmony_ci	os_free(txt);
4688e5b75505Sopenharmony_ci
4689e5b75505Sopenharmony_ci	BIO_free(out);
4690e5b75505Sopenharmony_ci#endif /* CONFIG_NO_STDOUT_DEBUG */
4691e5b75505Sopenharmony_ci}
4692e5b75505Sopenharmony_ci
4693e5b75505Sopenharmony_ci
4694e5b75505Sopenharmony_cistatic int ocsp_resp_cb(SSL *s, void *arg)
4695e5b75505Sopenharmony_ci{
4696e5b75505Sopenharmony_ci	struct tls_connection *conn = arg;
4697e5b75505Sopenharmony_ci	const unsigned char *p;
4698e5b75505Sopenharmony_ci	int len, status, reason, res;
4699e5b75505Sopenharmony_ci	OCSP_RESPONSE *rsp;
4700e5b75505Sopenharmony_ci	OCSP_BASICRESP *basic;
4701e5b75505Sopenharmony_ci	OCSP_CERTID *id;
4702e5b75505Sopenharmony_ci	ASN1_GENERALIZEDTIME *produced_at, *this_update, *next_update;
4703e5b75505Sopenharmony_ci	X509_STORE *store;
4704e5b75505Sopenharmony_ci	STACK_OF(X509) *certs = NULL;
4705e5b75505Sopenharmony_ci
4706e5b75505Sopenharmony_ci	len = SSL_get_tlsext_status_ocsp_resp(s, &p);
4707e5b75505Sopenharmony_ci	if (!p) {
4708e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: No OCSP response received");
4709e5b75505Sopenharmony_ci		return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1;
4710e5b75505Sopenharmony_ci	}
4711e5b75505Sopenharmony_ci
4712e5b75505Sopenharmony_ci	wpa_hexdump(MSG_DEBUG, "OpenSSL: OCSP response", p, len);
4713e5b75505Sopenharmony_ci
4714e5b75505Sopenharmony_ci	rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
4715e5b75505Sopenharmony_ci	if (!rsp) {
4716e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "OpenSSL: Failed to parse OCSP response");
4717e5b75505Sopenharmony_ci		return 0;
4718e5b75505Sopenharmony_ci	}
4719e5b75505Sopenharmony_ci
4720e5b75505Sopenharmony_ci	ocsp_debug_print_resp(rsp);
4721e5b75505Sopenharmony_ci
4722e5b75505Sopenharmony_ci	status = OCSP_response_status(rsp);
4723e5b75505Sopenharmony_ci	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
4724e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "OpenSSL: OCSP responder error %d (%s)",
4725e5b75505Sopenharmony_ci			   status, OCSP_response_status_str(status));
4726e5b75505Sopenharmony_ci		return 0;
4727e5b75505Sopenharmony_ci	}
4728e5b75505Sopenharmony_ci
4729e5b75505Sopenharmony_ci	basic = OCSP_response_get1_basic(rsp);
4730e5b75505Sopenharmony_ci	if (!basic) {
4731e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "OpenSSL: Could not find BasicOCSPResponse");
4732e5b75505Sopenharmony_ci		return 0;
4733e5b75505Sopenharmony_ci	}
4734e5b75505Sopenharmony_ci
4735e5b75505Sopenharmony_ci	store = SSL_CTX_get_cert_store(conn->ssl_ctx);
4736e5b75505Sopenharmony_ci	if (conn->peer_issuer) {
4737e5b75505Sopenharmony_ci		debug_print_cert(conn->peer_issuer, "Add OCSP issuer");
4738e5b75505Sopenharmony_ci
4739e5b75505Sopenharmony_ci		if (X509_STORE_add_cert(store, conn->peer_issuer) != 1) {
4740e5b75505Sopenharmony_ci			tls_show_errors(MSG_INFO, __func__,
4741e5b75505Sopenharmony_ci					"OpenSSL: Could not add issuer to certificate store");
4742e5b75505Sopenharmony_ci		}
4743e5b75505Sopenharmony_ci		certs = sk_X509_new_null();
4744e5b75505Sopenharmony_ci		if (certs) {
4745e5b75505Sopenharmony_ci			X509 *cert;
4746e5b75505Sopenharmony_ci			cert = X509_dup(conn->peer_issuer);
4747e5b75505Sopenharmony_ci			if (cert && !sk_X509_push(certs, cert)) {
4748e5b75505Sopenharmony_ci				tls_show_errors(
4749e5b75505Sopenharmony_ci					MSG_INFO, __func__,
4750e5b75505Sopenharmony_ci					"OpenSSL: Could not add issuer to OCSP responder trust store");
4751e5b75505Sopenharmony_ci				X509_free(cert);
4752e5b75505Sopenharmony_ci				sk_X509_free(certs);
4753e5b75505Sopenharmony_ci				certs = NULL;
4754e5b75505Sopenharmony_ci			}
4755e5b75505Sopenharmony_ci			if (certs && conn->peer_issuer_issuer) {
4756e5b75505Sopenharmony_ci				cert = X509_dup(conn->peer_issuer_issuer);
4757e5b75505Sopenharmony_ci				if (cert && !sk_X509_push(certs, cert)) {
4758e5b75505Sopenharmony_ci					tls_show_errors(
4759e5b75505Sopenharmony_ci						MSG_INFO, __func__,
4760e5b75505Sopenharmony_ci						"OpenSSL: Could not add issuer's issuer to OCSP responder trust store");
4761e5b75505Sopenharmony_ci					X509_free(cert);
4762e5b75505Sopenharmony_ci				}
4763e5b75505Sopenharmony_ci			}
4764e5b75505Sopenharmony_ci		}
4765e5b75505Sopenharmony_ci	}
4766e5b75505Sopenharmony_ci
4767e5b75505Sopenharmony_ci	status = OCSP_basic_verify(basic, certs, store, OCSP_TRUSTOTHER);
4768e5b75505Sopenharmony_ci	sk_X509_pop_free(certs, X509_free);
4769e5b75505Sopenharmony_ci	if (status <= 0) {
4770e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__,
4771e5b75505Sopenharmony_ci				"OpenSSL: OCSP response failed verification");
4772e5b75505Sopenharmony_ci		OCSP_BASICRESP_free(basic);
4773e5b75505Sopenharmony_ci		OCSP_RESPONSE_free(rsp);
4774e5b75505Sopenharmony_ci		return 0;
4775e5b75505Sopenharmony_ci	}
4776e5b75505Sopenharmony_ci
4777e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP response verification succeeded");
4778e5b75505Sopenharmony_ci
4779e5b75505Sopenharmony_ci	if (!conn->peer_cert) {
4780e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: Peer certificate not available for OCSP status check");
4781e5b75505Sopenharmony_ci		OCSP_BASICRESP_free(basic);
4782e5b75505Sopenharmony_ci		OCSP_RESPONSE_free(rsp);
4783e5b75505Sopenharmony_ci		return 0;
4784e5b75505Sopenharmony_ci	}
4785e5b75505Sopenharmony_ci
4786e5b75505Sopenharmony_ci	if (!conn->peer_issuer) {
4787e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: Peer issuer certificate not available for OCSP status check");
4788e5b75505Sopenharmony_ci		OCSP_BASICRESP_free(basic);
4789e5b75505Sopenharmony_ci		OCSP_RESPONSE_free(rsp);
4790e5b75505Sopenharmony_ci		return 0;
4791e5b75505Sopenharmony_ci	}
4792e5b75505Sopenharmony_ci
4793e5b75505Sopenharmony_ci	id = OCSP_cert_to_id(EVP_sha256(), conn->peer_cert, conn->peer_issuer);
4794e5b75505Sopenharmony_ci	if (!id) {
4795e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
4796e5b75505Sopenharmony_ci			   "OpenSSL: Could not create OCSP certificate identifier (SHA256)");
4797e5b75505Sopenharmony_ci		OCSP_BASICRESP_free(basic);
4798e5b75505Sopenharmony_ci		OCSP_RESPONSE_free(rsp);
4799e5b75505Sopenharmony_ci		return 0;
4800e5b75505Sopenharmony_ci	}
4801e5b75505Sopenharmony_ci
4802e5b75505Sopenharmony_ci	res = OCSP_resp_find_status(basic, id, &status, &reason, &produced_at,
4803e5b75505Sopenharmony_ci				    &this_update, &next_update);
4804e5b75505Sopenharmony_ci	if (!res) {
4805e5b75505Sopenharmony_ci		OCSP_CERTID_free(id);
4806e5b75505Sopenharmony_ci		id = OCSP_cert_to_id(NULL, conn->peer_cert, conn->peer_issuer);
4807e5b75505Sopenharmony_ci		if (!id) {
4808e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
4809e5b75505Sopenharmony_ci				   "OpenSSL: Could not create OCSP certificate identifier (SHA1)");
4810e5b75505Sopenharmony_ci			OCSP_BASICRESP_free(basic);
4811e5b75505Sopenharmony_ci			OCSP_RESPONSE_free(rsp);
4812e5b75505Sopenharmony_ci			return 0;
4813e5b75505Sopenharmony_ci		}
4814e5b75505Sopenharmony_ci
4815e5b75505Sopenharmony_ci		res = OCSP_resp_find_status(basic, id, &status, &reason,
4816e5b75505Sopenharmony_ci					    &produced_at, &this_update,
4817e5b75505Sopenharmony_ci					    &next_update);
4818e5b75505Sopenharmony_ci	}
4819e5b75505Sopenharmony_ci
4820e5b75505Sopenharmony_ci	if (!res) {
4821e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "OpenSSL: Could not find current server certificate from OCSP response%s",
4822e5b75505Sopenharmony_ci			   (conn->flags & TLS_CONN_REQUIRE_OCSP) ? "" :
4823e5b75505Sopenharmony_ci			   " (OCSP not required)");
4824e5b75505Sopenharmony_ci		OCSP_CERTID_free(id);
4825e5b75505Sopenharmony_ci		OCSP_BASICRESP_free(basic);
4826e5b75505Sopenharmony_ci		OCSP_RESPONSE_free(rsp);
4827e5b75505Sopenharmony_ci		return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1;
4828e5b75505Sopenharmony_ci	}
4829e5b75505Sopenharmony_ci	OCSP_CERTID_free(id);
4830e5b75505Sopenharmony_ci
4831e5b75505Sopenharmony_ci	if (!OCSP_check_validity(this_update, next_update, 5 * 60, -1)) {
4832e5b75505Sopenharmony_ci		tls_show_errors(MSG_INFO, __func__,
4833e5b75505Sopenharmony_ci				"OpenSSL: OCSP status times invalid");
4834e5b75505Sopenharmony_ci		OCSP_BASICRESP_free(basic);
4835e5b75505Sopenharmony_ci		OCSP_RESPONSE_free(rsp);
4836e5b75505Sopenharmony_ci		return 0;
4837e5b75505Sopenharmony_ci	}
4838e5b75505Sopenharmony_ci
4839e5b75505Sopenharmony_ci	OCSP_BASICRESP_free(basic);
4840e5b75505Sopenharmony_ci	OCSP_RESPONSE_free(rsp);
4841e5b75505Sopenharmony_ci
4842e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status for server certificate: %s",
4843e5b75505Sopenharmony_ci		   OCSP_cert_status_str(status));
4844e5b75505Sopenharmony_ci
4845e5b75505Sopenharmony_ci	if (status == V_OCSP_CERTSTATUS_GOOD)
4846e5b75505Sopenharmony_ci		return 1;
4847e5b75505Sopenharmony_ci	if (status == V_OCSP_CERTSTATUS_REVOKED)
4848e5b75505Sopenharmony_ci		return 0;
4849e5b75505Sopenharmony_ci	if (conn->flags & TLS_CONN_REQUIRE_OCSP) {
4850e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP required");
4851e5b75505Sopenharmony_ci		return 0;
4852e5b75505Sopenharmony_ci	}
4853e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP was not required, so allow connection to continue");
4854e5b75505Sopenharmony_ci	return 1;
4855e5b75505Sopenharmony_ci}
4856e5b75505Sopenharmony_ci
4857e5b75505Sopenharmony_ci
4858e5b75505Sopenharmony_cistatic int ocsp_status_cb(SSL *s, void *arg)
4859e5b75505Sopenharmony_ci{
4860e5b75505Sopenharmony_ci	char *tmp;
4861e5b75505Sopenharmony_ci	char *resp;
4862e5b75505Sopenharmony_ci	size_t len;
4863e5b75505Sopenharmony_ci
4864e5b75505Sopenharmony_ci	if (tls_global->ocsp_stapling_response == NULL) {
4865e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - no response configured");
4866e5b75505Sopenharmony_ci		return SSL_TLSEXT_ERR_OK;
4867e5b75505Sopenharmony_ci	}
4868e5b75505Sopenharmony_ci
4869e5b75505Sopenharmony_ci	resp = os_readfile(tls_global->ocsp_stapling_response, &len);
4870e5b75505Sopenharmony_ci	if (resp == NULL) {
4871e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - could not read response file");
4872e5b75505Sopenharmony_ci		/* TODO: Build OCSPResponse with responseStatus = internalError
4873e5b75505Sopenharmony_ci		 */
4874e5b75505Sopenharmony_ci		return SSL_TLSEXT_ERR_OK;
4875e5b75505Sopenharmony_ci	}
4876e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - send cached response");
4877e5b75505Sopenharmony_ci	tmp = OPENSSL_malloc(len);
4878e5b75505Sopenharmony_ci	if (tmp == NULL) {
4879e5b75505Sopenharmony_ci		os_free(resp);
4880e5b75505Sopenharmony_ci		return SSL_TLSEXT_ERR_ALERT_FATAL;
4881e5b75505Sopenharmony_ci	}
4882e5b75505Sopenharmony_ci
4883e5b75505Sopenharmony_ci	os_memcpy(tmp, resp, len);
4884e5b75505Sopenharmony_ci	os_free(resp);
4885e5b75505Sopenharmony_ci	SSL_set_tlsext_status_ocsp_resp(s, tmp, len);
4886e5b75505Sopenharmony_ci
4887e5b75505Sopenharmony_ci	return SSL_TLSEXT_ERR_OK;
4888e5b75505Sopenharmony_ci}
4889e5b75505Sopenharmony_ci
4890e5b75505Sopenharmony_ci#endif /* HAVE_OCSP */
4891e5b75505Sopenharmony_ci
4892e5b75505Sopenharmony_ci
4893e5b75505Sopenharmony_ciint tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
4894e5b75505Sopenharmony_ci			      const struct tls_connection_params *params)
4895e5b75505Sopenharmony_ci{
4896e5b75505Sopenharmony_ci	struct tls_data *data = tls_ctx;
4897e5b75505Sopenharmony_ci	int ret;
4898e5b75505Sopenharmony_ci	unsigned long err;
4899e5b75505Sopenharmony_ci	int can_pkcs11 = 0;
4900e5b75505Sopenharmony_ci	const char *key_id = params->key_id;
4901e5b75505Sopenharmony_ci	const char *cert_id = params->cert_id;
4902e5b75505Sopenharmony_ci	const char *ca_cert_id = params->ca_cert_id;
4903e5b75505Sopenharmony_ci	const char *engine_id = params->engine ? params->engine_id : NULL;
4904e5b75505Sopenharmony_ci	const char *ciphers;
4905e5b75505Sopenharmony_ci
4906e5b75505Sopenharmony_ci	if (conn == NULL)
4907e5b75505Sopenharmony_ci		return -1;
4908e5b75505Sopenharmony_ci
4909e5b75505Sopenharmony_ci	if (params->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
4910e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO,
4911e5b75505Sopenharmony_ci			   "OpenSSL: ocsp=3 not supported");
4912e5b75505Sopenharmony_ci		return -1;
4913e5b75505Sopenharmony_ci	}
4914e5b75505Sopenharmony_ci
4915e5b75505Sopenharmony_ci	/*
4916e5b75505Sopenharmony_ci	 * If the engine isn't explicitly configured, and any of the
4917e5b75505Sopenharmony_ci	 * cert/key fields are actually PKCS#11 URIs, then automatically
4918e5b75505Sopenharmony_ci	 * use the PKCS#11 ENGINE.
4919e5b75505Sopenharmony_ci	 */
4920e5b75505Sopenharmony_ci	if (!engine_id || os_strcmp(engine_id, "pkcs11") == 0)
4921e5b75505Sopenharmony_ci		can_pkcs11 = 1;
4922e5b75505Sopenharmony_ci
4923e5b75505Sopenharmony_ci	if (!key_id && params->private_key && can_pkcs11 &&
4924e5b75505Sopenharmony_ci	    os_strncmp(params->private_key, "pkcs11:", 7) == 0) {
4925e5b75505Sopenharmony_ci		can_pkcs11 = 2;
4926e5b75505Sopenharmony_ci		key_id = params->private_key;
4927e5b75505Sopenharmony_ci	}
4928e5b75505Sopenharmony_ci
4929e5b75505Sopenharmony_ci	if (!cert_id && params->client_cert && can_pkcs11 &&
4930e5b75505Sopenharmony_ci	    os_strncmp(params->client_cert, "pkcs11:", 7) == 0) {
4931e5b75505Sopenharmony_ci		can_pkcs11 = 2;
4932e5b75505Sopenharmony_ci		cert_id = params->client_cert;
4933e5b75505Sopenharmony_ci	}
4934e5b75505Sopenharmony_ci
4935e5b75505Sopenharmony_ci	if (!ca_cert_id && params->ca_cert && can_pkcs11 &&
4936e5b75505Sopenharmony_ci	    os_strncmp(params->ca_cert, "pkcs11:", 7) == 0) {
4937e5b75505Sopenharmony_ci		can_pkcs11 = 2;
4938e5b75505Sopenharmony_ci		ca_cert_id = params->ca_cert;
4939e5b75505Sopenharmony_ci	}
4940e5b75505Sopenharmony_ci
4941e5b75505Sopenharmony_ci	/* If we need to automatically enable the PKCS#11 ENGINE, do so. */
4942e5b75505Sopenharmony_ci	if (can_pkcs11 == 2 && !engine_id)
4943e5b75505Sopenharmony_ci		engine_id = "pkcs11";
4944e5b75505Sopenharmony_ci
4945e5b75505Sopenharmony_ci#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
4946e5b75505Sopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
4947e5b75505Sopenharmony_ci	if (params->flags & TLS_CONN_EAP_FAST) {
4948e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
4949e5b75505Sopenharmony_ci			   "OpenSSL: Use TLSv1_method() for EAP-FAST");
4950e5b75505Sopenharmony_ci		if (SSL_set_ssl_method(conn->ssl, TLSv1_method()) != 1) {
4951e5b75505Sopenharmony_ci			tls_show_errors(MSG_INFO, __func__,
4952e5b75505Sopenharmony_ci					"Failed to set TLSv1_method() for EAP-FAST");
4953e5b75505Sopenharmony_ci			return -1;
4954e5b75505Sopenharmony_ci		}
4955e5b75505Sopenharmony_ci	}
4956e5b75505Sopenharmony_ci#endif
4957e5b75505Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10101000L
4958e5b75505Sopenharmony_ci#ifdef SSL_OP_NO_TLSv1_3
4959e5b75505Sopenharmony_ci	if (params->flags & TLS_CONN_EAP_FAST) {
4960e5b75505Sopenharmony_ci		/* Need to disable TLS v1.3 at least for now since OpenSSL 1.1.1
4961e5b75505Sopenharmony_ci		 * refuses to start the handshake with the modified ciphersuite
4962e5b75505Sopenharmony_ci		 * list (no TLS v1.3 ciphersuites included) for EAP-FAST. */
4963e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: Disable TLSv1.3 for EAP-FAST");
4964e5b75505Sopenharmony_ci		SSL_set_options(conn->ssl, SSL_OP_NO_TLSv1_3);
4965e5b75505Sopenharmony_ci	}
4966e5b75505Sopenharmony_ci#endif /* SSL_OP_NO_TLSv1_3 */
4967e5b75505Sopenharmony_ci#endif
4968e5b75505Sopenharmony_ci#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
4969e5b75505Sopenharmony_ci
4970e5b75505Sopenharmony_ci	while ((err = ERR_get_error())) {
4971e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s",
4972e5b75505Sopenharmony_ci			   __func__, ERR_error_string(err, NULL));
4973e5b75505Sopenharmony_ci	}
4974e5b75505Sopenharmony_ci
4975e5b75505Sopenharmony_ci	if (engine_id) {
4976e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine");
4977e5b75505Sopenharmony_ci		ret = tls_engine_init(conn, engine_id, params->pin,
4978e5b75505Sopenharmony_ci				      key_id, cert_id, ca_cert_id);
4979e5b75505Sopenharmony_ci		if (ret)
4980e5b75505Sopenharmony_ci			return ret;
4981e5b75505Sopenharmony_ci	}
4982e5b75505Sopenharmony_ci	if (tls_connection_set_subject_match(conn,
4983e5b75505Sopenharmony_ci					     params->subject_match,
4984e5b75505Sopenharmony_ci					     params->altsubject_match,
4985e5b75505Sopenharmony_ci					     params->suffix_match,
4986e5b75505Sopenharmony_ci					     params->domain_match,
4987e5b75505Sopenharmony_ci					     params->check_cert_subject))
4988e5b75505Sopenharmony_ci		return -1;
4989e5b75505Sopenharmony_ci
4990e5b75505Sopenharmony_ci	if (engine_id && ca_cert_id) {
4991e5b75505Sopenharmony_ci		if (tls_connection_engine_ca_cert(data, conn, ca_cert_id))
4992e5b75505Sopenharmony_ci			return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
4993e5b75505Sopenharmony_ci	} else if (tls_connection_ca_cert(data, conn, params->ca_cert,
4994e5b75505Sopenharmony_ci					  params->ca_cert_blob,
4995e5b75505Sopenharmony_ci					  params->ca_cert_blob_len,
4996e5b75505Sopenharmony_ci					  params->ca_path))
4997e5b75505Sopenharmony_ci		return -1;
4998e5b75505Sopenharmony_ci
4999e5b75505Sopenharmony_ci	if (engine_id && cert_id) {
5000e5b75505Sopenharmony_ci		if (tls_connection_engine_client_cert(conn, cert_id))
5001e5b75505Sopenharmony_ci			return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
5002e5b75505Sopenharmony_ci	} else if (tls_connection_client_cert(conn, params->client_cert,
5003e5b75505Sopenharmony_ci					      params->client_cert_blob,
5004e5b75505Sopenharmony_ci					      params->client_cert_blob_len))
5005e5b75505Sopenharmony_ci		return -1;
5006e5b75505Sopenharmony_ci
5007e5b75505Sopenharmony_ci	if (engine_id && key_id) {
5008e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "TLS: Using private key from engine");
5009e5b75505Sopenharmony_ci		if (tls_connection_engine_private_key(conn))
5010e5b75505Sopenharmony_ci			return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
5011e5b75505Sopenharmony_ci	} else if (tls_connection_private_key(data, conn,
5012e5b75505Sopenharmony_ci					      params->private_key,
5013e5b75505Sopenharmony_ci					      params->private_key_passwd,
5014e5b75505Sopenharmony_ci					      params->private_key_blob,
5015e5b75505Sopenharmony_ci					      params->private_key_blob_len)) {
5016e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "TLS: Failed to load private key '%s'",
5017e5b75505Sopenharmony_ci			   params->private_key);
5018e5b75505Sopenharmony_ci		return -1;
5019e5b75505Sopenharmony_ci	}
5020e5b75505Sopenharmony_ci
5021e5b75505Sopenharmony_ci	if (tls_connection_dh(conn, params->dh_file)) {
5022e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'",
5023e5b75505Sopenharmony_ci			   params->dh_file);
5024e5b75505Sopenharmony_ci		return -1;
5025e5b75505Sopenharmony_ci	}
5026e5b75505Sopenharmony_ci
5027e5b75505Sopenharmony_ci	ciphers = params->openssl_ciphers;
5028e5b75505Sopenharmony_ci#ifdef CONFIG_SUITEB
5029e5b75505Sopenharmony_ci#ifdef OPENSSL_IS_BORINGSSL
5030e5b75505Sopenharmony_ci	if (ciphers && os_strcmp(ciphers, "SUITEB192") == 0) {
5031e5b75505Sopenharmony_ci		/* BoringSSL removed support for SUITEB192, so need to handle
5032e5b75505Sopenharmony_ci		 * this with hardcoded ciphersuite and additional checks for
5033e5b75505Sopenharmony_ci		 * other parameters. */
5034e5b75505Sopenharmony_ci		ciphers = "ECDHE-ECDSA-AES256-GCM-SHA384";
5035e5b75505Sopenharmony_ci	}
5036e5b75505Sopenharmony_ci#endif /* OPENSSL_IS_BORINGSSL */
5037e5b75505Sopenharmony_ci#endif /* CONFIG_SUITEB */
5038e5b75505Sopenharmony_ci	if (ciphers && SSL_set_cipher_list(conn->ssl, ciphers) != 1) {
5039e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO,
5040e5b75505Sopenharmony_ci			   "OpenSSL: Failed to set cipher string '%s'",
5041e5b75505Sopenharmony_ci			   ciphers);
5042e5b75505Sopenharmony_ci		return -1;
5043e5b75505Sopenharmony_ci	}
5044e5b75505Sopenharmony_ci
5045e5b75505Sopenharmony_ci	if (!params->openssl_ecdh_curves) {
5046e5b75505Sopenharmony_ci#ifndef OPENSSL_IS_BORINGSSL
5047e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_EC
5048e5b75505Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x10002000L) && \
5049e5b75505Sopenharmony_ci	(OPENSSL_VERSION_NUMBER < 0x10100000L)
5050e5b75505Sopenharmony_ci		if (SSL_set_ecdh_auto(conn->ssl, 1) != 1) {
5051e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
5052e5b75505Sopenharmony_ci				   "OpenSSL: Failed to set ECDH curves to auto");
5053e5b75505Sopenharmony_ci			return -1;
5054e5b75505Sopenharmony_ci		}
5055e5b75505Sopenharmony_ci#endif /* >= 1.0.2 && < 1.1.0 */
5056e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_EC */
5057e5b75505Sopenharmony_ci#endif /* OPENSSL_IS_BORINGSSL */
5058e5b75505Sopenharmony_ci	} else if (params->openssl_ecdh_curves[0]) {
5059e5b75505Sopenharmony_ci#if defined(OPENSSL_IS_BORINGSSL) || (OPENSSL_VERSION_NUMBER < 0x10002000L)
5060e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO,
5061e5b75505Sopenharmony_ci			"OpenSSL: ECDH configuration nnot supported");
5062e5b75505Sopenharmony_ci		return -1;
5063e5b75505Sopenharmony_ci#else /* OPENSSL_IS_BORINGSSL || < 1.0.2 */
5064e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_EC
5065e5b75505Sopenharmony_ci		if (SSL_set1_curves_list(conn->ssl,
5066e5b75505Sopenharmony_ci					 params->openssl_ecdh_curves) != 1) {
5067e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
5068e5b75505Sopenharmony_ci				   "OpenSSL: Failed to set ECDH curves '%s'",
5069e5b75505Sopenharmony_ci				   params->openssl_ecdh_curves);
5070e5b75505Sopenharmony_ci			return -1;
5071e5b75505Sopenharmony_ci		}
5072e5b75505Sopenharmony_ci#else /* OPENSSL_NO_EC */
5073e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "OpenSSL: ECDH not supported");
5074e5b75505Sopenharmony_ci		return -1;
5075e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_EC */
5076e5b75505Sopenharmony_ci#endif /* OPENSSL_IS_BORINGSSL */
5077e5b75505Sopenharmony_ci	}
5078e5b75505Sopenharmony_ci
5079e5b75505Sopenharmony_ci	if (tls_set_conn_flags(conn, params->flags,
5080e5b75505Sopenharmony_ci			       params->openssl_ciphers) < 0)
5081e5b75505Sopenharmony_ci		return -1;
5082e5b75505Sopenharmony_ci
5083e5b75505Sopenharmony_ci#ifdef OPENSSL_IS_BORINGSSL
5084e5b75505Sopenharmony_ci	if (params->flags & TLS_CONN_REQUEST_OCSP) {
5085e5b75505Sopenharmony_ci		SSL_enable_ocsp_stapling(conn->ssl);
5086e5b75505Sopenharmony_ci	}
5087e5b75505Sopenharmony_ci#else /* OPENSSL_IS_BORINGSSL */
5088e5b75505Sopenharmony_ci#ifdef HAVE_OCSP
5089e5b75505Sopenharmony_ci	if (params->flags & TLS_CONN_REQUEST_OCSP) {
5090e5b75505Sopenharmony_ci		SSL_CTX *ssl_ctx = data->ssl;
5091e5b75505Sopenharmony_ci		SSL_set_tlsext_status_type(conn->ssl, TLSEXT_STATUSTYPE_ocsp);
5092e5b75505Sopenharmony_ci		SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_resp_cb);
5093e5b75505Sopenharmony_ci		SSL_CTX_set_tlsext_status_arg(ssl_ctx, conn);
5094e5b75505Sopenharmony_ci	}
5095e5b75505Sopenharmony_ci#else /* HAVE_OCSP */
5096e5b75505Sopenharmony_ci	if (params->flags & TLS_CONN_REQUIRE_OCSP) {
5097e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO,
5098e5b75505Sopenharmony_ci			   "OpenSSL: No OCSP support included - reject configuration");
5099e5b75505Sopenharmony_ci		return -1;
5100e5b75505Sopenharmony_ci	}
5101e5b75505Sopenharmony_ci	if (params->flags & TLS_CONN_REQUEST_OCSP) {
5102e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
5103e5b75505Sopenharmony_ci			   "OpenSSL: No OCSP support included - allow optional OCSP case to continue");
5104e5b75505Sopenharmony_ci	}
5105e5b75505Sopenharmony_ci#endif /* HAVE_OCSP */
5106e5b75505Sopenharmony_ci#endif /* OPENSSL_IS_BORINGSSL */
5107e5b75505Sopenharmony_ci
5108e5b75505Sopenharmony_ci	conn->flags = params->flags;
5109e5b75505Sopenharmony_ci
5110e5b75505Sopenharmony_ci	tls_get_errors(data);
5111e5b75505Sopenharmony_ci
5112e5b75505Sopenharmony_ci	return 0;
5113e5b75505Sopenharmony_ci}
5114e5b75505Sopenharmony_ci
5115e5b75505Sopenharmony_ci
5116e5b75505Sopenharmony_cistatic void openssl_debug_dump_cipher_list(SSL_CTX *ssl_ctx)
5117e5b75505Sopenharmony_ci{
5118e5b75505Sopenharmony_ci	SSL *ssl;
5119e5b75505Sopenharmony_ci	int i;
5120e5b75505Sopenharmony_ci
5121e5b75505Sopenharmony_ci	ssl = SSL_new(ssl_ctx);
5122e5b75505Sopenharmony_ci	if (!ssl)
5123e5b75505Sopenharmony_ci		return;
5124e5b75505Sopenharmony_ci
5125e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG,
5126e5b75505Sopenharmony_ci		   "OpenSSL: Enabled cipher suites in priority order");
5127e5b75505Sopenharmony_ci	for (i = 0; ; i++) {
5128e5b75505Sopenharmony_ci		const char *cipher;
5129e5b75505Sopenharmony_ci
5130e5b75505Sopenharmony_ci		cipher = SSL_get_cipher_list(ssl, i);
5131e5b75505Sopenharmony_ci		if (!cipher)
5132e5b75505Sopenharmony_ci			break;
5133e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "Cipher %d: %s", i, cipher);
5134e5b75505Sopenharmony_ci	}
5135e5b75505Sopenharmony_ci
5136e5b75505Sopenharmony_ci	SSL_free(ssl);
5137e5b75505Sopenharmony_ci}
5138e5b75505Sopenharmony_ci
5139e5b75505Sopenharmony_ci
5140e5b75505Sopenharmony_ci#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(BORINGSSL_API_VERSION)
5141e5b75505Sopenharmony_ci
5142e5b75505Sopenharmony_cistatic const char * openssl_pkey_type_str(const EVP_PKEY *pkey)
5143e5b75505Sopenharmony_ci{
5144e5b75505Sopenharmony_ci	if (!pkey)
5145e5b75505Sopenharmony_ci		return "NULL";
5146e5b75505Sopenharmony_ci	switch (EVP_PKEY_type(EVP_PKEY_id(pkey))) {
5147e5b75505Sopenharmony_ci	case EVP_PKEY_RSA:
5148e5b75505Sopenharmony_ci		return "RSA";
5149e5b75505Sopenharmony_ci	case EVP_PKEY_DSA:
5150e5b75505Sopenharmony_ci		return "DSA";
5151e5b75505Sopenharmony_ci	case EVP_PKEY_DH:
5152e5b75505Sopenharmony_ci		return "DH";
5153e5b75505Sopenharmony_ci	case EVP_PKEY_EC:
5154e5b75505Sopenharmony_ci		return "EC";
5155e5b75505Sopenharmony_ci	}
5156e5b75505Sopenharmony_ci	return "?";
5157e5b75505Sopenharmony_ci}
5158e5b75505Sopenharmony_ci
5159e5b75505Sopenharmony_ci
5160e5b75505Sopenharmony_cistatic void openssl_debug_dump_certificate(int i, X509 *cert)
5161e5b75505Sopenharmony_ci{
5162e5b75505Sopenharmony_ci	char buf[256];
5163e5b75505Sopenharmony_ci	EVP_PKEY *pkey;
5164e5b75505Sopenharmony_ci	ASN1_INTEGER *ser;
5165e5b75505Sopenharmony_ci	char serial_num[128];
5166e5b75505Sopenharmony_ci
5167e5b75505Sopenharmony_ci	X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
5168e5b75505Sopenharmony_ci
5169e5b75505Sopenharmony_ci	ser = X509_get_serialNumber(cert);
5170e5b75505Sopenharmony_ci	if (ser)
5171e5b75505Sopenharmony_ci		wpa_snprintf_hex_uppercase(serial_num, sizeof(serial_num),
5172e5b75505Sopenharmony_ci					   ASN1_STRING_get0_data(ser),
5173e5b75505Sopenharmony_ci					   ASN1_STRING_length(ser));
5174e5b75505Sopenharmony_ci	else
5175e5b75505Sopenharmony_ci		serial_num[0] = '\0';
5176e5b75505Sopenharmony_ci
5177e5b75505Sopenharmony_ci	pkey = X509_get_pubkey(cert);
5178e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "%d: %s (%s) %s", i, buf,
5179e5b75505Sopenharmony_ci		   openssl_pkey_type_str(pkey), serial_num);
5180e5b75505Sopenharmony_ci	EVP_PKEY_free(pkey);
5181e5b75505Sopenharmony_ci}
5182e5b75505Sopenharmony_ci
5183e5b75505Sopenharmony_ci
5184e5b75505Sopenharmony_cistatic void openssl_debug_dump_certificates(SSL_CTX *ssl_ctx)
5185e5b75505Sopenharmony_ci{
5186e5b75505Sopenharmony_ci	STACK_OF(X509) *certs;
5187e5b75505Sopenharmony_ci
5188e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "OpenSSL: Configured certificate chain");
5189e5b75505Sopenharmony_ci	if (SSL_CTX_get0_chain_certs(ssl_ctx, &certs) == 1) {
5190e5b75505Sopenharmony_ci		int i;
5191e5b75505Sopenharmony_ci
5192e5b75505Sopenharmony_ci		for (i = sk_X509_num(certs); i > 0; i--)
5193e5b75505Sopenharmony_ci			openssl_debug_dump_certificate(i, sk_X509_value(certs,
5194e5b75505Sopenharmony_ci									i - 1));
5195e5b75505Sopenharmony_ci	}
5196e5b75505Sopenharmony_ci	openssl_debug_dump_certificate(0, SSL_CTX_get0_certificate(ssl_ctx));
5197e5b75505Sopenharmony_ci}
5198e5b75505Sopenharmony_ci
5199e5b75505Sopenharmony_ci#endif
5200e5b75505Sopenharmony_ci
5201e5b75505Sopenharmony_ci
5202e5b75505Sopenharmony_cistatic void openssl_debug_dump_certificate_chains(SSL_CTX *ssl_ctx)
5203e5b75505Sopenharmony_ci{
5204e5b75505Sopenharmony_ci#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(BORINGSSL_API_VERSION)
5205e5b75505Sopenharmony_ci	int res;
5206e5b75505Sopenharmony_ci
5207e5b75505Sopenharmony_ci	for (res = SSL_CTX_set_current_cert(ssl_ctx, SSL_CERT_SET_FIRST);
5208e5b75505Sopenharmony_ci	     res == 1;
5209e5b75505Sopenharmony_ci	     res = SSL_CTX_set_current_cert(ssl_ctx, SSL_CERT_SET_NEXT))
5210e5b75505Sopenharmony_ci		openssl_debug_dump_certificates(ssl_ctx);
5211e5b75505Sopenharmony_ci
5212e5b75505Sopenharmony_ci	SSL_CTX_set_current_cert(ssl_ctx, SSL_CERT_SET_FIRST);
5213e5b75505Sopenharmony_ci#endif
5214e5b75505Sopenharmony_ci}
5215e5b75505Sopenharmony_ci
5216e5b75505Sopenharmony_ci
5217e5b75505Sopenharmony_cistatic void openssl_debug_dump_ctx(SSL_CTX *ssl_ctx)
5218e5b75505Sopenharmony_ci{
5219e5b75505Sopenharmony_ci	openssl_debug_dump_cipher_list(ssl_ctx);
5220e5b75505Sopenharmony_ci	openssl_debug_dump_certificate_chains(ssl_ctx);
5221e5b75505Sopenharmony_ci}
5222e5b75505Sopenharmony_ci
5223e5b75505Sopenharmony_ci
5224e5b75505Sopenharmony_ciint tls_global_set_params(void *tls_ctx,
5225e5b75505Sopenharmony_ci			  const struct tls_connection_params *params)
5226e5b75505Sopenharmony_ci{
5227e5b75505Sopenharmony_ci	struct tls_data *data = tls_ctx;
5228e5b75505Sopenharmony_ci	SSL_CTX *ssl_ctx = data->ssl;
5229e5b75505Sopenharmony_ci	unsigned long err;
5230e5b75505Sopenharmony_ci
5231e5b75505Sopenharmony_ci	while ((err = ERR_get_error())) {
5232e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s",
5233e5b75505Sopenharmony_ci			   __func__, ERR_error_string(err, NULL));
5234e5b75505Sopenharmony_ci	}
5235e5b75505Sopenharmony_ci
5236e5b75505Sopenharmony_ci	os_free(data->check_cert_subject);
5237e5b75505Sopenharmony_ci	data->check_cert_subject = NULL;
5238e5b75505Sopenharmony_ci	if (params->check_cert_subject) {
5239e5b75505Sopenharmony_ci		data->check_cert_subject =
5240e5b75505Sopenharmony_ci			os_strdup(params->check_cert_subject);
5241e5b75505Sopenharmony_ci		if (!data->check_cert_subject)
5242e5b75505Sopenharmony_ci			return -1;
5243e5b75505Sopenharmony_ci	}
5244e5b75505Sopenharmony_ci
5245e5b75505Sopenharmony_ci	if (tls_global_ca_cert(data, params->ca_cert) ||
5246e5b75505Sopenharmony_ci	    tls_global_client_cert(data, params->client_cert) ||
5247e5b75505Sopenharmony_ci	    tls_global_private_key(data, params->private_key,
5248e5b75505Sopenharmony_ci				   params->private_key_passwd) ||
5249e5b75505Sopenharmony_ci	    tls_global_client_cert(data, params->client_cert2) ||
5250e5b75505Sopenharmony_ci	    tls_global_private_key(data, params->private_key2,
5251e5b75505Sopenharmony_ci				   params->private_key_passwd2) ||
5252e5b75505Sopenharmony_ci	    tls_global_dh(data, params->dh_file)) {
5253e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "TLS: Failed to set global parameters");
5254e5b75505Sopenharmony_ci		return -1;
5255e5b75505Sopenharmony_ci	}
5256e5b75505Sopenharmony_ci
5257e5b75505Sopenharmony_ci	if (params->openssl_ciphers &&
5258e5b75505Sopenharmony_ci	    SSL_CTX_set_cipher_list(ssl_ctx, params->openssl_ciphers) != 1) {
5259e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO,
5260e5b75505Sopenharmony_ci			   "OpenSSL: Failed to set cipher string '%s'",
5261e5b75505Sopenharmony_ci			   params->openssl_ciphers);
5262e5b75505Sopenharmony_ci		return -1;
5263e5b75505Sopenharmony_ci	}
5264e5b75505Sopenharmony_ci
5265e5b75505Sopenharmony_ci	if (!params->openssl_ecdh_curves) {
5266e5b75505Sopenharmony_ci#ifndef OPENSSL_IS_BORINGSSL
5267e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_EC
5268e5b75505Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x10002000L) && \
5269e5b75505Sopenharmony_ci	(OPENSSL_VERSION_NUMBER < 0x10100000L)
5270e5b75505Sopenharmony_ci		if (SSL_CTX_set_ecdh_auto(ssl_ctx, 1) != 1) {
5271e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
5272e5b75505Sopenharmony_ci				   "OpenSSL: Failed to set ECDH curves to auto");
5273e5b75505Sopenharmony_ci			return -1;
5274e5b75505Sopenharmony_ci		}
5275e5b75505Sopenharmony_ci#endif /* >= 1.0.2 && < 1.1.0 */
5276e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_EC */
5277e5b75505Sopenharmony_ci#endif /* OPENSSL_IS_BORINGSSL */
5278e5b75505Sopenharmony_ci	} else if (params->openssl_ecdh_curves[0]) {
5279e5b75505Sopenharmony_ci#if defined(OPENSSL_IS_BORINGSSL) || (OPENSSL_VERSION_NUMBER < 0x10002000L)
5280e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO,
5281e5b75505Sopenharmony_ci			"OpenSSL: ECDH configuration nnot supported");
5282e5b75505Sopenharmony_ci		return -1;
5283e5b75505Sopenharmony_ci#else /* OPENSSL_IS_BORINGSSL || < 1.0.2 */
5284e5b75505Sopenharmony_ci#ifndef OPENSSL_NO_EC
5285e5b75505Sopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10100000L
5286e5b75505Sopenharmony_ci		SSL_CTX_set_ecdh_auto(ssl_ctx, 1);
5287e5b75505Sopenharmony_ci#endif
5288e5b75505Sopenharmony_ci		if (SSL_CTX_set1_curves_list(ssl_ctx,
5289e5b75505Sopenharmony_ci					     params->openssl_ecdh_curves) !=
5290e5b75505Sopenharmony_ci		    1) {
5291e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
5292e5b75505Sopenharmony_ci				   "OpenSSL: Failed to set ECDH curves '%s'",
5293e5b75505Sopenharmony_ci				   params->openssl_ecdh_curves);
5294e5b75505Sopenharmony_ci			return -1;
5295e5b75505Sopenharmony_ci		}
5296e5b75505Sopenharmony_ci#else /* OPENSSL_NO_EC */
5297e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "OpenSSL: ECDH not supported");
5298e5b75505Sopenharmony_ci		return -1;
5299e5b75505Sopenharmony_ci#endif /* OPENSSL_NO_EC */
5300e5b75505Sopenharmony_ci#endif /* OPENSSL_IS_BORINGSSL */
5301e5b75505Sopenharmony_ci	}
5302e5b75505Sopenharmony_ci
5303e5b75505Sopenharmony_ci#ifdef SSL_OP_NO_TICKET
5304e5b75505Sopenharmony_ci	if (params->flags & TLS_CONN_DISABLE_SESSION_TICKET)
5305e5b75505Sopenharmony_ci		SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TICKET);
5306e5b75505Sopenharmony_ci	else
5307e5b75505Sopenharmony_ci		SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TICKET);
5308e5b75505Sopenharmony_ci#endif /*  SSL_OP_NO_TICKET */
5309e5b75505Sopenharmony_ci
5310e5b75505Sopenharmony_ci#ifdef HAVE_OCSP
5311e5b75505Sopenharmony_ci	SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_status_cb);
5312e5b75505Sopenharmony_ci	SSL_CTX_set_tlsext_status_arg(ssl_ctx, ssl_ctx);
5313e5b75505Sopenharmony_ci	os_free(tls_global->ocsp_stapling_response);
5314e5b75505Sopenharmony_ci	if (params->ocsp_stapling_response)
5315e5b75505Sopenharmony_ci		tls_global->ocsp_stapling_response =
5316e5b75505Sopenharmony_ci			os_strdup(params->ocsp_stapling_response);
5317e5b75505Sopenharmony_ci	else
5318e5b75505Sopenharmony_ci		tls_global->ocsp_stapling_response = NULL;
5319e5b75505Sopenharmony_ci#endif /* HAVE_OCSP */
5320e5b75505Sopenharmony_ci
5321e5b75505Sopenharmony_ci	openssl_debug_dump_ctx(ssl_ctx);
5322e5b75505Sopenharmony_ci
5323e5b75505Sopenharmony_ci	return 0;
5324e5b75505Sopenharmony_ci}
5325e5b75505Sopenharmony_ci
5326e5b75505Sopenharmony_ci
5327e5b75505Sopenharmony_ci#ifdef EAP_FAST_OR_TEAP
5328e5b75505Sopenharmony_ci/* Pre-shared secred requires a patch to openssl, so this function is
5329e5b75505Sopenharmony_ci * commented out unless explicitly needed for EAP-FAST in order to be able to
5330e5b75505Sopenharmony_ci * build this file with unmodified openssl. */
5331e5b75505Sopenharmony_ci
5332e5b75505Sopenharmony_ci#if (defined(OPENSSL_IS_BORINGSSL) || OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
5333e5b75505Sopenharmony_cistatic int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
5334e5b75505Sopenharmony_ci			   STACK_OF(SSL_CIPHER) *peer_ciphers,
5335e5b75505Sopenharmony_ci			   const SSL_CIPHER **cipher, void *arg)
5336e5b75505Sopenharmony_ci#else /* OPENSSL_IS_BORINGSSL */
5337e5b75505Sopenharmony_cistatic int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
5338e5b75505Sopenharmony_ci			   STACK_OF(SSL_CIPHER) *peer_ciphers,
5339e5b75505Sopenharmony_ci			   SSL_CIPHER **cipher, void *arg)
5340e5b75505Sopenharmony_ci#endif /* OPENSSL_IS_BORINGSSL */
5341e5b75505Sopenharmony_ci{
5342e5b75505Sopenharmony_ci	struct tls_connection *conn = arg;
5343e5b75505Sopenharmony_ci	int ret;
5344e5b75505Sopenharmony_ci
5345e5b75505Sopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
5346e5b75505Sopenharmony_ci	(defined(LIBRESSL_VERSION_NUMBER) && \
5347e5b75505Sopenharmony_ci	 LIBRESSL_VERSION_NUMBER < 0x20700000L)
5348e5b75505Sopenharmony_ci	if (conn == NULL || conn->session_ticket_cb == NULL)
5349e5b75505Sopenharmony_ci		return 0;
5350e5b75505Sopenharmony_ci
5351e5b75505Sopenharmony_ci	ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx,
5352e5b75505Sopenharmony_ci				      conn->session_ticket,
5353e5b75505Sopenharmony_ci				      conn->session_ticket_len,
5354e5b75505Sopenharmony_ci				      s->s3->client_random,
5355e5b75505Sopenharmony_ci				      s->s3->server_random, secret);
5356e5b75505Sopenharmony_ci#else
5357e5b75505Sopenharmony_ci	unsigned char client_random[SSL3_RANDOM_SIZE];
5358e5b75505Sopenharmony_ci	unsigned char server_random[SSL3_RANDOM_SIZE];
5359e5b75505Sopenharmony_ci
5360e5b75505Sopenharmony_ci	if (conn == NULL || conn->session_ticket_cb == NULL)
5361e5b75505Sopenharmony_ci		return 0;
5362e5b75505Sopenharmony_ci
5363e5b75505Sopenharmony_ci	SSL_get_client_random(s, client_random, sizeof(client_random));
5364e5b75505Sopenharmony_ci	SSL_get_server_random(s, server_random, sizeof(server_random));
5365e5b75505Sopenharmony_ci
5366e5b75505Sopenharmony_ci	ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx,
5367e5b75505Sopenharmony_ci				      conn->session_ticket,
5368e5b75505Sopenharmony_ci				      conn->session_ticket_len,
5369e5b75505Sopenharmony_ci				      client_random,
5370e5b75505Sopenharmony_ci				      server_random, secret);
5371e5b75505Sopenharmony_ci#endif
5372e5b75505Sopenharmony_ci
5373e5b75505Sopenharmony_ci	os_free(conn->session_ticket);
5374e5b75505Sopenharmony_ci	conn->session_ticket = NULL;
5375e5b75505Sopenharmony_ci
5376e5b75505Sopenharmony_ci	if (ret <= 0)
5377e5b75505Sopenharmony_ci		return 0;
5378e5b75505Sopenharmony_ci
5379e5b75505Sopenharmony_ci	*secret_len = SSL_MAX_MASTER_KEY_LENGTH;
5380e5b75505Sopenharmony_ci	return 1;
5381e5b75505Sopenharmony_ci}
5382e5b75505Sopenharmony_ci
5383e5b75505Sopenharmony_ci
5384e5b75505Sopenharmony_cistatic int tls_session_ticket_ext_cb(SSL *s, const unsigned char *data,
5385e5b75505Sopenharmony_ci				     int len, void *arg)
5386e5b75505Sopenharmony_ci{
5387e5b75505Sopenharmony_ci	struct tls_connection *conn = arg;
5388e5b75505Sopenharmony_ci
5389e5b75505Sopenharmony_ci	if (conn == NULL || conn->session_ticket_cb == NULL)
5390e5b75505Sopenharmony_ci		return 0;
5391e5b75505Sopenharmony_ci
5392e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "OpenSSL: %s: length=%d", __func__, len);
5393e5b75505Sopenharmony_ci
5394e5b75505Sopenharmony_ci	os_free(conn->session_ticket);
5395e5b75505Sopenharmony_ci	conn->session_ticket = NULL;
5396e5b75505Sopenharmony_ci
5397e5b75505Sopenharmony_ci	wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket "
5398e5b75505Sopenharmony_ci		    "extension", data, len);
5399e5b75505Sopenharmony_ci
5400e5b75505Sopenharmony_ci	conn->session_ticket = os_memdup(data, len);
5401e5b75505Sopenharmony_ci	if (conn->session_ticket == NULL)
5402e5b75505Sopenharmony_ci		return 0;
5403e5b75505Sopenharmony_ci
5404e5b75505Sopenharmony_ci	conn->session_ticket_len = len;
5405e5b75505Sopenharmony_ci
5406e5b75505Sopenharmony_ci	return 1;
5407e5b75505Sopenharmony_ci}
5408e5b75505Sopenharmony_ci#endif /* EAP_FAST_OR_TEAP */
5409e5b75505Sopenharmony_ci
5410e5b75505Sopenharmony_ci
5411e5b75505Sopenharmony_ciint tls_connection_set_session_ticket_cb(void *tls_ctx,
5412e5b75505Sopenharmony_ci					 struct tls_connection *conn,
5413e5b75505Sopenharmony_ci					 tls_session_ticket_cb cb,
5414e5b75505Sopenharmony_ci					 void *ctx)
5415e5b75505Sopenharmony_ci{
5416e5b75505Sopenharmony_ci#ifdef EAP_FAST_OR_TEAP
5417e5b75505Sopenharmony_ci	conn->session_ticket_cb = cb;
5418e5b75505Sopenharmony_ci	conn->session_ticket_cb_ctx = ctx;
5419e5b75505Sopenharmony_ci
5420e5b75505Sopenharmony_ci	if (cb) {
5421e5b75505Sopenharmony_ci		if (SSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb,
5422e5b75505Sopenharmony_ci					      conn) != 1)
5423e5b75505Sopenharmony_ci			return -1;
5424e5b75505Sopenharmony_ci		SSL_set_session_ticket_ext_cb(conn->ssl,
5425e5b75505Sopenharmony_ci					      tls_session_ticket_ext_cb, conn);
5426e5b75505Sopenharmony_ci	} else {
5427e5b75505Sopenharmony_ci		if (SSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1)
5428e5b75505Sopenharmony_ci			return -1;
5429e5b75505Sopenharmony_ci		SSL_set_session_ticket_ext_cb(conn->ssl, NULL, NULL);
5430e5b75505Sopenharmony_ci	}
5431e5b75505Sopenharmony_ci
5432e5b75505Sopenharmony_ci	return 0;
5433e5b75505Sopenharmony_ci#else /* EAP_FAST_OR_TEAP */
5434e5b75505Sopenharmony_ci	return -1;
5435e5b75505Sopenharmony_ci#endif /* EAP_FAST_OR_TEAP */
5436e5b75505Sopenharmony_ci}
5437e5b75505Sopenharmony_ci
5438e5b75505Sopenharmony_ci
5439e5b75505Sopenharmony_ciint tls_get_library_version(char *buf, size_t buf_len)
5440e5b75505Sopenharmony_ci{
5441e5b75505Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
5442e5b75505Sopenharmony_ci	return os_snprintf(buf, buf_len, "OpenSSL build=%s run=%s",
5443e5b75505Sopenharmony_ci			   OPENSSL_VERSION_TEXT,
5444e5b75505Sopenharmony_ci			   OpenSSL_version(OPENSSL_VERSION));
5445e5b75505Sopenharmony_ci#else
5446e5b75505Sopenharmony_ci	return os_snprintf(buf, buf_len, "OpenSSL build=%s run=%s",
5447e5b75505Sopenharmony_ci			   OPENSSL_VERSION_TEXT,
5448e5b75505Sopenharmony_ci			   SSLeay_version(SSLEAY_VERSION));
5449e5b75505Sopenharmony_ci#endif
5450e5b75505Sopenharmony_ci}
5451e5b75505Sopenharmony_ci
5452e5b75505Sopenharmony_ci
5453e5b75505Sopenharmony_civoid tls_connection_set_success_data(struct tls_connection *conn,
5454e5b75505Sopenharmony_ci				     struct wpabuf *data)
5455e5b75505Sopenharmony_ci{
5456e5b75505Sopenharmony_ci	SSL_SESSION *sess;
5457e5b75505Sopenharmony_ci	struct wpabuf *old;
5458e5b75505Sopenharmony_ci
5459e5b75505Sopenharmony_ci	if (tls_ex_idx_session < 0)
5460e5b75505Sopenharmony_ci		goto fail;
5461e5b75505Sopenharmony_ci	sess = SSL_get_session(conn->ssl);
5462e5b75505Sopenharmony_ci	if (!sess)
5463e5b75505Sopenharmony_ci		goto fail;
5464e5b75505Sopenharmony_ci	old = SSL_SESSION_get_ex_data(sess, tls_ex_idx_session);
5465e5b75505Sopenharmony_ci	if (old) {
5466e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "OpenSSL: Replacing old success data %p",
5467e5b75505Sopenharmony_ci			   old);
5468e5b75505Sopenharmony_ci		wpabuf_free(old);
5469e5b75505Sopenharmony_ci	}
5470e5b75505Sopenharmony_ci	if (SSL_SESSION_set_ex_data(sess, tls_ex_idx_session, data) != 1)
5471e5b75505Sopenharmony_ci		goto fail;
5472e5b75505Sopenharmony_ci
5473e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "OpenSSL: Stored success data %p", data);
5474e5b75505Sopenharmony_ci	conn->success_data = 1;
5475e5b75505Sopenharmony_ci	return;
5476e5b75505Sopenharmony_ci
5477e5b75505Sopenharmony_cifail:
5478e5b75505Sopenharmony_ci	wpa_printf(MSG_INFO, "OpenSSL: Failed to store success data");
5479e5b75505Sopenharmony_ci	wpabuf_free(data);
5480e5b75505Sopenharmony_ci}
5481e5b75505Sopenharmony_ci
5482e5b75505Sopenharmony_ci
5483e5b75505Sopenharmony_civoid tls_connection_set_success_data_resumed(struct tls_connection *conn)
5484e5b75505Sopenharmony_ci{
5485e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG,
5486e5b75505Sopenharmony_ci		   "OpenSSL: Success data accepted for resumed session");
5487e5b75505Sopenharmony_ci	conn->success_data = 1;
5488e5b75505Sopenharmony_ci}
5489e5b75505Sopenharmony_ci
5490e5b75505Sopenharmony_ci
5491e5b75505Sopenharmony_ciconst struct wpabuf *
5492e5b75505Sopenharmony_citls_connection_get_success_data(struct tls_connection *conn)
5493e5b75505Sopenharmony_ci{
5494e5b75505Sopenharmony_ci	SSL_SESSION *sess;
5495e5b75505Sopenharmony_ci
5496e5b75505Sopenharmony_ci	if (tls_ex_idx_session < 0 ||
5497e5b75505Sopenharmony_ci	    !(sess = SSL_get_session(conn->ssl)))
5498e5b75505Sopenharmony_ci		return NULL;
5499e5b75505Sopenharmony_ci	return SSL_SESSION_get_ex_data(sess, tls_ex_idx_session);
5500e5b75505Sopenharmony_ci}
5501e5b75505Sopenharmony_ci
5502e5b75505Sopenharmony_ci
5503e5b75505Sopenharmony_civoid tls_connection_remove_session(struct tls_connection *conn)
5504e5b75505Sopenharmony_ci{
5505e5b75505Sopenharmony_ci	SSL_SESSION *sess;
5506e5b75505Sopenharmony_ci
5507e5b75505Sopenharmony_ci	sess = SSL_get_session(conn->ssl);
5508e5b75505Sopenharmony_ci	if (!sess)
5509e5b75505Sopenharmony_ci		return;
5510e5b75505Sopenharmony_ci
5511e5b75505Sopenharmony_ci	if (SSL_CTX_remove_session(conn->ssl_ctx, sess) != 1)
5512e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
5513e5b75505Sopenharmony_ci			   "OpenSSL: Session was not cached");
5514e5b75505Sopenharmony_ci	else
5515e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
5516e5b75505Sopenharmony_ci			   "OpenSSL: Removed cached session to disable session resumption");
5517e5b75505Sopenharmony_ci}
5518e5b75505Sopenharmony_ci
5519e5b75505Sopenharmony_ci
5520e5b75505Sopenharmony_ciint tls_get_tls_unique(struct tls_connection *conn, u8 *buf, size_t max_len)
5521e5b75505Sopenharmony_ci{
5522e5b75505Sopenharmony_ci	size_t len;
5523e5b75505Sopenharmony_ci	int reused;
5524e5b75505Sopenharmony_ci
5525e5b75505Sopenharmony_ci	reused = SSL_session_reused(conn->ssl);
5526e5b75505Sopenharmony_ci	if ((conn->server && !reused) || (!conn->server && reused))
5527e5b75505Sopenharmony_ci		len = SSL_get_peer_finished(conn->ssl, buf, max_len);
5528e5b75505Sopenharmony_ci	else
5529e5b75505Sopenharmony_ci		len = SSL_get_finished(conn->ssl, buf, max_len);
5530e5b75505Sopenharmony_ci
5531e5b75505Sopenharmony_ci	if (len == 0 || len > max_len)
5532e5b75505Sopenharmony_ci		return -1;
5533e5b75505Sopenharmony_ci
5534e5b75505Sopenharmony_ci	return len;
5535e5b75505Sopenharmony_ci}
5536e5b75505Sopenharmony_ci
5537e5b75505Sopenharmony_ci
5538e5b75505Sopenharmony_ciu16 tls_connection_get_cipher_suite(struct tls_connection *conn)
5539e5b75505Sopenharmony_ci{
5540e5b75505Sopenharmony_ci	const SSL_CIPHER *cipher;
5541e5b75505Sopenharmony_ci
5542e5b75505Sopenharmony_ci	cipher = SSL_get_current_cipher(conn->ssl);
5543e5b75505Sopenharmony_ci	if (!cipher)
5544e5b75505Sopenharmony_ci		return 0;
5545e5b75505Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined(LIBRESSL_VERSION_NUMBER)
5546e5b75505Sopenharmony_ci	return SSL_CIPHER_get_protocol_id(cipher);
5547e5b75505Sopenharmony_ci#else
5548e5b75505Sopenharmony_ci	return SSL_CIPHER_get_id(cipher) & 0xFFFF;
5549e5b75505Sopenharmony_ci#endif
5550e5b75505Sopenharmony_ci}
5551