From: Jared Bents <jared.bents@xxxxxxxxxxxxxxxxxxx> This patch has been added new flag 'crl_reload_interval' to reload crl. This can be used to reload ca_cert file on every new tls session if difference between last reload and current reload time(seconds) greater-than crl_reload_interval. For this support 'check_crl' should be 1 or 2. Signed-off-by: Paresh Chaudhary <paresh.chaudhary@xxxxxxxxxxxxxxxxxxx> -- [v1->v2]: Rebased for current hostapd and upstream feedback on v1 - Removed the min limit 5 minutes and list a warning for cpu overhead - Moved all info to tls_data - Removed openssl include in tls.h - Changed to use os_get_reltime() - Removed mutex because hostapd is single thread Signed-off-by: Jared Bents <jared.bents@xxxxxxxxxxxxxxxxxxx> --- hostapd/config_file.c | 2 ++ hostapd/hostapd.conf | 10 ++++++ src/ap/ap_config.h | 1 + src/ap/authsrv.c | 8 +++++ src/crypto/tls.h | 1 + src/crypto/tls_openssl.c | 77 +++++++++++++++++++++++++++++++++++++++- 6 files changed, 98 insertions(+), 1 deletion(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index aff147399..c69a1a536 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2480,6 +2480,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) { diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index dc12c27b6..425ec9a0a 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -904,6 +904,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 on every new tls session if difference +# between last reload and current reload time(seconds) 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. +# For this support 'check_crl' should be 1 or 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. diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 91931cbdb..19dd84aad 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -385,6 +385,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; diff --git a/src/ap/authsrv.c b/src/ap/authsrv.c index cebd5b1e5..4f2d418fb 100644 --- a/src/ap/authsrv.c +++ b/src/ap/authsrv.c @@ -200,6 +200,14 @@ 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, "Failed to enable crl reload functionality," + "It's depend on check_crl."); + } + if(hapd->conf->check_crl > 0 && 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; diff --git a/src/crypto/tls.h b/src/crypto/tls.h index 1f7e45701..0a8d38c76 100644 --- a/src/crypto/tls.h +++ b/src/crypto/tls.h @@ -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, diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c index ee357540c..77c77b36c 100644 --- a/src/crypto/tls_openssl.c +++ b/src/crypto/tls_openssl.c @@ -213,6 +213,11 @@ struct tls_data { SSL_CTX *ssl; unsigned int tls_session_lifetime; int check_crl_strict; + int check_crl; + const char *ca_cert; + unsigned int crl_reload_interval; + unsigned int crl_last_reload; + X509_STORE *old_x509_store; }; struct tls_connection { @@ -303,6 +308,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 == NULL) { + wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new " + "certificate store", __func__); + return NULL; + } + + if (ca_cert) { + if(!X509_STORE_load_locations(store, ca_cert, NULL)) { + tls_show_errors(MSG_WARNING, __func__, + "Failed to load root certificates"); + 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 */ @@ -991,8 +1027,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); @@ -1469,8 +1507,34 @@ 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); + /* Get current time */ + if (os_get_reltime(&now) < 0) + wpa_printf(MSG_ERROR,"Error getting relative time for crl reload"); + + /* Replace X509 store if it is time to update crl */ + /* Replace X509 store if difference between current time and previous store + * reload time greater-than crl_reload_interval */ + if (data->crl_reload_interval > 0 && data->crl_last_reload + + data->crl_reload_interval <= now.sec) { + wpa_printf(MSG_INFO, "Flushing X509 store with ca_cert file"); + new_cert_store = (X509_STORE *)tls_crl_cert_reload + (data->ca_cert, data->check_crl); + if (new_cert_store == NULL) { + wpa_printf(MSG_ERROR, + "Error replacing X509 store with ca_cert file"); + } else { + /*Free old store */ + if (data->old_x509_store) X509_STORE_free(data->old_x509_store); + data->old_x509_store = ssl->cert_store; + ssl->cert_store = new_cert_store; + data->crl_last_reload = now.sec; + } + } + conn = os_zalloc(sizeof(*conn)); if (conn == NULL) return NULL; @@ -2226,6 +2290,7 @@ static int tls_connection_ca_cert(struct tls_data *data, return 0; } + if (ca_cert && os_strncmp(ca_cert, "hash://", 7) == 0) { #ifdef CONFIG_SHA256 const char *pos = ca_cert + 7; @@ -2391,6 +2456,8 @@ 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 */ + + data->ca_cert = ca_cert; } return 0; @@ -2400,6 +2467,7 @@ static int tls_global_ca_cert(struct tls_data *data, const char *ca_cert) int tls_global_set_verify(void *ssl_ctx, int check_crl, int strict) { int flags; + struct os_reltime now; if (check_crl) { struct tls_data *data = ssl_ctx; @@ -2416,6 +2484,13 @@ int tls_global_set_verify(void *ssl_ctx, int check_crl, int strict) X509_STORE_set_flags(cs, flags); data->check_crl_strict = strict; + data->check_crl = check_crl; + /* Get current time */ + if (os_get_reltime(&now) < 0) + wpa_printf(MSG_ERROR,"Error getting relative time for crl reload"); + /* Store crl last reload time */ + data->crl_last_reload = now.sec; + data->old_x509_store = NULL; } return 0; } -- 2.18.0 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap