OpenSSL: Allow two server certificates/keys to be configured on server

hostapd EAP server can now be configured with two separate server
certificates/keys to enable parallel operations using 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.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2019-07-12 18:11:53 +03:00
parent 857edf4bf4
commit e2722bf81d
7 changed files with 43 additions and 1 deletions

View file

@ -2589,12 +2589,21 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "server_cert") == 0) { } else if (os_strcmp(buf, "server_cert") == 0) {
os_free(bss->server_cert); os_free(bss->server_cert);
bss->server_cert = os_strdup(pos); 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) { } else if (os_strcmp(buf, "private_key") == 0) {
os_free(bss->private_key); os_free(bss->private_key);
bss->private_key = os_strdup(pos); 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) { } else if (os_strcmp(buf, "private_key_passwd") == 0) {
os_free(bss->private_key_passwd); os_free(bss->private_key_passwd);
bss->private_key_passwd = os_strdup(pos); 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) { } else if (os_strcmp(buf, "check_cert_subject") == 0) {
if (!pos[0]) { if (!pos[0]) {
wpa_printf(MSG_ERROR, "Line %d: unknown check_cert_subject '%s'", wpa_printf(MSG_ERROR, "Line %d: unknown check_cert_subject '%s'",

View file

@ -977,6 +977,23 @@ eap_server=0
# Passphrase for private key # Passphrase for private key
#private_key_passwd=secret passphrase #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 # Server identity
# EAP methods that provide mechanism for authenticated server identity delivery # EAP methods that provide mechanism for authenticated server identity delivery
# use this value. If not set, "hostapd" is used as a default. # use this value. If not set, "hostapd" is used as a default.

View file

@ -629,8 +629,11 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
os_free(conf->ctrl_interface); os_free(conf->ctrl_interface);
os_free(conf->ca_cert); os_free(conf->ca_cert);
os_free(conf->server_cert); os_free(conf->server_cert);
os_free(conf->server_cert2);
os_free(conf->private_key); os_free(conf->private_key);
os_free(conf->private_key2);
os_free(conf->private_key_passwd); os_free(conf->private_key_passwd);
os_free(conf->private_key_passwd2);
os_free(conf->check_cert_subject); os_free(conf->check_cert_subject);
os_free(conf->ocsp_stapling_response); os_free(conf->ocsp_stapling_response);
os_free(conf->ocsp_stapling_response_multi); os_free(conf->ocsp_stapling_response_multi);

View file

@ -403,8 +403,11 @@ struct hostapd_bss_config {
char *ca_cert; char *ca_cert;
char *server_cert; char *server_cert;
char *server_cert2;
char *private_key; char *private_key;
char *private_key2;
char *private_key_passwd; char *private_key_passwd;
char *private_key_passwd2;
char *check_cert_subject; char *check_cert_subject;
int check_crl; int check_crl;
int check_crl_strict; int check_crl_strict;

View file

@ -197,7 +197,8 @@ int authsrv_init(struct hostapd_data *hapd)
#ifdef EAP_TLS_FUNCS #ifdef EAP_TLS_FUNCS
if (hapd->conf->eap_server && if (hapd->conf->eap_server &&
(hapd->conf->ca_cert || hapd->conf->server_cert || (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_config conf;
struct tls_connection_params params; struct tls_connection_params params;
@ -226,8 +227,11 @@ int authsrv_init(struct hostapd_data *hapd)
os_memset(&params, 0, sizeof(params)); os_memset(&params, 0, sizeof(params));
params.ca_cert = hapd->conf->ca_cert; params.ca_cert = hapd->conf->ca_cert;
params.client_cert = hapd->conf->server_cert; params.client_cert = hapd->conf->server_cert;
params.client_cert2 = hapd->conf->server_cert2;
params.private_key = hapd->conf->private_key; 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_passwd = hapd->conf->private_key_passwd;
params.private_key_passwd2 = hapd->conf->private_key_passwd2;
params.dh_file = hapd->conf->dh_file; params.dh_file = hapd->conf->dh_file;
params.openssl_ciphers = hapd->conf->openssl_ciphers; params.openssl_ciphers = hapd->conf->openssl_ciphers;
params.openssl_ecdh_curves = hapd->conf->openssl_ecdh_curves; params.openssl_ecdh_curves = hapd->conf->openssl_ecdh_curves;

View file

@ -188,12 +188,15 @@ struct tls_connection_params {
const char *suffix_match; const char *suffix_match;
const char *domain_match; const char *domain_match;
const char *client_cert; const char *client_cert;
const char *client_cert2;
const u8 *client_cert_blob; const u8 *client_cert_blob;
size_t client_cert_blob_len; size_t client_cert_blob_len;
const char *private_key; const char *private_key;
const char *private_key2;
const u8 *private_key_blob; const u8 *private_key_blob;
size_t private_key_blob_len; size_t private_key_blob_len;
const char *private_key_passwd; const char *private_key_passwd;
const char *private_key_passwd2;
const char *dh_file; const char *dh_file;
const u8 *dh_blob; const u8 *dh_blob;
size_t dh_blob_len; size_t dh_blob_len;

View file

@ -5228,6 +5228,9 @@ int tls_global_set_params(void *tls_ctx,
tls_global_client_cert(data, params->client_cert) || tls_global_client_cert(data, params->client_cert) ||
tls_global_private_key(data, params->private_key, tls_global_private_key(data, params->private_key,
params->private_key_passwd) || 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)) { tls_global_dh(data, params->dh_file)) {
wpa_printf(MSG_INFO, "TLS: Failed to set global parameters"); wpa_printf(MSG_INFO, "TLS: Failed to set global parameters");
return -1; return -1;