diff options
Diffstat (limited to 'src/crypto/tls_wolfssl.c')
-rw-r--r-- | src/crypto/tls_wolfssl.c | 256 |
1 files changed, 173 insertions, 83 deletions
diff --git a/src/crypto/tls_wolfssl.c b/src/crypto/tls_wolfssl.c index cf482bfc..b4f1bbe7 100644 --- a/src/crypto/tls_wolfssl.c +++ b/src/crypto/tls_wolfssl.c @@ -26,6 +26,10 @@ #include <wolfssl/wolfcrypt/aes.h> #endif +#ifdef CONFIG_FIPS +#include <wolfssl/wolfcrypt/fips_test.h> +#endif /* CONFIG_FIPS */ + #if !defined(CONFIG_FIPS) && \ (defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || \ defined(EAP_SERVER_FAST)) @@ -58,6 +62,7 @@ struct tls_context { void *cb_ctx; int cert_in_cb; char *ocsp_stapling_response; + unsigned int tls_session_lifetime; }; static struct tls_context *tls_global = NULL; @@ -94,6 +99,7 @@ struct tls_connection { WOLFSSL_X509 *peer_cert; WOLFSSL_X509 *peer_issuer; WOLFSSL_X509 *peer_issuer_issuer; + char *peer_subject; /* peer subject info for authenticated peer */ }; @@ -190,6 +196,33 @@ static void remove_session_cb(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *sess) } +#if defined(CONFIG_FIPS) && defined(HAVE_FIPS) +static void wcFipsCb(int ok, int err, const char *hash) +{ + wpa_printf(MSG_INFO, + "wolfFIPS: wolfCrypt Fips error callback, ok = %d, err = %d", + ok, err); + wpa_printf(MSG_INFO, "wolfFIPS: message = %s", wc_GetErrorString(err)); + wpa_printf(MSG_INFO, "wolfFIPS: hash = %s", hash); + if (err == IN_CORE_FIPS_E) { + wpa_printf(MSG_ERROR, + "wolfFIPS: In core integrity hash check failure, copy above hash"); + wpa_printf(MSG_ERROR, "wolfFIPS: into verifyCore[] in fips_test.c and rebuild"); + } +} +#endif /* CONFIG_FIPS && HAVE_FIPS */ + + +#ifdef DEBUG_WOLFSSL +static void wolfSSL_logging_cb(const int log_level, + const char * const log_message) +{ + (void) log_level; + wpa_printf(MSG_DEBUG, "wolfSSL log:%s", log_message); +} +#endif /* DEBUG_WOLFSSL */ + + void * tls_init(const struct tls_config *conf) { WOLFSSL_CTX *ssl_ctx; @@ -197,6 +230,7 @@ void * tls_init(const struct tls_config *conf) const char *ciphers; #ifdef DEBUG_WOLFSSL + wolfSSL_SetLoggingCb(wolfSSL_logging_cb); wolfSSL_Debugging_ON(); #endif /* DEBUG_WOLFSSL */ @@ -209,7 +243,9 @@ void * tls_init(const struct tls_config *conf) if (wolfSSL_Init() < 0) return NULL; - /* wolfSSL_Debugging_ON(); */ +#if defined(CONFIG_FIPS) && defined(HAVE_FIPS) + wolfCrypt_SetCb_fips(wcFipsCb); +#endif /* CONFIG_FIPS && HAVE_FIPS */ } tls_ref_count++; @@ -227,17 +263,21 @@ void * tls_init(const struct tls_config *conf) } wolfSSL_SetIORecv(ssl_ctx, wolfssl_receive_cb); wolfSSL_SetIOSend(ssl_ctx, wolfssl_send_cb); + context->tls_session_lifetime = conf->tls_session_lifetime; wolfSSL_CTX_set_ex_data(ssl_ctx, 0, context); if (conf->tls_session_lifetime > 0) { + wolfSSL_CTX_set_session_id_context(ssl_ctx, + (const unsigned char *) + "hostapd", 7); wolfSSL_CTX_set_quiet_shutdown(ssl_ctx, 1); wolfSSL_CTX_set_session_cache_mode(ssl_ctx, - SSL_SESS_CACHE_SERVER); + WOLFSSL_SESS_CACHE_SERVER); wolfSSL_CTX_set_timeout(ssl_ctx, conf->tls_session_lifetime); wolfSSL_CTX_sess_set_remove_cb(ssl_ctx, remove_session_cb); } else { wolfSSL_CTX_set_session_cache_mode(ssl_ctx, - SSL_SESS_CACHE_CLIENT); + WOLFSSL_SESS_CACHE_OFF); } if (conf && conf->openssl_ciphers) @@ -336,6 +376,7 @@ void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) os_free(conn->alt_subject_match); os_free(conn->suffix_match); os_free(conn->domain_match); + os_free(conn->peer_subject); /* self */ os_free(conn); @@ -369,10 +410,13 @@ int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) wolfSSL_set_quiet_shutdown(conn->ssl, 1); wolfSSL_shutdown(conn->ssl); - session = wolfSSL_get_session(conn->ssl); - if (wolfSSL_clear(conn->ssl) != 1) + session = wolfSSL_get1_session(conn->ssl); + if (wolfSSL_clear(conn->ssl) != 1) { + wolfSSL_SESSION_free(session); return -1; + } wolfSSL_set_session(conn->ssl, session); + wolfSSL_SESSION_free(session); return 0; } @@ -420,44 +464,6 @@ static int tls_connection_set_subject_match(struct tls_connection *conn, } -static int tls_connection_dh(struct tls_connection *conn, const char *dh_file, - const u8 *dh_blob, size_t blob_len) -{ - if (!dh_file && !dh_blob) - return 0; - - wolfSSL_set_accept_state(conn->ssl); - - if (dh_blob) { - if (wolfSSL_SetTmpDH_buffer(conn->ssl, dh_blob, blob_len, - SSL_FILETYPE_ASN1) < 0) { - wpa_printf(MSG_INFO, "SSL: use DH DER blob failed"); - return -1; - } - wpa_printf(MSG_DEBUG, "SSL: use DH blob OK"); - return 0; - } - - if (dh_file) { - wpa_printf(MSG_INFO, "SSL: use DH PEM file: %s", dh_file); - if (wolfSSL_SetTmpDH_file(conn->ssl, dh_file, - SSL_FILETYPE_PEM) < 0) { - wpa_printf(MSG_INFO, "SSL: use DH PEM file failed"); - if (wolfSSL_SetTmpDH_file(conn->ssl, dh_file, - SSL_FILETYPE_ASN1) < 0) { - wpa_printf(MSG_INFO, - "SSL: use DH DER file failed"); - return -1; - } - } - wpa_printf(MSG_DEBUG, "SSL: use DH file OK"); - return 0; - } - - return 0; -} - - static int tls_connection_client_cert(struct tls_connection *conn, const char *client_cert, const u8 *client_cert_blob, @@ -472,7 +478,13 @@ static int tls_connection_client_cert(struct tls_connection *conn, SSL_FILETYPE_ASN1) != SSL_SUCCESS) { wpa_printf(MSG_INFO, "SSL: use client cert DER blob failed"); - return -1; + if (wolfSSL_use_certificate_chain_buffer_format( + conn->ssl, client_cert_blob, blob_len, + SSL_FILETYPE_PEM) != SSL_SUCCESS) { + wpa_printf(MSG_INFO, + "SSL: use client cert PEM blob failed"); + return -1; + } } wpa_printf(MSG_DEBUG, "SSL: use client cert blob OK"); return 0; @@ -534,23 +546,35 @@ static int tls_connection_private_key(void *tls_ctx, if (private_key_blob) { if (wolfSSL_use_PrivateKey_buffer(conn->ssl, private_key_blob, blob_len, - SSL_FILETYPE_ASN1) <= 0) { + SSL_FILETYPE_ASN1) != + SSL_SUCCESS) { wpa_printf(MSG_INFO, "SSL: use private DER blob failed"); + if (wolfSSL_use_PrivateKey_buffer( + conn->ssl, + private_key_blob, blob_len, + SSL_FILETYPE_PEM) != SSL_SUCCESS) { + wpa_printf(MSG_INFO, + "SSL: use private PEM blob failed"); + } else { + ok = 1; + } } else { - wpa_printf(MSG_DEBUG, "SSL: use private key blob OK"); ok = 1; } + if (ok) + wpa_printf(MSG_DEBUG, "SSL: use private key blob OK"); } if (!ok && private_key) { if (wolfSSL_use_PrivateKey_file(conn->ssl, private_key, - SSL_FILETYPE_PEM) <= 0) { + SSL_FILETYPE_PEM) != + SSL_SUCCESS) { wpa_printf(MSG_INFO, "SSL: use private key PEM file failed"); if (wolfSSL_use_PrivateKey_file(conn->ssl, private_key, - SSL_FILETYPE_ASN1) <= 0) - { + SSL_FILETYPE_ASN1) != + SSL_SUCCESS) { wpa_printf(MSG_INFO, "SSL: use private key DER file failed"); } else { @@ -721,8 +745,7 @@ static int tls_match_suffix_helper(WOLFSSL_X509 *cert, const char *match, WOLFSSL_X509_NAME_ENTRY *e; WOLFSSL_ASN1_STRING *cn; - i = wolfSSL_X509_NAME_get_index_by_NID(name, ASN_COMMON_NAME, - i); + i = wolfSSL_X509_NAME_get_index_by_NID(name, NID_commonName, i); if (i == -1) break; e = wolfSSL_X509_NAME_get_entry(name, i); @@ -1134,6 +1157,11 @@ static int tls_verify_cb(int preverify_ok, WOLFSSL_X509_STORE_CTX *x509_ctx) context->event_cb(context->cb_ctx, TLS_CERT_CHAIN_SUCCESS, NULL); + if (depth == 0 && preverify_ok) { + os_free(conn->peer_subject); + conn->peer_subject = os_strdup(buf); + } + return preverify_ok; } @@ -1194,8 +1222,14 @@ static int tls_connection_ca_cert(void *tls_ctx, struct tls_connection *conn, if (wolfSSL_CTX_load_verify_buffer(ctx, ca_cert_blob, blob_len, SSL_FILETYPE_ASN1) != SSL_SUCCESS) { - wpa_printf(MSG_INFO, "SSL: failed to load CA blob"); - return -1; + wpa_printf(MSG_INFO, "SSL: failed to load DER CA blob"); + if (wolfSSL_CTX_load_verify_buffer( + ctx, ca_cert_blob, blob_len, + SSL_FILETYPE_PEM) != SSL_SUCCESS) { + wpa_printf(MSG_INFO, + "SSL: failed to load PEM CA blob"); + return -1; + } } wpa_printf(MSG_DEBUG, "SSL: use CA cert blob OK"); return 0; @@ -1238,10 +1272,8 @@ static int tls_connection_ca_cert(void *tls_ctx, struct tls_connection *conn, static void tls_set_conn_flags(WOLFSSL *ssl, unsigned int flags) { #ifdef HAVE_SESSION_TICKET -#if 0 if (!(flags & TLS_CONN_DISABLE_SESSION_TICKET)) wolfSSL_UseSessionTicket(ssl); -#endif #endif /* HAVE_SESSION_TICKET */ if (flags & TLS_CONN_DISABLE_TLSv1_0) @@ -1250,6 +1282,8 @@ static void tls_set_conn_flags(WOLFSSL *ssl, unsigned int flags) wolfSSL_set_options(ssl, SSL_OP_NO_TLSv1_1); if (flags & TLS_CONN_DISABLE_TLSv1_2) wolfSSL_set_options(ssl, SSL_OP_NO_TLSv1_2); + if (flags & TLS_CONN_DISABLE_TLSv1_3) + wolfSSL_set_options(ssl, SSL_OP_NO_TLSv1_3); } @@ -1289,12 +1323,6 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, return -1; } - if (tls_connection_dh(conn, params->dh_file, params->dh_blob, - params->dh_blob_len) < 0) { - wpa_printf(MSG_INFO, "Error setting DH"); - return -1; - } - if (params->openssl_ciphers && wolfSSL_set_cipher_list(conn->ssl, params->openssl_ciphers) != 1) { wpa_printf(MSG_INFO, @@ -1311,7 +1339,8 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, WOLFSSL_CSR_OCSP_USE_NONCE) != SSL_SUCCESS) return -1; - wolfSSL_CTX_EnableOCSP(tls_ctx, 0); + if (wolfSSL_EnableOCSPStapling(conn->ssl) != SSL_SUCCESS) + return -1; } #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 @@ -1320,7 +1349,8 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, WOLFSSL_CSR2_OCSP_MULTI, 0) != SSL_SUCCESS) return -1; - wolfSSL_CTX_EnableOCSP(tls_ctx, 0); + if (wolfSSL_EnableOCSPStapling(conn->ssl) != SSL_SUCCESS) + return -1; } #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ #if !defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \ @@ -1427,25 +1457,10 @@ static int tls_global_private_key(void *ssl_ctx, const char *private_key, } -static int tls_global_dh(void *ssl_ctx, const char *dh_file, - const u8 *dh_blob, size_t blob_len) +static int tls_global_dh(void *ssl_ctx, const char *dh_file) { WOLFSSL_CTX *ctx = ssl_ctx; - if (!dh_file && !dh_blob) - return 0; - - if (dh_blob) { - if (wolfSSL_CTX_SetTmpDH_buffer(ctx, dh_blob, blob_len, - SSL_FILETYPE_ASN1) < 0) { - wpa_printf(MSG_INFO, - "SSL: global use DH DER blob failed"); - return -1; - } - wpa_printf(MSG_DEBUG, "SSL: global use DH blob OK"); - return 0; - } - if (dh_file) { if (wolfSSL_CTX_SetTmpDH_file(ctx, dh_file, SSL_FILETYPE_PEM) < 0) { @@ -1532,8 +1547,7 @@ int tls_global_set_params(void *tls_ctx, return -1; } - if (tls_global_dh(tls_ctx, params->dh_file, params->dh_blob, - params->dh_blob_len) < 0) { + if (tls_global_dh(tls_ctx, params->dh_file) < 0) { wpa_printf(MSG_INFO, "SSL: Failed to load DH file '%s'", params->dh_file); return -1; @@ -1590,6 +1604,9 @@ int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, int verify_peer, unsigned int flags, const u8 *session_ctx, size_t session_ctx_len) { + static int counter = 0; + struct tls_context *context; + if (!conn) return -1; @@ -1607,6 +1624,22 @@ int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, wolfSSL_set_accept_state(conn->ssl); + context = wolfSSL_CTX_get_ex_data((WOLFSSL_CTX *) ssl_ctx, 0); + if (context && context->tls_session_lifetime == 0) { + /* + * Set session id context to a unique value to make sure + * session resumption cannot be used either through session + * caching or TLS ticket extension. + */ + counter++; + wolfSSL_set_session_id_context(conn->ssl, + (const unsigned char *) &counter, + sizeof(counter)); + } else { + wolfSSL_set_session_id_context(conn->ssl, session_ctx, + session_ctx_len); + } + /* TODO: do we need to fake a session like OpenSSL does here? */ return 0; @@ -1997,11 +2030,21 @@ int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn, const char *label, const u8 *context, size_t context_len, u8 *out, size_t out_len) { - if (context) + if (!conn) return -1; - if (!conn || wolfSSL_make_eap_keys(conn->ssl, out, out_len, label) != 0) +#if LIBWOLFSSL_VERSION_HEX >= 0x04007000 + if (wolfSSL_export_keying_material(conn->ssl, out, out_len, + label, os_strlen(label), + context, context_len, + context != NULL) != WOLFSSL_SUCCESS) return -1; return 0; +#else + if (context || + wolfSSL_make_eap_keys(conn->ssl, out, out_len, label) != 0) + return -1; +#endif + return 0; } @@ -2046,9 +2089,15 @@ int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn, _out, skip + out_len); ret = 0; } else { +#ifdef CONFIG_FIPS + wpa_printf(MSG_ERROR, + "wolfSSL: Can't use sha1_md5 in FIPS build"); + ret = -1; +#else /* CONFIG_FIPS */ ret = tls_prf_sha1_md5(master_key, master_key_len, "key expansion", seed, sizeof(seed), _out, skip + out_len); +#endif /* CONFIG_FIPS */ } forced_memzero(master_key, master_key_len); @@ -2160,6 +2209,39 @@ void tls_connection_remove_session(struct tls_connection *conn) } +int tls_get_tls_unique(struct tls_connection *conn, u8 *buf, size_t max_len) +{ + size_t len; + int reused; + + reused = wolfSSL_session_reused(conn->ssl); + if ((wolfSSL_is_server(conn->ssl) && !reused) || + (!wolfSSL_is_server(conn->ssl) && reused)) + len = wolfSSL_get_peer_finished(conn->ssl, buf, max_len); + else + len = wolfSSL_get_finished(conn->ssl, buf, max_len); + + if (len == 0 || len > max_len) + return -1; + + return len; +} + + +u16 tls_connection_get_cipher_suite(struct tls_connection *conn) +{ + return (u16) wolfSSL_get_current_cipher_suite(conn->ssl); +} + + +const char * tls_connection_get_peer_subject(struct tls_connection *conn) +{ + if (conn) + return conn->peer_subject; + return NULL; +} + + void tls_connection_set_success_data(struct tls_connection *conn, struct wpabuf *data) { @@ -2206,3 +2288,11 @@ tls_connection_get_success_data(struct tls_connection *conn) return NULL; return wolfSSL_SESSION_get_ex_data(sess, tls_ex_idx_session); } + + +bool tls_connection_get_own_cert_used(struct tls_connection *conn) +{ + if (conn) + return wolfSSL_get_certificate(conn->ssl) != NULL; + return false; +} |