You are on page 1of 25

Hi, This is a first diff of a series that brings support for the Galois/Counter Mode for AES in OpenBSD.

Intro ===== For those unfamiliar with GCM, I'm going to quote Wikipedia[1]: GCM mode (Galois/Counter Mode) is a mode of operation for symmetri key cryptographic block ciphers. It is an authenticated encryption algorithm designed to provide both authentication and secrecy. GCM mode is defined for block ciphers with a block size of 128 bits. GMAC is an authentication-only variant of the GCM. So GCM is an emerging standard for IPsec that is approved by NIST in the NIST Special Publication 800-38D[2]. patents. GCM is cryptographically secure as long as underlying cipher is secure; it heavily relies on uniqueness and non-repeating of the Initialization Vector. Quoting RFC 4106[3]: Because reusing an nonce/key combination destroys the security guarantees of AES-GCM mode, it can be difficult to use this mode securely when using statically configured keys. For safety's sake, implementations MUST use an automated key management system, such as the Internet Key Exchange (IKE) [RFC2409], to ensure that this requirement is met. "Authentication weaknesses in GCM" by Niels Ferguson[4] describes some of the potentian issues with GCM in detail. Implementation details ====================== Also use of IKE is mandatory for GCM. It's unencumbered by

As this is the first time a combined authentication-encryption transformation hits OpenBSD kernel, I chose to split to split it into two parts: encryption transformation and authentication hash, AES-GCM and AES-GMAC respectively. AES-GCM part is fairly simple and it reuses AES-CTR code to do key generation, encryption and decryption. IV handling is almost the same, except that GCM spec requires to start counter with 1. Here I have to note that AES-GCM is a stream cipher hence it has a block size of "1". Now GMAC is a bit different to HMAC-style functions. as AES-GCM; - requires input data to be continuous, i.e.: given block C of 16 bytes which is a concatenation of blocks A an B (C = A || B): GMAC(C) =/= GMAC(B, GMAC(A, Z)), where GMAC(X, Y) denotes GMAC application to the block X and initial (or state) block Y. - can be efficiently accelerated by using table method or CPU instructions (CLMUL instructions on newer Intel CPUs). - defines two types of input data: Additional Authentication Data (AAD) and plaintext; - requires the last invocation of the hash routine to be done on the so-called length block that includes lengths of AAD and plaintext inputs. RFC 4106 (use of AES-GCM in ESP) specifies three key sizes (128, 192 and 256) and three types of "Type 1" (encryption) transforms: AES-GCM with an Integrity Check Value (ICV) of 8 bytes (as MAY) AES-GCM with an ICV of 12 bytes (as MAY) AES-GCM with an ICV of 16 bytes (as MUST) Highlights:

- uses one round of AES (GCTR) hence requires the same key an IV

