diff options
author | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2010-09-22 11:54:24 +0000 |
---|---|---|
committer | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2010-09-22 11:54:24 +0000 |
commit | 9a8c4153305177b616e3d7e1c5da5f342c96dc5b (patch) | |
tree | f73bcdb9b727a468bf8a906e8f246e02edd6bed6 /sys | |
parent | 6ec85bf63c728dc364401adfb19bc65cde8d7f54 (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.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/conf/files | 3 | ||||
-rw-r--r-- | sys/crypto/cryptodev.h | 9 | ||||
-rw-r--r-- | sys/crypto/cryptosoft.c | 193 | ||||
-rw-r--r-- | sys/crypto/cryptosoft.h | 3 | ||||
-rw-r--r-- | sys/crypto/gmac.c | 158 | ||||
-rw-r--r-- | sys/crypto/gmac.h | 50 | ||||
-rw-r--r-- | sys/crypto/xform.c | 98 | ||||
-rw-r--r-- | sys/crypto/xform.h | 11 |
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; |