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