This implementation provides support for AES-GCM-16 only. RFC 4543[5] (use of AES-GMAC in ESP and AH) specifies GMAC to have ICV values of 16 bytes only. OCF integration =============== OCF integration required extension of the auth_hash structure to include two new function pointers (Setkey and Reinit). done to keep AES_GMAC_Update stateless. on the callee to composing the last lengths block. GMAC code is written in a way that supporting other block cipher won't require cipher-independent changes. Software crypto implementation gets a separate routine to handle combined modes that is also written in a way that will support future enchancements. Please note that it's not an overhead, in this case it actually simplifies the integration. Test vectors ============ Yes, they do exist! the auth algorithms. It is possible to include a regress program with test vectors for the encryption part though. Obviously I've done tests in userland and with IPsec against Linux to verify correctness. it's on my TODO list). AES-GMAC in ESP and AH ====================== (I didn't test on !AMD64 though The problem here is that we can't (sort of) That was AES_GMAC_Update relies

test GMAC through the /dev/crypto as we don't provide access to

This section is here just to clarify presense of the AES-GMAC encryption transformation with all function pointers set to NIL. Well, blame the committee. They've specified [in RFC 4543] a ESP encryption transformation that only does authentication: It is called ENCR_NULL_AUTH_AES_GMAC to highlight the fact that it performs no encryption and provides no confidentiality. C'est la vie. Outro ===== For now this is provided for reference and discussion purposes only. (Not asking for okays, but will if my account will be reenabled) PS. I'm deeply sorry for my Engrish, mistakes and bad phrase composition. Have fun. References: [1] http://en.wikipedia.org/wiki/Galois/Counter_Mode [2] http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf [3] http://tools.ietf.org/html/rfc4106 [4] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/comments/CWC-

GCM/Ferguson2.pdf
[5] http://tools.ietf.org/html/rfc4543 Index: conf/files =================================================================== RCS file: /home/cvs/src/sys/conf/files,v retrieving revision 1.499 diff -u -p -r1.499 files --- conf/files31 Jul 2010 08:33:19 -0000 +++ conf/files3 Aug 2010 17:42:09 -0000 1.499

@@ -897,6 +897,7 @@ file crypto/arc4.c file crypto/michael.c file crypto/cmac.c file crypto/hmac.c +file crypto/gmac.c file crypto/key_wrap.c file crypto/idgen.c file netatalk/aarp.c Index: crypto/cryptodev.c =================================================================== RCS file: /home/cvs/src/sys/crypto/cryptodev.c,v retrieving revision 1.73 diff -u -p -r1.73 cryptodev.c --- crypto/cryptodev.c +++ crypto/cryptodev.c 21 Jul 2010 18:44:01 -0000 26 Jul 2010 11:26:07 -0000 1.73 wlan wlan | (softraid & crypto) (inet & ipsec) | crypto wlan inet6 | nfsclient | nfsserver netatalk wlan

@@ -178,6 +178,9 @@ cryptof_ioctl(struct file *fp, u_long cm case CRYPTO_AES_XTS: txform = &enc_xform_aes_xts; break; + + + case CRYPTO_AES_GCM_16: txform = &enc_xform_aes_gcm; break; case CRYPTO_ARC4: txform = &enc_xform_arc4; break; Index: crypto/cryptodev.h =================================================================== RCS file: /home/cvs/src/sys/crypto/cryptodev.h,v retrieving revision 1.51 diff -u -p -r1.51 cryptodev.h --- crypto/cryptodev.h +++ crypto/cryptodev.h @@ -105,7 +105,12 @@ #define CRYPTO_SHA2_512_HMAC 20 #define CRYPTO_AES_CTR #define CRYPTO_AES_XTS +#define CRYPTO_AES_GCM_16 23 21 22 23 Jun 2010 09:26:32 -0000 28 Jul 2010 16:13:56 -0000 1.51

-#define CRYPTO_ALGORITHM_MAX 22 /* Keep updated */

+#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 28 /* Keep updated */ /* Algorithm flags */ #define */ Index: crypto/cryptosoft.c =================================================================== RCS file: /home/cvs/src/sys/crypto/cryptosoft.c,v retrieving revision 1.54 diff -u -p -r1.54 cryptosoft.c --- crypto/cryptosoft.c +++ crypto/cryptosoft.c } /* + * Apply a combined encryption-authentication transformation + */ +int +swcr_combined(struct cryptop *crp) +{ + + + + + + + + + + + + + unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN]; unsigned char aalg[AALG_MAX_RESULT_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; 2 Jul 2010 02:40:15 -0000 20 Aug 2010 15:38:50 -0000 1.54 CRYPTO_ALG_FLAG_SUPPORTED 0x01 /* Algorithm is supported

@@ -492,6 +492,147 @@ swcr_authcompute(struct cryptop *crp, st

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

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 +794,13 @@ swcr_newsession(u_int32_t *sid, struct c 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 +917,29 @@ swcr_newsession(u_int32_t *sid, struct c (*swd)->sw_axf = axf; break; + + + + + + + + case CRYPTO_AES_192_GMAC: axf = &auth_hash_gmac_aes_192; goto auth4common; case CRYPTO_AES_128_GMAC: axf = &auth_hash_gmac_aes_128; 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;

@@ -855,6 +1026,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 +1127,13 @@ swcr_process(struct cryptop *crp) goto done; break; + + + + + + case CRYPTO_AES_GCM_16: 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 +1187,15 @@ 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_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); Index: crypto/cryptosoft.h =================================================================== RCS file: /home/cvs/src/sys/crypto/cryptosoft.h,v retrieving revision 1.12 diff -u -p -r1.12 cryptosoft.h --- crypto/cryptosoft.h +++ crypto/cryptosoft.h int int 10 Jan 2010 12:43:07 -0000 27 Jul 2010 13:34:13 -0000 1.12

@@ -63,6 +63,7 @@ extern const u_int8_t hmac_opad_buffer[H swcr_encdec(struct cryptodesc *, struct swcr_data *, caddr_t, int); swcr_authcompute(struct cryptop *, struct cryptodesc *, struct caddr_t, int); +int int int int swcr_combined(struct cryptop *); swcr_compdec(struct cryptodesc *, struct swcr_data *, caddr_t, int); swcr_process(struct cryptop *); swcr_newsession(u_int32_t *, struct cryptoini *);

swcr_data *,

Index: crypto/gmac.c ===================================================================

RCS file: crypto/gmac.c diff -N crypto/gmac.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ crypto/gmac.c @@ -0,0 +1,158 @@ +/* + +/* + * 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. + */ + +#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); + FIPS SP 800-38D describes the algorithm details. $OpenBSD$ */ 20 Aug 2010 15:40:29 -0000

+/* Computes a block multiplication in the GF(2^128) */ +void +ghash_gfmul(uint32_t *X, uint32_t *Y, uint32_t *product) +{ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + product[0] = htobe32(z[0]); product[1] = htobe32(z[1]); product[2] = htobe32(z[2]); product[3] = htobe32(z[3]); } /* 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); 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 */ v[0] = betoh32(Y[0]); v[1] = betoh32(Y[1]); v[2] = betoh32(Y[2]); v[3] = betoh32(Y[3]); uint32_t uint32_t uint8_t uint32_t int v[4]; z[4] = { 0, 0, 0, 0}; *x = (uint8_t *)X; mul; i;

+void +ghash_update(GHASH_CTX *ctx, uint8_t *X, size_t len) +{ + + + + + + + + + + + + + + + + + + + +} + +/* defines from xform.c */ +#define AES_GCM_SALTSIZE +#define AES_GCM_IVSIZE + +void +AES_GMAC_Init(AES_GMAC_CTX *ctx) +{ + + + + +} + +void 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); 4 8 bcopy(ctx->S, ctx->Z, GMAC_BLOCK_LEN); } y = s; x += 4; ghash_gfmul((uint32_t *)ctx->S, (uint32_t *)ctx->H, (uint32_t *)ctx->S); 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]; uint32_t uint32_t uint32_t int *x = (uint32_t *)X; *s = (uint32_t *)ctx->S; *y = (uint32_t *)ctx->Z; i;

+AES_GMAC_Setkey(AES_GMAC_CTX *ctx, const uint8_t *key, uint16_t klen) +{ + + + + + + +} + +void +AES_GMAC_Reinit(AES_GMAC_CTX *ctx, const uint8_t *iv, uint16_t ivlen) +{ + + +} + +int +AES_GMAC_Update(AES_GMAC_CTX *ctx, const uint8_t *data, uint16_t len) +{ + + + + + + + + + + + + + + + +} + +void } return (0); } 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); uint32_t int blk[4] = { 0, 0, 0, 0 }; plen; /* copy out IV to the counter block */ bcopy(iv, ctx->J + AES_GCM_SALTSIZE, ivlen); 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);

+AES_GMAC_Final(uint8_t digest[GMAC_DIGEST_LEN], AES_GMAC_CTX *ctx) +{ + + + + + + + + +} Index: crypto/gmac.h =================================================================== RCS file: crypto/gmac.h diff -N crypto/gmac.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ crypto/gmac.h @@ -0,0 +1,50 @@ +/* + +/* + * 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_ $OpenBSD$ */ 20 Aug 2010 13:04:59 -0000 /* 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]; uint8_t int keystream[GMAC_BLOCK_LEN]; i;

+ +#include <crypto/rijndael.h> + +#define GMAC_BLOCK_LEN +#define GMAC_DIGEST_LEN + +typedef struct _GHASH_CTX { + + + + +typedef struct _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_ */ Index: crypto/xform.c =================================================================== RCS file: /home/cvs/src/sys/crypto/xform.c,v retrieving revision 1.38 diff -u -p -r1.38 xform.c --- crypto/xform.c +++ crypto/xform.c @@ -60,6 +60,7 @@ 20 Apr 2010 22:05:41 -0000 20 Aug 2010 17:28:54 -0000 1.38 GHASH_CTX uint32_t uint8_t int ghash; K[4*(AES_MAXROUNDS + 1)]; J[GMAC_BLOCK_LEN]; rounds; /* counter block */ uint8_t uint8_t uint8_t H[GMAC_BLOCK_LEN]; S[GMAC_BLOCK_LEN]; Z[GMAC_BLOCK_LEN]; /* hash subkey */ /* state */ /* initial state */ 16 16

+} GHASH_CTX;

