opencrypto - Add AES GCM/GMAC support
authorAlex Hornung <ahornung@gmail.com>
Mon, 27 Jun 2011 20:17:24 +0000 (21:17 +0100)
committerAlex Hornung <ahornung@gmail.com>
Fri, 1 Jul 2011 20:57:06 +0000 (21:57 +0100)
Obtained-from: OpenBSD

sys/conf/files
sys/opencrypto/cryptodev.h
sys/opencrypto/cryptosoft.c
sys/opencrypto/gmac.c [new file with mode: 0644]
sys/opencrypto/gmac.h [new file with mode: 0644]
sys/opencrypto/xform.c
sys/opencrypto/xform.h

index c02e405..5b2bed7 100644 (file)
@@ -1917,6 +1917,7 @@ opencrypto/cryptodev.c                    optional cryptodev
 opencrypto/cryptodev_if.m              optional crypto
 opencrypto/cryptosoft.c                        optional crypto
 opencrypto/deflate.c                   optional crypto
+opencrypto/gmac.c                      optional crypto
 opencrypto/rmd160.c                    optional crypto
 opencrypto/skipjack.c                  optional crypto
 opencrypto/xform.c                     optional crypto
index 7da7e67..37a8c39 100644 (file)
 #define AES_XTS_IV_LEN         8
 #define AESCTR_IV_LEN          8
 #define AESCTR_BLOCK_LEN       16
+#define AESGCM_IV_LEN          8
+#define AESGCM_BLOCK_LEN       1
+#define AESGMAC_IV_LEN         8
+#define AESGMAC_BLOCK_LEN      1
 #define CAMELLIA_BLOCK_LEN     16
 #define EALG_MAX_BLOCK_LEN     AES_BLOCK_LEN /* Keep this updated */
 
 #define CRYPTO_CAMELLIA_CBC    21
 #define CRYPTO_AES_XTS         22
 #define CRYPTO_AES_CTR          23
-#define        CRYPTO_ALGORITHM_MAX    23 /* Keep updated - see below */
+#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 */
@@ -345,6 +354,8 @@ struct cryptop {
        int (*crp_callback)(struct cryptop *); /* Callback function */
 
        struct timespec crp_tstamp;     /* performance time stamp */
+
+       caddr_t         crp_mac;
 };
 
 #define CRYPTO_BUF_CONTIG      0x0
index 15e3ba1..4106f49 100644 (file)
@@ -32,6 +32,7 @@
 #include <sys/module.h>
 #include <sys/sysctl.h>
 #include <sys/errno.h>
+#include <sys/endian.h>
 #include <sys/random.h>
 #include <sys/kernel.h>
 #include <sys/uio.h>
@@ -64,6 +65,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_combined(struct cryptop *);
 static int swcr_compdec(struct cryptodesc *, struct swcr_data *, caddr_t, int);
 static int swcr_freesession(device_t dev, u_int64_t tid);
 static int swcr_freesession_slot(struct swcr_data **swdp, u_int32_t sid);
