diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 3a294386f..df41f1424 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2589,12 +2589,21 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "server_cert") == 0) { os_free(bss->server_cert); bss->server_cert = os_strdup(pos); + } else if (os_strcmp(buf, "server_cert2") == 0) { + os_free(bss->server_cert2); + bss->server_cert2 = os_strdup(pos); } else if (os_strcmp(buf, "private_key") == 0) { os_free(bss->private_key); bss->private_key = os_strdup(pos); + } else if (os_strcmp(buf, "private_key2") == 0) { + os_free(bss->private_key2); + bss->private_key2 = os_strdup(pos); } else if (os_strcmp(buf, "private_key_passwd") == 0) { os_free(bss->private_key_passwd); bss->private_key_passwd = os_strdup(pos); + } else if (os_strcmp(buf, "private_key_passwd2") == 0) { + os_free(bss->private_key_passwd2); + bss->private_key_passwd2 = os_strdup(pos); } else if (os_strcmp(buf, "check_cert_subject") == 0) { if (!pos[0]) { wpa_printf(MSG_ERROR, "Line %d: unknown check_cert_subject '%s'", diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index d67a40573..f2d587388 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -977,6 +977,23 @@ eap_server=0 # Passphrase for private key #private_key_passwd=secret passphrase +# An alternative server certificate and private key can be configured with the +# following parameters (with values just like the parameters above without the +# '2' suffix). The ca_cert file (in PEM encoding) is used to add the trust roots +# for both server certificates and/or client certificates). +# +# The main use case for this alternative server certificate configuration is to +# enable both RSA and ECC public keys. The server will pick which one to use +# based on the client preferences for the cipher suite (in the TLS ClientHello +# message). It should be noted that number of deployed EAP peer implementations +# do not filter out the cipher suite list based on their local configuration and +# as such, configuration of alternative types of certificates on the server may +# result in interoperability issues. +#server_cert2=/etc/hostapd.server-ecc.pem +#private_key2=/etc/hostapd.server-ecc.prv +#private_key_passwd2=secret passphrase + + # Server identity # EAP methods that provide mechanism for authenticated server identity delivery # use this value. If not set, "hostapd" is used as a default. diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 6a2deb6de..a061bd863 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -629,8 +629,11 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf) os_free(conf->ctrl_interface); os_free(conf->ca_cert); os_free(conf->server_cert); + os_free(conf->server_cert2); os_free(conf->private_key); + os_free(conf->private_key2); os_free(conf->private_key_passwd); + os_free(conf->private_key_passwd2); os_free(conf->check_cert_subject); os_free(conf->ocsp_stapling_response); os_free(conf->ocsp_stapling_response_multi); diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index b1007622c..eebf8981d 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -403,8 +403,11 @@ struct hostapd_bss_config { char *ca_cert; char *server_cert; + char *server_cert2; char *private_key; + char *private_key2; char *private_key_passwd; + char *private_key_passwd2; char *check_cert_subject; int check_crl; int check_crl_strict; diff --git a/src/ap/authsrv.c b/src/ap/authsrv.c index 3dd6b7bee..b3d910742 100644 --- a/src/ap/authsrv.c +++ b/src/ap/authsrv.c @@ -197,7 +197,8 @@ int authsrv_init(struct hostapd_data *hapd) #ifdef EAP_TLS_FUNCS if (hapd->conf->eap_server && (hapd->conf->ca_cert || hapd->conf->server_cert || - hapd->conf->private_key || hapd->conf->dh_file)) { + hapd->conf->private_key || hapd->conf->dh_file || + hapd->conf->server_cert2 || hapd->conf->private_key2)) { struct tls_config conf; struct tls_connection_params params; @@ -226,8 +227,11 @@ int authsrv_init(struct hostapd_data *hapd) os_memset(¶ms, 0, sizeof(params)); params.ca_cert = hapd->conf->ca_cert; params.client_cert = hapd->conf->server_cert; + params.client_cert2 = hapd->conf->server_cert2; params.private_key = hapd->conf->private_key; + params.private_key2 = hapd->conf->private_key2; params.private_key_passwd = hapd->conf->private_key_passwd; + params.private_key_passwd2 = hapd->conf->private_key_passwd2; params.dh_file = hapd->conf->dh_file; params.openssl_ciphers = hapd->conf->openssl_ciphers; params.openssl_ecdh_curves = hapd->conf->openssl_ecdh_curves; diff --git a/src/crypto/tls.h b/src/crypto/tls.h index a9ba7d11a..c8b1a824e 100644 --- a/src/crypto/tls.h +++ b/src/crypto/tls.h @@ -188,12 +188,15 @@ struct tls_connection_params { const char *suffix_match; const char *domain_match; const char *client_cert; + const char *client_cert2; const u8 *client_cert_blob; size_t client_cert_blob_len; const char *private_key; + const char *private_key2; const u8 *private_key_blob; size_t private_key_blob_len; const char *private_key_passwd; + const char *private_key_passwd2; const char *dh_file; const u8 *dh_blob; size_t dh_blob_len; diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c index 48b48e9bc..d45543e66 100644 --- a/src/crypto/tls_openssl.c +++ b/src/crypto/tls_openssl.c @@ -5228,6 +5228,9 @@ int tls_global_set_params(void *tls_ctx, tls_global_client_cert(data, params->client_cert) || tls_global_private_key(data, params->private_key, params->private_key_passwd) || + tls_global_client_cert(data, params->client_cert2) || + tls_global_private_key(data, params->private_key2, + params->private_key_passwd2) || tls_global_dh(data, params->dh_file)) { wpa_printf(MSG_INFO, "TLS: Failed to set global parameters"); return -1;