summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Belopuhov <mikeb@cvs.openbsd.org>2010-09-22 11:54:24 +0000
committerMike Belopuhov <mikeb@cvs.openbsd.org>2010-09-22 11:54:24 +0000
commit9a8c4153305177b616e3d7e1c5da5f342c96dc5b (patch)
treef73bcdb9b727a468bf8a906e8f246e02edd6bed6
parent6ec85bf63c728dc364401adfb19bc65cde8d7f54 (diff)
OCF support for the Galois/Counter Mode (GCM) for AES as
described in FIPS SP 800-38D. This implementation supports 16 byte authentication tag only, splitting transformation into two parts: encryption and authentication. Encryption is handled by the existing AES-CTR implementation, while authentication requires new AES_GMAC hash function. Additional routine is added to the software crypto driver to deal with peculiarities of a combined authentication- encryption transformation. With suggestions from reyk, naddy and toby.
-rw-r--r--sys/conf/files3
-rw-r--r--sys/crypto/cryptodev.h9
-rw-r--r--sys/crypto/cryptosoft.c193
-rw-r--r--sys/crypto/cryptosoft.h3
-rw-r--r--sys/crypto/gmac.c158
-rw-r--r--sys/crypto/gmac.h50
-rw-r--r--sys/crypto/xform.c98
-rw-r--r--sys/crypto/xform.h11
8 files changed, 508 insertions, 17 deletions
diff --git a/sys/conf/files b/sys/conf/files
index eca56ce6ffc..54e95de232a 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1,4 +1,4 @@
-# $OpenBSD: files,v 1.501 2010/09/10 16:34:08 thib Exp $
+# $OpenBSD: files,v 1.502 2010/09/22 11:54:23 mikeb Exp $
# $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@@ -897,6 +897,7 @@ file crypto/arc4.c
file crypto/michael.c wlan
file crypto/cmac.c wlan
file crypto/hmac.c wlan | (softraid & crypto)
+file crypto/gmac.c (inet & ipsec) | crypto
file crypto/key_wrap.c wlan
file crypto/idgen.c inet6 | nfsclient | nfsserver
file netatalk/aarp.c netatalk
diff --git a/sys/crypto/cryptodev.h b/sys/crypto/cryptodev.h
index 855ebd7a754..02606577ee9 100644
--- a/sys/crypto/cryptodev.h
+++ b/sys/crypto/cryptodev.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cryptodev.h,v 1.51 2010/06/23 09:26:32 thib Exp $ */
+/* $OpenBSD: cryptodev.h,v 1.52 2010/09/22 11:54:23 mikeb Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
@@ -105,7 +105,12 @@
#define CRYPTO_SHA2_512_HMAC 20
#define CRYPTO_AES_CTR 21
#define CRYPTO_AES_XTS 22
-#define CRYPTO_ALGORITHM_MAX 22 /* Keep updated */
+#define CRYPTO_AES_GCM_16 23
+#define CRYPTO_AES_128_GMAC 24
+#define CRYPTO_AES_192_GMAC 25
+#define CRYPTO_AES_256_GMAC 26
+#define CRYPTO_AES_GMAC 27
+#define CRYPTO_ALGORITHM_MAX 27 /* Keep updated */
/* Algorithm flags */
#define CRYPTO_ALG_FLAG_SUPPORTED 0x01 /* Algorithm is supported */
diff --git a/sys/crypto/cryptosoft.c b/sys/crypto/cryptosoft.c
index b0d135714ee..446c91c49de 100644
--- a/sys/crypto/cryptosoft.c
+++ b/sys/crypto/cryptosoft.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cryptosoft.c,v 1.54 2010/07/02 02:40:15 blambert Exp $ */
+/* $OpenBSD: cryptosoft.c,v 1.55 2010/09/22 11:54:23 mikeb Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
@@ -492,6 +492,149 @@ swcr_authcompute(struct cryptop *crp, struct cryptodesc *crd,
}
/*
+ * Apply a combined encryption-authentication transformation
+ */
+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[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;
+ 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;
+
+ 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
+ arc4random_buf(iv, ivlen);
+
+ /* Do we need to write the IV */
+ if (!(crde->crd_flags & CRD_F_IV_PRESENT)) {
+ COPYBACK(outtype, 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 */
+ COPYDATA(outtype, 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);
+ COPYDATA(outtype, buf, crda->crd_skip + i, len, blk);
+ axf->Update(&ctx, blk, len);
+ }
+
+ 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);
+ COPYDATA(outtype, 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);
+ }
+ COPYBACK(outtype, 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 */
+ if (outtype == CRYPTO_BUF_MBUF)
+ COPYBACK(outtype, buf, crda->crd_inject, axf->authsize, aalg);
+ else
+ bcopy(aalg, crp->crp_mac, axf->authsize);
+
+ return (0);
+}
+
+/*
* Apply a compression/decompression algorithm
*/
int
@@ -653,6 +796,13 @@ swcr_newsession(u_int32_t *sid, struct cryptoini *cri)
case CRYPTO_AES_XTS:
txf = &enc_xform_aes_xts;
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_NULL:
txf = &enc_xform_null;
goto enccommon;
@@ -769,6 +919,29 @@ swcr_newsession(u_int32_t *sid, struct cryptoini *cri)
(*swd)->sw_axf = axf;
break;
+ 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(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;
@@ -816,6 +989,8 @@ swcr_freesession(u_int64_t tid)
case CRYPTO_RIJNDAEL128_CBC:
case CRYPTO_AES_CTR:
case CRYPTO_AES_XTS:
+ case CRYPTO_AES_GCM_16:
+ case CRYPTO_AES_GMAC:
case CRYPTO_NULL:
txf = swd->sw_exf;
@@ -855,6 +1030,9 @@ swcr_freesession(u_int64_t tid)
}
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;
@@ -953,6 +1131,14 @@ swcr_process(struct cryptop *crp)
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, type)) != 0)
@@ -1006,11 +1192,16 @@ swcr_init(void)
algs[CRYPTO_RIJNDAEL128_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_AES_CTR] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_AES_XTS] = CRYPTO_ALG_FLAG_SUPPORTED;
+ algs[CRYPTO_AES_GCM_16] = CRYPTO_ALG_FLAG_SUPPORTED;
+ algs[CRYPTO_AES_GMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_DEFLATE_COMP] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_NULL] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_SHA2_256_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_SHA2_384_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_SHA2_512_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
+ algs[CRYPTO_AES_128_GMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
+ algs[CRYPTO_AES_192_GMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
+ algs[CRYPTO_AES_256_GMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
crypto_register(swcr_id, algs, swcr_newsession,
swcr_freesession, swcr_process);
diff --git a/sys/crypto/cryptosoft.h b/sys/crypto/cryptosoft.h
index d7133645a27..9a1c6840312 100644
--- a/sys/crypto/cryptosoft.h
+++ b/sys/crypto/cryptosoft.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cryptosoft.h,v 1.12 2010/01/10 12:43:07 markus Exp $ */
+/* $OpenBSD: cryptosoft.h,v 1.13 2010/09/22 11:54:23 mikeb Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
@@ -63,6 +63,7 @@ extern const u_int8_t hmac_opad_buffer[HMAC_MAX_BLOCK_LEN];
int swcr_encdec(struct cryptodesc *, struct swcr_data *, caddr_t, int);
int swcr_authcompute(struct cryptop *, struct cryptodesc *, struct swcr_data *,
caddr_t, int);
+int swcr_combined(struct cryptop *);
int swcr_compdec(struct cryptodesc *, struct swcr_data *, caddr_t, int);
int swcr_process(struct cryptop *);
int swcr_newsession(u_int32_t *, struct cryptoini *);
diff --git a/sys/crypto/gmac.c b/sys/crypto/gmac.c
new file mode 100644
index 00000000000..35d4cfff239
--- /dev/null
+++ b/sys/crypto/gmac.c
@@ -0,0 +1,158 @@
+/* $OpenBSD: gmac.c,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.
+ */
+
+/*
+ * 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 <crypto/rijndael.h>
+#include <crypto/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] = betoh32(Y[0]);
+ v[1] = betoh32(Y[1]);
+ v[2] = betoh32(Y[2]);
+ v[3] = betoh32(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);
+}
+
+/* defines from xform.c */
+#define AES_GCM_SALTSIZE 4
+#define AES_GCM_IVSIZE 8
+
+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 - AES_GCM_SALTSIZE) * 8);
+ /* copy out salt to the counter block */
+ bcopy(key + klen - AES_GCM_SALTSIZE, ctx->J, AES_GCM_SALTSIZE);
+ /* 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 + AES_GCM_SALTSIZE, ivlen);
+}
+
+int
+AES_GMAC_Update(AES_GMAC_CTX *ctx, const 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];
+}
diff --git a/sys/crypto/gmac.h b/sys/crypto/gmac.h
new file mode 100644
index 00000000000..ce26faf2863
--- /dev/null
+++ b/sys/crypto/gmac.h
@@ -0,0 +1,50 @@
+/* $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.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*(AES_MAXROUNDS + 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 *, 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/crypto/xform.c b/sys/crypto/xform.c
index 437e9ea8844..fb59c5f78e3 100644
--- a/sys/crypto/xform.c
+++ b/sys/crypto/xform.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xform.c,v 1.38 2010/04/20 22:05:41 tedu Exp $ */
+/* $OpenBSD: xform.c,v 1.39 2010/09/22 11:54:23 mikeb Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
@@ -60,6 +60,7 @@
#include <crypto/cryptodev.h>
#include <crypto/xform.h>
#include <crypto/deflate.h>
+#include <crypto/gmac.h>
extern void des_ecb3_encrypt(caddr_t, caddr_t, caddr_t, caddr_t, caddr_t, int);
extern void des_ecb_encrypt(caddr_t, caddr_t, caddr_t, int);
@@ -107,6 +108,7 @@ void null_zerokey(u_int8_t **);
void aes_ctr_reinit(caddr_t, u_int8_t *);
void aes_xts_reinit(caddr_t, u_int8_t *);
+void aes_gcm_reinit(caddr_t, u_int8_t *);
int MD5Update_int(void *, const u_int8_t *, u_int16_t);
int SHA1Update_int(void *, const u_int8_t *, u_int16_t);
@@ -194,6 +196,26 @@ struct enc_xform enc_xform_aes_ctr = {
aes_ctr_reinit
};
+struct enc_xform enc_xform_aes_gcm = {
+ CRYPTO_AES_GCM_16, "AES-GCM",
+ 1, 8, 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, 8, 16+4, 32+4,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
struct enc_xform enc_xform_aes_xts = {
CRYPTO_AES_XTS, "AES-XTS",
16, 8, 32, 64,
@@ -228,70 +250,110 @@ struct enc_xform enc_xform_null = {
struct auth_hash auth_hash_hmac_md5_96 = {
CRYPTO_MD5_HMAC, "HMAC-MD5",
16, 16, 12, sizeof(MD5_CTX), HMAC_MD5_BLOCK_LEN,
- (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_96 = {
CRYPTO_SHA1_HMAC, "HMAC-SHA1",
20, 20, 12, sizeof(SHA1_CTX), HMAC_SHA1_BLOCK_LEN,
- (void (*) (void *)) SHA1Init, SHA1Update_int,
+ (void (*) (void *)) SHA1Init, NULL, NULL,
+ SHA1Update_int,
(void (*) (u_int8_t *, void *)) SHA1Final
};
struct auth_hash auth_hash_hmac_ripemd_160_96 = {
CRYPTO_RIPEMD160_HMAC, "HMAC-RIPEMD-160",
20, 20, 12, sizeof(RMD160_CTX), HMAC_RIPEMD160_BLOCK_LEN,
- (void (*)(void *)) RMD160Init, RMD160Update_int,
+ (void (*)(void *)) RMD160Init, NULL, NULL,
+ RMD160Update_int,
(void (*)(u_int8_t *, void *)) RMD160Final
};
struct auth_hash auth_hash_hmac_sha2_256_128 = {
CRYPTO_SHA2_256_HMAC, "HMAC-SHA2-256",
32, 32, 16, sizeof(SHA2_CTX), HMAC_SHA2_256_BLOCK_LEN,
- (void (*)(void *)) SHA256Init, SHA256Update_int,
+ (void (*)(void *)) SHA256Init, NULL, NULL,
+ SHA256Update_int,
(void (*)(u_int8_t *, void *)) SHA256Final
};
struct auth_hash auth_hash_hmac_sha2_384_192 = {
CRYPTO_SHA2_384_HMAC, "HMAC-SHA2-384",
48, 48, 24, sizeof(SHA2_CTX), HMAC_SHA2_384_BLOCK_LEN,
- (void (*)(void *)) SHA384Init, SHA384Update_int,
+ (void (*)(void *)) SHA384Init, NULL, NULL,
+ SHA384Update_int,
(void (*)(u_int8_t *, void *)) SHA384Final
};
struct auth_hash auth_hash_hmac_sha2_512_256 = {
CRYPTO_SHA2_512_HMAC, "HMAC-SHA2-512",
64, 64, 32, sizeof(SHA2_CTX), HMAC_SHA2_512_BLOCK_LEN,
- (void (*)(void *)) SHA512Init, SHA512Update_int,
+ (void (*)(void *)) SHA512Init, NULL, NULL,
+ SHA512Update_int,
(void (*)(u_int8_t *, void *)) SHA512Final
};
+struct auth_hash auth_hash_gmac_aes_128 = {
+ CRYPTO_AES_128_GMAC, "GMAC-AES-128",
+ 16+4, 16, 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, 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, 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_key_md5 = {
CRYPTO_MD5_KPDK, "Keyed MD5",
0, 16, 16, sizeof(MD5_CTX), 0,
- (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, 20, 20, sizeof(SHA1_CTX), 0,
- (void (*)(void *)) SHA1Init, SHA1Update_int,
+ (void (*)(void *)) SHA1Init, NULL, NULL,
+ SHA1Update_int,
(void (*)(u_int8_t *, void *)) SHA1Final
};
struct auth_hash auth_hash_md5 = {
CRYPTO_MD5, "MD5",
0, 16, 16, sizeof(MD5_CTX), 0,
- (void (*) (void *)) MD5Init, MD5Update_int,
+ (void (*) (void *)) MD5Init, NULL, NULL,
+ MD5Update_int,
(void (*) (u_int8_t *, void *)) MD5Final
};
struct auth_hash auth_hash_sha1 = {
CRYPTO_SHA1, "SHA1",
0, 20, 20, sizeof(SHA1_CTX), 0,
- (void (*)(void *)) SHA1Init, SHA1Update_int,
+ (void (*)(void *)) SHA1Init, NULL, NULL,
+ SHA1Update_int,
(void (*)(u_int8_t *, void *)) SHA1Final
};
@@ -552,6 +614,19 @@ aes_ctr_reinit(caddr_t key, u_int8_t *iv)
}
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_IVSIZE);
+
+ /* reset counter */
+ bzero(ctx->ac_block + AESCTR_NONCESIZE + AESCTR_IVSIZE, 4);
+ 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;
@@ -744,6 +819,7 @@ SHA512Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
return 0;
}
+
/*
* And compression
*/
diff --git a/sys/crypto/xform.h b/sys/crypto/xform.h
index d7abcf4c36d..0e873819a32 100644
--- a/sys/crypto/xform.h
+++ b/sys/crypto/xform.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: xform.h,v 1.20 2010/01/10 12:43:07 markus Exp $ */
+/* $OpenBSD: xform.h,v 1.21 2010/09/22 11:54:23 mikeb Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
@@ -28,6 +28,7 @@
#include <crypto/sha1.h>
#include <crypto/rmd160.h>
#include <crypto/sha2.h>
+#include <crypto/gmac.h>
/* Declarations */
struct auth_hash {
@@ -39,6 +40,8 @@ struct auth_hash {
u_int16_t ctxsize;
u_int16_t blocksize;
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 *, const u_int8_t *, u_int16_t);
void (*Final) (u_int8_t *, void *);
};
@@ -68,6 +71,7 @@ union authctx {
SHA1_CTX sha1ctx;
RMD160_CTX rmd160ctx;
SHA2_CTX sha2_ctx;
+ AES_GMAC_CTX aes_gmac_ctx;
};
extern struct enc_xform enc_xform_des;
@@ -77,6 +81,8 @@ 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_null;
@@ -91,6 +97,9 @@ extern struct auth_hash auth_hash_hmac_ripemd_160_96;
extern struct auth_hash auth_hash_hmac_sha2_256_128;
extern struct auth_hash auth_hash_hmac_sha2_384_192;
extern struct auth_hash auth_hash_hmac_sha2_512_256;
+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;
extern struct comp_algo comp_algo_lzs;