diff options
Diffstat (limited to 'src/crypto/tls_openssl.c')
| -rw-r--r-- | src/crypto/tls_openssl.c | 586 |
1 files changed, 387 insertions, 199 deletions
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c index 8b7b47bc256d5..23ac64b48cd9b 100644 --- a/src/crypto/tls_openssl.c +++ b/src/crypto/tls_openssl.c @@ -18,6 +18,7 @@ #include <openssl/ssl.h> #include <openssl/err.h> +#include <openssl/opensslv.h> #include <openssl/pkcs12.h> #include <openssl/x509v3.h> #ifndef OPENSSL_NO_ENGINE @@ -35,12 +36,12 @@ #include "sha1.h" #include "sha256.h" #include "tls.h" +#include "tls_openssl.h" -#if OPENSSL_VERSION_NUMBER < 0x10000000L -/* ERR_remove_thread_state replaces ERR_remove_state and the latter is - * deprecated. However, OpenSSL 0.9.8 doesn't include - * ERR_remove_thread_state. */ -#define ERR_remove_thread_state(tid) ERR_remove_state(0) +#if !defined(CONFIG_FIPS) && \ + (defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || \ + defined(EAP_SERVER_FAST)) +#define OPENSSL_NEED_EAP_FAST_PRF #endif #if defined(OPENSSL_IS_BORINGSSL) @@ -57,6 +58,51 @@ typedef int stack_index_t; #endif /* OPENSSL_NO_TLSEXT */ #endif /* SSL_set_tlsext_status_type */ +#if (OPENSSL_VERSION_NUMBER < 0x10100000L || \ + defined(LIBRESSL_VERSION_NUMBER)) && \ + !defined(BORINGSSL_API_VERSION) +/* + * SSL_get_client_random() and SSL_get_server_random() were added in OpenSSL + * 1.1.0 and newer BoringSSL revisions. Provide compatibility wrappers for + * older versions. + */ + +static size_t SSL_get_client_random(const SSL *ssl, unsigned char *out, + size_t outlen) +{ + if (!ssl->s3 || outlen < SSL3_RANDOM_SIZE) + return 0; + os_memcpy(out, ssl->s3->client_random, SSL3_RANDOM_SIZE); + return SSL3_RANDOM_SIZE; +} + + +static size_t SSL_get_server_random(const SSL *ssl, unsigned char *out, + size_t outlen) +{ + if (!ssl->s3 || outlen < SSL3_RANDOM_SIZE) + return 0; + os_memcpy(out, ssl->s3->server_random, SSL3_RANDOM_SIZE); + return SSL3_RANDOM_SIZE; +} + + +#ifdef OPENSSL_NEED_EAP_FAST_PRF +static size_t SSL_SESSION_get_master_key(const SSL_SESSION *session, + unsigned char *out, size_t outlen) +{ + if (!session || session->master_key_length < 0 || + (size_t) session->master_key_length > outlen) + return 0; + if ((size_t) session->master_key_length < outlen) + outlen = session->master_key_length; + os_memcpy(out, session->master_key, outlen); + return outlen; +} +#endif /* OPENSSL_NEED_EAP_FAST_PRF */ + +#endif + #ifdef ANDROID #include <openssl/pem.h> #include <keystore/keystore_get.h> @@ -71,6 +117,66 @@ static BIO * BIO_from_keystore(const char *key) free(value); return bio; } + + +static int tls_add_ca_from_keystore(X509_STORE *ctx, const char *key_alias) +{ + BIO *bio = BIO_from_keystore(key_alias); + STACK_OF(X509_INFO) *stack = NULL; + stack_index_t i; + + if (bio) { + stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL); + BIO_free(bio); + } + + if (!stack) { + wpa_printf(MSG_WARNING, "TLS: Failed to parse certificate: %s", + key_alias); + return -1; + } + + for (i = 0; i < sk_X509_INFO_num(stack); ++i) { + X509_INFO *info = sk_X509_INFO_value(stack, i); + + if (info->x509) + X509_STORE_add_cert(ctx, info->x509); + if (info->crl) + X509_STORE_add_crl(ctx, info->crl); + } + + sk_X509_INFO_pop_free(stack, X509_INFO_free); + + return 0; +} + + +static int tls_add_ca_from_keystore_encoded(X509_STORE *ctx, + const char *encoded_key_alias) +{ + int rc = -1; + int len = os_strlen(encoded_key_alias); + unsigned char *decoded_alias; + + if (len & 1) { + wpa_printf(MSG_WARNING, "Invalid hex-encoded alias: %s", + encoded_key_alias); + return rc; + } + + decoded_alias = os_malloc(len / 2 + 1); + if (decoded_alias) { + if (!hexstr2bin(encoded_key_alias, decoded_alias, len / 2)) { + decoded_alias[len / 2] = '\0'; + rc = tls_add_ca_from_keystore( + ctx, (const char *) decoded_alias); + } + os_free(decoded_alias); + } + + return rc; +} + #endif /* ANDROID */ static int tls_openssl_ref_count = 0; @@ -97,7 +203,7 @@ struct tls_connection { SSL_CTX *ssl_ctx; SSL *ssl; BIO *ssl_in, *ssl_out; -#ifndef OPENSSL_NO_ENGINE +#if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE) ENGINE *engine; /* functional reference to the engine */ EVP_PKEY *private_key; /* the private key if using engine */ #endif /* OPENSSL_NO_ENGINE */ @@ -125,10 +231,8 @@ struct tls_connection { X509 *peer_issuer; X509 *peer_issuer_issuer; -#if OPENSSL_VERSION_NUMBER >= 0x10100000L unsigned char client_random[SSL3_RANDOM_SIZE]; unsigned char server_random[SSL3_RANDOM_SIZE]; -#endif }; @@ -526,7 +630,8 @@ static int tls_cryptoapi_ca_cert(SSL_CTX *ssl_ctx, SSL *ssl, const char *name) wpa_printf(MSG_DEBUG, "OpenSSL: Loaded CA certificate for " "system certificate store: subject='%s'", buf); - if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) { + if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(ssl_ctx), + cert)) { tls_show_errors(MSG_WARNING, __func__, "Failed to add ca_cert to OpenSSL " "certificate store"); @@ -624,10 +729,16 @@ static int tls_engine_load_dynamic_generic(const char *pre[], engine = ENGINE_by_id(id); if (engine) { - ENGINE_free(engine); wpa_printf(MSG_DEBUG, "ENGINE: engine '%s' is already " "available", id); - return 0; + /* + * If it was auto-loaded by ENGINE_by_id() we might still + * need to tell it which PKCS#11 module to use in legacy + * (non-p11-kit) environments. Do so now; even if it was + * properly initialised before, setting it again will be + * harmless. + */ + goto found; } ERR_clear_error(); @@ -664,7 +775,7 @@ static int tls_engine_load_dynamic_generic(const char *pre[], id, ERR_error_string(ERR_get_error(), NULL)); return -1; } - + found: while (post && post[0]) { wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", post[0], post[1]); if (ENGINE_ctrl_cmd_string(engine, post[0], post[1], 0) == 0) { @@ -808,6 +919,7 @@ void * tls_init(const struct tls_config *conf) } #endif /* OPENSSL_FIPS */ #endif /* CONFIG_FIPS */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L SSL_load_error_strings(); SSL_library_init(); #ifndef OPENSSL_NO_SHA256 @@ -829,6 +941,7 @@ void * tls_init(const struct tls_config *conf) #endif /* OPENSSL_NO_RC2 */ PKCS12_PBE_add(); #endif /* PKCS12_FUNCS */ +#endif /* < 1.1.0 */ } else { context = tls_context_new(conf); if (context == NULL) @@ -849,6 +962,7 @@ void * tls_init(const struct tls_config *conf) os_free(tls_global); tls_global = NULL; } + os_free(data); return NULL; } data->ssl = ssl; @@ -929,6 +1043,7 @@ void tls_deinit(void *ssl_ctx) tls_openssl_ref_count--; if (tls_openssl_ref_count == 0) { +#if OPENSSL_VERSION_NUMBER < 0x10100000L #ifndef OPENSSL_NO_ENGINE ENGINE_cleanup(); #endif /* OPENSSL_NO_ENGINE */ @@ -936,6 +1051,7 @@ void tls_deinit(void *ssl_ctx) ERR_remove_thread_state(NULL); ERR_free_strings(); EVP_cleanup(); +#endif /* < 1.1.0 */ os_free(tls_global->ocsp_stapling_response); tls_global->ocsp_stapling_response = NULL; os_free(tls_global); @@ -967,10 +1083,32 @@ static int tls_is_pin_error(unsigned int err) #endif /* OPENSSL_NO_ENGINE */ +#ifdef ANDROID +/* EVP_PKEY_from_keystore comes from system/security/keystore-engine. */ +EVP_PKEY * EVP_PKEY_from_keystore(const char *key_id); +#endif /* ANDROID */ + static int tls_engine_init(struct tls_connection *conn, const char *engine_id, const char *pin, const char *key_id, const char *cert_id, const char *ca_cert_id) { +#if defined(ANDROID) && defined(OPENSSL_IS_BORINGSSL) +#if !defined(OPENSSL_NO_ENGINE) +#error "This code depends on OPENSSL_NO_ENGINE being defined by BoringSSL." +#endif + if (!key_id) + return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; + conn->engine = NULL; + conn->private_key = EVP_PKEY_from_keystore(key_id); + if (!conn->private_key) { + wpa_printf(MSG_ERROR, + "ENGINE: cannot load private key with id '%s' [%s]", + key_id, + ERR_error_string(ERR_get_error(), NULL)); + return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; + } +#endif /* ANDROID && OPENSSL_IS_BORINGSSL */ + #ifndef OPENSSL_NO_ENGINE int ret = -1; if (engine_id == NULL) { @@ -1068,17 +1206,19 @@ err: static void tls_engine_deinit(struct tls_connection *conn) { -#ifndef OPENSSL_NO_ENGINE +#if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE) wpa_printf(MSG_DEBUG, "ENGINE: engine deinit"); if (conn->private_key) { EVP_PKEY_free(conn->private_key); conn->private_key = NULL; } if (conn->engine) { +#if !defined(OPENSSL_IS_BORINGSSL) ENGINE_finish(conn->engine); +#endif /* !OPENSSL_IS_BORINGSSL */ conn->engine = NULL; } -#endif /* OPENSSL_NO_ENGINE */ +#endif /* ANDROID || !OPENSSL_NO_ENGINE */ } @@ -1097,14 +1237,83 @@ int tls_get_errors(void *ssl_ctx) } +static const char * openssl_content_type(int content_type) +{ + switch (content_type) { + case 20: + return "change cipher spec"; + case 21: + return "alert"; + case 22: + return "handshake"; + case 23: + return "application data"; + case 24: + return "heartbeat"; + case 256: + return "TLS header info"; /* pseudo content type */ + default: + return "?"; + } +} + + +static const char * openssl_handshake_type(int content_type, const u8 *buf, + size_t len) +{ + if (content_type != 22 || !buf || len == 0) + return ""; + switch (buf[0]) { + case 0: + return "hello request"; + case 1: + return "client hello"; + case 2: + return "server hello"; + case 4: + return "new session ticket"; + case 11: + return "certificate"; + case 12: + return "server key exchange"; + case 13: + return "certificate request"; + case 14: + return "server hello done"; + case 15: + return "certificate verify"; + case 16: + return "client key exchange"; + case 20: + return "finished"; + case 21: + return "certificate url"; + case 22: + return "certificate status"; + default: + return "?"; + } +} + + static void tls_msg_cb(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg) { struct tls_connection *conn = arg; const u8 *pos = buf; - wpa_printf(MSG_DEBUG, "OpenSSL: %s ver=0x%x content_type=%d", - write_p ? "TX" : "RX", version, content_type); + if (write_p == 2) { + wpa_printf(MSG_DEBUG, + "OpenSSL: session ver=0x%x content_type=%d", + version, content_type); + wpa_hexdump_key(MSG_MSGDUMP, "OpenSSL: Data", buf, len); + return; + } + + wpa_printf(MSG_DEBUG, "OpenSSL: %s ver=0x%x content_type=%d (%s/%s)", + write_p ? "TX" : "RX", version, content_type, + openssl_content_type(content_type), + openssl_handshake_type(content_type, buf, len)); wpa_hexdump_key(MSG_MSGDUMP, "OpenSSL: Message", buf, len); if (content_type == 24 && len >= 3 && pos[0] == 1) { size_t payload_len = WPA_GET_BE16(pos + 1); @@ -1234,6 +1443,8 @@ static int tls_match_altsubject_component(X509 *cert, int type, found++; } + sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free); + return found; } @@ -1346,9 +1557,11 @@ static int tls_match_suffix(X509 *cert, const char *match, int full) 1) { wpa_printf(MSG_DEBUG, "TLS: %s in dNSName found", full ? "Match" : "Suffix match"); + sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free); return 1; } } + sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free); if (dns_name) { wpa_printf(MSG_DEBUG, "TLS: None of the dNSName(s) matched"); @@ -1489,7 +1702,8 @@ static void openssl_tls_cert_event(struct tls_connection *conn, return; os_memset(&ev, 0, sizeof(ev)); - if (conn->cert_probe || context->cert_in_cb) { + if (conn->cert_probe || (conn->flags & TLS_CONN_EXT_CERT_CHECK) || + context->cert_in_cb) { cert = get_x509_cert(err_cert); ev.peer_cert.cert = cert; } @@ -1544,6 +1758,7 @@ static void openssl_tls_cert_event(struct tls_connection *conn, pos += gen->d.ia5->length; *pos = '\0'; } + sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free); for (alt = 0; alt < num_altsubject; alt++) ev.peer_cert.altsubject[alt] = altsubject[alt]; @@ -1701,7 +1916,33 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) TLS_FAIL_SERVER_CHAIN_PROBE); } - if (preverify_ok && context->event_cb != NULL) +#ifdef OPENSSL_IS_BORINGSSL + if (depth == 0 && (conn->flags & TLS_CONN_REQUEST_OCSP) && + preverify_ok) { + enum ocsp_result res; + + res = check_ocsp_resp(conn->ssl_ctx, conn->ssl, err_cert, + conn->peer_issuer, + conn->peer_issuer_issuer); + if (res == OCSP_REVOKED) { + preverify_ok = 0; + openssl_tls_fail_event(conn, err_cert, err, depth, buf, + "certificate revoked", + TLS_FAIL_REVOKED); + if (err == X509_V_OK) + X509_STORE_CTX_set_error( + x509_ctx, X509_V_ERR_CERT_REVOKED); + } else if (res != OCSP_GOOD && + (conn->flags & TLS_CONN_REQUIRE_OCSP)) { + preverify_ok = 0; + openssl_tls_fail_event(conn, err_cert, err, depth, buf, + "bad certificate status response", + TLS_FAIL_UNSPECIFIED); + } + } +#endif /* OPENSSL_IS_BORINGSSL */ + + if (depth == 0 && preverify_ok && context->event_cb != NULL) context->event_cb(context->cb_ctx, TLS_CERT_CHAIN_SUCCESS, NULL); @@ -1837,30 +2078,40 @@ static int tls_connection_ca_cert(struct tls_data *data, } #ifdef ANDROID + /* Single alias */ if (ca_cert && os_strncmp("keystore://", ca_cert, 11) == 0) { - BIO *bio = BIO_from_keystore(&ca_cert[11]); - STACK_OF(X509_INFO) *stack = NULL; - stack_index_t i; - - if (bio) { - stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL); - BIO_free(bio); - } - if (!stack) + if (tls_add_ca_from_keystore(SSL_CTX_get_cert_store(ssl_ctx), + &ca_cert[11]) < 0) return -1; + SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); + return 0; + } - for (i = 0; i < sk_X509_INFO_num(stack); ++i) { - X509_INFO *info = sk_X509_INFO_value(stack, i); - if (info->x509) { - X509_STORE_add_cert(ssl_ctx->cert_store, - info->x509); - } - if (info->crl) { - X509_STORE_add_crl(ssl_ctx->cert_store, - info->crl); + /* Multiple aliases separated by space */ + if (ca_cert && os_strncmp("keystores://", ca_cert, 12) == 0) { + char *aliases = os_strdup(&ca_cert[12]); + const char *delim = " "; + int rc = 0; + char *savedptr; + char *alias; + + if (!aliases) + return -1; + alias = strtok_r(aliases, delim, &savedptr); + for (; alias; alias = strtok_r(NULL, delim, &savedptr)) { + if (tls_add_ca_from_keystore_encoded( + SSL_CTX_get_cert_store(ssl_ctx), alias)) { + wpa_printf(MSG_WARNING, + "OpenSSL: %s - Failed to add ca_cert %s from keystore", + __func__, alias); + rc = -1; + break; } } - sk_X509_INFO_pop_free(stack, X509_INFO_free); + os_free(aliases); + if (rc) + return rc; + SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); return 0; } @@ -2082,6 +2333,17 @@ static int tls_connection_client_cert(struct tls_connection *conn, if (client_cert == NULL && client_cert_blob == NULL) return 0; +#ifdef PKCS12_FUNCS +#if OPENSSL_VERSION_NUMBER < 0x10002000L + /* + * Clear previously set extra chain certificates, if any, from PKCS#12 + * processing in tls_parse_pkcs12() to allow OpenSSL to build a new + * chain properly. + */ + SSL_CTX_clear_extra_chain_certs(conn->ssl_ctx); +#endif /* OPENSSL_VERSION_NUMBER < 0x10002000L */ +#endif /* PKCS12_FUNCS */ + if (client_cert_blob && SSL_use_certificate_ASN1(conn->ssl, (u8 *) client_cert_blob, client_cert_blob_len) == 1) { @@ -2229,28 +2491,42 @@ static int tls_parse_pkcs12(struct tls_data *data, SSL *ssl, PKCS12 *p12, } if (certs) { -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - SSL_clear_chain_certs(ssl); +#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER) + if (ssl) + SSL_clear_chain_certs(ssl); + else + SSL_CTX_clear_chain_certs(data->ssl); while ((cert = sk_X509_pop(certs)) != NULL) { X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "TLS: additional certificate" " from PKCS12: subject='%s'", buf); - if (SSL_add1_chain_cert(ssl, cert) != 1) { + if ((ssl && SSL_add1_chain_cert(ssl, cert) != 1) || + (!ssl && SSL_CTX_add1_chain_cert(data->ssl, + cert) != 1)) { tls_show_errors(MSG_DEBUG, __func__, "Failed to add additional certificate"); res = -1; + X509_free(cert); break; } + X509_free(cert); } if (!res) { /* Try to continue anyway */ } - sk_X509_free(certs); + sk_X509_pop_free(certs, X509_free); #ifndef OPENSSL_IS_BORINGSSL - res = SSL_build_cert_chain(ssl, - SSL_BUILD_CHAIN_FLAG_CHECK | - SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR); + if (ssl) + res = SSL_build_cert_chain( + ssl, + SSL_BUILD_CHAIN_FLAG_CHECK | + SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR); + else + res = SSL_CTX_build_cert_chain( + data->ssl, + SSL_BUILD_CHAIN_FLAG_CHECK | + SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR); if (!res) { tls_show_errors(MSG_DEBUG, __func__, "Failed to build certificate chain"); @@ -2265,9 +2541,7 @@ static int tls_parse_pkcs12(struct tls_data *data, SSL *ssl, PKCS12 *p12, */ res = 0; #else /* OPENSSL_VERSION_NUMBER >= 0x10002000L */ -#if OPENSSL_VERSION_NUMBER >= 0x10001000L SSL_CTX_clear_extra_chain_certs(data->ssl); -#endif /* OPENSSL_VERSION_NUMBER >= 0x10001000L */ while ((cert = sk_X509_pop(certs)) != NULL) { X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); @@ -2279,11 +2553,12 @@ static int tls_parse_pkcs12(struct tls_data *data, SSL *ssl, PKCS12 *p12, */ if (SSL_CTX_add_extra_chain_cert(data->ssl, cert) != 1) { + X509_free(cert); res = -1; break; } } - sk_X509_free(certs); + sk_X509_pop_free(certs, X509_free); #endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */ } @@ -2463,7 +2738,7 @@ static int tls_connection_engine_ca_cert(struct tls_data *data, static int tls_connection_engine_private_key(struct tls_connection *conn) { -#ifndef OPENSSL_NO_ENGINE +#if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE) if (SSL_use_PrivateKey(conn->ssl, conn->private_key) != 1) { tls_show_errors(MSG_ERROR, __func__, "ENGINE: cannot use private key for TLS"); @@ -2812,16 +3087,6 @@ int tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn, if (conn == NULL || keys == NULL) return -1; ssl = conn->ssl; -#if OPENSSL_VERSION_NUMBER < 0x10100000L - if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL) - return -1; - - os_memset(keys, 0, sizeof(*keys)); - keys->client_random = ssl->s3->client_random; - keys->client_random_len = SSL3_RANDOM_SIZE; - keys->server_random = ssl->s3->server_random; - keys->server_random_len = SSL3_RANDOM_SIZE; -#else if (ssl == NULL) return -1; @@ -2832,16 +3097,15 @@ int tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn, keys->server_random = conn->server_random; keys->server_random_len = SSL_get_server_random( ssl, conn->server_random, sizeof(conn->server_random)); -#endif return 0; } -#ifndef CONFIG_FIPS +#ifdef OPENSSL_NEED_EAP_FAST_PRF static int openssl_get_keyblock_size(SSL *ssl) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) const EVP_CIPHER *c; const EVP_MD *h; int md_size; @@ -2851,17 +3115,11 @@ static int openssl_get_keyblock_size(SSL *ssl) return -1; c = ssl->enc_read_ctx->cipher; -#if OPENSSL_VERSION_NUMBER >= 0x00909000L h = EVP_MD_CTX_md(ssl->read_hash); -#else - h = ssl->read_hash; -#endif if (h) md_size = EVP_MD_size(h); -#if OPENSSL_VERSION_NUMBER >= 0x10000000L else if (ssl->s3) md_size = ssl->s3->tmp.new_mac_secret_size; -#endif else return -1; @@ -2899,86 +3157,24 @@ static int openssl_get_keyblock_size(SSL *ssl) EVP_CIPHER_iv_length(c)); #endif } -#endif /* CONFIG_FIPS */ +#endif /* OPENSSL_NEED_EAP_FAST_PRF */ -static int openssl_tls_prf(struct tls_connection *conn, - const char *label, int server_random_first, - int skip_keyblock, u8 *out, size_t out_len) +int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn, + const char *label, u8 *out, size_t out_len) { -#ifdef CONFIG_FIPS - wpa_printf(MSG_ERROR, "OpenSSL: TLS keys cannot be exported in FIPS " - "mode"); - return -1; -#else /* CONFIG_FIPS */ -#if OPENSSL_VERSION_NUMBER < 0x10100000L - SSL *ssl; - u8 *rnd; - int ret = -1; - int skip = 0; - u8 *tmp_out = NULL; - u8 *_out = out; - const char *ver; - - /* - * TLS library did not support key generation, so get the needed TLS - * session parameters and use an internal implementation of TLS PRF to - * derive the key. - */ - - if (conn == NULL) - return -1; - ssl = conn->ssl; - if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL || - ssl->session->master_key_length <= 0) - return -1; - ver = SSL_get_version(ssl); - - if (skip_keyblock) { - skip = openssl_get_keyblock_size(ssl); - if (skip < 0) - return -1; - tmp_out = os_malloc(skip + out_len); - if (!tmp_out) - return -1; - _out = tmp_out; - } - - rnd = os_malloc(2 * SSL3_RANDOM_SIZE); - if (!rnd) { - os_free(tmp_out); + if (!conn || + SSL_export_keying_material(conn->ssl, out, out_len, label, + os_strlen(label), NULL, 0, 0) != 1) return -1; - } - - if (server_random_first) { - os_memcpy(rnd, ssl->s3->server_random, SSL3_RANDOM_SIZE); - os_memcpy(rnd + SSL3_RANDOM_SIZE, ssl->s3->client_random, - SSL3_RANDOM_SIZE); - } else { - os_memcpy(rnd, ssl->s3->client_random, SSL3_RANDOM_SIZE); - os_memcpy(rnd + SSL3_RANDOM_SIZE, ssl->s3->server_random, - SSL3_RANDOM_SIZE); - } + return 0; +} - if (os_strcmp(ver, "TLSv1.2") == 0) { - tls_prf_sha256(ssl->session->master_key, - ssl->session->master_key_length, - label, rnd, 2 * SSL3_RANDOM_SIZE, - _out, skip + out_len); - ret = 0; - } else if (tls_prf_sha1_md5(ssl->session->master_key, - ssl->session->master_key_length, - label, rnd, 2 * SSL3_RANDOM_SIZE, - _out, skip + out_len) == 0) { - ret = 0; - } - os_free(rnd); - if (ret == 0 && skip_keyblock) - os_memcpy(out, _out + skip, out_len); - bin_clear_free(tmp_out, skip); - return ret; -#else +int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn, + u8 *out, size_t out_len) +{ +#ifdef OPENSSL_NEED_EAP_FAST_PRF SSL *ssl; SSL_SESSION *sess; u8 *rnd; @@ -2993,9 +3189,9 @@ static int openssl_tls_prf(struct tls_connection *conn, const char *ver; /* - * TLS library did not support key generation, so get the needed TLS - * session parameters and use an internal implementation of TLS PRF to - * derive the key. + * TLS library did not support EAP-FAST key generation, so get the + * needed TLS session parameters and use an internal implementation of + * TLS PRF to derive the key. */ if (conn == NULL) @@ -3008,15 +3204,13 @@ static int openssl_tls_prf(struct tls_connection *conn, if (!ver || !sess) return -1; - if (skip_keyblock) { - skip = openssl_get_keyblock_size(ssl); - if (skip < 0) - return -1; - tmp_out = os_malloc(skip + out_len); - if (!tmp_out) - return -1; - _out = tmp_out; - } + skip = openssl_get_keyblock_size(ssl); + if (skip < 0) + return -1; + tmp_out = os_malloc(skip + out_len); + if (!tmp_out) + return -1; + _out = tmp_out; rnd = os_malloc(2 * SSL3_RANDOM_SIZE); if (!rnd) { @@ -3029,59 +3223,31 @@ static int openssl_tls_prf(struct tls_connection *conn, master_key_len = SSL_SESSION_get_master_key(sess, master_key, sizeof(master_key)); - if (server_random_first) { - os_memcpy(rnd, server_random, SSL3_RANDOM_SIZE); - os_memcpy(rnd + SSL3_RANDOM_SIZE, client_random, - SSL3_RANDOM_SIZE); - } else { - os_memcpy(rnd, client_random, SSL3_RANDOM_SIZE); - os_memcpy(rnd + SSL3_RANDOM_SIZE, server_random, - SSL3_RANDOM_SIZE); - } + os_memcpy(rnd, server_random, SSL3_RANDOM_SIZE); + os_memcpy(rnd + SSL3_RANDOM_SIZE, client_random, SSL3_RANDOM_SIZE); if (os_strcmp(ver, "TLSv1.2") == 0) { tls_prf_sha256(master_key, master_key_len, - label, rnd, 2 * SSL3_RANDOM_SIZE, + "key expansion", rnd, 2 * SSL3_RANDOM_SIZE, _out, skip + out_len); ret = 0; } else if (tls_prf_sha1_md5(master_key, master_key_len, - label, rnd, 2 * SSL3_RANDOM_SIZE, + "key expansion", rnd, 2 * SSL3_RANDOM_SIZE, _out, skip + out_len) == 0) { ret = 0; } os_memset(master_key, 0, sizeof(master_key)); os_free(rnd); - if (ret == 0 && skip_keyblock) + if (ret == 0) os_memcpy(out, _out + skip, out_len); bin_clear_free(tmp_out, skip); return ret; -#endif -#endif /* CONFIG_FIPS */ -} - - -int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, - const char *label, int server_random_first, - int skip_keyblock, u8 *out, size_t out_len) -{ -#if OPENSSL_VERSION_NUMBER >= 0x10001000L - SSL *ssl; - if (conn == NULL) - return -1; - if (server_random_first || skip_keyblock) - return openssl_tls_prf(conn, label, - server_random_first, skip_keyblock, - out, out_len); - ssl = conn->ssl; - if (SSL_export_keying_material(ssl, out, out_len, label, - os_strlen(label), NULL, 0, 0) == 1) { - wpa_printf(MSG_DEBUG, "OpenSSL: Using internal PRF"); - return 0; - } -#endif - return openssl_tls_prf(conn, label, server_random_first, - skip_keyblock, out, out_len); +#else /* OPENSSL_NEED_EAP_FAST_PRF */ + wpa_printf(MSG_ERROR, + "OpenSSL: EAP-FAST keys cannot be exported in FIPS mode"); + return -1; +#endif /* OPENSSL_NEED_EAP_FAST_PRF */ } @@ -3340,18 +3506,14 @@ struct wpabuf * tls_connection_decrypt(void *tls_ctx, int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) { -#if OPENSSL_VERSION_NUMBER >= 0x10001000L return conn ? SSL_cache_hit(conn->ssl) : 0; -#else - return conn ? conn->ssl->hit : 0; -#endif } int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, u8 *ciphers) { - char buf[100], *pos, *end; + char buf[500], *pos, *end; u8 *c; int ret; @@ -3379,6 +3541,12 @@ int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, case TLS_CIPHER_ANON_DH_AES128_SHA: suite = "ADH-AES128-SHA"; break; + case TLS_CIPHER_RSA_DHE_AES256_SHA: + suite = "DHE-RSA-AES256-SHA"; + break; + case TLS_CIPHER_AES256_SHA: + suite = "AES256-SHA"; + break; default: wpa_printf(MSG_DEBUG, "TLS: Unsupported " "cipher selection: %d", *c); @@ -3394,7 +3562,7 @@ int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, wpa_printf(MSG_DEBUG, "OpenSSL: cipher suites: %s", buf + 1); -#if OPENSSL_VERSION_NUMBER >= 0x10100000L +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) if (os_strstr(buf, ":ADH-")) { /* @@ -3687,10 +3855,12 @@ static int ocsp_resp_cb(SSL *s, void *arg) wpa_printf(MSG_INFO, "OpenSSL: Could not find current server certificate from OCSP response%s", (conn->flags & TLS_CONN_REQUIRE_OCSP) ? "" : " (OCSP not required)"); + OCSP_CERTID_free(id); OCSP_BASICRESP_free(basic); OCSP_RESPONSE_free(rsp); return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1; } + OCSP_CERTID_free(id); if (!OCSP_check_validity(this_update, next_update, 5 * 60, -1)) { tls_show_errors(MSG_INFO, __func__, @@ -3769,6 +3939,12 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, if (conn == NULL) return -1; + if (params->flags & TLS_CONN_REQUIRE_OCSP_ALL) { + wpa_printf(MSG_INFO, + "OpenSSL: ocsp=3 not supported"); + return -1; + } + /* * If the engine isn't explicitly configured, and any of the * cert/key fields are actually PKCS#11 URIs, then automatically @@ -3879,6 +4055,11 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, tls_set_conn_flags(conn->ssl, params->flags); +#ifdef OPENSSL_IS_BORINGSSL + if (params->flags & TLS_CONN_REQUEST_OCSP) { + SSL_enable_ocsp_stapling(conn->ssl); + } +#else /* OPENSSL_IS_BORINGSSL */ #ifdef HAVE_OCSP if (params->flags & TLS_CONN_REQUEST_OCSP) { SSL_CTX *ssl_ctx = data->ssl; @@ -3897,6 +4078,7 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, "OpenSSL: No OCSP support included - allow optional OCSP case to continue"); } #endif /* HAVE_OCSP */ +#endif /* OPENSSL_IS_BORINGSSL */ conn->flags = params->flags; @@ -3964,7 +4146,7 @@ int tls_global_set_params(void *tls_ctx, * commented out unless explicitly needed for EAP-FAST in order to be able to * build this file with unmodified openssl. */ -#ifdef OPENSSL_IS_BORINGSSL +#if (defined(OPENSSL_IS_BORINGSSL) || OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER) static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, const SSL_CIPHER **cipher, void *arg) @@ -3977,7 +4159,7 @@ static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len, struct tls_connection *conn = arg; int ret; -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) if (conn == NULL || conn->session_ticket_cb == NULL) return 0; @@ -4072,9 +4254,15 @@ int tls_connection_set_session_ticket_cb(void *tls_ctx, int tls_get_library_version(char *buf, size_t buf_len) { +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) + return os_snprintf(buf, buf_len, "OpenSSL build=%s run=%s", + OPENSSL_VERSION_TEXT, + OpenSSL_version(OPENSSL_VERSION)); +#else return os_snprintf(buf, buf_len, "OpenSSL build=%s run=%s", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION)); +#endif } |
