static int init_esp_ciphers(struct openconnect_info *vpninfo, struct esp *esp, const EVP_MD *macalg, const EVP_CIPHER *encalg, int decrypt) { int ret; destroy_esp_ciphers(esp); EVP_CIPHER_CTX_init(&esp->cipher); if (decrypt) ret = EVP_DecryptInit_ex(&esp->cipher, encalg, NULL, esp->secrets, NULL); else ret = EVP_EncryptInit_ex(&esp->cipher, encalg, NULL, esp->secrets, NULL); if (!ret) { vpn_progress(vpninfo, PRG_ERR, _("Failed to initialise ESP cipher:\n")); openconnect_report_ssl_errors(vpninfo); return -EIO; } EVP_CIPHER_CTX_set_padding(&esp->cipher, 0); HMAC_CTX_init(&esp->hmac); if (!HMAC_Init_ex(&esp->hmac, esp->secrets + EVP_CIPHER_key_length(encalg), EVP_MD_size(macalg), macalg, NULL)) { vpn_progress(vpninfo, PRG_ERR, _("Failed to initialize ESP HMAC\n")); openconnect_report_ssl_errors(vpninfo); destroy_esp_ciphers(esp); } esp->seq = 0; esp->seq_backlog = 0; return 0; }
void esp_shutdown(struct openconnect_info *vpninfo) { destroy_esp_ciphers(&vpninfo->esp_in[0]); destroy_esp_ciphers(&vpninfo->esp_in[1]); destroy_esp_ciphers(&vpninfo->esp_out); esp_close(vpninfo); }
int setup_esp_keys(struct openconnect_info *vpninfo) { 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: encalg = EVP_aes_128_cbc(); break; case 0x05: encalg = EVP_aes_256_cbc(); break; default: return -EINVAL; } switch (vpninfo->esp_hmac) { case 0x01: macalg = EVP_md5(); break; case 0x02: macalg = EVP_sha1(); break; default: return -EINVAL; } 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)) || !RAND_bytes((void *)&esp_in->secrets, sizeof(esp_in->secrets))) { 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); if (ret) return ret; ret = init_esp_ciphers(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; }