commit 4ab3b90b7d948ab4411e54ba886a6514e09f9f76
Author: Ermal <eri@pfsense.org>
Date:   Mon Jun 9 18:17:52 2014 +0000

    Add AES-GCM software version implementation for IPSec

diff --git a/builder_scripts/conf/patchlist/stable/10/patches b/builder_scripts/conf/patchlist/stable/10/patches
index 4c6e347e..fdd94362 100644
--- a/builder_scripts/conf/patchlist/stable/10/patches
+++ b/builder_scripts/conf/patchlist/stable/10/patches
@@ -67,3 +67,4 @@
 -p1~~pf_table_paddr_clean.diff~
 -p1~~pf_ifacebound_state.diff~
 -p1~~pf_icmp_redirect.diff~
+-p1~~aesgcm.soft.1.patch~
diff --git a/patches/stable/10/aesgcm.soft.1.patch b/patches/stable/10/aesgcm.soft.1.patch
new file mode 100644
index 00000000..78bbe16e
--- /dev/null
+++ b/patches/stable/10/aesgcm.soft.1.patch
@@ -0,0 +1,1398 @@
+diff --git a/lib/libipsec/pfkey_dump.c b/lib/libipsec/pfkey_dump.c
+index 068ad0e..872aa43 100644
+--- a/lib/libipsec/pfkey_dump.c
++++ b/lib/libipsec/pfkey_dump.c
+@@ -187,6 +187,9 @@ static struct val2str str_alg_enc[] = {
+ #ifdef SADB_X_EALG_AESCTR
+ 	{ SADB_X_EALG_AESCTR, "aes-ctr", },
+ #endif
++#ifdef SADB_X_EALG_AESGCM16
++	{ SADB_X_EALG_AESGCM16, "aes-gcm-16", },
++#endif
+ #ifdef SADB_X_EALG_CAMELLIACBC
+ 	{ SADB_X_EALG_CAMELLIACBC, "camellia-cbc", },
+ #endif
+diff --git a/sbin/setkey/setkey.8 b/sbin/setkey/setkey.8
+index 19a9164..0e67bb2 100644
+--- a/sbin/setkey/setkey.8
++++ b/sbin/setkey/setkey.8
+@@ -627,11 +627,12 @@ des-deriv	64		ipsec-ciph-des-derived-01
+ 3des-deriv	192		no document
+ rijndael-cbc	128/192/256	rfc3602
+ aes-ctr		160/224/288	draft-ietf-ipsec-ciph-aes-ctr-03
++aes-gcm-16	160/224/288	rfc4106
+ camllia-cbc	128/192/256	rfc4312
+ .Ed
+ .Pp
+ Note that the first 128/192/256 bits of a key for
+-.Li aes-ctr
++.Li aes-ctr or aes-gcm-16
+ will be used as AES key, and remaining 32 bits will be used as nonce.
+ .Pp
+ The following are the list of compression algorithms that can be used
+diff --git a/sbin/setkey/token.l b/sbin/setkey/token.l
+index c89982f..f258e63 100644
+--- a/sbin/setkey/token.l
++++ b/sbin/setkey/token.l
+@@ -168,6 +168,7 @@ tcp		{ yylval.num = 0; return(PR_TCP); }
+ <S_ENCALG>rijndael-cbc	{ yylval.num = SADB_X_EALG_RIJNDAELCBC; BEGIN INITIAL; return(ALG_ENC); }
+ <S_ENCALG>aes-ctr	{ yylval.num = SADB_X_EALG_AESCTR; BEGIN INITIAL; return(ALG_ENC); }
+ <S_ENCALG>camellia-cbc	{ yylval.num = SADB_X_EALG_CAMELLIACBC; BEGIN INITIAL; return(ALG_ENC); }
++<S_ENCALG>aes-gcm-16	{ yylval.num = SADB_X_EALG_AESGCM16; BEGIN INITIAL; return(ALG_ENC); }
+ 
+ 	/* compression algorithms */
+ {hyphen}C	{ return(F_COMP); }
+diff --git a/sys/conf/files b/sys/conf/files
+index e978443..8440b86 100644
+--- a/sys/conf/files
++++ b/sys/conf/files
+@@ -3777,6 +3777,7 @@ opencrypto/cryptodev.c		optional cryptodev
+ opencrypto/cryptodev_if.m	optional crypto
+ opencrypto/cryptosoft.c		optional crypto
+ opencrypto/cryptodeflate.c	optional crypto
++opencrypto/gmac.c		optional crypto
+ opencrypto/rmd160.c		optional crypto | ipsec
+ opencrypto/skipjack.c		optional crypto
+ opencrypto/xform.c		optional crypto
+diff --git a/sys/crypto/via/padlock_hash.c b/sys/crypto/via/padlock_hash.c
+index 924a9ec..133581f 100644
+--- a/sys/crypto/via/padlock_hash.c
++++ b/sys/crypto/via/padlock_hash.c
+@@ -75,7 +75,7 @@ struct padlock_sha_ctx {
+ CTASSERT(sizeof(struct padlock_sha_ctx) <= sizeof(union authctx));
+ 
+ static void padlock_sha_init(struct padlock_sha_ctx *ctx);
+-static int padlock_sha_update(struct padlock_sha_ctx *ctx, uint8_t *buf,
++static int padlock_sha_update(struct padlock_sha_ctx *ctx, const uint8_t *buf,
+     uint16_t bufsize);
+ static void padlock_sha1_final(uint8_t *hash, struct padlock_sha_ctx *ctx);
+ static void padlock_sha256_final(uint8_t *hash, struct padlock_sha_ctx *ctx);
+@@ -83,16 +83,16 @@ static void padlock_sha256_final(uint8_t *hash, struct padlock_sha_ctx *ctx);
+ static struct auth_hash padlock_hmac_sha1 = {
+ 	CRYPTO_SHA1_HMAC, "HMAC-SHA1",
+ 	20, SHA1_HASH_LEN, SHA1_HMAC_BLOCK_LEN, sizeof(struct padlock_sha_ctx),
+-        (void (*)(void *))padlock_sha_init,
+-	(int (*)(void *, uint8_t *, uint16_t))padlock_sha_update,
++        (void (*)(void *))padlock_sha_init, NULL, NULL,
++	(int (*)(void *, const uint8_t *, uint16_t))padlock_sha_update,
+ 	(void (*)(uint8_t *, void *))padlock_sha1_final
+ };
+ 
+ static struct auth_hash padlock_hmac_sha256 = {
+ 	CRYPTO_SHA2_256_HMAC, "HMAC-SHA2-256",
+ 	32, SHA2_256_HASH_LEN, SHA2_256_HMAC_BLOCK_LEN, sizeof(struct padlock_sha_ctx),
+-        (void (*)(void *))padlock_sha_init,
+-	(int (*)(void *, uint8_t *, uint16_t))padlock_sha_update,
++        (void (*)(void *))padlock_sha_init, NULL, NULL,
++	(int (*)(void *, const uint8_t *, uint16_t))padlock_sha_update,
+ 	(void (*)(uint8_t *, void *))padlock_sha256_final
+ };
+ 
+@@ -167,7 +167,7 @@ padlock_sha_init(struct padlock_sha_ctx *ctx)
+ }
+ 
+ static int
+-padlock_sha_update(struct padlock_sha_ctx *ctx, uint8_t *buf, uint16_t bufsize)
++padlock_sha_update(struct padlock_sha_ctx *ctx, const uint8_t *buf, uint16_t bufsize)
+ {
+ 
+ 	if (ctx->psc_size - ctx->psc_offset < bufsize) {
+diff --git a/sys/modules/crypto/Makefile b/sys/modules/crypto/Makefile
+index 6a37c10..7d84c97 100644
+--- a/sys/modules/crypto/Makefile
++++ b/sys/modules/crypto/Makefile
+@@ -15,6 +15,7 @@ SRCS	+= cast.c cryptodeflate.c rmd160.c rijndael-alg-fst.c rijndael-api.c
+ SRCS	+= skipjack.c bf_enc.c bf_ecb.c bf_skey.c
+ SRCS	+= des_ecb.c des_enc.c des_setkey.c
+ SRCS	+= sha1.c sha2.c
++SRCS	+= gmac.c
+ SRCS	+= opt_param.h cryptodev_if.h bus_if.h device_if.h
+ SRCS	+= opt_ddb.h opt_kdtrace.h
+ SRCS	+= camellia.c camellia-api.c
+diff --git a/sys/net/pfkeyv2.h b/sys/net/pfkeyv2.h
+index c45f8b0..fc8bea7 100644
+--- a/sys/net/pfkeyv2.h
++++ b/sys/net/pfkeyv2.h
+@@ -343,6 +343,9 @@ struct sadb_x_nat_t_frag {
+ #define SADB_X_AALG_SHA2_512	7
+ #define SADB_X_AALG_RIPEMD160HMAC	8
+ #define SADB_X_AALG_AES_XCBC_MAC	9	/* draft-ietf-ipsec-ciph-aes-xcbc-mac-04 */
++#define SADB_X_AALG_AES128GMAC	11		/* RFC4543 + Errata1821 */
++#define SADB_X_AALG_AES192GMAC	12
++#define SADB_X_AALG_AES256GMAC	13
+ /* private allocations should use 249-255 (RFC2407) */
+ #define SADB_X_AALG_MD5		249	/* Keyed MD5 */
+ #define SADB_X_AALG_SHA		250	/* Keyed SHA */
+@@ -360,6 +363,9 @@ struct sadb_x_nat_t_frag {
+ #define SADB_X_EALG_BLOWFISHCBC	7
+ #define SADB_X_EALG_RIJNDAELCBC	12
+ #define SADB_X_EALG_AES		12
++#define SADB_X_EALG_AESGCM8	18	/* RFC4106 */
++#define SADB_X_EALG_AESGCM12	19
++#define SADB_X_EALG_AESGCM16	20
+ /* private allocations - based on RFC4312/IANA assignment */
+ #define SADB_X_EALG_CAMELLIACBC		22
+ /* private allocations should use 249-255 (RFC2407) */
+diff --git a/sys/netipsec/xform_esp.c b/sys/netipsec/xform_esp.c
+index bb6d1e6..2639634 100644
+--- a/sys/netipsec/xform_esp.c
++++ b/sys/netipsec/xform_esp.c
+@@ -120,6 +120,10 @@ esp_algorithm_lookup(int alg)
+ 		return &enc_xform_null;
+ 	case SADB_X_EALG_CAMELLIACBC:
+ 		return &enc_xform_camellia;
++	case SADB_X_EALG_AESCTR:
++		return &enc_xform_aes_ctr;
++	case SADB_X_EALG_AESGCM16:
++		return &enc_xform_aes_gcm;
+ 	}
+ 	return NULL;
+ }
+@@ -214,6 +218,27 @@ esp_init(struct secasvar *sav, struct xformsw *xsp)
+ 	sav->tdb_xform = xsp;
+ 	sav->tdb_encalgxform = txform;
+ 
++	if (sav->alg_enc == SADB_X_EALG_AESGCM16) {
++		switch (keylen) {
++		case 20:
++			sav->alg_auth = SADB_X_AALG_AES128GMAC;
++			sav->tdb_authalgxform = &auth_hash_gmac_aes_128;
++			break;
++		case 28:
++			sav->alg_auth = SADB_X_AALG_AES192GMAC;
++			sav->tdb_authalgxform = &auth_hash_gmac_aes_192;
++			break;
++		case 36:
++			sav->alg_auth = SADB_X_AALG_AES256GMAC;
++			sav->tdb_authalgxform = &auth_hash_gmac_aes_256;
++			break;
++		}
++		bzero(&cria, sizeof(cria));
++		cria.cri_alg = sav->tdb_authalgxform->type;
++		cria.cri_klen = _KEYBITS(sav->key_enc);
++		cria.cri_key = sav->key_enc->key_data;
++	}
++
+ 	/* Initialize crypto session. */
+ 	bzero(&crie, sizeof (crie));
+ 	crie.cri_alg = sav->tdb_encalgxform->type;
+@@ -309,6 +334,11 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
+ 		case CRYPTO_SHA2_512_HMAC:
+ 			alen = esph->hashsize/2;
+ 			break;
++		case CRYPTO_AES_128_GMAC:
++		case CRYPTO_AES_192_GMAC:
++		case CRYPTO_AES_256_GMAC:
++			alen = esph->hashsize; 
++			break;
+ 		default:
+ 			alen = AH_HMAC_HASHLEN;
+ 			break;
+@@ -396,12 +426,20 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
+ 
+ 		/* Authentication descriptor */
+ 		crda->crd_skip = skip;
+-		crda->crd_len = m->m_pkthdr.len - (skip + alen);
++		if (espx && espx->type == CRYPTO_AES_GCM_16)
++			crda->crd_len = hlen - sav->ivlen;
++		else
++			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 = sav->key_auth->key_data;
+-		crda->crd_klen = _KEYBITS(sav->key_auth);
++		if (espx && (espx->type == CRYPTO_AES_GCM_16)) {
++			crda->crd_key = sav->key_enc->key_data;
++			crda->crd_klen = _KEYBITS(sav->key_enc);
++		} else {
++			crda->crd_key = sav->key_auth->key_data;
++			crda->crd_klen = _KEYBITS(sav->key_auth);
++		}	
+ 
+ 		/* Copy the authenticator */
+ 		if (mtag == NULL)
+@@ -521,6 +559,11 @@ esp_input_cb(struct cryptop *crp)
+ 		case CRYPTO_SHA2_512_HMAC:
+ 			alen = esph->hashsize/2;
+ 			break;
++		case CRYPTO_AES_128_GMAC:
++		case CRYPTO_AES_192_GMAC:
++		case CRYPTO_AES_256_GMAC:
++			alen = esph->hashsize; 
++			break;
+ 		default:
+ 			alen = AH_HMAC_HASHLEN;
+ 			break;
+@@ -891,13 +934,21 @@ esp_output(
+ 	if (esph) {
+ 		/* Authentication descriptor. */
+ 		crda->crd_skip = skip;
+-		crda->crd_len = m->m_pkthdr.len - (skip + alen);
++		if (espx && espx->type == CRYPTO_AES_GCM_16)
++			crda->crd_len = hlen - sav->ivlen;
++		else
++			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 = sav->key_auth->key_data;
+-		crda->crd_klen = _KEYBITS(sav->key_auth);
++		if (espx && espx->type == CRYPTO_AES_GCM_16) {
++			crda->crd_key = sav->key_enc->key_data;
++			crda->crd_klen = _KEYBITS(sav->key_enc);
++		} else {
++			crda->crd_key = sav->key_auth->key_data;
++			crda->crd_klen = _KEYBITS(sav->key_auth);
++		}
+ 	}
+ 
+ 	return crypto_dispatch(crp);
+@@ -988,6 +1039,11 @@ esp_output_cb(struct cryptop *crp)
+ 			case CRYPTO_SHA2_512_HMAC:
+ 				alen = esph->hashsize/2;
+ 				break;
++			case CRYPTO_AES_128_GMAC:
++			case CRYPTO_AES_192_GMAC:
++			case CRYPTO_AES_256_GMAC:
++				alen = esph->hashsize;
++				break;
+ 			default:
+ 				alen = AH_HMAC_HASHLEN;
+ 				break;
+diff --git a/sys/opencrypto/cryptodev.c b/sys/opencrypto/cryptodev.c
+index 44bfa5c..cbb8531 100644
+--- a/sys/opencrypto/cryptodev.c
++++ b/sys/opencrypto/cryptodev.c
+@@ -434,6 +434,13 @@ cryptof_ioctl(
+  		case CRYPTO_CAMELLIA_CBC:
+  			txform = &enc_xform_camellia;
+  			break;
++		case CRYPTO_AES_CTR:
++			txform = &enc_xform_aes_ctr;
++ 			break;
++		case CRYPTO_AES_GCM_16:
++			txform = &enc_xform_aes_gcm;
++ 			break;
++
+ 		default:
+ 			return (EINVAL);
+ 		}
+@@ -459,6 +466,16 @@ cryptof_ioctl(
+ 		case CRYPTO_RIPEMD160_HMAC:
+ 			thash = &auth_hash_hmac_ripemd_160;
+ 			break;
++		case CRYPTO_AES_128_GMAC:
++			thash = &auth_hash_gmac_aes_128;
++			break;
++		case CRYPTO_AES_192_GMAC:
++			thash = &auth_hash_gmac_aes_192;
++			break;
++		case CRYPTO_AES_256_GMAC:
++			thash = &auth_hash_gmac_aes_256;
++			break;
++
+ #ifdef notdef
+ 		case CRYPTO_MD5:
+ 			thash = &auth_hash_md5;
+diff --git a/sys/opencrypto/cryptodev.h b/sys/opencrypto/cryptodev.h
+index e299522..fbf049b 100644
+--- a/sys/opencrypto/cryptodev.h
++++ b/sys/opencrypto/cryptodev.h
+@@ -72,6 +72,7 @@
+ #define	SHA2_512_HASH_LEN	64
+ #define	MD5_KPDK_HASH_LEN	16
+ #define	SHA1_KPDK_HASH_LEN	20
++#define	AES_GMAC_HASH_LEN	16
+ /* Maximum hash algorithm result length */
+ #define	HASH_MAX_LEN		SHA2_512_HASH_LEN /* Keep this updated */
+ 
+@@ -100,6 +101,9 @@
+ #define CAMELLIA_BLOCK_LEN	16
+ #define EALG_MAX_BLOCK_LEN	AES_BLOCK_LEN /* Keep this updated */
+ 
++/* Maximum hash algorithm result length */
++#define AALG_MAX_RESULT_LEN	64 /* Keep this updated */
++
+ #define	CRYPTO_ALGORITHM_MIN	1
+ #define CRYPTO_DES_CBC		1
+ #define CRYPTO_3DES_CBC		2
+@@ -122,9 +126,15 @@
+ #define	CRYPTO_SHA2_256_HMAC	18
+ #define	CRYPTO_SHA2_384_HMAC	19
+ #define	CRYPTO_SHA2_512_HMAC	20
+-#define CRYPTO_CAMELLIA_CBC	21
++#define	CRYPTO_CAMELLIA_CBC	21
+ #define	CRYPTO_AES_XTS		22
+-#define	CRYPTO_ALGORITHM_MAX	22 /* Keep updated - see below */
++#define	CRYPTO_AES_CTR		23
++#define	CRYPTO_AES_GCM_16	24
++#define	CRYPTO_AES_128_GMAC	25
++#define	CRYPTO_AES_192_GMAC	26
++#define	CRYPTO_AES_256_GMAC	27
++#define	CRYPTO_AES_GMAC		28
++#define	CRYPTO_ALGORITHM_MAX	28 /* Keep updated - see below */
+ 
+ /* Algorithm flags */
+ #define	CRYPTO_ALG_FLAG_SUPPORTED	0x01 /* Algorithm is supported */
+@@ -276,7 +286,12 @@ struct cryptoini {
+ 	int		cri_mlen;	/* Number of bytes we want from the
+ 					   entire hash. 0 means all. */
+ 	caddr_t		cri_key;	/* key to use */
+-	u_int8_t	cri_iv[EALG_MAX_BLOCK_LEN];	/* IV to use */
++	union {
++		u_int8_t	iv[EALG_MAX_BLOCK_LEN];	/* IV to use */
++		u_int8_t	esn[4];			/* high-order ESN */
++	} u;
++#define cri_iv		u.iv
++#define cri_esn		u.esn
+ 	struct cryptoini *cri_next;
+ };
+ 
+@@ -294,8 +309,10 @@ struct cryptodesc {
+ #define	CRD_F_DSA_SHA_NEEDED	0x08	/* Compute SHA-1 of buffer for DSA */
+ #define	CRD_F_KEY_EXPLICIT	0x10	/* Key explicitly provided */
+ #define CRD_F_COMP		0x0f    /* Set when doing compression */
++#define CRD_F_ESN		0x20    /* Set when doing compression */
+ 
+ 	struct cryptoini	CRD_INI; /* Initialization/context data */
++#define crd_esn		CRD_INI.cri_esn
+ #define crd_iv		CRD_INI.cri_iv
+ #define crd_key		CRD_INI.cri_key
+ #define crd_alg		CRD_INI.cri_alg
+diff --git a/sys/opencrypto/cryptosoft.c b/sys/opencrypto/cryptosoft.c
+index d73f462..a1f7480 100644
+--- a/sys/opencrypto/cryptosoft.c
++++ b/sys/opencrypto/cryptosoft.c
+@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
+ #include <sys/random.h>
+ #include <sys/kernel.h>
+ #include <sys/uio.h>
++#include <sys/endian.h>
+ 
+ #include <crypto/blowfish/blowfish.h>
+ #include <crypto/sha1.h>
+@@ -60,6 +61,7 @@ u_int8_t hmac_opad_buffer[HMAC_MAX_BLOCK_LEN];
+ 
+ static	int swcr_encdec(struct cryptodesc *, struct swcr_data *, caddr_t, int);
+ static	int swcr_authcompute(struct cryptodesc *, struct swcr_data *, caddr_t, int);
++static	int swcr_authenc(struct cryptop *crp);
+ static	int swcr_compdec(struct cryptodesc *, struct swcr_data *, caddr_t, int);
+ static	int swcr_freesession(device_t dev, u_int64_t tid);
+ 
+@@ -579,6 +581,164 @@ swcr_authcompute(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
+ }
+ 
+ /*
++ * Apply a combined encryption-authentication transformation
++ */
++static int
++swcr_authenc(struct cryptop *crp)
++{
++	uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))];
++	u_char *blk = (u_char *)blkbuf;
++	u_char aalg[AALG_MAX_RESULT_LEN];
++	u_char iv[EALG_MAX_BLOCK_LEN];
++	union authctx ctx;
++	struct cryptodesc *crd, *crda = NULL, *crde = NULL;
++	struct swcr_data *sw, *swa, *swe = NULL;
++	struct auth_hash *axf = NULL;
++	struct enc_xform *exf = NULL;
++	caddr_t buf = (caddr_t)crp->crp_buf;
++	uint32_t *blkp;
++	int aadlen, blksz, i, ivlen, len, iskip, oskip;
++
++	ivlen = blksz = iskip = oskip = 0;
++
++	for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
++		for (sw = swcr_sessions[crp->crp_sid & 0xffffffff];
++		     sw && sw->sw_alg != crd->crd_alg;
++		     sw = sw->sw_next)
++			;
++		if (sw == NULL)
++			return (EINVAL);
++
++		switch (sw->sw_alg) {
++		case CRYPTO_AES_GCM_16:
++		case CRYPTO_AES_GMAC:
++			swe = sw;
++			crde = crd;
++			exf = swe->sw_exf;
++			ivlen = 8;
++			break;
++		case CRYPTO_AES_128_GMAC:
++		case CRYPTO_AES_192_GMAC:
++		case CRYPTO_AES_256_GMAC:
++			swa = sw;
++			crda = crd;
++			axf = swa->sw_axf;
++			if (swa->sw_ictx == 0)
++				return (EINVAL);
++			bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
++			blksz = axf->blocksize;
++			break;
++		default:
++			return (EINVAL);
++		}
++	}
++	if (crde == NULL || crda == NULL)
++		return (EINVAL);
++
++	/* Initialize the IV */
++	if (crde->crd_flags & CRD_F_ENCRYPT) {
++		/* IV explicitly provided ? */
++		if (crde->crd_flags & CRD_F_IV_EXPLICIT)
++			bcopy(crde->crd_iv, iv, ivlen);
++		else
++			arc4rand(iv, ivlen, 0);
++
++		/* Do we need to write the IV */
++		if (!(crde->crd_flags & CRD_F_IV_PRESENT))
++			crypto_copyback(crp->crp_flags, buf, crde->crd_inject,
++			    ivlen, iv);
++
++	} else {	/* Decryption */
++			/* IV explicitly provided ? */
++		if (crde->crd_flags & CRD_F_IV_EXPLICIT)
++			bcopy(crde->crd_iv, iv, ivlen);
++		else {
++			/* Get IV off buf */
++			crypto_copydata(crp->crp_flags, buf, crde->crd_inject,
++			    ivlen, iv);
++		}
++	}
++
++	/* Supply MAC with IV */
++	if (axf->Reinit)
++		axf->Reinit(&ctx, iv, ivlen);
++
++	/* Supply MAC with AAD */
++	aadlen = crda->crd_len;
++	/*
++	 * Section 5 of RFC 4106 specifies that AAD construction consists of
++	 * {SPI, ESN, SN} whereas the real packet contains only {SPI, SN}.
++	 * Unfortunately it doesn't follow a good example set in the Section
++	 * 3.3.2.1 of RFC 4303 where upper part of the ESN, located in the
++	 * external (to the packet) memory buffer, is processed by the hash
++	 * function in the end thus allowing to retain simple programming
++	 * interfaces and avoid kludges like the one below.
++	 */
++	if (crda->crd_flags & CRD_F_ESN) {
++		aadlen += 4;
++		/* SPI */
++		crypto_copydata(crp->crp_flags, buf, crda->crd_skip, 4, blk);
++		iskip = 4; /* loop below will start with an offset of 4 */
++		/* ESN */
++		bcopy(crda->crd_esn, blk + 4, 4);
++		oskip = iskip + 4; /* offset output buffer blk by 8 */
++	}
++	for (i = iskip; i < crda->crd_len; i += blksz) {
++		len = MIN(crda->crd_len - i, blksz - oskip);
++		crypto_copydata(crp->crp_flags, buf, crda->crd_skip + i, len,
++		    blk + oskip);
++		bzero(blk + len + oskip, blksz - len - oskip);
++		axf->Update(&ctx, blk, blksz);
++		oskip = 0; /* reset initial output offset */
++	}
++
++	if (exf->reinit)
++		exf->reinit(swe->sw_kschedule, iv);
++
++	/* Do encryption/decryption with MAC */
++	for (i = 0; i < crde->crd_len; i += blksz) {
++		len = MIN(crde->crd_len - i, blksz);
++		if (len < blksz)
++			bzero(blk, blksz);
++		crypto_copydata(crp->crp_flags, buf, crde->crd_skip + i, len,
++		    blk);
++		if (crde->crd_flags & CRD_F_ENCRYPT) {
++			exf->encrypt(swe->sw_kschedule, blk);
++			axf->Update(&ctx, blk, len);
++		} else {
++			axf->Update(&ctx, blk, len);
++			exf->decrypt(swe->sw_kschedule, blk);
++		}
++		crypto_copyback(crp->crp_flags, buf, crde->crd_skip + i, len,
++		    blk);
++	}
++
++	/* Do any required special finalization */
++	switch (crda->crd_alg) {
++		case CRYPTO_AES_128_GMAC:
++		case CRYPTO_AES_192_GMAC:
++		case CRYPTO_AES_256_GMAC:
++			/* length block */
++			bzero(blk, blksz);
++			blkp = (uint32_t *)blk + 1;
++			*blkp = htobe32(aadlen * 8);
++			blkp = (uint32_t *)blk + 3;
++			*blkp = htobe32(crde->crd_len * 8);
++			axf->Update(&ctx, blk, blksz);
++			break;
++	}
++
++	/* Finalize MAC */
++	axf->Final(aalg, &ctx);
++
++	/* Inject the authentication data */
++	crypto_copyback(crp->crp_flags, buf, crda->crd_inject, axf->hashsize,
++	    aalg);
++
++	return (0);
++}
++
++/*
+  * Apply a compression/decompression algorithm
+  */
+ static int
+@@ -738,6 +898,16 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
+ 		case CRYPTO_AES_XTS:
+ 			txf = &enc_xform_aes_xts;
+ 			goto enccommon;
++		case CRYPTO_AES_CTR:
++			txf = &enc_xform_aes_ctr;
++			goto enccommon;
++		case CRYPTO_AES_GCM_16:
++			txf = &enc_xform_aes_gcm;
++			goto enccommon;
++		case CRYPTO_AES_GMAC:
++			txf = &enc_xform_aes_gmac;
++			(*swd)->sw_exf = txf;
++			break;
+ 		case CRYPTO_CAMELLIA_CBC:
+ 			txf = &enc_xform_camellia;
+ 			goto enccommon;
+@@ -850,6 +1020,30 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
+ 			(*swd)->sw_axf = axf;
+ 			break;
+ #endif
++
++		case CRYPTO_AES_128_GMAC:
++			axf = &auth_hash_gmac_aes_128;
++			goto auth4common;
++
++		case CRYPTO_AES_192_GMAC:
++			axf = &auth_hash_gmac_aes_192;
++			goto auth4common;
++
++		case CRYPTO_AES_256_GMAC:
++			axf = &auth_hash_gmac_aes_256;
++		auth4common:
++			(*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
++			    M_NOWAIT);
++			if ((*swd)->sw_ictx == NULL) {
++				swcr_freesession(dev, i);
++				return ENOBUFS;
++			}
++			axf->Init((*swd)->sw_ictx);
++			axf->Setkey((*swd)->sw_ictx, cri->cri_key,
++			    cri->cri_klen / 8);
++			(*swd)->sw_axf = axf;
++			break;
++
+ 		case CRYPTO_DEFLATE_COMP:
+ 			cxf = &comp_algo_deflate;
+ 			(*swd)->sw_cxf = cxf;
+@@ -897,6 +1092,9 @@ swcr_freesession(device_t dev, u_int64_t tid)
+ 		case CRYPTO_SKIPJACK_CBC:
+ 		case CRYPTO_RIJNDAEL128_CBC:
+ 		case CRYPTO_AES_XTS:
++		case CRYPTO_AES_CTR:
++		case CRYPTO_AES_GCM_16:
++		case CRYPTO_AES_GMAC:
+ 		case CRYPTO_CAMELLIA_CBC:
+ 		case CRYPTO_NULL_CBC:
+ 			txf = swd->sw_exf;
+@@ -1011,6 +1209,7 @@ swcr_process(device_t dev, struct cryptop *crp, int hint)
+ 		case CRYPTO_SKIPJACK_CBC:
+ 		case CRYPTO_RIJNDAEL128_CBC:
+ 		case CRYPTO_AES_XTS:
++		case CRYPTO_AES_CTR:
+ 		case CRYPTO_CAMELLIA_CBC:
+ 			if ((crp->crp_etype = swcr_encdec(crd, sw,
+ 			    crp->crp_buf, crp->crp_flags)) != 0)
+@@ -1035,6 +1234,14 @@ swcr_process(device_t dev, struct cryptop *crp, int hint)
+ 				goto done;
+ 			break;
+ 
++		case CRYPTO_AES_GCM_16:
++		case CRYPTO_AES_GMAC:
++		case CRYPTO_AES_128_GMAC:
++		case CRYPTO_AES_192_GMAC:
++		case CRYPTO_AES_256_GMAC:
++			crp->crp_etype = swcr_authenc(crp);
++			goto done;
++
+ 		case CRYPTO_DEFLATE_COMP:
+ 			if ((crp->crp_etype = swcr_compdec(crd, sw, 
+ 			    crp->crp_buf, crp->crp_flags)) != 0)
+@@ -1104,6 +1311,12 @@ swcr_attach(device_t dev)
+ 	REGISTER(CRYPTO_SHA1);
+ 	REGISTER(CRYPTO_RIJNDAEL128_CBC);
+ 	REGISTER(CRYPTO_AES_XTS);
++	REGISTER(CRYPTO_AES_CTR);
++	REGISTER(CRYPTO_AES_GCM_16);
++	REGISTER(CRYPTO_AES_GMAC);
++	REGISTER(CRYPTO_AES_128_GMAC);
++	REGISTER(CRYPTO_AES_192_GMAC);
++	REGISTER(CRYPTO_AES_256_GMAC);
+  	REGISTER(CRYPTO_CAMELLIA_CBC);
+ 	REGISTER(CRYPTO_DEFLATE_COMP);
+ #undef REGISTER
+diff --git a/sys/opencrypto/gmac.c b/sys/opencrypto/gmac.c
+new file mode 100644
+index 0000000..72ac227
+--- /dev/null
++++ b/sys/opencrypto/gmac.c
+@@ -0,0 +1,163 @@
++/*	$OpenBSD: gmac.c,v 1.3 2011/01/11 15:44:23 deraadt Exp $	*/
++
++/*
++ * Copyright (c) 2010 Mike Belopuhov <mike@vantronix.net>
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++/*
++ * This code implements the Message Authentication part of the
++ * Galois/Counter Mode (as being described in the RFC 4543) using
++ * the AES cipher.  FIPS SP 800-38D describes the algorithm details.
++ */
++
++#ifdef _KERNEL
++#include <sys/param.h>
++#include <sys/systm.h>
++#include <sys/endian.h>
++#else
++#include <sys/types.h>
++#include <sys/endian.h>
++#include <stdint.h>
++#include <string.h>
++#endif
++
++#include <crypto/rijndael/rijndael.h>
++#include <opencrypto/gmac.h>
++
++void	ghash_gfmul(uint32_t *, uint32_t *, uint32_t *);
++void	ghash_update(GHASH_CTX *, uint8_t *, size_t);
++
++/* Computes a block multiplication in the GF(2^128) */
++void
++ghash_gfmul(uint32_t *X, uint32_t *Y, uint32_t *product)
++{
++	uint32_t	v[4];
++	uint32_t	z[4] = { 0, 0, 0, 0};
++	uint8_t		*x = (uint8_t *)X;
++	uint32_t	mul;
++	int		i;
++
++	v[0] = be32toh(Y[0]);
++	v[1] = be32toh(Y[1]);
++	v[2] = be32toh(Y[2]);
++	v[3] = be32toh(Y[3]);
++
++	for (i = 0; i < GMAC_BLOCK_LEN * 8; i++) {
++		/* update Z */
++		if (x[i >> 3] & (1 << (~i & 7))) {
++			z[0] ^= v[0];
++			z[1] ^= v[1];
++			z[2] ^= v[2];
++			z[3] ^= v[3];
++		} /* else: we preserve old values */
++
++		/* update V */
++		mul = v[3] & 1;
++		v[3] = (v[2] << 31) | (v[3] >> 1);
++		v[2] = (v[1] << 31) | (v[2] >> 1);
++		v[1] = (v[0] << 31) | (v[1] >> 1);
++		v[0] = (v[0] >> 1) ^ (0xe1000000 * mul);
++	}
++
++	product[0] = htobe32(z[0]);
++	product[1] = htobe32(z[1]);
++	product[2] = htobe32(z[2]);
++	product[3] = htobe32(z[3]);
++}
++
++void
++ghash_update(GHASH_CTX *ctx, uint8_t *X, size_t len)
++{
++	uint32_t	*x = (uint32_t *)X;
++	uint32_t	*s = (uint32_t *)ctx->S;
++	uint32_t	*y = (uint32_t *)ctx->Z;
++	int		i;
++
++	for (i = 0; i < len / GMAC_BLOCK_LEN; i++) {
++		s[0] = y[0] ^ x[0];
++		s[1] = y[1] ^ x[1];
++		s[2] = y[2] ^ x[2];
++		s[3] = y[3] ^ x[3];
++
++		ghash_gfmul((uint32_t *)ctx->S, (uint32_t *)ctx->H,
++		    (uint32_t *)ctx->S);
++
++		y = s;
++		x += 4;
++	}
++
++	bcopy(ctx->S, ctx->Z, GMAC_BLOCK_LEN);
++}
++
++#define AESCTR_NONCESIZE	4
++
++void
++AES_GMAC_Init(AES_GMAC_CTX *ctx)
++{
++	bzero(ctx->ghash.H, GMAC_BLOCK_LEN);
++	bzero(ctx->ghash.S, GMAC_BLOCK_LEN);
++	bzero(ctx->ghash.Z, GMAC_BLOCK_LEN);
++	bzero(ctx->J, GMAC_BLOCK_LEN);
++}
++
++void
++AES_GMAC_Setkey(AES_GMAC_CTX *ctx, const uint8_t *key, uint16_t klen)
++{
++	ctx->rounds = rijndaelKeySetupEnc(ctx->K, (u_char *)key,
++	    (klen - AESCTR_NONCESIZE) * 8);
++	/* copy out salt to the counter block */
++	bcopy(key + klen - AESCTR_NONCESIZE, ctx->J, AESCTR_NONCESIZE);
++	/* prepare a hash subkey */
++	rijndaelEncrypt(ctx->K, ctx->rounds, ctx->ghash.H, ctx->ghash.H);
++}
++
++void
++AES_GMAC_Reinit(AES_GMAC_CTX *ctx, const uint8_t *iv, uint16_t ivlen)
++{
++	/* copy out IV to the counter block */
++	bcopy(iv, ctx->J + AESCTR_NONCESIZE, ivlen);
++}
++
++int
++AES_GMAC_Update(AES_GMAC_CTX *ctx, const uint8_t *data, uint16_t len)
++{
++	uint8_t	blk[16] = {};
++	int	plen;
++
++	if (len > 0) {
++		plen = len % GMAC_BLOCK_LEN;
++		if (len >= GMAC_BLOCK_LEN)
++			ghash_update(&ctx->ghash, (uint8_t *)data, len - plen);
++		if (plen) {
++			bcopy((uint8_t *)data + (len - plen), blk, plen);
++			ghash_update(&ctx->ghash, blk, GMAC_BLOCK_LEN);
++		}
++	}
++	return (0);
++}
++
++void
++AES_GMAC_Final(uint8_t digest[GMAC_DIGEST_LEN], AES_GMAC_CTX *ctx)
++{
++	uint8_t		keystream[GMAC_BLOCK_LEN];
++	int		i;
++
++	/* do one round of GCTR */
++	ctx->J[GMAC_BLOCK_LEN - 1] = 1;
++	rijndaelEncrypt(ctx->K, ctx->rounds, ctx->J, keystream);
++	for (i = 0; i < GMAC_DIGEST_LEN; i++)
++		digest[i] = ctx->ghash.S[i] ^ keystream[i];
++	bzero(keystream, sizeof(keystream));
++}
+diff --git a/sys/opencrypto/gmac.h b/sys/opencrypto/gmac.h
+new file mode 100644
+index 0000000..94137da
+--- /dev/null
++++ b/sys/opencrypto/gmac.h
+@@ -0,0 +1,48 @@
++/*	$OpenBSD: gmac.h,v 1.2 2012/12/05 23:20:15 deraadt Exp $	*/
++
++/*
++ * Copyright (c) 2010 Mike Belopuhov <mike@vantronix.net>
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#ifndef _GMAC_H_
++#define _GMAC_H_
++
++#include <crypto/rijndael/rijndael.h>
++
++#define GMAC_BLOCK_LEN		16
++#define GMAC_DIGEST_LEN		16
++
++typedef struct _GHASH_CTX {
++	uint8_t		H[GMAC_BLOCK_LEN];		/* hash subkey */
++	uint8_t		S[GMAC_BLOCK_LEN];		/* state */
++	uint8_t		Z[GMAC_BLOCK_LEN];		/* initial state */
++} GHASH_CTX;
++
++typedef struct _AES_GMAC_CTX {
++	GHASH_CTX	ghash;
++	uint32_t	K[4*(RIJNDAEL_MAXNR + 1)];
++	uint8_t		J[GMAC_BLOCK_LEN];		/* counter block */
++	int		rounds;
++} AES_GMAC_CTX;
++
++__BEGIN_DECLS
++void	AES_GMAC_Init(AES_GMAC_CTX *);
++void	AES_GMAC_Setkey(AES_GMAC_CTX *, const uint8_t *, uint16_t);
++void	AES_GMAC_Reinit(AES_GMAC_CTX *, const uint8_t *, uint16_t);
++int	AES_GMAC_Update(AES_GMAC_CTX *, const uint8_t *, uint16_t);
++void	AES_GMAC_Final(uint8_t [GMAC_DIGEST_LEN], AES_GMAC_CTX *);
++__END_DECLS
++
++#endif /* _GMAC_H_ */
+diff --git a/sys/opencrypto/xform.c b/sys/opencrypto/xform.c
+index bfb061b..590116c 100644
+--- a/sys/opencrypto/xform.c
++++ b/sys/opencrypto/xform.c
+@@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
+ #include <opencrypto/deflate.h>
+ #include <opencrypto/rmd160.h>
+ #include <opencrypto/skipjack.h>
++#include <opencrypto/gmac.h>
+ 
+ #include <sys/md5.h>
+ 
+@@ -76,6 +77,7 @@ static	int blf_setkey(u_int8_t **, u_int8_t *, int);
+ static	int cast5_setkey(u_int8_t **, u_int8_t *, int);
+ static	int skipjack_setkey(u_int8_t **, u_int8_t *, int);
+ static	int rijndael128_setkey(u_int8_t **, u_int8_t *, int);
++static	int aes_ctr_setkey(u_int8_t **, u_int8_t *, int);
+ static	int aes_xts_setkey(u_int8_t **, u_int8_t *, int);
+ static	int cml_setkey(u_int8_t **, u_int8_t *, int);
+ 
+@@ -99,6 +101,8 @@ static	void rijndael128_decrypt(caddr_t, u_int8_t *);
+ static	void aes_xts_decrypt(caddr_t, u_int8_t *);
+ static	void cml_decrypt(caddr_t, u_int8_t *);
+ 
++static void aes_ctr_crypt(caddr_t, u_int8_t *);
++
+ static	void null_zerokey(u_int8_t **);
+ static	void des1_zerokey(u_int8_t **);
+ static	void des3_zerokey(u_int8_t **);
+@@ -106,26 +110,46 @@ static	void blf_zerokey(u_int8_t **);
+ static	void cast5_zerokey(u_int8_t **);
+ static	void skipjack_zerokey(u_int8_t **);
+ static	void rijndael128_zerokey(u_int8_t **);
++static	void aes_ctr_zerokey(u_int8_t **);
+ static	void aes_xts_zerokey(u_int8_t **);
+ static	void cml_zerokey(u_int8_t **);
+ 
++static	void aes_ctr_reinit(caddr_t, u_int8_t *);
+ static	void aes_xts_reinit(caddr_t, u_int8_t *);
++static	void aes_gcm_reinit(caddr_t, u_int8_t *);
+ 
+ static	void null_init(void *);
+-static	int null_update(void *, u_int8_t *, u_int16_t);
++static	void null_reinit(void *ctx, const u_int8_t *buf, u_int16_t len);
++static	int null_update(void *, const u_int8_t *, u_int16_t);
+ static	void null_final(u_int8_t *, void *);
+-static	int MD5Update_int(void *, u_int8_t *, u_int16_t);
++static	int MD5Update_int(void *, const u_int8_t *, u_int16_t);
+ static	void SHA1Init_int(void *);
+-static	int SHA1Update_int(void *, u_int8_t *, u_int16_t);
++static	int SHA1Update_int(void *, const u_int8_t *, u_int16_t);
+ static	void SHA1Final_int(u_int8_t *, void *);
+-static	int RMD160Update_int(void *, u_int8_t *, u_int16_t);
+-static	int SHA256Update_int(void *, u_int8_t *, u_int16_t);
+-static	int SHA384Update_int(void *, u_int8_t *, u_int16_t);
+-static	int SHA512Update_int(void *, u_int8_t *, u_int16_t);
++static	int RMD160Update_int(void *, const u_int8_t *, u_int16_t);
++static	int SHA256Update_int(void *, const u_int8_t *, u_int16_t);
++static	int SHA384Update_int(void *, const u_int8_t *, u_int16_t);
++static	int SHA512Update_int(void *, const u_int8_t *, u_int16_t);
+ 
+ static	u_int32_t deflate_compress(u_int8_t *, u_int32_t, u_int8_t **);
+ static	u_int32_t deflate_decompress(u_int8_t *, u_int32_t, u_int8_t **);
+ 
++#define AESCTR_NONCESIZE	4
++#define AESCTR_IVSIZE		8
++#define AESCTR_BLOCKSIZE	16
++
++struct aes_ctr_ctx {
++	u_int32_t	ac_ek[4*(RIJNDAEL_MAXNR + 1)];
++	/*
++	 * ac_block is initalized to: [ NONCE : IV : CNTR ]
++	 * Where NONCE is the last four bytes of the key.
++	 * IV is provided by user.
++	 * CNTR is initalized to 0 for CTR and 1 for GCM.
++	 */
++	u_int8_t	ac_block[AESCTR_BLOCKSIZE];
++	int		ac_nr;
++};
++
+ MALLOC_DEFINE(M_XDATA, "xform", "xform data buffers");
+ 
+ /* Encryption instances */
+@@ -137,7 +161,7 @@ struct enc_xform enc_xform_null = {
+ 	null_decrypt,
+ 	null_setkey,
+ 	null_zerokey,
+-	NULL
++	NULL,
+ };
+ 
+ struct enc_xform enc_xform_des = {
+@@ -147,7 +171,7 @@ struct enc_xform enc_xform_des = {
+ 	des1_decrypt,
+ 	des1_setkey,
+ 	des1_zerokey,
+-	NULL
++	NULL,
+ };
+ 
+ struct enc_xform enc_xform_3des = {
+@@ -157,7 +181,7 @@ struct enc_xform enc_xform_3des = {
+ 	des3_decrypt,
+ 	des3_setkey,
+ 	des3_zerokey,
+-	NULL
++	NULL,
+ };
+ 
+ struct enc_xform enc_xform_blf = {
+@@ -167,7 +191,7 @@ struct enc_xform enc_xform_blf = {
+ 	blf_decrypt,
+ 	blf_setkey,
+ 	blf_zerokey,
+-	NULL
++	NULL,
+ };
+ 
+ struct enc_xform enc_xform_cast5 = {
+@@ -177,17 +201,16 @@ struct enc_xform enc_xform_cast5 = {
+ 	cast5_decrypt,
+ 	cast5_setkey,
+ 	cast5_zerokey,
+-	NULL
++	NULL,
+ };
+ 
+ struct enc_xform enc_xform_skipjack = {
+ 	CRYPTO_SKIPJACK_CBC, "Skipjack",
+ 	SKIPJACK_BLOCK_LEN, 10, 10,
+ 	skipjack_encrypt,
+-	skipjack_decrypt,
+-	skipjack_setkey,
++	skipjack_decrypt, skipjack_setkey,
+ 	skipjack_zerokey,
+-	NULL
++	NULL,
+ };
+ 
+ struct enc_xform enc_xform_rijndael128 = {
+@@ -197,7 +220,37 @@ struct enc_xform enc_xform_rijndael128 = {
+ 	rijndael128_decrypt,
+ 	rijndael128_setkey,
+ 	rijndael128_zerokey,
+-	NULL
++	NULL,
++};
++
++struct enc_xform enc_xform_aes_ctr = {
++	CRYPTO_AES_CTR, "AES-CTR",
++	RIJNDAEL128_BLOCK_LEN, 8+4, 32+4,
++	aes_ctr_crypt,
++	aes_ctr_crypt,
++	aes_ctr_setkey,
++	rijndael128_zerokey,
++	aes_ctr_reinit,
++};
++
++struct enc_xform enc_xform_aes_gcm = {
++	CRYPTO_AES_GCM_16, "AES-GCM",
++	1, 16+4, 32+4,
++	aes_ctr_crypt,
++	aes_ctr_crypt,
++	aes_ctr_setkey,
++	aes_ctr_zerokey,
++	aes_gcm_reinit,
++};
++
++struct enc_xform enc_xform_aes_gmac = {
++	CRYPTO_AES_GMAC, "AES-GMAC",
++	1, 16+4, 32+4,
++	NULL,
++	NULL,
++	NULL,
++	NULL,
++	NULL,
+ };
+ 
+ struct enc_xform enc_xform_aes_xts = {
+@@ -217,7 +270,7 @@ struct enc_xform enc_xform_arc4 = {
+ 	NULL,
+ 	NULL,
+ 	NULL,
+-	NULL
++	NULL,
+ };
+ 
+ struct enc_xform enc_xform_camellia = {
+@@ -227,70 +280,100 @@ struct enc_xform enc_xform_camellia = {
+ 	cml_decrypt,
+ 	cml_setkey,
+ 	cml_zerokey,
+-	NULL
++	NULL,
+ };
+ 
+ /* Authentication instances */
+-struct auth_hash auth_hash_null = {
++struct auth_hash auth_hash_null = {	/* NB: context isn't used */
+ 	CRYPTO_NULL_HMAC, "NULL-HMAC",
+-	0, NULL_HASH_LEN, NULL_HMAC_BLOCK_LEN, sizeof(int),	/* NB: context isn't used */
+-	null_init, null_update, null_final
++	0, NULL_HASH_LEN, sizeof(int), NULL_HMAC_BLOCK_LEN,
++	null_init, null_reinit, null_reinit, null_update, null_final
+ };
+ 
+ struct auth_hash auth_hash_hmac_md5 = {
+ 	CRYPTO_MD5_HMAC, "HMAC-MD5",
+-	16, MD5_HASH_LEN, MD5_HMAC_BLOCK_LEN, sizeof(MD5_CTX),
+-	(void (*) (void *)) MD5Init, MD5Update_int,
++	16, MD5_HASH_LEN, sizeof(MD5_CTX), MD5_HMAC_BLOCK_LEN,
++	(void (*) (void *)) MD5Init, NULL, NULL, MD5Update_int,
+ 	(void (*) (u_int8_t *, void *)) MD5Final
+ };
+ 
+ struct auth_hash auth_hash_hmac_sha1 = {
+ 	CRYPTO_SHA1_HMAC, "HMAC-SHA1",
+-	20, SHA1_HASH_LEN, SHA1_HMAC_BLOCK_LEN, sizeof(SHA1_CTX),
+-	SHA1Init_int, SHA1Update_int, SHA1Final_int
++	20, SHA1_HASH_LEN, sizeof(SHA1_CTX), SHA1_HMAC_BLOCK_LEN,
++	SHA1Init_int, NULL, NULL, SHA1Update_int, SHA1Final_int
+ };
+ 
+ struct auth_hash auth_hash_hmac_ripemd_160 = {
+ 	CRYPTO_RIPEMD160_HMAC, "HMAC-RIPEMD-160",
+-	20, RIPEMD160_HASH_LEN, RIPEMD160_HMAC_BLOCK_LEN, sizeof(RMD160_CTX),
+-	(void (*)(void *)) RMD160Init, RMD160Update_int,
++	20, RIPEMD160_HASH_LEN, sizeof(RMD160_CTX), RIPEMD160_HMAC_BLOCK_LEN,
++	(void (*)(void *)) RMD160Init, NULL, NULL, RMD160Update_int,
+ 	(void (*)(u_int8_t *, void *)) RMD160Final
+ };
+ 
+ struct auth_hash auth_hash_key_md5 = {
+ 	CRYPTO_MD5_KPDK, "Keyed MD5",
+-	0, MD5_KPDK_HASH_LEN, 0, sizeof(MD5_CTX),
+-	(void (*)(void *)) MD5Init, MD5Update_int,
++	0, MD5_KPDK_HASH_LEN, sizeof(MD5_CTX), 0,
++	(void (*)(void *)) MD5Init, NULL, NULL, MD5Update_int,
+ 	(void (*)(u_int8_t *, void *)) MD5Final
+ };
+ 
+ struct auth_hash auth_hash_key_sha1 = {
+ 	CRYPTO_SHA1_KPDK, "Keyed SHA1",
+-	0, SHA1_KPDK_HASH_LEN, 0, sizeof(SHA1_CTX),
+-	SHA1Init_int, SHA1Update_int, SHA1Final_int
++	0, SHA1_KPDK_HASH_LEN, sizeof(SHA1_CTX), 0,
++	SHA1Init_int, NULL, NULL, SHA1Update_int, SHA1Final_int
+ };
+ 
+ struct auth_hash auth_hash_hmac_sha2_256 = {
+ 	CRYPTO_SHA2_256_HMAC, "HMAC-SHA2-256",
+-	32, SHA2_256_HASH_LEN, SHA2_256_HMAC_BLOCK_LEN, sizeof(SHA256_CTX),
+-	(void (*)(void *)) SHA256_Init, SHA256Update_int,
++	32, SHA2_256_HASH_LEN, sizeof(SHA256_CTX), SHA2_256_HMAC_BLOCK_LEN,
++	(void (*)(void *)) SHA256_Init, NULL, NULL, SHA256Update_int,
+ 	(void (*)(u_int8_t *, void *)) SHA256_Final
+ };
+ 
+ struct auth_hash auth_hash_hmac_sha2_384 = {
+ 	CRYPTO_SHA2_384_HMAC, "HMAC-SHA2-384",
+-	48, SHA2_384_HASH_LEN, SHA2_384_HMAC_BLOCK_LEN, sizeof(SHA384_CTX),
+-	(void (*)(void *)) SHA384_Init, SHA384Update_int,
++	48, SHA2_384_HASH_LEN, sizeof(SHA384_CTX), SHA2_384_HMAC_BLOCK_LEN,
++	(void (*)(void *)) SHA384_Init, NULL, NULL, SHA384Update_int,
+ 	(void (*)(u_int8_t *, void *)) SHA384_Final
+ };
+ 
+ struct auth_hash auth_hash_hmac_sha2_512 = {
+ 	CRYPTO_SHA2_512_HMAC, "HMAC-SHA2-512",
+-	64, SHA2_512_HASH_LEN, SHA2_512_HMAC_BLOCK_LEN, sizeof(SHA512_CTX),
+-	(void (*)(void *)) SHA512_Init, SHA512Update_int,
++	64, SHA2_512_HASH_LEN, sizeof(SHA512_CTX), SHA2_512_HMAC_BLOCK_LEN,
++	(void (*)(void *)) SHA512_Init, NULL, NULL, SHA512Update_int,
+ 	(void (*)(u_int8_t *, void *)) SHA512_Final
+ };
+ 
++struct auth_hash auth_hash_gmac_aes_128 = {
++	CRYPTO_AES_128_GMAC, "GMAC-AES-128",
++	16+4, 16, sizeof(AES_GMAC_CTX), GMAC_BLOCK_LEN,
++	(void (*)(void *)) AES_GMAC_Init,
++	(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey,
++	(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Reinit,
++	(int  (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Update,
++	(void (*)(u_int8_t *, void *)) AES_GMAC_Final
++};
++
++struct auth_hash auth_hash_gmac_aes_192 = {
++	CRYPTO_AES_192_GMAC, "GMAC-AES-192",
++	24+4, 16, sizeof(AES_GMAC_CTX), GMAC_BLOCK_LEN,
++	(void (*)(void *)) AES_GMAC_Init,
++	(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey,
++	(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Reinit,
++	(int  (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Update,
++	(void (*)(u_int8_t *, void *)) AES_GMAC_Final
++};
++
++struct auth_hash auth_hash_gmac_aes_256 = {
++	CRYPTO_AES_256_GMAC, "GMAC-AES-256",
++	32+4, 16, sizeof(AES_GMAC_CTX), GMAC_BLOCK_LEN,
++	(void (*)(void *)) AES_GMAC_Init,
++	(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey,
++	(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Reinit,
++	(int  (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Update,
++	(void (*)(u_int8_t *, void *)) AES_GMAC_Final
++};
++
+ /* Compression instance */
+ struct comp_algo comp_algo_deflate = {
+ 	CRYPTO_DEFLATE_COMP, "Deflate",
+@@ -579,6 +662,79 @@ rijndael128_zerokey(u_int8_t **sched)
+ 	*sched = NULL;
+ }
+ 
++void
++aes_ctr_reinit(caddr_t key, u_int8_t *iv)
++{
++	struct aes_ctr_ctx *ctx;
++
++	ctx = (struct aes_ctr_ctx *)key;
++	bcopy(iv, ctx->ac_block + AESCTR_NONCESIZE, AESCTR_IVSIZE);
++
++	/* reset counter */
++	bzero(ctx->ac_block + AESCTR_NONCESIZE + AESCTR_IVSIZE, 4);
++}
++
++void
++aes_gcm_reinit(caddr_t key, u_int8_t *iv)
++{
++	struct aes_ctr_ctx *ctx;
++
++	aes_ctr_reinit(key, iv);
++
++	ctx = (struct aes_ctr_ctx *)key;
++	ctx->ac_block[AESCTR_BLOCKSIZE - 1] = 1; /* GCM starts with 1 */
++}
++
++void
++aes_ctr_crypt(caddr_t key, u_int8_t *data)
++{
++	struct aes_ctr_ctx *ctx;
++	u_int8_t keystream[AESCTR_BLOCKSIZE];
++	int i;
++
++	ctx = (struct aes_ctr_ctx *)key;
++	/* increment counter */
++	for (i = AESCTR_BLOCKSIZE - 1;
++	     i >= AESCTR_NONCESIZE + AESCTR_IVSIZE; i--)
++		if (++ctx->ac_block[i])   /* continue on overflow */
++			break;
++	rijndaelEncrypt(ctx->ac_ek, ctx->ac_nr, ctx->ac_block, keystream);
++	for (i = 0; i < AESCTR_BLOCKSIZE; i++)
++		data[i] ^= keystream[i];
++	bzero(keystream, sizeof(keystream));
++}
++
++int
++aes_ctr_setkey(u_int8_t **sched, u_int8_t *key, int len)
++{
++	struct aes_ctr_ctx *ctx;
++
++	if (len < AESCTR_NONCESIZE)
++		return EINVAL;
++
++	*sched = malloc(sizeof(struct aes_ctr_ctx), M_CRYPTO_DATA,
++	    M_NOWAIT | M_ZERO);
++	if (*sched == NULL)
++		return ENOMEM;
++
++	ctx = (struct aes_ctr_ctx *)*sched;
++	ctx->ac_nr = rijndaelKeySetupEnc(ctx->ac_ek, (u_char *)key,
++	    (len - AESCTR_NONCESIZE) * 8);
++	if (ctx->ac_nr == 0)
++		return EINVAL;
++	bcopy(key + len - AESCTR_NONCESIZE, ctx->ac_block, AESCTR_NONCESIZE);
++	return 0;
++}
++
++void
++aes_ctr_zerokey(u_int8_t **sched)
++{
++
++	bzero(*sched, sizeof(struct aes_ctr_ctx));
++	free(*sched, M_CRYPTO_DATA);
++	*sched = NULL;
++}
++
+ #define	AES_XTS_BLOCKSIZE	16
+ #define	AES_XTS_IVSIZE		8
+ #define	AES_XTS_ALPHA		0x87	/* GF(2^128) generator polynomial */
+@@ -728,8 +884,13 @@ null_init(void *ctx)
+ {
+ }
+ 
++static void
++null_reinit(void *ctx, const u_int8_t *buf, u_int16_t len)
++{
++}
++
+ static int
+-null_update(void *ctx, u_int8_t *buf, u_int16_t len)
++null_update(void *ctx, const u_int8_t *buf, u_int16_t len)
+ {
+ 	return 0;
+ }
+@@ -742,14 +903,14 @@ null_final(u_int8_t *buf, void *ctx)
+ }
+ 
+ static int
+-RMD160Update_int(void *ctx, u_int8_t *buf, u_int16_t len)
++RMD160Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
+ {
+ 	RMD160Update(ctx, buf, len);
+ 	return 0;
+ }
+ 
+ static int
+-MD5Update_int(void *ctx, u_int8_t *buf, u_int16_t len)
++MD5Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
+ {
+ 	MD5Update(ctx, buf, len);
+ 	return 0;
+@@ -762,7 +923,7 @@ SHA1Init_int(void *ctx)
+ }
+ 
+ static int
+-SHA1Update_int(void *ctx, u_int8_t *buf, u_int16_t len)
++SHA1Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
+ {
+ 	SHA1Update(ctx, buf, len);
+ 	return 0;
+@@ -775,21 +936,21 @@ SHA1Final_int(u_int8_t *blk, void *ctx)
+ }
+ 
+ static int
+-SHA256Update_int(void *ctx, u_int8_t *buf, u_int16_t len)
++SHA256Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
+ {
+ 	SHA256_Update(ctx, buf, len);
+ 	return 0;
+ }
+ 
+ static int
+-SHA384Update_int(void *ctx, u_int8_t *buf, u_int16_t len)
++SHA384Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
+ {
+ 	SHA384_Update(ctx, buf, len);
+ 	return 0;
+ }
+ 
+ static int
+-SHA512Update_int(void *ctx, u_int8_t *buf, u_int16_t len)
++SHA512Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
+ {
+ 	SHA512_Update(ctx, buf, len);
+ 	return 0;
+diff --git a/sys/opencrypto/xform.h b/sys/opencrypto/xform.h
+index 8df7b07..c92723c 100644
+--- a/sys/opencrypto/xform.h
++++ b/sys/opencrypto/xform.h
+@@ -29,6 +29,7 @@
+ #include <crypto/sha1.h>
+ #include <crypto/sha2/sha2.h>
+ #include <opencrypto/rmd160.h>
++#include <opencrypto/gmac.h>
+ 
+ /* Declarations */
+ struct auth_hash {
+@@ -36,10 +37,12 @@ struct auth_hash {
+ 	char *name;
+ 	u_int16_t keysize;
+ 	u_int16_t hashsize; 
+-	u_int16_t blocksize;
+ 	u_int16_t ctxsize;
++	u_int16_t blocksize;
+ 	void (*Init) (void *);
+-	int  (*Update) (void *, u_int8_t *, u_int16_t);
++	void (*Setkey) (void *, const u_int8_t *, u_int16_t);
++	void (*Reinit) (void *, const u_int8_t *, u_int16_t);
++	int  (*Update) (void *, const u_int8_t *, u_int16_t);
+ 	void (*Final) (u_int8_t *, void *);
+ };
+ 
+@@ -53,7 +56,7 @@ struct enc_xform {
+ 	u_int16_t minkey, maxkey;
+ 	void (*encrypt) (caddr_t, u_int8_t *);
+ 	void (*decrypt) (caddr_t, u_int8_t *);
+-	int (*setkey) (u_int8_t **, u_int8_t *, int len);
++	int (*setkey) (u_int8_t **, u_int8_t *, int);
+ 	void (*zerokey) (u_int8_t **);
+ 	void (*reinit) (caddr_t, u_int8_t *);
+ };
+@@ -73,6 +76,7 @@ union authctx {
+ 	SHA256_CTX sha256ctx;
+ 	SHA384_CTX sha384ctx;
+ 	SHA512_CTX sha512ctx;
++	AES_GMAC_CTX aes_gmac_ctx;
+ };
+ 
+ extern struct enc_xform enc_xform_null;
+@@ -82,6 +86,9 @@ extern struct enc_xform enc_xform_blf;
+ extern struct enc_xform enc_xform_cast5;
+ extern struct enc_xform enc_xform_skipjack;
+ extern struct enc_xform enc_xform_rijndael128;
++extern struct enc_xform enc_xform_aes_ctr;
++extern struct enc_xform enc_xform_aes_gcm;
++extern struct enc_xform enc_xform_aes_gmac;
+ extern struct enc_xform enc_xform_aes_xts;
+ extern struct enc_xform enc_xform_arc4;
+ extern struct enc_xform enc_xform_camellia;
+@@ -95,6 +102,9 @@ extern struct auth_hash auth_hash_hmac_ripemd_160;
+ extern struct auth_hash auth_hash_hmac_sha2_256;
+ extern struct auth_hash auth_hash_hmac_sha2_384;
+ extern struct auth_hash auth_hash_hmac_sha2_512;
++extern struct auth_hash auth_hash_gmac_aes_128;
++extern struct auth_hash auth_hash_gmac_aes_192;
++extern struct auth_hash auth_hash_gmac_aes_256;
+ 
+ extern struct comp_algo comp_algo_deflate;
+ 
+diff --git a/usr.bin/netstat/ipsec.c b/usr.bin/netstat/ipsec.c
+index b4014ad..af1b234 100644
+--- a/usr.bin/netstat/ipsec.c
++++ b/usr.bin/netstat/ipsec.c
+@@ -155,6 +155,9 @@ static struct val2str ipsec_espnames[] = {
+ #ifdef SADB_X_EALG_AESCTR
+ 	{ SADB_X_EALG_AESCTR, "aes-ctr", },
+ #endif
++#ifdef SADB_X_EALG_AESGCM16
++	{ SADB_X_EALG_AESGCM16, "aes-gcm-16", },
++#endif
+ 	{ -1, NULL },
+ };
+ 
