Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
store length of ESP encryption and HMAC keys so that they can be mani…
…pulated separately for both Juniper and GP

David Woodhouse wrote:
> Daniel Lenski wrote:
>> -       unsigned char secrets[0x40];
>> +       unsigned char secrets[0x40]; /* Encryption key bytes, then HMAC key bytes */
>
> You're allowed to object to that horridness and split it into two
> separate fields for the encryption and HMAC keys, instead of just
> documenting it.
>
> In fact, one might argue that would be the better approach...

Signed-off-by: Daniel Lenski <dlenski@gmail.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
  • Loading branch information
dlenski authored and dwmw2 committed May 15, 2017
1 parent e68c169 commit b2b1dd0
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 25 deletions.
13 changes: 4 additions & 9 deletions esp.c
Expand Up @@ -32,37 +32,32 @@ int print_esp_keys(struct openconnect_info *vpninfo, const char *name, struct es
int i;
const char *enctype, *mactype;
char enckey[256], mackey[256];
int enclen, maclen;

switch(vpninfo->esp_enc) {
case 0x02:
enctype = "AES-128-CBC (RFC3602)";
enclen = 16;
break;
case 0x05:
enctype = "AES-256-CBC (RFC3602)";
enclen = 32;
break;
default:
return -EINVAL;
}
switch(vpninfo->esp_hmac) {
case 0x01:
mactype = "HMAC-MD5-96 (RFC2403)";
maclen = 16;
break;
case 0x02:
mactype = "HMAC-SHA-1-96 (RFC2404)";
maclen = 20;
break;
default:
return -EINVAL;
}

for (i = 0; i < enclen; i++)
sprintf(enckey + (2 * i), "%02x", esp->secrets[i]);
for (i = 0; i < maclen; i++)
sprintf(mackey + (2 * i), "%02x", esp->secrets[enclen + i]);
for (i = 0; i < vpninfo->enc_key_len; i++)
sprintf(enckey + (2 * i), "%02x", esp->enc_key[i]);
for (i = 0; i < vpninfo->hmac_key_len; i++)
sprintf(mackey + (2 * i), "%02x", esp->hmac_key[i]);

vpn_progress(vpninfo, PRG_TRACE,
_("Parameters for %s ESP: SPI 0x%08x\n"),
Expand Down
7 changes: 4 additions & 3 deletions gnutls-esp.c
Expand Up @@ -48,7 +48,7 @@ static int init_esp_ciphers(struct openconnect_info *vpninfo, struct esp *esp,
destroy_esp_ciphers(esp);

enc_key.size = gnutls_cipher_get_key_size(encalg);
enc_key.data = esp->secrets;
enc_key.data = esp->enc_key;

err = gnutls_cipher_init(&esp->cipher, encalg, &enc_key, NULL);
if (err) {
Expand All @@ -59,7 +59,7 @@ static int init_esp_ciphers(struct openconnect_info *vpninfo, struct esp *esp,
}

err = gnutls_hmac_init(&esp->hmac, macalg,
esp->secrets + enc_key.size,
esp->hmac_key,
gnutls_hmac_get_len(macalg));
if (err) {
vpn_progress(vpninfo, PRG_ERR,
Expand Down Expand Up @@ -111,7 +111,8 @@ int setup_esp_keys(struct openconnect_info *vpninfo)
esp_in = &vpninfo->esp_in[vpninfo->current_esp_in];

if ((ret = gnutls_rnd(GNUTLS_RND_NONCE, &esp_in->spi, sizeof(esp_in->spi))) ||
(ret = gnutls_rnd(GNUTLS_RND_RANDOM, &esp_in->secrets, sizeof(esp_in->secrets)))) {
(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));
Expand Down
37 changes: 27 additions & 10 deletions oncp.c
Expand Up @@ -302,11 +302,13 @@ static int process_attr(struct openconnect_info *vpninfo, int group, int attr,

if (attrlen != 1)
goto badlen;
if (data[0] == 0x02)
if (data[0] == ENC_AES_128_CBC) {
enctype = "AES-128";
else if (data[0] == 0x05)
vpninfo->enc_key_len = 16;
} else if (data[0] == ENC_AES_256_CBC) {
enctype = "AES-256";
else
vpninfo->enc_key_len = 32;
} else
enctype = "unknown";
vpn_progress(vpninfo, PRG_DEBUG, _("ESP encryption: 0x%02x (%s)\n"),
data[0], enctype);
Expand All @@ -319,11 +321,13 @@ static int process_attr(struct openconnect_info *vpninfo, int group, int attr,

if (attrlen != 1)
goto badlen;
if (data[0] == 0x01)
if (data[0] == HMAC_MD5) {
mactype = "MD5";
else if (data[0] == 0x02)
vpninfo->hmac_key_len = 16;
} else if (data[0] == HMAC_SHA1) {
mactype = "SHA1";
else
vpninfo->hmac_key_len = 20;
} else
mactype = "unknown";
vpn_progress(vpninfo, PRG_DEBUG, _("ESP HMAC: 0x%02x (%s)\n"),
data[0], mactype);
Expand Down Expand Up @@ -389,7 +393,8 @@ static int process_attr(struct openconnect_info *vpninfo, int group, int attr,
case GRP_ATTR(7, 2):
if (attrlen != 0x40)
goto badlen;
memcpy(vpninfo->esp_out.secrets, data, 0x40);
/* data contains enc_key and hmac_key concatenated */
memcpy(vpninfo->esp_out.enc_key, data, 0x40);
vpn_progress(vpninfo, PRG_DEBUG, _("%d bytes of ESP secrets\n"),
attrlen);
break;
Expand Down Expand Up @@ -490,6 +495,7 @@ static int parse_conf_pkt(struct openconnect_info *vpninfo, unsigned char *bytes
{
int kmplen, kmpend, grouplen, groupend, group, attr, attrlen;
int ofs = 0;
int split_enc_hmac_keys = 0;

kmplen = load_be16(bytes + ofs + 18);
kmpend = ofs + kmplen;
Expand Down Expand Up @@ -533,12 +539,21 @@ static int parse_conf_pkt(struct openconnect_info *vpninfo, unsigned char *bytes
goto eparse;
if (process_attr(vpninfo, group, attr, bytes + ofs, attrlen))
goto eparse;
if (GRP_ATTR(group, attr)==GRP_ATTR(7, 2))
split_enc_hmac_keys = 1;
ofs += attrlen;
}
}

/* The encryption and HMAC keys are sent concatenated together in a block of 0x40 bytes;
we can't split them apart until we know how long the encryption key is. */
if (split_enc_hmac_keys)
memcpy(vpninfo->esp_out.hmac_key, vpninfo->esp_out.enc_key + vpninfo->enc_key_len, vpninfo->hmac_key_len);

return 0;
}


int oncp_connect(struct openconnect_info *vpninfo)
{
int ret, len, kmp, kmplen, group;
Expand Down Expand Up @@ -786,7 +801,8 @@ int oncp_connect(struct openconnect_info *vpninfo)
buf_append_bytes(reqbuf, esp_kmp_hdr, sizeof(esp_kmp_hdr));
buf_append_bytes(reqbuf, &esp->spi, sizeof(esp->spi));
buf_append_bytes(reqbuf, esp_kmp_part2, sizeof(esp_kmp_part2));
buf_append_bytes(reqbuf, &esp->secrets, sizeof(esp->secrets));
buf_append_bytes(reqbuf, &esp->enc_key, vpninfo->enc_key_len);
buf_append_bytes(reqbuf, &esp->hmac_key, 0x40 - vpninfo->enc_key_len);
if (buf_error(reqbuf)) {
vpn_progress(vpninfo, PRG_ERR,
_("Error negotiating ESP keys\n"));
Expand Down Expand Up @@ -840,8 +856,9 @@ static int oncp_receive_espkeys(struct openconnect_info *vpninfo, int len)
p += sizeof(esp->spi);
memcpy(p, esp_kmp_part2, sizeof(esp_kmp_part2));
p += sizeof(esp_kmp_part2);
memcpy(p, esp->secrets, sizeof(esp->secrets));
p += sizeof(esp->secrets);
memcpy(p, esp->enc_key, vpninfo->enc_key_len);
memcpy(p+vpninfo->enc_key_len, esp->hmac_key, 0x40 - vpninfo->enc_key_len);
p += 0x40;
vpninfo->cstp_pkt->len = p - vpninfo->cstp_pkt->data;
store_le16(vpninfo->cstp_pkt->oncp.rec,
(p - vpninfo->cstp_pkt->oncp.kmp));
Expand Down
11 changes: 10 additions & 1 deletion openconnect-internal.h
Expand Up @@ -338,7 +338,8 @@ struct esp {
uint64_t seq_backlog;
uint64_t seq;
uint32_t spi; /* Stored network-endian */
unsigned char secrets[0x40];
unsigned char enc_key[0x40]; /* Encryption key */
unsigned char hmac_key[0x40]; /* HMAC key */
};

struct openconnect_info {
Expand All @@ -362,6 +363,8 @@ struct openconnect_info {
int old_esp_maxseq;
struct esp esp_in[2];
struct esp esp_out;
int enc_key_len;
int hmac_key_len;

int tncc_fd; /* For Juniper TNCC */
const char *csd_xmltag;
Expand Down Expand Up @@ -690,6 +693,12 @@ struct openconnect_info {
#define AC_PKT_COMPRESSED 8 /* Compressed data */
#define AC_PKT_TERM_SERVER 9 /* Server kick */

/* Encryption and HMAC algorithms (matching Juniper's binary encoding) */
#define ENC_AES_128_CBC 2
#define ENC_AES_256_CBC 5
#define HMAC_MD5 1
#define HMAC_SHA1 2

#define vpn_progress(_v, lvl, ...) do { \
if ((_v)->verbose >= (lvl)) \
(_v)->progress((_v)->cbdata, lvl, __VA_ARGS__); \
Expand Down
5 changes: 3 additions & 2 deletions openssl-esp.c
Expand Up @@ -99,7 +99,7 @@ static int init_esp_ciphers(struct openconnect_info *vpninfo, struct esp *esp,
destroy_esp_ciphers(esp);
return -ENOMEM;
}
if (!HMAC_Init_ex(esp->hmac, esp->secrets + EVP_CIPHER_key_length(encalg),
if (!HMAC_Init_ex(esp->hmac, esp->hmac_key,
EVP_MD_size(macalg), macalg, NULL)) {
vpn_progress(vpninfo, PRG_ERR,
_("Failed to initialize ESP HMAC\n"));
Expand Down Expand Up @@ -151,7 +151,8 @@ int setup_esp_keys(struct openconnect_info *vpninfo)
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))) {
!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);
Expand Down

0 comments on commit b2b1dd0

Please sign in to comment.