tls_openssl.c revision 7d5c8f257a74ac0d12828962a492e8b84ef83923
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SSL/TLS interface functions for OpenSSL
334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * Copyright (c) 2004-2013, 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>
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <openssl/pkcs12.h>
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <openssl/x509v3.h>
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <openssl/engine.h>
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto.h"
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tls.h"
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OPENSSL_d2i_TYPE const unsigned char **
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OPENSSL_d2i_TYPE unsigned char **
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt#if defined(SSL_CTX_get_app_data) && defined(SSL_CTX_set_app_data)
38ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt#define OPENSSL_SUPPORTS_CTX_APP_DATA
39ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt#endif
40ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef SSL_F_SSL_SET_SESSION_TICKET_EXT
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef SSL_OP_NO_TICKET
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Session ticket override patch was merged into OpenSSL 0.9.9 tree on
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2008-11-15. This version uses a bit different API compared to the old patch.
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define CONFIG_OPENSSL_TICKET_OVERRIDE
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
51ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt#ifdef SSL_set_tlsext_status_type
52ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt#ifndef OPENSSL_NO_TLSEXT
53ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt#define HAVE_OCSP
54ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt#include <openssl/ocsp.h>
55ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt#endif /* OPENSSL_NO_TLSEXT */
56ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt#endif /* SSL_set_tlsext_status_type */
57ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt
583f3ca3bb849b192d41b99aae775f6fc52f67118dKenny Root#ifdef ANDROID
593f3ca3bb849b192d41b99aae775f6fc52f67118dKenny Root#include <openssl/pem.h>
603f3ca3bb849b192d41b99aae775f6fc52f67118dKenny Root#include <keystore/keystore_get.h>
613f3ca3bb849b192d41b99aae775f6fc52f67118dKenny Root
623f3ca3bb849b192d41b99aae775f6fc52f67118dKenny Rootstatic BIO * BIO_from_keystore(const char *key)
633f3ca3bb849b192d41b99aae775f6fc52f67118dKenny Root{
64ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt	BIO *bio = NULL;
65ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt	uint8_t *value = NULL;
66ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt	int length = keystore_get(key, strlen(key), &value);
67ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt	if (length != -1 && (bio = BIO_new(BIO_s_mem())) != NULL)
68ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt		BIO_write(bio, value, length);
69ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt	free(value);
70ff07917b8921a2a178ed9188a63b166af144ae53Dmitry Shmidt	return bio;
713f3ca3bb849b192d41b99aae775f6fc52f67118dKenny Root}
723f3ca3bb849b192d41b99aae775f6fc52f67118dKenny Root#endif /* ANDROID */
733f3ca3bb849b192d41b99aae775f6fc52f67118dKenny Root
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_openssl_ref_count = 0;
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
76ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidtstruct tls_context {
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void (*event_cb)(void *ctx, enum tls_event ev,
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 union tls_event_data *data);
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *cb_ctx;
801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int cert_in_cb;
8134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	char *ocsp_stapling_response;
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
84ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidtstatic struct tls_context *tls_global = NULL;
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct tls_connection {
88ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	struct tls_context *context;
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL *ssl;
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BIO *ssl_in, *ssl_out;
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ENGINE *engine;        /* functional reference to the engine */
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EVP_PKEY *private_key; /* the private key if using engine */
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
95051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	char *subject_match, *altsubject_match, *suffix_match;
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int read_alerts, write_alerts, failed;
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_session_ticket_cb session_ticket_cb;
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *session_ticket_cb_ctx;
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* SessionTicket received from OpenSSL hello_extension_cb (server) */
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *session_ticket;
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t session_ticket_len;
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int ca_cert_verify:1;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int cert_probe:1;
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int server_cert_only:1;
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 srv_cert_hash[32];
110c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
111c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	unsigned int flags;
11234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
11334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	X509 *peer_cert;
11434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	X509 *peer_issuer;
115fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	X509 *peer_issuer_issuer;
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
119ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidtstatic struct tls_context * tls_context_new(const struct tls_config *conf)
120ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt{
121ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	struct tls_context *context = os_zalloc(sizeof(*context));
122ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	if (context == NULL)
123ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		return NULL;
124ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	if (conf) {
125ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		context->event_cb = conf->event_cb;
126ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		context->cb_ctx = conf->cb_ctx;
127ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		context->cert_in_cb = conf->cert_in_cb;
128ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	}
129ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	return context;
130ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt}
131ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt
132ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_NO_STDOUT_DEBUG
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void _tls_show_errors(void)
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned long err;
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while ((err = ERR_get_error())) {
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Just ignore the errors, since stdout is disabled */
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define tls_show_errors(l, f, t) _tls_show_errors()
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_NO_STDOUT_DEBUG */
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void tls_show_errors(int level, const char *func, const char *txt)
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned long err;
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(level, "OpenSSL: %s - %s %s",
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   func, txt, ERR_error_string(ERR_get_error(), NULL));
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while ((err = ERR_get_error())) {
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "OpenSSL: pending error: %s",
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(err, NULL));
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_NATIVE_WINDOWS
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Windows CryptoAPI and access to certificate stores */
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <wincrypt.h>
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef __MINGW32_VERSION
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * MinGW does not yet include all the needed definitions for CryptoAPI, so
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * define here whatever extra is needed.
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define CERT_SYSTEM_STORE_CURRENT_USER (1 << 16)
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define CERT_STORE_READONLY_FLAG 0x00008000
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __MINGW32_VERSION */
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct cryptoapi_rsa_data {
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const CERT_CONTEXT *cert;
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTPROV crypt_prov;
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD key_spec;
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BOOL free_crypt_prov;
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void cryptoapi_error(const char *msg)
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_INFO, "CryptoAPI: %s; err=%u",
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   msg, (unsigned int) GetLastError());
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int cryptoapi_rsa_pub_enc(int flen, const unsigned char *from,
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 unsigned char *to, RSA *rsa, int padding)
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int cryptoapi_rsa_pub_dec(int flen, const unsigned char *from,
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 unsigned char *to, RSA *rsa, int padding)
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int cryptoapi_rsa_priv_enc(int flen, const unsigned char *from,
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  unsigned char *to, RSA *rsa, int padding)
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct cryptoapi_rsa_data *priv =
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		(struct cryptoapi_rsa_data *) rsa->meth->app_data;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTHASH hash;
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD hash_size, len, i;
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char *buf = NULL;
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 0;
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv == NULL) {
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       ERR_R_PASSED_NULL_PARAMETER);
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (padding != RSA_PKCS1_PADDING) {
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       RSA_R_UNKNOWN_PADDING_TYPE);
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (flen != 16 /* MD5 */ + 20 /* SHA-1 */) {
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "%s - only MD5-SHA1 hash supported",
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__);
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       RSA_R_INVALID_MESSAGE_LENGTH);
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptCreateHash(priv->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash))
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_error("CryptCreateHash failed");
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = sizeof(hash_size);
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptGetHashParam(hash, HP_HASHSIZE, (BYTE *) &hash_size, &len,
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       0)) {
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_error("CryptGetHashParam failed");
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((int) hash_size != flen) {
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "CryptoAPI: Invalid hash size (%u != %d)",
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned) hash_size, flen);
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       RSA_R_INVALID_MESSAGE_LENGTH);
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptSetHashParam(hash, HP_HASHVAL, (BYTE * ) from, 0)) {
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_error("CryptSetHashParam failed");
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = RSA_size(rsa);
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_malloc(len);
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL) {
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptSignHash(hash, priv->key_spec, NULL, 0, buf, &len)) {
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_error("CryptSignHash failed");
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < len; i++)
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		to[i] = buf[len - i - 1];
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = len;
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterr:
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CryptDestroyHash(hash);
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int cryptoapi_rsa_priv_dec(int flen, const unsigned char *from,
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  unsigned char *to, RSA *rsa, int padding)
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void cryptoapi_free_data(struct cryptoapi_rsa_data *priv)
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv == NULL)
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->crypt_prov && priv->free_crypt_prov)
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CryptReleaseContext(priv->crypt_prov, 0);
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->cert)
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CertFreeCertificateContext(priv->cert);
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(priv);
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int cryptoapi_finish(RSA *rsa)
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cryptoapi_free_data((struct cryptoapi_rsa_data *) rsa->meth->app_data);
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free((void *) rsa->meth);
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa->meth = NULL;
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 1;
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const CERT_CONTEXT * cryptoapi_find_cert(const char *name, DWORD store)
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCERTSTORE cs;
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const CERT_CONTEXT *ret = NULL;
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0,
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   store | CERT_STORE_OPEN_EXISTING_FLAG |
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   CERT_STORE_READONLY_FLAG, L"MY");
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cs == NULL) {
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_error("Failed to open 'My system store'");
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (strncmp(name, "cert://", 7) == 0) {
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unsigned short wbuf[255];
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MultiByteToWideChar(CP_ACP, 0, name + 7, -1, wbuf, 255);
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = CertFindCertificateInStore(cs, X509_ASN_ENCODING |
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 PKCS_7_ASN_ENCODING,
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 0, CERT_FIND_SUBJECT_STR,
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 wbuf, NULL);
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (strncmp(name, "hash://", 7) == 0) {
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CRYPT_HASH_BLOB blob;
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int len;
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const char *hash = name + 7;
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unsigned char *buf;
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = os_strlen(hash) / 2;
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf = os_malloc(len);
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (buf && hexstr2bin(hash, buf, len) == 0) {
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			blob.cbData = len;
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			blob.pbData = buf;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = CertFindCertificateInStore(cs,
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							 X509_ASN_ENCODING |
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							 PKCS_7_ASN_ENCODING,
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							 0, CERT_FIND_HASH,
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							 &blob, NULL);
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CertCloseStore(cs, 0);
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_cryptoapi_cert(SSL *ssl, const char *name)
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509 *cert = NULL;
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RSA *rsa = NULL, *pub_rsa;
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct cryptoapi_rsa_data *priv;
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RSA_METHOD *rsa_meth;
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (name == NULL ||
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (strncmp(name, "cert://", 7) != 0 &&
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     strncmp(name, "hash://", 7) != 0))
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	priv = os_zalloc(sizeof(*priv));
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_meth = os_zalloc(sizeof(*rsa_meth));
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv == NULL || rsa_meth == NULL) {
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "CryptoAPI: Failed to allocate memory "
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "for CryptoAPI RSA method");
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(priv);
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(rsa_meth);
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	priv->cert = cryptoapi_find_cert(name, CERT_SYSTEM_STORE_CURRENT_USER);
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->cert == NULL) {
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		priv->cert = cryptoapi_find_cert(
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			name, CERT_SYSTEM_STORE_LOCAL_MACHINE);
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->cert == NULL) {
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "CryptoAPI: Could not find certificate "
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "'%s'", name);
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &priv->cert->pbCertEncoded,
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			priv->cert->cbCertEncoded);
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cert == NULL) {
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "CryptoAPI: Could not process X509 DER "
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "encoding");
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptAcquireCertificatePrivateKey(priv->cert,
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       NULL, &priv->crypt_prov,
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       &priv->key_spec,
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       &priv->free_crypt_prov)) {
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_error("Failed to acquire a private key for the "
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"certificate");
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_meth->name = "Microsoft CryptoAPI RSA Method";
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_meth->rsa_pub_enc = cryptoapi_rsa_pub_enc;
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_meth->rsa_pub_dec = cryptoapi_rsa_pub_dec;
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_meth->rsa_priv_enc = cryptoapi_rsa_priv_enc;
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_meth->rsa_priv_dec = cryptoapi_rsa_priv_dec;
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_meth->finish = cryptoapi_finish;
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_meth->flags = RSA_METHOD_FLAG_NO_CHECK;
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_meth->app_data = (char *) priv;
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa = RSA_new();
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rsa == NULL) {
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       ERR_R_MALLOC_FAILURE);
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!SSL_use_certificate(ssl, cert)) {
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSA_free(rsa);
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rsa = NULL;
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pub_rsa = cert->cert_info->key->pkey->pkey.rsa;
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509_free(cert);
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cert = NULL;
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa->n = BN_dup(pub_rsa->n);
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa->e = BN_dup(pub_rsa->e);
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!RSA_set_method(rsa, rsa_meth))
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!SSL_use_RSAPrivateKey(ssl, rsa))
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RSA_free(rsa);
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterr:
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cert)
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509_free(cert);
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rsa)
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSA_free(rsa);
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(rsa_meth);
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_free_data(priv);
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_cryptoapi_ca_cert(SSL_CTX *ssl_ctx, SSL *ssl, const char *name)
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCERTSTORE cs;
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PCCERT_CONTEXT ctx = NULL;
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509 *cert;
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[128];
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *store;
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef UNICODE
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WCHAR *wstore;
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* UNICODE */
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (name == NULL || strncmp(name, "cert_store://", 13) != 0)
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	store = name + 13;
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef UNICODE
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wstore = os_malloc((os_strlen(store) + 1) * sizeof(WCHAR));
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wstore == NULL)
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wsprintf(wstore, L"%S", store);
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cs = CertOpenSystemStore(0, wstore);
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(wstore);
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* UNICODE */
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cs = CertOpenSystemStore(0, store);
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* UNICODE */
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cs == NULL) {
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: failed to open system cert store "
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "'%s': error=%d", __func__, store,
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while ((ctx = CertEnumCertificatesInStore(cs, ctx))) {
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &ctx->pbCertEncoded,
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				ctx->cbCertEncoded);
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cert == NULL) {
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "CryptoAPI: Could not process "
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "X509 DER encoding for CA cert");
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509_NAME_oneline(X509_get_subject_name(cert), buf,
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sizeof(buf));
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Loaded CA certificate for "
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "system certificate store: subject='%s'", buf);
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) {
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_WARNING, __func__,
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"Failed to add ca_cert to OpenSSL "
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"certificate store");
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509_free(cert);
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CertCloseStore(cs, 0)) {
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: failed to close system cert store "
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "'%s': error=%d", __func__, name + 13,
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_NATIVE_WINDOWS */
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_cryptoapi_cert(SSL *ssl, const char *name)
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ssl_info_cb(const SSL *ssl, int where, int ret)
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *str;
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int w;
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "SSL: (where=0x%x ret=0x%x)", where, ret);
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	w = where & ~SSL_ST_MASK;
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (w & SSL_ST_CONNECT)
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		str = "SSL_connect";
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (w & SSL_ST_ACCEPT)
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		str = "SSL_accept";
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		str = "undefined";
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (where & SSL_CB_LOOP) {
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: %s:%s",
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   str, SSL_state_string_long(ssl));
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (where & SSL_CB_ALERT) {
558ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		struct tls_connection *conn = SSL_get_app_data((SSL *) ssl);
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "SSL: SSL3 alert: %s:%s:%s",
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   where & SSL_CB_READ ?
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "read (remote end reported an error)" :
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "write (local SSL3 detected an error)",
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   SSL_alert_type_string_long(ret),
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   SSL_alert_desc_string_long(ret));
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((ret >> 8) == SSL3_AL_FATAL) {
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (where & SSL_CB_READ)
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				conn->read_alerts++;
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				conn->write_alerts++;
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
571ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		if (conn->context->event_cb != NULL) {
57204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			union tls_event_data ev;
573ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt			struct tls_context *context = conn->context;
57404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			os_memset(&ev, 0, sizeof(ev));
57504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			ev.alert.is_local = !(where & SSL_CB_READ);
57604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			ev.alert.type = SSL_alert_type_string_long(ret);
57704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			ev.alert.description = SSL_alert_desc_string_long(ret);
578ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt			context->event_cb(context->cb_ctx, TLS_ALERT, &ev);
57904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (where & SSL_CB_EXIT && ret <= 0) {
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s",
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   str, ret == 0 ? "failed" : "error",
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   SSL_state_string_long(ssl));
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tls_engine_load_dynamic_generic - load any openssl engine
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pre: an array of commands and values that load an engine initialized
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *       in the engine specific function
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @post: an array of commands and values that initialize an already loaded
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *        engine (or %NULL if not required)
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @id: the engine id of the engine to load (only required if post is not %NULL
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is a generic function that loads any openssl engine.
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_engine_load_dynamic_generic(const char *pre[],
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   const char *post[], const char *id)
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ENGINE *engine;
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *dynamic_id = "dynamic";
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	engine = ENGINE_by_id(id);
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (engine) {
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ENGINE_free(engine);
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "ENGINE: engine '%s' is already "
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "available", id);
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ERR_clear_error();
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	engine = ENGINE_by_id(dynamic_id);
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (engine == NULL) {
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]",
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   dynamic_id,
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(ERR_get_error(), NULL));
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Perform the pre commands. This will load the engine. */
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pre && pre[0]) {
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", pre[0], pre[1]);
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ENGINE_ctrl_cmd_string(engine, pre[0], pre[1], 0) == 0) {
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "ENGINE: ctrl cmd_string failed: "
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "%s %s [%s]", pre[0], pre[1],
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   ERR_error_string(ERR_get_error(), NULL));
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ENGINE_free(engine);
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pre += 2;
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Free the reference to the "dynamic" engine. The loaded engine can
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * now be looked up using ENGINE_by_id().
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ENGINE_free(engine);
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	engine = ENGINE_by_id(id);
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (engine == NULL) {
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]",
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   id, ERR_error_string(ERR_get_error(), NULL));
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (post && post[0]) {
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", post[0], post[1]);
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ENGINE_ctrl_cmd_string(engine, post[0], post[1], 0) == 0) {
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "ENGINE: ctrl cmd_string failed:"
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" %s %s [%s]", post[0], post[1],
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   ERR_error_string(ERR_get_error(), NULL));
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ENGINE_remove(engine);
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ENGINE_free(engine);
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		post += 2;
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ENGINE_free(engine);
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tls_engine_load_dynamic_pkcs11 - load the pkcs11 engine provided by opensc
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pkcs11_so_path: pksc11_so_path from the configuration
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pcks11_module_path: pkcs11_module_path from the configuration
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_engine_load_dynamic_pkcs11(const char *pkcs11_so_path,
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const char *pkcs11_module_path)
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *engine_id = "pkcs11";
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *pre_cmd[] = {
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"SO_PATH", NULL /* pkcs11_so_path */,
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"ID", NULL /* engine_id */,
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"LIST_ADD", "1",
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* "NO_VCHECK", "1", */
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"LOAD", NULL,
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NULL, NULL
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	};
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *post_cmd[] = {
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"MODULE_PATH", NULL /* pkcs11_module_path */,
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NULL, NULL
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	};
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!pkcs11_so_path || !pkcs11_module_path)
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pre_cmd[1] = pkcs11_so_path;
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pre_cmd[3] = engine_id;
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	post_cmd[1] = pkcs11_module_path;
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "ENGINE: Loading pkcs11 Engine from %s",
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   pkcs11_so_path);
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return tls_engine_load_dynamic_generic(pre_cmd, post_cmd, engine_id);
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tls_engine_load_dynamic_opensc - load the opensc engine provided by opensc
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @opensc_so_path: opensc_so_path from the configuration
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_engine_load_dynamic_opensc(const char *opensc_so_path)
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *engine_id = "opensc";
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *pre_cmd[] = {
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"SO_PATH", NULL /* opensc_so_path */,
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"ID", NULL /* engine_id */,
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"LIST_ADD", "1",
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"LOAD", NULL,
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NULL, NULL
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	};
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!opensc_so_path)
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pre_cmd[1] = opensc_so_path;
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pre_cmd[3] = engine_id;
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "ENGINE: Loading OpenSC Engine from %s",
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   opensc_so_path);
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return tls_engine_load_dynamic_generic(pre_cmd, NULL, engine_id);
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * tls_init(const struct tls_config *conf)
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX *ssl;
736ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	struct tls_context *context;
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_openssl_ref_count == 0) {
739ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		tls_global = context = tls_context_new(conf);
740ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		if (context == NULL)
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_FIPS
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef OPENSSL_FIPS
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conf && conf->fips_mode) {
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (!FIPS_mode_set(1)) {
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_ERROR, "Failed to enable FIPS "
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "mode");
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				ERR_load_crypto_strings();
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				ERR_print_errors_fp(stderr);
75061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				os_free(tls_global);
75161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				tls_global = NULL;
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_INFO, "Running in FIPS mode");
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_FIPS */
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conf && conf->fips_mode) {
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "FIPS mode requested, but not "
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "supported");
76061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			os_free(tls_global);
76161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			tls_global = NULL;
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_FIPS */
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_FIPS */
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_load_error_strings();
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_library_init();
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EVP_add_digest(EVP_sha256());
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_SHA256 */
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: if /dev/urandom is available, PRNG is seeded
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * automatically. If this is not the case, random data should
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * be added here. */
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PKCS12_FUNCS
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_RC2
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * 40-bit RC2 is commonly used in PKCS#12 files, so enable it.
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * This is enabled by PKCS12_PBE_add() in OpenSSL 0.9.8
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * versions, but it looks like OpenSSL 1.0.0 does not do that
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * anymore.
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EVP_add_cipher(EVP_rc2_40_cbc());
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_RC2 */
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		PKCS12_PBE_add();
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif  /* PKCS12_FUNCS */
787ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	} else {
788ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
789ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		/* Newer OpenSSL can store app-data per-SSL */
790ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		context = tls_context_new(conf);
791ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		if (context == NULL)
792ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt			return NULL;
7937d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt#else /* OPENSSL_SUPPORTS_CTX_APP_DATA */
7947d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt		context = tls_global;
795ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_openssl_ref_count++;
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssl = SSL_CTX_new(TLSv1_method());
800ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	if (ssl == NULL) {
801ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		tls_openssl_ref_count--;
80268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
80368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		if (context != tls_global)
80468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt			os_free(context);
80568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
806ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		if (tls_openssl_ref_count == 0) {
807ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt			os_free(tls_global);
808ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt			tls_global = NULL;
809ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		}
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
811ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	}
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX_set_info_callback(ssl, ssl_info_cb);
814ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
815ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	SSL_CTX_set_app_data(ssl, context);
816ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf &&
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (conf->opensc_engine_path || conf->pkcs11_engine_path ||
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     conf->pkcs11_module_path)) {
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "ENGINE: Loading dynamic engine");
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ERR_load_ENGINE_strings();
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ENGINE_load_dynamic();
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_engine_load_dynamic_opensc(conf->opensc_engine_path) ||
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    tls_engine_load_dynamic_pkcs11(conf->pkcs11_engine_path,
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   conf->pkcs11_module_path)) {
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_deinit(ssl);
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ssl;
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tls_deinit(void *ssl_ctx)
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX *ssl = ssl_ctx;
842ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
843ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	struct tls_context *context = SSL_CTX_get_app_data(ssl);
844ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	if (context != tls_global)
845ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		os_free(context);
846ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX_free(ssl);
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_openssl_ref_count--;
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_openssl_ref_count == 0) {
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ENGINE_cleanup();
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CRYPTO_cleanup_all_ex_data();
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ERR_remove_state(0);
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ERR_free_strings();
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EVP_cleanup();
85834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		os_free(tls_global->ocsp_stapling_response);
85934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		tls_global->ocsp_stapling_response = NULL;
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(tls_global);
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_global = NULL;
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_engine_init(struct tls_connection *conn, const char *engine_id,
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   const char *pin, const char *key_id,
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   const char *cert_id, const char *ca_cert_id)
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = -1;
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (engine_id == NULL) {
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "ENGINE: Engine ID not set");
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
876db3c5a43353099fd4771f3b7a13efae905878ce9Kenny Root#ifndef ANDROID
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pin == NULL) {
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "ENGINE: Smartcard PIN not set");
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
881db3c5a43353099fd4771f3b7a13efae905878ce9Kenny Root#endif
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key_id == NULL) {
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "ENGINE: Key Id not set");
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ERR_clear_error();
888db3c5a43353099fd4771f3b7a13efae905878ce9Kenny Root#ifdef ANDROID
889db3c5a43353099fd4771f3b7a13efae905878ce9Kenny Root	ENGINE_load_dynamic();
890db3c5a43353099fd4771f3b7a13efae905878ce9Kenny Root#endif
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->engine = ENGINE_by_id(engine_id);
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!conn->engine) {
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "ENGINE: engine %s not available [%s]",
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   engine_id, ERR_error_string(ERR_get_error(), NULL));
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ENGINE_init(conn->engine) != 1) {
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "ENGINE: engine init failed "
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(engine: %s) [%s]", engine_id,
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(ERR_get_error(), NULL));
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "ENGINE: engine initialized");
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
905db3c5a43353099fd4771f3b7a13efae905878ce9Kenny Root#ifndef ANDROID
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ENGINE_ctrl_cmd_string(conn->engine, "PIN", pin, 0) == 0) {
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "ENGINE: cannot set pin [%s]",
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(ERR_get_error(), NULL));
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
911db3c5a43353099fd4771f3b7a13efae905878ce9Kenny Root#endif
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* load private key first in-case PIN is required for cert */
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->private_key = ENGINE_load_private_key(conn->engine,
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    key_id, NULL, NULL);
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!conn->private_key) {
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "ENGINE: cannot load private key with id"
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" '%s' [%s]", key_id,
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(ERR_get_error(), NULL));
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* handle a certificate and/or CA certificate */
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cert_id || ca_cert_id) {
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const char *cmd_name = "LOAD_CERT_CTRL";
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* test if the engine supports a LOAD_CERT_CTRL */
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!ENGINE_ctrl(conn->engine, ENGINE_CTRL_GET_CMD_FROM_NAME,
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 0, (void *)cmd_name, NULL)) {
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "ENGINE: engine does not support"
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " loading certificates");
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto err;
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterr:
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->engine) {
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ENGINE_free(conn->engine);
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->engine = NULL;
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->private_key) {
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EVP_PKEY_free(conn->private_key);
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->private_key = NULL;
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_ENGINE */
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void tls_engine_deinit(struct tls_connection *conn)
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "ENGINE: engine deinit");
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->private_key) {
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EVP_PKEY_free(conn->private_key);
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->private_key = NULL;
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->engine) {
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ENGINE_finish(conn->engine);
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->engine = NULL;
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_get_errors(void *ssl_ctx)
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int count = 0;
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned long err;
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while ((err = ERR_get_error())) {
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS - SSL error: %s",
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(err, NULL));
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		count++;
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return count;
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct tls_connection * tls_connection_init(void *ssl_ctx)
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX *ssl = ssl_ctx;
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_connection *conn;
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	long options;
992ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
9937d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt	struct tls_context *context = SSL_CTX_get_app_data(ssl);
9947d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt#else /* OPENSSL_SUPPORTS_CTX_APP_DATA */
9957d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt	struct tls_context *context = tls_global;
996ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn = os_zalloc(sizeof(*conn));
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->ssl = SSL_new(ssl);
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->ssl == NULL) {
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to initialize new SSL connection");
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(conn);
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1009ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	conn->context = context;
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_set_app_data(conn->ssl, conn);
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_OP_SINGLE_DH_USE;
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef SSL_OP_NO_COMPRESSION
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	options |= SSL_OP_NO_COMPRESSION;
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* SSL_OP_NO_COMPRESSION */
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_set_options(conn->ssl, options);
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->ssl_in = BIO_new(BIO_s_mem());
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!conn->ssl_in) {
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to create a new BIO for ssl_in");
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_free(conn->ssl);
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(conn);
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->ssl_out = BIO_new(BIO_s_mem());
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!conn->ssl_out) {
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to create a new BIO for ssl_out");
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_free(conn->ssl);
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		BIO_free(conn->ssl_in);
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(conn);
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_set_bio(conn->ssl, conn->ssl_in, conn->ssl_out);
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return conn;
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_free(conn->ssl);
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_engine_deinit(conn);
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->subject_match);
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->altsubject_match);
1051051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	os_free(conn->suffix_match);
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->session_ticket);
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn);
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return conn ? SSL_is_init_finished(conn->ssl) : 0;
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Shutdown previous TLS connection without notifying the peer
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * because the connection was already terminated in practice
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * and "close notify" shutdown alert would confuse AS. */
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_set_quiet_shutdown(conn->ssl, 1);
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_shutdown(conn->ssl);
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_match_altsubject_component(X509 *cert, int type,
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const char *value, size_t len)
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	GENERAL_NAME *gen;
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *ext;
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i, found = 0;
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gen = sk_GENERAL_NAME_value(ext, i);
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (gen->type != type)
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strlen((char *) gen->d.ia5->data) == len &&
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(value, gen->d.ia5->data, len) == 0)
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			found++;
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return found;
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_match_altsubject(X509 *cert, const char *match)
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int type;
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *pos, *end;
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = match;
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	do {
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strncmp(pos, "EMAIL:", 6) == 0) {
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			type = GEN_EMAIL;
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 6;
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (os_strncmp(pos, "DNS:", 4) == 0) {
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			type = GEN_DNS;
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 4;
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (os_strncmp(pos, "URI:", 4) == 0) {
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			type = GEN_URI;
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 4;
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "TLS: Invalid altSubjectName "
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "match '%s'", pos);
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = os_strchr(pos, ';');
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (end) {
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (os_strncmp(end + 1, "EMAIL:", 6) == 0 ||
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    os_strncmp(end + 1, "DNS:", 4) == 0 ||
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    os_strncmp(end + 1, "URI:", 4) == 0)
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end = os_strchr(end + 1, ';');
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end)
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = end - pos;
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = os_strlen(pos);
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_match_altsubject_component(cert, type, pos, len) > 0)
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1;
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = end + 1;
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} while (end);
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1142fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
1143051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtstatic int domain_suffix_match(const u8 *val, size_t len, const char *match)
1144051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{
1145051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	size_t i, match_len;
1146051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1147051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	/* Check for embedded nuls that could mess up suffix matching */
1148051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	for (i = 0; i < len; i++) {
1149051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		if (val[i] == '\0') {
1150051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLS: Embedded null in a string - reject");
1151051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			return 0;
1152051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		}
1153051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
1154051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1155051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	match_len = os_strlen(match);
1156051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (match_len > len)
1157051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return 0;
1158051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1159051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (os_strncasecmp((const char *) val + len - match_len, match,
1160051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			   match_len) != 0)
1161051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return 0; /* no match */
1162051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1163051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (match_len == len)
1164051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return 1; /* exact match */
1165051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1166051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (val[len - match_len - 1] == '.')
1167051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return 1; /* full label match completes suffix match */
1168051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1169051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLS: Reject due to incomplete label match");
1170051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	return 0;
1171051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt}
1172fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
1173051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1174051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1175051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtstatic int tls_match_suffix(X509 *cert, const char *match)
1176051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{
1177fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt#ifdef CONFIG_NATIVE_WINDOWS
1178fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	/* wincrypt.h has conflicting X509_NAME definition */
1179fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	return -1;
1180fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt#else /* CONFIG_NATIVE_WINDOWS */
1181051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	GENERAL_NAME *gen;
1182051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	void *ext;
1183051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	int i;
1184051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	int dns_name = 0;
1185051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	X509_NAME *name;
1186051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1187051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLS: Match domain against suffix %s", match);
1188051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1189051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
1190051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1191051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
1192051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		gen = sk_GENERAL_NAME_value(ext, i);
1193051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		if (gen->type != GEN_DNS)
1194051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			continue;
1195051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		dns_name++;
1196051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate dNSName",
1197051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt				  gen->d.dNSName->data,
1198051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt				  gen->d.dNSName->length);
1199051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		if (domain_suffix_match(gen->d.dNSName->data,
1200051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt					gen->d.dNSName->length, match) == 1) {
1201051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLS: Suffix match in dNSName found");
1202051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			return 1;
1203051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		}
1204051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
1205051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1206051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (dns_name) {
1207051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLS: None of the dNSName(s) matched");
1208051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return 0;
1209051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
1210051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1211051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	name = X509_get_subject_name(cert);
1212051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	i = -1;
1213051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	for (;;) {
1214051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		X509_NAME_ENTRY *e;
1215051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		ASN1_STRING *cn;
1216051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1217051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		i = X509_NAME_get_index_by_NID(name, NID_commonName, i);
1218051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		if (i == -1)
1219051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			break;
1220051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		e = X509_NAME_get_entry(name, i);
1221051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		if (e == NULL)
1222051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			continue;
1223051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		cn = X509_NAME_ENTRY_get_data(e);
1224051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		if (cn == NULL)
1225051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			continue;
1226051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate commonName",
1227051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt				  cn->data, cn->length);
1228051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		if (domain_suffix_match(cn->data, cn->length, match) == 1) {
1229051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLS: Suffix match in commonName found");
1230051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			return 1;
1231051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		}
1232051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
1233051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1234051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLS: No CommonName suffix match found");
1235051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	return 0;
1236fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
1237051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt}
1238051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1239051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum tls_fail_reason openssl_tls_fail_reason(int err)
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (err) {
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_CERT_REVOKED:
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TLS_FAIL_REVOKED;
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_CERT_NOT_YET_VALID:
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_CRL_NOT_YET_VALID:
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TLS_FAIL_NOT_YET_VALID;
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_CERT_HAS_EXPIRED:
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_CRL_HAS_EXPIRED:
12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TLS_FAIL_EXPIRED;
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_UNABLE_TO_GET_CRL:
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_CERT_CHAIN_TOO_LONG:
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_PATH_LENGTH_EXCEEDED:
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_INVALID_CA:
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TLS_FAIL_UNTRUSTED;
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_CERT_UNTRUSTED:
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case X509_V_ERR_CERT_REJECTED:
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TLS_FAIL_BAD_CERTIFICATE;
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TLS_FAIL_UNSPECIFIED;
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * get_x509_cert(X509 *cert)
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *tmp;
12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int cert_len = i2d_X509(cert, NULL);
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cert_len <= 0)
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(cert_len);
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = wpabuf_put(buf, cert_len);
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	i2d_X509(cert, &tmp);
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void openssl_tls_fail_event(struct tls_connection *conn,
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   X509 *err_cert, int err, int depth,
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const char *subject, const char *err_str,
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   enum tls_fail_reason reason)
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union tls_event_data ev;
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *cert = NULL;
1304ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	struct tls_context *context = conn->context;
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1306ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	if (context->event_cb == NULL)
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cert = get_x509_cert(err_cert);
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&ev, 0, sizeof(ev));
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ev.cert_fail.reason = reason != TLS_FAIL_UNSPECIFIED ?
13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reason : openssl_tls_fail_reason(err);
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ev.cert_fail.depth = depth;
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ev.cert_fail.subject = subject;
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ev.cert_fail.reason_txt = err_str;
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ev.cert_fail.cert = cert;
1317ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	context->event_cb(context->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(cert);
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void openssl_tls_cert_event(struct tls_connection *conn,
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   X509 *err_cert, int depth,
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const char *subject)
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *cert = NULL;
13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union tls_event_data ev;
1328ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	struct tls_context *context = conn->context;
13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_SHA256
13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 hash[32];
13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_SHA256 */
13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1333ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	if (context->event_cb == NULL)
13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&ev, 0, sizeof(ev));
1337ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	if (conn->cert_probe || context->cert_in_cb) {
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cert = get_x509_cert(err_cert);
13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ev.peer_cert.cert = cert;
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_SHA256
13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cert) {
13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const u8 *addr[1];
13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		size_t len[1];
13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		addr[0] = wpabuf_head(cert);
13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len[0] = wpabuf_len(cert);
13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sha256_vector(1, addr, len, hash) == 0) {
13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ev.peer_cert.hash = hash;
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ev.peer_cert.hash_len = sizeof(hash);
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_SHA256 */
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ev.peer_cert.depth = depth;
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ev.peer_cert.subject = subject;
1355ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	context->event_cb(context->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(cert);
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[256];
13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509 *err_cert;
13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int err, depth;
13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL *ssl;
13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_connection *conn;
1367ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	struct tls_context *context;
1368051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	char *match, *altmatch, *suffix_match;
13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *err_str;
13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
137296be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt	if (!err_cert)
137396be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt		return 0;
137496be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt
13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	err = X509_STORE_CTX_get_error(x509_ctx);
13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	depth = X509_STORE_CTX_get_error_depth(x509_ctx);
13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 SSL_get_ex_data_X509_STORE_CTX_idx());
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn = SSL_get_app_data(ssl);
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
138434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
138534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (depth == 0)
138634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		conn->peer_cert = err_cert;
138734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	else if (depth == 1)
138834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		conn->peer_issuer = err_cert;
1389fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	else if (depth == 2)
1390fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		conn->peer_issuer_issuer = err_cert;
139134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
1392ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	context = conn->context;
13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	match = conn->subject_match;
13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	altmatch = conn->altsubject_match;
1395051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	suffix_match = conn->suffix_match;
13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!preverify_ok && !conn->ca_cert_verify)
13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		preverify_ok = 1;
13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!preverify_ok && depth > 0 && conn->server_cert_only)
14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		preverify_ok = 1;
1401c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	if (!preverify_ok && (conn->flags & TLS_CONN_DISABLE_TIME_CHECKS) &&
1402c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	    (err == X509_V_ERR_CERT_HAS_EXPIRED ||
1403c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	     err == X509_V_ERR_CERT_NOT_YET_VALID)) {
1404c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Ignore certificate validity "
1405c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			   "time mismatch");
1406c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		preverify_ok = 1;
1407c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	}
14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	err_str = X509_verify_cert_error_string(err);
14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_SHA256
14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (preverify_ok && depth == 0 && conn->server_cert_only) {
14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct wpabuf *cert;
14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cert = get_x509_cert(err_cert);
14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!cert) {
14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: Could not fetch "
14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "server certificate data");
14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			preverify_ok = 0;
14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 hash[32];
14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *addr[1];
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t len[1];
14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			addr[0] = wpabuf_head(cert);
14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len[0] = wpabuf_len(cert);
14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (sha256_vector(1, addr, len, hash) < 0 ||
14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    os_memcmp(conn->srv_cert_hash, hash, 32) != 0) {
14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				err_str = "Server certificate mismatch";
14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				err = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				preverify_ok = 0;
14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_free(cert);
14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_SHA256 */
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!preverify_ok) {
14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "TLS: Certificate verification failed,"
14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " error %d (%s) depth %d for '%s'", err, err_str,
14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   depth, buf);
14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       err_str, TLS_FAIL_UNSPECIFIED);
14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return preverify_ok;
14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - preverify_ok=%d "
14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "err=%d (%s) ca_cert_verify=%d depth=%d buf='%s'",
14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   preverify_ok, err, err_str,
14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   conn->ca_cert_verify, depth, buf);
14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (depth == 0 && match && os_strstr(buf, match) == NULL) {
14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "match with '%s'", buf, match);
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		preverify_ok = 0;
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "Subject mismatch",
14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       TLS_FAIL_SUBJECT_MISMATCH);
14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (depth == 0 && altmatch &&
14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   !tls_match_altsubject(err_cert, altmatch)) {
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "TLS: altSubjectName match "
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "'%s' not found", altmatch);
14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		preverify_ok = 0;
14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "AltSubject mismatch",
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       TLS_FAIL_ALTSUBJECT_MISMATCH);
1464051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	} else if (depth == 0 && suffix_match &&
1465051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		   !tls_match_suffix(err_cert, suffix_match)) {
1466051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		wpa_printf(MSG_WARNING, "TLS: Domain suffix match '%s' not found",
1467051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			   suffix_match);
1468051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		preverify_ok = 0;
1469051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
1470051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt				       "Domain suffix mismatch",
1471051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt				       TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		openssl_tls_cert_event(conn, err_cert, depth, buf);
14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->cert_probe && preverify_ok && depth == 0) {
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Reject server certificate "
14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "on probe-only run");
14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		preverify_ok = 0;
14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "Server certificate chain probe",
14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       TLS_FAIL_SERVER_CHAIN_PROBE);
14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1484ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	if (preverify_ok && context->event_cb != NULL)
1485ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt		context->event_cb(context->cb_ctx,
1486ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt				  TLS_CERT_CHAIN_SUCCESS, NULL);
148704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return preverify_ok;
14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_STDIO
14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_load_ca_der(void *_ssl_ctx, const char *ca_cert)
14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX *ssl_ctx = _ssl_ctx;
14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509_LOOKUP *lookup;
14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 0;
14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	lookup = X509_STORE_add_lookup(ssl_ctx->cert_store,
15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       X509_LOOKUP_file());
15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (lookup == NULL) {
15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_WARNING, __func__,
15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed add lookup for X509 store");
15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!X509_LOOKUP_load_file(lookup, ca_cert, X509_FILETYPE_ASN1)) {
15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unsigned long err = ERR_peek_error();
15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_WARNING, __func__,
15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed load CA in DER format");
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) {
15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring "
15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "cert already in hash table error",
15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   __func__);
15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_STDIO */
15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn,
15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const char *ca_cert, const u8 *ca_cert_blob,
15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  size_t ca_cert_blob_len, const char *ca_path)
15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX *ssl_ctx = _ssl_ctx;
15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Remove previously configured trusted CA certificates before adding
15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * new ones.
15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509_STORE_free(ssl_ctx->cert_store);
15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssl_ctx->cert_store = X509_STORE_new();
15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssl_ctx->cert_store == NULL) {
15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new "
15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "certificate store", __func__);
15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->ca_cert_verify = 1;
15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ca_cert && os_strncmp(ca_cert, "probe://", 8) == 0) {
15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Probe for server certificate "
15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "chain");
15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->cert_probe = 1;
15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->ca_cert_verify = 0;
15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ca_cert && os_strncmp(ca_cert, "hash://", 7) == 0) {
15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_SHA256
15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const char *pos = ca_cert + 7;
15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strncmp(pos, "server/sha256/", 14) != 0) {
15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: Unsupported ca_cert "
15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "hash value '%s'", ca_cert);
15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 14;
15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strlen(pos) != 32 * 2) {
15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: Unexpected SHA256 "
15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "hash length in ca_cert '%s'", ca_cert);
15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hexstr2bin(pos, conn->srv_cert_hash, 32) < 0) {
15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: Invalid SHA256 hash "
15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "value in ca_cert '%s'", ca_cert);
15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->server_cert_only = 1;
15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Checking only server "
15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "certificate match");
15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_SHA256 */
15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "No SHA256 included in the build - "
15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "cannot validate server certificate hash");
15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_SHA256 */
15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ca_cert_blob) {
15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509 *cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &ca_cert_blob,
15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      ca_cert_blob_len);
15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cert == NULL) {
15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_WARNING, __func__,
15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"Failed to parse ca_cert_blob");
15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) {
15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			unsigned long err = ERR_peek_error();
15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_WARNING, __func__,
15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"Failed to add ca_cert_blob to "
15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"certificate store");
15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    ERR_GET_REASON(err) ==
16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    X509_R_CERT_ALREADY_IN_HASH_TABLE) {
16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring "
16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "cert already in hash table error",
16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   __func__);
16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else {
16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				X509_free(cert);
16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509_free(cert);
16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: %s - added ca_cert_blob "
16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "to certificate store", __func__);
16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef ANDROID
16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ca_cert && os_strncmp("keystore://", ca_cert, 11) == 0) {
16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		BIO *bio = BIO_from_keystore(&ca_cert[11]);
16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		STACK_OF(X509_INFO) *stack = NULL;
16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int i;
16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (bio) {
16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			BIO_free(bio);
16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!stack)
16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (i = 0; i < sk_X509_INFO_num(stack); ++i) {
16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			X509_INFO *info = sk_X509_INFO_value(stack, i);
16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (info->x509) {
16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				X509_STORE_add_cert(ssl_ctx->cert_store,
16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    info->x509);
16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (info->crl) {
16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				X509_STORE_add_crl(ssl_ctx->cert_store,
16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   info->crl);
16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sk_X509_INFO_pop_free(stack, X509_INFO_free);
16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* ANDROID */
16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_NATIVE_WINDOWS
16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ca_cert && tls_cryptoapi_ca_cert(ssl_ctx, conn->ssl, ca_cert) ==
16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Added CA certificates from "
16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "system certificate store");
16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ca_cert || ca_path) {
16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_STDIO
16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, ca_path) !=
16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    1) {
16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_WARNING, __func__,
16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"Failed to load root certificates");
16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (ca_cert &&
16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    tls_load_ca_der(ssl_ctx, ca_cert) == 0) {
16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "OpenSSL: %s - loaded "
16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "DER format CA certificate",
16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   __func__);
16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else
16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLS: Trusted root "
16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "certificate(s) loaded");
16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_get_errors(ssl_ctx);
16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_STDIO */
16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO",
16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__);
16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_STDIO */
16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* No ca_cert configured - do not try to verify server
16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * certificate */
16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->ca_cert_verify = 0;
16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_global_ca_cert(SSL_CTX *ssl_ctx, const char *ca_cert)
16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ca_cert) {
16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, NULL) != 1)
16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		{
16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_WARNING, __func__,
16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"Failed to load root certificates");
16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLS: Trusted root "
16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "certificate(s) loaded");
16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_STDIO
17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Add the same CAs to the client certificate requests */
17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_CTX_set_client_CA_list(ssl_ctx,
17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   SSL_load_client_CA_file(ca_cert));
17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_STDIO */
17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_global_set_verify(void *ssl_ctx, int check_crl)
17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int flags;
17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (check_crl) {
17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509_STORE *cs = SSL_CTX_get_cert_store(ssl_ctx);
17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cs == NULL) {
17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_INFO, __func__, "Failed to get "
17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"certificate store when enabling "
17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"check_crl");
17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		flags = X509_V_FLAG_CRL_CHECK;
17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (check_crl == 2)
17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			flags |= X509_V_FLAG_CRL_CHECK_ALL;
17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509_STORE_set_flags(cs, flags);
17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_connection_set_subject_match(struct tls_connection *conn,
17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    const char *subject_match,
1734051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt					    const char *altsubject_match,
1735051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt					    const char *suffix_match)
17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->subject_match);
17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->subject_match = NULL;
17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (subject_match) {
17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->subject_match = os_strdup(subject_match);
17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conn->subject_match == NULL)
17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->altsubject_match);
17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->altsubject_match = NULL;
17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (altsubject_match) {
17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->altsubject_match = os_strdup(altsubject_match);
17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conn->altsubject_match == NULL)
17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1753051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	os_free(conn->suffix_match);
1754051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	conn->suffix_match = NULL;
1755051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (suffix_match) {
1756051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		conn->suffix_match = os_strdup(suffix_match);
1757051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		if (conn->suffix_match == NULL)
1758051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			return -1;
1759051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
1760051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      int verify_peer)
17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static int counter = 0;
17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (verify_peer) {
17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->ca_cert_verify = 1;
17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER |
17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       SSL_VERIFY_FAIL_IF_NO_PEER_CERT |
17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       SSL_VERIFY_CLIENT_ONCE, tls_verify_cb);
17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->ca_cert_verify = 0;
17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_set_accept_state(conn->ssl);
17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Set session id context in order to avoid fatal errors when client
17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * tries to resume a session. However, set the context to a unique
17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * value in order to effectively disable session resumption for now
17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * since not all areas of the server code are ready for it (e.g.,
17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * EAP-TTLS needs special handling for Phase 2 after abbreviated TLS
17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * handshake).
17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	counter++;
17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_set_session_id_context(conn->ssl,
17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (const unsigned char *) &counter,
17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   sizeof(counter));
17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_connection_client_cert(struct tls_connection *conn,
18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const char *client_cert,
18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *client_cert_blob,
18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      size_t client_cert_blob_len)
18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (client_cert == NULL && client_cert_blob == NULL)
18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (client_cert_blob &&
18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    SSL_use_certificate_ASN1(conn->ssl, (u8 *) client_cert_blob,
18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     client_cert_blob_len) == 1) {
18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_ASN1 --> "
18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "OK");
18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (client_cert_blob) {
18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_DEBUG, __func__,
18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"SSL_use_certificate_ASN1 failed");
18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (client_cert == NULL)
18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef ANDROID
18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strncmp("keystore://", client_cert, 11) == 0) {
18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		BIO *bio = BIO_from_keystore(&client_cert[11]);
18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509 *x509 = NULL;
18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int ret = -1;
18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (bio) {
18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			BIO_free(bio);
18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (x509) {
18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (SSL_use_certificate(conn->ssl, x509) == 1)
18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				ret = 0;
18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			X509_free(x509);
18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return ret;
18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* ANDROID */
18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_STDIO
18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (SSL_use_certificate_file(conn->ssl, client_cert,
18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     SSL_FILETYPE_ASN1) == 1) {
18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (DER)"
18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " --> OK");
18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (SSL_use_certificate_file(conn->ssl, client_cert,
18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     SSL_FILETYPE_PEM) == 1) {
18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ERR_clear_error();
18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (PEM)"
18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " --> OK");
18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_show_errors(MSG_DEBUG, __func__,
18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"SSL_use_certificate_file failed");
18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_STDIO */
18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__);
18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_STDIO */
18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_global_client_cert(SSL_CTX *ssl_ctx, const char *client_cert)
18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_STDIO
18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (client_cert == NULL)
18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (SSL_CTX_use_certificate_file(ssl_ctx, client_cert,
18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 SSL_FILETYPE_ASN1) != 1 &&
18761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    SSL_CTX_use_certificate_chain_file(ssl_ctx, client_cert) != 1 &&
18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    SSL_CTX_use_certificate_file(ssl_ctx, client_cert,
18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 SSL_FILETYPE_PEM) != 1) {
18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to load client certificate");
18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_STDIO */
18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (client_cert == NULL)
18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__);
18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_STDIO */
18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_passwd_cb(char *buf, int size, int rwflag, void *password)
18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (password == NULL) {
18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(buf, (char *) password, size);
18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return os_strlen(buf);
19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PKCS12_FUNCS
19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_parse_pkcs12(SSL_CTX *ssl_ctx, SSL *ssl, PKCS12 *p12,
19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const char *passwd)
19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EVP_PKEY *pkey;
19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509 *cert;
19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STACK_OF(X509) *certs;
19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res = 0;
19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[256];
19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pkey = NULL;
19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cert = NULL;
19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	certs = NULL;
19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!PKCS12_parse(p12, passwd, &pkey, &cert, &certs)) {
19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_DEBUG, __func__,
19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to parse PKCS12 file");
19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		PKCS12_free(p12);
19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLS: Successfully parsed PKCS12 data");
19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cert) {
19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509_NAME_oneline(X509_get_subject_name(cert), buf,
19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sizeof(buf));
19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLS: Got certificate from PKCS12: "
19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "subject='%s'", buf);
19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ssl) {
19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (SSL_use_certificate(ssl, cert) != 1)
19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				res = -1;
19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (SSL_CTX_use_certificate(ssl_ctx, cert) != 1)
19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				res = -1;
19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509_free(cert);
19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pkey) {
19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLS: Got private key from PKCS12");
19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ssl) {
19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (SSL_use_PrivateKey(ssl, pkey) != 1)
19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				res = -1;
19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) != 1)
19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				res = -1;
19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EVP_PKEY_free(pkey);
19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (certs) {
19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while ((cert = sk_X509_pop(certs)) != NULL) {
19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			X509_NAME_oneline(X509_get_subject_name(cert), buf,
19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  sizeof(buf));
19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLS: additional certificate"
19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " from PKCS12: subject='%s'", buf);
19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * There is no SSL equivalent for the chain cert - so
19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * always add it to the context...
19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (SSL_CTX_add_extra_chain_cert(ssl_ctx, cert) != 1) {
19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				res = -1;
19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sk_X509_free(certs);
19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PKCS12_free(p12);
19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0)
19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_get_errors(ssl_ctx);
19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif  /* PKCS12_FUNCS */
19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_read_pkcs12(SSL_CTX *ssl_ctx, SSL *ssl, const char *private_key,
19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   const char *passwd)
19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PKCS12_FUNCS
19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	FILE *f;
19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PKCS12 *p12;
19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	f = fopen(private_key, "rb");
19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (f == NULL)
19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p12 = d2i_PKCS12_fp(f, NULL);
19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fclose(f);
19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p12 == NULL) {
19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to use PKCS#12 file");
19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return tls_parse_pkcs12(ssl_ctx, ssl, p12, passwd);
20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* PKCS12_FUNCS */
20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot read "
20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "p12/pfx files");
20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif  /* PKCS12_FUNCS */
20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_read_pkcs12_blob(SSL_CTX *ssl_ctx, SSL *ssl,
20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				const u8 *blob, size_t len, const char *passwd)
20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PKCS12_FUNCS
20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PKCS12 *p12;
20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p12 = d2i_PKCS12(NULL, (OPENSSL_d2i_TYPE) &blob, len);
20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p12 == NULL) {
20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to use PKCS#12 blob");
20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return tls_parse_pkcs12(ssl_ctx, ssl, p12, passwd);
20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* PKCS12_FUNCS */
20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot parse "
20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "p12/pfx blobs");
20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif  /* PKCS12_FUNCS */
20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_engine_get_cert(struct tls_connection *conn,
20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       const char *cert_id,
20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       X509 **cert)
20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* this runs after the private key is loaded so no PIN is required */
20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct {
20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const char *cert_id;
20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509 *cert;
20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} params;
20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.cert_id = cert_id;
20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.cert = NULL;
20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ENGINE_ctrl_cmd(conn->engine, "LOAD_CERT_CTRL",
20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     0, &params, NULL, 1)) {
20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "ENGINE: cannot load client cert with id"
20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " '%s' [%s]", cert_id,
20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(ERR_get_error(), NULL));
20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!params.cert) {
20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "ENGINE: did not properly cert with id"
20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " '%s'", cert_id);
20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*cert = params.cert;
20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_connection_engine_client_cert(struct tls_connection *conn,
20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const char *cert_id)
20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509 *cert;
20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_engine_get_cert(conn, cert_id, &cert))
20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!SSL_use_certificate(conn->ssl, cert)) {
20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_ERROR, __func__,
20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"SSL_use_certificate failed");
20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                X509_free(cert);
20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509_free(cert);
20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "ENGINE: SSL_use_certificate --> "
20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "OK");
20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_ENGINE */
20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_connection_engine_ca_cert(void *_ssl_ctx,
20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 struct tls_connection *conn,
20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 const char *ca_cert_id)
20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509 *cert;
20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX *ssl_ctx = _ssl_ctx;
20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_engine_get_cert(conn, ca_cert_id, &cert))
20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* start off the same as tls_connection_ca_cert */
21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509_STORE_free(ssl_ctx->cert_store);
21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssl_ctx->cert_store = X509_STORE_new();
21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssl_ctx->cert_store == NULL) {
21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new "
21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "certificate store", __func__);
21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		X509_free(cert);
21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) {
21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unsigned long err = ERR_peek_error();
21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_WARNING, __func__,
21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to add CA certificate from engine "
21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"to certificate store");
21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) {
21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring cert"
21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " already in hash table error",
21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   __func__);
21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			X509_free(cert);
21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	X509_free(cert);
21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: %s - added CA certificate from engine "
21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "to certificate store", __func__);
21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
212861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	conn->ca_cert_verify = 1;
212961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_ENGINE */
21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_connection_engine_private_key(struct tls_connection *conn)
21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_ENGINE
21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (SSL_use_PrivateKey(conn->ssl, conn->private_key) != 1) {
21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_ERROR, __func__,
21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"ENGINE: cannot use private key for TLS");
21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!SSL_check_private_key(conn->ssl)) {
21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Private key failed verification");
21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_ENGINE */
21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_ERROR, "SSL: Configuration uses engine, but "
21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "engine support was not compiled in");
21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_ENGINE */
21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_connection_private_key(void *_ssl_ctx,
21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      struct tls_connection *conn,
21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const char *private_key,
21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const char *private_key_passwd,
21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *private_key_blob,
21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      size_t private_key_blob_len)
21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX *ssl_ctx = _ssl_ctx;
21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *passwd;
21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ok;
21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (private_key == NULL && private_key_blob == NULL)
21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (private_key_passwd) {
21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		passwd = os_strdup(private_key_passwd);
21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (passwd == NULL)
21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		passwd = NULL;
21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb);
21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, passwd);
21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ok = 0;
21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (private_key_blob) {
21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA, conn->ssl,
21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    (u8 *) private_key_blob,
21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    private_key_blob_len) == 1) {
21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_"
21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "ASN1(EVP_PKEY_RSA) --> OK");
21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ok = 1;
21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_use_PrivateKey_ASN1(EVP_PKEY_DSA, conn->ssl,
21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    (u8 *) private_key_blob,
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    private_key_blob_len) == 1) {
21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_"
21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "ASN1(EVP_PKEY_DSA) --> OK");
22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ok = 1;
22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_use_RSAPrivateKey_ASN1(conn->ssl,
22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       (u8 *) private_key_blob,
22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       private_key_blob_len) == 1) {
22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: "
22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "SSL_use_RSAPrivateKey_ASN1 --> OK");
22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ok = 1;
22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_read_pkcs12_blob(ssl_ctx, conn->ssl, private_key_blob,
22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 private_key_blob_len, passwd) == 0) {
22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: PKCS#12 as blob --> "
22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "OK");
22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ok = 1;
22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (!ok && private_key) {
22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_STDIO
22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_use_PrivateKey_file(conn->ssl, private_key,
22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    SSL_FILETYPE_ASN1) == 1) {
22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: "
22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "SSL_use_PrivateKey_File (DER) --> OK");
22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ok = 1;
22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_use_PrivateKey_file(conn->ssl, private_key,
22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    SSL_FILETYPE_PEM) == 1) {
22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: "
22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "SSL_use_PrivateKey_File (PEM) --> OK");
22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ok = 1;
22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_STDIO */
22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO",
22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__);
22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_STDIO */
22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_read_pkcs12(ssl_ctx, conn->ssl, private_key, passwd)
22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    == 0) {
22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: Reading PKCS#12 file "
22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "--> OK");
22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ok = 1;
22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_cryptoapi_cert(conn->ssl, private_key) == 0) {
22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: Using CryptoAPI to "
22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "access certificate store --> OK");
22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ok = 1;
22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ok) {
22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to load private key");
22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(passwd);
22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ERR_clear_error();
22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL);
22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(passwd);
227361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!SSL_check_private_key(conn->ssl)) {
22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__, "Private key failed "
22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"verification");
22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "SSL: Private key loaded successfully");
22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_global_private_key(SSL_CTX *ssl_ctx, const char *private_key,
22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const char *private_key_passwd)
22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *passwd;
22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (private_key == NULL)
22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (private_key_passwd) {
22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		passwd = os_strdup(private_key_passwd);
22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (passwd == NULL)
22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		passwd = NULL;
22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb);
23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, passwd);
23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (
23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_STDIO
23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key,
23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					SSL_FILETYPE_ASN1) != 1 &&
23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key,
23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					SSL_FILETYPE_PEM) != 1 &&
23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_STDIO */
23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    tls_read_pkcs12(ssl_ctx, NULL, private_key, passwd)) {
23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Failed to load private key");
23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(passwd);
23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ERR_clear_error();
23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(passwd);
23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ERR_clear_error();
23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL);
231961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!SSL_CTX_check_private_key(ssl_ctx)) {
23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Private key failed verification");
23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_connection_dh(struct tls_connection *conn, const char *dh_file)
23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef OPENSSL_NO_DH
23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dh_file == NULL)
23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but "
23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "dh_file specified");
23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_DH */
23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DH *dh;
23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BIO *bio;
23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: add support for dh_blob */
23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dh_file == NULL)
23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bio = BIO_new_file(dh_file, "r");
23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bio == NULL) {
23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s",
23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   dh_file, ERR_error_string(ERR_get_error(), NULL));
23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BIO_free(bio);
23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_DSA
23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (dh == NULL) {
23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DSA *dsa;
23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -"
23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " trying to parse as DSA params", dh_file,
23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(ERR_get_error(), NULL));
23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		bio = BIO_new_file(dh_file, "r");
23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (bio == NULL)
23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL);
23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		BIO_free(bio);
23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dsa) {
23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file "
23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "'%s': %s", dh_file,
23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   ERR_error_string(ERR_get_error(), NULL));
23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format");
23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dh = DSA_dup_DH(dsa);
23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DSA_free(dsa);
23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dh == NULL) {
23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "TLS: Failed to convert DSA "
23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "params into DH params");
23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* !OPENSSL_NO_DSA */
23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dh == NULL) {
23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file "
23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "'%s'", dh_file);
23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (SSL_set_tmp_dh(conn->ssl, dh) != 1) {
23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': "
23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%s", dh_file,
23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(ERR_get_error(), NULL));
23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DH_free(dh);
23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DH_free(dh);
23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_DH */
24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_global_dh(SSL_CTX *ssl_ctx, const char *dh_file)
24058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef OPENSSL_NO_DH
24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dh_file == NULL)
24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but "
24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "dh_file specified");
24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_DH */
24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DH *dh;
24148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BIO *bio;
24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: add support for dh_blob */
24178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dh_file == NULL)
24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssl_ctx == NULL)
24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bio = BIO_new_file(dh_file, "r");
24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bio == NULL) {
24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s",
24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   dh_file, ERR_error_string(ERR_get_error(), NULL));
24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BIO_free(bio);
24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_DSA
24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (dh == NULL) {
24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DSA *dsa;
24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -"
24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " trying to parse as DSA params", dh_file,
24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(ERR_get_error(), NULL));
24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		bio = BIO_new_file(dh_file, "r");
24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (bio == NULL)
24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL);
24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		BIO_free(bio);
24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dsa) {
24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file "
24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "'%s': %s", dh_file,
24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   ERR_error_string(ERR_get_error(), NULL));
24458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format");
24498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dh = DSA_dup_DH(dsa);
24508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DSA_free(dsa);
24518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dh == NULL) {
24528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "TLS: Failed to convert DSA "
24538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "params into DH params");
24548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
24558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
24568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
24578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* !OPENSSL_NO_DSA */
24598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dh == NULL) {
24608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file "
24618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "'%s'", dh_file);
24628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (SSL_CTX_set_tmp_dh(ssl_ctx, dh) != 1) {
24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': "
24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%s", dh_file,
24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(ERR_get_error(), NULL));
24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DH_free(dh);
24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DH_free(dh);
24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_DH */
24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    struct tls_keys *keys)
24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
248161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_FIPS
248261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_printf(MSG_ERROR, "OpenSSL: TLS keys cannot be exported in FIPS "
248361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		   "mode");
248461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return -1;
248561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#else /* CONFIG_FIPS */
24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL *ssl;
24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL || keys == NULL)
24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssl = conn->ssl;
24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL)
24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(keys, 0, sizeof(*keys));
24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	keys->master_key = ssl->session->master_key;
24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	keys->master_key_len = ssl->session->master_key_length;
24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	keys->client_random = ssl->s3->client_random;
24988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	keys->client_random_len = SSL3_RANDOM_SIZE;
24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	keys->server_random = ssl->s3->server_random;
25008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	keys->server_random_len = SSL3_RANDOM_SIZE;
25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
250361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_FIPS */
25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
25088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       const char *label, int server_random_first,
25098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       u8 *out, size_t out_len)
25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
251161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#if OPENSSL_VERSION_NUMBER >= 0x10001000L
251261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	SSL *ssl;
251361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (conn == NULL)
251461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
251561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (server_random_first)
251661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
251761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ssl = conn->ssl;
251861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (SSL_export_keying_material(ssl, out, out_len, label,
251961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				       os_strlen(label), NULL, 0, 0) == 1) {
252061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Using internal PRF");
252161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 0;
252261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
252361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif
25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf *
25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtopenssl_handshake(struct tls_connection *conn, const struct wpabuf *in_data,
25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  int server)
25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *out_data;
25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Give TLS handshake data from the server (if available) to OpenSSL
25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * for processing.
25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (in_data &&
25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    BIO_write(conn->ssl_in, wpabuf_head(in_data), wpabuf_len(in_data))
25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    < 0) {
25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Handshake failed - BIO_write");
25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Initiate TLS handshake or continue the existing handshake */
25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (server)
25498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = SSL_accept(conn->ssl);
25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = SSL_connect(conn->ssl);
25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res != 1) {
25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int err = SSL_get_error(conn->ssl, res);
25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (err == SSL_ERROR_WANT_READ)
25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want "
25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "more data");
25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (err == SSL_ERROR_WANT_WRITE)
25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want to "
25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "write");
25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else {
25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_INFO, __func__, "SSL_connect");
25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->failed++;
25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Get the TLS handshake data to be sent to the server */
25678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = BIO_ctrl_pending(conn->ssl_out);
25688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res);
25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	out_data = wpabuf_alloc(res);
25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (out_data == NULL) {
25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for "
25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "handshake output (%d bytes)", res);
25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (BIO_reset(conn->ssl_out) < 0) {
25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_INFO, __func__,
25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"BIO_reset failed");
25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = res == 0 ? 0 : BIO_read(conn->ssl_out, wpabuf_mhead(out_data),
25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      res);
25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Handshake failed - BIO_read");
25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (BIO_reset(conn->ssl_out) < 0) {
25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_INFO, __func__,
25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"BIO_reset failed");
25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(out_data);
25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put(out_data, res);
25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return out_data;
25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf *
25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtopenssl_get_appl_data(struct tls_connection *conn, size_t max_len)
25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *appl_data;
26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	appl_data = wpabuf_alloc(max_len + 100);
26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (appl_data == NULL)
26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = SSL_read(conn->ssl, wpabuf_mhead(appl_data),
26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       wpabuf_size(appl_data));
26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int err = SSL_get_error(conn->ssl, res);
26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (err == SSL_ERROR_WANT_READ ||
26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    err == SSL_ERROR_WANT_WRITE) {
26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "SSL: No Application Data "
26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "included");
26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_show_errors(MSG_INFO, __func__,
26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"Failed to read possible "
26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"Application Data");
26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(appl_data);
26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put(appl_data, res);
26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application Data in Finished "
26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    "message", appl_data);
26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return appl_data;
26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf *
26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtopenssl_connection_handshake(struct tls_connection *conn,
26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     const struct wpabuf *in_data,
26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     struct wpabuf **appl_data, int server)
26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *out_data;
26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (appl_data)
26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*appl_data = NULL;
26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	out_data = openssl_handshake(conn, in_data, server);
26438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (out_data == NULL)
26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (SSL_is_init_finished(conn->ssl) && appl_data && in_data)
26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*appl_data = openssl_get_appl_data(conn, wpabuf_len(in_data));
26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return out_data;
26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf *
26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 const struct wpabuf *in_data,
26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 struct wpabuf **appl_data)
26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return openssl_connection_handshake(conn, in_data, appl_data, 0);
26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_server_handshake(void *tls_ctx,
26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						struct tls_connection *conn,
26648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						const struct wpabuf *in_data,
26658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						struct wpabuf **appl_data)
26668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return openssl_connection_handshake(conn, in_data, appl_data, 1);
26688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_encrypt(void *tls_ctx,
26728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct tls_connection *conn,
26738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const struct wpabuf *in_data)
26748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
26768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
26778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
26798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
26808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Give plaintext data for OpenSSL to encrypt into the TLS tunnel. */
26828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((res = BIO_reset(conn->ssl_in)) < 0 ||
26838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (res = BIO_reset(conn->ssl_out)) < 0) {
26848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
26858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
26868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = SSL_write(conn->ssl, wpabuf_head(in_data), wpabuf_len(in_data));
26888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
26898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
26908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Encryption failed - SSL_write");
26918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
26928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Read encrypted data to be sent to the server */
26958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
26968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
26978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
26988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = BIO_read(conn->ssl_out, wpabuf_mhead(buf), wpabuf_size(buf));
26998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
27008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
27018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Encryption failed - BIO_read");
27028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(buf);
27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
27048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put(buf, res);
27068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
27088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_decrypt(void *tls_ctx,
27128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct tls_connection *conn,
27138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const struct wpabuf *in_data)
27148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
27168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
27178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Give encrypted data from TLS tunnel for OpenSSL to decrypt. */
27198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = BIO_write(conn->ssl_in, wpabuf_head(in_data),
27208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_len(in_data));
27218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
27228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
27238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Decryption failed - BIO_write");
27248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
27258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (BIO_reset(conn->ssl_out) < 0) {
27278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
27288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
27298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Read decrypted data for further processing */
27328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
27338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Even though we try to disable TLS compression, it is possible that
27348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * this cannot be done with all TLS libraries. Add extra buffer space
27358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * to handle the possibility of the decrypted data being longer than
27368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * input data.
27378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
27388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
27398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
27408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
27418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = SSL_read(conn->ssl, wpabuf_mhead(buf), wpabuf_size(buf));
27428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
27438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
27448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Decryption failed - SSL_read");
27458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(buf);
27468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
27478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put(buf, res);
27498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
27518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
27558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return conn ? conn->ssl->hit : 0;
27578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
27618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   u8 *ciphers)
27628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[100], *pos, *end;
27648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *c;
27658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
27668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL || conn->ssl == NULL || ciphers == NULL)
27688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf[0] = '\0';
27718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf;
27728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + sizeof(buf);
27738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	c = ciphers;
27758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (*c != TLS_CIPHER_NONE) {
27768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const char *suite;
27778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (*c) {
27798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case TLS_CIPHER_RC4_SHA:
27808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			suite = "RC4-SHA";
27818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
27828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case TLS_CIPHER_AES128_SHA:
27838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			suite = "AES128-SHA";
27848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
27858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case TLS_CIPHER_RSA_DHE_AES128_SHA:
27868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			suite = "DHE-RSA-AES128-SHA";
27878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
27888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case TLS_CIPHER_ANON_DH_AES128_SHA:
27898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			suite = "ADH-AES128-SHA";
27908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
27918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
27928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLS: Unsupported "
27938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "cipher selection: %d", *c);
27948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
27958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
27968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, ":%s", suite);
27978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || ret >= end - pos)
27988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
27998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
28008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		c++;
28028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: cipher suites: %s", buf + 1);
28058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (SSL_set_cipher_list(conn->ssl, buf + 1) != 1) {
28078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
28088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Cipher suite configuration failed");
28098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
28108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
28138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
28178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   char *buf, size_t buflen)
28188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *name;
28208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL || conn->ssl == NULL)
28218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
28228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	name = SSL_get_cipher(conn->ssl);
28248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (name == NULL)
28258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
28268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(buf, name, buflen);
28288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
28298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_enable_workaround(void *ssl_ctx,
28338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct tls_connection *conn)
28348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_set_options(conn->ssl, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
28368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
28388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
28428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* ClientHello TLS extensions require a patch to openssl, so this function is
28438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * commented out unless explicitly needed for EAP-FAST in order to be able to
28448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * build this file with unmodified openssl. */
28458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
28468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    int ext_type, const u8 *data,
28478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    size_t data_len)
28488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL || conn->ssl == NULL || ext_type != 35)
28508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
28518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_OPENSSL_TICKET_OVERRIDE
28538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (SSL_set_session_ticket_ext(conn->ssl, (void *) data,
28548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       data_len) != 1)
28558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
28568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_OPENSSL_TICKET_OVERRIDE */
28578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (SSL_set_hello_extension(conn->ssl, ext_type, (void *) data,
28588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    data_len) != 1)
28598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
28608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */
28618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
28638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
28658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
28688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
28708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
28718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return conn->failed;
28728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
28768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
28788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
28798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return conn->read_alerts;
28808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
28848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
28868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
28878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return conn->write_alerts;
28888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
289134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#ifdef HAVE_OCSP
289234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
289334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void ocsp_debug_print_resp(OCSP_RESPONSE *rsp)
289434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
289534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG
289634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	BIO *out;
289734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	size_t rlen;
289834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	char *txt;
289934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	int res;
290034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
290134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (wpa_debug_level > MSG_DEBUG)
290234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
290334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
290434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	out = BIO_new(BIO_s_mem());
290534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (!out)
290634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
290734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
290834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	OCSP_RESPONSE_print(out, rsp, 0);
290934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	rlen = BIO_ctrl_pending(out);
291034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	txt = os_malloc(rlen + 1);
291134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (!txt) {
291234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		BIO_free(out);
291334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
291434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
291534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
291634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	res = BIO_read(out, txt, rlen);
291734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (res > 0) {
291834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		txt[res] = '\0';
291934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP Response\n%s", txt);
292034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
292134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_free(txt);
292234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	BIO_free(out);
292334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */
292434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
292534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
292634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
292734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int ocsp_resp_cb(SSL *s, void *arg)
292834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
292934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct tls_connection *conn = arg;
293034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	const unsigned char *p;
293134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	int len, status, reason;
293234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	OCSP_RESPONSE *rsp;
293334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	OCSP_BASICRESP *basic;
293434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	OCSP_CERTID *id;
293534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	ASN1_GENERALIZEDTIME *produced_at, *this_update, *next_update;
2936fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	X509_STORE *store;
2937fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	STACK_OF(X509) *certs = NULL;
293834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
293934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	len = SSL_get_tlsext_status_ocsp_resp(s, &p);
294034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (!p) {
294134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: No OCSP response received");
294234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1;
294334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
294434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
294534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "OpenSSL: OCSP response", p, len);
294634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
294734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
294834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (!rsp) {
294934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "OpenSSL: Failed to parse OCSP response");
295034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 0;
295134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
295234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
295334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	ocsp_debug_print_resp(rsp);
295434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
295534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	status = OCSP_response_status(rsp);
295634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
295734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "OpenSSL: OCSP responder error %d (%s)",
295834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			   status, OCSP_response_status_str(status));
295934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 0;
296034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
296134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
296234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	basic = OCSP_response_get1_basic(rsp);
296334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (!basic) {
296434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "OpenSSL: Could not find BasicOCSPResponse");
296534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 0;
296634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
296734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
2968fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	store = SSL_CTX_get_cert_store(s->ctx);
2969fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (conn->peer_issuer) {
2970fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Add issuer");
2971fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		X509_print_fp(stdout, conn->peer_issuer);
2972fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2973fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		if (X509_STORE_add_cert(store, conn->peer_issuer) != 1) {
2974fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			tls_show_errors(MSG_INFO, __func__,
2975fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt					"OpenSSL: Could not add issuer to certificate store\n");
2976fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		}
2977fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		certs = sk_X509_new_null();
2978fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		if (certs) {
2979fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			X509 *cert;
2980fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			cert = X509_dup(conn->peer_issuer);
2981fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			if (cert && !sk_X509_push(certs, cert)) {
2982fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				tls_show_errors(
2983fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt					MSG_INFO, __func__,
2984fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt					"OpenSSL: Could not add issuer to OCSP responder trust store\n");
2985fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				X509_free(cert);
2986fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				sk_X509_free(certs);
2987fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				certs = NULL;
2988fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			}
2989fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			if (conn->peer_issuer_issuer) {
2990fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				cert = X509_dup(conn->peer_issuer_issuer);
2991fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				if (cert && !sk_X509_push(certs, cert)) {
2992fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt					tls_show_errors(
2993fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt						MSG_INFO, __func__,
2994fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt						"OpenSSL: Could not add issuer to OCSP responder trust store\n");
2995fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt					X509_free(cert);
2996fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				}
2997fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			}
2998fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		}
2999fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	}
3000fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
3001fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	status = OCSP_basic_verify(basic, certs, store, OCSP_TRUSTOTHER);
3002fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	sk_X509_pop_free(certs, X509_free);
300334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (status <= 0) {
300434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
300534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				"OpenSSL: OCSP response failed verification");
300634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_BASICRESP_free(basic);
300734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_RESPONSE_free(rsp);
300834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 0;
300934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
301034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
301134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP response verification succeeded");
301234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
30135605286c30e1701491bd3af974ae423727750eddDmitry Shmidt	if (!conn->peer_cert) {
30145605286c30e1701491bd3af974ae423727750eddDmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Peer certificate not available for OCSP status check");
30155605286c30e1701491bd3af974ae423727750eddDmitry Shmidt		OCSP_BASICRESP_free(basic);
30165605286c30e1701491bd3af974ae423727750eddDmitry Shmidt		OCSP_RESPONSE_free(rsp);
30175605286c30e1701491bd3af974ae423727750eddDmitry Shmidt		return 0;
30185605286c30e1701491bd3af974ae423727750eddDmitry Shmidt	}
30195605286c30e1701491bd3af974ae423727750eddDmitry Shmidt
30205605286c30e1701491bd3af974ae423727750eddDmitry Shmidt	if (!conn->peer_issuer) {
30215605286c30e1701491bd3af974ae423727750eddDmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Peer issuer certificate not available for OCSP status check");
302234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_BASICRESP_free(basic);
302334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_RESPONSE_free(rsp);
302434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 0;
302534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
302634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
302734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	id = OCSP_cert_to_id(NULL, conn->peer_cert, conn->peer_issuer);
302834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (!id) {
302934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Could not create OCSP certificate identifier");
303034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_BASICRESP_free(basic);
303134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_RESPONSE_free(rsp);
303234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 0;
303334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
303434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
303534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (!OCSP_resp_find_status(basic, id, &status, &reason, &produced_at,
303634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				   &this_update, &next_update)) {
303734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "OpenSSL: Could not find current server certificate from OCSP response%s",
303834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			   (conn->flags & TLS_CONN_REQUIRE_OCSP) ? "" :
303934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			   " (OCSP not required)");
304034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_BASICRESP_free(basic);
304134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_RESPONSE_free(rsp);
304234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1;
304334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
304434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
304534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (!OCSP_check_validity(this_update, next_update, 5 * 60, -1)) {
304634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		tls_show_errors(MSG_INFO, __func__,
304734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				"OpenSSL: OCSP status times invalid");
304834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_BASICRESP_free(basic);
304934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		OCSP_RESPONSE_free(rsp);
305034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 0;
305134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
305234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
305334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	OCSP_BASICRESP_free(basic);
305434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	OCSP_RESPONSE_free(rsp);
305534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
305634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status for server certificate: %s",
305734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		   OCSP_cert_status_str(status));
305834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
305934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (status == V_OCSP_CERTSTATUS_GOOD)
306034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 1;
306134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (status == V_OCSP_CERTSTATUS_REVOKED)
306234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 0;
306334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (conn->flags & TLS_CONN_REQUIRE_OCSP) {
306434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP required");
306534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 0;
306634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
3067051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP was not required, so allow connection to continue");
306834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return 1;
306934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
307034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
307134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
307234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int ocsp_status_cb(SSL *s, void *arg)
307334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
307434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	char *tmp;
307534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	char *resp;
307634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	size_t len;
307734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
307834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (tls_global->ocsp_stapling_response == NULL) {
307934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - no response configured");
308034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return SSL_TLSEXT_ERR_OK;
308134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
308234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
308334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	resp = os_readfile(tls_global->ocsp_stapling_response, &len);
308434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (resp == NULL) {
308534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - could not read response file");
308634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		/* TODO: Build OCSPResponse with responseStatus = internalError
308734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		 */
308834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return SSL_TLSEXT_ERR_OK;
308934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
309034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - send cached response");
309134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	tmp = OPENSSL_malloc(len);
309234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (tmp == NULL) {
309334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		os_free(resp);
309434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return SSL_TLSEXT_ERR_ALERT_FATAL;
309534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
309634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
309734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_memcpy(tmp, resp, len);
309834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_free(resp);
309934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	SSL_set_tlsext_status_ocsp_resp(s, tmp, len);
310034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
310134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return SSL_TLSEXT_ERR_OK;
310234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
310334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
310434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#endif /* HAVE_OCSP */
310534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
310634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
31078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
31088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const struct tls_connection_params *params)
31098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
31118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned long err;
31128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
31148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
31158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while ((err = ERR_get_error())) {
31178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s",
31188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__, ERR_error_string(err, NULL));
31198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params->engine) {
31228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine");
31238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = tls_engine_init(conn, params->engine_id, params->pin,
31248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      params->key_id, params->cert_id,
31258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      params->ca_cert_id);
31268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret)
31278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return ret;
31288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_connection_set_subject_match(conn,
31308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     params->subject_match,
3131051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt					     params->altsubject_match,
3132051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt					     params->suffix_match))
31338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
31348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params->engine && params->ca_cert_id) {
31368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_connection_engine_ca_cert(tls_ctx, conn,
31378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						  params->ca_cert_id))
31388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
31398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (tls_connection_ca_cert(tls_ctx, conn, params->ca_cert,
31408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  params->ca_cert_blob,
31418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  params->ca_cert_blob_len,
31428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  params->ca_path))
31438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
31448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params->engine && params->cert_id) {
31468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_connection_engine_client_cert(conn, params->cert_id))
31478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
31488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (tls_connection_client_cert(conn, params->client_cert,
31498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      params->client_cert_blob,
31508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      params->client_cert_blob_len))
31518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
31528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params->engine && params->key_id) {
31548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLS: Using private key from engine");
31558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_connection_engine_private_key(conn))
31568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
31578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (tls_connection_private_key(tls_ctx, conn,
31588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      params->private_key,
31598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      params->private_key_passwd,
31608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      params->private_key_blob,
31618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      params->private_key_blob_len)) {
31628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS: Failed to load private key '%s'",
31638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   params->private_key);
31648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
31658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_connection_dh(conn, params->dh_file)) {
31688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'",
31698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   params->dh_file);
31708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
31718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
317361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef SSL_OP_NO_TICKET
317461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (params->flags & TLS_CONN_DISABLE_SESSION_TICKET)
317561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		SSL_set_options(conn->ssl, SSL_OP_NO_TICKET);
317634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#ifdef SSL_clear_options
317761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	else
317861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		SSL_clear_options(conn->ssl, SSL_OP_NO_TICKET);
317934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#endif /* SSL_clear_options */
318061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /*  SSL_OP_NO_TICKET */
318161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
318213ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt#ifdef SSL_OP_NO_TLSv1_1
318313ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt	if (params->flags & TLS_CONN_DISABLE_TLSv1_1)
318413ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt		SSL_set_options(conn->ssl, SSL_OP_NO_TLSv1_1);
318513ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt	else
318613ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt		SSL_clear_options(conn->ssl, SSL_OP_NO_TLSv1_1);
318713ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt#endif /* SSL_OP_NO_TLSv1_1 */
318813ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt#ifdef SSL_OP_NO_TLSv1_2
318913ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt	if (params->flags & TLS_CONN_DISABLE_TLSv1_2)
319013ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt		SSL_set_options(conn->ssl, SSL_OP_NO_TLSv1_2);
319113ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt	else
319213ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt		SSL_clear_options(conn->ssl, SSL_OP_NO_TLSv1_2);
319313ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt#endif /* SSL_OP_NO_TLSv1_2 */
319413ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt
319534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#ifdef HAVE_OCSP
319634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (params->flags & TLS_CONN_REQUEST_OCSP) {
3197fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt		SSL_CTX *ssl_ctx = tls_ctx;
319834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		SSL_set_tlsext_status_type(conn->ssl, TLSEXT_STATUSTYPE_ocsp);
319934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_resp_cb);
320034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		SSL_CTX_set_tlsext_status_arg(ssl_ctx, conn);
320134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
320234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#endif /* HAVE_OCSP */
320334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
3204c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	conn->flags = params->flags;
3205c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
32068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_get_errors(tls_ctx);
32078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
32098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_global_set_params(void *tls_ctx,
32138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const struct tls_connection_params *params)
32148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SSL_CTX *ssl_ctx = tls_ctx;
32168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned long err;
32178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while ((err = ERR_get_error())) {
32198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s",
32208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__, ERR_error_string(err, NULL));
32218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_global_ca_cert(ssl_ctx, params->ca_cert))
32248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
32258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_global_client_cert(ssl_ctx, params->client_cert))
32278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
32288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_global_private_key(ssl_ctx, params->private_key,
32308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   params->private_key_passwd))
32318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
32328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_global_dh(ssl_ctx, params->dh_file)) {
32348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'",
32358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   params->dh_file);
32368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
32378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
323961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef SSL_OP_NO_TICKET
324061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (params->flags & TLS_CONN_DISABLE_SESSION_TICKET)
324161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TICKET);
324234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#ifdef SSL_CTX_clear_options
324361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	else
324461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TICKET);
324534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#endif /* SSL_clear_options */
324661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /*  SSL_OP_NO_TICKET */
324761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
324834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#ifdef HAVE_OCSP
324934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_status_cb);
325034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	SSL_CTX_set_tlsext_status_arg(ssl_ctx, ssl_ctx);
325134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_free(tls_global->ocsp_stapling_response);
325234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (params->ocsp_stapling_response)
325334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		tls_global->ocsp_stapling_response =
325434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			os_strdup(params->ocsp_stapling_response);
325534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	else
325634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		tls_global->ocsp_stapling_response = NULL;
325734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#endif /* HAVE_OCSP */
325834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
32598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
32608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_keyblock_size(void *tls_ctx,
32648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct tls_connection *conn)
32658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const EVP_CIPHER *c;
32678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const EVP_MD *h;
326861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	int md_size;
32698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL || conn->ssl == NULL ||
32718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    conn->ssl->enc_read_ctx == NULL ||
32728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    conn->ssl->enc_read_ctx->cipher == NULL ||
32738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    conn->ssl->read_hash == NULL)
32748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
32758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	c = conn->ssl->enc_read_ctx->cipher;
32778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if OPENSSL_VERSION_NUMBER >= 0x00909000L
32788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	h = EVP_MD_CTX_md(conn->ssl->read_hash);
32798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else
32808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	h = conn->ssl->read_hash;
32818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
328261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (h)
328361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		md_size = EVP_MD_size(h);
328461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#if OPENSSL_VERSION_NUMBER >= 0x10000000L
328561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	else if (conn->ssl->s3)
328661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		md_size = conn->ssl->s3->tmp.new_mac_secret_size;
328761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif
328861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	else
328961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
32908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
329161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: keyblock size: key_len=%d MD_size=%d "
329261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		   "IV_len=%d", EVP_CIPHER_key_length(c), md_size,
329361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		   EVP_CIPHER_iv_length(c));
32948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 2 * (EVP_CIPHER_key_length(c) +
329561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    md_size +
32968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    EVP_CIPHER_iv_length(c));
32978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int tls_capabilities(void *tls_ctx)
33018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
33038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
33078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Pre-shared secred requires a patch to openssl, so this function is
33088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * commented out unless explicitly needed for EAP-FAST in order to be able to
33098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * build this file with unmodified openssl. */
33108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
33128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   STACK_OF(SSL_CIPHER) *peer_ciphers,
33138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   SSL_CIPHER **cipher, void *arg)
33148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_connection *conn = arg;
33168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
33178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL || conn->session_ticket_cb == NULL)
33198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
33208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx,
33228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      conn->session_ticket,
33238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      conn->session_ticket_len,
33248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      s->s3->client_random,
33258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      s->s3->server_random, secret);
33268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->session_ticket);
33278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->session_ticket = NULL;
33288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret <= 0)
33308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
33318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*secret_len = SSL_MAX_MASTER_KEY_LENGTH;
33338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 1;
33348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_OPENSSL_TICKET_OVERRIDE
33388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_session_ticket_ext_cb(SSL *s, const unsigned char *data,
33398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int len, void *arg)
33408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_connection *conn = arg;
33428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL || conn->session_ticket_cb == NULL)
33448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
33458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: %s: length=%d", __func__, len);
33478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->session_ticket);
33498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->session_ticket = NULL;
33508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket "
33528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    "extension", data, len);
33538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->session_ticket = os_malloc(len);
33558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->session_ticket == NULL)
33568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
33578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(conn->session_ticket, data, len);
33598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->session_ticket_len = len;
33608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 1;
33628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_OPENSSL_TICKET_OVERRIDE */
33648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef SSL_OP_NO_TICKET
33658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void tls_hello_ext_cb(SSL *s, int client_server, int type,
33668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     unsigned char *data, int len, void *arg)
33678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_connection *conn = arg;
33698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL || conn->session_ticket_cb == NULL)
33718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
33728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: %s: type=%d length=%d", __func__,
33748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   type, len);
33758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type == TLSEXT_TYPE_session_ticket && !client_server) {
33778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(conn->session_ticket);
33788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->session_ticket = NULL;
33798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket "
33818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    "extension", data, len);
33828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->session_ticket = os_malloc(len);
33838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conn->session_ticket == NULL)
33848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
33858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(conn->session_ticket, data, len);
33878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->session_ticket_len = len;
33888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* SSL_OP_NO_TICKET */
33918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_hello_ext_cb(SSL *s, TLS_EXTENSION *ext, void *arg)
33928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_connection *conn = arg;
33948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL || conn->session_ticket_cb == NULL)
33968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
33978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: %s: type=%d length=%d", __func__,
33998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   ext->type, ext->length);
34008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->session_ticket);
34028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->session_ticket = NULL;
34038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ext->type == 35) {
34058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket "
34068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    "extension", ext->data, ext->length);
34078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->session_ticket = os_malloc(ext->length);
34088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conn->session_ticket == NULL)
34098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return SSL_AD_INTERNAL_ERROR;
34108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(conn->session_ticket, ext->data, ext->length);
34128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->session_ticket_len = ext->length;
34138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
34168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* SSL_OP_NO_TICKET */
34188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */
34198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
34208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_session_ticket_cb(void *tls_ctx,
34238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 struct tls_connection *conn,
34248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 tls_session_ticket_cb cb,
34258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 void *ctx)
34268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
34288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->session_ticket_cb = cb;
34298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->session_ticket_cb_ctx = ctx;
34308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cb) {
34328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb,
34338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      conn) != 1)
34348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
34358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_OPENSSL_TICKET_OVERRIDE
34368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_set_session_ticket_ext_cb(conn->ssl,
34378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      tls_session_ticket_ext_cb, conn);
34388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_OPENSSL_TICKET_OVERRIDE */
34398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef SSL_OP_NO_TICKET
34408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_set_tlsext_debug_callback(conn->ssl, tls_hello_ext_cb);
34418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_set_tlsext_debug_arg(conn->ssl, conn);
34428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* SSL_OP_NO_TICKET */
34438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_set_hello_extension_cb(conn->ssl, tls_hello_ext_cb,
34448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       conn) != 1)
34458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
34468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* SSL_OP_NO_TICKET */
34478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */
34488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
34498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1)
34508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
34518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_OPENSSL_TICKET_OVERRIDE
34528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_set_session_ticket_ext_cb(conn->ssl, NULL, NULL);
34538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_OPENSSL_TICKET_OVERRIDE */
34548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef SSL_OP_NO_TICKET
34558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_set_tlsext_debug_callback(conn->ssl, NULL);
34568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SSL_set_tlsext_debug_arg(conn->ssl, conn);
34578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* SSL_OP_NO_TICKET */
34588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (SSL_set_hello_extension_cb(conn->ssl, NULL, NULL) != 1)
34598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
34608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* SSL_OP_NO_TICKET */
34618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */
34628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
34658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
34668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
34678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
34688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3469