18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SSL/TLS interface functions for OpenSSL
3d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_SMARTCARD
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
13db3c5a43353099fd4771f3b7a13efae905878ce9Kenny Root#ifndef ANDROID
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OPENSSL_NO_ENGINE
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
17db3c5a43353099fd4771f3b7a13efae905878ce9Kenny Root#endif
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <openssl/ssl.h>
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <openssl/err.h>
21849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt#include <openssl/opensslv.h>
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <openssl/pkcs12.h>
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <openssl/x509v3.h>
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <openssl/engine.h>
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
27d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifndef OPENSSL_NO_DSA
28d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#include <openssl/dsa.h>
29d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif
30d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifndef OPENSSL_NO_DH
31d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#include <openssl/dh.h>
32d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif
33d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto.h"
36af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt#include "sha1.h"
37d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#include "sha256.h"
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tls.h"
39d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt#include "tls_openssl.h"
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt#if !defined(CONFIG_FIPS) &&                             \
42849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt    (defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) ||   \
43849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt     defined(EAP_SERVER_FAST))
44849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt#define OPENSSL_NEED_EAP_FAST_PRF
45849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt#endif
46849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt
479ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt#if defined(OPENSSL_IS_BORINGSSL)
489ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt/* stack_index_t is the return type of OpenSSL's sk_XXX_num() functions. */
499ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidttypedef size_t stack_index_t;
509ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt#else
519ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidttypedef int stack_index_t;
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
54ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt#ifdef SSL_set_tlsext_status_type
55ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt#ifndef OPENSSL_NO_TLSEXT
56ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt#define HAVE_OCSP
57ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt#include <openssl/ocsp.h>
58ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt#endif /* OPENSSL_NO_TLSEXT */
59ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt#endif /* SSL_set_tlsext_status_type */
60ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt
61849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt#if (OPENSSL_VERSION_NUMBER < 0x10100000L || \
62849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt     defined(LIBRESSL_VERSION_NUMBER)) &&    \
63849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt    !defined(BORINGSSL_API_VERSION)
64de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt/*
65de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt * SSL_get_client_random() and SSL_get_server_random() were added in OpenSSL
66849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt * 1.1.0 and newer BoringSSL revisions. Provide compatibility wrappers for
67849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt * older versions.
68de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt */
69de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt
70de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidtstatic size_t SSL_get_client_random(const SSL *ssl, unsigned char *out,
71de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt				    size_t outlen)
72de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt{
73de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	if (!ssl->s3 || outlen < SSL3_RANDOM_SIZE)
74de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt		return 0;
75de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	os_memcpy(out, ssl->s3->client_random, SSL3_RANDOM_SIZE);
76de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	return SSL3_RANDOM_SIZE;
77de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt}
78de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt
79de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt
80de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidtstatic size_t SSL_get_server_random(const SSL *ssl, unsigned char *out,
81de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt				    size_t outlen)
82de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt{
83de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	if (!ssl->s3 || outlen < SSL3_RANDOM_SIZE)
84de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt		return 0;
85de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	os_memcpy(out, ssl->s3->server_random, SSL3_RANDOM_SIZE);
86de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	return SSL3_RANDOM_SIZE;
87de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt}
88de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt
89de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt
90849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt#ifdef OPENSSL_NEED_EAP_FAST_PRF
91de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidtstatic size_t SSL_SESSION_get_master_key(const SSL_SESSION *session,
92de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt					 unsigned char *out, size_t outlen)
93de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt{
94de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	if (!session || session->master_key_length < 0 ||
95de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	    (size_t) session->master_key_length > outlen)
96de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt		return 0;
97de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	if ((size_t) session->master_key_length < outlen)
98de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt		outlen = session->master_key_length;
99de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	os_memcpy(out, session->master_key, outlen);
100de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	return outlen;
101de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt}
102849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt#endif /* OPENSSL_NEED_EAP_FAST_PRF */
103de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt
104de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt#endif
105de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt
106d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#if OPENSSL_VERSION_NUMBER < 0x10100000L
107d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#ifdef CONFIG_SUITEB
108d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidtstatic int RSA_bits(const RSA *r)
109d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt{
110d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	return BN_num_bits(r->n);
111d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt}
112d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#endif /* CONFIG_SUITEB */
113d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#endif
114d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1153f3ca3bb849b192d41b99aae775f6fc52f67118dKenny Root#ifdef ANDROID
1163f3ca3bb849b192d41b99aae775f6fc52f67118dKenny Root#include <openssl/pem.h>
1173f3ca3bb849b192d41b99aae775f6fc52f67118dKenny Root#include <keystore/keystore_get.h>
1183f3ca3bb849b192d41b99aae775f6fc52f67118dKenny Root
1194d8552e9d137f0aab7d64e1476b7f892d0468aebPavel Grafov#include <log/log.h>
1204d8552e9d137f0aab7d64e1476b7f892d0468aebPavel Grafov#include <log/log_event_list.h>
1214d8552e9d137f0aab7d64e1476b7f892d0468aebPavel Grafov
1224d8552e9d137f0aab7d64e1476b7f892d0468aebPavel Grafov#define CERT_VALIDATION_FAILURE 210033
1234d8552e9d137f0aab7d64e1476b7f892d0468aebPavel Grafov
1244d8552e9d137f0aab7d64e1476b7f892d0468aebPavel Grafovstatic void log_cert_validation_failure(const char *reason)
1254d8552e9d137f0aab7d64e1476b7f892d0468aebPavel Grafov{
1264d8552e9d137f0aab7d64e1476b7f892d0468aebPavel Grafov	android_log_context ctx = create_android_logger(CERT_VALIDATION_FAILURE);
1274d8552e9d137f0aab7d64e1476b7f892d0468aebPavel Grafov	android_log_write_string8(ctx, reason);
1284d8552e9d137f0aab7d64e1476b7f892d0468aebPavel Grafov	android_log_write_list(ctx, LOG_ID_SECURITY);
1294d8552e9d137f0aab7d64e1476b7f892d0468aebPavel Grafov	android_log_destroy(&ctx);
1304d8552e9d137f0aab7d64e1476b7f892d0468aebPavel Grafov}
1314d8552e9d137f0aab7d64e1476b7f892d0468aebPavel Grafov
1324d8552e9d137f0aab7d64e1476b7f892d0468aebPavel Grafov
1333f3ca3bb849b192d41b99aae775f6fc52f67118dKenny Rootstatic BIO * BIO_from_keystore(const char *key)
1343f3ca3bb849b192d41b99aae775f6fc52f67118dKenny Root{
135ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt	BIO *bio = NULL;
136ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt	uint8_t *value = NULL;
137ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt	int length = keystore_get(key, strlen(key), &value);
138ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt	if (length != -1 && (bio = BIO_new(BIO_s_mem())) != NULL)
139ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt		BIO_write(bio, value, length);
140ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt	free(value);
141ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt	return bio;
1423f3ca3bb849b192d41b99aae775f6fc52f67118dKenny Root}
143b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt
144b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt
145b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidtstatic int tls_add_ca_from_keystore(X509_STORE *ctx, const char *key_alias)
146b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt{
147b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	BIO *bio = BIO_from_keystore(key_alias);
148b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	STACK_OF(X509_INFO) *stack = NULL;
149b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	stack_index_t i;
150b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt
151b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	if (bio) {
152b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
153b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		BIO_free(bio);
154b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	}
155b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt
156b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	if (!stack) {
157b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		wpa_printf(MSG_WARNING, "TLS: Failed to parse certificate: %s",
158b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			   key_alias);
159b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		return -1;
160b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	}
161b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt
162b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	for (i = 0; i < sk_X509_INFO_num(stack); ++i) {
163b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		X509_INFO *info = sk_X509_INFO_value(stack, i);
164b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt
165b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		if (info->x509)
166b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			X509_STORE_add_cert(ctx, info->x509);
167b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		if (info->crl)
168b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			X509_STORE_add_crl(ctx, info->crl);
169b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	}
170b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt
171b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	sk_X509_INFO_pop_free(stack, X509_INFO_free);
172b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt
173b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	return 0;
174b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt}
175b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt
176b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt
177b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidtstatic int tls_add_ca_from_keystore_encoded(X509_STORE *ctx,
178b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt					    const char *encoded_key_alias)
179b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt{
180b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	int rc = -1;
181b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	int len = os_strlen(encoded_key_alias);
182b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	unsigned char *decoded_alias;
183b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt
184b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	if (len & 1) {
185b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		wpa_printf(MSG_WARNING, "Invalid hex-encoded alias: %s",
186b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			   encoded_key_alias);
187b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		return rc;
188b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	}
189b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt
190b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	decoded_alias = os_malloc(len / 2 + 1);
191b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	if (decoded_alias) {
192b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		if (!hexstr2bin(encoded_key_alias, decoded_alias, len / 2)) {
193b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			decoded_alias[len / 2] = '\0';
194b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			rc = tls_add_ca_from_keystore(
195b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt				ctx, (const char *) decoded_alias);
196b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		}
197b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		os_free(decoded_alias);
198b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	}
199b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt
200b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	return rc;
201b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt}
202b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt
2033f3ca3bb849b192d41b99aae775f6fc52f67118dKenny Root#endif /* ANDROID */
2043f3ca3bb849b192d41b99aae775f6fc52f67118dKenny Root
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_openssl_ref_count = 0;
206d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int tls_ex_idx_session = -1;
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
208ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidtstruct tls_context {
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void (*event_cb)(void *ctx, enum tls_event ev,
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 union tls_event_data *data);
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *cb_ctx;
2121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int cert_in_cb;
21334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	char *ocsp_stapling_response;
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
216ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidtstatic struct tls_context *tls_global = NULL;
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
219d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstruct tls_data {
220d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_CTX *ssl;
221d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	unsigned int tls_session_lifetime;
222d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt};
223d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct tls_connection {
225ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	struct tls_context *context;
226216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	SSL_CTX *ssl_ctx;
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL *ssl;
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BIO *ssl_in, *ssl_out;
2291eb02edb319d462031f0c2f1f3548498558e95a5Adam Langley#if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE)
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ENGINE *engine;        /* functional reference to the engine */
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EVP_PKEY *private_key; /* the private key if using engine */
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
2332f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	char *subject_match, *altsubject_match, *suffix_match, *domain_match;
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int read_alerts, write_alerts, failed;
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_session_ticket_cb session_ticket_cb;
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *session_ticket_cb_ctx;
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* SessionTicket received from OpenSSL hello_extension_cb (server) */
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *session_ticket;
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t session_ticket_len;
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int ca_cert_verify:1;
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int cert_probe:1;
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int server_cert_only:1;
24626af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen	unsigned int invalid_hb_used:1;
247d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	unsigned int success_data:1;
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 srv_cert_hash[32];
250c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
251c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	unsigned int flags;
25234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
25334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	X509 *peer_cert;
25434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	X509 *peer_issuer;
255fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	X509 *peer_issuer_issuer;
256d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
257d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	unsigned char client_random[SSL3_RANDOM_SIZE];
258d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	unsigned char server_random[SSL3_RANDOM_SIZE];
259d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
260d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	u16 cipher_suite;
261d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	int server_dh_prime_len;
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
265ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidtstatic struct tls_context * tls_context_new(const struct tls_config *conf)
266ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt{
267ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	struct tls_context *context = os_zalloc(sizeof(*context));
268ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	if (context == NULL)
269ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		return NULL;
270ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	if (conf) {
271ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		context->event_cb = conf->event_cb;
272ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		context->cb_ctx = conf->cb_ctx;
273ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		context->cert_in_cb = conf->cert_in_cb;
274ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	}
275ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	return context;
276ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt}
277ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt
278ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_NO_STDOUT_DEBUG
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void _tls_show_errors(void)
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned long err;
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while ((err = ERR_get_error())) {
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Just ignore the errors, since stdout is disabled */
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define tls_show_errors(l, f, t) _tls_show_errors()
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_NO_STDOUT_DEBUG */
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void tls_show_errors(int level, const char *func, const char *txt)
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned long err;
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(level, "OpenSSL: %s - %s %s",
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   func, txt, ERR_error_string(ERR_get_error(), NULL));
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while ((err = ERR_get_error())) {
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "OpenSSL: pending error: %s",
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(err, NULL));
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_NATIVE_WINDOWS
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Windows CryptoAPI and access to certificate stores */
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <wincrypt.h>
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef __MINGW32_VERSION
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * MinGW does not yet include all the needed definitions for CryptoAPI, so
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * define here whatever extra is needed.
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define CERT_SYSTEM_STORE_CURRENT_USER (1 << 16)
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define CERT_STORE_READONLY_FLAG 0x00008000
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __MINGW32_VERSION */
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct cryptoapi_rsa_data {
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const CERT_CONTEXT *cert;
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTPROV crypt_prov;
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD key_spec;
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BOOL free_crypt_prov;
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void cryptoapi_error(const char *msg)
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_INFO, "CryptoAPI: %s; err=%u",
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   msg, (unsigned int) GetLastError());
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int cryptoapi_rsa_pub_enc(int flen, const unsigned char *from,
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 unsigned char *to, RSA *rsa, int padding)
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int cryptoapi_rsa_pub_dec(int flen, const unsigned char *from,
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 unsigned char *to, RSA *rsa, int padding)
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int cryptoapi_rsa_priv_enc(int flen, const unsigned char *from,
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  unsigned char *to, RSA *rsa, int padding)
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct cryptoapi_rsa_data *priv =
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		(struct cryptoapi_rsa_data *) rsa->meth->app_data;
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTHASH hash;
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD hash_size, len, i;
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char *buf = NULL;
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 0;
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv == NULL) {
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       ERR_R_PASSED_NULL_PARAMETER);
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (padding != RSA_PKCS1_PADDING) {
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       RSA_R_UNKNOWN_PADDING_TYPE);
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (flen != 16 /* MD5 */ + 20 /* SHA-1 */) {
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "%s - only MD5-SHA1 hash supported",
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__);
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       RSA_R_INVALID_MESSAGE_LENGTH);
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptCreateHash(priv->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash))
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_error("CryptCreateHash failed");
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = sizeof(hash_size);
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptGetHashParam(hash, HP_HASHSIZE, (BYTE *) &hash_size, &len,
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       0)) {
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_error("CryptGetHashParam failed");
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((int) hash_size != flen) {
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "CryptoAPI: Invalid hash size (%u != %d)",
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned) hash_size, flen);
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       RSA_R_INVALID_MESSAGE_LENGTH);
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptSetHashParam(hash, HP_HASHVAL, (BYTE * ) from, 0)) {
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_error("CryptSetHashParam failed");
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = RSA_size(rsa);
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_malloc(len);
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL) {
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptSignHash(hash, priv->key_spec, NULL, 0, buf, &len)) {
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_error("CryptSignHash failed");
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < len; i++)
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		to[i] = buf[len - i - 1];
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = len;
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterr:
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CryptDestroyHash(hash);
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int cryptoapi_rsa_priv_dec(int flen, const unsigned char *from,
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  unsigned char *to, RSA *rsa, int padding)
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void cryptoapi_free_data(struct cryptoapi_rsa_data *priv)
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv == NULL)
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->crypt_prov && priv->free_crypt_prov)
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CryptReleaseContext(priv->crypt_prov, 0);
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->cert)
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CertFreeCertificateContext(priv->cert);
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(priv);
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int cryptoapi_finish(RSA *rsa)
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cryptoapi_free_data((struct cryptoapi_rsa_data *) rsa->meth->app_data);
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free((void *) rsa->meth);
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa->meth = NULL;
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 1;
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const CERT_CONTEXT * cryptoapi_find_cert(const char *name, DWORD store)
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCERTSTORE cs;
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const CERT_CONTEXT *ret = NULL;
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0,
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   store | CERT_STORE_OPEN_EXISTING_FLAG |
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   CERT_STORE_READONLY_FLAG, L"MY");
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cs == NULL) {
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_error("Failed to open 'My system store'");
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (strncmp(name, "cert://", 7) == 0) {
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unsigned short wbuf[255];
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MultiByteToWideChar(CP_ACP, 0, name + 7, -1, wbuf, 255);
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = CertFindCertificateInStore(cs, X509_ASN_ENCODING |
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 PKCS_7_ASN_ENCODING,
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 0, CERT_FIND_SUBJECT_STR,
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 wbuf, NULL);
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (strncmp(name, "hash://", 7) == 0) {
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CRYPT_HASH_BLOB blob;
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int len;
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const char *hash = name + 7;
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unsigned char *buf;
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = os_strlen(hash) / 2;
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf = os_malloc(len);
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (buf && hexstr2bin(hash, buf, len) == 0) {
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			blob.cbData = len;
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			blob.pbData = buf;
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = CertFindCertificateInStore(cs,
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							 X509_ASN_ENCODING |
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							 PKCS_7_ASN_ENCODING,
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							 0, CERT_FIND_HASH,
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							 &blob, NULL);
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CertCloseStore(cs, 0);
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_cryptoapi_cert(SSL *ssl, const char *name)
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509 *cert = NULL;
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RSA *rsa = NULL, *pub_rsa;
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct cryptoapi_rsa_data *priv;
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RSA_METHOD *rsa_meth;
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (name == NULL ||
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (strncmp(name, "cert://", 7) != 0 &&
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     strncmp(name, "hash://", 7) != 0))
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	priv = os_zalloc(sizeof(*priv));
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_meth = os_zalloc(sizeof(*rsa_meth));
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv == NULL || rsa_meth == NULL) {
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "CryptoAPI: Failed to allocate memory "
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "for CryptoAPI RSA method");
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(priv);
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(rsa_meth);
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	priv->cert = cryptoapi_find_cert(name, CERT_SYSTEM_STORE_CURRENT_USER);
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->cert == NULL) {
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		priv->cert = cryptoapi_find_cert(
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			name, CERT_SYSTEM_STORE_LOCAL_MACHINE);
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->cert == NULL) {
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "CryptoAPI: Could not find certificate "
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "'%s'", name);
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
544216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	cert = d2i_X509(NULL,
545216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			(const unsigned char **) &priv->cert->pbCertEncoded,
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			priv->cert->cbCertEncoded);
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cert == NULL) {
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "CryptoAPI: Could not process X509 DER "
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "encoding");
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptAcquireCertificatePrivateKey(priv->cert,
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       NULL, &priv->crypt_prov,
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       &priv->key_spec,
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       &priv->free_crypt_prov)) {
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_error("Failed to acquire a private key for the "
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"certificate");
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_meth->name = "Microsoft CryptoAPI RSA Method";
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_meth->rsa_pub_enc = cryptoapi_rsa_pub_enc;
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_meth->rsa_pub_dec = cryptoapi_rsa_pub_dec;
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_meth->rsa_priv_enc = cryptoapi_rsa_priv_enc;
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_meth->rsa_priv_dec = cryptoapi_rsa_priv_dec;
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_meth->finish = cryptoapi_finish;
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_meth->flags = RSA_METHOD_FLAG_NO_CHECK;
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_meth->app_data = (char *) priv;
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa = RSA_new();
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rsa == NULL) {
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       ERR_R_MALLOC_FAILURE);
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!SSL_use_certificate(ssl, cert)) {
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSA_free(rsa);
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rsa = NULL;
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pub_rsa = cert->cert_info->key->pkey->pkey.rsa;
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509_free(cert);
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cert = NULL;
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa->n = BN_dup(pub_rsa->n);
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa->e = BN_dup(pub_rsa->e);
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!RSA_set_method(rsa, rsa_meth))
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!SSL_use_RSAPrivateKey(ssl, rsa))
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RSA_free(rsa);
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterr:
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cert)
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509_free(cert);
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rsa)
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSA_free(rsa);
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(rsa_meth);
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_free_data(priv);
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_cryptoapi_ca_cert(SSL_CTX *ssl_ctx, SSL *ssl, const char *name)
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCERTSTORE cs;
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PCCERT_CONTEXT ctx = NULL;
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509 *cert;
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[128];
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *store;
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef UNICODE
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WCHAR *wstore;
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* UNICODE */
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (name == NULL || strncmp(name, "cert_store://", 13) != 0)
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	store = name + 13;
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef UNICODE
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wstore = os_malloc((os_strlen(store) + 1) * sizeof(WCHAR));
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wstore == NULL)
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wsprintf(wstore, L"%S", store);
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cs = CertOpenSystemStore(0, wstore);
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(wstore);
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* UNICODE */
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cs = CertOpenSystemStore(0, store);
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* UNICODE */
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cs == NULL) {
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: failed to open system cert store "
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "'%s': error=%d", __func__, store,
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while ((ctx = CertEnumCertificatesInStore(cs, ctx))) {
645216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		cert = d2i_X509(NULL,
646216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				(const unsigned char **) &ctx->pbCertEncoded,
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				ctx->cbCertEncoded);
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cert == NULL) {
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "CryptoAPI: Could not process "
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "X509 DER encoding for CA cert");
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509_NAME_oneline(X509_get_subject_name(cert), buf,
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sizeof(buf));
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Loaded CA certificate for "
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "system certificate store: subject='%s'", buf);
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
659849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt		if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(ssl_ctx),
660849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt					 cert)) {
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_WARNING, __func__,
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"Failed to add ca_cert to OpenSSL "
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"certificate store");
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509_free(cert);
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CertCloseStore(cs, 0)) {
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: failed to close system cert store "
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "'%s': error=%d", __func__, name + 13,
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_NATIVE_WINDOWS */
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_cryptoapi_cert(SSL *ssl, const char *name)
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ssl_info_cb(const SSL *ssl, int where, int ret)
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *str;
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int w;
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "SSL: (where=0x%x ret=0x%x)", where, ret);
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	w = where & ~SSL_ST_MASK;
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (w & SSL_ST_CONNECT)
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		str = "SSL_connect";
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (w & SSL_ST_ACCEPT)
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		str = "SSL_accept";
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		str = "undefined";
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (where & SSL_CB_LOOP) {
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: %s:%s",
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   str, SSL_state_string_long(ssl));
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (where & SSL_CB_ALERT) {
707ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		struct tls_connection *conn = SSL_get_app_data((SSL *) ssl);
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "SSL: SSL3 alert: %s:%s:%s",
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   where & SSL_CB_READ ?
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "read (remote end reported an error)" :
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "write (local SSL3 detected an error)",
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   SSL_alert_type_string_long(ret),
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   SSL_alert_desc_string_long(ret));
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((ret >> 8) == SSL3_AL_FATAL) {
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (where & SSL_CB_READ)
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				conn->read_alerts++;
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				conn->write_alerts++;
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
720ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		if (conn->context->event_cb != NULL) {
72104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			union tls_event_data ev;
722ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt			struct tls_context *context = conn->context;
72304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			os_memset(&ev, 0, sizeof(ev));
72404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			ev.alert.is_local = !(where & SSL_CB_READ);
72504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			ev.alert.type = SSL_alert_type_string_long(ret);
72604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			ev.alert.description = SSL_alert_desc_string_long(ret);
727ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt			context->event_cb(context->cb_ctx, TLS_ALERT, &ev);
72804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (where & SSL_CB_EXIT && ret <= 0) {
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s",
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   str, ret == 0 ? "failed" : "error",
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   SSL_state_string_long(ssl));
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tls_engine_load_dynamic_generic - load any openssl engine
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pre: an array of commands and values that load an engine initialized
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *       in the engine specific function
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @post: an array of commands and values that initialize an already loaded
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *        engine (or %NULL if not required)
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @id: the engine id of the engine to load (only required if post is not %NULL
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is a generic function that loads any openssl engine.
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_engine_load_dynamic_generic(const char *pre[],
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   const char *post[], const char *id)
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ENGINE *engine;
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *dynamic_id = "dynamic";
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	engine = ENGINE_by_id(id);
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (engine) {
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "ENGINE: engine '%s' is already "
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "available", id);
760d5ab1b53af720d05586ccc0addabe93459f1f388Dmitry Shmidt		/*
761d5ab1b53af720d05586ccc0addabe93459f1f388Dmitry Shmidt		 * If it was auto-loaded by ENGINE_by_id() we might still
762d5ab1b53af720d05586ccc0addabe93459f1f388Dmitry Shmidt		 * need to tell it which PKCS#11 module to use in legacy
763d5ab1b53af720d05586ccc0addabe93459f1f388Dmitry Shmidt		 * (non-p11-kit) environments. Do so now; even if it was
764d5ab1b53af720d05586ccc0addabe93459f1f388Dmitry Shmidt		 * properly initialised before, setting it again will be
765d5ab1b53af720d05586ccc0addabe93459f1f388Dmitry Shmidt		 * harmless.
766d5ab1b53af720d05586ccc0addabe93459f1f388Dmitry Shmidt		 */
767d5ab1b53af720d05586ccc0addabe93459f1f388Dmitry Shmidt		goto found;
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ERR_clear_error();
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	engine = ENGINE_by_id(dynamic_id);
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (engine == NULL) {
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]",
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   dynamic_id,
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(ERR_get_error(), NULL));
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Perform the pre commands. This will load the engine. */
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pre && pre[0]) {
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", pre[0], pre[1]);
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ENGINE_ctrl_cmd_string(engine, pre[0], pre[1], 0) == 0) {
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "ENGINE: ctrl cmd_string failed: "
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "%s %s [%s]", pre[0], pre[1],
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   ERR_error_string(ERR_get_error(), NULL));
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ENGINE_free(engine);
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pre += 2;
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Free the reference to the "dynamic" engine. The loaded engine can
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * now be looked up using ENGINE_by_id().
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ENGINE_free(engine);
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	engine = ENGINE_by_id(id);
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (engine == NULL) {
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]",
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   id, ERR_error_string(ERR_get_error(), NULL));
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
804d5ab1b53af720d05586ccc0addabe93459f1f388Dmitry Shmidt found:
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (post && post[0]) {
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", post[0], post[1]);
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ENGINE_ctrl_cmd_string(engine, post[0], post[1], 0) == 0) {
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "ENGINE: ctrl cmd_string failed:"
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" %s %s [%s]", post[0], post[1],
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   ERR_error_string(ERR_get_error(), NULL));
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ENGINE_remove(engine);
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ENGINE_free(engine);
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		post += 2;
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ENGINE_free(engine);
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tls_engine_load_dynamic_pkcs11 - load the pkcs11 engine provided by opensc
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pkcs11_so_path: pksc11_so_path from the configuration
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pcks11_module_path: pkcs11_module_path from the configuration
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_engine_load_dynamic_pkcs11(const char *pkcs11_so_path,
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const char *pkcs11_module_path)
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *engine_id = "pkcs11";
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *pre_cmd[] = {
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"SO_PATH", NULL /* pkcs11_so_path */,
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"ID", NULL /* engine_id */,
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"LIST_ADD", "1",
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* "NO_VCHECK", "1", */
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"LOAD", NULL,
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NULL, NULL
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	};
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *post_cmd[] = {
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"MODULE_PATH", NULL /* pkcs11_module_path */,
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NULL, NULL
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	};
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!pkcs11_so_path)
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pre_cmd[1] = pkcs11_so_path;
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pre_cmd[3] = engine_id;
8506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (pkcs11_module_path)
8516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		post_cmd[1] = pkcs11_module_path;
8526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	else
8536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		post_cmd[0] = NULL;
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "ENGINE: Loading pkcs11 Engine from %s",
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   pkcs11_so_path);
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return tls_engine_load_dynamic_generic(pre_cmd, post_cmd, engine_id);
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tls_engine_load_dynamic_opensc - load the opensc engine provided by opensc
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @opensc_so_path: opensc_so_path from the configuration
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_engine_load_dynamic_opensc(const char *opensc_so_path)
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *engine_id = "opensc";
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *pre_cmd[] = {
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"SO_PATH", NULL /* opensc_so_path */,
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"ID", NULL /* engine_id */,
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"LIST_ADD", "1",
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"LOAD", NULL,
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NULL, NULL
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	};
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!opensc_so_path)
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pre_cmd[1] = opensc_so_path;
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pre_cmd[3] = engine_id;
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "ENGINE: Loading OpenSC Engine from %s",
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   opensc_so_path);
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return tls_engine_load_dynamic_generic(pre_cmd, NULL, engine_id);
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
891d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic void remove_session_cb(SSL_CTX *ctx, SSL_SESSION *sess)
892d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
893d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct wpabuf *buf;
894d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
895d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (tls_ex_idx_session < 0)
896d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return;
897d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	buf = SSL_SESSION_get_ex_data(sess, tls_ex_idx_session);
898d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!buf)
899d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return;
900d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_printf(MSG_DEBUG,
901d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		   "OpenSSL: Free application session data %p (sess %p)",
902d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		   buf, sess);
903d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpabuf_free(buf);
904d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
905d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_SESSION_set_ex_data(sess, tls_ex_idx_session, NULL);
906d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
907d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
908d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * tls_init(const struct tls_config *conf)
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
911d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct tls_data *data;
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX *ssl;
913ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	struct tls_context *context;
9146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	const char *ciphers;
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_openssl_ref_count == 0) {
917ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		tls_global = context = tls_context_new(conf);
918ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		if (context == NULL)
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_FIPS
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef OPENSSL_FIPS
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conf && conf->fips_mode) {
923d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			static int fips_enabled = 0;
924d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
925d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			if (!fips_enabled && !FIPS_mode_set(1)) {
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_ERROR, "Failed to enable FIPS "
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "mode");
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				ERR_load_crypto_strings();
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				ERR_print_errors_fp(stderr);
93061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				os_free(tls_global);
93161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				tls_global = NULL;
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
933d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			} else {
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_INFO, "Running in FIPS mode");
935d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				fips_enabled = 1;
936d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			}
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_FIPS */
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conf && conf->fips_mode) {
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "FIPS mode requested, but not "
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "supported");
94261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			os_free(tls_global);
94361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			tls_global = NULL;
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_FIPS */
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_FIPS */
9489839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_load_error_strings();
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_library_init();
951216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt#ifndef OPENSSL_NO_SHA256
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EVP_add_digest(EVP_sha256());
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_SHA256 */
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: if /dev/urandom is available, PRNG is seeded
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * automatically. If this is not the case, random data should
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * be added here. */
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PKCS12_FUNCS
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_RC2
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * 40-bit RC2 is commonly used in PKCS#12 files, so enable it.
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * This is enabled by PKCS12_PBE_add() in OpenSSL 0.9.8
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * versions, but it looks like OpenSSL 1.0.0 does not do that
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * anymore.
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EVP_add_cipher(EVP_rc2_40_cbc());
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_RC2 */
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		PKCS12_PBE_add();
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif  /* PKCS12_FUNCS */
97057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt#endif /* < 1.1.0 */
971ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	} else {
972ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		context = tls_context_new(conf);
973ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		if (context == NULL)
974ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt			return NULL;
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_openssl_ref_count++;
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
978d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	data = os_zalloc(sizeof(*data));
979d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (data)
980d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ssl = SSL_CTX_new(SSLv23_method());
981d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	else
982d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ssl = NULL;
983ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	if (ssl == NULL) {
984ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		tls_openssl_ref_count--;
98568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		if (context != tls_global)
98668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt			os_free(context);
987ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		if (tls_openssl_ref_count == 0) {
988ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt			os_free(tls_global);
989ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt			tls_global = NULL;
990ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		}
99157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		os_free(data);
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
993ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	}
994d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	data->ssl = ssl;
995d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (conf)
996d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		data->tls_session_lifetime = conf->tls_session_lifetime;
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv2);
9996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv3);
10006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1001293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt#ifdef SSL_MODE_NO_AUTO_CHAIN
1002293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	/* Number of deployed use cases assume the default OpenSSL behavior of
1003293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	 * auto chaining the local certificate is in use. BoringSSL removed this
1004293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	 * functionality by default, so we need to restore it here to avoid
1005293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	 * breaking existing use cases. */
1006293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	SSL_CTX_clear_mode(ssl, SSL_MODE_NO_AUTO_CHAIN);
1007293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt#endif /* SSL_MODE_NO_AUTO_CHAIN */
1008293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX_set_info_callback(ssl, ssl_info_cb);
1010ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	SSL_CTX_set_app_data(ssl, context);
1011d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (data->tls_session_lifetime > 0) {
1012d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_CTX_set_quiet_shutdown(ssl, 1);
1013d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		/*
1014d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		 * Set default context here. In practice, this will be replaced
1015d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		 * by the per-EAP method context in tls_connection_set_verify().
1016d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		 */
1017d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_CTX_set_session_id_context(ssl, (u8 *) "hostapd", 7);
1018d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_CTX_set_session_cache_mode(ssl, SSL_SESS_CACHE_SERVER);
1019d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_CTX_set_timeout(ssl, data->tls_session_lifetime);
1020d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_CTX_sess_set_remove_cb(ssl, remove_session_cb);
1021d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else {
1022d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_CTX_set_session_cache_mode(ssl, SSL_SESS_CACHE_OFF);
1023d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
1024d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1025d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (tls_ex_idx_session < 0) {
1026d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		tls_ex_idx_session = SSL_SESSION_get_ex_new_index(
1027d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			0, NULL, NULL, NULL, NULL);
1028d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (tls_ex_idx_session < 0) {
1029d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			tls_deinit(data);
1030d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return NULL;
1031d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
1032d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
10356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_printf(MSG_DEBUG, "ENGINE: Loading dynamic engine");
10366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	ERR_load_ENGINE_strings();
10376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	ENGINE_load_dynamic();
10386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf &&
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (conf->opensc_engine_path || conf->pkcs11_engine_path ||
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     conf->pkcs11_module_path)) {
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_engine_load_dynamic_opensc(conf->opensc_engine_path) ||
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    tls_engine_load_dynamic_pkcs11(conf->pkcs11_engine_path,
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   conf->pkcs11_module_path)) {
1045d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			tls_deinit(data);
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (conf && conf->openssl_ciphers)
10526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		ciphers = conf->openssl_ciphers;
10536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	else
1054d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		ciphers = TLS_DEFAULT_CIPHERS;
10556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (SSL_CTX_set_cipher_list(ssl, ciphers) != 1) {
10566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_ERROR,
10576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "OpenSSL: Failed to set cipher string '%s'",
10586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   ciphers);
1059d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		tls_deinit(data);
10606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return NULL;
10616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
10626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1063d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return data;
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tls_deinit(void *ssl_ctx)
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1069d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct tls_data *data = ssl_ctx;
1070d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_CTX *ssl = data->ssl;
1071ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	struct tls_context *context = SSL_CTX_get_app_data(ssl);
1072ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	if (context != tls_global)
1073ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		os_free(context);
1074d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (data->tls_session_lifetime > 0)
1075d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_CTX_flush_sessions(ssl, 0);
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX_free(ssl);
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_openssl_ref_count--;
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_openssl_ref_count == 0) {
10809839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ENGINE_cleanup();
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CRYPTO_cleanup_all_ex_data();
10859ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt		ERR_remove_thread_state(NULL);
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ERR_free_strings();
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EVP_cleanup();
108857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt#endif /* < 1.1.0 */
108934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		os_free(tls_global->ocsp_stapling_response);
109034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		tls_global->ocsp_stapling_response = NULL;
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(tls_global);
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_global = NULL;
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1094d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1095d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_free(data);
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10991d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
11001d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt
11011d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt/* Cryptoki return values */
11021d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt#define CKR_PIN_INCORRECT 0x000000a0
11031d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt#define CKR_PIN_INVALID 0x000000a1
11041d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt#define CKR_PIN_LEN_RANGE 0x000000a2
11051d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt
11061d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt/* libp11 */
11071d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt#define ERR_LIB_PKCS11	ERR_LIB_USER
11081d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt
11091d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtstatic int tls_is_pin_error(unsigned int err)
11101d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt{
11111d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt	return ERR_GET_LIB(err) == ERR_LIB_PKCS11 &&
11121d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt		(ERR_GET_REASON(err) == CKR_PIN_INCORRECT ||
11131d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt		 ERR_GET_REASON(err) == CKR_PIN_INVALID ||
11141d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt		 ERR_GET_REASON(err) == CKR_PIN_LEN_RANGE);
11151d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt}
11161d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt
11171d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
11181d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt
11191d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt
1120d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef ANDROID
1121d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/* EVP_PKEY_from_keystore comes from system/security/keystore-engine. */
1122d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry ShmidtEVP_PKEY * EVP_PKEY_from_keystore(const char *key_id);
1123d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* ANDROID */
1124d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_engine_init(struct tls_connection *conn, const char *engine_id,
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   const char *pin, const char *key_id,
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   const char *cert_id, const char *ca_cert_id)
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11291eb02edb319d462031f0c2f1f3548498558e95a5Adam Langley#if defined(ANDROID) && defined(OPENSSL_IS_BORINGSSL)
11301eb02edb319d462031f0c2f1f3548498558e95a5Adam Langley#if !defined(OPENSSL_NO_ENGINE)
11311eb02edb319d462031f0c2f1f3548498558e95a5Adam Langley#error "This code depends on OPENSSL_NO_ENGINE being defined by BoringSSL."
11321eb02edb319d462031f0c2f1f3548498558e95a5Adam Langley#endif
1133d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!key_id)
1134d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
11351eb02edb319d462031f0c2f1f3548498558e95a5Adam Langley	conn->engine = NULL;
11361eb02edb319d462031f0c2f1f3548498558e95a5Adam Langley	conn->private_key = EVP_PKEY_from_keystore(key_id);
11371eb02edb319d462031f0c2f1f3548498558e95a5Adam Langley	if (!conn->private_key) {
11381eb02edb319d462031f0c2f1f3548498558e95a5Adam Langley		wpa_printf(MSG_ERROR,
11391eb02edb319d462031f0c2f1f3548498558e95a5Adam Langley			   "ENGINE: cannot load private key with id '%s' [%s]",
11401eb02edb319d462031f0c2f1f3548498558e95a5Adam Langley			   key_id,
11411eb02edb319d462031f0c2f1f3548498558e95a5Adam Langley			   ERR_error_string(ERR_get_error(), NULL));
11421eb02edb319d462031f0c2f1f3548498558e95a5Adam Langley		return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
11431eb02edb319d462031f0c2f1f3548498558e95a5Adam Langley	}
1144d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* ANDROID && OPENSSL_IS_BORINGSSL */
11451eb02edb319d462031f0c2f1f3548498558e95a5Adam Langley
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = -1;
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (engine_id == NULL) {
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "ENGINE: Engine ID not set");
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ERR_clear_error();
1154db3c5a43353099fd4771f3b7a13efae905878ce9Kenny Root#ifdef ANDROID
1155db3c5a43353099fd4771f3b7a13efae905878ce9Kenny Root	ENGINE_load_dynamic();
1156db3c5a43353099fd4771f3b7a13efae905878ce9Kenny Root#endif
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->engine = ENGINE_by_id(engine_id);
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!conn->engine) {
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "ENGINE: engine %s not available [%s]",
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   engine_id, ERR_error_string(ERR_get_error(), NULL));
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ENGINE_init(conn->engine) != 1) {
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "ENGINE: engine init failed "
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(engine: %s) [%s]", engine_id,
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(ERR_get_error(), NULL));
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "ENGINE: engine initialized");
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1171db3c5a43353099fd4771f3b7a13efae905878ce9Kenny Root#ifndef ANDROID
11726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (pin && ENGINE_ctrl_cmd_string(conn->engine, "PIN", pin, 0) == 0) {
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "ENGINE: cannot set pin [%s]",
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(ERR_get_error(), NULL));
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1177db3c5a43353099fd4771f3b7a13efae905878ce9Kenny Root#endif
11786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (key_id) {
11796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		/*
11806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * Ensure that the ENGINE does not attempt to use the OpenSSL
11816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * UI system to obtain a PIN, if we didn't provide one.
11826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 */
11836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		struct {
11846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			const void *password;
11856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			const char *prompt_info;
11866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		} key_cb = { "", NULL };
11876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
11886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		/* load private key first in-case PIN is required for cert */
11896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		conn->private_key = ENGINE_load_private_key(conn->engine,
11906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt							    key_id, NULL,
11916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt							    &key_cb);
11926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (!conn->private_key) {
11931d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt			unsigned long err = ERR_get_error();
11941d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt
11956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			wpa_printf(MSG_ERROR,
11966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				   "ENGINE: cannot load private key with id '%s' [%s]",
11976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				   key_id,
11981d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt				   ERR_error_string(err, NULL));
11991d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt			if (tls_is_pin_error(err))
12001d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt				ret = TLS_SET_PARAMS_ENGINE_PRV_BAD_PIN;
12011d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt			else
12021d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt				ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
12036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			goto err;
12046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		}
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* handle a certificate and/or CA certificate */
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cert_id || ca_cert_id) {
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const char *cmd_name = "LOAD_CERT_CTRL";
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* test if the engine supports a LOAD_CERT_CTRL */
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!ENGINE_ctrl(conn->engine, ENGINE_CTRL_GET_CMD_FROM_NAME,
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 0, (void *)cmd_name, NULL)) {
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "ENGINE: engine does not support"
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " loading certificates");
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto err;
12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterr:
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->engine) {
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ENGINE_free(conn->engine);
12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->engine = NULL;
12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->private_key) {
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EVP_PKEY_free(conn->private_key);
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->private_key = NULL;
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_ENGINE */
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void tls_engine_deinit(struct tls_connection *conn)
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12431eb02edb319d462031f0c2f1f3548498558e95a5Adam Langley#if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE)
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "ENGINE: engine deinit");
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->private_key) {
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EVP_PKEY_free(conn->private_key);
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->private_key = NULL;
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->engine) {
12501eb02edb319d462031f0c2f1f3548498558e95a5Adam Langley#if !defined(OPENSSL_IS_BORINGSSL)
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ENGINE_finish(conn->engine);
1252d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* !OPENSSL_IS_BORINGSSL */
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->engine = NULL;
12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1255d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* ANDROID || !OPENSSL_NO_ENGINE */
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_get_errors(void *ssl_ctx)
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int count = 0;
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned long err;
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while ((err = ERR_get_error())) {
12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS - SSL error: %s",
12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(err, NULL));
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		count++;
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return count;
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
127326af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen
1274d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic const char * openssl_content_type(int content_type)
1275d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
1276d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	switch (content_type) {
1277d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case 20:
1278d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "change cipher spec";
1279d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case 21:
1280d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "alert";
1281d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case 22:
1282d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "handshake";
1283d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case 23:
1284d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "application data";
1285d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case 24:
1286d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "heartbeat";
1287d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case 256:
1288d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "TLS header info"; /* pseudo content type */
1289d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	default:
1290d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "?";
1291d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
1292d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
1293d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1294d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1295d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic const char * openssl_handshake_type(int content_type, const u8 *buf,
1296d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					   size_t len)
1297d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
1298d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (content_type != 22 || !buf || len == 0)
1299d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "";
1300d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	switch (buf[0]) {
1301d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case 0:
1302d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "hello request";
1303d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case 1:
1304d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "client hello";
1305d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case 2:
1306d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "server hello";
1307d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case 4:
1308d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "new session ticket";
1309d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case 11:
1310d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "certificate";
1311d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case 12:
1312d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "server key exchange";
1313d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case 13:
1314d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "certificate request";
1315d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case 14:
1316d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "server hello done";
1317d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case 15:
1318d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "certificate verify";
1319d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case 16:
1320d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "client key exchange";
1321d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case 20:
1322d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "finished";
1323d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case 21:
1324d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "certificate url";
1325d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case 22:
1326d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "certificate status";
1327d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	default:
1328d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return "?";
1329d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
1330d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
1331d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1332d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1333d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#ifdef CONFIG_SUITEB
1334d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1335d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidtstatic void check_server_hello(struct tls_connection *conn,
1336d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			       const u8 *pos, const u8 *end)
1337d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt{
1338d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	size_t payload_len, id_len;
1339d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1340d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	/*
1341d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 * Parse ServerHello to get the selected cipher suite since OpenSSL does
1342d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 * not make it cleanly available during handshake and we need to know
1343d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 * whether DHE was selected.
1344d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 */
1345d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1346d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (end - pos < 3)
1347d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return;
1348d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	payload_len = WPA_GET_BE24(pos);
1349d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	pos += 3;
1350d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1351d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if ((size_t) (end - pos) < payload_len)
1352d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return;
1353d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	end = pos + payload_len;
1354d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1355d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	/* Skip Version and Random */
1356d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (end - pos < 2 + SSL3_RANDOM_SIZE)
1357d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return;
1358d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	pos += 2 + SSL3_RANDOM_SIZE;
1359d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1360d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	/* Skip Session ID */
1361d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (end - pos < 1)
1362d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return;
1363d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	id_len = *pos++;
1364d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if ((size_t) (end - pos) < id_len)
1365d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return;
1366d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	pos += id_len;
1367d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1368d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (end - pos < 2)
1369d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return;
1370d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	conn->cipher_suite = WPA_GET_BE16(pos);
1371d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: Server selected cipher suite 0x%x",
1372d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		   conn->cipher_suite);
1373d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt}
1374d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1375d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1376d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidtstatic void check_server_key_exchange(SSL *ssl, struct tls_connection *conn,
1377d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				      const u8 *pos, const u8 *end)
1378d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt{
1379d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	size_t payload_len;
1380d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	u16 dh_len;
1381d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	BIGNUM *p;
1382d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	int bits;
1383d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1384d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (!(conn->flags & TLS_CONN_SUITEB))
1385d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return;
1386d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1387d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	/* DHE is enabled only with DHE-RSA-AES256-GCM-SHA384 */
1388d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (conn->cipher_suite != 0x9f)
1389d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return;
1390d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1391d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (end - pos < 3)
1392d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return;
1393d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	payload_len = WPA_GET_BE24(pos);
1394d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	pos += 3;
1395d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1396d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if ((size_t) (end - pos) < payload_len)
1397d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return;
1398d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	end = pos + payload_len;
1399d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1400d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (end - pos < 2)
1401d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return;
1402d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	dh_len = WPA_GET_BE16(pos);
1403d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	pos += 2;
1404d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1405d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if ((size_t) (end - pos) < dh_len)
1406d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return;
1407d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	p = BN_bin2bn(pos, dh_len, NULL);
1408d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (!p)
1409d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return;
1410d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1411d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	bits = BN_num_bits(p);
1412d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	BN_free(p);
1413d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1414d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	conn->server_dh_prime_len = bits;
1415d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: Server DH prime length: %d bits",
1416d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		   conn->server_dh_prime_len);
1417d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt}
1418d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1419d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#endif /* CONFIG_SUITEB */
1420d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1421d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
142226af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinenstatic void tls_msg_cb(int write_p, int version, int content_type,
142326af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen		       const void *buf, size_t len, SSL *ssl, void *arg)
142426af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen{
142526af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen	struct tls_connection *conn = arg;
142626af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen	const u8 *pos = buf;
142726af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen
1428d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (write_p == 2) {
1429d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpa_printf(MSG_DEBUG,
1430d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   "OpenSSL: session ver=0x%x content_type=%d",
1431d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   version, content_type);
1432d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpa_hexdump_key(MSG_MSGDUMP, "OpenSSL: Data", buf, len);
1433d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return;
1434d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
1435d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1436d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: %s ver=0x%x content_type=%d (%s/%s)",
1437d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		   write_p ? "TX" : "RX", version, content_type,
1438d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		   openssl_content_type(content_type),
1439d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		   openssl_handshake_type(content_type, buf, len));
144026af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen	wpa_hexdump_key(MSG_MSGDUMP, "OpenSSL: Message", buf, len);
144126af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen	if (content_type == 24 && len >= 3 && pos[0] == 1) {
144226af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen		size_t payload_len = WPA_GET_BE16(pos + 1);
144326af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen		if (payload_len + 3 > len) {
144426af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen			wpa_printf(MSG_ERROR, "OpenSSL: Heartbeat attack detected");
144526af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen			conn->invalid_hb_used = 1;
144626af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen		}
144726af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen	}
1448d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1449d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#ifdef CONFIG_SUITEB
1450d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	/*
1451d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 * Need to parse these handshake messages to be able to check DH prime
1452d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 * length since OpenSSL does not expose the new cipher suite and DH
1453d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 * parameters during handshake (e.g., for cert_cb() callback).
1454d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 */
1455d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (content_type == 22 && pos && len > 0 && pos[0] == 2)
1456d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		check_server_hello(conn, pos + 1, pos + len);
1457d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (content_type == 22 && pos && len > 0 && pos[0] == 12)
1458d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		check_server_key_exchange(ssl, conn, pos + 1, pos + len);
1459d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#endif /* CONFIG_SUITEB */
146026af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen}
146126af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen
146226af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct tls_connection * tls_connection_init(void *ssl_ctx)
14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1465d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct tls_data *data = ssl_ctx;
1466d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_CTX *ssl = data->ssl;
14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_connection *conn;
14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	long options;
14697d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt	struct tls_context *context = SSL_CTX_get_app_data(ssl);
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn = os_zalloc(sizeof(*conn));
14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1474d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	conn->ssl_ctx = ssl;
14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->ssl = SSL_new(ssl);
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->ssl == NULL) {
14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to initialize new SSL connection");
14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(conn);
14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1483ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	conn->context = context;
14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_set_app_data(conn->ssl, conn);
148526af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen	SSL_set_msg_callback(conn->ssl, tls_msg_cb);
148626af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen	SSL_set_msg_callback_arg(conn->ssl, conn);
14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_OP_SINGLE_DH_USE;
14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef SSL_OP_NO_COMPRESSION
14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	options |= SSL_OP_NO_COMPRESSION;
14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* SSL_OP_NO_COMPRESSION */
14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_set_options(conn->ssl, options);
14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->ssl_in = BIO_new(BIO_s_mem());
14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!conn->ssl_in) {
14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to create a new BIO for ssl_in");
14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_free(conn->ssl);
14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(conn);
15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->ssl_out = BIO_new(BIO_s_mem());
15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!conn->ssl_out) {
15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to create a new BIO for ssl_out");
15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_free(conn->ssl);
15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		BIO_free(conn->ssl_in);
15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(conn);
15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_set_bio(conn->ssl, conn->ssl_in, conn->ssl_out);
15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return conn;
15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1523d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (conn->success_data) {
1524d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		/*
1525d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		 * Make sure ssl_clear_bad_session() does not remove this
1526d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		 * session.
1527d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		 */
1528d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_set_quiet_shutdown(conn->ssl, 1);
1529d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_shutdown(conn->ssl);
1530d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_free(conn->ssl);
15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_engine_deinit(conn);
15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->subject_match);
15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->altsubject_match);
1535051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	os_free(conn->suffix_match);
15362f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	os_free(conn->domain_match);
15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->session_ticket);
15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn);
15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return conn ? SSL_is_init_finished(conn->ssl) : 0;
15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Shutdown previous TLS connection without notifying the peer
15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * because the connection was already terminated in practice
15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * and "close notify" shutdown alert would confuse AS. */
15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_set_quiet_shutdown(conn->ssl, 1);
15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_shutdown(conn->ssl);
1558f291c682d490cef0b520b68e694a2bf97126b441Jouni Malinen	return SSL_clear(conn->ssl) == 1 ? 0 : -1;
15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_match_altsubject_component(X509 *cert, int type,
15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const char *value, size_t len)
15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	GENERAL_NAME *gen;
15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *ext;
15679ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt	int found = 0;
15689ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt	stack_index_t i;
15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gen = sk_GENERAL_NAME_value(ext, i);
15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (gen->type != type)
15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strlen((char *) gen->d.ia5->data) == len &&
15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(value, gen->d.ia5->data, len) == 0)
15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			found++;
15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
158157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
158257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return found;
15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_match_altsubject(X509 *cert, const char *match)
15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int type;
15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *pos, *end;
15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = match;
15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	do {
15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strncmp(pos, "EMAIL:", 6) == 0) {
15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			type = GEN_EMAIL;
15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 6;
15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (os_strncmp(pos, "DNS:", 4) == 0) {
15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			type = GEN_DNS;
16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 4;
16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (os_strncmp(pos, "URI:", 4) == 0) {
16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			type = GEN_URI;
16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 4;
16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "TLS: Invalid altSubjectName "
16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "match '%s'", pos);
16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = os_strchr(pos, ';');
16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (end) {
16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (os_strncmp(end + 1, "EMAIL:", 6) == 0 ||
16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    os_strncmp(end + 1, "DNS:", 4) == 0 ||
16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    os_strncmp(end + 1, "URI:", 4) == 0)
16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end = os_strchr(end + 1, ';');
16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end)
16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = end - pos;
16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = os_strlen(pos);
16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_match_altsubject_component(cert, type, pos, len) > 0)
16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1;
16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = end + 1;
16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} while (end);
16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1630fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
16312f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidtstatic int domain_suffix_match(const u8 *val, size_t len, const char *match,
16322f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			       int full)
1633051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{
1634051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	size_t i, match_len;
1635051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1636051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	/* Check for embedded nuls that could mess up suffix matching */
1637051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	for (i = 0; i < len; i++) {
1638051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		if (val[i] == '\0') {
1639051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLS: Embedded null in a string - reject");
1640051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			return 0;
1641051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		}
1642051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
1643051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1644051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	match_len = os_strlen(match);
16452f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	if (match_len > len || (full && match_len != len))
1646051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return 0;
1647051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1648051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (os_strncasecmp((const char *) val + len - match_len, match,
1649051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			   match_len) != 0)
1650051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return 0; /* no match */
1651051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1652051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (match_len == len)
1653051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return 1; /* exact match */
1654051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1655051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (val[len - match_len - 1] == '.')
1656051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return 1; /* full label match completes suffix match */
1657051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1658051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLS: Reject due to incomplete label match");
1659051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	return 0;
1660051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt}
1661fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
1662051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1663051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
16642f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidtstatic int tls_match_suffix(X509 *cert, const char *match, int full)
1665051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{
1666fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt#ifdef CONFIG_NATIVE_WINDOWS
1667fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	/* wincrypt.h has conflicting X509_NAME definition */
1668fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	return -1;
1669fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt#else /* CONFIG_NATIVE_WINDOWS */
1670051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	GENERAL_NAME *gen;
1671051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	void *ext;
1672051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	int i;
16739ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt	stack_index_t j;
1674051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	int dns_name = 0;
1675051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	X509_NAME *name;
1676051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
16772f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	wpa_printf(MSG_DEBUG, "TLS: Match domain against %s%s",
16782f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		   full ? "": "suffix ", match);
1679051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1680051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
1681051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
16829ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt	for (j = 0; ext && j < sk_GENERAL_NAME_num(ext); j++) {
16839ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt		gen = sk_GENERAL_NAME_value(ext, j);
1684051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		if (gen->type != GEN_DNS)
1685051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			continue;
1686051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		dns_name++;
1687051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate dNSName",
1688051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt				  gen->d.dNSName->data,
1689051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt				  gen->d.dNSName->length);
1690051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		if (domain_suffix_match(gen->d.dNSName->data,
16912f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt					gen->d.dNSName->length, match, full) ==
16922f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		    1) {
16932f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			wpa_printf(MSG_DEBUG, "TLS: %s in dNSName found",
16942f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt				   full ? "Match" : "Suffix match");
169557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt			sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
1696051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			return 1;
1697051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		}
1698051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
169957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
1700051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1701051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (dns_name) {
1702051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLS: None of the dNSName(s) matched");
1703051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return 0;
1704051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
1705051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1706051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	name = X509_get_subject_name(cert);
1707051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	i = -1;
1708051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	for (;;) {
1709051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		X509_NAME_ENTRY *e;
1710051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		ASN1_STRING *cn;
1711051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1712051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		i = X509_NAME_get_index_by_NID(name, NID_commonName, i);
1713051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		if (i == -1)
1714051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			break;
1715051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		e = X509_NAME_get_entry(name, i);
1716051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		if (e == NULL)
1717051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			continue;
1718051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		cn = X509_NAME_ENTRY_get_data(e);
1719051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		if (cn == NULL)
1720051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			continue;
1721051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate commonName",
1722051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt				  cn->data, cn->length);
17232f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		if (domain_suffix_match(cn->data, cn->length, match, full) == 1)
17242f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		{
17252f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			wpa_printf(MSG_DEBUG, "TLS: %s in commonName found",
17262f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt				   full ? "Match" : "Suffix match");
1727051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			return 1;
1728051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		}
1729051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
1730051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
17312f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	wpa_printf(MSG_DEBUG, "TLS: No CommonName %smatch found",
17322f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		   full ? "": "suffix ");
1733051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	return 0;
1734fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
1735051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt}
1736051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1737051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum tls_fail_reason openssl_tls_fail_reason(int err)
17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (err) {
17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_CERT_REVOKED:
17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TLS_FAIL_REVOKED;
17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_CERT_NOT_YET_VALID:
17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_CRL_NOT_YET_VALID:
17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TLS_FAIL_NOT_YET_VALID;
17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_CERT_HAS_EXPIRED:
17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_CRL_HAS_EXPIRED:
17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TLS_FAIL_EXPIRED;
17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_UNABLE_TO_GET_CRL:
17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_CERT_CHAIN_TOO_LONG:
17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_PATH_LENGTH_EXCEEDED:
17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_INVALID_CA:
17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TLS_FAIL_UNTRUSTED;
17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_CERT_UNTRUSTED:
17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_CERT_REJECTED:
17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TLS_FAIL_BAD_CERTIFICATE;
17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TLS_FAIL_UNSPECIFIED;
17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * get_x509_cert(X509 *cert)
17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *tmp;
17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int cert_len = i2d_X509(cert, NULL);
17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cert_len <= 0)
17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(cert_len);
17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = wpabuf_put(buf, cert_len);
17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	i2d_X509(cert, &tmp);
17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void openssl_tls_fail_event(struct tls_connection *conn,
17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   X509 *err_cert, int err, int depth,
17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const char *subject, const char *err_str,
17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   enum tls_fail_reason reason)
17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union tls_event_data ev;
18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *cert = NULL;
1802ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	struct tls_context *context = conn->context;
18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18044d8552e9d137f0aab7d64e1476b7f892d0468aebPavel Grafov#ifdef ANDROID
18054d8552e9d137f0aab7d64e1476b7f892d0468aebPavel Grafov	log_cert_validation_failure(err_str);
18064d8552e9d137f0aab7d64e1476b7f892d0468aebPavel Grafov#endif
18074d8552e9d137f0aab7d64e1476b7f892d0468aebPavel Grafov
1808ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	if (context->event_cb == NULL)
18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cert = get_x509_cert(err_cert);
18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&ev, 0, sizeof(ev));
18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ev.cert_fail.reason = reason != TLS_FAIL_UNSPECIFIED ?
18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reason : openssl_tls_fail_reason(err);
18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ev.cert_fail.depth = depth;
18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ev.cert_fail.subject = subject;
18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ev.cert_fail.reason_txt = err_str;
18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ev.cert_fail.cert = cert;
1819ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	context->event_cb(context->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(cert);
18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void openssl_tls_cert_event(struct tls_connection *conn,
18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   X509 *err_cert, int depth,
18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const char *subject)
18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *cert = NULL;
18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union tls_event_data ev;
1830ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	struct tls_context *context = conn->context;
18312f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	char *altsubject[TLS_MAX_ALT_SUBJECT];
18322f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	int alt, num_altsubject = 0;
18332f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	GENERAL_NAME *gen;
18342f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	void *ext;
18352f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	stack_index_t i;
18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_SHA256
18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 hash[32];
18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_SHA256 */
18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1840ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	if (context->event_cb == NULL)
18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&ev, 0, sizeof(ev));
184455840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt	if (conn->cert_probe || (conn->flags & TLS_CONN_EXT_CERT_CHECK) ||
184555840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt	    context->cert_in_cb) {
18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cert = get_x509_cert(err_cert);
18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ev.peer_cert.cert = cert;
18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_SHA256
18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cert) {
18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const u8 *addr[1];
18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		size_t len[1];
18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		addr[0] = wpabuf_head(cert);
18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len[0] = wpabuf_len(cert);
18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sha256_vector(1, addr, len, hash) == 0) {
18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ev.peer_cert.hash = hash;
18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ev.peer_cert.hash_len = sizeof(hash);
18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_SHA256 */
18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ev.peer_cert.depth = depth;
18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ev.peer_cert.subject = subject;
18632f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt
18642f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	ext = X509_get_ext_d2i(err_cert, NID_subject_alt_name, NULL, NULL);
18652f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
18662f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		char *pos;
18672f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt
18682f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		if (num_altsubject == TLS_MAX_ALT_SUBJECT)
18692f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			break;
18702f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		gen = sk_GENERAL_NAME_value(ext, i);
18712f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		if (gen->type != GEN_EMAIL &&
18722f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		    gen->type != GEN_DNS &&
18732f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		    gen->type != GEN_URI)
18742f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			continue;
18752f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt
18762f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		pos = os_malloc(10 + gen->d.ia5->length + 1);
18772f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		if (pos == NULL)
18782f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			break;
18792f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		altsubject[num_altsubject++] = pos;
18802f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt
18812f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		switch (gen->type) {
18822f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		case GEN_EMAIL:
18832f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			os_memcpy(pos, "EMAIL:", 6);
18842f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			pos += 6;
18852f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			break;
18862f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		case GEN_DNS:
18872f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			os_memcpy(pos, "DNS:", 4);
18882f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			pos += 4;
18892f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			break;
18902f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		case GEN_URI:
18912f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			os_memcpy(pos, "URI:", 4);
18922f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			pos += 4;
18932f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			break;
18942f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		}
18952f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt
1896d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		os_memcpy(pos, gen->d.ia5->data, gen->d.ia5->length);
1897d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		pos += gen->d.ia5->length;
1898d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		*pos = '\0';
1899d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
190057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
1901d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1902d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	for (alt = 0; alt < num_altsubject; alt++)
1903d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ev.peer_cert.altsubject[alt] = altsubject[alt];
1904d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	ev.peer_cert.num_altsubject = num_altsubject;
1905d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1906d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	context->event_cb(context->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
1907d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpabuf_free(cert);
1908d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	for (alt = 0; alt < num_altsubject; alt++)
1909d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		os_free(altsubject[alt]);
1910d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
1911d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1912d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[256];
19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509 *err_cert;
19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int err, depth;
19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL *ssl;
19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_connection *conn;
1920ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	struct tls_context *context;
19212f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	char *match, *altmatch, *suffix_match, *domain_match;
19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *err_str;
19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
192596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt	if (!err_cert)
192696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt		return 0;
192796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt
19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	err = X509_STORE_CTX_get_error(x509_ctx);
19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	depth = X509_STORE_CTX_get_error_depth(x509_ctx);
19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 SSL_get_ex_data_X509_STORE_CTX_idx());
19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn = SSL_get_app_data(ssl);
19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
193734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
193834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (depth == 0)
193934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		conn->peer_cert = err_cert;
194034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	else if (depth == 1)
194134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		conn->peer_issuer = err_cert;
1942fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	else if (depth == 2)
1943fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		conn->peer_issuer_issuer = err_cert;
194434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
1945ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	context = conn->context;
19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	match = conn->subject_match;
19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	altmatch = conn->altsubject_match;
1948051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	suffix_match = conn->suffix_match;
19492f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	domain_match = conn->domain_match;
19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!preverify_ok && !conn->ca_cert_verify)
19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		preverify_ok = 1;
19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!preverify_ok && depth > 0 && conn->server_cert_only)
19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		preverify_ok = 1;
1955c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	if (!preverify_ok && (conn->flags & TLS_CONN_DISABLE_TIME_CHECKS) &&
1956c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	    (err == X509_V_ERR_CERT_HAS_EXPIRED ||
1957c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	     err == X509_V_ERR_CERT_NOT_YET_VALID)) {
1958c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Ignore certificate validity "
1959c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			   "time mismatch");
1960c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		preverify_ok = 1;
1961c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	}
19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	err_str = X509_verify_cert_error_string(err);
19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_SHA256
19664dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt	/*
19674dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt	 * Do not require preverify_ok so we can explicity allow otherwise
19684dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt	 * invalid pinned server certificates.
19694dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt	 */
19704dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt	if (depth == 0 && conn->server_cert_only) {
19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct wpabuf *cert;
19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cert = get_x509_cert(err_cert);
19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!cert) {
19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: Could not fetch "
19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "server certificate data");
19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			preverify_ok = 0;
19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 hash[32];
19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *addr[1];
19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t len[1];
19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			addr[0] = wpabuf_head(cert);
19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len[0] = wpabuf_len(cert);
19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (sha256_vector(1, addr, len, hash) < 0 ||
19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    os_memcmp(conn->srv_cert_hash, hash, 32) != 0) {
19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				err_str = "Server certificate mismatch";
19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				err = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				preverify_ok = 0;
19884dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt			} else if (!preverify_ok) {
19894dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt				/*
19904dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt				 * Certificate matches pinned certificate, allow
19914dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt				 * regardless of other problems.
19924dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt				 */
19934dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt				wpa_printf(MSG_DEBUG,
19944dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt					   "OpenSSL: Ignore validation issues for a pinned server certificate");
19954dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt				preverify_ok = 1;
19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_free(cert);
19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_SHA256 */
20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!preverify_ok) {
20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "TLS: Certificate verification failed,"
20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " error %d (%s) depth %d for '%s'", err, err_str,
20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   depth, buf);
20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       err_str, TLS_FAIL_UNSPECIFIED);
20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return preverify_ok;
20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - preverify_ok=%d "
20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "err=%d (%s) ca_cert_verify=%d depth=%d buf='%s'",
20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   preverify_ok, err, err_str,
20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   conn->ca_cert_verify, depth, buf);
20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (depth == 0 && match && os_strstr(buf, match) == NULL) {
20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "match with '%s'", buf, match);
20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		preverify_ok = 0;
20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "Subject mismatch",
20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       TLS_FAIL_SUBJECT_MISMATCH);
20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (depth == 0 && altmatch &&
20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   !tls_match_altsubject(err_cert, altmatch)) {
20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "TLS: altSubjectName match "
20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "'%s' not found", altmatch);
20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		preverify_ok = 0;
20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "AltSubject mismatch",
20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       TLS_FAIL_ALTSUBJECT_MISMATCH);
2030051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	} else if (depth == 0 && suffix_match &&
20312f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		   !tls_match_suffix(err_cert, suffix_match, 0)) {
2032051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		wpa_printf(MSG_WARNING, "TLS: Domain suffix match '%s' not found",
2033051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			   suffix_match);
2034051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		preverify_ok = 0;
2035051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2036051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt				       "Domain suffix mismatch",
2037051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt				       TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
20382f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	} else if (depth == 0 && domain_match &&
20392f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		   !tls_match_suffix(err_cert, domain_match, 1)) {
20402f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		wpa_printf(MSG_WARNING, "TLS: Domain match '%s' not found",
20412f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			   domain_match);
20422f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		preverify_ok = 0;
20432f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
20442f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt				       "Domain mismatch",
20452f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt				       TLS_FAIL_DOMAIN_MISMATCH);
20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		openssl_tls_cert_event(conn, err_cert, depth, buf);
20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->cert_probe && preverify_ok && depth == 0) {
20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Reject server certificate "
20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "on probe-only run");
20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		preverify_ok = 0;
20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "Server certificate chain probe",
20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       TLS_FAIL_SERVER_CHAIN_PROBE);
20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2058d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#ifdef CONFIG_SUITEB
2059d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (conn->flags & TLS_CONN_SUITEB) {
2060d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		EVP_PKEY *pk;
2061d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		RSA *rsa;
2062d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		int len = -1;
2063d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
2064d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		pk = X509_get_pubkey(err_cert);
2065d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (pk) {
2066d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			rsa = EVP_PKEY_get1_RSA(pk);
2067d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			if (rsa) {
2068d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				len = RSA_bits(rsa);
2069d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				RSA_free(rsa);
2070d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			}
2071d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			EVP_PKEY_free(pk);
2072d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		}
2073d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
2074d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (len >= 0) {
2075d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			wpa_printf(MSG_DEBUG,
2076d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				   "OpenSSL: RSA modulus size: %d bits", len);
2077d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			if (len < 3072) {
2078d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				preverify_ok = 0;
2079d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				openssl_tls_fail_event(
2080d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt					conn, err_cert, err,
2081d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt					depth, buf,
2082d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt					"Insufficient RSA modulus size",
2083d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt					TLS_FAIL_INSUFFICIENT_KEY_LEN);
2084d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			}
2085d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		}
2086d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	}
2087d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#endif /* CONFIG_SUITEB */
2088d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
2089d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef OPENSSL_IS_BORINGSSL
2090d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt	if (depth == 0 && (conn->flags & TLS_CONN_REQUEST_OCSP) &&
2091d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt	    preverify_ok) {
2092d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		enum ocsp_result res;
2093d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
2094d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt		res = check_ocsp_resp(conn->ssl_ctx, conn->ssl, err_cert,
2095d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt				      conn->peer_issuer,
2096d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt				      conn->peer_issuer_issuer);
2097d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (res == OCSP_REVOKED) {
2098d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			preverify_ok = 0;
2099d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2100d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					       "certificate revoked",
2101d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					       TLS_FAIL_REVOKED);
2102d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			if (err == X509_V_OK)
2103d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				X509_STORE_CTX_set_error(
2104d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					x509_ctx, X509_V_ERR_CERT_REVOKED);
2105d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		} else if (res != OCSP_GOOD &&
2106d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   (conn->flags & TLS_CONN_REQUIRE_OCSP)) {
2107d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			preverify_ok = 0;
2108d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2109d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					       "bad certificate status response",
2110d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					       TLS_FAIL_UNSPECIFIED);
2111d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
2112d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
2113d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* OPENSSL_IS_BORINGSSL */
2114d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
211555840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt	if (depth == 0 && preverify_ok && context->event_cb != NULL)
2116ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		context->event_cb(context->cb_ctx,
2117ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt				  TLS_CERT_CHAIN_SUCCESS, NULL);
211804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return preverify_ok;
21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_STDIO
2124d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int tls_load_ca_der(struct tls_data *data, const char *ca_cert)
21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2126d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_CTX *ssl_ctx = data->ssl;
21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509_LOOKUP *lookup;
21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 0;
21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2130216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(ssl_ctx),
21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       X509_LOOKUP_file());
21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (lookup == NULL) {
21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_WARNING, __func__,
21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed add lookup for X509 store");
21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!X509_LOOKUP_load_file(lookup, ca_cert, X509_FILETYPE_ASN1)) {
21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unsigned long err = ERR_peek_error();
21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_WARNING, __func__,
21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed load CA in DER format");
21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) {
21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring "
21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "cert already in hash table error",
21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   __func__);
21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_STDIO */
21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2156d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int tls_connection_ca_cert(struct tls_data *data,
2157d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				  struct tls_connection *conn,
21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const char *ca_cert, const u8 *ca_cert_blob,
21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  size_t ca_cert_blob_len, const char *ca_path)
21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2161d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_CTX *ssl_ctx = data->ssl;
2162216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	X509_STORE *store;
21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Remove previously configured trusted CA certificates before adding
21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * new ones.
21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
2168216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	store = X509_STORE_new();
2169216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (store == NULL) {
21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new "
21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "certificate store", __func__);
21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2174216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	SSL_CTX_set_cert_store(ssl_ctx, store);
21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->ca_cert_verify = 1;
21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ca_cert && os_strncmp(ca_cert, "probe://", 8) == 0) {
21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Probe for server certificate "
21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "chain");
21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->cert_probe = 1;
21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->ca_cert_verify = 0;
21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ca_cert && os_strncmp(ca_cert, "hash://", 7) == 0) {
21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_SHA256
21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const char *pos = ca_cert + 7;
21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strncmp(pos, "server/sha256/", 14) != 0) {
21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: Unsupported ca_cert "
21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "hash value '%s'", ca_cert);
21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 14;
21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strlen(pos) != 32 * 2) {
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: Unexpected SHA256 "
21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "hash length in ca_cert '%s'", ca_cert);
21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hexstr2bin(pos, conn->srv_cert_hash, 32) < 0) {
22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: Invalid SHA256 hash "
22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "value in ca_cert '%s'", ca_cert);
22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->server_cert_only = 1;
22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Checking only server "
22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "certificate match");
22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_SHA256 */
22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "No SHA256 included in the build - "
22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "cannot validate server certificate hash");
22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_SHA256 */
22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ca_cert_blob) {
2218216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		X509 *cert = d2i_X509(NULL,
2219216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				      (const unsigned char **) &ca_cert_blob,
22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      ca_cert_blob_len);
22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cert == NULL) {
22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_WARNING, __func__,
22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"Failed to parse ca_cert_blob");
22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2227216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(ssl_ctx),
2228216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt					 cert)) {
22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			unsigned long err = ERR_peek_error();
22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_WARNING, __func__,
22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"Failed to add ca_cert_blob to "
22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"certificate store");
22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    ERR_GET_REASON(err) ==
22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    X509_R_CERT_ALREADY_IN_HASH_TABLE) {
22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring "
22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "cert already in hash table error",
22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   __func__);
22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else {
22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				X509_free(cert);
22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509_free(cert);
22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: %s - added ca_cert_blob "
22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "to certificate store", __func__);
22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef ANDROID
2251b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	/* Single alias */
22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ca_cert && os_strncmp("keystore://", ca_cert, 11) == 0) {
2253849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt		if (tls_add_ca_from_keystore(SSL_CTX_get_cert_store(ssl_ctx),
2254b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt					     &ca_cert[11]) < 0)
22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2256b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
2257b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		return 0;
2258b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	}
22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2260b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	/* Multiple aliases separated by space */
2261b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	if (ca_cert && os_strncmp("keystores://", ca_cert, 12) == 0) {
2262b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		char *aliases = os_strdup(&ca_cert[12]);
2263b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		const char *delim = " ";
2264b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		int rc = 0;
2265b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		char *savedptr;
2266b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		char *alias;
2267b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt
2268b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		if (!aliases)
2269b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			return -1;
2270b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		alias = strtok_r(aliases, delim, &savedptr);
2271b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		for (; alias; alias = strtok_r(NULL, delim, &savedptr)) {
2272b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			if (tls_add_ca_from_keystore_encoded(
2273849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt				    SSL_CTX_get_cert_store(ssl_ctx), alias)) {
2274b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt				wpa_printf(MSG_WARNING,
2275b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt					   "OpenSSL: %s - Failed to add ca_cert %s from keystore",
2276b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt					   __func__, alias);
2277b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt				rc = -1;
2278b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt				break;
22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2281b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		os_free(aliases);
2282b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		if (rc)
2283b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			return rc;
2284b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt
22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* ANDROID */
22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_NATIVE_WINDOWS
22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ca_cert && tls_cryptoapi_ca_cert(ssl_ctx, conn->ssl, ca_cert) ==
22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Added CA certificates from "
22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "system certificate store");
22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ca_cert || ca_path) {
23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_STDIO
23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, ca_path) !=
23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    1) {
23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_WARNING, __func__,
23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"Failed to load root certificates");
23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (ca_cert &&
2306d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			    tls_load_ca_der(data, ca_cert) == 0) {
23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "OpenSSL: %s - loaded "
23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "DER format CA certificate",
23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   __func__);
23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else
23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLS: Trusted root "
23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "certificate(s) loaded");
2315d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			tls_get_errors(data);
23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_STDIO */
23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO",
23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__);
23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_STDIO */
23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* No ca_cert configured - do not try to verify server
23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * certificate */
23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->ca_cert_verify = 0;
23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2332d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int tls_global_ca_cert(struct tls_data *data, const char *ca_cert)
23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2334d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_CTX *ssl_ctx = data->ssl;
2335d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ca_cert) {
23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, NULL) != 1)
23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		{
23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_WARNING, __func__,
23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"Failed to load root certificates");
23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLS: Trusted root "
23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "certificate(s) loaded");
23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_STDIO
23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Add the same CAs to the client certificate requests */
23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_CTX_set_client_CA_list(ssl_ctx,
23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   SSL_load_client_CA_file(ca_cert));
23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_STDIO */
23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_global_set_verify(void *ssl_ctx, int check_crl)
23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int flags;
23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (check_crl) {
2363d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		struct tls_data *data = ssl_ctx;
2364d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		X509_STORE *cs = SSL_CTX_get_cert_store(data->ssl);
23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cs == NULL) {
23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_INFO, __func__, "Failed to get "
23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"certificate store when enabling "
23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"check_crl");
23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		flags = X509_V_FLAG_CRL_CHECK;
23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (check_crl == 2)
23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			flags |= X509_V_FLAG_CRL_CHECK_ALL;
23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509_STORE_set_flags(cs, flags);
23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_connection_set_subject_match(struct tls_connection *conn,
23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    const char *subject_match,
2382051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt					    const char *altsubject_match,
23832f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt					    const char *suffix_match,
23842f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt					    const char *domain_match)
23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->subject_match);
23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->subject_match = NULL;
23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (subject_match) {
23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->subject_match = os_strdup(subject_match);
23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conn->subject_match == NULL)
23918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->altsubject_match);
23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->altsubject_match = NULL;
23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (altsubject_match) {
23978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->altsubject_match = os_strdup(altsubject_match);
23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conn->altsubject_match == NULL)
23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2402051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	os_free(conn->suffix_match);
2403051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	conn->suffix_match = NULL;
2404051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (suffix_match) {
2405051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		conn->suffix_match = os_strdup(suffix_match);
2406051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		if (conn->suffix_match == NULL)
2407051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			return -1;
2408051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
2409051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
24102f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	os_free(conn->domain_match);
24112f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	conn->domain_match = NULL;
24122f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	if (domain_match) {
24132f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		conn->domain_match = os_strdup(domain_match);
24142f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		if (conn->domain_match == NULL)
24152f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			return -1;
24162f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	}
24172f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt
24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2422d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#ifdef CONFIG_SUITEB
2423d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#if OPENSSL_VERSION_NUMBER >= 0x10002000L
2424d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidtstatic int suiteb_cert_cb(SSL *ssl, void *arg)
2425d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
2426d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	struct tls_connection *conn = arg;
2427d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
2428d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	/*
2429d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 * This cert_cb() is not really the best location for doing a
2430d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 * constraint check for the ServerKeyExchange message, but this seems to
2431d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 * be the only place where the current OpenSSL sequence can be
2432d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 * terminated cleanly with an TLS alert going out to the server.
2433d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 */
2434d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
2435d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (!(conn->flags & TLS_CONN_SUITEB))
2436d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return 1;
2437d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
2438d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	/* DHE is enabled only with DHE-RSA-AES256-GCM-SHA384 */
2439d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (conn->cipher_suite != 0x9f)
2440d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return 1;
2441d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
2442d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (conn->server_dh_prime_len >= 3072)
2443d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return 1;
2444d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
2445d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	wpa_printf(MSG_DEBUG,
2446d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		   "OpenSSL: Server DH prime length (%d bits) not sufficient for Suite B RSA - reject handshake",
2447d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		   conn->server_dh_prime_len);
2448d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	return 0;
2449d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt}
2450d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#endif /* OPENSSL_VERSION_NUMBER */
2451d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#endif /* CONFIG_SUITEB */
2452d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
2453d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
2454d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidtstatic int tls_set_conn_flags(struct tls_connection *conn, unsigned int flags)
2455d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt{
2456d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	SSL *ssl = conn->ssl;
2457d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
2458d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef SSL_OP_NO_TICKET
2459d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (flags & TLS_CONN_DISABLE_SESSION_TICKET)
2460d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_set_options(ssl, SSL_OP_NO_TICKET);
2461d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	else
2462d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_clear_options(ssl, SSL_OP_NO_TICKET);
2463d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* SSL_OP_NO_TICKET */
2464d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
2465d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef SSL_OP_NO_TLSv1
2466d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (flags & TLS_CONN_DISABLE_TLSv1_0)
2467d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_set_options(ssl, SSL_OP_NO_TLSv1);
2468d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	else
2469d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_clear_options(ssl, SSL_OP_NO_TLSv1);
2470d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* SSL_OP_NO_TLSv1 */
2471d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef SSL_OP_NO_TLSv1_1
2472d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (flags & TLS_CONN_DISABLE_TLSv1_1)
2473d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_set_options(ssl, SSL_OP_NO_TLSv1_1);
2474d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	else
2475d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_clear_options(ssl, SSL_OP_NO_TLSv1_1);
2476d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* SSL_OP_NO_TLSv1_1 */
2477d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef SSL_OP_NO_TLSv1_2
2478d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (flags & TLS_CONN_DISABLE_TLSv1_2)
2479d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_set_options(ssl, SSL_OP_NO_TLSv1_2);
2480d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	else
2481d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_clear_options(ssl, SSL_OP_NO_TLSv1_2);
2482d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* SSL_OP_NO_TLSv1_2 */
2483d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#ifdef CONFIG_SUITEB
2484d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#if OPENSSL_VERSION_NUMBER >= 0x10002000L
2485d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (flags & TLS_CONN_SUITEB_NO_ECDH) {
2486d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		const char *ciphers = "DHE-RSA-AES256-GCM-SHA384";
2487d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
2488d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (SSL_set_cipher_list(ssl, ciphers) != 1) {
2489d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			wpa_printf(MSG_INFO,
2490d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				   "OpenSSL: Failed to set Suite B ciphers");
2491d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			return -1;
2492d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		}
2493d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	} else if (flags & TLS_CONN_SUITEB) {
2494d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		EC_KEY *ecdh;
2495d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		const char *ciphers =
2496d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			"ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384";
2497d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
2498d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (SSL_set_cipher_list(ssl, ciphers) != 1) {
2499d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			wpa_printf(MSG_INFO,
2500d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				   "OpenSSL: Failed to set Suite B ciphers");
2501d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			return -1;
2502d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		}
2503d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
2504d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (SSL_set1_curves_list(ssl, "P-384") != 1) {
2505d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			wpa_printf(MSG_INFO,
2506d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				   "OpenSSL: Failed to set Suite B curves");
2507d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			return -1;
2508d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		}
2509d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
2510d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		ecdh = EC_KEY_new_by_curve_name(NID_secp384r1);
2511d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (!ecdh || SSL_set_tmp_ecdh(ssl, ecdh) != 1) {
2512d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			EC_KEY_free(ecdh);
2513d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			wpa_printf(MSG_INFO,
2514d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				   "OpenSSL: Failed to set ECDH parameter");
2515d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			return -1;
2516d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		}
2517d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		EC_KEY_free(ecdh);
2518d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	}
2519d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (flags & (TLS_CONN_SUITEB | TLS_CONN_SUITEB_NO_ECDH)) {
2520d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		/* ECDSA+SHA384 if need to add EC support here */
2521d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (SSL_set1_sigalgs_list(ssl, "RSA+SHA384") != 1) {
2522d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			wpa_printf(MSG_INFO,
2523d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				   "OpenSSL: Failed to set Suite B sigalgs");
2524d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			return -1;
2525d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		}
2526d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
2527d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		SSL_set_options(ssl, SSL_OP_NO_TLSv1);
2528d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		SSL_set_options(ssl, SSL_OP_NO_TLSv1_1);
2529d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		SSL_set_cert_cb(ssl, suiteb_cert_cb, conn);
2530d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	}
2531d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#else /* OPENSSL_VERSION_NUMBER < 0x10002000L */
2532d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (flags & (TLS_CONN_SUITEB | TLS_CONN_SUITEB_NO_ECDH)) {
2533d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		wpa_printf(MSG_ERROR,
2534d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			   "OpenSSL: Suite B RSA case not supported with this OpenSSL version");
2535d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return -1;
2536d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	}
2537d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#endif /* OPENSSL_VERSION_NUMBER */
2538d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#endif /* CONFIG_SUITEB */
2539d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
2540d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	return 0;
2541d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
2542d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
2543d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
2545d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			      int verify_peer, unsigned int flags,
2546d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			      const u8 *session_ctx, size_t session_ctx_len)
25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static int counter = 0;
2549d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct tls_data *data = ssl_ctx;
25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (verify_peer) {
25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->ca_cert_verify = 1;
25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER |
25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       SSL_VERIFY_FAIL_IF_NO_PEER_CERT |
25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       SSL_VERIFY_CLIENT_ONCE, tls_verify_cb);
25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->ca_cert_verify = 0;
25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2564d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (tls_set_conn_flags(conn, flags) < 0)
2565d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return -1;
2566d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	conn->flags = flags;
2567d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
25688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_set_accept_state(conn->ssl);
25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2570d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (data->tls_session_lifetime == 0) {
2571d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		/*
2572d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		 * Set session id context to a unique value to make sure
2573d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		 * session resumption cannot be used either through session
2574d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		 * caching or TLS ticket extension.
2575d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		 */
2576d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		counter++;
2577d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_set_session_id_context(conn->ssl,
2578d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					   (const unsigned char *) &counter,
2579d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					   sizeof(counter));
2580d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else if (session_ctx) {
2581d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_set_session_id_context(conn->ssl, session_ctx,
2582d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					   session_ctx_len);
2583d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_connection_client_cert(struct tls_connection *conn,
25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const char *client_cert,
25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *client_cert_blob,
25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      size_t client_cert_blob_len)
25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (client_cert == NULL && client_cert_blob == NULL)
25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2597de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt#ifdef PKCS12_FUNCS
25989839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt#if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER)
2599de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	/*
2600de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	 * Clear previously set extra chain certificates, if any, from PKCS#12
2601de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	 * processing in tls_parse_pkcs12() to allow OpenSSL to build a new
2602de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	 * chain properly.
2603de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	 */
2604de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	SSL_CTX_clear_extra_chain_certs(conn->ssl_ctx);
2605de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt#endif /* OPENSSL_VERSION_NUMBER < 0x10002000L */
2606de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt#endif /* PKCS12_FUNCS */
2607de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt
26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (client_cert_blob &&
26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    SSL_use_certificate_ASN1(conn->ssl, (u8 *) client_cert_blob,
26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     client_cert_blob_len) == 1) {
26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_ASN1 --> "
26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "OK");
26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (client_cert_blob) {
26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_DEBUG, __func__,
26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"SSL_use_certificate_ASN1 failed");
26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (client_cert == NULL)
26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef ANDROID
26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strncmp("keystore://", client_cert, 11) == 0) {
26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		BIO *bio = BIO_from_keystore(&client_cert[11]);
26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509 *x509 = NULL;
26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int ret = -1;
2627d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (bio) {
26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
2629d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		}
26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (x509) {
26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (SSL_use_certificate(conn->ssl, x509) == 1)
26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				ret = 0;
26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			X509_free(x509);
26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
263550772e8622904b97ec2840383b4f7395e952344cPaul Stewart
263650772e8622904b97ec2840383b4f7395e952344cPaul Stewart		/* Read additional certificates into the chain. */
263750772e8622904b97ec2840383b4f7395e952344cPaul Stewart		while (bio) {
263850772e8622904b97ec2840383b4f7395e952344cPaul Stewart			x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
263950772e8622904b97ec2840383b4f7395e952344cPaul Stewart			if (x509) {
264050772e8622904b97ec2840383b4f7395e952344cPaul Stewart				/* Takes ownership of x509 */
264150772e8622904b97ec2840383b4f7395e952344cPaul Stewart				SSL_add0_chain_cert(conn->ssl, x509);
264250772e8622904b97ec2840383b4f7395e952344cPaul Stewart			} else {
264350772e8622904b97ec2840383b4f7395e952344cPaul Stewart				BIO_free(bio);
264450772e8622904b97ec2840383b4f7395e952344cPaul Stewart				bio = NULL;
264550772e8622904b97ec2840383b4f7395e952344cPaul Stewart			}
264650772e8622904b97ec2840383b4f7395e952344cPaul Stewart		}
26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return ret;
26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* ANDROID */
26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_STDIO
26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (SSL_use_certificate_file(conn->ssl, client_cert,
26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     SSL_FILETYPE_ASN1) == 1) {
26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (DER)"
26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " --> OK");
26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (SSL_use_certificate_file(conn->ssl, client_cert,
26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     SSL_FILETYPE_PEM) == 1) {
26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ERR_clear_error();
26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (PEM)"
26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " --> OK");
26648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
26658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_show_errors(MSG_DEBUG, __func__,
26688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"SSL_use_certificate_file failed");
26698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_STDIO */
26708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__);
26718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_STDIO */
26728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
26748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2677d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int tls_global_client_cert(struct tls_data *data,
2678d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				  const char *client_cert)
26798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_STDIO
2681d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_CTX *ssl_ctx = data->ssl;
2682d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
26838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (client_cert == NULL)
26848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
26858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (SSL_CTX_use_certificate_file(ssl_ctx, client_cert,
26878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 SSL_FILETYPE_ASN1) != 1 &&
26881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    SSL_CTX_use_certificate_chain_file(ssl_ctx, client_cert) != 1 &&
26898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    SSL_CTX_use_certificate_file(ssl_ctx, client_cert,
26908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 SSL_FILETYPE_PEM) != 1) {
26918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
26928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to load client certificate");
26938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
26948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_STDIO */
26978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (client_cert == NULL)
26988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
26998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__);
27008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
27018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_STDIO */
27028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_passwd_cb(char *buf, int size, int rwflag, void *password)
27068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (password == NULL) {
27088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
27098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(buf, (char *) password, size);
27118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return os_strlen(buf);
27128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PKCS12_FUNCS
2716d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int tls_parse_pkcs12(struct tls_data *data, SSL *ssl, PKCS12 *p12,
27178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const char *passwd)
27188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EVP_PKEY *pkey;
27208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509 *cert;
27218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STACK_OF(X509) *certs;
27228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res = 0;
27238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[256];
27248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pkey = NULL;
27268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cert = NULL;
27278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	certs = NULL;
2728d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!passwd)
2729d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		passwd = "";
27308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!PKCS12_parse(p12, passwd, &pkey, &cert, &certs)) {
27318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_DEBUG, __func__,
27328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to parse PKCS12 file");
27338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		PKCS12_free(p12);
27348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLS: Successfully parsed PKCS12 data");
27378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cert) {
27398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509_NAME_oneline(X509_get_subject_name(cert), buf,
27408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sizeof(buf));
27418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLS: Got certificate from PKCS12: "
27428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "subject='%s'", buf);
27438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ssl) {
27448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (SSL_use_certificate(ssl, cert) != 1)
27458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				res = -1;
27468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
2747d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			if (SSL_CTX_use_certificate(data->ssl, cert) != 1)
27488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				res = -1;
27498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
27508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509_free(cert);
27518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pkey) {
27548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLS: Got private key from PKCS12");
27558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ssl) {
27568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (SSL_use_PrivateKey(ssl, pkey) != 1)
27578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				res = -1;
27588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
2759d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			if (SSL_CTX_use_PrivateKey(data->ssl, pkey) != 1)
27608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				res = -1;
27618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
27628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EVP_PKEY_free(pkey);
27638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (certs) {
2766d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
2767b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		if (ssl)
2768b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			SSL_clear_chain_certs(ssl);
2769b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		else
2770b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			SSL_CTX_clear_chain_certs(data->ssl);
2771d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		while ((cert = sk_X509_pop(certs)) != NULL) {
2772d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			X509_NAME_oneline(X509_get_subject_name(cert), buf,
2773d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					  sizeof(buf));
2774d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLS: additional certificate"
2775d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				   " from PKCS12: subject='%s'", buf);
2776b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			if ((ssl && SSL_add1_chain_cert(ssl, cert) != 1) ||
2777b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			    (!ssl && SSL_CTX_add1_chain_cert(data->ssl,
2778b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt							     cert) != 1)) {
2779d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				tls_show_errors(MSG_DEBUG, __func__,
2780d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt						"Failed to add additional certificate");
2781d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				res = -1;
278257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt				X509_free(cert);
2783d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				break;
2784d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			}
278557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt			X509_free(cert);
2786d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
2787d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (!res) {
2788d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			/* Try to continue anyway */
2789d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
279057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		sk_X509_pop_free(certs, X509_free);
2791d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifndef OPENSSL_IS_BORINGSSL
2792b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		if (ssl)
2793b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			res = SSL_build_cert_chain(
2794b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt				ssl,
2795b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt				SSL_BUILD_CHAIN_FLAG_CHECK |
2796b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt				SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR);
2797b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		else
2798b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			res = SSL_CTX_build_cert_chain(
2799b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt				data->ssl,
2800b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt				SSL_BUILD_CHAIN_FLAG_CHECK |
2801b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt				SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR);
2802d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (!res) {
2803d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			tls_show_errors(MSG_DEBUG, __func__,
2804d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					"Failed to build certificate chain");
2805d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		} else if (res == 2) {
2806d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			wpa_printf(MSG_DEBUG,
2807d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				   "TLS: Ignore certificate chain verification error when building chain with PKCS#12 extra certificates");
2808d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
2809d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* OPENSSL_IS_BORINGSSL */
2810d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		/*
2811d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		 * Try to continue regardless of result since it is possible for
2812d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		 * the extra certificates not to be required.
2813d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		 */
2814d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		res = 0;
2815d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#else /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
2816d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_CTX_clear_extra_chain_certs(data->ssl);
28178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while ((cert = sk_X509_pop(certs)) != NULL) {
28188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			X509_NAME_oneline(X509_get_subject_name(cert), buf,
28198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  sizeof(buf));
28208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLS: additional certificate"
28218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " from PKCS12: subject='%s'", buf);
28228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
28238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * There is no SSL equivalent for the chain cert - so
28248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * always add it to the context...
28258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
2826d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			if (SSL_CTX_add_extra_chain_cert(data->ssl, cert) != 1)
2827d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			{
282857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt				X509_free(cert);
28298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				res = -1;
28308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
28318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
28328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
283357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		sk_X509_pop_free(certs, X509_free);
2834d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
28358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PKCS12_free(p12);
28388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0)
2840d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		tls_get_errors(data);
28418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
28438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif  /* PKCS12_FUNCS */
28458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2847d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int tls_read_pkcs12(struct tls_data *data, SSL *ssl,
2848d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   const char *private_key, const char *passwd)
28498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PKCS12_FUNCS
28518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	FILE *f;
28528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PKCS12 *p12;
28538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	f = fopen(private_key, "rb");
28558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (f == NULL)
28568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
28578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p12 = d2i_PKCS12_fp(f, NULL);
28598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fclose(f);
28608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p12 == NULL) {
28628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
28638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to use PKCS#12 file");
28648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
28658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2867d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return tls_parse_pkcs12(data, ssl, p12, passwd);
28688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* PKCS12_FUNCS */
28708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot read "
28718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "p12/pfx files");
28728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
28738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif  /* PKCS12_FUNCS */
28748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2877d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int tls_read_pkcs12_blob(struct tls_data *data, SSL *ssl,
28788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				const u8 *blob, size_t len, const char *passwd)
28798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PKCS12_FUNCS
28818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PKCS12 *p12;
28828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2883216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p12 = d2i_PKCS12(NULL, (const unsigned char **) &blob, len);
28848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p12 == NULL) {
28858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
28868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to use PKCS#12 blob");
28878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
28888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2890d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return tls_parse_pkcs12(data, ssl, p12, passwd);
28918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* PKCS12_FUNCS */
28938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot parse "
28948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "p12/pfx blobs");
28958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
28968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif  /* PKCS12_FUNCS */
28978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
29018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_engine_get_cert(struct tls_connection *conn,
29028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       const char *cert_id,
29038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       X509 **cert)
29048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* this runs after the private key is loaded so no PIN is required */
29068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct {
29078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const char *cert_id;
29088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509 *cert;
29098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} params;
29108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.cert_id = cert_id;
29118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.cert = NULL;
29128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ENGINE_ctrl_cmd(conn->engine, "LOAD_CERT_CTRL",
29148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     0, &params, NULL, 1)) {
29151d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt		unsigned long err = ERR_get_error();
29161d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt
29178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "ENGINE: cannot load client cert with id"
29188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " '%s' [%s]", cert_id,
29191d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt			   ERR_error_string(err, NULL));
29201d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt		if (tls_is_pin_error(err))
29211d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt			return TLS_SET_PARAMS_ENGINE_PRV_BAD_PIN;
29228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
29238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!params.cert) {
29258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "ENGINE: did not properly cert with id"
29268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " '%s'", cert_id);
29278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
29288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*cert = params.cert;
29308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
29318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
29338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_connection_engine_client_cert(struct tls_connection *conn,
29368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const char *cert_id)
29378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
29398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509 *cert;
29408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_engine_get_cert(conn, cert_id, &cert))
29428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
29438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!SSL_use_certificate(conn->ssl, cert)) {
29458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_ERROR, __func__,
29468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"SSL_use_certificate failed");
29478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                X509_free(cert);
29488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
29498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509_free(cert);
29518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "ENGINE: SSL_use_certificate --> "
29528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "OK");
29538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
29548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_ENGINE */
29568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
29578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
29588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2961d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int tls_connection_engine_ca_cert(struct tls_data *data,
29628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 struct tls_connection *conn,
29638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 const char *ca_cert_id)
29648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
29668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509 *cert;
2967d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_CTX *ssl_ctx = data->ssl;
2968216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	X509_STORE *store;
29698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_engine_get_cert(conn, ca_cert_id, &cert))
29718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
29728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* start off the same as tls_connection_ca_cert */
2974216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	store = X509_STORE_new();
2975216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (store == NULL) {
29768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new "
29778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "certificate store", __func__);
29788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509_free(cert);
29798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
29808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2981216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	SSL_CTX_set_cert_store(ssl_ctx, store);
2982216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!X509_STORE_add_cert(store, cert)) {
29838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unsigned long err = ERR_peek_error();
29848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_WARNING, __func__,
29858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to add CA certificate from engine "
29868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"to certificate store");
29878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
29888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) {
29898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring cert"
29908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " already in hash table error",
29918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   __func__);
29928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
29938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			X509_free(cert);
29948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
29958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
29968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509_free(cert);
29988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: %s - added CA certificate from engine "
29998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "to certificate store", __func__);
30008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
300161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	conn->ca_cert_verify = 1;
300261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
30038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
30048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_ENGINE */
30068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
30078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
30088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_connection_engine_private_key(struct tls_connection *conn)
30128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30131eb02edb319d462031f0c2f1f3548498558e95a5Adam Langley#if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE)
30148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (SSL_use_PrivateKey(conn->ssl, conn->private_key) != 1) {
30158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_ERROR, __func__,
30168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"ENGINE: cannot use private key for TLS");
30178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
30188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!SSL_check_private_key(conn->ssl)) {
30208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
30218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Private key failed verification");
30228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
30238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
30258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_ENGINE */
30268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_ERROR, "SSL: Configuration uses engine, but "
30278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "engine support was not compiled in");
30288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
30298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
30308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3033d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidtstatic void tls_clear_default_passwd_cb(SSL_CTX *ssl_ctx, SSL *ssl)
3034d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt{
3035d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL)
3036d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (ssl) {
3037d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		SSL_set_default_passwd_cb(ssl, NULL);
3038d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		SSL_set_default_passwd_cb_userdata(ssl, NULL);
3039d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	}
3040d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#endif /* >= 1.1.0f && !LibreSSL && !BoringSSL */
3041d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL);
3042d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, NULL);
3043d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt}
3044d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
3045d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
3046d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int tls_connection_private_key(struct tls_data *data,
30478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      struct tls_connection *conn,
30488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const char *private_key,
30498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const char *private_key_passwd,
30508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *private_key_blob,
30518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      size_t private_key_blob_len)
30528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3053d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_CTX *ssl_ctx = data->ssl;
30548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *passwd;
30558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ok;
30568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (private_key == NULL && private_key_blob == NULL)
30588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
30598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (private_key_passwd) {
30618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		passwd = os_strdup(private_key_passwd);
30628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (passwd == NULL)
30638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
30648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
30658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		passwd = NULL;
30668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3067d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL)
3068d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	/*
3069d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 * In OpenSSL >= 1.1.0f SSL_use_PrivateKey_file() uses the callback
3070d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 * from the SSL object. See OpenSSL commit d61461a75253.
3071d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 */
3072d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	SSL_set_default_passwd_cb(conn->ssl, tls_passwd_cb);
3073d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	SSL_set_default_passwd_cb_userdata(conn->ssl, passwd);
3074d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#endif /* >= 1.1.0f && !LibreSSL && !BoringSSL */
3075d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	/* Keep these for OpenSSL < 1.1.0f */
30768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb);
30778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, passwd);
30788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ok = 0;
30808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (private_key_blob) {
30818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA, conn->ssl,
30828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    (u8 *) private_key_blob,
30838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    private_key_blob_len) == 1) {
30848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_"
30858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "ASN1(EVP_PKEY_RSA) --> OK");
30868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ok = 1;
30878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
30888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
30898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_use_PrivateKey_ASN1(EVP_PKEY_DSA, conn->ssl,
30918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    (u8 *) private_key_blob,
30928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    private_key_blob_len) == 1) {
30938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_"
30948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "ASN1(EVP_PKEY_DSA) --> OK");
30958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ok = 1;
30968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
30978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
30988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_use_RSAPrivateKey_ASN1(conn->ssl,
31008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       (u8 *) private_key_blob,
31018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       private_key_blob_len) == 1) {
31028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: "
31038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "SSL_use_RSAPrivateKey_ASN1 --> OK");
31048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ok = 1;
31058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3108d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (tls_read_pkcs12_blob(data, conn->ssl, private_key_blob,
31098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 private_key_blob_len, passwd) == 0) {
31108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: PKCS#12 as blob --> "
31118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "OK");
31128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ok = 1;
31138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (!ok && private_key) {
31208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_STDIO
31218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_use_PrivateKey_file(conn->ssl, private_key,
31228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    SSL_FILETYPE_ASN1) == 1) {
31238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: "
31248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "SSL_use_PrivateKey_File (DER) --> OK");
31258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ok = 1;
31268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_use_PrivateKey_file(conn->ssl, private_key,
31308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    SSL_FILETYPE_PEM) == 1) {
31318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: "
31328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "SSL_use_PrivateKey_File (PEM) --> OK");
31338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ok = 1;
31348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_STDIO */
31378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO",
31388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__);
31398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_STDIO */
31408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3141d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (tls_read_pkcs12(data, conn->ssl, private_key, passwd)
31428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    == 0) {
31438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: Reading PKCS#12 file "
31448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "--> OK");
31458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ok = 1;
31468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_cryptoapi_cert(conn->ssl, private_key) == 0) {
31508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: Using CryptoAPI to "
31518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "access certificate store --> OK");
31528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ok = 1;
31538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ok) {
31608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
31618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to load private key");
3162d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		tls_clear_default_passwd_cb(ssl_ctx, conn->ssl);
31638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(passwd);
31648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
31658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ERR_clear_error();
3167d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	tls_clear_default_passwd_cb(ssl_ctx, conn->ssl);
31688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(passwd);
316961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
31708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!SSL_check_private_key(conn->ssl)) {
31718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__, "Private key failed "
31728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"verification");
31738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
31748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "SSL: Private key loaded successfully");
31778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
31788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3181d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int tls_global_private_key(struct tls_data *data,
3182d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				  const char *private_key,
31838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const char *private_key_passwd)
31848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3185d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_CTX *ssl_ctx = data->ssl;
31868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *passwd;
31878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (private_key == NULL)
31898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
31908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (private_key_passwd) {
31928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		passwd = os_strdup(private_key_passwd);
31938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (passwd == NULL)
31948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
31958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
31968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		passwd = NULL;
31978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb);
31998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, passwd);
32008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (
32018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_STDIO
32028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key,
32038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					SSL_FILETYPE_ASN1) != 1 &&
32048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key,
32058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					SSL_FILETYPE_PEM) != 1 &&
32068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_STDIO */
3207d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	    tls_read_pkcs12(data, NULL, private_key, passwd)) {
32088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
32098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to load private key");
3210d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		tls_clear_default_passwd_cb(ssl_ctx, NULL);
32118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(passwd);
32128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ERR_clear_error();
32138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
32148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3215d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	tls_clear_default_passwd_cb(ssl_ctx, NULL);
32168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(passwd);
32178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ERR_clear_error();
321861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
32198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!SSL_CTX_check_private_key(ssl_ctx)) {
32208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
32218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Private key failed verification");
32228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
32238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
32268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_connection_dh(struct tls_connection *conn, const char *dh_file)
32308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef OPENSSL_NO_DH
32328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dh_file == NULL)
32338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
32348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but "
32358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "dh_file specified");
32368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
32378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_DH */
32388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DH *dh;
32398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BIO *bio;
32408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: add support for dh_blob */
32428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dh_file == NULL)
32438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
32448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
32458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
32468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bio = BIO_new_file(dh_file, "r");
32488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bio == NULL) {
32498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s",
32508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   dh_file, ERR_error_string(ERR_get_error(), NULL));
32518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
32528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
32548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BIO_free(bio);
32558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_DSA
32568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (dh == NULL) {
32578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DSA *dsa;
32588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -"
32598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " trying to parse as DSA params", dh_file,
32608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(ERR_get_error(), NULL));
32618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		bio = BIO_new_file(dh_file, "r");
32628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (bio == NULL)
32638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
32648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL);
32658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		BIO_free(bio);
32668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dsa) {
32678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file "
32688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "'%s': %s", dh_file,
32698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   ERR_error_string(ERR_get_error(), NULL));
32708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
32718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
32728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format");
32748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dh = DSA_dup_DH(dsa);
32758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DSA_free(dsa);
32768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dh == NULL) {
32778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "TLS: Failed to convert DSA "
32788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "params into DH params");
32798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
32808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
32818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
32828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* !OPENSSL_NO_DSA */
32848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dh == NULL) {
32858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file "
32868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "'%s'", dh_file);
32878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
32888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (SSL_set_tmp_dh(conn->ssl, dh) != 1) {
32918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': "
32928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%s", dh_file,
32938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(ERR_get_error(), NULL));
32948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DH_free(dh);
32958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
32968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DH_free(dh);
32988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
32998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_DH */
33008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3303d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int tls_global_dh(struct tls_data *data, const char *dh_file)
33048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef OPENSSL_NO_DH
33068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dh_file == NULL)
33078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
33088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but "
33098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "dh_file specified");
33108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
33118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_DH */
3312d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_CTX *ssl_ctx = data->ssl;
33138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DH *dh;
33148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BIO *bio;
33158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: add support for dh_blob */
33178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dh_file == NULL)
33188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
33198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssl_ctx == NULL)
33208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
33218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bio = BIO_new_file(dh_file, "r");
33238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bio == NULL) {
33248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s",
33258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   dh_file, ERR_error_string(ERR_get_error(), NULL));
33268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
33278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
33298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BIO_free(bio);
33308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_DSA
33318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (dh == NULL) {
33328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DSA *dsa;
33338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -"
33348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " trying to parse as DSA params", dh_file,
33358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(ERR_get_error(), NULL));
33368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		bio = BIO_new_file(dh_file, "r");
33378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (bio == NULL)
33388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
33398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL);
33408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		BIO_free(bio);
33418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dsa) {
33428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file "
33438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "'%s': %s", dh_file,
33448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   ERR_error_string(ERR_get_error(), NULL));
33458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
33468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
33478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format");
33498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dh = DSA_dup_DH(dsa);
33508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DSA_free(dsa);
33518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dh == NULL) {
33528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "TLS: Failed to convert DSA "
33538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "params into DH params");
33548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
33558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
33568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
33578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* !OPENSSL_NO_DSA */
33598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dh == NULL) {
33608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file "
33618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "'%s'", dh_file);
33628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
33638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (SSL_CTX_set_tmp_dh(ssl_ctx, dh) != 1) {
33668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': "
33678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%s", dh_file,
33688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(ERR_get_error(), NULL));
33698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DH_free(dh);
33708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
33718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DH_free(dh);
33738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
33748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_DH */
33758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3378d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtint tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn,
3379d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			      struct tls_random *keys)
33808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL *ssl;
33828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL || keys == NULL)
33848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
33858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssl = conn->ssl;
3386d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (ssl == NULL)
3387d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return -1;
3388d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3389d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_memset(keys, 0, sizeof(*keys));
3390d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	keys->client_random = conn->client_random;
3391d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	keys->client_random_len = SSL_get_client_random(
3392d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ssl, conn->client_random, sizeof(conn->client_random));
3393d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	keys->server_random = conn->server_random;
3394d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	keys->server_random_len = SSL_get_server_random(
3395d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ssl, conn->server_random, sizeof(conn->server_random));
33968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
33988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3401849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt#ifdef OPENSSL_NEED_EAP_FAST_PRF
3402af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidtstatic int openssl_get_keyblock_size(SSL *ssl)
3403af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt{
3404d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
3405af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	const EVP_CIPHER *c;
3406af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	const EVP_MD *h;
3407af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	int md_size;
3408af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt
3409af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	if (ssl->enc_read_ctx == NULL || ssl->enc_read_ctx->cipher == NULL ||
3410af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	    ssl->read_hash == NULL)
3411af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt		return -1;
3412af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt
3413af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	c = ssl->enc_read_ctx->cipher;
3414af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	h = EVP_MD_CTX_md(ssl->read_hash);
3415af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	if (h)
3416af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt		md_size = EVP_MD_size(h);
3417af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	else if (ssl->s3)
3418af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt		md_size = ssl->s3->tmp.new_mac_secret_size;
3419af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	else
3420af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt		return -1;
3421af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt
3422af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: keyblock size: key_len=%d MD_size=%d "
3423af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt		   "IV_len=%d", EVP_CIPHER_key_length(c), md_size,
3424af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt		   EVP_CIPHER_iv_length(c));
3425af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	return 2 * (EVP_CIPHER_key_length(c) +
3426af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt		    md_size +
3427af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt		    EVP_CIPHER_iv_length(c));
3428d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#else
3429d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const SSL_CIPHER *ssl_cipher;
3430d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	int cipher, digest;
3431d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const EVP_CIPHER *c;
3432d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const EVP_MD *h;
3433d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3434d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	ssl_cipher = SSL_get_current_cipher(ssl);
3435d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!ssl_cipher)
3436d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return -1;
3437d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	cipher = SSL_CIPHER_get_cipher_nid(ssl_cipher);
3438d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	digest = SSL_CIPHER_get_digest_nid(ssl_cipher);
3439d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: cipher nid %d digest nid %d",
3440d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		   cipher, digest);
3441d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (cipher < 0 || digest < 0)
3442d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return -1;
3443d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	c = EVP_get_cipherbynid(cipher);
3444d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	h = EVP_get_digestbynid(digest);
3445d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!c || !h)
3446d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return -1;
3447d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3448d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_printf(MSG_DEBUG,
3449d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		   "OpenSSL: keyblock size: key_len=%d MD_size=%d IV_len=%d",
3450d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		   EVP_CIPHER_key_length(c), EVP_MD_size(h),
3451d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		   EVP_CIPHER_iv_length(c));
3452d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return 2 * (EVP_CIPHER_key_length(c) + EVP_MD_size(h) +
3453d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		    EVP_CIPHER_iv_length(c));
3454d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif
3455af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt}
3456849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt#endif /* OPENSSL_NEED_EAP_FAST_PRF */
3457af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt
3458af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt
3459849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidtint tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
3460849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt			      const char *label, u8 *out, size_t out_len)
3461af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt{
3462849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt	if (!conn ||
3463849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt	    SSL_export_keying_material(conn->ssl, out, out_len, label,
3464849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt				       os_strlen(label), NULL, 0, 0) != 1)
3465849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt		return -1;
3466849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt	return 0;
3467849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt}
3468849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt
3469849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt
3470849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidtint tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
3471849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt				    u8 *out, size_t out_len)
3472849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt{
3473849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt#ifdef OPENSSL_NEED_EAP_FAST_PRF
3474d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL *ssl;
3475d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_SESSION *sess;
3476d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	u8 *rnd;
3477d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	int ret = -1;
3478d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	int skip = 0;
3479d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	u8 *tmp_out = NULL;
3480d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	u8 *_out = out;
3481d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	unsigned char client_random[SSL3_RANDOM_SIZE];
3482d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	unsigned char server_random[SSL3_RANDOM_SIZE];
3483d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	unsigned char master_key[64];
3484d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	size_t master_key_len;
3485d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const char *ver;
3486d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3487d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	/*
3488849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt	 * TLS library did not support EAP-FAST key generation, so get the
3489849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt	 * needed TLS session parameters and use an internal implementation of
3490849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt	 * TLS PRF to derive the key.
3491d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	 */
3492d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3493d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (conn == NULL)
3494d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return -1;
3495d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	ssl = conn->ssl;
3496d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (ssl == NULL)
3497d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return -1;
3498d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	ver = SSL_get_version(ssl);
3499d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	sess = SSL_get_session(ssl);
3500d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!ver || !sess)
3501d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return -1;
3502d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3503849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt	skip = openssl_get_keyblock_size(ssl);
3504849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt	if (skip < 0)
3505849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt		return -1;
3506849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt	tmp_out = os_malloc(skip + out_len);
3507849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt	if (!tmp_out)
3508849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt		return -1;
3509849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt	_out = tmp_out;
3510d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3511d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	rnd = os_malloc(2 * SSL3_RANDOM_SIZE);
3512d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!rnd) {
3513d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		os_free(tmp_out);
3514d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return -1;
3515d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
3516d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3517d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_get_client_random(ssl, client_random, sizeof(client_random));
3518d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_get_server_random(ssl, server_random, sizeof(server_random));
3519d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	master_key_len = SSL_SESSION_get_master_key(sess, master_key,
3520d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt						    sizeof(master_key));
3521d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3522849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt	os_memcpy(rnd, server_random, SSL3_RANDOM_SIZE);
3523849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt	os_memcpy(rnd + SSL3_RANDOM_SIZE, client_random, SSL3_RANDOM_SIZE);
3524d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3525d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (os_strcmp(ver, "TLSv1.2") == 0) {
3526d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		tls_prf_sha256(master_key, master_key_len,
3527849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt			       "key expansion", rnd, 2 * SSL3_RANDOM_SIZE,
3528d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			       _out, skip + out_len);
3529af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt		ret = 0;
3530d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else if (tls_prf_sha1_md5(master_key, master_key_len,
3531849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt				    "key expansion", rnd, 2 * SSL3_RANDOM_SIZE,
3532d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    _out, skip + out_len) == 0) {
3533d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ret = 0;
3534d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
3535d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_memset(master_key, 0, sizeof(master_key));
3536af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	os_free(rnd);
3537849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt	if (ret == 0)
3538af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt		os_memcpy(out, _out + skip, out_len);
3539af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	bin_clear_free(tmp_out, skip);
3540af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt
3541af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	return ret;
3542849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt#else /* OPENSSL_NEED_EAP_FAST_PRF */
3543849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt	wpa_printf(MSG_ERROR,
3544849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt		   "OpenSSL: EAP-FAST keys cannot be exported in FIPS mode");
3545849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt	return -1;
3546849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt#endif /* OPENSSL_NEED_EAP_FAST_PRF */
35478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf *
35518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtopenssl_handshake(struct tls_connection *conn, const struct wpabuf *in_data,
35528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  int server)
35538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
35558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *out_data;
35568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
35588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Give TLS handshake data from the server (if available) to OpenSSL
35598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * for processing.
35608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
3561d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (in_data && wpabuf_len(in_data) > 0 &&
35628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    BIO_write(conn->ssl_in, wpabuf_head(in_data), wpabuf_len(in_data))
35638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    < 0) {
35648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
35658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Handshake failed - BIO_write");
35668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
35678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
35688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Initiate TLS handshake or continue the existing handshake */
35708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (server)
35718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = SSL_accept(conn->ssl);
35728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
35738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = SSL_connect(conn->ssl);
35748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res != 1) {
35758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int err = SSL_get_error(conn->ssl, res);
35768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (err == SSL_ERROR_WANT_READ)
35778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want "
35788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "more data");
35798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (err == SSL_ERROR_WANT_WRITE)
35808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want to "
35818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "write");
35828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else {
35838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_INFO, __func__, "SSL_connect");
35848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->failed++;
35858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
35868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
35878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3588d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#ifdef CONFIG_SUITEB
3589d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if ((conn->flags & TLS_CONN_SUITEB) && !server &&
3590d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	    os_strncmp(SSL_get_cipher(conn->ssl), "DHE-", 4) == 0 &&
3591d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	    conn->server_dh_prime_len < 3072) {
3592d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		struct tls_context *context = conn->context;
3593d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
3594d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		/*
3595d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		 * This should not be reached since earlier cert_cb should have
3596d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		 * terminated the handshake. Keep this check here for extra
3597d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		 * protection if anything goes wrong with the more low-level
3598d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		 * checks based on having to parse the TLS handshake messages.
3599d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		 */
3600d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		wpa_printf(MSG_DEBUG,
3601d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			   "OpenSSL: Server DH prime length: %d bits",
3602d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			   conn->server_dh_prime_len);
3603d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
3604d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (context->event_cb) {
3605d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			union tls_event_data ev;
3606d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
3607d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			os_memset(&ev, 0, sizeof(ev));
3608d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			ev.alert.is_local = 1;
3609d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			ev.alert.type = "fatal";
3610d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			ev.alert.description = "insufficient security";
3611d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			context->event_cb(context->cb_ctx, TLS_ALERT, &ev);
3612d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		}
3613d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		/*
3614d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		 * Could send a TLS Alert to the server, but for now, simply
3615d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		 * terminate handshake.
3616d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		 */
3617d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		conn->failed++;
3618d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		conn->write_alerts++;
3619d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return NULL;
3620d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	}
3621d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#endif /* CONFIG_SUITEB */
3622d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
36238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Get the TLS handshake data to be sent to the server */
36248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = BIO_ctrl_pending(conn->ssl_out);
36258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res);
36268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	out_data = wpabuf_alloc(res);
36278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (out_data == NULL) {
36288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for "
36298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "handshake output (%d bytes)", res);
36308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (BIO_reset(conn->ssl_out) < 0) {
36318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_INFO, __func__,
36328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"BIO_reset failed");
36338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
36348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
36358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = res == 0 ? 0 : BIO_read(conn->ssl_out, wpabuf_mhead(out_data),
36378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      res);
36388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
36398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
36408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Handshake failed - BIO_read");
36418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (BIO_reset(conn->ssl_out) < 0) {
36428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_INFO, __func__,
36438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"BIO_reset failed");
36448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
36458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(out_data);
36468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
36478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put(out_data, res);
36498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return out_data;
36518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf *
36558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtopenssl_get_appl_data(struct tls_connection *conn, size_t max_len)
36568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *appl_data;
36588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
36598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	appl_data = wpabuf_alloc(max_len + 100);
36618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (appl_data == NULL)
36628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
36638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = SSL_read(conn->ssl, wpabuf_mhead(appl_data),
36658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       wpabuf_size(appl_data));
36668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
36678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int err = SSL_get_error(conn->ssl, res);
36688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (err == SSL_ERROR_WANT_READ ||
36698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    err == SSL_ERROR_WANT_WRITE) {
36708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "SSL: No Application Data "
36718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "included");
36728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
36738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_INFO, __func__,
36748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"Failed to read possible "
36758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"Application Data");
36768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
36778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(appl_data);
36788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
36798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put(appl_data, res);
36828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application Data in Finished "
36838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    "message", appl_data);
36848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return appl_data;
36868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf *
36908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtopenssl_connection_handshake(struct tls_connection *conn,
36918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     const struct wpabuf *in_data,
36928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     struct wpabuf **appl_data, int server)
36938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *out_data;
36958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (appl_data)
36978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*appl_data = NULL;
36988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	out_data = openssl_handshake(conn, in_data, server);
37008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (out_data == NULL)
37018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
370226af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen	if (conn->invalid_hb_used) {
370326af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen		wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response");
370426af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen		wpabuf_free(out_data);
370526af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen		return NULL;
370626af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen	}
37078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3708d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (SSL_is_init_finished(conn->ssl)) {
3709d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpa_printf(MSG_DEBUG,
3710d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   "OpenSSL: Handshake finished - resumed=%d",
3711d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   tls_connection_resumed(conn->ssl_ctx, conn));
3712d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (appl_data && in_data)
3713d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			*appl_data = openssl_get_appl_data(conn,
3714d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt							   wpabuf_len(in_data));
3715d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
37168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
371726af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen	if (conn->invalid_hb_used) {
371826af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen		wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response");
371926af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen		if (appl_data) {
372026af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen			wpabuf_free(*appl_data);
372126af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen			*appl_data = NULL;
372226af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen		}
372326af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen		wpabuf_free(out_data);
372426af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen		return NULL;
372526af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen	}
372626af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen
37278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return out_data;
37288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
37298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf *
37328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
37338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 const struct wpabuf *in_data,
37348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 struct wpabuf **appl_data)
37358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
37368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return openssl_connection_handshake(conn, in_data, appl_data, 0);
37378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
37388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_server_handshake(void *tls_ctx,
37418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						struct tls_connection *conn,
37428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						const struct wpabuf *in_data,
37438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						struct wpabuf **appl_data)
37448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
37458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return openssl_connection_handshake(conn, in_data, appl_data, 1);
37468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
37478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_encrypt(void *tls_ctx,
37508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct tls_connection *conn,
37518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const struct wpabuf *in_data)
37528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
37538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
37548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
37558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
37578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
37588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Give plaintext data for OpenSSL to encrypt into the TLS tunnel. */
37608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((res = BIO_reset(conn->ssl_in)) < 0 ||
37618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (res = BIO_reset(conn->ssl_out)) < 0) {
37628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
37638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
37648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = SSL_write(conn->ssl, wpabuf_head(in_data), wpabuf_len(in_data));
37668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
37678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
37688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Encryption failed - SSL_write");
37698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
37708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Read encrypted data to be sent to the server */
37738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
37748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
37758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
37768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = BIO_read(conn->ssl_out, wpabuf_mhead(buf), wpabuf_size(buf));
37778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
37788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
37798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Encryption failed - BIO_read");
37808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(buf);
37818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
37828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put(buf, res);
37848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
37868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
37878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_decrypt(void *tls_ctx,
37908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct tls_connection *conn,
37918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const struct wpabuf *in_data)
37928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
37938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
37948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
37958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Give encrypted data from TLS tunnel for OpenSSL to decrypt. */
37978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = BIO_write(conn->ssl_in, wpabuf_head(in_data),
37988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_len(in_data));
37998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
38008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
38018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Decryption failed - BIO_write");
38028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
38038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (BIO_reset(conn->ssl_out) < 0) {
38058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
38068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
38078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Read decrypted data for further processing */
38108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
38118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Even though we try to disable TLS compression, it is possible that
38128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * this cannot be done with all TLS libraries. Add extra buffer space
38138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * to handle the possibility of the decrypted data being longer than
38148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * input data.
38158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
38168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
38178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
38188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
38198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = SSL_read(conn->ssl, wpabuf_mhead(buf), wpabuf_size(buf));
38208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
38218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
38228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Decryption failed - SSL_read");
38238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(buf);
38248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
38258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put(buf, res);
38278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
382826af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen	if (conn->invalid_hb_used) {
382926af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen		wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response");
383026af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen		wpabuf_free(buf);
383126af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen		return NULL;
383226af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen	}
383326af48b2fcdee1b88e4092a9078cb7c9bf79da6eJouni Malinen
38348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
38358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
38398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3840216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	return conn ? SSL_cache_hit(conn->ssl) : 0;
38418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
38458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   u8 *ciphers)
38468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3847de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	char buf[500], *pos, *end;
38488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *c;
38498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
38508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL || conn->ssl == NULL || ciphers == NULL)
38528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
38538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf[0] = '\0';
38558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf;
38568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + sizeof(buf);
38578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	c = ciphers;
38598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (*c != TLS_CIPHER_NONE) {
38608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const char *suite;
38618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (*c) {
38638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case TLS_CIPHER_RC4_SHA:
38648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			suite = "RC4-SHA";
38658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
38668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case TLS_CIPHER_AES128_SHA:
38678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			suite = "AES128-SHA";
38688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
38698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case TLS_CIPHER_RSA_DHE_AES128_SHA:
38708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			suite = "DHE-RSA-AES128-SHA";
38718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
38728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case TLS_CIPHER_ANON_DH_AES128_SHA:
38738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			suite = "ADH-AES128-SHA";
38748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3875de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt		case TLS_CIPHER_RSA_DHE_AES256_SHA:
3876de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt			suite = "DHE-RSA-AES256-SHA";
3877de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt			break;
3878de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt		case TLS_CIPHER_AES256_SHA:
3879de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt			suite = "AES256-SHA";
3880de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt			break;
38818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
38828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLS: Unsupported "
38838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "cipher selection: %d", *c);
38848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
38858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
38868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, ":%s", suite);
38876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_snprintf_error(end - pos, ret))
38888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
38898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
38908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		c++;
38928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: cipher suites: %s", buf + 1);
38958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3896d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
3897d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
3898d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (os_strstr(buf, ":ADH-")) {
3899d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		/*
3900d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		 * Need to drop to security level 0 to allow anonymous
3901d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		 * cipher suites for EAP-FAST.
3902d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		 */
3903d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_set_security_level(conn->ssl, 0);
3904d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else if (SSL_get_security_level(conn->ssl) == 0) {
3905d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		/* Force at least security level 1 */
3906d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_set_security_level(conn->ssl, 1);
3907d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
3908d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
3909d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif
3910d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
39118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (SSL_set_cipher_list(conn->ssl, buf + 1) != 1) {
39128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
39138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Cipher suite configuration failed");
39148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
39158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
39188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3921d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtint tls_get_version(void *ssl_ctx, struct tls_connection *conn,
3922d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		    char *buf, size_t buflen)
3923d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
3924d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const char *name;
3925d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (conn == NULL || conn->ssl == NULL)
3926d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return -1;
3927d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3928d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	name = SSL_get_version(conn->ssl);
3929d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (name == NULL)
3930d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return -1;
3931d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3932d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_strlcpy(buf, name, buflen);
3933d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return 0;
3934d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
3935d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3936d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
39378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
39388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   char *buf, size_t buflen)
39398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *name;
39418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL || conn->ssl == NULL)
39428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
39438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	name = SSL_get_cipher(conn->ssl);
39458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (name == NULL)
39468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
39478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(buf, name, buflen);
39498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
39508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_enable_workaround(void *ssl_ctx,
39548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct tls_connection *conn)
39558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_set_options(conn->ssl, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
39578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
39598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
39638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* ClientHello TLS extensions require a patch to openssl, so this function is
39648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * commented out unless explicitly needed for EAP-FAST in order to be able to
39658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * build this file with unmodified openssl. */
39668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
39678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    int ext_type, const u8 *data,
39688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    size_t data_len)
39698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL || conn->ssl == NULL || ext_type != 35)
39718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
39728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (SSL_set_session_ticket_ext(conn->ssl, (void *) data,
39748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       data_len) != 1)
39758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
39768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
39788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
39808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
39838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
39858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
39868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return conn->failed;
39878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
39918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
39938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
39948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return conn->read_alerts;
39958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
39998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
40018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
40028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return conn->write_alerts;
40038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
400634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#ifdef HAVE_OCSP
400734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
400834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void ocsp_debug_print_resp(OCSP_RESPONSE *rsp)
400934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
401034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG
401134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	BIO *out;
401234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	size_t rlen;
401334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	char *txt;
401434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	int res;
401534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
401634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (wpa_debug_level > MSG_DEBUG)
401734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
401834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
401934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	out = BIO_new(BIO_s_mem());
402034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (!out)
402134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
402234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
402334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	OCSP_RESPONSE_print(out, rsp, 0);
402434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	rlen = BIO_ctrl_pending(out);
402534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	txt = os_malloc(rlen + 1);
402634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (!txt) {
402734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		BIO_free(out);
402834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
402934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
403034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
403134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	res = BIO_read(out, txt, rlen);
403234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (res > 0) {
403334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		txt[res] = '\0';
403434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP Response\n%s", txt);
403534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
403634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_free(txt);
403734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	BIO_free(out);
403834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */
403934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
404034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
404134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
4042717574375e969e8272c6d1a26137286eac158abbDmitry Shmidtstatic void debug_print_cert(X509 *cert, const char *title)
4043717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt{
4044717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG
4045717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	BIO *out;
4046717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	size_t rlen;
4047717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	char *txt;
4048717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	int res;
4049717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt
4050717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	if (wpa_debug_level > MSG_DEBUG)
4051717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt		return;
4052717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt
4053717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	out = BIO_new(BIO_s_mem());
4054717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	if (!out)
4055717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt		return;
4056717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt
4057717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	X509_print(out, cert);
4058717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	rlen = BIO_ctrl_pending(out);
4059717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	txt = os_malloc(rlen + 1);
4060717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	if (!txt) {
4061717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt		BIO_free(out);
4062717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt		return;
4063717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	}
4064717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt
4065717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	res = BIO_read(out, txt, rlen);
4066717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	if (res > 0) {
4067717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt		txt[res] = '\0';
4068717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: %s\n%s", title, txt);
4069717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	}
4070717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	os_free(txt);
4071717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt
4072717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	BIO_free(out);
4073717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */
4074717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt}
4075717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt
4076717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt
407734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int ocsp_resp_cb(SSL *s, void *arg)
407834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
407934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct tls_connection *conn = arg;
408034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	const unsigned char *p;
4081d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	int len, status, reason, res;
408234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	OCSP_RESPONSE *rsp;
408334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	OCSP_BASICRESP *basic;
408434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	OCSP_CERTID *id;
408534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	ASN1_GENERALIZEDTIME *produced_at, *this_update, *next_update;
4086fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	X509_STORE *store;
4087fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	STACK_OF(X509) *certs = NULL;
408834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
408934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	len = SSL_get_tlsext_status_ocsp_resp(s, &p);
409034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (!p) {
409134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: No OCSP response received");
409234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1;
409334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
409434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
409534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "OpenSSL: OCSP response", p, len);
409634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
409734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
409834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (!rsp) {
409934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "OpenSSL: Failed to parse OCSP response");
410034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 0;
410134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
410234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
410334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	ocsp_debug_print_resp(rsp);
410434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
410534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	status = OCSP_response_status(rsp);
410634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
410734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "OpenSSL: OCSP responder error %d (%s)",
410834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			   status, OCSP_response_status_str(status));
410934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 0;
411034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
411134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
411234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	basic = OCSP_response_get1_basic(rsp);
411334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (!basic) {
411434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "OpenSSL: Could not find BasicOCSPResponse");
411534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 0;
411634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
411734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
4118216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	store = SSL_CTX_get_cert_store(conn->ssl_ctx);
4119fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (conn->peer_issuer) {
4120717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt		debug_print_cert(conn->peer_issuer, "Add OCSP issuer");
4121fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
4122fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		if (X509_STORE_add_cert(store, conn->peer_issuer) != 1) {
4123fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			tls_show_errors(MSG_INFO, __func__,
41247f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt					"OpenSSL: Could not add issuer to certificate store");
4125fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		}
4126fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		certs = sk_X509_new_null();
4127fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		if (certs) {
4128fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			X509 *cert;
4129fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			cert = X509_dup(conn->peer_issuer);
4130fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			if (cert && !sk_X509_push(certs, cert)) {
4131fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				tls_show_errors(
4132fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt					MSG_INFO, __func__,
41337f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt					"OpenSSL: Could not add issuer to OCSP responder trust store");
4134fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				X509_free(cert);
4135fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				sk_X509_free(certs);
4136fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				certs = NULL;
4137fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			}
41387f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt			if (certs && conn->peer_issuer_issuer) {
4139fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				cert = X509_dup(conn->peer_issuer_issuer);
4140fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				if (cert && !sk_X509_push(certs, cert)) {
4141fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt					tls_show_errors(
4142fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt						MSG_INFO, __func__,
41437f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt						"OpenSSL: Could not add issuer's issuer to OCSP responder trust store");
4144fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt					X509_free(cert);
4145fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				}
4146fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			}
4147fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		}
4148fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	}
4149fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
4150fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	status = OCSP_basic_verify(basic, certs, store, OCSP_TRUSTOTHER);
4151fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	sk_X509_pop_free(certs, X509_free);
415234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (status <= 0) {
415334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
415434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				"OpenSSL: OCSP response failed verification");
415534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_BASICRESP_free(basic);
415634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_RESPONSE_free(rsp);
415734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 0;
415834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
415934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
416034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP response verification succeeded");
416134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
41625605286c30e1701491bd3af974ae423727750eddDmitry Shmidt	if (!conn->peer_cert) {
41635605286c30e1701491bd3af974ae423727750eddDmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Peer certificate not available for OCSP status check");
41645605286c30e1701491bd3af974ae423727750eddDmitry Shmidt		OCSP_BASICRESP_free(basic);
41655605286c30e1701491bd3af974ae423727750eddDmitry Shmidt		OCSP_RESPONSE_free(rsp);
41665605286c30e1701491bd3af974ae423727750eddDmitry Shmidt		return 0;
41675605286c30e1701491bd3af974ae423727750eddDmitry Shmidt	}
41685605286c30e1701491bd3af974ae423727750eddDmitry Shmidt
41695605286c30e1701491bd3af974ae423727750eddDmitry Shmidt	if (!conn->peer_issuer) {
41705605286c30e1701491bd3af974ae423727750eddDmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Peer issuer certificate not available for OCSP status check");
417134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_BASICRESP_free(basic);
417234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_RESPONSE_free(rsp);
417334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 0;
417434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
417534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
4176d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	id = OCSP_cert_to_id(EVP_sha256(), conn->peer_cert, conn->peer_issuer);
417734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (!id) {
4178d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		wpa_printf(MSG_DEBUG,
4179d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			   "OpenSSL: Could not create OCSP certificate identifier (SHA256)");
418034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_BASICRESP_free(basic);
418134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_RESPONSE_free(rsp);
418234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 0;
418334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
418434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
4185d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	res = OCSP_resp_find_status(basic, id, &status, &reason, &produced_at,
4186d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				    &this_update, &next_update);
4187d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (!res) {
4188d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		id = OCSP_cert_to_id(NULL, conn->peer_cert, conn->peer_issuer);
4189d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (!id) {
4190d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			wpa_printf(MSG_DEBUG,
4191d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				   "OpenSSL: Could not create OCSP certificate identifier (SHA1)");
4192d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			OCSP_BASICRESP_free(basic);
4193d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			OCSP_RESPONSE_free(rsp);
4194d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			return 0;
4195d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		}
4196d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
4197d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		res = OCSP_resp_find_status(basic, id, &status, &reason,
4198d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt					    &produced_at, &this_update,
4199d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt					    &next_update);
4200d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	}
4201d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
4202d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (!res) {
420334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "OpenSSL: Could not find current server certificate from OCSP response%s",
420434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			   (conn->flags & TLS_CONN_REQUIRE_OCSP) ? "" :
420534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			   " (OCSP not required)");
420657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		OCSP_CERTID_free(id);
420734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_BASICRESP_free(basic);
420834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_RESPONSE_free(rsp);
420934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1;
421034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
421157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	OCSP_CERTID_free(id);
421234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
421334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (!OCSP_check_validity(this_update, next_update, 5 * 60, -1)) {
421434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
421534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				"OpenSSL: OCSP status times invalid");
421634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_BASICRESP_free(basic);
421734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_RESPONSE_free(rsp);
421834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 0;
421934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
422034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
422134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	OCSP_BASICRESP_free(basic);
422234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	OCSP_RESPONSE_free(rsp);
422334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
422434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status for server certificate: %s",
422534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		   OCSP_cert_status_str(status));
422634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
422734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (status == V_OCSP_CERTSTATUS_GOOD)
422834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 1;
422934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (status == V_OCSP_CERTSTATUS_REVOKED)
423034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 0;
423134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (conn->flags & TLS_CONN_REQUIRE_OCSP) {
423234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP required");
423334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 0;
423434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
4235051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP was not required, so allow connection to continue");
423634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return 1;
423734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
423834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
423934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
424034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int ocsp_status_cb(SSL *s, void *arg)
424134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
424234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	char *tmp;
424334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	char *resp;
424434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	size_t len;
424534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
424634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (tls_global->ocsp_stapling_response == NULL) {
424734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - no response configured");
424834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return SSL_TLSEXT_ERR_OK;
424934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
425034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
425134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	resp = os_readfile(tls_global->ocsp_stapling_response, &len);
425234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (resp == NULL) {
425334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - could not read response file");
425434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		/* TODO: Build OCSPResponse with responseStatus = internalError
425534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		 */
425634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return SSL_TLSEXT_ERR_OK;
425734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
425834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - send cached response");
425934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	tmp = OPENSSL_malloc(len);
426034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (tmp == NULL) {
426134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		os_free(resp);
426234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return SSL_TLSEXT_ERR_ALERT_FATAL;
426334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
426434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
426534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_memcpy(tmp, resp, len);
426634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_free(resp);
426734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	SSL_set_tlsext_status_ocsp_resp(s, tmp, len);
426834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
426934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return SSL_TLSEXT_ERR_OK;
427034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
427134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
427234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#endif /* HAVE_OCSP */
427334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
427434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
42758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
42768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const struct tls_connection_params *params)
42778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4278d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct tls_data *data = tls_ctx;
42798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
42808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned long err;
42816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	int can_pkcs11 = 0;
42826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	const char *key_id = params->key_id;
42836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	const char *cert_id = params->cert_id;
42846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	const char *ca_cert_id = params->ca_cert_id;
42856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	const char *engine_id = params->engine ? params->engine_id : NULL;
42868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
42888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
42898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4290014a3ff83915745d57480e99b47e281a82143c79Dmitry Shmidt	if (params->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
4291014a3ff83915745d57480e99b47e281a82143c79Dmitry Shmidt		wpa_printf(MSG_INFO,
4292014a3ff83915745d57480e99b47e281a82143c79Dmitry Shmidt			   "OpenSSL: ocsp=3 not supported");
4293014a3ff83915745d57480e99b47e281a82143c79Dmitry Shmidt		return -1;
4294014a3ff83915745d57480e99b47e281a82143c79Dmitry Shmidt	}
4295014a3ff83915745d57480e99b47e281a82143c79Dmitry Shmidt
42966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	/*
42976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * If the engine isn't explicitly configured, and any of the
42986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * cert/key fields are actually PKCS#11 URIs, then automatically
42996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * use the PKCS#11 ENGINE.
43006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 */
43016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!engine_id || os_strcmp(engine_id, "pkcs11") == 0)
43026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		can_pkcs11 = 1;
43036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
43046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!key_id && params->private_key && can_pkcs11 &&
43056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	    os_strncmp(params->private_key, "pkcs11:", 7) == 0) {
43066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		can_pkcs11 = 2;
43076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		key_id = params->private_key;
43086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
43096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
43106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!cert_id && params->client_cert && can_pkcs11 &&
43116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	    os_strncmp(params->client_cert, "pkcs11:", 7) == 0) {
43126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		can_pkcs11 = 2;
43136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		cert_id = params->client_cert;
43146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
43156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
43166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!ca_cert_id && params->ca_cert && can_pkcs11 &&
43176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	    os_strncmp(params->ca_cert, "pkcs11:", 7) == 0) {
43186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		can_pkcs11 = 2;
43196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		ca_cert_id = params->ca_cert;
43206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
43216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
43226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	/* If we need to automatically enable the PKCS#11 ENGINE, do so. */
43236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (can_pkcs11 == 2 && !engine_id)
43246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		engine_id = "pkcs11";
43256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4326d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
43279839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
43286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (params->flags & TLS_CONN_EAP_FAST) {
43296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG,
43306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "OpenSSL: Use TLSv1_method() for EAP-FAST");
43316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (SSL_set_ssl_method(conn->ssl, TLSv1_method()) != 1) {
43326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			tls_show_errors(MSG_INFO, __func__,
43336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt					"Failed to set TLSv1_method() for EAP-FAST");
43346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
43356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		}
43366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
4337d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif
4338d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
43396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
43408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while ((err = ERR_get_error())) {
43418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s",
43428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__, ERR_error_string(err, NULL));
43438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
43448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (engine_id) {
43468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine");
43476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		ret = tls_engine_init(conn, engine_id, params->pin,
43486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				      key_id, cert_id, ca_cert_id);
43498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret)
43508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return ret;
43518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
43528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_connection_set_subject_match(conn,
43538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     params->subject_match,
4354051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt					     params->altsubject_match,
43552f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt					     params->suffix_match,
43562f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt					     params->domain_match))
43578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
43588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (engine_id && ca_cert_id) {
4360d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (tls_connection_engine_ca_cert(data, conn, ca_cert_id))
43618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
4362d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else if (tls_connection_ca_cert(data, conn, params->ca_cert,
43638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  params->ca_cert_blob,
43648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  params->ca_cert_blob_len,
43658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  params->ca_path))
43668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
43678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (engine_id && cert_id) {
43696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (tls_connection_engine_client_cert(conn, cert_id))
43708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
43718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (tls_connection_client_cert(conn, params->client_cert,
43728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      params->client_cert_blob,
43738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      params->client_cert_blob_len))
43748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
43758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (engine_id && key_id) {
43778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLS: Using private key from engine");
43788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_connection_engine_private_key(conn))
43798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
4380d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else if (tls_connection_private_key(data, conn,
43818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      params->private_key,
43828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      params->private_key_passwd,
43838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      params->private_key_blob,
43848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      params->private_key_blob_len)) {
43858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS: Failed to load private key '%s'",
43868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   params->private_key);
43878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
43888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
43898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_connection_dh(conn, params->dh_file)) {
43918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'",
43928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   params->dh_file);
43938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
43948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
43958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (params->openssl_ciphers &&
43976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	    SSL_set_cipher_list(conn->ssl, params->openssl_ciphers) != 1) {
43986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_INFO,
43996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "OpenSSL: Failed to set cipher string '%s'",
44006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   params->openssl_ciphers);
44016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return -1;
44026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
44036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4404d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (tls_set_conn_flags(conn, params->flags) < 0)
4405d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return -1;
440613ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt
4407d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef OPENSSL_IS_BORINGSSL
4408d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (params->flags & TLS_CONN_REQUEST_OCSP) {
4409d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_enable_ocsp_stapling(conn->ssl);
4410d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
4411d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#else /* OPENSSL_IS_BORINGSSL */
441234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#ifdef HAVE_OCSP
441334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (params->flags & TLS_CONN_REQUEST_OCSP) {
4414d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		SSL_CTX *ssl_ctx = data->ssl;
441534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		SSL_set_tlsext_status_type(conn->ssl, TLSEXT_STATUSTYPE_ocsp);
441634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_resp_cb);
441734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		SSL_CTX_set_tlsext_status_arg(ssl_ctx, conn);
441834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
4419d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#else /* HAVE_OCSP */
4420d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (params->flags & TLS_CONN_REQUIRE_OCSP) {
4421d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpa_printf(MSG_INFO,
4422d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   "OpenSSL: No OCSP support included - reject configuration");
4423d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return -1;
4424d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
4425d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (params->flags & TLS_CONN_REQUEST_OCSP) {
4426d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpa_printf(MSG_DEBUG,
4427d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   "OpenSSL: No OCSP support included - allow optional OCSP case to continue");
4428d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
442934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#endif /* HAVE_OCSP */
4430d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* OPENSSL_IS_BORINGSSL */
443134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
4432c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	conn->flags = params->flags;
4433c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
4434d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	tls_get_errors(data);
44358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
44378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
44388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_global_set_params(void *tls_ctx,
44418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const struct tls_connection_params *params)
44428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4443d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct tls_data *data = tls_ctx;
4444d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_CTX *ssl_ctx = data->ssl;
44458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned long err;
44468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while ((err = ERR_get_error())) {
44488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s",
44498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__, ERR_error_string(err, NULL));
44508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
44518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4452d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (tls_global_ca_cert(data, params->ca_cert) ||
4453d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	    tls_global_client_cert(data, params->client_cert) ||
4454d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	    tls_global_private_key(data, params->private_key,
4455d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				   params->private_key_passwd) ||
4456d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	    tls_global_dh(data, params->dh_file)) {
4457d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS: Failed to set global parameters");
44588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
44598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
44608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (params->openssl_ciphers &&
44626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	    SSL_CTX_set_cipher_list(ssl_ctx, params->openssl_ciphers) != 1) {
44636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_INFO,
44646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "OpenSSL: Failed to set cipher string '%s'",
44656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   params->openssl_ciphers);
44666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return -1;
44676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
44686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
446961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef SSL_OP_NO_TICKET
447061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (params->flags & TLS_CONN_DISABLE_SESSION_TICKET)
447161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TICKET);
447261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	else
447361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TICKET);
447461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /*  SSL_OP_NO_TICKET */
447561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
447634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#ifdef HAVE_OCSP
447734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_status_cb);
447834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	SSL_CTX_set_tlsext_status_arg(ssl_ctx, ssl_ctx);
447934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_free(tls_global->ocsp_stapling_response);
448034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (params->ocsp_stapling_response)
448134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		tls_global->ocsp_stapling_response =
448234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			os_strdup(params->ocsp_stapling_response);
448334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	else
448434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		tls_global->ocsp_stapling_response = NULL;
448534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#endif /* HAVE_OCSP */
448634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
44878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
44888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
44898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
44928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Pre-shared secred requires a patch to openssl, so this function is
44938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * commented out unless explicitly needed for EAP-FAST in order to be able to
44948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * build this file with unmodified openssl. */
44958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44961d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt#if (defined(OPENSSL_IS_BORINGSSL) || OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
44979ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidtstatic int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
44989ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt			   STACK_OF(SSL_CIPHER) *peer_ciphers,
44999ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt			   const SSL_CIPHER **cipher, void *arg)
45009ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt#else /* OPENSSL_IS_BORINGSSL */
45018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
45028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   STACK_OF(SSL_CIPHER) *peer_ciphers,
45038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   SSL_CIPHER **cipher, void *arg)
45049ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt#endif /* OPENSSL_IS_BORINGSSL */
45058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
45068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_connection *conn = arg;
45078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
45088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4509d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
45108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL || conn->session_ticket_cb == NULL)
45118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
45128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx,
45148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      conn->session_ticket,
45158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      conn->session_ticket_len,
45168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      s->s3->client_random,
45178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      s->s3->server_random, secret);
4518d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#else
4519d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	unsigned char client_random[SSL3_RANDOM_SIZE];
4520d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	unsigned char server_random[SSL3_RANDOM_SIZE];
4521d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
4522d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (conn == NULL || conn->session_ticket_cb == NULL)
4523d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return 0;
4524d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
4525d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_get_client_random(s, client_random, sizeof(client_random));
4526d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_get_server_random(s, server_random, sizeof(server_random));
4527d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
4528d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx,
4529d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				      conn->session_ticket,
4530d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				      conn->session_ticket_len,
4531d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				      client_random,
4532d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				      server_random, secret);
4533d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif
4534d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
45358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->session_ticket);
45368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->session_ticket = NULL;
45378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret <= 0)
45398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
45408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*secret_len = SSL_MAX_MASTER_KEY_LENGTH;
45428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 1;
45438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
45448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_session_ticket_ext_cb(SSL *s, const unsigned char *data,
45478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int len, void *arg)
45488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
45498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_connection *conn = arg;
45508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL || conn->session_ticket_cb == NULL)
45528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
45538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: %s: length=%d", __func__, len);
45558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->session_ticket);
45578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->session_ticket = NULL;
45588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket "
45608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    "extension", data, len);
45618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4562d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	conn->session_ticket = os_memdup(data, len);
45638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->session_ticket == NULL)
45648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
45658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->session_ticket_len = len;
45678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 1;
45698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
45708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
45718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_session_ticket_cb(void *tls_ctx,
45748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 struct tls_connection *conn,
45758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 tls_session_ticket_cb cb,
45768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 void *ctx)
45778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
45788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
45798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->session_ticket_cb = cb;
45808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->session_ticket_cb_ctx = ctx;
45818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cb) {
45838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb,
45848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      conn) != 1)
45858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
45868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_set_session_ticket_ext_cb(conn->ssl,
45878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      tls_session_ticket_ext_cb, conn);
45888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
45898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1)
45908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
45918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_set_session_ticket_ext_cb(conn->ssl, NULL, NULL);
45928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
45938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
45958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
45968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
45978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
45988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4599ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt
4600ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt
4601ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidtint tls_get_library_version(char *buf, size_t buf_len)
4602ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt{
46031d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
4604d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt	return os_snprintf(buf, buf_len, "OpenSSL build=%s run=%s",
4605d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt			   OPENSSL_VERSION_TEXT,
4606d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt			   OpenSSL_version(OPENSSL_VERSION));
4607d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt#else
4608ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	return os_snprintf(buf, buf_len, "OpenSSL build=%s run=%s",
4609ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt			   OPENSSL_VERSION_TEXT,
4610ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt			   SSLeay_version(SSLEAY_VERSION));
4611d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt#endif
4612ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt}
4613d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
4614d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
4615d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtvoid tls_connection_set_success_data(struct tls_connection *conn,
4616d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				     struct wpabuf *data)
4617d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
4618d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_SESSION *sess;
4619d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct wpabuf *old;
4620d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
4621d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (tls_ex_idx_session < 0)
4622d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		goto fail;
4623d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	sess = SSL_get_session(conn->ssl);
4624d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!sess)
4625d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		goto fail;
4626d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	old = SSL_SESSION_get_ex_data(sess, tls_ex_idx_session);
4627d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (old) {
4628d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Replacing old success data %p",
4629d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   old);
4630d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpabuf_free(old);
4631d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
4632d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (SSL_SESSION_set_ex_data(sess, tls_ex_idx_session, data) != 1)
4633d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		goto fail;
4634d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
4635d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: Stored success data %p", data);
4636d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	conn->success_data = 1;
4637d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return;
4638d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
4639d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtfail:
4640d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_printf(MSG_INFO, "OpenSSL: Failed to store success data");
4641d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpabuf_free(data);
4642d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
4643d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
4644d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
4645d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtvoid tls_connection_set_success_data_resumed(struct tls_connection *conn)
4646d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
4647d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_printf(MSG_DEBUG,
4648d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		   "OpenSSL: Success data accepted for resumed session");
4649d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	conn->success_data = 1;
4650d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
4651d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
4652d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
4653d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtconst struct wpabuf *
4654d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidttls_connection_get_success_data(struct tls_connection *conn)
4655d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
4656d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_SESSION *sess;
4657d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
4658d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (tls_ex_idx_session < 0 ||
4659d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	    !(sess = SSL_get_session(conn->ssl)))
4660d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return NULL;
4661d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return SSL_SESSION_get_ex_data(sess, tls_ex_idx_session);
4662d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
4663d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
4664d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
4665d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtvoid tls_connection_remove_session(struct tls_connection *conn)
4666d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
4667d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	SSL_SESSION *sess;
4668d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
4669d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	sess = SSL_get_session(conn->ssl);
4670d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!sess)
4671d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return;
4672d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
4673d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (SSL_CTX_remove_session(conn->ssl_ctx, sess) != 1)
4674d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpa_printf(MSG_DEBUG,
4675d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   "OpenSSL: Session was not cached");
4676d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	else
4677d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpa_printf(MSG_DEBUG,
4678d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   "OpenSSL: Removed cached session to disable session resumption");
4679d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
4680