diff options
author | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2010-09-22 13:40:06 +0000 |
---|---|---|
committer | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2010-09-22 13:40:06 +0000 |
commit | 43de7d144205f315f7e743732ba0fef7321144c7 (patch) | |
tree | 6f13c86aceacab2bece3c331ff05c82ebb0b73e0 /sys/netinet/ip_esp.c | |
parent | 6efe2a2078580a1d1b02bdff5f4752e4997c9656 (diff) |
Support for AES-GCM-16 and ENCR_NULL_AUTH_AES_GMAC in ESP as per
RFC 4106 and 4543.
Authentication hash key is set to be the same as an encryption key.
The length that is specified for the authentication hash descriptor
denotes the the length of Additional Authentication Data (AAD).
The encryption transformation descriptor length denotes the length
of the payload (to be encrypted and authenticated).
ENCR_NULL_AUTH_AES_GMAC treats all input as AAD, thus the encryption
length is set to zero.
This also fixes padding for stream ciphers, so that payload will
be 4-byte aligned.
Diffstat (limited to 'sys/netinet/ip_esp.c')
-rw-r--r-- | sys/netinet/ip_esp.c | 70 |
1 files changed, 61 insertions, 9 deletions
diff --git a/sys/netinet/ip_esp.c b/sys/netinet/ip_esp.c index a843c0eb18e..240f9747aae 100644 --- a/sys/netinet/ip_esp.c +++ b/sys/netinet/ip_esp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_esp.c,v 1.111 2010/07/20 15:36:03 matthew Exp $ */ +/* $OpenBSD: ip_esp.c,v 1.112 2010/09/22 13:40:05 mikeb Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and @@ -131,6 +131,14 @@ esp_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii) txform = &enc_xform_aes_ctr; break; + case SADB_X_EALG_AESGCM16: + txform = &enc_xform_aes_gcm; + break; + + case SADB_X_EALG_AESGMAC: + txform = &enc_xform_aes_gmac; + break; + case SADB_X_EALG_BLF: txform = &enc_xform_blf; break; @@ -158,6 +166,23 @@ esp_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii) return EINVAL; } + if (ii->ii_encalg == SADB_X_EALG_AESGCM16 || + ii->ii_encalg == SADB_X_EALG_AESGMAC) { + switch (ii->ii_enckeylen) { + case 20: + ii->ii_authalg = SADB_X_AALG_AES128GMAC; + break; + case 28: + ii->ii_authalg = SADB_X_AALG_AES192GMAC; + break; + case 36: + ii->ii_authalg = SADB_X_AALG_AES256GMAC; + break; + } + ii->ii_authkeylen = ii->ii_enckeylen; + ii->ii_authkey = ii->ii_enckey; + } + tdbp->tdb_encalgxform = txform; DPRINTF(("esp_init(): initialized TDB with enc algorithm %s\n", @@ -194,6 +219,18 @@ esp_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii) thash = &auth_hash_hmac_sha2_512_256; break; + case SADB_X_AALG_AES128GMAC: + thash = &auth_hash_gmac_aes_128; + break; + + case SADB_X_AALG_AES192GMAC: + thash = &auth_hash_gmac_aes_192; + break; + + case SADB_X_AALG_AES256GMAC: + thash = &auth_hash_gmac_aes_256; + break; + default: DPRINTF(("esp_init(): unsupported authentication algorithm %d specified\n", ii->ii_authalg)); return EINVAL; @@ -290,14 +327,13 @@ esp_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff) { struct auth_hash *esph = (struct auth_hash *) tdb->tdb_authalgxform; struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform; + struct cryptodesc *crde = NULL, *crda = NULL; + struct cryptop *crp; struct tdb_crypto *tc; int plen, alen, hlen; struct m_tag *mtag; u_int32_t btsx; - struct cryptodesc *crde = NULL, *crda = NULL; - struct cryptop *crp; - /* Determine the ESP header length */ if (tdb->tdb_flags & TDBF_NOREPLAY) hlen = sizeof(u_int32_t) + tdb->tdb_ivlen; /* "old" ESP */ @@ -424,13 +460,17 @@ esp_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff) /* Authentication descriptor */ crda->crd_skip = skip; - crda->crd_len = m->m_pkthdr.len - (skip + alen); crda->crd_inject = m->m_pkthdr.len - alen; crda->crd_alg = esph->type; crda->crd_key = tdb->tdb_amxkey; crda->crd_klen = tdb->tdb_amxkeylen * 8; + if (espx && espx->type == CRYPTO_AES_GCM_16) + crda->crd_len = hlen - tdb->tdb_ivlen; + else + crda->crd_len = m->m_pkthdr.len - (skip + alen); + /* Copy the authenticator */ if (mtag == NULL) m_copydata(m, m->m_pkthdr.len - alen, alen, (caddr_t) (tc + 1)); @@ -456,7 +496,6 @@ esp_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff) /* Decryption descriptor */ if (espx) { crde->crd_skip = skip + hlen; - crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen); crde->crd_inject = skip + hlen - tdb->tdb_ivlen; if (tdb->tdb_flags & TDBF_HALFIV) { @@ -474,6 +513,11 @@ esp_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff) crde->crd_key = tdb->tdb_emxkey; crde->crd_klen = tdb->tdb_emxkeylen * 8; /* XXX Rounds ? */ + + if (crde->crd_alg == CRYPTO_AES_GMAC) + crde->crd_len = 0; + else + crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen); } if (mtag == NULL) @@ -764,7 +808,7 @@ esp_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip, rlen = m->m_pkthdr.len - skip; /* Raw payload length. */ if (espx) - blks = espx->blocksize; + blks = MAX(espx->blocksize, 4); else blks = 4; /* If no encryption, we have to be 4-byte aligned. */ @@ -926,7 +970,6 @@ esp_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip, /* Encryption descriptor. */ crde->crd_skip = skip + hlen; - crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen); crde->crd_flags = CRD_F_ENCRYPT; crde->crd_inject = skip + hlen - tdb->tdb_ivlen; @@ -950,6 +993,11 @@ esp_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip, crde->crd_key = tdb->tdb_emxkey; crde->crd_klen = tdb->tdb_emxkeylen * 8; /* XXX Rounds ? */ + + if (crde->crd_alg == CRYPTO_AES_GMAC) + crde->crd_len = 0; + else + crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen); } else crda = crp->crp_desc; @@ -979,13 +1027,17 @@ esp_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip, if (esph) { /* Authentication descriptor. */ crda->crd_skip = skip; - crda->crd_len = m->m_pkthdr.len - (skip + alen); crda->crd_inject = m->m_pkthdr.len - alen; /* Authentication operation. */ crda->crd_alg = esph->type; crda->crd_key = tdb->tdb_amxkey; crda->crd_klen = tdb->tdb_amxkeylen * 8; + + if (espx && espx->type == CRYPTO_AES_GCM_16) + crda->crd_len = hlen - tdb->tdb_ivlen; + else + crda->crd_len = m->m_pkthdr.len - (skip + alen); } if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0) |