PERFORCE change 163537 for review
Gleb Kurtsou
gk at FreeBSD.org
Fri Jun 5 01:58:50 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=163537
Change 163537 by gk at 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 at tla.org),
- * Angelos D. Keromytis (kermit at csd.uch.gr) and
- * Niels Provos (provos at physnet.uni-hamburg.de).
+ * Angelos D. Keromytis (kermit at csd.uch.gr),
+ * Niels Provos (provos at physnet.uni-hamburg.de) and
+ * Damien Miller (djm at 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;
More information about the p4-projects
mailing list