+} AES_GMAC_CTX;

#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 = { + + + + + + + +}; + +struct enc_xform enc_xform_aes_gmac = { + + + + + + + CRYPTO_AES_GMAC, "AES-GMAC", 1, 8, 16+4, 32+4, NULL, NULL, NULL, NULL, NULL 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_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, + + }; struct auth_hash auth_hash_hmac_sha1_96 = { CRYPTO_SHA1_HMAC, "HMAC-SHA1", 20, 20, 12, sizeof(SHA1_CTX), HMAC_SHA1_BLOCK_LEN, + + }; 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, + + }; 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, (void (*)(void *)) RMD160Init, RMD160Update_int, (void (*)(void *)) RMD160Init, NULL, NULL, RMD160Update_int, (void (*)(u_int8_t *, void *)) RMD160Final (void (*) (void *)) SHA1Init, SHA1Update_int, (void (*) (void *)) SHA1Init, NULL, NULL, SHA1Update_int, (void (*) (u_int8_t *, void *)) SHA1Final (void (*) (void *)) MD5Init, MD5Update_int, (void (*) (void *)) MD5Init, NULL, NULL, MD5Update_int, (void (*) (u_int8_t *, void *)) MD5Final

+ };

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, + + }; 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, + + }; +struct auth_hash auth_hash_gmac_aes_128 = { + + + + + + + +}; + +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, 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 (void (*)(void *)) SHA512Init, SHA512Update_int, (void (*)(void *)) SHA512Init, NULL, NULL, SHA512Update_int, (void (*)(u_int8_t *, void *)) SHA512Final (void (*)(void *)) SHA384Init, SHA384Update_int, (void (*)(void *)) SHA384Init, NULL, NULL, SHA384Update_int, (void (*)(u_int8_t *, void *)) SHA384Final

