[PATCH 6/8] add new_keys argument to esp_setup_keys() in preparation for supporting GlobalProtect ESP

Daniel Lenski dlenski at gmail.com
Sat May 20 15:43:27 PDT 2017


The existing ESP key setup code can be almost entirely reused for
GlobalProtect ESP, except for the fact that esp_setup_keys() always
overwrites the secret keys with new random keys.

Since GlobalProtect ESP always uses keys provided by the server, a new
argument is added to esp_setup_keys() to make this behavior optional.
The Juniper-specific code in oncp.c calls it with new_keys=1 in order
to explicitly request it.

Signed-off-by: Daniel Lenski <dlenski at gmail.com>
---
 gnutls-esp.c           | 23 ++++++++++++++---------
 oncp.c                 |  4 ++--
 openconnect-internal.h |  2 +-
 openssl-esp.c          | 23 ++++++++++++++---------
 4 files changed, 31 insertions(+), 21 deletions(-)

diff --git a/gnutls-esp.c b/gnutls-esp.c
index f3fd499..916cbc7 100644
--- a/gnutls-esp.c
+++ b/gnutls-esp.c
@@ -72,7 +72,7 @@ static int init_esp_ciphers(struct openconnect_info *vpninfo, struct esp *esp,
 	return 0;
 }
 
-int setup_esp_keys(struct openconnect_info *vpninfo)
+int setup_esp_keys(struct openconnect_info *vpninfo, int new_keys)
 {
 	struct esp *esp_in;
 	gnutls_mac_algorithm_t macalg;
@@ -106,17 +106,22 @@ int setup_esp_keys(struct openconnect_info *vpninfo)
 		return -EINVAL;
 	}
 
-	vpninfo->old_esp_maxseq = vpninfo->esp_in[vpninfo->current_esp_in].seq + 32;
-	vpninfo->current_esp_in ^= 1;
+	if (new_keys) {
+		vpninfo->old_esp_maxseq = vpninfo->esp_in[vpninfo->current_esp_in].seq + 32;
+		vpninfo->current_esp_in ^= 1;
+	}
+
 	esp_in = &vpninfo->esp_in[vpninfo->current_esp_in];
 
