diff mbox series

[v2,1/2] crl_reload_interval: Add reload crl support

Message ID 20190116151502.24590-1-jared.bents@rockwellcollins.com
State Accepted
Headers show
Series [v2,1/2] crl_reload_interval: Add reload crl support | expand

Commit Message

Jared Bents Jan. 16, 2019, 3:15 p.m. UTC
From: Jared Bents <jared.bents@rockwellcollins.com>

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@rockwellcollins.com>
--
[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@rockwellcollins.com>
---
 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(-)

Comments

Jouni Malinen Jan. 27, 2019, 10:29 p.m. UTC | #1
On Wed, Jan 16, 2019 at 09:15:01AM -0600, jared.bents@rockwellcollins.com wrote:
> 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.

Thanks, applied with some cleanup and fixes.
diff mbox series

Patch

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