crl_reload_interval: Add CRL reloading support

This patch adds a new flag 'crl_reload_interval' to reload CRL
periodically. This can be used to reload ca_cert file and the included
CRL information on every new TLS session if difference between the last
reload and the current time in seconds is greater than
crl_reload_interval.

This reloading is used for cases where check_crl is 1 or 2 and the CRL
is included in the ca_file.

Signed-off-by: Paresh Chaudhary <paresh.chaudhary@rockwellcollins.com>
Signed-off-by: Jared Bents <jared.bents@rockwellcollins.com>
This commit is contained in:
Jared Bents 2019-01-16 09:15:01 -06:00 committed by Jouni Malinen
parent 0eb34f8f28
commit 159a7fbdea
6 changed files with 90 additions and 2 deletions

View file

@ -2505,6 +2505,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->check_crl = atoi(pos);
} else if (os_strcmp(buf, "check_crl_strict") == 0) {
bss->check_crl_strict = atoi(pos);
} else if (os_strcmp(buf, "crl_reload_interval") == 0) {
bss->crl_reload_interval = atoi(pos);
} else if (os_strcmp(buf, "tls_session_lifetime") == 0) {
bss->tls_session_lifetime = atoi(pos);
} else if (os_strcmp(buf, "tls_flags") == 0) {

View file

@ -922,7 +922,8 @@ eap_server=0
# valid CRL signed by the CA is required to be included in the ca_cert file.
# This can be done by using PEM format for CA certificate and CRL and
# concatenating these into one file. Whenever CRL changes, hostapd needs to be
# restarted to take the new CRL into use.
# restarted to take the new CRL into use. Alternatively, crl_reload_interval can
# be used to configure periodic updating of the loaded CRL information.
# 0 = do not verify CRLs (default)
# 1 = check the CRL of the user certificate
# 2 = check all CRLs in the certificate path
@ -935,6 +936,16 @@ eap_server=0
# 1 = do not ignore errors (default)
#check_crl_strict=1
# CRL reload interval in seconds
# This can be used to reload ca_cert file and the included CRL on every new TLS
# session if difference between last reload and the current reload time in
# seconds is greater than crl_reload_interval.
# Note: If interval time is very short, CPU overhead may be negatively affected
# and it is advised to not go below 300 seconds.
# This is applicable only with check_crl values 1 and 2.
# 0 = do not reload CRLs (default)
# crl_reload_interval = 300
# TLS Session Lifetime in seconds
# This can be used to allow TLS sessions to be cached and resumed with an
# abbreviated handshake when using EAP-TLS/TTLS/PEAP.

View file

@ -392,6 +392,7 @@ struct hostapd_bss_config {
char *private_key_passwd;
int check_crl;
int check_crl_strict;
unsigned int crl_reload_interval;
unsigned int tls_session_lifetime;
unsigned int tls_flags;
char *ocsp_stapling_response;

View file

@ -201,6 +201,16 @@ int authsrv_init(struct hostapd_data *hapd)
os_memset(&conf, 0, sizeof(conf));
conf.tls_session_lifetime = hapd->conf->tls_session_lifetime;
if (hapd->conf->crl_reload_interval > 0 &&
hapd->conf->check_crl <= 0) {
wpa_printf(MSG_INFO,
"Cannot enable CRL reload functionality - it depends on check_crl being set");
} else if (hapd->conf->crl_reload_interval > 0) {
conf.crl_reload_interval =
hapd->conf->crl_reload_interval;
wpa_printf(MSG_INFO,
"Enabled CRL reload functionality");
}
conf.tls_flags = hapd->conf->tls_flags;
conf.event_cb = authsrv_tls_event;
conf.cb_ctx = hapd;

View file

@ -82,6 +82,7 @@ struct tls_config {
int cert_in_cb;
const char *openssl_ciphers;
unsigned int tls_session_lifetime;
unsigned int crl_reload_interval;
unsigned int tls_flags;
void (*event_cb)(void *ctx, enum tls_event ev,

View file

@ -214,7 +214,11 @@ static struct tls_context *tls_global = NULL;
struct tls_data {
SSL_CTX *ssl;
unsigned int tls_session_lifetime;
int check_crl;
int check_crl_strict;
char *ca_cert;
unsigned int crl_reload_interval;
struct os_reltime crl_last_reload;
};
struct tls_connection {
@ -305,6 +309,37 @@ static void tls_show_errors(int level, const char *func, const char *txt)
#endif /* CONFIG_NO_STDOUT_DEBUG */
static X509_STORE * tls_crl_cert_reload(const char *ca_cert, int check_crl)
{
int flags;
X509_STORE *store;
store = X509_STORE_new();
if (!store) {
wpa_printf(MSG_DEBUG,
"OpenSSL: %s - failed to allocate new certificate store",
__func__);
return NULL;
}
if (ca_cert && X509_STORE_load_locations(store, ca_cert, NULL) != 1) {
tls_show_errors(MSG_WARNING, __func__,
"Failed to load root certificates");
X509_STORE_free(store);
return NULL;
}
if (check_crl)
flags = X509_V_FLAG_CRL_CHECK;
if (check_crl == 2)
flags |= X509_V_FLAG_CRL_CHECK_ALL;
X509_STORE_set_flags(store, flags);
return store;
}
#ifdef CONFIG_NATIVE_WINDOWS
/* Windows CryptoAPI and access to certificate stores */
@ -993,8 +1028,10 @@ void * tls_init(const struct tls_config *conf)
return NULL;
}
data->ssl = ssl;
if (conf)
if (conf) {
data->tls_session_lifetime = conf->tls_session_lifetime;
data->crl_reload_interval = conf->crl_reload_interval;
}
SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv2);
SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv3);
@ -1076,6 +1113,7 @@ void tls_deinit(void *ssl_ctx)
os_free(context);
if (data->tls_session_lifetime > 0)
SSL_CTX_flush_sessions(ssl, 0);
os_free(data->ca_cert);
SSL_CTX_free(ssl);
tls_openssl_ref_count--;
@ -1471,8 +1509,28 @@ struct tls_connection * tls_connection_init(void *ssl_ctx)
SSL_CTX *ssl = data->ssl;
struct tls_connection *conn;
long options;
X509_STORE *new_cert_store;
struct os_reltime now;
struct tls_context *context = SSL_CTX_get_app_data(ssl);
/* Replace X509 store if it is time to update CRL. */
if (data->crl_reload_interval > 0 && os_get_reltime(&now) == 0 &&
os_reltime_expired(&now, &data->crl_last_reload,
data->crl_reload_interval)) {
wpa_printf(MSG_INFO,
"OpenSSL: Flushing X509 store with ca_cert file");
new_cert_store = tls_crl_cert_reload(data->ca_cert,
data->check_crl);
if (!new_cert_store) {
wpa_printf(MSG_ERROR,
"OpenSSL: Error replacing X509 store with ca_cert file");
} else {
/* Replace old store */
SSL_CTX_set_cert_store(ssl, new_cert_store);
data->crl_last_reload = now;
}
}
conn = os_zalloc(sizeof(*conn));
if (conn == NULL)
return NULL;
@ -2393,6 +2451,9 @@ static int tls_global_ca_cert(struct tls_data *data, const char *ca_cert)
SSL_CTX_set_client_CA_list(ssl_ctx,
SSL_load_client_CA_file(ca_cert));
#endif /* OPENSSL_NO_STDIO */
os_free(data->ca_cert);
data->ca_cert = os_strdup(ca_cert);
}
return 0;
@ -2417,7 +2478,9 @@ int tls_global_set_verify(void *ssl_ctx, int check_crl, int strict)
flags |= X509_V_FLAG_CRL_CHECK_ALL;
X509_STORE_set_flags(cs, flags);
data->check_crl = check_crl;
data->check_crl_strict = strict;
os_get_reltime(&data->crl_last_reload);
}
return 0;
}