+ + +}; +

(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 = { + + + + + + + +}; + struct auth_hash auth_hash_key_md5 = { CRYPTO_MD5_KPDK, "Keyed MD5", 0, 16, 16, sizeof(MD5_CTX), 0, + + }; struct auth_hash auth_hash_key_sha1 = { CRYPTO_SHA1_KPDK, "Keyed SHA1", 0, 20, 20, sizeof(SHA1_CTX), 0, + + }; 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 (*)(void *)) SHA1Init, SHA1Update_int, (void (*)(void *)) SHA1Init, NULL, NULL, SHA1Update_int, (void (*)(u_int8_t *, void *)) SHA1Final (void (*)(void *)) MD5Init, MD5Update_int, (void (*)(void *)) MD5Init, NULL, NULL, MD5Update_int, (void (*)(u_int8_t *, void *)) MD5Final 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

(void (*) (u_int8_t *, void *)) MD5Final }; struct auth_hash auth_hash_sha1 = { CRYPTO_SHA1, "SHA1", 0, 20, 20, sizeof(SHA1_CTX), 0, + + }; @@ -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) +{ + + + + + + + + +} + +void aes_ctr_crypt(caddr_t key, u_int8_t *data) { struct aes_ctr_ctx *ctx; @@ -743,6 +818,7 @@ SHA512Update_int(void *ctx, const u_int8 SHA512Update(ctx, buf, len); return 0; } + /* reset counter */ bzero(ctx->ac_block + AESCTR_NONCESIZE + AESCTR_IVSIZE, 4); ctx->ac_block[AESCTR_BLOCKSIZE - 1] = 1; /* GCM starts with 1 */ ctx = (struct aes_ctr_ctx *)key; bcopy(iv, ctx->ac_block + AESCTR_NONCESIZE, AESCTR_IVSIZE); struct aes_ctr_ctx *ctx; (void (*)(void *)) SHA1Init, SHA1Update_int, (void (*)(void *)) SHA1Init, NULL, NULL, SHA1Update_int, (void (*)(u_int8_t *, void *)) SHA1Final

/* * And compression Index: crypto/xform.h =================================================================== RCS file: /home/cvs/src/sys/crypto/xform.h,v retrieving revision 1.20 diff -u -p -r1.20 xform.h --- crypto/xform.h +++ crypto/xform.h @@ -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 }; @@ -68,6 +71,7 @@ union authctx { SHA1_CTX sha1ctx; RMD160_CTX rmd160ctx; SHA2_CTX sha2_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; AES_GMAC_CTX aes_gmac_ctx; (*Update) (void *, const u_int8_t *, u_int16_t); void (*Final) (u_int8_t *, void *); 10 Jan 2010 12:43:07 -0000 3 Aug 2010 16:24:48 -0000 1.20

+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_r 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;

You might also like