Date: Fri, 5 Jun 2009 01:58:48 GMT From: Gleb Kurtsou <gk@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 163537 for review Message-ID: <200906050158.n551wme3083821@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=163537 Change 163537 by gk@gk_h1 on 2009/06/05 01:58:45 Import OpenBSD XTS-AES implementation Affected files ... .. //depot/projects/soc2009/gk_pefs/sys/opencrypto/cryptodev.c#2 edit .. //depot/projects/soc2009/gk_pefs/sys/opencrypto/cryptodev.h#2 edit .. //depot/projects/soc2009/gk_pefs/sys/opencrypto/cryptosoft.c#2 edit .. //depot/projects/soc2009/gk_pefs/sys/opencrypto/xform.c#2 edit .. //depot/projects/soc2009/gk_pefs/sys/opencrypto/xform.h#2 edit Differences ... ==== //depot/projects/soc2009/gk_pefs/sys/opencrypto/cryptodev.c#2 (text+ko) ==== @@ -215,6 +215,9 @@ case CRYPTO_CAMELLIA_CBC: txform = &enc_xform_camellia; break; + case CRYPTO_AES_XTS: + txform = &enc_xform_aes_xts; + break; default: return (EINVAL); } ==== //depot/projects/soc2009/gk_pefs/sys/opencrypto/cryptodev.h#2 (text+ko) ==== @@ -123,7 +123,8 @@ #define CRYPTO_SHA2_384_HMAC 19 #define CRYPTO_SHA2_512_HMAC 20 #define CRYPTO_CAMELLIA_CBC 21 -#define CRYPTO_ALGORITHM_MAX 21 /* Keep updated - see below */ +#define CRYPTO_AES_XTS 22 +#define CRYPTO_ALGORITHM_MAX 22 /* Keep updated - see below */ /* Algorithm flags */ #define CRYPTO_ALG_FLAG_SUPPORTED 0x01 /* Algorithm is supported */ ==== //depot/projects/soc2009/gk_pefs/sys/opencrypto/cryptosoft.c#2 (text+ko) ==== @@ -61,7 +61,8 @@ 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_compdec(struct cryptodesc *, struct swcr_data *, caddr_t, int); -static int swcr_freesession(device_t dev, u_int64_t tid); +static int swcr_freesession(device_t, u_int64_t); +/* $OpenBSD: cryptosoft.c,v 1.51 2008/06/09 16:07:00 djm Exp $ */ /* * Apply a symmetric encryption/decryption algorithm. @@ -73,10 +74,11 @@ unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN], *idat; unsigned char *ivp, piv[EALG_MAX_BLOCK_LEN]; struct enc_xform *exf; - int i, k, j, blks; + int i, k, j, blks, ivlen; exf = sw->sw_exf; blks = exf->blocksize; + ivlen = exf->ivsize; /* Check for non-padded data */ if (crd->crd_len % blks) @@ -86,21 +88,21 @@ if (crd->crd_flags & CRD_F_ENCRYPT) { /* IV explicitly provided ? */ if (crd->crd_flags & CRD_F_IV_EXPLICIT) - bcopy(crd->crd_iv, iv, blks); + bcopy(crd->crd_iv, iv, ivlen); else - arc4rand(iv, blks, 0); + arc4rand(iv, ivlen, 0); /* Do we need to write the IV */ if (!(crd->crd_flags & CRD_F_IV_PRESENT)) - crypto_copyback(flags, buf, crd->crd_inject, blks, iv); + crypto_copyback(flags, buf, crd->crd_inject, ivlen, iv); } else { /* Decryption */ /* IV explicitly provided ? */ if (crd->crd_flags & CRD_F_IV_EXPLICIT) - bcopy(crd->crd_iv, iv, blks); + bcopy(crd->crd_iv, iv, ivlen); else { /* Get IV off buf */ - crypto_copydata(flags, buf, crd->crd_inject, blks, iv); + crypto_copydata(flags, buf, crd->crd_inject, ivlen, iv); } } @@ -116,6 +118,13 @@ } ivp = iv; + /* + * xforms that provide a reinit method perform all IV + * handling themselves. + */ + if (exf->reinit) + exf->reinit(sw->sw_kschedule, iv); + if (flags & CRYPTO_F_IMBUF) { struct mbuf *m = (struct mbuf *) buf; @@ -135,7 +144,15 @@ m_copydata(m, k, blks, blk); /* Actual encryption/decryption */ - if (crd->crd_flags & CRD_F_ENCRYPT) { + if (exf->reinit) { + if (crd->crd_flags & CRD_F_ENCRYPT) { + exf->encrypt(sw->sw_kschedule, + blk); + } else { + exf->decrypt(sw->sw_kschedule, + blk); + } + } else if (crd->crd_flags & CRD_F_ENCRYPT) { /* XOR with previous block */ for (j = 0; j < blks; j++) blk[j] ^= ivp[j]; @@ -205,7 +222,15 @@ idat = mtod(m, unsigned char *) + k; while (m->m_len >= k + blks && i > 0) { - if (crd->crd_flags & CRD_F_ENCRYPT) { + if (exf->reinit) { + if (crd->crd_flags & CRD_F_ENCRYPT) { + exf->encrypt(sw->sw_kschedule, + idat); + } else { + exf->decrypt(sw->sw_kschedule, + idat); + } + } else if (crd->crd_flags & CRD_F_ENCRYPT) { /* XOR with previous block/IV */ for (j = 0; j < blks; j++) idat[j] ^= ivp[j]; @@ -261,7 +286,15 @@ cuio_copydata(uio, k, blks, blk); /* Actual encryption/decryption */ - if (crd->crd_flags & CRD_F_ENCRYPT) { + if (exf->reinit) { + if (crd->crd_flags & CRD_F_ENCRYPT) { + exf->encrypt(sw->sw_kschedule, + blk); + } else { + exf->decrypt(sw->sw_kschedule, + blk); + } + } else if (crd->crd_flags & CRD_F_ENCRYPT) { /* XOR with previous block */ for (j = 0; j < blks; j++) blk[j] ^= ivp[j]; @@ -319,7 +352,15 @@ idat = (char *)iov->iov_base + k; while (iov->iov_len >= k + blks && i > 0) { - if (crd->crd_flags & CRD_F_ENCRYPT) { + if (exf->reinit) { + if (crd->crd_flags & CRD_F_ENCRYPT) { + exf->encrypt(sw->sw_kschedule, + idat); + } else { + exf->decrypt(sw->sw_kschedule, + idat); + } + } else if (crd->crd_flags & CRD_F_ENCRYPT) { /* XOR with previous block/IV */ for (j = 0; j < blks; j++) idat[j] ^= ivp[j]; ==== //depot/projects/soc2009/gk_pefs/sys/opencrypto/xform.c#2 (text+ko) ==== @@ -1,8 +1,9 @@ /* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ /*- * The authors of this code are John Ioannidis (ji@tla.org), - * Angelos D. Keromytis (kermit@csd.uch.gr) and - * Niels Provos (provos@physnet.uni-hamburg.de). + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Damien Miller (djm@mindrot.org). * * This code was written by John Ioannidis for BSD/OS in Athens, Greece, * in November 1995. @@ -15,11 +16,15 @@ * * Additional features in 1999 by Angelos D. Keromytis. * + * AES XTS implementation in 2008 by Damien Miller + * * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, * Angelos D. Keromytis and Niels Provos. * * Copyright (C) 2001, Angelos D. Keromytis. * + * Copyright (C) 2008, Damien Miller + * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or @@ -76,6 +81,7 @@ static int skipjack_setkey(u_int8_t **, u_int8_t *, int); static int rijndael128_setkey(u_int8_t **, u_int8_t *, int); static int cml_setkey(u_int8_t **, u_int8_t *, int); +static int aes_xts_setkey(u_int8_t **, u_int8_t *, int); static void des1_encrypt(caddr_t, u_int8_t *); static void des3_encrypt(caddr_t, u_int8_t *); static void blf_encrypt(caddr_t, u_int8_t *); @@ -83,6 +89,7 @@ static void skipjack_encrypt(caddr_t, u_int8_t *); static void rijndael128_encrypt(caddr_t, u_int8_t *); static void cml_encrypt(caddr_t, u_int8_t *); +static void aes_xts_encrypt(caddr_t, u_int8_t *); static void des1_decrypt(caddr_t, u_int8_t *); static void des3_decrypt(caddr_t, u_int8_t *); static void blf_decrypt(caddr_t, u_int8_t *); @@ -90,6 +97,7 @@ static void skipjack_decrypt(caddr_t, u_int8_t *); static void rijndael128_decrypt(caddr_t, u_int8_t *); static void cml_decrypt(caddr_t, u_int8_t *); +static void aes_xts_decrypt(caddr_t, u_int8_t *); static void des1_zerokey(u_int8_t **); static void des3_zerokey(u_int8_t **); static void blf_zerokey(u_int8_t **); @@ -97,7 +105,10 @@ static void skipjack_zerokey(u_int8_t **); static void rijndael128_zerokey(u_int8_t **); static void cml_zerokey(u_int8_t **); +static void aes_xts_zerokey(u_int8_t **); +static void aes_xts_reinit(caddr_t, u_int8_t *); + static void null_init(void *); static int null_update(void *, u_int8_t *, u_int16_t); static void null_final(u_int8_t *, void *); @@ -115,20 +126,25 @@ MALLOC_DEFINE(M_XDATA, "xform", "xform data buffers"); +/* Helper */ +struct aes_xts_ctx; +void aes_xts_crypt(struct aes_xts_ctx *, u_int8_t *, u_int); + /* Encryption instances */ struct enc_xform enc_xform_null = { CRYPTO_NULL_CBC, "NULL", /* NB: blocksize of 4 is to generate a properly aligned ESP header */ - NULL_BLOCK_LEN, 0, 256, /* 2048 bits, max key */ + NULL_BLOCK_LEN, 0, 0, 256, /* 2048 bits, max key */ null_encrypt, null_decrypt, null_setkey, null_zerokey, + NULL }; struct enc_xform enc_xform_des = { CRYPTO_DES_CBC, "DES", - DES_BLOCK_LEN, 8, 8, + DES_BLOCK_LEN, DES_BLOCK_LEN, 8, 8, des1_encrypt, des1_decrypt, des1_setkey, @@ -137,67 +153,83 @@ struct enc_xform enc_xform_3des = { CRYPTO_3DES_CBC, "3DES", - DES3_BLOCK_LEN, 24, 24, + DES3_BLOCK_LEN, DES3_BLOCK_LEN, 24, 24, des3_encrypt, des3_decrypt, des3_setkey, - des3_zerokey + des3_zerokey, + NULL }; struct enc_xform enc_xform_blf = { CRYPTO_BLF_CBC, "Blowfish", - BLOWFISH_BLOCK_LEN, 5, 56 /* 448 bits, max key */, + BLOWFISH_BLOCK_LEN, BLOWFISH_BLOCK_LEN, 5, 56 /* 448 bits, max key */, blf_encrypt, blf_decrypt, blf_setkey, - blf_zerokey + blf_zerokey, + NULL }; struct enc_xform enc_xform_cast5 = { CRYPTO_CAST_CBC, "CAST-128", - CAST128_BLOCK_LEN, 5, 16, + CAST128_BLOCK_LEN, CAST128_BLOCK_LEN, 5, 16, cast5_encrypt, cast5_decrypt, cast5_setkey, - cast5_zerokey + cast5_zerokey, + NULL }; struct enc_xform enc_xform_skipjack = { CRYPTO_SKIPJACK_CBC, "Skipjack", - SKIPJACK_BLOCK_LEN, 10, 10, + SKIPJACK_BLOCK_LEN, SKIPJACK_BLOCK_LEN, 10, 10, skipjack_encrypt, skipjack_decrypt, skipjack_setkey, - skipjack_zerokey + skipjack_zerokey, + NULL }; struct enc_xform enc_xform_rijndael128 = { CRYPTO_RIJNDAEL128_CBC, "Rijndael-128/AES", - RIJNDAEL128_BLOCK_LEN, 8, 32, + RIJNDAEL128_BLOCK_LEN, RIJNDAEL128_BLOCK_LEN, 8, 32, rijndael128_encrypt, rijndael128_decrypt, rijndael128_setkey, rijndael128_zerokey, + NULL }; struct enc_xform enc_xform_arc4 = { CRYPTO_ARC4, "ARC4", - 1, 1, 32, + 1, 1, 1, 32, NULL, NULL, NULL, NULL, + NULL }; struct enc_xform enc_xform_camellia = { CRYPTO_CAMELLIA_CBC, "Camellia", - CAMELLIA_BLOCK_LEN, 8, 32, + CAMELLIA_BLOCK_LEN, CAMELLIA_BLOCK_LEN, 8, 32, cml_encrypt, cml_decrypt, cml_setkey, cml_zerokey, }; +struct enc_xform enc_xform_aes_xts = { + CRYPTO_AES_XTS, "AES-XTS", + 16, 8, 32, 64, + aes_xts_encrypt, + aes_xts_decrypt, + aes_xts_setkey, + aes_xts_zerokey, + aes_xts_reinit +}; + /* Authentication instances */ struct auth_hash auth_hash_null = { CRYPTO_NULL_HMAC, "NULL-HMAC", @@ -586,6 +618,106 @@ *sched = NULL; } +#define AES_XTS_BLOCKSIZE 16 +#define AES_XTS_IVSIZE 8 +#define AES_XTS_ALPHA 0x87 /* GF(2^128) generator polynomial */ + +struct aes_xts_ctx { + rijndael_ctx key1; + rijndael_ctx key2; + u_int8_t tweak[AES_XTS_BLOCKSIZE]; +}; + +void +aes_xts_reinit(caddr_t key, u_int8_t *iv) +{ + struct aes_xts_ctx *ctx = (struct aes_xts_ctx *)key; + u_int64_t blocknum; + u_int i; + + /* + * Prepare tweak as E_k2(IV). IV is specified as LE representation + * of a 64-bit block number which we allow to be passed in directly. + */ + bcopy(iv, &blocknum, AES_XTS_IVSIZE); + for (i = 0; i < AES_XTS_IVSIZE; i++) { + ctx->tweak[i] = blocknum & 0xff; + blocknum >>= 8; + } + /* Last 64 bits of IV are always zero */ + bzero(ctx->tweak + AES_XTS_IVSIZE, AES_XTS_IVSIZE); + + rijndael_encrypt(&ctx->key2, ctx->tweak, ctx->tweak); +} + +void +aes_xts_crypt(struct aes_xts_ctx *ctx, u_int8_t *data, u_int do_encrypt) +{ + u_int8_t block[AES_XTS_BLOCKSIZE]; + u_int i, carry_in, carry_out; + + for (i = 0; i < AES_XTS_BLOCKSIZE; i++) + block[i] = data[i] ^ ctx->tweak[i]; + + if (do_encrypt) + rijndael_encrypt(&ctx->key1, block, data); + else + rijndael_decrypt(&ctx->key1, block, data); + + for (i = 0; i < AES_XTS_BLOCKSIZE; i++) + data[i] ^= ctx->tweak[i]; + + /* Exponentiate tweak */ + carry_in = 0; + for (i = 0; i < AES_XTS_BLOCKSIZE; i++) { + carry_out = ctx->tweak[i] & 0x80; + ctx->tweak[i] = (ctx->tweak[i] << 1) | (carry_in ? 1 : 0); + carry_in = carry_out; + } + if (carry_in) + ctx->tweak[0] ^= AES_XTS_ALPHA; + bzero(block, sizeof(block)); +} + +void +aes_xts_encrypt(caddr_t key, u_int8_t *data) +{ + aes_xts_crypt((struct aes_xts_ctx *)key, data, 1); +} + +void +aes_xts_decrypt(caddr_t key, u_int8_t *data) +{ + aes_xts_crypt((struct aes_xts_ctx *)key, data, 0); +} + +int +aes_xts_setkey(u_int8_t **sched, u_int8_t *key, int len) +{ + struct aes_xts_ctx *ctx; + + if (len != 32 && len != 64) + return -1; + + *sched = malloc(sizeof(struct aes_xts_ctx), M_CRYPTO_DATA, + M_WAITOK | M_ZERO); + ctx = (struct aes_xts_ctx *)*sched; + + rijndael_set_key(&ctx->key1, key, len * 4); + rijndael_set_key(&ctx->key2, key + (len / 2), len * 4); + + return 0; +} + +void +aes_xts_zerokey(u_int8_t **sched) +{ + bzero(*sched, sizeof(struct aes_xts_ctx)); + free(*sched, M_CRYPTO_DATA); + *sched = NULL; +} + + /* * And now for auth. */ ==== //depot/projects/soc2009/gk_pefs/sys/opencrypto/xform.h#2 (text+ko) ==== @@ -48,12 +48,13 @@ struct enc_xform { int type; char *name; - u_int16_t blocksize; + u_int16_t blocksize, ivsize; u_int16_t minkey, maxkey; void (*encrypt) (caddr_t, u_int8_t *); void (*decrypt) (caddr_t, u_int8_t *); int (*setkey) (u_int8_t **, u_int8_t *, int len); void (*zerokey) (u_int8_t **); + void (*reinit) (caddr_t, u_int8_t *); }; struct comp_algo { @@ -80,6 +81,7 @@ 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_xts; extern struct enc_xform enc_xform_arc4; extern struct enc_xform enc_xform_camellia;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906050158.n551wme3083821>