diff options
author | 2008-06-09 16:07:00 +0000 | |
---|---|---|
committer | 2008-06-09 16:07:00 +0000 | |
commit | e2ed96e1416e8a5ad0bbd92b3fa6be63d8efc7cc (patch) | |
tree | 60155bb3e7288abf29b94d02be3970119a7d723f | |
parent | man bits for arc4random_bytes => arc4random_buf rename; ok deraadt@ (diff) | |
download | wireguard-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.c | 5 | ||||
-rw-r--r-- | sys/crypto/cryptodev.h | 5 | ||||
-rw-r--r-- | sys/crypto/cryptosoft.c | 44 | ||||
-rw-r--r-- | sys/crypto/xform.c | 135 | ||||
-rw-r--r-- | sys/crypto/xform.h | 3 |
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; |