1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * SSL/TLS interface functions for wolfSSL TLS case 3e5b75505Sopenharmony_ci * Copyright (c) 2004-2017, 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#include "common.h" 12e5b75505Sopenharmony_ci#include "crypto.h" 13e5b75505Sopenharmony_ci#include "crypto/sha1.h" 14e5b75505Sopenharmony_ci#include "crypto/sha256.h" 15e5b75505Sopenharmony_ci#include "tls.h" 16e5b75505Sopenharmony_ci 17e5b75505Sopenharmony_ci/* wolfSSL includes */ 18e5b75505Sopenharmony_ci#include <wolfssl/options.h> 19e5b75505Sopenharmony_ci#include <wolfssl/ssl.h> 20e5b75505Sopenharmony_ci#include <wolfssl/error-ssl.h> 21e5b75505Sopenharmony_ci#include <wolfssl/wolfcrypt/asn.h> 22e5b75505Sopenharmony_ci 23e5b75505Sopenharmony_ci#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) 24e5b75505Sopenharmony_ci#define HAVE_AESGCM 25e5b75505Sopenharmony_ci#include <wolfssl/wolfcrypt/aes.h> 26e5b75505Sopenharmony_ci#endif 27e5b75505Sopenharmony_ci 28e5b75505Sopenharmony_ci#if !defined(CONFIG_FIPS) && \ 29e5b75505Sopenharmony_ci (defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || \ 30e5b75505Sopenharmony_ci defined(EAP_SERVER_FAST)) 31e5b75505Sopenharmony_ci#define WOLFSSL_NEED_EAP_FAST_PRF 32e5b75505Sopenharmony_ci#endif 33e5b75505Sopenharmony_ci 34e5b75505Sopenharmony_ci#define SECRET_LEN 48 35e5b75505Sopenharmony_ci#define RAN_LEN 32 36e5b75505Sopenharmony_ci#define SESSION_TICKET_LEN 256 37e5b75505Sopenharmony_ci 38e5b75505Sopenharmony_cistatic int tls_ref_count = 0; 39e5b75505Sopenharmony_ci 40e5b75505Sopenharmony_cistatic int tls_ex_idx_session = 0; 41e5b75505Sopenharmony_ci 42e5b75505Sopenharmony_ci 43e5b75505Sopenharmony_ci/* tls input data for wolfSSL Read Callback */ 44e5b75505Sopenharmony_cistruct tls_in_data { 45e5b75505Sopenharmony_ci const struct wpabuf *in_data; 46e5b75505Sopenharmony_ci size_t consumed; /* how many bytes have we used already */ 47e5b75505Sopenharmony_ci}; 48e5b75505Sopenharmony_ci 49e5b75505Sopenharmony_ci/* tls output data for wolfSSL Write Callback */ 50e5b75505Sopenharmony_cistruct tls_out_data { 51e5b75505Sopenharmony_ci struct wpabuf *out_data; 52e5b75505Sopenharmony_ci}; 53e5b75505Sopenharmony_ci 54e5b75505Sopenharmony_cistruct tls_context { 55e5b75505Sopenharmony_ci void (*event_cb)(void *ctx, enum tls_event ev, 56e5b75505Sopenharmony_ci union tls_event_data *data); 57e5b75505Sopenharmony_ci void *cb_ctx; 58e5b75505Sopenharmony_ci int cert_in_cb; 59e5b75505Sopenharmony_ci char *ocsp_stapling_response; 60e5b75505Sopenharmony_ci}; 61e5b75505Sopenharmony_ci 62e5b75505Sopenharmony_cistatic struct tls_context *tls_global = NULL; 63e5b75505Sopenharmony_ci 64e5b75505Sopenharmony_ci/* wolfssl tls_connection */ 65e5b75505Sopenharmony_cistruct tls_connection { 66e5b75505Sopenharmony_ci struct tls_context *context; 67e5b75505Sopenharmony_ci WOLFSSL *ssl; 68e5b75505Sopenharmony_ci int read_alerts; 69e5b75505Sopenharmony_ci int write_alerts; 70e5b75505Sopenharmony_ci int failed; 71e5b75505Sopenharmony_ci struct tls_in_data input; 72e5b75505Sopenharmony_ci struct tls_out_data output; 73e5b75505Sopenharmony_ci char *subject_match; 74e5b75505Sopenharmony_ci char *alt_subject_match; 75e5b75505Sopenharmony_ci char *suffix_match; 76e5b75505Sopenharmony_ci char *domain_match; 77e5b75505Sopenharmony_ci 78e5b75505Sopenharmony_ci u8 srv_cert_hash[32]; 79e5b75505Sopenharmony_ci 80e5b75505Sopenharmony_ci unsigned char client_random[RAN_LEN]; 81e5b75505Sopenharmony_ci unsigned char server_random[RAN_LEN]; 82e5b75505Sopenharmony_ci unsigned int flags; 83e5b75505Sopenharmony_ci#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) 84e5b75505Sopenharmony_ci tls_session_ticket_cb session_ticket_cb; 85e5b75505Sopenharmony_ci void *session_ticket_cb_ctx; 86e5b75505Sopenharmony_ci byte session_ticket[SESSION_TICKET_LEN]; 87e5b75505Sopenharmony_ci#endif 88e5b75505Sopenharmony_ci unsigned int ca_cert_verify:1; 89e5b75505Sopenharmony_ci unsigned int cert_probe:1; 90e5b75505Sopenharmony_ci unsigned int server_cert_only:1; 91e5b75505Sopenharmony_ci unsigned int success_data:1; 92e5b75505Sopenharmony_ci 93e5b75505Sopenharmony_ci WOLFSSL_X509 *peer_cert; 94e5b75505Sopenharmony_ci WOLFSSL_X509 *peer_issuer; 95e5b75505Sopenharmony_ci WOLFSSL_X509 *peer_issuer_issuer; 96e5b75505Sopenharmony_ci}; 97e5b75505Sopenharmony_ci 98e5b75505Sopenharmony_ci 99e5b75505Sopenharmony_cistatic struct tls_context * tls_context_new(const struct tls_config *conf) 100e5b75505Sopenharmony_ci{ 101e5b75505Sopenharmony_ci struct tls_context *context = os_zalloc(sizeof(*context)); 102e5b75505Sopenharmony_ci 103e5b75505Sopenharmony_ci if (!context) 104e5b75505Sopenharmony_ci return NULL; 105e5b75505Sopenharmony_ci 106e5b75505Sopenharmony_ci if (conf) { 107e5b75505Sopenharmony_ci context->event_cb = conf->event_cb; 108e5b75505Sopenharmony_ci context->cb_ctx = conf->cb_ctx; 109e5b75505Sopenharmony_ci context->cert_in_cb = conf->cert_in_cb; 110e5b75505Sopenharmony_ci } 111e5b75505Sopenharmony_ci 112e5b75505Sopenharmony_ci return context; 113e5b75505Sopenharmony_ci} 114e5b75505Sopenharmony_ci 115e5b75505Sopenharmony_ci 116e5b75505Sopenharmony_cistatic void wolfssl_reset_in_data(struct tls_in_data *in, 117e5b75505Sopenharmony_ci const struct wpabuf *buf) 118e5b75505Sopenharmony_ci{ 119e5b75505Sopenharmony_ci /* old one not owned by us so don't free */ 120e5b75505Sopenharmony_ci in->in_data = buf; 121e5b75505Sopenharmony_ci in->consumed = 0; 122e5b75505Sopenharmony_ci} 123e5b75505Sopenharmony_ci 124e5b75505Sopenharmony_ci 125e5b75505Sopenharmony_cistatic void wolfssl_reset_out_data(struct tls_out_data *out) 126e5b75505Sopenharmony_ci{ 127e5b75505Sopenharmony_ci /* old one not owned by us so don't free */ 128e5b75505Sopenharmony_ci out->out_data = wpabuf_alloc_copy("", 0); 129e5b75505Sopenharmony_ci} 130e5b75505Sopenharmony_ci 131e5b75505Sopenharmony_ci 132e5b75505Sopenharmony_ci/* wolfSSL I/O Receive CallBack */ 133e5b75505Sopenharmony_cistatic int wolfssl_receive_cb(WOLFSSL *ssl, char *buf, int sz, void *ctx) 134e5b75505Sopenharmony_ci{ 135e5b75505Sopenharmony_ci size_t get = sz; 136e5b75505Sopenharmony_ci struct tls_in_data *data = ctx; 137e5b75505Sopenharmony_ci 138e5b75505Sopenharmony_ci if (!data) 139e5b75505Sopenharmony_ci return -1; 140e5b75505Sopenharmony_ci 141e5b75505Sopenharmony_ci if (get > (wpabuf_len(data->in_data) - data->consumed)) 142e5b75505Sopenharmony_ci get = wpabuf_len(data->in_data) - data->consumed; 143e5b75505Sopenharmony_ci 144e5b75505Sopenharmony_ci os_memcpy(buf, wpabuf_head_u8(data->in_data) + data->consumed, get); 145e5b75505Sopenharmony_ci data->consumed += get; 146e5b75505Sopenharmony_ci 147e5b75505Sopenharmony_ci if (get == 0) 148e5b75505Sopenharmony_ci return -2; /* WANT_READ */ 149e5b75505Sopenharmony_ci 150e5b75505Sopenharmony_ci return (int) get; 151e5b75505Sopenharmony_ci} 152e5b75505Sopenharmony_ci 153e5b75505Sopenharmony_ci 154e5b75505Sopenharmony_ci/* wolfSSL I/O Send CallBack */ 155e5b75505Sopenharmony_cistatic int wolfssl_send_cb(WOLFSSL *ssl, char *buf, int sz, void *ctx) 156e5b75505Sopenharmony_ci{ 157e5b75505Sopenharmony_ci struct wpabuf *tmp; 158e5b75505Sopenharmony_ci struct tls_out_data *data = ctx; 159e5b75505Sopenharmony_ci 160e5b75505Sopenharmony_ci if (!data) 161e5b75505Sopenharmony_ci return -1; 162e5b75505Sopenharmony_ci 163e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: adding %d bytes", sz); 164e5b75505Sopenharmony_ci 165e5b75505Sopenharmony_ci tmp = wpabuf_alloc_copy(buf, sz); 166e5b75505Sopenharmony_ci if (!tmp) 167e5b75505Sopenharmony_ci return -1; 168e5b75505Sopenharmony_ci data->out_data = wpabuf_concat(data->out_data, tmp); 169e5b75505Sopenharmony_ci if (!data->out_data) 170e5b75505Sopenharmony_ci return -1; 171e5b75505Sopenharmony_ci 172e5b75505Sopenharmony_ci return sz; 173e5b75505Sopenharmony_ci} 174e5b75505Sopenharmony_ci 175e5b75505Sopenharmony_ci 176e5b75505Sopenharmony_cistatic void remove_session_cb(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *sess) 177e5b75505Sopenharmony_ci{ 178e5b75505Sopenharmony_ci struct wpabuf *buf; 179e5b75505Sopenharmony_ci 180e5b75505Sopenharmony_ci buf = wolfSSL_SESSION_get_ex_data(sess, tls_ex_idx_session); 181e5b75505Sopenharmony_ci if (!buf) 182e5b75505Sopenharmony_ci return; 183e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 184e5b75505Sopenharmony_ci "wolfSSL: Free application session data %p (sess %p)", 185e5b75505Sopenharmony_ci buf, sess); 186e5b75505Sopenharmony_ci wpabuf_free(buf); 187e5b75505Sopenharmony_ci 188e5b75505Sopenharmony_ci wolfSSL_SESSION_set_ex_data(sess, tls_ex_idx_session, NULL); 189e5b75505Sopenharmony_ci} 190e5b75505Sopenharmony_ci 191e5b75505Sopenharmony_ci 192e5b75505Sopenharmony_civoid * tls_init(const struct tls_config *conf) 193e5b75505Sopenharmony_ci{ 194e5b75505Sopenharmony_ci WOLFSSL_CTX *ssl_ctx; 195e5b75505Sopenharmony_ci struct tls_context *context; 196e5b75505Sopenharmony_ci const char *ciphers; 197e5b75505Sopenharmony_ci 198e5b75505Sopenharmony_ci#ifdef DEBUG_WOLFSSL 199e5b75505Sopenharmony_ci wolfSSL_Debugging_ON(); 200e5b75505Sopenharmony_ci#endif /* DEBUG_WOLFSSL */ 201e5b75505Sopenharmony_ci 202e5b75505Sopenharmony_ci context = tls_context_new(conf); 203e5b75505Sopenharmony_ci if (!context) 204e5b75505Sopenharmony_ci return NULL; 205e5b75505Sopenharmony_ci 206e5b75505Sopenharmony_ci if (tls_ref_count == 0) { 207e5b75505Sopenharmony_ci tls_global = context; 208e5b75505Sopenharmony_ci 209e5b75505Sopenharmony_ci if (wolfSSL_Init() < 0) 210e5b75505Sopenharmony_ci return NULL; 211e5b75505Sopenharmony_ci /* wolfSSL_Debugging_ON(); */ 212e5b75505Sopenharmony_ci } 213e5b75505Sopenharmony_ci 214e5b75505Sopenharmony_ci tls_ref_count++; 215e5b75505Sopenharmony_ci 216e5b75505Sopenharmony_ci /* start as client */ 217e5b75505Sopenharmony_ci ssl_ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); 218e5b75505Sopenharmony_ci if (!ssl_ctx) { 219e5b75505Sopenharmony_ci tls_ref_count--; 220e5b75505Sopenharmony_ci if (context != tls_global) 221e5b75505Sopenharmony_ci os_free(context); 222e5b75505Sopenharmony_ci if (tls_ref_count == 0) { 223e5b75505Sopenharmony_ci os_free(tls_global); 224e5b75505Sopenharmony_ci tls_global = NULL; 225e5b75505Sopenharmony_ci } 226e5b75505Sopenharmony_ci } 227e5b75505Sopenharmony_ci wolfSSL_SetIORecv(ssl_ctx, wolfssl_receive_cb); 228e5b75505Sopenharmony_ci wolfSSL_SetIOSend(ssl_ctx, wolfssl_send_cb); 229e5b75505Sopenharmony_ci wolfSSL_CTX_set_ex_data(ssl_ctx, 0, context); 230e5b75505Sopenharmony_ci 231e5b75505Sopenharmony_ci if (conf->tls_session_lifetime > 0) { 232e5b75505Sopenharmony_ci wolfSSL_CTX_set_quiet_shutdown(ssl_ctx, 1); 233e5b75505Sopenharmony_ci wolfSSL_CTX_set_session_cache_mode(ssl_ctx, 234e5b75505Sopenharmony_ci SSL_SESS_CACHE_SERVER); 235e5b75505Sopenharmony_ci wolfSSL_CTX_set_timeout(ssl_ctx, conf->tls_session_lifetime); 236e5b75505Sopenharmony_ci wolfSSL_CTX_sess_set_remove_cb(ssl_ctx, remove_session_cb); 237e5b75505Sopenharmony_ci } else { 238e5b75505Sopenharmony_ci wolfSSL_CTX_set_session_cache_mode(ssl_ctx, 239e5b75505Sopenharmony_ci SSL_SESS_CACHE_CLIENT); 240e5b75505Sopenharmony_ci } 241e5b75505Sopenharmony_ci 242e5b75505Sopenharmony_ci if (conf && conf->openssl_ciphers) 243e5b75505Sopenharmony_ci ciphers = conf->openssl_ciphers; 244e5b75505Sopenharmony_ci else 245e5b75505Sopenharmony_ci ciphers = "ALL"; 246e5b75505Sopenharmony_ci if (wolfSSL_CTX_set_cipher_list(ssl_ctx, ciphers) != 1) { 247e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, 248e5b75505Sopenharmony_ci "wolfSSL: Failed to set cipher string '%s'", 249e5b75505Sopenharmony_ci ciphers); 250e5b75505Sopenharmony_ci tls_deinit(ssl_ctx); 251e5b75505Sopenharmony_ci return NULL; 252e5b75505Sopenharmony_ci } 253e5b75505Sopenharmony_ci 254e5b75505Sopenharmony_ci return ssl_ctx; 255e5b75505Sopenharmony_ci} 256e5b75505Sopenharmony_ci 257e5b75505Sopenharmony_ci 258e5b75505Sopenharmony_civoid tls_deinit(void *ssl_ctx) 259e5b75505Sopenharmony_ci{ 260e5b75505Sopenharmony_ci struct tls_context *context = wolfSSL_CTX_get_ex_data(ssl_ctx, 0); 261e5b75505Sopenharmony_ci 262e5b75505Sopenharmony_ci if (context != tls_global) 263e5b75505Sopenharmony_ci os_free(context); 264e5b75505Sopenharmony_ci 265e5b75505Sopenharmony_ci wolfSSL_CTX_free((WOLFSSL_CTX *) ssl_ctx); 266e5b75505Sopenharmony_ci 267e5b75505Sopenharmony_ci tls_ref_count--; 268e5b75505Sopenharmony_ci if (tls_ref_count == 0) { 269e5b75505Sopenharmony_ci wolfSSL_Cleanup(); 270e5b75505Sopenharmony_ci os_free(tls_global); 271e5b75505Sopenharmony_ci tls_global = NULL; 272e5b75505Sopenharmony_ci } 273e5b75505Sopenharmony_ci} 274e5b75505Sopenharmony_ci 275e5b75505Sopenharmony_ci 276e5b75505Sopenharmony_ciint tls_get_errors(void *tls_ctx) 277e5b75505Sopenharmony_ci{ 278e5b75505Sopenharmony_ci#ifdef DEBUG_WOLFSSL 279e5b75505Sopenharmony_ci#if 0 280e5b75505Sopenharmony_ci unsigned long err; 281e5b75505Sopenharmony_ci 282e5b75505Sopenharmony_ci err = wolfSSL_ERR_peek_last_error_line(NULL, NULL); 283e5b75505Sopenharmony_ci if (err != 0) { 284e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "TLS - SSL error: %s", 285e5b75505Sopenharmony_ci wolfSSL_ERR_error_string(err, NULL)); 286e5b75505Sopenharmony_ci return 1; 287e5b75505Sopenharmony_ci } 288e5b75505Sopenharmony_ci#endif 289e5b75505Sopenharmony_ci#endif /* DEBUG_WOLFSSL */ 290e5b75505Sopenharmony_ci return 0; 291e5b75505Sopenharmony_ci} 292e5b75505Sopenharmony_ci 293e5b75505Sopenharmony_ci 294e5b75505Sopenharmony_cistruct tls_connection * tls_connection_init(void *tls_ctx) 295e5b75505Sopenharmony_ci{ 296e5b75505Sopenharmony_ci WOLFSSL_CTX *ssl_ctx = tls_ctx; 297e5b75505Sopenharmony_ci struct tls_connection *conn; 298e5b75505Sopenharmony_ci 299e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: connection init"); 300e5b75505Sopenharmony_ci 301e5b75505Sopenharmony_ci conn = os_zalloc(sizeof(*conn)); 302e5b75505Sopenharmony_ci if (!conn) 303e5b75505Sopenharmony_ci return NULL; 304e5b75505Sopenharmony_ci conn->ssl = wolfSSL_new(ssl_ctx); 305e5b75505Sopenharmony_ci if (!conn->ssl) { 306e5b75505Sopenharmony_ci os_free(conn); 307e5b75505Sopenharmony_ci return NULL; 308e5b75505Sopenharmony_ci } 309e5b75505Sopenharmony_ci 310e5b75505Sopenharmony_ci wolfSSL_SetIOReadCtx(conn->ssl, &conn->input); 311e5b75505Sopenharmony_ci wolfSSL_SetIOWriteCtx(conn->ssl, &conn->output); 312e5b75505Sopenharmony_ci wolfSSL_set_ex_data(conn->ssl, 0, conn); 313e5b75505Sopenharmony_ci conn->context = wolfSSL_CTX_get_ex_data(ssl_ctx, 0); 314e5b75505Sopenharmony_ci 315e5b75505Sopenharmony_ci /* Need randoms post-hanshake for EAP-FAST, export key and deriving 316e5b75505Sopenharmony_ci * session ID in EAP methods. */ 317e5b75505Sopenharmony_ci wolfSSL_KeepArrays(conn->ssl); 318e5b75505Sopenharmony_ci wolfSSL_KeepHandshakeResources(conn->ssl); 319e5b75505Sopenharmony_ci wolfSSL_UseClientSuites(conn->ssl); 320e5b75505Sopenharmony_ci 321e5b75505Sopenharmony_ci return conn; 322e5b75505Sopenharmony_ci} 323e5b75505Sopenharmony_ci 324e5b75505Sopenharmony_ci 325e5b75505Sopenharmony_civoid tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) 326e5b75505Sopenharmony_ci{ 327e5b75505Sopenharmony_ci if (!conn) 328e5b75505Sopenharmony_ci return; 329e5b75505Sopenharmony_ci 330e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: connection deinit"); 331e5b75505Sopenharmony_ci 332e5b75505Sopenharmony_ci /* parts */ 333e5b75505Sopenharmony_ci wolfSSL_free(conn->ssl); 334e5b75505Sopenharmony_ci os_free(conn->subject_match); 335e5b75505Sopenharmony_ci os_free(conn->alt_subject_match); 336e5b75505Sopenharmony_ci os_free(conn->suffix_match); 337e5b75505Sopenharmony_ci os_free(conn->domain_match); 338e5b75505Sopenharmony_ci 339e5b75505Sopenharmony_ci /* self */ 340e5b75505Sopenharmony_ci os_free(conn); 341e5b75505Sopenharmony_ci} 342e5b75505Sopenharmony_ci 343e5b75505Sopenharmony_ci 344e5b75505Sopenharmony_ciint tls_connection_established(void *tls_ctx, struct tls_connection *conn) 345e5b75505Sopenharmony_ci{ 346e5b75505Sopenharmony_ci return conn ? wolfSSL_is_init_finished(conn->ssl) : 0; 347e5b75505Sopenharmony_ci} 348e5b75505Sopenharmony_ci 349e5b75505Sopenharmony_ci 350e5b75505Sopenharmony_cichar * tls_connection_peer_serial_num(void *tls_ctx, 351e5b75505Sopenharmony_ci struct tls_connection *conn) 352e5b75505Sopenharmony_ci{ 353e5b75505Sopenharmony_ci /* TODO */ 354e5b75505Sopenharmony_ci return NULL; 355e5b75505Sopenharmony_ci} 356e5b75505Sopenharmony_ci 357e5b75505Sopenharmony_ci 358e5b75505Sopenharmony_ciint tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) 359e5b75505Sopenharmony_ci{ 360e5b75505Sopenharmony_ci WOLFSSL_SESSION *session; 361e5b75505Sopenharmony_ci 362e5b75505Sopenharmony_ci if (!conn) 363e5b75505Sopenharmony_ci return -1; 364e5b75505Sopenharmony_ci 365e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: connection shutdown"); 366e5b75505Sopenharmony_ci 367e5b75505Sopenharmony_ci /* Set quiet as OpenSSL does */ 368e5b75505Sopenharmony_ci wolfSSL_set_quiet_shutdown(conn->ssl, 1); 369e5b75505Sopenharmony_ci wolfSSL_shutdown(conn->ssl); 370e5b75505Sopenharmony_ci 371e5b75505Sopenharmony_ci session = wolfSSL_get_session(conn->ssl); 372e5b75505Sopenharmony_ci if (wolfSSL_clear(conn->ssl) != 1) 373e5b75505Sopenharmony_ci return -1; 374e5b75505Sopenharmony_ci wolfSSL_set_session(conn->ssl, session); 375e5b75505Sopenharmony_ci 376e5b75505Sopenharmony_ci return 0; 377e5b75505Sopenharmony_ci} 378e5b75505Sopenharmony_ci 379e5b75505Sopenharmony_ci 380e5b75505Sopenharmony_cistatic int tls_connection_set_subject_match(struct tls_connection *conn, 381e5b75505Sopenharmony_ci const char *subject_match, 382e5b75505Sopenharmony_ci const char *alt_subject_match, 383e5b75505Sopenharmony_ci const char *suffix_match, 384e5b75505Sopenharmony_ci const char *domain_match) 385e5b75505Sopenharmony_ci{ 386e5b75505Sopenharmony_ci os_free(conn->subject_match); 387e5b75505Sopenharmony_ci conn->subject_match = NULL; 388e5b75505Sopenharmony_ci if (subject_match) { 389e5b75505Sopenharmony_ci conn->subject_match = os_strdup(subject_match); 390e5b75505Sopenharmony_ci if (!conn->subject_match) 391e5b75505Sopenharmony_ci return -1; 392e5b75505Sopenharmony_ci } 393e5b75505Sopenharmony_ci 394e5b75505Sopenharmony_ci os_free(conn->alt_subject_match); 395e5b75505Sopenharmony_ci conn->alt_subject_match = NULL; 396e5b75505Sopenharmony_ci if (alt_subject_match) { 397e5b75505Sopenharmony_ci conn->alt_subject_match = os_strdup(alt_subject_match); 398e5b75505Sopenharmony_ci if (!conn->alt_subject_match) 399e5b75505Sopenharmony_ci return -1; 400e5b75505Sopenharmony_ci } 401e5b75505Sopenharmony_ci 402e5b75505Sopenharmony_ci os_free(conn->suffix_match); 403e5b75505Sopenharmony_ci conn->suffix_match = NULL; 404e5b75505Sopenharmony_ci if (suffix_match) { 405e5b75505Sopenharmony_ci conn->suffix_match = os_strdup(suffix_match); 406e5b75505Sopenharmony_ci if (!conn->suffix_match) 407e5b75505Sopenharmony_ci return -1; 408e5b75505Sopenharmony_ci } 409e5b75505Sopenharmony_ci 410e5b75505Sopenharmony_ci os_free(conn->domain_match); 411e5b75505Sopenharmony_ci conn->domain_match = NULL; 412e5b75505Sopenharmony_ci if (domain_match) { 413e5b75505Sopenharmony_ci conn->domain_match = os_strdup(domain_match); 414e5b75505Sopenharmony_ci if (!conn->domain_match) 415e5b75505Sopenharmony_ci return -1; 416e5b75505Sopenharmony_ci } 417e5b75505Sopenharmony_ci 418e5b75505Sopenharmony_ci return 0; 419e5b75505Sopenharmony_ci} 420e5b75505Sopenharmony_ci 421e5b75505Sopenharmony_ci 422e5b75505Sopenharmony_cistatic int tls_connection_dh(struct tls_connection *conn, const char *dh_file, 423e5b75505Sopenharmony_ci const u8 *dh_blob, size_t blob_len) 424e5b75505Sopenharmony_ci{ 425e5b75505Sopenharmony_ci if (!dh_file && !dh_blob) 426e5b75505Sopenharmony_ci return 0; 427e5b75505Sopenharmony_ci 428e5b75505Sopenharmony_ci wolfSSL_set_accept_state(conn->ssl); 429e5b75505Sopenharmony_ci 430e5b75505Sopenharmony_ci if (dh_blob) { 431e5b75505Sopenharmony_ci if (wolfSSL_SetTmpDH_buffer(conn->ssl, dh_blob, blob_len, 432e5b75505Sopenharmony_ci SSL_FILETYPE_ASN1) < 0) { 433e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "SSL: use DH DER blob failed"); 434e5b75505Sopenharmony_ci return -1; 435e5b75505Sopenharmony_ci } 436e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: use DH blob OK"); 437e5b75505Sopenharmony_ci return 0; 438e5b75505Sopenharmony_ci } 439e5b75505Sopenharmony_ci 440e5b75505Sopenharmony_ci if (dh_file) { 441e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "SSL: use DH PEM file: %s", dh_file); 442e5b75505Sopenharmony_ci if (wolfSSL_SetTmpDH_file(conn->ssl, dh_file, 443e5b75505Sopenharmony_ci SSL_FILETYPE_PEM) < 0) { 444e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "SSL: use DH PEM file failed"); 445e5b75505Sopenharmony_ci if (wolfSSL_SetTmpDH_file(conn->ssl, dh_file, 446e5b75505Sopenharmony_ci SSL_FILETYPE_ASN1) < 0) { 447e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 448e5b75505Sopenharmony_ci "SSL: use DH DER file failed"); 449e5b75505Sopenharmony_ci return -1; 450e5b75505Sopenharmony_ci } 451e5b75505Sopenharmony_ci } 452e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: use DH file OK"); 453e5b75505Sopenharmony_ci return 0; 454e5b75505Sopenharmony_ci } 455e5b75505Sopenharmony_ci 456e5b75505Sopenharmony_ci return 0; 457e5b75505Sopenharmony_ci} 458e5b75505Sopenharmony_ci 459e5b75505Sopenharmony_ci 460e5b75505Sopenharmony_cistatic int tls_connection_client_cert(struct tls_connection *conn, 461e5b75505Sopenharmony_ci const char *client_cert, 462e5b75505Sopenharmony_ci const u8 *client_cert_blob, 463e5b75505Sopenharmony_ci size_t blob_len) 464e5b75505Sopenharmony_ci{ 465e5b75505Sopenharmony_ci if (!client_cert && !client_cert_blob) 466e5b75505Sopenharmony_ci return 0; 467e5b75505Sopenharmony_ci 468e5b75505Sopenharmony_ci if (client_cert_blob) { 469e5b75505Sopenharmony_ci if (wolfSSL_use_certificate_chain_buffer_format( 470e5b75505Sopenharmony_ci conn->ssl, client_cert_blob, blob_len, 471e5b75505Sopenharmony_ci SSL_FILETYPE_ASN1) < 0) { 472e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 473e5b75505Sopenharmony_ci "SSL: use client cert DER blob failed"); 474e5b75505Sopenharmony_ci return -1; 475e5b75505Sopenharmony_ci } 476e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: use client cert blob OK"); 477e5b75505Sopenharmony_ci return 0; 478e5b75505Sopenharmony_ci } 479e5b75505Sopenharmony_ci 480e5b75505Sopenharmony_ci if (client_cert) { 481e5b75505Sopenharmony_ci if (wolfSSL_use_certificate_chain_file(conn->ssl, 482e5b75505Sopenharmony_ci client_cert) < 0) { 483e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 484e5b75505Sopenharmony_ci "SSL: use client cert PEM file failed"); 485e5b75505Sopenharmony_ci if (wolfSSL_use_certificate_chain_file_format( 486e5b75505Sopenharmony_ci conn->ssl, client_cert, 487e5b75505Sopenharmony_ci SSL_FILETYPE_ASN1) < 0) { 488e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 489e5b75505Sopenharmony_ci "SSL: use client cert DER file failed"); 490e5b75505Sopenharmony_ci return -1; 491e5b75505Sopenharmony_ci } 492e5b75505Sopenharmony_ci } 493e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: use client cert file OK"); 494e5b75505Sopenharmony_ci return 0; 495e5b75505Sopenharmony_ci } 496e5b75505Sopenharmony_ci 497e5b75505Sopenharmony_ci return 0; 498e5b75505Sopenharmony_ci} 499e5b75505Sopenharmony_ci 500e5b75505Sopenharmony_ci 501e5b75505Sopenharmony_cistatic int tls_passwd_cb(char *buf, int size, int rwflag, void *password) 502e5b75505Sopenharmony_ci{ 503e5b75505Sopenharmony_ci if (!password) 504e5b75505Sopenharmony_ci return 0; 505e5b75505Sopenharmony_ci os_strlcpy(buf, (char *) password, size); 506e5b75505Sopenharmony_ci return os_strlen(buf); 507e5b75505Sopenharmony_ci} 508e5b75505Sopenharmony_ci 509e5b75505Sopenharmony_ci 510e5b75505Sopenharmony_cistatic int tls_connection_private_key(void *tls_ctx, 511e5b75505Sopenharmony_ci struct tls_connection *conn, 512e5b75505Sopenharmony_ci const char *private_key, 513e5b75505Sopenharmony_ci const char *private_key_passwd, 514e5b75505Sopenharmony_ci const u8 *private_key_blob, 515e5b75505Sopenharmony_ci size_t blob_len) 516e5b75505Sopenharmony_ci{ 517e5b75505Sopenharmony_ci WOLFSSL_CTX *ctx = tls_ctx; 518e5b75505Sopenharmony_ci char *passwd = NULL; 519e5b75505Sopenharmony_ci int ok = 0; 520e5b75505Sopenharmony_ci 521e5b75505Sopenharmony_ci if (!private_key && !private_key_blob) 522e5b75505Sopenharmony_ci return 0; 523e5b75505Sopenharmony_ci 524e5b75505Sopenharmony_ci if (private_key_passwd) { 525e5b75505Sopenharmony_ci passwd = os_strdup(private_key_passwd); 526e5b75505Sopenharmony_ci if (!passwd) 527e5b75505Sopenharmony_ci return -1; 528e5b75505Sopenharmony_ci } 529e5b75505Sopenharmony_ci 530e5b75505Sopenharmony_ci wolfSSL_CTX_set_default_passwd_cb(ctx, tls_passwd_cb); 531e5b75505Sopenharmony_ci wolfSSL_CTX_set_default_passwd_cb_userdata(ctx, passwd); 532e5b75505Sopenharmony_ci 533e5b75505Sopenharmony_ci if (private_key_blob) { 534e5b75505Sopenharmony_ci if (wolfSSL_use_PrivateKey_buffer(conn->ssl, 535e5b75505Sopenharmony_ci private_key_blob, blob_len, 536e5b75505Sopenharmony_ci SSL_FILETYPE_ASN1) < 0) { 537e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 538e5b75505Sopenharmony_ci "SSL: use private DER blob failed"); 539e5b75505Sopenharmony_ci } else { 540e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: use private key blob OK"); 541e5b75505Sopenharmony_ci ok = 1; 542e5b75505Sopenharmony_ci } 543e5b75505Sopenharmony_ci } 544e5b75505Sopenharmony_ci 545e5b75505Sopenharmony_ci if (!ok && private_key) { 546e5b75505Sopenharmony_ci if (wolfSSL_use_PrivateKey_file(conn->ssl, private_key, 547e5b75505Sopenharmony_ci SSL_FILETYPE_PEM) < 0) { 548e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 549e5b75505Sopenharmony_ci "SSL: use private key PEM file failed"); 550e5b75505Sopenharmony_ci if (wolfSSL_use_PrivateKey_file(conn->ssl, private_key, 551e5b75505Sopenharmony_ci SSL_FILETYPE_ASN1) < 0) 552e5b75505Sopenharmony_ci { 553e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 554e5b75505Sopenharmony_ci "SSL: use private key DER file failed"); 555e5b75505Sopenharmony_ci } else { 556e5b75505Sopenharmony_ci ok = 1; 557e5b75505Sopenharmony_ci } 558e5b75505Sopenharmony_ci } else { 559e5b75505Sopenharmony_ci ok = 1; 560e5b75505Sopenharmony_ci } 561e5b75505Sopenharmony_ci 562e5b75505Sopenharmony_ci if (ok) 563e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: use private key file OK"); 564e5b75505Sopenharmony_ci } 565e5b75505Sopenharmony_ci 566e5b75505Sopenharmony_ci wolfSSL_CTX_set_default_passwd_cb(ctx, NULL); 567e5b75505Sopenharmony_ci os_free(passwd); 568e5b75505Sopenharmony_ci 569e5b75505Sopenharmony_ci if (!ok) 570e5b75505Sopenharmony_ci return -1; 571e5b75505Sopenharmony_ci 572e5b75505Sopenharmony_ci return 0; 573e5b75505Sopenharmony_ci} 574e5b75505Sopenharmony_ci 575e5b75505Sopenharmony_ci 576e5b75505Sopenharmony_cistatic int tls_match_alt_subject_component(WOLFSSL_X509 *cert, int type, 577e5b75505Sopenharmony_ci const char *value, size_t len) 578e5b75505Sopenharmony_ci{ 579e5b75505Sopenharmony_ci WOLFSSL_ASN1_OBJECT *gen; 580e5b75505Sopenharmony_ci void *ext; 581e5b75505Sopenharmony_ci int found = 0; 582e5b75505Sopenharmony_ci int i; 583e5b75505Sopenharmony_ci 584e5b75505Sopenharmony_ci ext = wolfSSL_X509_get_ext_d2i(cert, ALT_NAMES_OID, NULL, NULL); 585e5b75505Sopenharmony_ci 586e5b75505Sopenharmony_ci for (i = 0; ext && i < wolfSSL_sk_num(ext); i++) { 587e5b75505Sopenharmony_ci gen = wolfSSL_sk_value(ext, i); 588e5b75505Sopenharmony_ci if (gen->type != type) 589e5b75505Sopenharmony_ci continue; 590e5b75505Sopenharmony_ci if (os_strlen((char *) gen->obj) == len && 591e5b75505Sopenharmony_ci os_memcmp(value, gen->obj, len) == 0) 592e5b75505Sopenharmony_ci found++; 593e5b75505Sopenharmony_ci } 594e5b75505Sopenharmony_ci 595e5b75505Sopenharmony_ci wolfSSL_sk_ASN1_OBJECT_free(ext); 596e5b75505Sopenharmony_ci 597e5b75505Sopenharmony_ci return found; 598e5b75505Sopenharmony_ci} 599e5b75505Sopenharmony_ci 600e5b75505Sopenharmony_ci 601e5b75505Sopenharmony_cistatic int tls_match_alt_subject(WOLFSSL_X509 *cert, const char *match) 602e5b75505Sopenharmony_ci{ 603e5b75505Sopenharmony_ci int type; 604e5b75505Sopenharmony_ci const char *pos, *end; 605e5b75505Sopenharmony_ci size_t len; 606e5b75505Sopenharmony_ci 607e5b75505Sopenharmony_ci pos = match; 608e5b75505Sopenharmony_ci do { 609e5b75505Sopenharmony_ci if (os_strncmp(pos, "EMAIL:", 6) == 0) { 610e5b75505Sopenharmony_ci type = GEN_EMAIL; 611e5b75505Sopenharmony_ci pos += 6; 612e5b75505Sopenharmony_ci } else if (os_strncmp(pos, "DNS:", 4) == 0) { 613e5b75505Sopenharmony_ci type = GEN_DNS; 614e5b75505Sopenharmony_ci pos += 4; 615e5b75505Sopenharmony_ci } else if (os_strncmp(pos, "URI:", 4) == 0) { 616e5b75505Sopenharmony_ci type = GEN_URI; 617e5b75505Sopenharmony_ci pos += 4; 618e5b75505Sopenharmony_ci } else { 619e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 620e5b75505Sopenharmony_ci "TLS: Invalid altSubjectName match '%s'", 621e5b75505Sopenharmony_ci pos); 622e5b75505Sopenharmony_ci return 0; 623e5b75505Sopenharmony_ci } 624e5b75505Sopenharmony_ci end = os_strchr(pos, ';'); 625e5b75505Sopenharmony_ci while (end) { 626e5b75505Sopenharmony_ci if (os_strncmp(end + 1, "EMAIL:", 6) == 0 || 627e5b75505Sopenharmony_ci os_strncmp(end + 1, "DNS:", 4) == 0 || 628e5b75505Sopenharmony_ci os_strncmp(end + 1, "URI:", 4) == 0) 629e5b75505Sopenharmony_ci break; 630e5b75505Sopenharmony_ci end = os_strchr(end + 1, ';'); 631e5b75505Sopenharmony_ci } 632e5b75505Sopenharmony_ci if (end) 633e5b75505Sopenharmony_ci len = end - pos; 634e5b75505Sopenharmony_ci else 635e5b75505Sopenharmony_ci len = os_strlen(pos); 636e5b75505Sopenharmony_ci if (tls_match_alt_subject_component(cert, type, pos, len) > 0) 637e5b75505Sopenharmony_ci return 1; 638e5b75505Sopenharmony_ci pos = end + 1; 639e5b75505Sopenharmony_ci } while (end); 640e5b75505Sopenharmony_ci 641e5b75505Sopenharmony_ci return 0; 642e5b75505Sopenharmony_ci} 643e5b75505Sopenharmony_ci 644e5b75505Sopenharmony_ci 645e5b75505Sopenharmony_cistatic int domain_suffix_match(const char *val, size_t len, const char *match, 646e5b75505Sopenharmony_ci size_t match_len, int full) 647e5b75505Sopenharmony_ci{ 648e5b75505Sopenharmony_ci size_t i; 649e5b75505Sopenharmony_ci 650e5b75505Sopenharmony_ci /* Check for embedded nuls that could mess up suffix matching */ 651e5b75505Sopenharmony_ci for (i = 0; i < len; i++) { 652e5b75505Sopenharmony_ci if (val[i] == '\0') { 653e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 654e5b75505Sopenharmony_ci "TLS: Embedded null in a string - reject"); 655e5b75505Sopenharmony_ci return 0; 656e5b75505Sopenharmony_ci } 657e5b75505Sopenharmony_ci } 658e5b75505Sopenharmony_ci 659e5b75505Sopenharmony_ci if (match_len > len || (full && match_len != len)) 660e5b75505Sopenharmony_ci return 0; 661e5b75505Sopenharmony_ci 662e5b75505Sopenharmony_ci if (os_strncasecmp(val + len - match_len, match, match_len) != 0) 663e5b75505Sopenharmony_ci return 0; /* no match */ 664e5b75505Sopenharmony_ci 665e5b75505Sopenharmony_ci if (match_len == len) 666e5b75505Sopenharmony_ci return 1; /* exact match */ 667e5b75505Sopenharmony_ci 668e5b75505Sopenharmony_ci if (val[len - match_len - 1] == '.') 669e5b75505Sopenharmony_ci return 1; /* full label match completes suffix match */ 670e5b75505Sopenharmony_ci 671e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TLS: Reject due to incomplete label match"); 672e5b75505Sopenharmony_ci return 0; 673e5b75505Sopenharmony_ci} 674e5b75505Sopenharmony_ci 675e5b75505Sopenharmony_ci 676e5b75505Sopenharmony_cistatic int tls_match_suffix_helper(WOLFSSL_X509 *cert, const char *match, 677e5b75505Sopenharmony_ci size_t match_len, int full) 678e5b75505Sopenharmony_ci{ 679e5b75505Sopenharmony_ci WOLFSSL_ASN1_OBJECT *gen; 680e5b75505Sopenharmony_ci void *ext; 681e5b75505Sopenharmony_ci int i; 682e5b75505Sopenharmony_ci int j; 683e5b75505Sopenharmony_ci int dns_name = 0; 684e5b75505Sopenharmony_ci WOLFSSL_X509_NAME *name; 685e5b75505Sopenharmony_ci 686e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TLS: Match domain against %s%s", 687e5b75505Sopenharmony_ci full ? "" : "suffix ", match); 688e5b75505Sopenharmony_ci 689e5b75505Sopenharmony_ci ext = wolfSSL_X509_get_ext_d2i(cert, ALT_NAMES_OID, NULL, NULL); 690e5b75505Sopenharmony_ci 691e5b75505Sopenharmony_ci for (j = 0; ext && j < wolfSSL_sk_num(ext); j++) { 692e5b75505Sopenharmony_ci gen = wolfSSL_sk_value(ext, j); 693e5b75505Sopenharmony_ci if (gen->type != ASN_DNS_TYPE) 694e5b75505Sopenharmony_ci continue; 695e5b75505Sopenharmony_ci dns_name++; 696e5b75505Sopenharmony_ci wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate dNSName", 697e5b75505Sopenharmony_ci gen->obj, os_strlen((char *)gen->obj)); 698e5b75505Sopenharmony_ci if (domain_suffix_match((const char *) gen->obj, 699e5b75505Sopenharmony_ci os_strlen((char *) gen->obj), match, 700e5b75505Sopenharmony_ci match_len, full) == 1) { 701e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TLS: %s in dNSName found", 702e5b75505Sopenharmony_ci full ? "Match" : "Suffix match"); 703e5b75505Sopenharmony_ci wolfSSL_sk_ASN1_OBJECT_free(ext); 704e5b75505Sopenharmony_ci return 1; 705e5b75505Sopenharmony_ci } 706e5b75505Sopenharmony_ci } 707e5b75505Sopenharmony_ci wolfSSL_sk_ASN1_OBJECT_free(ext); 708e5b75505Sopenharmony_ci 709e5b75505Sopenharmony_ci if (dns_name) { 710e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TLS: None of the dNSName(s) matched"); 711e5b75505Sopenharmony_ci return 0; 712e5b75505Sopenharmony_ci } 713e5b75505Sopenharmony_ci 714e5b75505Sopenharmony_ci name = wolfSSL_X509_get_subject_name(cert); 715e5b75505Sopenharmony_ci i = -1; 716e5b75505Sopenharmony_ci for (;;) { 717e5b75505Sopenharmony_ci WOLFSSL_X509_NAME_ENTRY *e; 718e5b75505Sopenharmony_ci WOLFSSL_ASN1_STRING *cn; 719e5b75505Sopenharmony_ci 720e5b75505Sopenharmony_ci i = wolfSSL_X509_NAME_get_index_by_NID(name, ASN_COMMON_NAME, 721e5b75505Sopenharmony_ci i); 722e5b75505Sopenharmony_ci if (i == -1) 723e5b75505Sopenharmony_ci break; 724e5b75505Sopenharmony_ci e = wolfSSL_X509_NAME_get_entry(name, i); 725e5b75505Sopenharmony_ci if (!e) 726e5b75505Sopenharmony_ci continue; 727e5b75505Sopenharmony_ci cn = wolfSSL_X509_NAME_ENTRY_get_data(e); 728e5b75505Sopenharmony_ci if (!cn) 729e5b75505Sopenharmony_ci continue; 730e5b75505Sopenharmony_ci wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate commonName", 731e5b75505Sopenharmony_ci cn->data, cn->length); 732e5b75505Sopenharmony_ci if (domain_suffix_match(cn->data, cn->length, 733e5b75505Sopenharmony_ci match, match_len, full) == 1) { 734e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TLS: %s in commonName found", 735e5b75505Sopenharmony_ci full ? "Match" : "Suffix match"); 736e5b75505Sopenharmony_ci return 1; 737e5b75505Sopenharmony_ci } 738e5b75505Sopenharmony_ci } 739e5b75505Sopenharmony_ci 740e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TLS: No CommonName %smatch found", 741e5b75505Sopenharmony_ci full ? "" : "suffix "); 742e5b75505Sopenharmony_ci return 0; 743e5b75505Sopenharmony_ci} 744e5b75505Sopenharmony_ci 745e5b75505Sopenharmony_ci 746e5b75505Sopenharmony_cistatic int tls_match_suffix(WOLFSSL_X509 *cert, const char *match, int full) 747e5b75505Sopenharmony_ci{ 748e5b75505Sopenharmony_ci const char *token, *last = NULL; 749e5b75505Sopenharmony_ci 750e5b75505Sopenharmony_ci /* Process each match alternative separately until a match is found */ 751e5b75505Sopenharmony_ci while ((token = cstr_token(match, ";", &last))) { 752e5b75505Sopenharmony_ci if (tls_match_suffix_helper(cert, token, last - token, full)) 753e5b75505Sopenharmony_ci return 1; 754e5b75505Sopenharmony_ci } 755e5b75505Sopenharmony_ci 756e5b75505Sopenharmony_ci return 0; 757e5b75505Sopenharmony_ci} 758e5b75505Sopenharmony_ci 759e5b75505Sopenharmony_ci 760e5b75505Sopenharmony_cistatic enum tls_fail_reason wolfssl_tls_fail_reason(int err) 761e5b75505Sopenharmony_ci{ 762e5b75505Sopenharmony_ci switch (err) { 763e5b75505Sopenharmony_ci case X509_V_ERR_CERT_REVOKED: 764e5b75505Sopenharmony_ci return TLS_FAIL_REVOKED; 765e5b75505Sopenharmony_ci case ASN_BEFORE_DATE_E: 766e5b75505Sopenharmony_ci case X509_V_ERR_CERT_NOT_YET_VALID: 767e5b75505Sopenharmony_ci case X509_V_ERR_CRL_NOT_YET_VALID: 768e5b75505Sopenharmony_ci return TLS_FAIL_NOT_YET_VALID; 769e5b75505Sopenharmony_ci case ASN_AFTER_DATE_E: 770e5b75505Sopenharmony_ci case X509_V_ERR_CERT_HAS_EXPIRED: 771e5b75505Sopenharmony_ci case X509_V_ERR_CRL_HAS_EXPIRED: 772e5b75505Sopenharmony_ci return TLS_FAIL_EXPIRED; 773e5b75505Sopenharmony_ci case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: 774e5b75505Sopenharmony_ci case X509_V_ERR_UNABLE_TO_GET_CRL: 775e5b75505Sopenharmony_ci case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: 776e5b75505Sopenharmony_ci case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: 777e5b75505Sopenharmony_ci case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: 778e5b75505Sopenharmony_ci case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: 779e5b75505Sopenharmony_ci case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: 780e5b75505Sopenharmony_ci case X509_V_ERR_CERT_CHAIN_TOO_LONG: 781e5b75505Sopenharmony_ci case X509_V_ERR_PATH_LENGTH_EXCEEDED: 782e5b75505Sopenharmony_ci case X509_V_ERR_INVALID_CA: 783e5b75505Sopenharmony_ci return TLS_FAIL_UNTRUSTED; 784e5b75505Sopenharmony_ci case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: 785e5b75505Sopenharmony_ci case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: 786e5b75505Sopenharmony_ci case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: 787e5b75505Sopenharmony_ci case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: 788e5b75505Sopenharmony_ci case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: 789e5b75505Sopenharmony_ci case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: 790e5b75505Sopenharmony_ci case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: 791e5b75505Sopenharmony_ci case X509_V_ERR_CERT_UNTRUSTED: 792e5b75505Sopenharmony_ci case X509_V_ERR_CERT_REJECTED: 793e5b75505Sopenharmony_ci return TLS_FAIL_BAD_CERTIFICATE; 794e5b75505Sopenharmony_ci default: 795e5b75505Sopenharmony_ci return TLS_FAIL_UNSPECIFIED; 796e5b75505Sopenharmony_ci } 797e5b75505Sopenharmony_ci} 798e5b75505Sopenharmony_ci 799e5b75505Sopenharmony_ci 800e5b75505Sopenharmony_cistatic const char * wolfssl_tls_err_string(int err, const char *err_str) 801e5b75505Sopenharmony_ci{ 802e5b75505Sopenharmony_ci switch (err) { 803e5b75505Sopenharmony_ci case ASN_BEFORE_DATE_E: 804e5b75505Sopenharmony_ci return "certificate is not yet valid"; 805e5b75505Sopenharmony_ci case ASN_AFTER_DATE_E: 806e5b75505Sopenharmony_ci return "certificate has expired"; 807e5b75505Sopenharmony_ci default: 808e5b75505Sopenharmony_ci return err_str; 809e5b75505Sopenharmony_ci } 810e5b75505Sopenharmony_ci} 811e5b75505Sopenharmony_ci 812e5b75505Sopenharmony_ci 813e5b75505Sopenharmony_cistatic struct wpabuf * get_x509_cert(WOLFSSL_X509 *cert) 814e5b75505Sopenharmony_ci{ 815e5b75505Sopenharmony_ci struct wpabuf *buf = NULL; 816e5b75505Sopenharmony_ci const u8 *data; 817e5b75505Sopenharmony_ci int cert_len; 818e5b75505Sopenharmony_ci 819e5b75505Sopenharmony_ci data = wolfSSL_X509_get_der(cert, &cert_len); 820e5b75505Sopenharmony_ci if (!data) 821e5b75505Sopenharmony_ci buf = wpabuf_alloc_copy(data, cert_len); 822e5b75505Sopenharmony_ci 823e5b75505Sopenharmony_ci return buf; 824e5b75505Sopenharmony_ci} 825e5b75505Sopenharmony_ci 826e5b75505Sopenharmony_ci 827e5b75505Sopenharmony_cistatic void wolfssl_tls_fail_event(struct tls_connection *conn, 828e5b75505Sopenharmony_ci WOLFSSL_X509 *err_cert, int err, int depth, 829e5b75505Sopenharmony_ci const char *subject, const char *err_str, 830e5b75505Sopenharmony_ci enum tls_fail_reason reason) 831e5b75505Sopenharmony_ci{ 832e5b75505Sopenharmony_ci union tls_event_data ev; 833e5b75505Sopenharmony_ci struct wpabuf *cert = NULL; 834e5b75505Sopenharmony_ci struct tls_context *context = conn->context; 835e5b75505Sopenharmony_ci 836e5b75505Sopenharmony_ci if (!context->event_cb) 837e5b75505Sopenharmony_ci return; 838e5b75505Sopenharmony_ci 839e5b75505Sopenharmony_ci cert = get_x509_cert(err_cert); 840e5b75505Sopenharmony_ci os_memset(&ev, 0, sizeof(ev)); 841e5b75505Sopenharmony_ci ev.cert_fail.reason = reason != TLS_FAIL_UNSPECIFIED ? 842e5b75505Sopenharmony_ci reason : wolfssl_tls_fail_reason(err); 843e5b75505Sopenharmony_ci ev.cert_fail.depth = depth; 844e5b75505Sopenharmony_ci ev.cert_fail.subject = subject; 845e5b75505Sopenharmony_ci ev.cert_fail.reason_txt = wolfssl_tls_err_string(err, err_str); 846e5b75505Sopenharmony_ci ev.cert_fail.cert = cert; 847e5b75505Sopenharmony_ci context->event_cb(context->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev); 848e5b75505Sopenharmony_ci wpabuf_free(cert); 849e5b75505Sopenharmony_ci} 850e5b75505Sopenharmony_ci 851e5b75505Sopenharmony_ci 852e5b75505Sopenharmony_cistatic void wolfssl_tls_cert_event(struct tls_connection *conn, 853e5b75505Sopenharmony_ci WOLFSSL_X509 *err_cert, int depth, 854e5b75505Sopenharmony_ci const char *subject) 855e5b75505Sopenharmony_ci{ 856e5b75505Sopenharmony_ci struct wpabuf *cert = NULL; 857e5b75505Sopenharmony_ci union tls_event_data ev; 858e5b75505Sopenharmony_ci struct tls_context *context = conn->context; 859e5b75505Sopenharmony_ci char *alt_subject[TLS_MAX_ALT_SUBJECT]; 860e5b75505Sopenharmony_ci int alt, num_alt_subject = 0; 861e5b75505Sopenharmony_ci WOLFSSL_ASN1_OBJECT *gen; 862e5b75505Sopenharmony_ci void *ext; 863e5b75505Sopenharmony_ci int i; 864e5b75505Sopenharmony_ci#ifdef CONFIG_SHA256 865e5b75505Sopenharmony_ci u8 hash[32]; 866e5b75505Sopenharmony_ci#endif /* CONFIG_SHA256 */ 867e5b75505Sopenharmony_ci 868e5b75505Sopenharmony_ci if (!context->event_cb) 869e5b75505Sopenharmony_ci return; 870e5b75505Sopenharmony_ci 871e5b75505Sopenharmony_ci os_memset(&ev, 0, sizeof(ev)); 872e5b75505Sopenharmony_ci if (conn->cert_probe || (conn->flags & TLS_CONN_EXT_CERT_CHECK) || 873e5b75505Sopenharmony_ci context->cert_in_cb) { 874e5b75505Sopenharmony_ci cert = get_x509_cert(err_cert); 875e5b75505Sopenharmony_ci ev.peer_cert.cert = cert; 876e5b75505Sopenharmony_ci } 877e5b75505Sopenharmony_ci 878e5b75505Sopenharmony_ci#ifdef CONFIG_SHA256 879e5b75505Sopenharmony_ci if (cert) { 880e5b75505Sopenharmony_ci const u8 *addr[1]; 881e5b75505Sopenharmony_ci size_t len[1]; 882e5b75505Sopenharmony_ci 883e5b75505Sopenharmony_ci addr[0] = wpabuf_head(cert); 884e5b75505Sopenharmony_ci len[0] = wpabuf_len(cert); 885e5b75505Sopenharmony_ci if (sha256_vector(1, addr, len, hash) == 0) { 886e5b75505Sopenharmony_ci ev.peer_cert.hash = hash; 887e5b75505Sopenharmony_ci ev.peer_cert.hash_len = sizeof(hash); 888e5b75505Sopenharmony_ci } 889e5b75505Sopenharmony_ci } 890e5b75505Sopenharmony_ci#endif /* CONFIG_SHA256 */ 891e5b75505Sopenharmony_ci 892e5b75505Sopenharmony_ci ev.peer_cert.depth = depth; 893e5b75505Sopenharmony_ci ev.peer_cert.subject = subject; 894e5b75505Sopenharmony_ci 895e5b75505Sopenharmony_ci ext = wolfSSL_X509_get_ext_d2i(err_cert, ALT_NAMES_OID, NULL, NULL); 896e5b75505Sopenharmony_ci for (i = 0; ext && i < wolfSSL_sk_num(ext); i++) { 897e5b75505Sopenharmony_ci char *pos; 898e5b75505Sopenharmony_ci 899e5b75505Sopenharmony_ci if (num_alt_subject == TLS_MAX_ALT_SUBJECT) 900e5b75505Sopenharmony_ci break; 901e5b75505Sopenharmony_ci gen = wolfSSL_sk_value((void *) ext, i); 902e5b75505Sopenharmony_ci if (gen->type != GEN_EMAIL && 903e5b75505Sopenharmony_ci gen->type != GEN_DNS && 904e5b75505Sopenharmony_ci gen->type != GEN_URI) 905e5b75505Sopenharmony_ci continue; 906e5b75505Sopenharmony_ci 907e5b75505Sopenharmony_ci pos = os_malloc(10 + os_strlen((char *) gen->obj) + 1); 908e5b75505Sopenharmony_ci if (!pos) 909e5b75505Sopenharmony_ci break; 910e5b75505Sopenharmony_ci alt_subject[num_alt_subject++] = pos; 911e5b75505Sopenharmony_ci 912e5b75505Sopenharmony_ci switch (gen->type) { 913e5b75505Sopenharmony_ci case GEN_EMAIL: 914e5b75505Sopenharmony_ci os_memcpy(pos, "EMAIL:", 6); 915e5b75505Sopenharmony_ci pos += 6; 916e5b75505Sopenharmony_ci break; 917e5b75505Sopenharmony_ci case GEN_DNS: 918e5b75505Sopenharmony_ci os_memcpy(pos, "DNS:", 4); 919e5b75505Sopenharmony_ci pos += 4; 920e5b75505Sopenharmony_ci break; 921e5b75505Sopenharmony_ci case GEN_URI: 922e5b75505Sopenharmony_ci os_memcpy(pos, "URI:", 4); 923e5b75505Sopenharmony_ci pos += 4; 924e5b75505Sopenharmony_ci break; 925e5b75505Sopenharmony_ci } 926e5b75505Sopenharmony_ci 927e5b75505Sopenharmony_ci os_memcpy(pos, gen->obj, os_strlen((char *)gen->obj)); 928e5b75505Sopenharmony_ci pos += os_strlen((char *)gen->obj); 929e5b75505Sopenharmony_ci *pos = '\0'; 930e5b75505Sopenharmony_ci } 931e5b75505Sopenharmony_ci wolfSSL_sk_ASN1_OBJECT_free(ext); 932e5b75505Sopenharmony_ci 933e5b75505Sopenharmony_ci for (alt = 0; alt < num_alt_subject; alt++) 934e5b75505Sopenharmony_ci ev.peer_cert.altsubject[alt] = alt_subject[alt]; 935e5b75505Sopenharmony_ci ev.peer_cert.num_altsubject = num_alt_subject; 936e5b75505Sopenharmony_ci 937e5b75505Sopenharmony_ci context->event_cb(context->cb_ctx, TLS_PEER_CERTIFICATE, &ev); 938e5b75505Sopenharmony_ci wpabuf_free(cert); 939e5b75505Sopenharmony_ci for (alt = 0; alt < num_alt_subject; alt++) 940e5b75505Sopenharmony_ci os_free(alt_subject[alt]); 941e5b75505Sopenharmony_ci} 942e5b75505Sopenharmony_ci 943e5b75505Sopenharmony_ci 944e5b75505Sopenharmony_cistatic int tls_verify_cb(int preverify_ok, WOLFSSL_X509_STORE_CTX *x509_ctx) 945e5b75505Sopenharmony_ci{ 946e5b75505Sopenharmony_ci char buf[256]; 947e5b75505Sopenharmony_ci WOLFSSL_X509 *err_cert; 948e5b75505Sopenharmony_ci int err, depth; 949e5b75505Sopenharmony_ci WOLFSSL *ssl; 950e5b75505Sopenharmony_ci struct tls_connection *conn; 951e5b75505Sopenharmony_ci struct tls_context *context; 952e5b75505Sopenharmony_ci char *match, *altmatch, *suffix_match, *domain_match; 953e5b75505Sopenharmony_ci const char *err_str; 954e5b75505Sopenharmony_ci 955e5b75505Sopenharmony_ci err_cert = wolfSSL_X509_STORE_CTX_get_current_cert(x509_ctx); 956e5b75505Sopenharmony_ci if (!err_cert) { 957e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "wolfSSL: No Cert"); 958e5b75505Sopenharmony_ci return 0; 959e5b75505Sopenharmony_ci } 960e5b75505Sopenharmony_ci 961e5b75505Sopenharmony_ci err = wolfSSL_X509_STORE_CTX_get_error(x509_ctx); 962e5b75505Sopenharmony_ci depth = wolfSSL_X509_STORE_CTX_get_error_depth(x509_ctx); 963e5b75505Sopenharmony_ci ssl = wolfSSL_X509_STORE_CTX_get_ex_data( 964e5b75505Sopenharmony_ci x509_ctx, wolfSSL_get_ex_data_X509_STORE_CTX_idx()); 965e5b75505Sopenharmony_ci wolfSSL_X509_NAME_oneline(wolfSSL_X509_get_subject_name(err_cert), buf, 966e5b75505Sopenharmony_ci sizeof(buf)); 967e5b75505Sopenharmony_ci 968e5b75505Sopenharmony_ci conn = wolfSSL_get_ex_data(ssl, 0); 969e5b75505Sopenharmony_ci if (!conn) { 970e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "wolfSSL: No ex_data"); 971e5b75505Sopenharmony_ci return 0; 972e5b75505Sopenharmony_ci } 973e5b75505Sopenharmony_ci 974e5b75505Sopenharmony_ci if (depth == 0) 975e5b75505Sopenharmony_ci conn->peer_cert = err_cert; 976e5b75505Sopenharmony_ci else if (depth == 1) 977e5b75505Sopenharmony_ci conn->peer_issuer = err_cert; 978e5b75505Sopenharmony_ci else if (depth == 2) 979e5b75505Sopenharmony_ci conn->peer_issuer_issuer = err_cert; 980e5b75505Sopenharmony_ci 981e5b75505Sopenharmony_ci context = conn->context; 982e5b75505Sopenharmony_ci match = conn->subject_match; 983e5b75505Sopenharmony_ci altmatch = conn->alt_subject_match; 984e5b75505Sopenharmony_ci suffix_match = conn->suffix_match; 985e5b75505Sopenharmony_ci domain_match = conn->domain_match; 986e5b75505Sopenharmony_ci 987e5b75505Sopenharmony_ci if (!preverify_ok && !conn->ca_cert_verify) 988e5b75505Sopenharmony_ci preverify_ok = 1; 989e5b75505Sopenharmony_ci if (!preverify_ok && depth > 0 && conn->server_cert_only) 990e5b75505Sopenharmony_ci preverify_ok = 1; 991e5b75505Sopenharmony_ci if (!preverify_ok && (conn->flags & TLS_CONN_DISABLE_TIME_CHECKS) && 992e5b75505Sopenharmony_ci (err == X509_V_ERR_CERT_HAS_EXPIRED || 993e5b75505Sopenharmony_ci err == ASN_AFTER_DATE_E || err == ASN_BEFORE_DATE_E || 994e5b75505Sopenharmony_ci err == X509_V_ERR_CERT_NOT_YET_VALID)) { 995e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 996e5b75505Sopenharmony_ci "wolfSSL: Ignore certificate validity time mismatch"); 997e5b75505Sopenharmony_ci preverify_ok = 1; 998e5b75505Sopenharmony_ci } 999e5b75505Sopenharmony_ci 1000e5b75505Sopenharmony_ci err_str = wolfSSL_X509_verify_cert_error_string(err); 1001e5b75505Sopenharmony_ci 1002e5b75505Sopenharmony_ci#ifdef CONFIG_SHA256 1003e5b75505Sopenharmony_ci /* 1004e5b75505Sopenharmony_ci * Do not require preverify_ok so we can explicity allow otherwise 1005e5b75505Sopenharmony_ci * invalid pinned server certificates. 1006e5b75505Sopenharmony_ci */ 1007e5b75505Sopenharmony_ci if (depth == 0 && conn->server_cert_only) { 1008e5b75505Sopenharmony_ci struct wpabuf *cert; 1009e5b75505Sopenharmony_ci 1010e5b75505Sopenharmony_ci cert = get_x509_cert(err_cert); 1011e5b75505Sopenharmony_ci if (!cert) { 1012e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1013e5b75505Sopenharmony_ci "wolfSSL: Could not fetch server certificate data"); 1014e5b75505Sopenharmony_ci preverify_ok = 0; 1015e5b75505Sopenharmony_ci } else { 1016e5b75505Sopenharmony_ci u8 hash[32]; 1017e5b75505Sopenharmony_ci const u8 *addr[1]; 1018e5b75505Sopenharmony_ci size_t len[1]; 1019e5b75505Sopenharmony_ci 1020e5b75505Sopenharmony_ci addr[0] = wpabuf_head(cert); 1021e5b75505Sopenharmony_ci len[0] = wpabuf_len(cert); 1022e5b75505Sopenharmony_ci if (sha256_vector(1, addr, len, hash) < 0 || 1023e5b75505Sopenharmony_ci os_memcmp(conn->srv_cert_hash, hash, 32) != 0) { 1024e5b75505Sopenharmony_ci err_str = "Server certificate mismatch"; 1025e5b75505Sopenharmony_ci err = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN; 1026e5b75505Sopenharmony_ci preverify_ok = 0; 1027e5b75505Sopenharmony_ci } else if (!preverify_ok) { 1028e5b75505Sopenharmony_ci /* 1029e5b75505Sopenharmony_ci * Certificate matches pinned certificate, allow 1030e5b75505Sopenharmony_ci * regardless of other problems. 1031e5b75505Sopenharmony_ci */ 1032e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1033e5b75505Sopenharmony_ci "wolfSSL: Ignore validation issues for a pinned server certificate"); 1034e5b75505Sopenharmony_ci preverify_ok = 1; 1035e5b75505Sopenharmony_ci } 1036e5b75505Sopenharmony_ci wpabuf_free(cert); 1037e5b75505Sopenharmony_ci } 1038e5b75505Sopenharmony_ci } 1039e5b75505Sopenharmony_ci#endif /* CONFIG_SHA256 */ 1040e5b75505Sopenharmony_ci 1041e5b75505Sopenharmony_ci if (!preverify_ok) { 1042e5b75505Sopenharmony_ci wpa_printf(MSG_WARNING, 1043e5b75505Sopenharmony_ci "TLS: Certificate verification failed, error %d (%s) depth %d for '%s'", 1044e5b75505Sopenharmony_ci err, err_str, depth, buf); 1045e5b75505Sopenharmony_ci wolfssl_tls_fail_event(conn, err_cert, err, depth, buf, 1046e5b75505Sopenharmony_ci err_str, TLS_FAIL_UNSPECIFIED); 1047e5b75505Sopenharmony_ci return preverify_ok; 1048e5b75505Sopenharmony_ci } 1049e5b75505Sopenharmony_ci 1050e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1051e5b75505Sopenharmony_ci "TLS: %s - preverify_ok=%d err=%d (%s) ca_cert_verify=%d depth=%d buf='%s'", 1052e5b75505Sopenharmony_ci __func__, preverify_ok, err, err_str, 1053e5b75505Sopenharmony_ci conn->ca_cert_verify, depth, buf); 1054e5b75505Sopenharmony_ci if (depth == 0 && match && os_strstr(buf, match) == NULL) { 1055e5b75505Sopenharmony_ci wpa_printf(MSG_WARNING, 1056e5b75505Sopenharmony_ci "TLS: Subject '%s' did not match with '%s'", 1057e5b75505Sopenharmony_ci buf, match); 1058e5b75505Sopenharmony_ci preverify_ok = 0; 1059e5b75505Sopenharmony_ci wolfssl_tls_fail_event(conn, err_cert, err, depth, buf, 1060e5b75505Sopenharmony_ci "Subject mismatch", 1061e5b75505Sopenharmony_ci TLS_FAIL_SUBJECT_MISMATCH); 1062e5b75505Sopenharmony_ci } else if (depth == 0 && altmatch && 1063e5b75505Sopenharmony_ci !tls_match_alt_subject(err_cert, altmatch)) { 1064e5b75505Sopenharmony_ci wpa_printf(MSG_WARNING, 1065e5b75505Sopenharmony_ci "TLS: altSubjectName match '%s' not found", 1066e5b75505Sopenharmony_ci altmatch); 1067e5b75505Sopenharmony_ci preverify_ok = 0; 1068e5b75505Sopenharmony_ci wolfssl_tls_fail_event(conn, err_cert, err, depth, buf, 1069e5b75505Sopenharmony_ci "AltSubject mismatch", 1070e5b75505Sopenharmony_ci TLS_FAIL_ALTSUBJECT_MISMATCH); 1071e5b75505Sopenharmony_ci } else if (depth == 0 && suffix_match && 1072e5b75505Sopenharmony_ci !tls_match_suffix(err_cert, suffix_match, 0)) { 1073e5b75505Sopenharmony_ci wpa_printf(MSG_WARNING, 1074e5b75505Sopenharmony_ci "TLS: Domain suffix match '%s' not found", 1075e5b75505Sopenharmony_ci suffix_match); 1076e5b75505Sopenharmony_ci preverify_ok = 0; 1077e5b75505Sopenharmony_ci wolfssl_tls_fail_event(conn, err_cert, err, depth, buf, 1078e5b75505Sopenharmony_ci "Domain suffix mismatch", 1079e5b75505Sopenharmony_ci TLS_FAIL_DOMAIN_SUFFIX_MISMATCH); 1080e5b75505Sopenharmony_ci } else if (depth == 0 && domain_match && 1081e5b75505Sopenharmony_ci !tls_match_suffix(err_cert, domain_match, 1)) { 1082e5b75505Sopenharmony_ci wpa_printf(MSG_WARNING, "TLS: Domain match '%s' not found", 1083e5b75505Sopenharmony_ci domain_match); 1084e5b75505Sopenharmony_ci preverify_ok = 0; 1085e5b75505Sopenharmony_ci wolfssl_tls_fail_event(conn, err_cert, err, depth, buf, 1086e5b75505Sopenharmony_ci "Domain mismatch", 1087e5b75505Sopenharmony_ci TLS_FAIL_DOMAIN_MISMATCH); 1088e5b75505Sopenharmony_ci } else { 1089e5b75505Sopenharmony_ci wolfssl_tls_cert_event(conn, err_cert, depth, buf); 1090e5b75505Sopenharmony_ci } 1091e5b75505Sopenharmony_ci 1092e5b75505Sopenharmony_ci if (conn->cert_probe && preverify_ok && depth == 0) { 1093e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1094e5b75505Sopenharmony_ci "wolfSSL: Reject server certificate on probe-only run"); 1095e5b75505Sopenharmony_ci preverify_ok = 0; 1096e5b75505Sopenharmony_ci wolfssl_tls_fail_event(conn, err_cert, err, depth, buf, 1097e5b75505Sopenharmony_ci "Server certificate chain probe", 1098e5b75505Sopenharmony_ci TLS_FAIL_SERVER_CHAIN_PROBE); 1099e5b75505Sopenharmony_ci } 1100e5b75505Sopenharmony_ci 1101e5b75505Sopenharmony_ci#ifdef HAVE_OCSP_WOLFSSL 1102e5b75505Sopenharmony_ci if (depth == 0 && (conn->flags & TLS_CONN_REQUEST_OCSP) && 1103e5b75505Sopenharmony_ci preverify_ok) { 1104e5b75505Sopenharmony_ci enum ocsp_result res; 1105e5b75505Sopenharmony_ci 1106e5b75505Sopenharmony_ci res = check_ocsp_resp(conn->ssl_ctx, conn->ssl, err_cert, 1107e5b75505Sopenharmony_ci conn->peer_issuer, 1108e5b75505Sopenharmony_ci conn->peer_issuer_issuer); 1109e5b75505Sopenharmony_ci if (res == OCSP_REVOKED) { 1110e5b75505Sopenharmony_ci preverify_ok = 0; 1111e5b75505Sopenharmony_ci wolfssl_tls_fail_event(conn, err_cert, err, depth, buf, 1112e5b75505Sopenharmony_ci "certificate revoked", 1113e5b75505Sopenharmony_ci TLS_FAIL_REVOKED); 1114e5b75505Sopenharmony_ci if (err == X509_V_OK) 1115e5b75505Sopenharmony_ci X509_STORE_CTX_set_error( 1116e5b75505Sopenharmony_ci x509_ctx, X509_V_ERR_CERT_REVOKED); 1117e5b75505Sopenharmony_ci } else if (res != OCSP_GOOD && 1118e5b75505Sopenharmony_ci (conn->flags & TLS_CONN_REQUIRE_OCSP)) { 1119e5b75505Sopenharmony_ci preverify_ok = 0; 1120e5b75505Sopenharmony_ci wolfssl_tls_fail_event(conn, err_cert, err, depth, buf, 1121e5b75505Sopenharmony_ci "bad certificate status response", 1122e5b75505Sopenharmony_ci TLS_FAIL_UNSPECIFIED); 1123e5b75505Sopenharmony_ci } 1124e5b75505Sopenharmony_ci } 1125e5b75505Sopenharmony_ci#endif /* HAVE_OCSP_WOLFSSL */ 1126e5b75505Sopenharmony_ci if (depth == 0 && preverify_ok && context->event_cb != NULL) 1127e5b75505Sopenharmony_ci context->event_cb(context->cb_ctx, 1128e5b75505Sopenharmony_ci TLS_CERT_CHAIN_SUCCESS, NULL); 1129e5b75505Sopenharmony_ci 1130e5b75505Sopenharmony_ci return preverify_ok; 1131e5b75505Sopenharmony_ci} 1132e5b75505Sopenharmony_ci 1133e5b75505Sopenharmony_ci 1134e5b75505Sopenharmony_cistatic int tls_connection_ca_cert(void *tls_ctx, struct tls_connection *conn, 1135e5b75505Sopenharmony_ci const char *ca_cert, 1136e5b75505Sopenharmony_ci const u8 *ca_cert_blob, size_t blob_len, 1137e5b75505Sopenharmony_ci const char *ca_path) 1138e5b75505Sopenharmony_ci{ 1139e5b75505Sopenharmony_ci WOLFSSL_CTX *ctx = tls_ctx; 1140e5b75505Sopenharmony_ci 1141e5b75505Sopenharmony_ci wolfSSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); 1142e5b75505Sopenharmony_ci conn->ca_cert_verify = 1; 1143e5b75505Sopenharmony_ci 1144e5b75505Sopenharmony_ci if (ca_cert && os_strncmp(ca_cert, "probe://", 8) == 0) { 1145e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1146e5b75505Sopenharmony_ci "wolfSSL: Probe for server certificate chain"); 1147e5b75505Sopenharmony_ci conn->cert_probe = 1; 1148e5b75505Sopenharmony_ci conn->ca_cert_verify = 0; 1149e5b75505Sopenharmony_ci return 0; 1150e5b75505Sopenharmony_ci } 1151e5b75505Sopenharmony_ci 1152e5b75505Sopenharmony_ci if (ca_cert && os_strncmp(ca_cert, "hash://", 7) == 0) { 1153e5b75505Sopenharmony_ci#ifdef CONFIG_SHA256 1154e5b75505Sopenharmony_ci const char *pos = ca_cert + 7; 1155e5b75505Sopenharmony_ci 1156e5b75505Sopenharmony_ci if (os_strncmp(pos, "server/sha256/", 14) != 0) { 1157e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1158e5b75505Sopenharmony_ci "wolfSSL: Unsupported ca_cert hash value '%s'", 1159e5b75505Sopenharmony_ci ca_cert); 1160e5b75505Sopenharmony_ci return -1; 1161e5b75505Sopenharmony_ci } 1162e5b75505Sopenharmony_ci pos += 14; 1163e5b75505Sopenharmony_ci if (os_strlen(pos) != 32 * 2) { 1164e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1165e5b75505Sopenharmony_ci "wolfSSL: Unexpected SHA256 hash length in ca_cert '%s'", 1166e5b75505Sopenharmony_ci ca_cert); 1167e5b75505Sopenharmony_ci return -1; 1168e5b75505Sopenharmony_ci } 1169e5b75505Sopenharmony_ci if (hexstr2bin(pos, conn->srv_cert_hash, 32) < 0) { 1170e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1171e5b75505Sopenharmony_ci "wolfSSL: Invalid SHA256 hash value in ca_cert '%s'", 1172e5b75505Sopenharmony_ci ca_cert); 1173e5b75505Sopenharmony_ci return -1; 1174e5b75505Sopenharmony_ci } 1175e5b75505Sopenharmony_ci conn->server_cert_only = 1; 1176e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1177e5b75505Sopenharmony_ci "wolfSSL: Checking only server certificate match"); 1178e5b75505Sopenharmony_ci return 0; 1179e5b75505Sopenharmony_ci#else /* CONFIG_SHA256 */ 1180e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 1181e5b75505Sopenharmony_ci "No SHA256 included in the build - cannot validate server certificate hash"); 1182e5b75505Sopenharmony_ci return -1; 1183e5b75505Sopenharmony_ci#endif /* CONFIG_SHA256 */ 1184e5b75505Sopenharmony_ci } 1185e5b75505Sopenharmony_ci 1186e5b75505Sopenharmony_ci if (ca_cert_blob) { 1187e5b75505Sopenharmony_ci if (wolfSSL_CTX_load_verify_buffer(ctx, ca_cert_blob, blob_len, 1188e5b75505Sopenharmony_ci SSL_FILETYPE_ASN1) != 1189e5b75505Sopenharmony_ci SSL_SUCCESS) { 1190e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "SSL: failed to load CA blob"); 1191e5b75505Sopenharmony_ci return -1; 1192e5b75505Sopenharmony_ci } 1193e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: use CA cert blob OK"); 1194e5b75505Sopenharmony_ci return 0; 1195e5b75505Sopenharmony_ci } 1196e5b75505Sopenharmony_ci 1197e5b75505Sopenharmony_ci if (ca_cert || ca_path) { 1198e5b75505Sopenharmony_ci WOLFSSL_X509_STORE *cm = wolfSSL_X509_STORE_new(); 1199e5b75505Sopenharmony_ci 1200e5b75505Sopenharmony_ci if (!cm) { 1201e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 1202e5b75505Sopenharmony_ci "SSL: failed to create certificate store"); 1203e5b75505Sopenharmony_ci return -1; 1204e5b75505Sopenharmony_ci } 1205e5b75505Sopenharmony_ci wolfSSL_CTX_set_cert_store(ctx, cm); 1206e5b75505Sopenharmony_ci 1207e5b75505Sopenharmony_ci if (wolfSSL_CTX_load_verify_locations(ctx, ca_cert, ca_path) != 1208e5b75505Sopenharmony_ci SSL_SUCCESS) { 1209e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 1210e5b75505Sopenharmony_ci "SSL: failed to load ca_cert as PEM"); 1211e5b75505Sopenharmony_ci 1212e5b75505Sopenharmony_ci if (!ca_cert) 1213e5b75505Sopenharmony_ci return -1; 1214e5b75505Sopenharmony_ci 1215e5b75505Sopenharmony_ci if (wolfSSL_CTX_der_load_verify_locations( 1216e5b75505Sopenharmony_ci ctx, ca_cert, SSL_FILETYPE_ASN1) != 1217e5b75505Sopenharmony_ci SSL_SUCCESS) { 1218e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 1219e5b75505Sopenharmony_ci "SSL: failed to load ca_cert as DER"); 1220e5b75505Sopenharmony_ci return -1; 1221e5b75505Sopenharmony_ci } 1222e5b75505Sopenharmony_ci } 1223e5b75505Sopenharmony_ci return 0; 1224e5b75505Sopenharmony_ci } 1225e5b75505Sopenharmony_ci 1226e5b75505Sopenharmony_ci conn->ca_cert_verify = 0; 1227e5b75505Sopenharmony_ci return 0; 1228e5b75505Sopenharmony_ci} 1229e5b75505Sopenharmony_ci 1230e5b75505Sopenharmony_ci 1231e5b75505Sopenharmony_cistatic void tls_set_conn_flags(WOLFSSL *ssl, unsigned int flags) 1232e5b75505Sopenharmony_ci{ 1233e5b75505Sopenharmony_ci#ifdef HAVE_SESSION_TICKET 1234e5b75505Sopenharmony_ci#if 0 1235e5b75505Sopenharmony_ci if (!(flags & TLS_CONN_DISABLE_SESSION_TICKET)) 1236e5b75505Sopenharmony_ci wolfSSL_UseSessionTicket(ssl); 1237e5b75505Sopenharmony_ci#endif 1238e5b75505Sopenharmony_ci#endif /* HAVE_SESSION_TICKET */ 1239e5b75505Sopenharmony_ci 1240e5b75505Sopenharmony_ci if (flags & TLS_CONN_DISABLE_TLSv1_0) 1241e5b75505Sopenharmony_ci wolfSSL_set_options(ssl, SSL_OP_NO_TLSv1); 1242e5b75505Sopenharmony_ci if (flags & TLS_CONN_DISABLE_TLSv1_1) 1243e5b75505Sopenharmony_ci wolfSSL_set_options(ssl, SSL_OP_NO_TLSv1_1); 1244e5b75505Sopenharmony_ci if (flags & TLS_CONN_DISABLE_TLSv1_2) 1245e5b75505Sopenharmony_ci wolfSSL_set_options(ssl, SSL_OP_NO_TLSv1_2); 1246e5b75505Sopenharmony_ci} 1247e5b75505Sopenharmony_ci 1248e5b75505Sopenharmony_ci 1249e5b75505Sopenharmony_ciint tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, 1250e5b75505Sopenharmony_ci const struct tls_connection_params *params) 1251e5b75505Sopenharmony_ci{ 1252e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: set params"); 1253e5b75505Sopenharmony_ci 1254e5b75505Sopenharmony_ci if (tls_connection_set_subject_match(conn, params->subject_match, 1255e5b75505Sopenharmony_ci params->altsubject_match, 1256e5b75505Sopenharmony_ci params->suffix_match, 1257e5b75505Sopenharmony_ci params->domain_match) < 0) { 1258e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "Error setting subject match"); 1259e5b75505Sopenharmony_ci return -1; 1260e5b75505Sopenharmony_ci } 1261e5b75505Sopenharmony_ci 1262e5b75505Sopenharmony_ci if (tls_connection_ca_cert(tls_ctx, conn, params->ca_cert, 1263e5b75505Sopenharmony_ci params->ca_cert_blob, 1264e5b75505Sopenharmony_ci params->ca_cert_blob_len, 1265e5b75505Sopenharmony_ci params->ca_path) < 0) { 1266e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "Error setting CA cert"); 1267e5b75505Sopenharmony_ci return -1; 1268e5b75505Sopenharmony_ci } 1269e5b75505Sopenharmony_ci 1270e5b75505Sopenharmony_ci if (tls_connection_client_cert(conn, params->client_cert, 1271e5b75505Sopenharmony_ci params->client_cert_blob, 1272e5b75505Sopenharmony_ci params->client_cert_blob_len) < 0) { 1273e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "Error setting client cert"); 1274e5b75505Sopenharmony_ci return -1; 1275e5b75505Sopenharmony_ci } 1276e5b75505Sopenharmony_ci 1277e5b75505Sopenharmony_ci if (tls_connection_private_key(tls_ctx, conn, params->private_key, 1278e5b75505Sopenharmony_ci params->private_key_passwd, 1279e5b75505Sopenharmony_ci params->private_key_blob, 1280e5b75505Sopenharmony_ci params->private_key_blob_len) < 0) { 1281e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "Error setting private key"); 1282e5b75505Sopenharmony_ci return -1; 1283e5b75505Sopenharmony_ci } 1284e5b75505Sopenharmony_ci 1285e5b75505Sopenharmony_ci if (tls_connection_dh(conn, params->dh_file, params->dh_blob, 1286e5b75505Sopenharmony_ci params->dh_blob_len) < 0) { 1287e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "Error setting DH"); 1288e5b75505Sopenharmony_ci return -1; 1289e5b75505Sopenharmony_ci } 1290e5b75505Sopenharmony_ci 1291e5b75505Sopenharmony_ci if (params->openssl_ciphers && 1292e5b75505Sopenharmony_ci wolfSSL_set_cipher_list(conn->ssl, params->openssl_ciphers) != 1) { 1293e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 1294e5b75505Sopenharmony_ci "wolfSSL: Failed to set cipher string '%s'", 1295e5b75505Sopenharmony_ci params->openssl_ciphers); 1296e5b75505Sopenharmony_ci return -1; 1297e5b75505Sopenharmony_ci } 1298e5b75505Sopenharmony_ci 1299e5b75505Sopenharmony_ci tls_set_conn_flags(conn->ssl, params->flags); 1300e5b75505Sopenharmony_ci 1301e5b75505Sopenharmony_ci#ifdef HAVE_CERTIFICATE_STATUS_REQUEST 1302e5b75505Sopenharmony_ci if (params->flags & TLS_CONN_REQUEST_OCSP) { 1303e5b75505Sopenharmony_ci if (wolfSSL_UseOCSPStapling(conn->ssl, WOLFSSL_CSR_OCSP, 1304e5b75505Sopenharmony_ci WOLFSSL_CSR_OCSP_USE_NONCE) != 1305e5b75505Sopenharmony_ci SSL_SUCCESS) 1306e5b75505Sopenharmony_ci return -1; 1307e5b75505Sopenharmony_ci wolfSSL_CTX_EnableOCSP(tls_ctx, 0); 1308e5b75505Sopenharmony_ci } 1309e5b75505Sopenharmony_ci#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ 1310e5b75505Sopenharmony_ci#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 1311e5b75505Sopenharmony_ci if (params->flags & TLS_CONN_REQUEST_OCSP) { 1312e5b75505Sopenharmony_ci if (wolfSSL_UseOCSPStaplingV2(conn->ssl, 1313e5b75505Sopenharmony_ci WOLFSSL_CSR2_OCSP_MULTI, 0) != 1314e5b75505Sopenharmony_ci SSL_SUCCESS) 1315e5b75505Sopenharmony_ci return -1; 1316e5b75505Sopenharmony_ci wolfSSL_CTX_EnableOCSP(tls_ctx, 0); 1317e5b75505Sopenharmony_ci } 1318e5b75505Sopenharmony_ci#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ 1319e5b75505Sopenharmony_ci#if !defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \ 1320e5b75505Sopenharmony_ci !defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) 1321e5b75505Sopenharmony_ci#ifdef HAVE_OCSP 1322e5b75505Sopenharmony_ci if (params->flags & TLS_CONN_REQUEST_OCSP) 1323e5b75505Sopenharmony_ci wolfSSL_CTX_EnableOCSP(ctx, 0); 1324e5b75505Sopenharmony_ci#else /* HAVE_OCSP */ 1325e5b75505Sopenharmony_ci if (params->flags & TLS_CONN_REQUIRE_OCSP) { 1326e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 1327e5b75505Sopenharmony_ci "wolfSSL: No OCSP support included - reject configuration"); 1328e5b75505Sopenharmony_ci return -1; 1329e5b75505Sopenharmony_ci } 1330e5b75505Sopenharmony_ci if (params->flags & TLS_CONN_REQUEST_OCSP) { 1331e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1332e5b75505Sopenharmony_ci "wolfSSL: No OCSP support included - allow optional OCSP case to continue"); 1333e5b75505Sopenharmony_ci } 1334e5b75505Sopenharmony_ci#endif /* HAVE_OCSP */ 1335e5b75505Sopenharmony_ci#endif /* !HAVE_CERTIFICATE_STATUS_REQUEST && 1336e5b75505Sopenharmony_ci * !HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ 1337e5b75505Sopenharmony_ci 1338e5b75505Sopenharmony_ci conn->flags = params->flags; 1339e5b75505Sopenharmony_ci 1340e5b75505Sopenharmony_ci return 0; 1341e5b75505Sopenharmony_ci} 1342e5b75505Sopenharmony_ci 1343e5b75505Sopenharmony_ci 1344e5b75505Sopenharmony_cistatic int tls_global_ca_cert(void *ssl_ctx, const char *ca_cert) 1345e5b75505Sopenharmony_ci{ 1346e5b75505Sopenharmony_ci WOLFSSL_CTX *ctx = ssl_ctx; 1347e5b75505Sopenharmony_ci 1348e5b75505Sopenharmony_ci if (ca_cert) { 1349e5b75505Sopenharmony_ci if (wolfSSL_CTX_load_verify_locations(ctx, ca_cert, NULL) != 1) 1350e5b75505Sopenharmony_ci { 1351e5b75505Sopenharmony_ci wpa_printf(MSG_WARNING, 1352e5b75505Sopenharmony_ci "Failed to load root certificates"); 1353e5b75505Sopenharmony_ci return -1; 1354e5b75505Sopenharmony_ci } 1355e5b75505Sopenharmony_ci 1356e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1357e5b75505Sopenharmony_ci "TLS: Trusted root certificate(s) loaded"); 1358e5b75505Sopenharmony_ci } 1359e5b75505Sopenharmony_ci 1360e5b75505Sopenharmony_ci return 0; 1361e5b75505Sopenharmony_ci} 1362e5b75505Sopenharmony_ci 1363e5b75505Sopenharmony_ci 1364e5b75505Sopenharmony_cistatic int tls_global_client_cert(void *ssl_ctx, const char *client_cert) 1365e5b75505Sopenharmony_ci{ 1366e5b75505Sopenharmony_ci WOLFSSL_CTX *ctx = ssl_ctx; 1367e5b75505Sopenharmony_ci 1368e5b75505Sopenharmony_ci if (!client_cert) 1369e5b75505Sopenharmony_ci return 0; 1370e5b75505Sopenharmony_ci 1371e5b75505Sopenharmony_ci if (wolfSSL_CTX_use_certificate_chain_file_format(ctx, client_cert, 1372e5b75505Sopenharmony_ci SSL_FILETYPE_ASN1) != 1373e5b75505Sopenharmony_ci SSL_SUCCESS && 1374e5b75505Sopenharmony_ci wolfSSL_CTX_use_certificate_chain_file(ctx, client_cert) != 1375e5b75505Sopenharmony_ci SSL_SUCCESS) { 1376e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "Failed to load client certificate"); 1377e5b75505Sopenharmony_ci return -1; 1378e5b75505Sopenharmony_ci } 1379e5b75505Sopenharmony_ci 1380e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: Loaded global client certificate: %s", 1381e5b75505Sopenharmony_ci client_cert); 1382e5b75505Sopenharmony_ci 1383e5b75505Sopenharmony_ci return 0; 1384e5b75505Sopenharmony_ci} 1385e5b75505Sopenharmony_ci 1386e5b75505Sopenharmony_ci 1387e5b75505Sopenharmony_cistatic int tls_global_private_key(void *ssl_ctx, const char *private_key, 1388e5b75505Sopenharmony_ci const char *private_key_passwd) 1389e5b75505Sopenharmony_ci{ 1390e5b75505Sopenharmony_ci WOLFSSL_CTX *ctx = ssl_ctx; 1391e5b75505Sopenharmony_ci char *passwd = NULL; 1392e5b75505Sopenharmony_ci int ret = 0; 1393e5b75505Sopenharmony_ci 1394e5b75505Sopenharmony_ci if (!private_key) 1395e5b75505Sopenharmony_ci return 0; 1396e5b75505Sopenharmony_ci 1397e5b75505Sopenharmony_ci if (private_key_passwd) { 1398e5b75505Sopenharmony_ci passwd = os_strdup(private_key_passwd); 1399e5b75505Sopenharmony_ci if (!passwd) 1400e5b75505Sopenharmony_ci return -1; 1401e5b75505Sopenharmony_ci } 1402e5b75505Sopenharmony_ci 1403e5b75505Sopenharmony_ci wolfSSL_CTX_set_default_passwd_cb(ctx, tls_passwd_cb); 1404e5b75505Sopenharmony_ci wolfSSL_CTX_set_default_passwd_cb_userdata(ctx, passwd); 1405e5b75505Sopenharmony_ci 1406e5b75505Sopenharmony_ci if (wolfSSL_CTX_use_PrivateKey_file(ctx, private_key, 1407e5b75505Sopenharmony_ci SSL_FILETYPE_ASN1) != 1 && 1408e5b75505Sopenharmony_ci wolfSSL_CTX_use_PrivateKey_file(ctx, private_key, 1409e5b75505Sopenharmony_ci SSL_FILETYPE_PEM) != 1) { 1410e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "Failed to load private key"); 1411e5b75505Sopenharmony_ci ret = -1; 1412e5b75505Sopenharmony_ci } 1413e5b75505Sopenharmony_ci 1414e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: Loaded global private key"); 1415e5b75505Sopenharmony_ci 1416e5b75505Sopenharmony_ci os_free(passwd); 1417e5b75505Sopenharmony_ci wolfSSL_CTX_set_default_passwd_cb(ctx, NULL); 1418e5b75505Sopenharmony_ci 1419e5b75505Sopenharmony_ci return ret; 1420e5b75505Sopenharmony_ci} 1421e5b75505Sopenharmony_ci 1422e5b75505Sopenharmony_ci 1423e5b75505Sopenharmony_cistatic int tls_global_dh(void *ssl_ctx, const char *dh_file, 1424e5b75505Sopenharmony_ci const u8 *dh_blob, size_t blob_len) 1425e5b75505Sopenharmony_ci{ 1426e5b75505Sopenharmony_ci WOLFSSL_CTX *ctx = ssl_ctx; 1427e5b75505Sopenharmony_ci 1428e5b75505Sopenharmony_ci if (!dh_file && !dh_blob) 1429e5b75505Sopenharmony_ci return 0; 1430e5b75505Sopenharmony_ci 1431e5b75505Sopenharmony_ci if (dh_blob) { 1432e5b75505Sopenharmony_ci if (wolfSSL_CTX_SetTmpDH_buffer(ctx, dh_blob, blob_len, 1433e5b75505Sopenharmony_ci SSL_FILETYPE_ASN1) < 0) { 1434e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 1435e5b75505Sopenharmony_ci "SSL: global use DH DER blob failed"); 1436e5b75505Sopenharmony_ci return -1; 1437e5b75505Sopenharmony_ci } 1438e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: global use DH blob OK"); 1439e5b75505Sopenharmony_ci return 0; 1440e5b75505Sopenharmony_ci } 1441e5b75505Sopenharmony_ci 1442e5b75505Sopenharmony_ci if (dh_file) { 1443e5b75505Sopenharmony_ci if (wolfSSL_CTX_SetTmpDH_file(ctx, dh_file, SSL_FILETYPE_PEM) < 1444e5b75505Sopenharmony_ci 0) { 1445e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 1446e5b75505Sopenharmony_ci "SSL: global use DH PEM file failed"); 1447e5b75505Sopenharmony_ci if (wolfSSL_CTX_SetTmpDH_file(ctx, dh_file, 1448e5b75505Sopenharmony_ci SSL_FILETYPE_ASN1) < 0) { 1449e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 1450e5b75505Sopenharmony_ci "SSL: global use DH DER file failed"); 1451e5b75505Sopenharmony_ci return -1; 1452e5b75505Sopenharmony_ci } 1453e5b75505Sopenharmony_ci } 1454e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: global use DH file OK"); 1455e5b75505Sopenharmony_ci return 0; 1456e5b75505Sopenharmony_ci } 1457e5b75505Sopenharmony_ci 1458e5b75505Sopenharmony_ci return 0; 1459e5b75505Sopenharmony_ci} 1460e5b75505Sopenharmony_ci 1461e5b75505Sopenharmony_ci 1462e5b75505Sopenharmony_ci#ifdef HAVE_OCSP 1463e5b75505Sopenharmony_ci 1464e5b75505Sopenharmony_ciint ocsp_status_cb(void *unused, const char *url, int url_sz, 1465e5b75505Sopenharmony_ci unsigned char *request, int request_sz, 1466e5b75505Sopenharmony_ci unsigned char **response) 1467e5b75505Sopenharmony_ci{ 1468e5b75505Sopenharmony_ci size_t len; 1469e5b75505Sopenharmony_ci 1470e5b75505Sopenharmony_ci (void) unused; 1471e5b75505Sopenharmony_ci 1472e5b75505Sopenharmony_ci if (!url) { 1473e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1474e5b75505Sopenharmony_ci "wolfSSL: OCSP status callback - no response configured"); 1475e5b75505Sopenharmony_ci *response = NULL; 1476e5b75505Sopenharmony_ci return 0; 1477e5b75505Sopenharmony_ci } 1478e5b75505Sopenharmony_ci 1479e5b75505Sopenharmony_ci *response = (unsigned char *) os_readfile(url, &len); 1480e5b75505Sopenharmony_ci if (!*response) { 1481e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1482e5b75505Sopenharmony_ci "wolfSSL: OCSP status callback - could not read response file"); 1483e5b75505Sopenharmony_ci return -1; 1484e5b75505Sopenharmony_ci } 1485e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1486e5b75505Sopenharmony_ci "wolfSSL: OCSP status callback - send cached response"); 1487e5b75505Sopenharmony_ci return len; 1488e5b75505Sopenharmony_ci} 1489e5b75505Sopenharmony_ci 1490e5b75505Sopenharmony_ci 1491e5b75505Sopenharmony_civoid ocsp_resp_free_cb(void *ocsp_stapling_response, unsigned char *response) 1492e5b75505Sopenharmony_ci{ 1493e5b75505Sopenharmony_ci os_free(response); 1494e5b75505Sopenharmony_ci} 1495e5b75505Sopenharmony_ci 1496e5b75505Sopenharmony_ci#endif /* HAVE_OCSP */ 1497e5b75505Sopenharmony_ci 1498e5b75505Sopenharmony_ci 1499e5b75505Sopenharmony_ciint tls_global_set_params(void *tls_ctx, 1500e5b75505Sopenharmony_ci const struct tls_connection_params *params) 1501e5b75505Sopenharmony_ci{ 1502e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: global set params"); 1503e5b75505Sopenharmony_ci 1504e5b75505Sopenharmony_ci if (params->check_cert_subject) 1505e5b75505Sopenharmony_ci return -1; /* not yet supported */ 1506e5b75505Sopenharmony_ci 1507e5b75505Sopenharmony_ci if (tls_global_ca_cert(tls_ctx, params->ca_cert) < 0) { 1508e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "SSL: Failed to load ca cert file '%s'", 1509e5b75505Sopenharmony_ci params->ca_cert); 1510e5b75505Sopenharmony_ci return -1; 1511e5b75505Sopenharmony_ci } 1512e5b75505Sopenharmony_ci 1513e5b75505Sopenharmony_ci if (tls_global_client_cert(tls_ctx, params->client_cert) < 0) { 1514e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 1515e5b75505Sopenharmony_ci "SSL: Failed to load client cert file '%s'", 1516e5b75505Sopenharmony_ci params->client_cert); 1517e5b75505Sopenharmony_ci return -1; 1518e5b75505Sopenharmony_ci } 1519e5b75505Sopenharmony_ci 1520e5b75505Sopenharmony_ci if (tls_global_private_key(tls_ctx, params->private_key, 1521e5b75505Sopenharmony_ci params->private_key_passwd) < 0) { 1522e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 1523e5b75505Sopenharmony_ci "SSL: Failed to load private key file '%s'", 1524e5b75505Sopenharmony_ci params->private_key); 1525e5b75505Sopenharmony_ci return -1; 1526e5b75505Sopenharmony_ci } 1527e5b75505Sopenharmony_ci 1528e5b75505Sopenharmony_ci if (tls_global_dh(tls_ctx, params->dh_file, params->dh_blob, 1529e5b75505Sopenharmony_ci params->dh_blob_len) < 0) { 1530e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "SSL: Failed to load DH file '%s'", 1531e5b75505Sopenharmony_ci params->dh_file); 1532e5b75505Sopenharmony_ci return -1; 1533e5b75505Sopenharmony_ci } 1534e5b75505Sopenharmony_ci 1535e5b75505Sopenharmony_ci if (params->openssl_ciphers && 1536e5b75505Sopenharmony_ci wolfSSL_CTX_set_cipher_list(tls_ctx, 1537e5b75505Sopenharmony_ci params->openssl_ciphers) != 1) { 1538e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 1539e5b75505Sopenharmony_ci "wolfSSL: Failed to set cipher string '%s'", 1540e5b75505Sopenharmony_ci params->openssl_ciphers); 1541e5b75505Sopenharmony_ci return -1; 1542e5b75505Sopenharmony_ci } 1543e5b75505Sopenharmony_ci 1544e5b75505Sopenharmony_ci if (params->openssl_ecdh_curves) { 1545e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 1546e5b75505Sopenharmony_ci "wolfSSL: openssl_ecdh_curves not supported"); 1547e5b75505Sopenharmony_ci return -1; 1548e5b75505Sopenharmony_ci } 1549e5b75505Sopenharmony_ci 1550e5b75505Sopenharmony_ci#ifdef HAVE_SESSION_TICKET 1551e5b75505Sopenharmony_ci /* Session ticket is off by default - can't disable once on. */ 1552e5b75505Sopenharmony_ci if (!(params->flags & TLS_CONN_DISABLE_SESSION_TICKET)) 1553e5b75505Sopenharmony_ci wolfSSL_CTX_UseSessionTicket(tls_ctx); 1554e5b75505Sopenharmony_ci#endif /* HAVE_SESSION_TICKET */ 1555e5b75505Sopenharmony_ci 1556e5b75505Sopenharmony_ci#ifdef HAVE_OCSP 1557e5b75505Sopenharmony_ci if (params->ocsp_stapling_response) { 1558e5b75505Sopenharmony_ci wolfSSL_CTX_SetOCSP_OverrideURL(tls_ctx, 1559e5b75505Sopenharmony_ci params->ocsp_stapling_response); 1560e5b75505Sopenharmony_ci wolfSSL_CTX_SetOCSP_Cb(tls_ctx, ocsp_status_cb, 1561e5b75505Sopenharmony_ci ocsp_resp_free_cb, NULL); 1562e5b75505Sopenharmony_ci } 1563e5b75505Sopenharmony_ci#endif /* HAVE_OCSP */ 1564e5b75505Sopenharmony_ci 1565e5b75505Sopenharmony_ci return 0; 1566e5b75505Sopenharmony_ci} 1567e5b75505Sopenharmony_ci 1568e5b75505Sopenharmony_ci 1569e5b75505Sopenharmony_ciint tls_global_set_verify(void *tls_ctx, int check_crl, int strict) 1570e5b75505Sopenharmony_ci{ 1571e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: global set verify: %d", check_crl); 1572e5b75505Sopenharmony_ci 1573e5b75505Sopenharmony_ci if (check_crl) { 1574e5b75505Sopenharmony_ci /* Hack to Enable CRLs. */ 1575e5b75505Sopenharmony_ci wolfSSL_CTX_LoadCRLBuffer(tls_ctx, NULL, 0, SSL_FILETYPE_PEM); 1576e5b75505Sopenharmony_ci } 1577e5b75505Sopenharmony_ci 1578e5b75505Sopenharmony_ci return 0; 1579e5b75505Sopenharmony_ci} 1580e5b75505Sopenharmony_ci 1581e5b75505Sopenharmony_ci 1582e5b75505Sopenharmony_ciint tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, 1583e5b75505Sopenharmony_ci int verify_peer, unsigned int flags, 1584e5b75505Sopenharmony_ci const u8 *session_ctx, size_t session_ctx_len) 1585e5b75505Sopenharmony_ci{ 1586e5b75505Sopenharmony_ci if (!conn) 1587e5b75505Sopenharmony_ci return -1; 1588e5b75505Sopenharmony_ci 1589e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: set verify: %d", verify_peer); 1590e5b75505Sopenharmony_ci 1591e5b75505Sopenharmony_ci if (verify_peer) { 1592e5b75505Sopenharmony_ci conn->ca_cert_verify = 1; 1593e5b75505Sopenharmony_ci wolfSSL_set_verify(conn->ssl, SSL_VERIFY_PEER | 1594e5b75505Sopenharmony_ci SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 1595e5b75505Sopenharmony_ci tls_verify_cb); 1596e5b75505Sopenharmony_ci } else { 1597e5b75505Sopenharmony_ci conn->ca_cert_verify = 0; 1598e5b75505Sopenharmony_ci wolfSSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL); 1599e5b75505Sopenharmony_ci } 1600e5b75505Sopenharmony_ci 1601e5b75505Sopenharmony_ci wolfSSL_set_accept_state(conn->ssl); 1602e5b75505Sopenharmony_ci 1603e5b75505Sopenharmony_ci /* TODO: do we need to fake a session like OpenSSL does here? */ 1604e5b75505Sopenharmony_ci 1605e5b75505Sopenharmony_ci return 0; 1606e5b75505Sopenharmony_ci} 1607e5b75505Sopenharmony_ci 1608e5b75505Sopenharmony_ci 1609e5b75505Sopenharmony_cistatic struct wpabuf * wolfssl_handshake(struct tls_connection *conn, 1610e5b75505Sopenharmony_ci const struct wpabuf *in_data, 1611e5b75505Sopenharmony_ci int server) 1612e5b75505Sopenharmony_ci{ 1613e5b75505Sopenharmony_ci int res; 1614e5b75505Sopenharmony_ci 1615e5b75505Sopenharmony_ci wolfssl_reset_out_data(&conn->output); 1616e5b75505Sopenharmony_ci 1617e5b75505Sopenharmony_ci /* Initiate TLS handshake or continue the existing handshake */ 1618e5b75505Sopenharmony_ci if (server) { 1619e5b75505Sopenharmony_ci wolfSSL_set_accept_state(conn->ssl); 1620e5b75505Sopenharmony_ci res = wolfSSL_accept(conn->ssl); 1621e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: wolfSSL_accept: %d", res); 1622e5b75505Sopenharmony_ci } else { 1623e5b75505Sopenharmony_ci wolfSSL_set_connect_state(conn->ssl); 1624e5b75505Sopenharmony_ci res = wolfSSL_connect(conn->ssl); 1625e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: wolfSSL_connect: %d", res); 1626e5b75505Sopenharmony_ci } 1627e5b75505Sopenharmony_ci 1628e5b75505Sopenharmony_ci if (res != 1) { 1629e5b75505Sopenharmony_ci int err = wolfSSL_get_error(conn->ssl, res); 1630e5b75505Sopenharmony_ci 1631e5b75505Sopenharmony_ci if (err == SSL_ERROR_WANT_READ) { 1632e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1633e5b75505Sopenharmony_ci "SSL: wolfSSL_connect - want more data"); 1634e5b75505Sopenharmony_ci } else if (err == SSL_ERROR_WANT_WRITE) { 1635e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1636e5b75505Sopenharmony_ci "SSL: wolfSSL_connect - want to write"); 1637e5b75505Sopenharmony_ci } else { 1638e5b75505Sopenharmony_ci char msg[80]; 1639e5b75505Sopenharmony_ci 1640e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1641e5b75505Sopenharmony_ci "SSL: wolfSSL_connect - failed %s", 1642e5b75505Sopenharmony_ci wolfSSL_ERR_error_string(err, msg)); 1643e5b75505Sopenharmony_ci conn->failed++; 1644e5b75505Sopenharmony_ci } 1645e5b75505Sopenharmony_ci } 1646e5b75505Sopenharmony_ci 1647e5b75505Sopenharmony_ci return conn->output.out_data; 1648e5b75505Sopenharmony_ci} 1649e5b75505Sopenharmony_ci 1650e5b75505Sopenharmony_ci 1651e5b75505Sopenharmony_cistatic struct wpabuf * wolfssl_get_appl_data(struct tls_connection *conn, 1652e5b75505Sopenharmony_ci size_t max_len) 1653e5b75505Sopenharmony_ci{ 1654e5b75505Sopenharmony_ci int res; 1655e5b75505Sopenharmony_ci struct wpabuf *appl_data = wpabuf_alloc(max_len + 100); 1656e5b75505Sopenharmony_ci 1657e5b75505Sopenharmony_ci if (!appl_data) 1658e5b75505Sopenharmony_ci return NULL; 1659e5b75505Sopenharmony_ci 1660e5b75505Sopenharmony_ci res = wolfSSL_read(conn->ssl, wpabuf_mhead(appl_data), 1661e5b75505Sopenharmony_ci wpabuf_size(appl_data)); 1662e5b75505Sopenharmony_ci if (res < 0) { 1663e5b75505Sopenharmony_ci int err = wolfSSL_get_error(conn->ssl, res); 1664e5b75505Sopenharmony_ci 1665e5b75505Sopenharmony_ci if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { 1666e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1667e5b75505Sopenharmony_ci "SSL: No Application Data included"); 1668e5b75505Sopenharmony_ci } else { 1669e5b75505Sopenharmony_ci char msg[80]; 1670e5b75505Sopenharmony_ci 1671e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1672e5b75505Sopenharmony_ci "Failed to read possible Application Data %s", 1673e5b75505Sopenharmony_ci wolfSSL_ERR_error_string(err, msg)); 1674e5b75505Sopenharmony_ci } 1675e5b75505Sopenharmony_ci 1676e5b75505Sopenharmony_ci wpabuf_free(appl_data); 1677e5b75505Sopenharmony_ci return NULL; 1678e5b75505Sopenharmony_ci } 1679e5b75505Sopenharmony_ci 1680e5b75505Sopenharmony_ci wpabuf_put(appl_data, res); 1681e5b75505Sopenharmony_ci wpa_hexdump_buf_key(MSG_MSGDUMP, 1682e5b75505Sopenharmony_ci "SSL: Application Data in Finished message", 1683e5b75505Sopenharmony_ci appl_data); 1684e5b75505Sopenharmony_ci return appl_data; 1685e5b75505Sopenharmony_ci} 1686e5b75505Sopenharmony_ci 1687e5b75505Sopenharmony_ci 1688e5b75505Sopenharmony_cistatic struct wpabuf * 1689e5b75505Sopenharmony_ciwolfssl_connection_handshake(struct tls_connection *conn, 1690e5b75505Sopenharmony_ci const struct wpabuf *in_data, 1691e5b75505Sopenharmony_ci struct wpabuf **appl_data, int server) 1692e5b75505Sopenharmony_ci{ 1693e5b75505Sopenharmony_ci struct wpabuf *out_data; 1694e5b75505Sopenharmony_ci 1695e5b75505Sopenharmony_ci wolfssl_reset_in_data(&conn->input, in_data); 1696e5b75505Sopenharmony_ci 1697e5b75505Sopenharmony_ci if (appl_data) 1698e5b75505Sopenharmony_ci *appl_data = NULL; 1699e5b75505Sopenharmony_ci 1700e5b75505Sopenharmony_ci out_data = wolfssl_handshake(conn, in_data, server); 1701e5b75505Sopenharmony_ci if (!out_data) 1702e5b75505Sopenharmony_ci return NULL; 1703e5b75505Sopenharmony_ci 1704e5b75505Sopenharmony_ci if (wolfSSL_is_init_finished(conn->ssl)) { 1705e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1706e5b75505Sopenharmony_ci "wolfSSL: Handshake finished - resumed=%d", 1707e5b75505Sopenharmony_ci tls_connection_resumed(NULL, conn)); 1708e5b75505Sopenharmony_ci if (appl_data && in_data) 1709e5b75505Sopenharmony_ci *appl_data = wolfssl_get_appl_data(conn, 1710e5b75505Sopenharmony_ci wpabuf_len(in_data)); 1711e5b75505Sopenharmony_ci } 1712e5b75505Sopenharmony_ci 1713e5b75505Sopenharmony_ci return out_data; 1714e5b75505Sopenharmony_ci} 1715e5b75505Sopenharmony_ci 1716e5b75505Sopenharmony_ci 1717e5b75505Sopenharmony_cistruct wpabuf * tls_connection_handshake(void *tls_ctx, 1718e5b75505Sopenharmony_ci struct tls_connection *conn, 1719e5b75505Sopenharmony_ci const struct wpabuf *in_data, 1720e5b75505Sopenharmony_ci struct wpabuf **appl_data) 1721e5b75505Sopenharmony_ci{ 1722e5b75505Sopenharmony_ci return wolfssl_connection_handshake(conn, in_data, appl_data, 0); 1723e5b75505Sopenharmony_ci} 1724e5b75505Sopenharmony_ci 1725e5b75505Sopenharmony_ci 1726e5b75505Sopenharmony_cistruct wpabuf * tls_connection_server_handshake(void *tls_ctx, 1727e5b75505Sopenharmony_ci struct tls_connection *conn, 1728e5b75505Sopenharmony_ci const struct wpabuf *in_data, 1729e5b75505Sopenharmony_ci struct wpabuf **appl_data) 1730e5b75505Sopenharmony_ci{ 1731e5b75505Sopenharmony_ci return wolfssl_connection_handshake(conn, in_data, appl_data, 1); 1732e5b75505Sopenharmony_ci} 1733e5b75505Sopenharmony_ci 1734e5b75505Sopenharmony_ci 1735e5b75505Sopenharmony_cistruct wpabuf * tls_connection_encrypt(void *tls_ctx, 1736e5b75505Sopenharmony_ci struct tls_connection *conn, 1737e5b75505Sopenharmony_ci const struct wpabuf *in_data) 1738e5b75505Sopenharmony_ci{ 1739e5b75505Sopenharmony_ci int res; 1740e5b75505Sopenharmony_ci 1741e5b75505Sopenharmony_ci if (!conn) 1742e5b75505Sopenharmony_ci return NULL; 1743e5b75505Sopenharmony_ci 1744e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: encrypt: %ld bytes", wpabuf_len(in_data)); 1745e5b75505Sopenharmony_ci 1746e5b75505Sopenharmony_ci wolfssl_reset_out_data(&conn->output); 1747e5b75505Sopenharmony_ci 1748e5b75505Sopenharmony_ci res = wolfSSL_write(conn->ssl, wpabuf_head(in_data), 1749e5b75505Sopenharmony_ci wpabuf_len(in_data)); 1750e5b75505Sopenharmony_ci if (res < 0) { 1751e5b75505Sopenharmony_ci int err = wolfSSL_get_error(conn->ssl, res); 1752e5b75505Sopenharmony_ci char msg[80]; 1753e5b75505Sopenharmony_ci 1754e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "Encryption failed - SSL_write: %s", 1755e5b75505Sopenharmony_ci wolfSSL_ERR_error_string(err, msg)); 1756e5b75505Sopenharmony_ci return NULL; 1757e5b75505Sopenharmony_ci } 1758e5b75505Sopenharmony_ci 1759e5b75505Sopenharmony_ci return conn->output.out_data; 1760e5b75505Sopenharmony_ci} 1761e5b75505Sopenharmony_ci 1762e5b75505Sopenharmony_ci 1763e5b75505Sopenharmony_cistruct wpabuf * tls_connection_decrypt(void *tls_ctx, 1764e5b75505Sopenharmony_ci struct tls_connection *conn, 1765e5b75505Sopenharmony_ci const struct wpabuf *in_data) 1766e5b75505Sopenharmony_ci{ 1767e5b75505Sopenharmony_ci int res; 1768e5b75505Sopenharmony_ci struct wpabuf *buf; 1769e5b75505Sopenharmony_ci 1770e5b75505Sopenharmony_ci if (!conn) 1771e5b75505Sopenharmony_ci return NULL; 1772e5b75505Sopenharmony_ci 1773e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: decrypt"); 1774e5b75505Sopenharmony_ci 1775e5b75505Sopenharmony_ci wolfssl_reset_in_data(&conn->input, in_data); 1776e5b75505Sopenharmony_ci 1777e5b75505Sopenharmony_ci /* Read decrypted data for further processing */ 1778e5b75505Sopenharmony_ci /* 1779e5b75505Sopenharmony_ci * Even though we try to disable TLS compression, it is possible that 1780e5b75505Sopenharmony_ci * this cannot be done with all TLS libraries. Add extra buffer space 1781e5b75505Sopenharmony_ci * to handle the possibility of the decrypted data being longer than 1782e5b75505Sopenharmony_ci * input data. 1783e5b75505Sopenharmony_ci */ 1784e5b75505Sopenharmony_ci buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); 1785e5b75505Sopenharmony_ci if (!buf) 1786e5b75505Sopenharmony_ci return NULL; 1787e5b75505Sopenharmony_ci res = wolfSSL_read(conn->ssl, wpabuf_mhead(buf), wpabuf_size(buf)); 1788e5b75505Sopenharmony_ci if (res < 0) { 1789e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "Decryption failed - SSL_read"); 1790e5b75505Sopenharmony_ci wpabuf_free(buf); 1791e5b75505Sopenharmony_ci return NULL; 1792e5b75505Sopenharmony_ci } 1793e5b75505Sopenharmony_ci wpabuf_put(buf, res); 1794e5b75505Sopenharmony_ci 1795e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "SSL: decrypt: %ld bytes", wpabuf_len(buf)); 1796e5b75505Sopenharmony_ci 1797e5b75505Sopenharmony_ci return buf; 1798e5b75505Sopenharmony_ci} 1799e5b75505Sopenharmony_ci 1800e5b75505Sopenharmony_ci 1801e5b75505Sopenharmony_ciint tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) 1802e5b75505Sopenharmony_ci{ 1803e5b75505Sopenharmony_ci return conn ? wolfSSL_session_reused(conn->ssl) : 0; 1804e5b75505Sopenharmony_ci} 1805e5b75505Sopenharmony_ci 1806e5b75505Sopenharmony_ci 1807e5b75505Sopenharmony_ciint tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, 1808e5b75505Sopenharmony_ci u8 *ciphers) 1809e5b75505Sopenharmony_ci{ 1810e5b75505Sopenharmony_ci char buf[128], *pos, *end; 1811e5b75505Sopenharmony_ci u8 *c; 1812e5b75505Sopenharmony_ci int ret; 1813e5b75505Sopenharmony_ci 1814e5b75505Sopenharmony_ci if (!conn || !conn->ssl || !ciphers) 1815e5b75505Sopenharmony_ci return -1; 1816e5b75505Sopenharmony_ci 1817e5b75505Sopenharmony_ci buf[0] = '\0'; 1818e5b75505Sopenharmony_ci pos = buf; 1819e5b75505Sopenharmony_ci end = pos + sizeof(buf); 1820e5b75505Sopenharmony_ci 1821e5b75505Sopenharmony_ci c = ciphers; 1822e5b75505Sopenharmony_ci while (*c != TLS_CIPHER_NONE) { 1823e5b75505Sopenharmony_ci const char *suite; 1824e5b75505Sopenharmony_ci 1825e5b75505Sopenharmony_ci switch (*c) { 1826e5b75505Sopenharmony_ci case TLS_CIPHER_RC4_SHA: 1827e5b75505Sopenharmony_ci suite = "RC4-SHA"; 1828e5b75505Sopenharmony_ci break; 1829e5b75505Sopenharmony_ci case TLS_CIPHER_AES128_SHA: 1830e5b75505Sopenharmony_ci suite = "AES128-SHA"; 1831e5b75505Sopenharmony_ci break; 1832e5b75505Sopenharmony_ci case TLS_CIPHER_RSA_DHE_AES128_SHA: 1833e5b75505Sopenharmony_ci suite = "DHE-RSA-AES128-SHA"; 1834e5b75505Sopenharmony_ci break; 1835e5b75505Sopenharmony_ci case TLS_CIPHER_ANON_DH_AES128_SHA: 1836e5b75505Sopenharmony_ci suite = "ADH-AES128-SHA"; 1837e5b75505Sopenharmony_ci break; 1838e5b75505Sopenharmony_ci case TLS_CIPHER_RSA_DHE_AES256_SHA: 1839e5b75505Sopenharmony_ci suite = "DHE-RSA-AES256-SHA"; 1840e5b75505Sopenharmony_ci break; 1841e5b75505Sopenharmony_ci case TLS_CIPHER_AES256_SHA: 1842e5b75505Sopenharmony_ci suite = "AES256-SHA"; 1843e5b75505Sopenharmony_ci break; 1844e5b75505Sopenharmony_ci default: 1845e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1846e5b75505Sopenharmony_ci "TLS: Unsupported cipher selection: %d", *c); 1847e5b75505Sopenharmony_ci return -1; 1848e5b75505Sopenharmony_ci } 1849e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, ":%s", suite); 1850e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1851e5b75505Sopenharmony_ci break; 1852e5b75505Sopenharmony_ci pos += ret; 1853e5b75505Sopenharmony_ci 1854e5b75505Sopenharmony_ci c++; 1855e5b75505Sopenharmony_ci } 1856e5b75505Sopenharmony_ci 1857e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "wolfSSL: cipher suites: %s", buf + 1); 1858e5b75505Sopenharmony_ci 1859e5b75505Sopenharmony_ci if (wolfSSL_set_cipher_list(conn->ssl, buf + 1) != 1) { 1860e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Cipher suite configuration failed"); 1861e5b75505Sopenharmony_ci return -1; 1862e5b75505Sopenharmony_ci } 1863e5b75505Sopenharmony_ci 1864e5b75505Sopenharmony_ci return 0; 1865e5b75505Sopenharmony_ci} 1866e5b75505Sopenharmony_ci 1867e5b75505Sopenharmony_ci 1868e5b75505Sopenharmony_ciint tls_get_cipher(void *tls_ctx, struct tls_connection *conn, 1869e5b75505Sopenharmony_ci char *buf, size_t buflen) 1870e5b75505Sopenharmony_ci{ 1871e5b75505Sopenharmony_ci WOLFSSL_CIPHER *cipher; 1872e5b75505Sopenharmony_ci const char *name; 1873e5b75505Sopenharmony_ci 1874e5b75505Sopenharmony_ci if (!conn || !conn->ssl) 1875e5b75505Sopenharmony_ci return -1; 1876e5b75505Sopenharmony_ci 1877e5b75505Sopenharmony_ci cipher = wolfSSL_get_current_cipher(conn->ssl); 1878e5b75505Sopenharmony_ci if (!cipher) 1879e5b75505Sopenharmony_ci return -1; 1880e5b75505Sopenharmony_ci 1881e5b75505Sopenharmony_ci name = wolfSSL_CIPHER_get_name(cipher); 1882e5b75505Sopenharmony_ci if (!name) 1883e5b75505Sopenharmony_ci return -1; 1884e5b75505Sopenharmony_ci 1885e5b75505Sopenharmony_ci if (os_strcmp(name, "SSL_RSA_WITH_RC4_128_SHA") == 0) 1886e5b75505Sopenharmony_ci os_strlcpy(buf, "RC4-SHA", buflen); 1887e5b75505Sopenharmony_ci else if (os_strcmp(name, "TLS_RSA_WITH_AES_128_CBC_SHA") == 0) 1888e5b75505Sopenharmony_ci os_strlcpy(buf, "AES128-SHA", buflen); 1889e5b75505Sopenharmony_ci else if (os_strcmp(name, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA") == 0) 1890e5b75505Sopenharmony_ci os_strlcpy(buf, "DHE-RSA-AES128-SHA", buflen); 1891e5b75505Sopenharmony_ci else if (os_strcmp(name, "TLS_DH_anon_WITH_AES_128_CBC_SHA") == 0) 1892e5b75505Sopenharmony_ci os_strlcpy(buf, "ADH-AES128-SHA", buflen); 1893e5b75505Sopenharmony_ci else if (os_strcmp(name, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA") == 0) 1894e5b75505Sopenharmony_ci os_strlcpy(buf, "DHE-RSA-AES256-SHA", buflen); 1895e5b75505Sopenharmony_ci else if (os_strcmp(name, "TLS_RSA_WITH_AES_256_CBC_SHA") == 0) 1896e5b75505Sopenharmony_ci os_strlcpy(buf, "AES256-SHA", buflen); 1897e5b75505Sopenharmony_ci else 1898e5b75505Sopenharmony_ci os_strlcpy(buf, name, buflen); 1899e5b75505Sopenharmony_ci 1900e5b75505Sopenharmony_ci return 0; 1901e5b75505Sopenharmony_ci} 1902e5b75505Sopenharmony_ci 1903e5b75505Sopenharmony_ci 1904e5b75505Sopenharmony_ciint tls_connection_enable_workaround(void *tls_ctx, 1905e5b75505Sopenharmony_ci struct tls_connection *conn) 1906e5b75505Sopenharmony_ci{ 1907e5b75505Sopenharmony_ci /* no empty fragments in wolfSSL for now */ 1908e5b75505Sopenharmony_ci return 0; 1909e5b75505Sopenharmony_ci} 1910e5b75505Sopenharmony_ci 1911e5b75505Sopenharmony_ci 1912e5b75505Sopenharmony_ciint tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) 1913e5b75505Sopenharmony_ci{ 1914e5b75505Sopenharmony_ci if (!conn) 1915e5b75505Sopenharmony_ci return -1; 1916e5b75505Sopenharmony_ci 1917e5b75505Sopenharmony_ci return conn->failed; 1918e5b75505Sopenharmony_ci} 1919e5b75505Sopenharmony_ci 1920e5b75505Sopenharmony_ci 1921e5b75505Sopenharmony_ciint tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) 1922e5b75505Sopenharmony_ci{ 1923e5b75505Sopenharmony_ci if (!conn) 1924e5b75505Sopenharmony_ci return -1; 1925e5b75505Sopenharmony_ci 1926e5b75505Sopenharmony_ci /* TODO: this is not incremented anywhere */ 1927e5b75505Sopenharmony_ci return conn->read_alerts; 1928e5b75505Sopenharmony_ci} 1929e5b75505Sopenharmony_ci 1930e5b75505Sopenharmony_ci 1931e5b75505Sopenharmony_ciint tls_connection_get_write_alerts(void *tls_ctx, 1932e5b75505Sopenharmony_ci struct tls_connection *conn) 1933e5b75505Sopenharmony_ci{ 1934e5b75505Sopenharmony_ci if (!conn) 1935e5b75505Sopenharmony_ci return -1; 1936e5b75505Sopenharmony_ci 1937e5b75505Sopenharmony_ci /* TODO: this is not incremented anywhere */ 1938e5b75505Sopenharmony_ci return conn->write_alerts; 1939e5b75505Sopenharmony_ci} 1940e5b75505Sopenharmony_ci 1941e5b75505Sopenharmony_ci 1942e5b75505Sopenharmony_ci 1943e5b75505Sopenharmony_ciint tls_get_library_version(char *buf, size_t buf_len) 1944e5b75505Sopenharmony_ci{ 1945e5b75505Sopenharmony_ci return os_snprintf(buf, buf_len, "wolfSSL build=%s run=%s", 1946e5b75505Sopenharmony_ci WOLFSSL_VERSION, wolfSSL_lib_version()); 1947e5b75505Sopenharmony_ci} 1948e5b75505Sopenharmony_ci 1949e5b75505Sopenharmony_ciint tls_get_version(void *ssl_ctx, struct tls_connection *conn, 1950e5b75505Sopenharmony_ci char *buf, size_t buflen) 1951e5b75505Sopenharmony_ci{ 1952e5b75505Sopenharmony_ci const char *name; 1953e5b75505Sopenharmony_ci 1954e5b75505Sopenharmony_ci if (!conn || !conn->ssl) 1955e5b75505Sopenharmony_ci return -1; 1956e5b75505Sopenharmony_ci 1957e5b75505Sopenharmony_ci name = wolfSSL_get_version(conn->ssl); 1958e5b75505Sopenharmony_ci if (!name) 1959e5b75505Sopenharmony_ci return -1; 1960e5b75505Sopenharmony_ci 1961e5b75505Sopenharmony_ci os_strlcpy(buf, name, buflen); 1962e5b75505Sopenharmony_ci return 0; 1963e5b75505Sopenharmony_ci} 1964e5b75505Sopenharmony_ci 1965e5b75505Sopenharmony_ci 1966e5b75505Sopenharmony_ciint tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn, 1967e5b75505Sopenharmony_ci struct tls_random *keys) 1968e5b75505Sopenharmony_ci{ 1969e5b75505Sopenharmony_ci WOLFSSL *ssl; 1970e5b75505Sopenharmony_ci 1971e5b75505Sopenharmony_ci if (!conn || !keys) 1972e5b75505Sopenharmony_ci return -1; 1973e5b75505Sopenharmony_ci ssl = conn->ssl; 1974e5b75505Sopenharmony_ci if (!ssl) 1975e5b75505Sopenharmony_ci return -1; 1976e5b75505Sopenharmony_ci 1977e5b75505Sopenharmony_ci os_memset(keys, 0, sizeof(*keys)); 1978e5b75505Sopenharmony_ci keys->client_random = conn->client_random; 1979e5b75505Sopenharmony_ci keys->client_random_len = wolfSSL_get_client_random( 1980e5b75505Sopenharmony_ci ssl, conn->client_random, sizeof(conn->client_random)); 1981e5b75505Sopenharmony_ci keys->server_random = conn->server_random; 1982e5b75505Sopenharmony_ci keys->server_random_len = wolfSSL_get_server_random( 1983e5b75505Sopenharmony_ci ssl, conn->server_random, sizeof(conn->server_random)); 1984e5b75505Sopenharmony_ci 1985e5b75505Sopenharmony_ci return 0; 1986e5b75505Sopenharmony_ci} 1987e5b75505Sopenharmony_ci 1988e5b75505Sopenharmony_ci 1989e5b75505Sopenharmony_ciint tls_connection_export_key(void *tls_ctx, struct tls_connection *conn, 1990e5b75505Sopenharmony_ci const char *label, const u8 *context, 1991e5b75505Sopenharmony_ci size_t context_len, u8 *out, size_t out_len) 1992e5b75505Sopenharmony_ci{ 1993e5b75505Sopenharmony_ci if (context) 1994e5b75505Sopenharmony_ci return -1; 1995e5b75505Sopenharmony_ci if (!conn || wolfSSL_make_eap_keys(conn->ssl, out, out_len, label) != 0) 1996e5b75505Sopenharmony_ci return -1; 1997e5b75505Sopenharmony_ci return 0; 1998e5b75505Sopenharmony_ci} 1999e5b75505Sopenharmony_ci 2000e5b75505Sopenharmony_ci 2001e5b75505Sopenharmony_ci#define SEED_LEN (RAN_LEN + RAN_LEN) 2002e5b75505Sopenharmony_ci 2003e5b75505Sopenharmony_ciint tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn, 2004e5b75505Sopenharmony_ci u8 *out, size_t out_len) 2005e5b75505Sopenharmony_ci{ 2006e5b75505Sopenharmony_ci byte seed[SEED_LEN]; 2007e5b75505Sopenharmony_ci int ret = -1; 2008e5b75505Sopenharmony_ci WOLFSSL *ssl; 2009e5b75505Sopenharmony_ci byte *tmp_out; 2010e5b75505Sopenharmony_ci byte *_out; 2011e5b75505Sopenharmony_ci int skip = 0; 2012e5b75505Sopenharmony_ci byte *master_key; 2013e5b75505Sopenharmony_ci unsigned int master_key_len; 2014e5b75505Sopenharmony_ci byte *server_random; 2015e5b75505Sopenharmony_ci unsigned int server_len; 2016e5b75505Sopenharmony_ci byte *client_random; 2017e5b75505Sopenharmony_ci unsigned int client_len; 2018e5b75505Sopenharmony_ci 2019e5b75505Sopenharmony_ci if (!conn || !conn->ssl) 2020e5b75505Sopenharmony_ci return -1; 2021e5b75505Sopenharmony_ci ssl = conn->ssl; 2022e5b75505Sopenharmony_ci 2023e5b75505Sopenharmony_ci skip = 2 * (wolfSSL_GetKeySize(ssl) + wolfSSL_GetHmacSize(ssl) + 2024e5b75505Sopenharmony_ci wolfSSL_GetIVSize(ssl)); 2025e5b75505Sopenharmony_ci 2026e5b75505Sopenharmony_ci tmp_out = os_malloc(skip + out_len); 2027e5b75505Sopenharmony_ci if (!tmp_out) 2028e5b75505Sopenharmony_ci return -1; 2029e5b75505Sopenharmony_ci _out = tmp_out; 2030e5b75505Sopenharmony_ci 2031e5b75505Sopenharmony_ci wolfSSL_get_keys(ssl, &master_key, &master_key_len, &server_random, 2032e5b75505Sopenharmony_ci &server_len, &client_random, &client_len); 2033e5b75505Sopenharmony_ci os_memcpy(seed, server_random, RAN_LEN); 2034e5b75505Sopenharmony_ci os_memcpy(seed + RAN_LEN, client_random, RAN_LEN); 2035e5b75505Sopenharmony_ci 2036e5b75505Sopenharmony_ci if (wolfSSL_GetVersion(ssl) == WOLFSSL_TLSV1_2) { 2037e5b75505Sopenharmony_ci tls_prf_sha256(master_key, master_key_len, 2038e5b75505Sopenharmony_ci "key expansion", seed, sizeof(seed), 2039e5b75505Sopenharmony_ci _out, skip + out_len); 2040e5b75505Sopenharmony_ci ret = 0; 2041e5b75505Sopenharmony_ci } else { 2042e5b75505Sopenharmony_ci ret = tls_prf_sha1_md5(master_key, master_key_len, 2043e5b75505Sopenharmony_ci "key expansion", seed, sizeof(seed), 2044e5b75505Sopenharmony_ci _out, skip + out_len); 2045e5b75505Sopenharmony_ci } 2046e5b75505Sopenharmony_ci 2047e5b75505Sopenharmony_ci forced_memzero(master_key, master_key_len); 2048e5b75505Sopenharmony_ci if (ret == 0) 2049e5b75505Sopenharmony_ci os_memcpy(out, _out + skip, out_len); 2050e5b75505Sopenharmony_ci bin_clear_free(tmp_out, skip + out_len); 2051e5b75505Sopenharmony_ci 2052e5b75505Sopenharmony_ci return ret; 2053e5b75505Sopenharmony_ci} 2054e5b75505Sopenharmony_ci 2055e5b75505Sopenharmony_ci 2056e5b75505Sopenharmony_ci#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) 2057e5b75505Sopenharmony_ci 2058e5b75505Sopenharmony_ciint tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, 2059e5b75505Sopenharmony_ci int ext_type, const u8 *data, 2060e5b75505Sopenharmony_ci size_t data_len) 2061e5b75505Sopenharmony_ci{ 2062e5b75505Sopenharmony_ci (void) ssl_ctx; 2063e5b75505Sopenharmony_ci 2064e5b75505Sopenharmony_ci if (!conn || !conn->ssl || ext_type != 35) 2065e5b75505Sopenharmony_ci return -1; 2066e5b75505Sopenharmony_ci 2067e5b75505Sopenharmony_ci if (wolfSSL_set_SessionTicket(conn->ssl, data, 2068e5b75505Sopenharmony_ci (unsigned int) data_len) != 1) 2069e5b75505Sopenharmony_ci return -1; 2070e5b75505Sopenharmony_ci 2071e5b75505Sopenharmony_ci return 0; 2072e5b75505Sopenharmony_ci} 2073e5b75505Sopenharmony_ci 2074e5b75505Sopenharmony_ci 2075e5b75505Sopenharmony_cistatic int tls_sess_sec_cb(WOLFSSL *s, void *secret, int *secret_len, void *arg) 2076e5b75505Sopenharmony_ci{ 2077e5b75505Sopenharmony_ci struct tls_connection *conn = arg; 2078e5b75505Sopenharmony_ci int ret; 2079e5b75505Sopenharmony_ci unsigned char client_random[RAN_LEN]; 2080e5b75505Sopenharmony_ci unsigned char server_random[RAN_LEN]; 2081e5b75505Sopenharmony_ci word32 ticket_len = sizeof(conn->session_ticket); 2082e5b75505Sopenharmony_ci 2083e5b75505Sopenharmony_ci if (!conn || !conn->session_ticket_cb) 2084e5b75505Sopenharmony_ci return 1; 2085e5b75505Sopenharmony_ci 2086e5b75505Sopenharmony_ci if (wolfSSL_get_client_random(s, client_random, 2087e5b75505Sopenharmony_ci sizeof(client_random)) == 0 || 2088e5b75505Sopenharmony_ci wolfSSL_get_server_random(s, server_random, 2089e5b75505Sopenharmony_ci sizeof(server_random)) == 0 || 2090e5b75505Sopenharmony_ci wolfSSL_get_SessionTicket(s, conn->session_ticket, 2091e5b75505Sopenharmony_ci &ticket_len) != 1) 2092e5b75505Sopenharmony_ci return 1; 2093e5b75505Sopenharmony_ci 2094e5b75505Sopenharmony_ci if (ticket_len == 0) 2095e5b75505Sopenharmony_ci return 0; 2096e5b75505Sopenharmony_ci 2097e5b75505Sopenharmony_ci ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx, 2098e5b75505Sopenharmony_ci conn->session_ticket, ticket_len, 2099e5b75505Sopenharmony_ci client_random, server_random, secret); 2100e5b75505Sopenharmony_ci if (ret <= 0) 2101e5b75505Sopenharmony_ci return 1; 2102e5b75505Sopenharmony_ci 2103e5b75505Sopenharmony_ci *secret_len = SECRET_LEN; 2104e5b75505Sopenharmony_ci return 0; 2105e5b75505Sopenharmony_ci} 2106e5b75505Sopenharmony_ci 2107e5b75505Sopenharmony_ci#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */ 2108e5b75505Sopenharmony_ci 2109e5b75505Sopenharmony_ci 2110e5b75505Sopenharmony_ciint tls_connection_set_session_ticket_cb(void *tls_ctx, 2111e5b75505Sopenharmony_ci struct tls_connection *conn, 2112e5b75505Sopenharmony_ci tls_session_ticket_cb cb, 2113e5b75505Sopenharmony_ci void *ctx) 2114e5b75505Sopenharmony_ci{ 2115e5b75505Sopenharmony_ci#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) 2116e5b75505Sopenharmony_ci conn->session_ticket_cb = cb; 2117e5b75505Sopenharmony_ci conn->session_ticket_cb_ctx = ctx; 2118e5b75505Sopenharmony_ci 2119e5b75505Sopenharmony_ci if (cb) { 2120e5b75505Sopenharmony_ci if (wolfSSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb, 2121e5b75505Sopenharmony_ci conn) != 1) 2122e5b75505Sopenharmony_ci return -1; 2123e5b75505Sopenharmony_ci } else { 2124e5b75505Sopenharmony_ci if (wolfSSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1) 2125e5b75505Sopenharmony_ci return -1; 2126e5b75505Sopenharmony_ci } 2127e5b75505Sopenharmony_ci 2128e5b75505Sopenharmony_ci return 0; 2129e5b75505Sopenharmony_ci#else /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */ 2130e5b75505Sopenharmony_ci return -1; 2131e5b75505Sopenharmony_ci#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */ 2132e5b75505Sopenharmony_ci} 2133e5b75505Sopenharmony_ci 2134e5b75505Sopenharmony_ci 2135e5b75505Sopenharmony_civoid tls_connection_set_success_data_resumed(struct tls_connection *conn) 2136e5b75505Sopenharmony_ci{ 2137e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 2138e5b75505Sopenharmony_ci "wolfSSL: Success data accepted for resumed session"); 2139e5b75505Sopenharmony_ci} 2140e5b75505Sopenharmony_ci 2141e5b75505Sopenharmony_ci 2142e5b75505Sopenharmony_civoid tls_connection_remove_session(struct tls_connection *conn) 2143e5b75505Sopenharmony_ci{ 2144e5b75505Sopenharmony_ci WOLFSSL_SESSION *sess; 2145e5b75505Sopenharmony_ci 2146e5b75505Sopenharmony_ci sess = wolfSSL_get_session(conn->ssl); 2147e5b75505Sopenharmony_ci if (!sess) 2148e5b75505Sopenharmony_ci return; 2149e5b75505Sopenharmony_ci 2150e5b75505Sopenharmony_ci wolfSSL_SSL_SESSION_set_timeout(sess, 0); 2151e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 2152e5b75505Sopenharmony_ci "wolfSSL: Removed cached session to disable session resumption"); 2153e5b75505Sopenharmony_ci} 2154e5b75505Sopenharmony_ci 2155e5b75505Sopenharmony_ci 2156e5b75505Sopenharmony_civoid tls_connection_set_success_data(struct tls_connection *conn, 2157e5b75505Sopenharmony_ci struct wpabuf *data) 2158e5b75505Sopenharmony_ci{ 2159e5b75505Sopenharmony_ci WOLFSSL_SESSION *sess; 2160e5b75505Sopenharmony_ci struct wpabuf *old; 2161e5b75505Sopenharmony_ci 2162e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "wolfSSL: Set success data"); 2163e5b75505Sopenharmony_ci 2164e5b75505Sopenharmony_ci sess = wolfSSL_get_session(conn->ssl); 2165e5b75505Sopenharmony_ci if (!sess) { 2166e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 2167e5b75505Sopenharmony_ci "wolfSSL: No session found for success data"); 2168e5b75505Sopenharmony_ci goto fail; 2169e5b75505Sopenharmony_ci } 2170e5b75505Sopenharmony_ci 2171e5b75505Sopenharmony_ci old = wolfSSL_SESSION_get_ex_data(sess, tls_ex_idx_session); 2172e5b75505Sopenharmony_ci if (old) { 2173e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "wolfSSL: Replacing old success data %p", 2174e5b75505Sopenharmony_ci old); 2175e5b75505Sopenharmony_ci wpabuf_free(old); 2176e5b75505Sopenharmony_ci } 2177e5b75505Sopenharmony_ci if (wolfSSL_SESSION_set_ex_data(sess, tls_ex_idx_session, data) != 1) 2178e5b75505Sopenharmony_ci goto fail; 2179e5b75505Sopenharmony_ci 2180e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "wolfSSL: Stored success data %p", data); 2181e5b75505Sopenharmony_ci conn->success_data = 1; 2182e5b75505Sopenharmony_ci return; 2183e5b75505Sopenharmony_ci 2184e5b75505Sopenharmony_cifail: 2185e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "wolfSSL: Failed to store success data"); 2186e5b75505Sopenharmony_ci wpabuf_free(data); 2187e5b75505Sopenharmony_ci} 2188e5b75505Sopenharmony_ci 2189e5b75505Sopenharmony_ci 2190e5b75505Sopenharmony_ciconst struct wpabuf * 2191e5b75505Sopenharmony_citls_connection_get_success_data(struct tls_connection *conn) 2192e5b75505Sopenharmony_ci{ 2193e5b75505Sopenharmony_ci WOLFSSL_SESSION *sess; 2194e5b75505Sopenharmony_ci 2195e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "wolfSSL: Get success data"); 2196e5b75505Sopenharmony_ci 2197e5b75505Sopenharmony_ci sess = wolfSSL_get_session(conn->ssl); 2198e5b75505Sopenharmony_ci if (!sess) 2199e5b75505Sopenharmony_ci return NULL; 2200e5b75505Sopenharmony_ci return wolfSSL_SESSION_get_ex_data(sess, tls_ex_idx_session); 2201e5b75505Sopenharmony_ci} 2202