summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordjm <djm@openbsd.org>2008-06-09 16:07:00 +0000
committerdjm <djm@openbsd.org>2008-06-09 16:07:00 +0000
commite2ed96e1416e8a5ad0bbd92b3fa6be63d8efc7cc (patch)
tree60155bb3e7288abf29b94d02be3970119a7d723f
parentman bits for arc4random_bytes => arc4random_buf rename; ok deraadt@ (diff)
downloadwireguard-openbsd-e2ed96e1416e8a5ad0bbd92b3fa6be63d8efc7cc.tar.xz
wireguard-openbsd-e2ed96e1416e8a5ad0bbd92b3fa6be63d8efc7cc.zip
Implement the AES XTS mode of operation for the crypto(9) framework.
XTS is a "tweaked" AES mode that has properties that are desirable for block device encryption and it is specified in the IEEE P1619-2007 standard for this purpose. prodded by & ok hshoexer@
-rw-r--r--sys/crypto/cryptodev.c5
-rw-r--r--sys/crypto/cryptodev.h5
-rw-r--r--sys/crypto/cryptosoft.c44
-rw-r--r--sys/crypto/xform.c135
-rw-r--r--sys/crypto/xform.h3
5 files changed, 177 insertions, 15 deletions
diff --git a/sys/crypto/cryptodev.c b/sys/crypto/cryptodev.c
index e35ab4a2bd6..9891f790937 100644
--- a/sys/crypto/cryptodev.c
+++ b/sys/crypto/cryptodev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cryptodev.c,v 1.67 2007/09/13 21:26:41 hshoexer Exp $ */
+/* $OpenBSD: cryptodev.c,v 1.68 2008/06/09 16:07:00 djm Exp $ */
/*
* Copyright (c) 2001 Theo de Raadt
@@ -176,6 +176,9 @@ cryptof_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p)
case CRYPTO_AES_CTR:
txform = &enc_xform_aes_ctr;
break;
+ case CRYPTO_AES_XTS:
+ txform = &enc_xform_aes_xts;
+ break;
case CRYPTO_ARC4:
txform = &enc_xform_arc4;
break;
diff --git a/sys/crypto/cryptodev.h b/sys/crypto/cryptodev.h
index 6616a718d58..1a0e7d4a51c 100644
--- a/sys/crypto/cryptodev.h
+++ b/sys/crypto/cryptodev.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cryptodev.h,v 1.46 2007/11/28 13:52:23 tedu Exp $ */
+/* $OpenBSD: cryptodev.h,v 1.47 2008/06/09 16:07:00 djm Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
@@ -97,7 +97,8 @@
#define CRYPTO_SHA2_384_HMAC 19
#define CRYPTO_SHA2_512_HMAC 20
#define CRYPTO_AES_CTR 21
-#define CRYPTO_ALGORITHM_MAX 21 /* Keep updated - see below */
+#define CRYPTO_AES_XTS 22
+#define CRYPTO_ALGORITHM_MAX 22 /* Keep updated - see below */
#define CRYPTO_ALGORITHM_ALL (CRYPTO_ALGORITHM_MAX + 1)
diff --git a/sys/crypto/cryptosoft.c b/sys/crypto/cryptosoft.c
index 9d084bd6f66..b8303d54a0f 100644
--- a/sys/crypto/cryptosoft.c
+++ b/sys/crypto/cryptosoft.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cryptosoft.c,v 1.50 2008/06/09 07:07:15 djm Exp $ */
+/* $OpenBSD: cryptosoft.c,v 1.51 2008/06/09 16:07:00 djm Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
@@ -124,6 +124,10 @@ swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
ivp = iv;
+ /*
+ * xforms that provide a reinit method perform all IV
+ * handling themselves.
+ */
if (exf->reinit)
exf->reinit(sw->sw_kschedule, iv);
@@ -145,7 +149,13 @@ swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
/* Actual encryption/decryption */
if (exf->reinit) {
- exf->encrypt(sw->sw_kschedule, blk);
+ 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++)
@@ -217,7 +227,13 @@ swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
while (m->m_len >= k + blks && i > 0) {
if (exf->reinit) {
- exf->encrypt(sw->sw_kschedule, idat);
+ 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++)
@@ -272,7 +288,13 @@ swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
/* Actual encryption/decryption */
if (exf->reinit) {
- exf->encrypt(sw->sw_kschedule, blk);
+ 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++)
@@ -335,7 +357,13 @@ swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
while (uio->uio_iov[ind].iov_len >= k + blks &&
i > 0) {
if (exf->reinit) {
- exf->encrypt(sw->sw_kschedule, idat);
+ 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++)
@@ -607,6 +635,9 @@ swcr_newsession(u_int32_t *sid, struct cryptoini *cri)
case CRYPTO_AES_CTR:
txf = &enc_xform_aes_ctr;
goto enccommon;
+ case CRYPTO_AES_XTS:
+ txf = &enc_xform_aes_xts;
+ goto enccommon;
case CRYPTO_NULL:
txf = &enc_xform_null;
goto enccommon;
@@ -769,6 +800,7 @@ swcr_freesession(u_int64_t tid)
case CRYPTO_SKIPJACK_CBC:
case CRYPTO_RIJNDAEL128_CBC:
case CRYPTO_AES_CTR:
+ case CRYPTO_AES_XTS:
case CRYPTO_NULL:
txf = swd->sw_exf;
@@ -886,6 +918,7 @@ swcr_process(struct cryptop *crp)
case CRYPTO_SKIPJACK_CBC:
case CRYPTO_RIJNDAEL128_CBC:
case CRYPTO_AES_CTR:
+ case CRYPTO_AES_XTS:
if ((crp->crp_etype = swcr_encdec(crd, sw,
crp->crp_buf, type)) != 0)
goto done;
@@ -957,6 +990,7 @@ swcr_init(void)
algs[CRYPTO_SHA1] = CRYPTO_ALG_FLAG_SUPPORTED;
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_DEFLATE_COMP] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_NULL] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_SHA2_256_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
diff --git a/sys/crypto/xform.c b/sys/crypto/xform.c
index 17ce706202c..ae25a9abdfb 100644
--- a/sys/crypto/xform.c
+++ b/sys/crypto/xform.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xform.c,v 1.33 2007/09/13 21:26:41 hshoexer Exp $ */
+/* $OpenBSD: xform.c,v 1.34 2008/06/09 16:07:00 djm Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -68,18 +68,29 @@ int cast5_setkey(u_int8_t **, u_int8_t *, int);
int skipjack_setkey(u_int8_t **, u_int8_t *, int);
int rijndael128_setkey(u_int8_t **, u_int8_t *, int);
int aes_ctr_setkey(u_int8_t **, u_int8_t *, int);
+int aes_xts_setkey(u_int8_t **, u_int8_t *, int);
+int null_setkey(u_int8_t **, u_int8_t *, int);
+
void des1_encrypt(caddr_t, u_int8_t *);
void des3_encrypt(caddr_t, u_int8_t *);
void blf_encrypt(caddr_t, u_int8_t *);
void cast5_encrypt(caddr_t, u_int8_t *);
void skipjack_encrypt(caddr_t, u_int8_t *);
void rijndael128_encrypt(caddr_t, u_int8_t *);
+void null_encrypt(caddr_t, u_int8_t *);
+void aes_xts_encrypt(caddr_t, u_int8_t *);
+
void des1_decrypt(caddr_t, u_int8_t *);
void des3_decrypt(caddr_t, u_int8_t *);
void blf_decrypt(caddr_t, u_int8_t *);
void cast5_decrypt(caddr_t, u_int8_t *);
void skipjack_decrypt(caddr_t, u_int8_t *);
void rijndael128_decrypt(caddr_t, u_int8_t *);
+void null_decrypt(caddr_t, u_int8_t *);
+void aes_xts_decrypt(caddr_t, u_int8_t *);
+
+void aes_ctr_crypt(caddr_t, u_int8_t *);
+
void des1_zerokey(u_int8_t **);
void des3_zerokey(u_int8_t **);
void blf_zerokey(u_int8_t **);
@@ -87,13 +98,11 @@ void cast5_zerokey(u_int8_t **);
void skipjack_zerokey(u_int8_t **);
void rijndael128_zerokey(u_int8_t **);
void aes_ctr_zerokey(u_int8_t **);
-void null_encrypt(caddr_t, u_int8_t *);
+void aes_xts_zerokey(u_int8_t **);
void null_zerokey(u_int8_t **);
-int null_setkey(u_int8_t **, u_int8_t *, int);
-void null_decrypt(caddr_t, u_int8_t *);
void aes_ctr_reinit(caddr_t, u_int8_t *);
-void aes_ctr_crypt(caddr_t, u_int8_t *);
+void aes_xts_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);
@@ -106,6 +115,10 @@ u_int32_t deflate_compress(u_int8_t *, u_int32_t, u_int8_t **);
u_int32_t deflate_decompress(u_int8_t *, u_int32_t, u_int8_t **);
u_int32_t lzs_dummy(u_int8_t *, u_int32_t, u_int8_t **);
+/* 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_des = {
CRYPTO_DES_CBC, "DES",
@@ -171,12 +184,22 @@ struct enc_xform enc_xform_aes_ctr = {
CRYPTO_AES_CTR, "AES-CTR",
16, 8, 16+4, 32+4,
aes_ctr_crypt,
- NULL,
+ aes_ctr_crypt,
aes_ctr_setkey,
aes_ctr_zerokey,
aes_ctr_reinit
};
+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
+};
+
struct enc_xform enc_xform_arc4 = {
CRYPTO_ARC4, "ARC4",
1, 1, 1, 32,
@@ -571,6 +594,106 @@ aes_ctr_zerokey(u_int8_t **sched)
*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.
*/
diff --git a/sys/crypto/xform.h b/sys/crypto/xform.h
index 5a665cd1e9b..55321bef960 100644
--- a/sys/crypto/xform.h
+++ b/sys/crypto/xform.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: xform.h,v 1.17 2007/09/10 22:19:42 henric Exp $ */
+/* $OpenBSD: xform.h,v 1.18 2008/06/09 16:07:00 djm Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
@@ -78,6 +78,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_ctr;
+extern struct enc_xform enc_xform_aes_xts;
extern struct enc_xform enc_xform_arc4;
extern struct enc_xform enc_xform_null;