@@ -590,6 +592,163 @@ swcr_authcompute(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
 }
 
 /*
+ * Apply a combined encryption-authentication transformation
+ */
+static int
+swcr_combined(struct cryptop *crp)
+{
+       uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))];
+       u_char *blk = (u_char *)blkbuf;
+       u_char aalg[HASH_MAX_LEN];
+       u_char iv[EALG_MAX_BLOCK_LEN];
+       uint8_t *kschedule;
+       union authctx ctx;
+       struct cryptodesc *crd, *crda = NULL, *crde = NULL;
+       struct swcr_data *sw, *swa, *swe;
+       struct auth_hash *axf = NULL;
+       struct enc_xform *exf = NULL;
+       struct mbuf *m = NULL;
+       struct uio *uio = NULL;
+       caddr_t buf = (caddr_t)crp->crp_buf;
+       uint32_t *blkp;
+       int i, blksz, ivlen, outtype, len;
+
+       blksz = 0;
+       ivlen = 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 = exf->ivsize;
+                       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);
+
+       if (crp->crp_flags & CRYPTO_F_IMBUF) {
+               outtype = CRYPTO_BUF_MBUF;
+               m = (struct mbuf *)buf;
+       } else {
+               outtype = CRYPTO_BUF_IOV;
+               uio = (struct uio *)buf;
+       }
+
+       /* 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
+                       karc4rand(iv, ivlen);
+
+               /* Do we need to write the IV */
+               if (!(crde->crd_flags & CRD_F_IV_PRESENT))
+                       crypto_copyback(crde->crd_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(crde->crd_flags, buf, crde->crd_inject,
+                           ivlen, iv);
+       }
+
+       /* Supply MAC with IV */
+       if (axf->Reinit)
+               axf->Reinit(&ctx, iv, ivlen);
+
+       /* Supply MAC with AAD */
+       for (i = 0; i < crda->crd_len; i += blksz) {
+               len = MIN(crda->crd_len - i, blksz);
+               crypto_copydata(crde->crd_flags, buf, crda->crd_skip + i, len,
+                   blk);
+               axf->Update(&ctx, blk, len);
+       }
+
+       spin_lock(&swcr_spin);
+       kschedule = sw->sw_kschedule;
+       ++sw->sw_kschedule_refs;
+       spin_unlock(&swcr_spin);
+
+       if (exf->reinit)
+               exf->reinit(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(crde->crd_flags, buf, crde->crd_skip + i, len,
+                   blk);
+               if (crde->crd_flags & CRD_F_ENCRYPT) {
+                       exf->encrypt(kschedule, blk, iv);
+                       axf->Update(&ctx, blk, len);
+               } else {
+                       axf->Update(&ctx, blk, len);
+                       exf->decrypt(kschedule, blk, iv);
+               }
+               crypto_copyback(crde->crd_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(crda->crd_len * 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(crda->crd_flags, crp->crp_buf, crda->crd_inject,
+           axf->blocksize, aalg);
+
+       spin_lock(&swcr_spin);
+       --sw->sw_kschedule_refs;
+       spin_unlock(&swcr_spin);
+
+       return (0);
+}
+
+/*
  * Apply a compression/decompression algorithm
  */
 static int
@@ -716,6 +875,13 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
                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;
@@ -829,6 +995,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 = kmalloc(axf->ctxsize, M_CRYPTO_DATA,
+                           M_NOWAIT);
+                       if ((*swd)->sw_ictx == NULL) {
+                               swcr_freesession_slot(&swd_base, 0);
+                               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;
@@ -952,6 +1142,8 @@ swcr_freesession_slot(struct swcr_data **swdp, u_int32_t sid)
                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;
@@ -993,6 +1185,9 @@ swcr_freesession_slot(struct swcr_data **swdp, u_int32_t sid)
                        }
                        break;
 
+               case CRYPTO_AES_128_GMAC:
+               case CRYPTO_AES_192_GMAC:
+               case CRYPTO_AES_256_GMAC:
                case CRYPTO_MD5:
                case CRYPTO_SHA1:
                        axf = swd->sw_axf;
@@ -1094,6 +1289,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_combined(crp);
+                       goto done;
+
                case CRYPTO_DEFLATE_COMP:
                        if ((crp->crp_etype = swcr_compdec(crd, sw, 
                            crp->crp_buf, crp->crp_flags)) != 0)
@@ -1167,6 +1370,11 @@ swcr_attach(device_t dev)
        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 (file)
index 0000000..f5a9cfe
--- /dev/null
@@ -0,0 +1,159 @@
+/*     $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.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/endian.h>
+
+#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, __DECONST(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, uint8_t *data, uint16_t len)
+{
+       uint32_t        blk[4] = { 0, 0, 0, 0 };
+       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), (uint8_t *)blk,
+                           plen);
+                       ghash_update(&ctx->ghash, (uint8_t *)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 (file)
index 0000000..c5a5324
--- /dev/null
@@ -0,0 +1,51 @@
+/*     $OpenBSD: gmac.h,v 1.1 2010/09/22 11:54:23 mikeb 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;
+
+#include <sys/cdefs.h>
+
+__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 *, uint8_t *, uint16_t);
+void   AES_GMAC_Final(uint8_t [GMAC_DIGEST_LEN], AES_GMAC_CTX *);
+__END_DECLS
+
+#endif /* _GMAC_H_ */
+
index 2560785..1c75b5b 100644 (file)
@@ -56,6 +56,7 @@
 #include <opencrypto/deflate.h>
 #include <opencrypto/rmd160.h>
 #include <opencrypto/skipjack.h>
+#include <opencrypto/gmac.h>
 
 #include <sys/md5.h>
 
@@ -106,6 +107,7 @@ static      void aes_ctr_crypt(caddr_t, u_int8_t *, 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);
@@ -220,6 +222,26 @@ struct enc_xform enc_xform_aes_ctr = {
        aes_ctr_reinit
 };
 
+struct enc_xform enc_xform_aes_gcm = {
+       CRYPTO_AES_GCM_16, "AES-GCM",
+       AESGCM_BLOCK_LEN, AESGCM_IV_LEN, 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",
+       AESGMAC_BLOCK_LEN, AESGMAC_IV_LEN, 16+4, 32+4,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL
+};
+
 struct enc_xform enc_xform_arc4 = {
        CRYPTO_ARC4, "ARC4",
        1, 1, 1, 32,
@@ -244,63 +266,101 @@ struct enc_xform enc_xform_camellia = {
 struct auth_hash auth_hash_null = {
        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
+       null_init, NULL, NULL, 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,
+       (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
+       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,
+       (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,
+       (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
+       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,
+       (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,
+       (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,
+       (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, 16, sizeof(AES_GMAC_CTX),
+       (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 *, 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, 16, sizeof(AES_GMAC_CTX),
+       (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 *, 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, 16, sizeof(AES_GMAC_CTX),
+       (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 *, 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",
@@ -762,6 +822,19 @@ aes_ctr_zerokey(u_int8_t **sched)
 }
 
 static void
+aes_gcm_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_IV_LEN);
+
+       /* reset counter */
+       bzero(ctx->ac_block + AESCTR_NONCESIZE + AESCTR_IV_LEN, 4);
+       ctx->ac_block[AESCTR_BLOCK_LEN - 1] = 1; /* GCM starts with 1 */
+}
+
+static void
 cml_encrypt(caddr_t key, u_int8_t *blk, u_int8_t *iv)
 {
        camellia_encrypt((camellia_ctx *) key, (u_char *) blk, (u_char *) blk);
index cfc49ce..b584b85 100644 (file)
@@ -30,6 +30,7 @@
 #include <crypto/sha1.h>
 #include <crypto/sha2/sha2.h>
 #include <opencrypto/rmd160.h>
+#include <opencrypto/gmac.h>
 
 /* Declarations */
 struct auth_hash {
@@ -40,6 +41,8 @@ struct auth_hash {
        u_int16_t blocksize;
        u_int16_t ctxsize;
        void (*Init) (void *);
+       void (*Setkey) (void *, const u_int8_t *, u_int16_t);
+       void (*Reinit) (void *, const u_int8_t *, u_int16_t);
        int  (*Update) (void *, u_int8_t *, u_int16_t);
        void (*Final) (u_int8_t *, void *);
 };
@@ -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;
@@ -84,6 +88,8 @@ extern struct enc_xform enc_xform_skipjack;
 extern struct enc_xform enc_xform_rijndael128;
 extern struct enc_xform enc_xform_aes_xts;
 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_arc4;
 extern struct enc_xform enc_xform_camellia;
 
@@ -96,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;