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

@ -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;
}