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