From: Alex Hornung Date: Mon, 27 Jun 2011 20:17:24 +0000 (+0100) Subject: opencrypto - Add AES GCM/GMAC support X-Git-Tag: v2.12.0~407 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/aface1425a7d078db8785139e186f3a4ffd18034 opencrypto - Add AES GCM/GMAC support Obtained-from: OpenBSD --- diff --git a/sys/conf/files b/sys/conf/files index c02e4059e5..5b2bed757f 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -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 diff --git a/sys/opencrypto/cryptodev.h b/sys/opencrypto/cryptodev.h index 7da7e67a8f..37a8c391e7 100644 --- a/sys/opencrypto/cryptodev.h +++ b/sys/opencrypto/cryptodev.h @@ -102,6 +102,10 @@ #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 */ @@ -130,7 +134,12 @@ #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 diff --git a/sys/opencrypto/cryptosoft.c b/sys/opencrypto/cryptosoft.c index 15e3ba1010..4106f4944a 100644 --- a/sys/opencrypto/cryptosoft.c +++ b/sys/opencrypto/cryptosoft.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -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); @@ -589,6 +591,163 @@ swcr_authcompute(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf, return 0; } +/* + * 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 */ @@ -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 index 0000000000..f5a9cfe392 --- /dev/null +++ b/sys/opencrypto/gmac.c @@ -0,0 +1,159 @@ +/* $OpenBSD: gmac.c,v 1.3 2011/01/11 15:44:23 deraadt Exp $ */ + +/* + * Copyright (c) 2010 Mike Belopuhov + * + * 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 +#include +#include + +#include +#include + +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 index 0000000000..c5a5324dc0 --- /dev/null +++ b/sys/opencrypto/gmac.h @@ -0,0 +1,51 @@ +/* $OpenBSD: gmac.h,v 1.1 2010/09/22 11:54:23 mikeb Exp $ */ + +/* + * Copyright (c) 2010 Mike Belopuhov + * + * 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 + +#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 + +__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_ */ + diff --git a/sys/opencrypto/xform.c b/sys/opencrypto/xform.c index 25607859e5..1c75b5b465 100644 --- a/sys/opencrypto/xform.c +++ b/sys/opencrypto/xform.c @@ -56,6 +56,7 @@ #include #include #include +#include #include @@ -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", @@ -761,6 +821,19 @@ aes_ctr_zerokey(u_int8_t **sched) *sched = NULL; } +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) { diff --git a/sys/opencrypto/xform.h b/sys/opencrypto/xform.h index cfc49ced94..b584b85291 100644 --- a/sys/opencrypto/xform.h +++ b/sys/opencrypto/xform.h @@ -30,6 +30,7 @@ #include #include #include +#include /* 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;