if (vpninfo->dtls_state != DTLS_DISABLED)
vpninfo->dtls_state = DTLS_NOSECRET;
}
+
+int openconnect_setup_esp_keys(struct openconnect_info *vpninfo, int new_keys)
+{
+ struct esp *esp_in;
+ int ret;
+
+ if (vpninfo->dtls_state == DTLS_DISABLED)
+ return -EOPNOTSUPP;
+ if (!vpninfo->dtls_addr)
+ return -EINVAL;
+
+ 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 (new_keys) {
+ if (openconnect_random(&esp_in->spi, sizeof(esp_in->spi)) ||
+ openconnect_random((void *)&esp_in->enc_key, vpninfo->enc_key_len) ||
+ openconnect_random((void *)&esp_in->hmac_key, vpninfo->hmac_key_len)) {
+ vpn_progress(vpninfo, PRG_ERR,
+ _("Failed to generate random keys for ESP\n"));
+ return -EIO;
+ }
+ }
+
+ if (openconnect_random(vpninfo->esp_out.iv, sizeof(vpninfo->esp_out.iv))) {
+ vpn_progress(vpninfo, PRG_ERR,
+ _("Failed to generate initial IV for ESP\n"));
+ return -EIO;
+ }
+
+ /* This is the minimum; some implementations may increase it */
+ vpninfo->pkt_trailer = 17 + 16 + 20; /* 17 for pad, 16 for IV, 20 for HMAC (of which we send 12) */
+
+ vpninfo->esp_out.seq = vpninfo->esp_out.seq_backlog = 0;
+ esp_in->seq = esp_in->seq_backlog = 0;
+
+ ret = init_esp_ciphers(vpninfo, &vpninfo->esp_out, esp_in);
+ if (ret)
+ return ret;
+
+ if (vpninfo->dtls_state == DTLS_NOSECRET)
+ vpninfo->dtls_state = DTLS_SECRET;
+
+ return 0;
+}
}
}
-static int init_esp_ciphers(struct openconnect_info *vpninfo, struct esp *esp,
- gnutls_mac_algorithm_t macalg, gnutls_cipher_algorithm_t encalg)
+static int init_esp_cipher(struct openconnect_info *vpninfo, struct esp *esp,
+ gnutls_mac_algorithm_t macalg, gnutls_cipher_algorithm_t encalg)
{
gnutls_datum_t enc_key;
int err;
gnutls_strerror(err));
destroy_esp_ciphers(esp);
}
- esp->seq = 0;
- esp->seq_backlog = 0;
return 0;
}
-int setup_esp_keys(struct openconnect_info *vpninfo, int new_keys)
+int init_esp_ciphers(struct openconnect_info *vpninfo, struct esp *esp_out, struct esp *esp_in)
{
- struct esp *esp_in;
gnutls_mac_algorithm_t macalg;
gnutls_cipher_algorithm_t encalg;
int ret;
- if (vpninfo->dtls_state == DTLS_DISABLED)
- return -EOPNOTSUPP;
- if (!vpninfo->dtls_addr)
- return -EINVAL;
-
switch (vpninfo->esp_enc) {
- case 0x02:
+ case ENC_AES_128_CBC:
encalg = GNUTLS_CIPHER_AES_128_CBC;
break;
- case 0x05:
+ case ENC_AES_256_CBC:
encalg = GNUTLS_CIPHER_AES_256_CBC;
break;
default:
}
switch (vpninfo->esp_hmac) {
- case 0x01:
+ case HMAC_MD5:
macalg = GNUTLS_MAC_MD5;
break;
- case 0x02:
+ case HMAC_SHA1:
macalg = GNUTLS_MAC_SHA1;
break;
default:
return -EINVAL;
}
- 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 (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;
- }
- }
-
- ret = init_esp_ciphers(vpninfo, &vpninfo->esp_out, macalg, encalg);
+ ret = init_esp_cipher(vpninfo, esp_out, macalg, encalg);
if (ret)
return ret;
- if (gnutls_rnd(GNUTLS_RND_NONCE, vpninfo->esp_out.iv, sizeof(vpninfo->esp_out.iv))) {
- vpn_progress(vpninfo, PRG_ERR, _("Failed to generate ESP IV\n"));
- destroy_esp_ciphers(&vpninfo->esp_out);
- return -EIO;
- }
- gnutls_cipher_set_iv(vpninfo->esp_out.cipher, vpninfo->esp_out.iv,
- sizeof(vpninfo->esp_out.iv));
-
+ gnutls_cipher_set_iv(esp_out->cipher, esp_out->iv, sizeof(esp_out->iv));
- ret = init_esp_ciphers(vpninfo, esp_in, macalg, encalg);
+ ret = init_esp_cipher(vpninfo, esp_in, macalg, encalg);
if (ret) {
- destroy_esp_ciphers(&vpninfo->esp_out);
+ destroy_esp_ciphers(esp_out);
return ret;
}
- if (vpninfo->dtls_state == DTLS_NOSECRET)
- vpninfo->dtls_state = DTLS_SECRET;
- vpninfo->pkt_trailer = 16 + 20; /* 16 for pad, 20 for HMAC (of which we use 16) */
return 0;
}
else if (!xmlnode_get_val(member, "ipsec-mode", &s) && strcmp(s, "esp-tunnel"))
vpn_progress(vpninfo, PRG_ERR, _("GlobalProtect config sent ipsec-mode=%s (expected esp-tunnel)\n"), s);
}
- if (setup_esp_keys(vpninfo, 0))
+ if (openconnect_setup_esp_keys(vpninfo, 0))
vpn_progress(vpninfo, PRG_ERR, "Failed to setup ESP keys.\n");
else
/* prevent race condition between esp_mainloop() and gpst_mainloop() timers */
put_len16(reqbuf, kmp);
#ifdef HAVE_ESP
- if (!setup_esp_keys(vpninfo, 1)) {
+ if (!openconnect_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
int ret;
ret = parse_conf_pkt(vpninfo, vpninfo->cstp_pkt->oncp.kmp, len + 20, 301);
- if (!ret && !setup_esp_keys(vpninfo, 1)) {
+ if (!ret && !openconnect_setup_esp_keys(vpninfo, 1)) {
struct esp *esp = &vpninfo->esp_in[vpninfo->current_esp_in];
unsigned char *p = vpninfo->cstp_pkt->oncp.kmp;
void esp_close(struct openconnect_info *vpninfo);
void esp_shutdown(struct openconnect_info *vpninfo);
int print_esp_keys(struct openconnect_info *vpninfo, const char *name, struct esp *esp);
+int openconnect_setup_esp_keys(struct openconnect_info *vpninfo, int new_keys);
/* {gnutls,openssl}-esp.c */
-int setup_esp_keys(struct openconnect_info *vpninfo, int new_keys);
void destroy_esp_ciphers(struct esp *esp);
+int init_esp_ciphers(struct openconnect_info *vpninfo, struct esp *out, struct esp *in);
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);
}
}
-static int init_esp_ciphers(struct openconnect_info *vpninfo, struct esp *esp,
+static int init_esp_cipher(struct openconnect_info *vpninfo, struct esp *esp,
const EVP_MD *macalg, const EVP_CIPHER *encalg, int decrypt)
{
int ret;
if (decrypt)
ret = EVP_DecryptInit_ex(esp->cipher, encalg, NULL, esp->enc_key, NULL);
else {
- ret = RAND_bytes((void *)&esp->iv, sizeof(esp->iv)) &&
- EVP_EncryptInit_ex(esp->cipher, encalg, NULL, esp->enc_key, esp->iv);
+ ret = EVP_EncryptInit_ex(esp->cipher, encalg, NULL, esp->enc_key, esp->iv);
}
if (!ret) {
openconnect_report_ssl_errors(vpninfo);
destroy_esp_ciphers(esp);
}
- esp->seq = 0;
- esp->seq_backlog = 0;
+
return 0;
}
-int setup_esp_keys(struct openconnect_info *vpninfo, int new_keys)
+int init_esp_ciphers(struct openconnect_info *vpninfo, struct esp *esp_out, struct esp *esp_in)
{
- struct esp *esp_in;
const EVP_CIPHER *encalg;
const EVP_MD *macalg;
int ret;
- if (vpninfo->dtls_state == DTLS_DISABLED)
- return -EOPNOTSUPP;
- if (!vpninfo->dtls_addr)
- return -EINVAL;
-
switch (vpninfo->esp_enc) {
- case 0x02:
+ case ENC_AES_128_CBC:
encalg = EVP_aes_128_cbc();
break;
- case 0x05:
+ case ENC_AES_256_CBC:
encalg = EVP_aes_256_cbc();
break;
default:
}
switch (vpninfo->esp_hmac) {
- case 0x01:
+ case HMAC_MD5:
macalg = EVP_md5();
break;
- case 0x02:
+ case HMAC_SHA1:
macalg = EVP_sha1();
break;
default:
return -EINVAL;
}
- 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 (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;
- }
- }
-
- ret = init_esp_ciphers(vpninfo, &vpninfo->esp_out, macalg, encalg, 0);
+ ret = init_esp_cipher(vpninfo, &vpninfo->esp_out, macalg, encalg, 0);
if (ret)
return ret;
- ret = init_esp_ciphers(vpninfo, esp_in, macalg, encalg, 1);
+ ret = init_esp_cipher(vpninfo, esp_in, macalg, encalg, 1);
if (ret) {
destroy_esp_ciphers(&vpninfo->esp_out);
return ret;
}
- if (vpninfo->dtls_state == DTLS_NOSECRET)
- vpninfo->dtls_state = DTLS_SECRET;
- vpninfo->pkt_trailer = 16 + 20; /* 16 for pad, 20 for HMAC (of which we use 16) */
return 0;
}