-	if ((ret = gnutls_rnd(GNUTLS_RND_NONCE, &esp_in->spi, sizeof(esp_in->spi))) ||
+	if (new_keys) {
+		if ((ret = gnutls_rnd(GNUTLS_RND_NONCE, &esp_in->spi, sizeof(esp_in->spi))) ||
 		    (ret = gnutls_rnd(GNUTLS_RND_RANDOM, &esp_in->enc_key, vpninfo->enc_key_len)) ||
 		    (ret = gnutls_rnd(GNUTLS_RND_RANDOM, &esp_in->hmac_key, vpninfo->hmac_key_len)) ) {
-		vpn_progress(vpninfo, PRG_ERR,
-			     _("Failed to generate random keys for ESP: %s\n"),
-			     gnutls_strerror(ret));
-		return -EIO;
+			vpn_progress(vpninfo, PRG_ERR,
+				     _("Failed to generate random keys for ESP: %s\n"),
+				     gnutls_strerror(ret));
+			return -EIO;
+		}
 	}
 
 	ret = init_esp_ciphers(vpninfo, &vpninfo->esp_out, macalg, encalg);
@@ -197,7 +202,7 @@ int encrypt_esp_packet(struct openconnect_info *vpninfo, struct pkt *pkt)
 		pkt->data[pkt->len + i] = i + 1;
 	pkt->data[pkt->len + padlen] = padlen;
 	pkt->data[pkt->len + padlen + 1] = 0x04; /* Legacy IP */
-	
+
 	gnutls_cipher_set_iv(vpninfo->esp_out.cipher, pkt->esp.iv, sizeof(pkt->esp.iv));
 	err = gnutls_cipher_encrypt(vpninfo->esp_out.cipher, pkt->data, pkt->len + padlen + 2);
 	if (err) {
diff --git a/oncp.c b/oncp.c
index 59cfa4b..f7d3d68 100644
--- a/oncp.c
+++ b/oncp.c
@@ -777,7 +777,7 @@ int oncp_connect(struct openconnect_info *vpninfo)
 	put_len16(reqbuf, kmp);
 
 #ifdef HAVE_ESP
-	if (!setup_esp_keys(vpninfo)) {
+	if (!setup_esp_keys(vpninfo, 1)) {
 		struct esp *esp = &vpninfo->esp_in[vpninfo->current_esp_in];
 		/* Since we'll want to do this in the oncp_mainloop too, where it's easier
 		 * *not* to have an oc_text_buf and build it up manually, and since it's
@@ -831,7 +831,7 @@ static int oncp_receive_espkeys(struct openconnect_info *vpninfo, int len)
 	int ret;
 
 	ret = parse_conf_pkt(vpninfo, vpninfo->cstp_pkt->oncp.kmp, len + 20, 301);
-	if (!ret && !setup_esp_keys(vpninfo)) {
+	if (!ret && !setup_esp_keys(vpninfo, 1)) {
 		struct esp *esp = &vpninfo->esp_in[vpninfo->current_esp_in];
 		unsigned char *p = vpninfo->cstp_pkt->oncp.kmp;
 
diff --git a/openconnect-internal.h b/openconnect-internal.h
index a9e2750..a16b05f 100644
--- a/openconnect-internal.h
+++ b/openconnect-internal.h
@@ -930,7 +930,7 @@ int esp_send_probes(struct openconnect_info *vpninfo);
 int esp_catch_probe(struct openconnect_info *vpninfo, struct pkt *pkt);
 
 /* {gnutls,openssl}-esp.c */
-int setup_esp_keys(struct openconnect_info *vpninfo);
+int setup_esp_keys(struct openconnect_info *vpninfo, int new_keys);
 void destroy_esp_ciphers(struct esp *esp);
 int decrypt_esp_packet(struct openconnect_info *vpninfo, struct esp *esp, struct pkt *pkt);
 int encrypt_esp_packet(struct openconnect_info *vpninfo, struct pkt *pkt);
diff --git a/openssl-esp.c b/openssl-esp.c
index faba1ff..ec60dfc 100644
--- a/openssl-esp.c
+++ b/openssl-esp.c
@@ -112,7 +112,7 @@ static int init_esp_ciphers(struct openconnect_info *vpninfo, struct esp *esp,
 	return 0;
 }
 
-int setup_esp_keys(struct openconnect_info *vpninfo)
+int setup_esp_keys(struct openconnect_info *vpninfo, int new_keys)
 {
 	struct esp *esp_in;
 	const EVP_CIPHER *encalg;
@@ -146,17 +146,22 @@ int setup_esp_keys(struct openconnect_info *vpninfo)
 		return -EINVAL;
 	}
 
-	vpninfo->old_esp_maxseq = vpninfo->esp_in[vpninfo->current_esp_in].seq + 32;
-	vpninfo->current_esp_in ^= 1;
+	if (new_keys) {
+		vpninfo->old_esp_maxseq = vpninfo->esp_in[vpninfo->current_esp_in].seq + 32;
+		vpninfo->current_esp_in ^= 1;
+	}
+
 	esp_in = &vpninfo->esp_in[vpninfo->current_esp_in];
 
-	if (!RAND_bytes((void *)&esp_in->spi, sizeof(esp_in->spi)) ||
+	if (new_keys) {
+		if (!RAND_bytes((void *)&esp_in->spi, sizeof(esp_in->spi)) ||
 		    !RAND_bytes((void *)&esp_in->enc_key, vpninfo->enc_key_len)) ||
 		    !RAND_bytes((void *)&esp_in->hmac_key, vpninfo->hmac_key_len)) ) {
-		vpn_progress(vpninfo, PRG_ERR,
-			     _("Failed to generate random keys for ESP:\n"));
-		openconnect_report_ssl_errors(vpninfo);
-		return -EIO;
+			vpn_progress(vpninfo, PRG_ERR,
+				     _("Failed to generate random keys for ESP:\n"));
+			openconnect_report_ssl_errors(vpninfo);
+			return -EIO;
+		}
 	}
 
 	ret = init_esp_ciphers(vpninfo, &vpninfo->esp_out, macalg, encalg, 0);
@@ -242,7 +247,7 @@ int encrypt_esp_packet(struct openconnect_info *vpninfo, struct pkt *pkt)
 		pkt->data[pkt->len + i] = i + 1;
 	pkt->data[pkt->len + padlen] = padlen;
 	pkt->data[pkt->len + padlen + 1] = 0x04; /* Legacy IP */
-	
+
 	if (!EVP_EncryptInit_ex(vpninfo->esp_out.cipher, NULL, NULL, NULL,
 				pkt->esp.iv)) {
 		vpn_progress(vpninfo, PRG_ERR,
-- 
2.7.4




More information about the openconnect-devel mailing list