diff options
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/Kconfig | 40 | ||||
-rw-r--r-- | crypto/Makefile | 16 | ||||
-rw-r--r-- | crypto/ablkcipher.c | 11 | ||||
-rw-r--r-- | crypto/aead.c | 101 | ||||
-rw-r--r-- | crypto/aes_generic.c (renamed from crypto/aes.c) | 2 | ||||
-rw-r--r-- | crypto/algapi.c | 37 | ||||
-rw-r--r-- | crypto/async_tx/async_memcpy.c | 19 | ||||
-rw-r--r-- | crypto/async_tx/async_tx.c | 12 | ||||
-rw-r--r-- | crypto/authenc.c | 400 | ||||
-rw-r--r-- | crypto/blkcipher.c | 66 | ||||
-rw-r--r-- | crypto/cipher.c | 7 | ||||
-rw-r--r-- | crypto/cryptd.c | 7 | ||||
-rw-r--r-- | crypto/cryptomgr.c | 96 | ||||
-rw-r--r-- | crypto/des_generic.c (renamed from crypto/des.c) | 1 | ||||
-rw-r--r-- | crypto/gf128mul.c | 11 | ||||
-rw-r--r-- | crypto/hash.c | 5 | ||||
-rw-r--r-- | crypto/internal.h | 11 | ||||
-rw-r--r-- | crypto/scatterwalk.c | 30 | ||||
-rw-r--r-- | crypto/scatterwalk.h | 3 | ||||
-rw-r--r-- | crypto/seed.c | 479 | ||||
-rw-r--r-- | crypto/sha1_generic.c (renamed from crypto/sha1.c) | 10 | ||||
-rw-r--r-- | crypto/sha256_generic.c (renamed from crypto/sha256.c) | 33 | ||||
-rw-r--r-- | crypto/sha512.c | 63 | ||||
-rw-r--r-- | crypto/tcrypt.c | 20 | ||||
-rw-r--r-- | crypto/tcrypt.h | 507 | ||||
-rw-r--r-- | crypto/xts.c | 292 |
26 files changed, 2098 insertions, 181 deletions
diff --git a/crypto/Kconfig b/crypto/Kconfig index 3d1a1e27944f..083d2e1dfc21 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -28,6 +28,10 @@ config CRYPTO_ABLKCIPHER tristate select CRYPTO_BLKCIPHER +config CRYPTO_AEAD + tristate + select CRYPTO_ALGAPI + config CRYPTO_BLKCIPHER tristate select CRYPTO_ALGAPI @@ -146,7 +150,6 @@ config CRYPTO_ECB tristate "ECB support" select CRYPTO_BLKCIPHER select CRYPTO_MANAGER - default m help ECB: Electronic CodeBook mode This is the simplest block cipher algorithm. It simply encrypts @@ -156,7 +159,6 @@ config CRYPTO_CBC tristate "CBC support" select CRYPTO_BLKCIPHER select CRYPTO_MANAGER - default m help CBC: Cipher Block Chaining mode This block cipher algorithm is required for IPSec. @@ -165,7 +167,6 @@ config CRYPTO_PCBC tristate "PCBC support" select CRYPTO_BLKCIPHER select CRYPTO_MANAGER - default m help PCBC: Propagating Cipher Block Chaining mode This block cipher algorithm is required for RxRPC. @@ -183,6 +184,17 @@ config CRYPTO_LRW The first 128, 192 or 256 bits in the key are used for AES and the rest is used to tie each cipher block to its logical position. +config CRYPTO_XTS + tristate "XTS support (EXPERIMENTAL)" + depends on EXPERIMENTAL + select CRYPTO_BLKCIPHER + select CRYPTO_MANAGER + select CRYPTO_GF128MUL + help + XTS: IEEE1619/D16 narrow block cipher use with aes-xts-plain, + key size 256, 384 or 512 bits. This implementation currently + can't handle a sectorsize which is not a multiple of 16 bytes. + config CRYPTO_CRYPTD tristate "Software async crypto daemon" select CRYPTO_ABLKCIPHER @@ -415,6 +427,20 @@ config CRYPTO_ANUBIS <https://www.cosic.esat.kuleuven.ac.be/nessie/reports/> <http://planeta.terra.com.br/informatica/paulobarreto/AnubisPage.html> +config CRYPTO_SEED + tristate "SEED cipher algorithm" + select CRYPTO_ALGAPI + help + SEED cipher algorithm (RFC4269). + + SEED is a 128-bit symmetric key block cipher that has been + developed by KISA (Korea Information Security Agency) as a + national standard encryption algorithm of the Republic of Korea. + It is a 16 round block cipher with the key size of 128 bit. + + See also: + <http://www.kisa.or.kr/kisa/seed/jsp/seed_eng.jsp> + config CRYPTO_DEFLATE tristate "Deflate compression algorithm" @@ -468,6 +494,14 @@ config CRYPTO_TEST help Quick & dirty crypto test module. +config CRYPTO_AUTHENC + tristate "Authenc support" + select CRYPTO_AEAD + select CRYPTO_MANAGER + help + Authenc: Combined mode wrapper for IPsec. + This is required for IPSec. + source "drivers/crypto/Kconfig" endif # if CRYPTO diff --git a/crypto/Makefile b/crypto/Makefile index 0cf17f1ea151..43c2a0dc9936 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -2,13 +2,14 @@ # Cryptographic API # -obj-$(CONFIG_CRYPTO) += api.o scatterwalk.o cipher.o digest.o compress.o +obj-$(CONFIG_CRYPTO) += api.o cipher.o digest.o compress.o crypto_algapi-$(CONFIG_PROC_FS) += proc.o -crypto_algapi-objs := algapi.o $(crypto_algapi-y) +crypto_algapi-objs := algapi.o scatterwalk.o $(crypto_algapi-y) obj-$(CONFIG_CRYPTO_ALGAPI) += crypto_algapi.o obj-$(CONFIG_CRYPTO_ABLKCIPHER) += ablkcipher.o +obj-$(CONFIG_CRYPTO_AEAD) += aead.o obj-$(CONFIG_CRYPTO_BLKCIPHER) += blkcipher.o crypto_hash-objs := hash.o @@ -20,8 +21,8 @@ obj-$(CONFIG_CRYPTO_XCBC) += xcbc.o obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o obj-$(CONFIG_CRYPTO_MD4) += md4.o obj-$(CONFIG_CRYPTO_MD5) += md5.o -obj-$(CONFIG_CRYPTO_SHA1) += sha1.o -obj-$(CONFIG_CRYPTO_SHA256) += sha256.o +obj-$(CONFIG_CRYPTO_SHA1) += sha1_generic.o +obj-$(CONFIG_CRYPTO_SHA256) += sha256_generic.o obj-$(CONFIG_CRYPTO_SHA512) += sha512.o obj-$(CONFIG_CRYPTO_WP512) += wp512.o obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o @@ -30,14 +31,15 @@ obj-$(CONFIG_CRYPTO_ECB) += ecb.o obj-$(CONFIG_CRYPTO_CBC) += cbc.o obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o obj-$(CONFIG_CRYPTO_LRW) += lrw.o +obj-$(CONFIG_CRYPTO_XTS) += xts.o obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o -obj-$(CONFIG_CRYPTO_DES) += des.o +obj-$(CONFIG_CRYPTO_DES) += des_generic.o obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o -obj-$(CONFIG_CRYPTO_AES) += aes.o +obj-$(CONFIG_CRYPTO_AES) += aes_generic.o obj-$(CONFIG_CRYPTO_CAMELLIA) += camellia.o obj-$(CONFIG_CRYPTO_CAST5) += cast5.o obj-$(CONFIG_CRYPTO_CAST6) += cast6.o @@ -45,9 +47,11 @@ obj-$(CONFIG_CRYPTO_ARC4) += arc4.o obj-$(CONFIG_CRYPTO_TEA) += tea.o obj-$(CONFIG_CRYPTO_KHAZAD) += khazad.o obj-$(CONFIG_CRYPTO_ANUBIS) += anubis.o +obj-$(CONFIG_CRYPTO_SEED) += seed.o obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o +obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c index 1c166b47b4cc..2731acb86e7d 100644 --- a/crypto/ablkcipher.c +++ b/crypto/ablkcipher.c @@ -16,10 +16,13 @@ #include <crypto/algapi.h> #include <linux/errno.h> #include <linux/init.h> +#include <linux/kernel.h> #include <linux/module.h> +#include <linux/slab.h> #include <linux/seq_file.h> -static int setkey_unaligned(struct crypto_ablkcipher *tfm, const u8 *key, unsigned int keylen) +static int setkey_unaligned(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int keylen) { struct ablkcipher_alg *cipher = crypto_ablkcipher_alg(tfm); unsigned long alignmask = crypto_ablkcipher_alignmask(tfm); @@ -35,7 +38,7 @@ static int setkey_unaligned(struct crypto_ablkcipher *tfm, const u8 *key, unsign alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); memcpy(alignbuffer, key, keylen); ret = cipher->setkey(tfm, alignbuffer, keylen); - memset(alignbuffer, 0, absize); + memset(alignbuffer, 0, keylen); kfree(buffer); return ret; } @@ -91,10 +94,6 @@ static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg) seq_printf(m, "min keysize : %u\n", ablkcipher->min_keysize); seq_printf(m, "max keysize : %u\n", ablkcipher->max_keysize); seq_printf(m, "ivsize : %u\n", ablkcipher->ivsize); - if (ablkcipher->queue) { - seq_printf(m, "qlen : %u\n", ablkcipher->queue->qlen); - seq_printf(m, "max qlen : %u\n", ablkcipher->queue->max_qlen); - } } const struct crypto_type crypto_ablkcipher_type = { diff --git a/crypto/aead.c b/crypto/aead.c new file mode 100644 index 000000000000..84a3501fb478 --- /dev/null +++ b/crypto/aead.c @@ -0,0 +1,101 @@ +/* + * AEAD: Authenticated Encryption with Associated Data + * + * This file provides API support for AEAD algorithms. + * + * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ + +#include <crypto/algapi.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/seq_file.h> + +static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key, + unsigned int keylen) +{ + struct aead_alg *aead = crypto_aead_alg(tfm); + unsigned long alignmask = crypto_aead_alignmask(tfm); + int ret; + u8 *buffer, *alignbuffer; + unsigned long absize; + + absize = keylen + alignmask; + buffer = kmalloc(absize, GFP_ATOMIC); + if (!buffer) + return -ENOMEM; + + alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); + memcpy(alignbuffer, key, keylen); + ret = aead->setkey(tfm, alignbuffer, keylen); + memset(alignbuffer, 0, keylen); + kfree(buffer); + return ret; +} + +static int setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) +{ + struct aead_alg *aead = crypto_aead_alg(tfm); + unsigned long alignmask = crypto_aead_alignmask(tfm); + + if ((unsigned long)key & alignmask) + return setkey_unaligned(tfm, key, keylen); + + return aead->setkey(tfm, key, keylen); +} + +static unsigned int crypto_aead_ctxsize(struct crypto_alg *alg, u32 type, + u32 mask) +{ + return alg->cra_ctxsize; +} + +static int crypto_init_aead_ops(struct crypto_tfm *tfm, u32 type, u32 mask) +{ + struct aead_alg *alg = &tfm->__crt_alg->cra_aead; + struct aead_tfm *crt = &tfm->crt_aead; + + if (max(alg->authsize, alg->ivsize) > PAGE_SIZE / 8) + return -EINVAL; + + crt->setkey = setkey; + crt->encrypt = alg->encrypt; + crt->decrypt = alg->decrypt; + crt->ivsize = alg->ivsize; + crt->authsize = alg->authsize; + + return 0; +} + +static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg) + __attribute__ ((unused)); +static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg) +{ + struct aead_alg *aead = &alg->cra_aead; + + seq_printf(m, "type : aead\n"); + seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); + seq_printf(m, "ivsize : %u\n", aead->ivsize); + seq_printf(m, "authsize : %u\n", aead->authsize); +} + +const struct crypto_type crypto_aead_type = { + .ctxsize = crypto_aead_ctxsize, + .init = crypto_init_aead_ops, +#ifdef CONFIG_PROC_FS + .show = crypto_aead_show, +#endif +}; +EXPORT_SYMBOL_GPL(crypto_aead_type); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)"); diff --git a/crypto/aes.c b/crypto/aes_generic.c index e2440773878c..9401dca85e87 100644 --- a/crypto/aes.c +++ b/crypto/aes_generic.c @@ -453,4 +453,4 @@ module_exit(aes_fini); MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm"); MODULE_LICENSE("Dual BSD/GPL"); - +MODULE_ALIAS("aes"); diff --git a/crypto/algapi.c b/crypto/algapi.c index 38aa9e994703..8ff8c2656d9c 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -63,9 +63,6 @@ static int crypto_check_alg(struct crypto_alg *alg) if (alg->cra_alignmask & (alg->cra_alignmask + 1)) return -EINVAL; - if (alg->cra_alignmask & alg->cra_blocksize) - return -EINVAL; - if (alg->cra_blocksize > PAGE_SIZE / 8) return -EINVAL; @@ -152,6 +149,11 @@ static int __crypto_register_alg(struct crypto_alg *alg, if (crypto_is_larval(q)) { struct crypto_larval *larval = (void *)q; + /* + * Check to see if either our generic name or + * specific name can satisfy the name requested + * by the larval entry q. + */ if (strcmp(alg->cra_name, q->cra_name) && strcmp(alg->cra_driver_name, q->cra_name)) continue; @@ -439,13 +441,15 @@ EXPORT_SYMBOL_GPL(crypto_unregister_notifier); struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb) { - struct rtattr *rta = tb[CRYPTOA_TYPE - 1]; + struct rtattr *rta = tb[0]; struct crypto_attr_type *algt; if (!rta) return ERR_PTR(-ENOENT); if (RTA_PAYLOAD(rta) < sizeof(*algt)) return ERR_PTR(-EINVAL); + if (rta->rta_type != CRYPTOA_TYPE) + return ERR_PTR(-EINVAL); algt = RTA_DATA(rta); @@ -468,22 +472,41 @@ int crypto_check_attr_type(struct rtattr **tb, u32 type) } EXPORT_SYMBOL_GPL(crypto_check_attr_type); -struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb, u32 type, u32 mask) +struct crypto_alg *crypto_attr_alg(struct rtattr *rta, u32 type, u32 mask) { - struct rtattr *rta = tb[CRYPTOA_ALG - 1]; struct crypto_attr_alg *alga; if (!rta) return ERR_PTR(-ENOENT); if (RTA_PAYLOAD(rta) < sizeof(*alga)) return ERR_PTR(-EINVAL); + if (rta->rta_type != CRYPTOA_ALG) + return ERR_PTR(-EINVAL); alga = RTA_DATA(rta); alga->name[CRYPTO_MAX_ALG_NAME - 1] = 0; return crypto_alg_mod_lookup(alga->name, type, mask); } -EXPORT_SYMBOL_GPL(crypto_get_attr_alg); +EXPORT_SYMBOL_GPL(crypto_attr_alg); + +int crypto_attr_u32(struct rtattr *rta, u32 *num) +{ + struct crypto_attr_u32 *nu32; + + if (!rta) + return -ENOENT; + if (RTA_PAYLOAD(rta) < sizeof(*nu32)) + return -EINVAL; + if (rta->rta_type != CRYPTOA_U32) + return -EINVAL; + + nu32 = RTA_DATA(rta); + *num = nu32->num; + + return 0; +} +EXPORT_SYMBOL_GPL(crypto_attr_u32); struct crypto_instance *crypto_alloc_instance(const char *name, struct crypto_alg *alg) diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c index a973f4ef897d..047e533fcc5b 100644 --- a/crypto/async_tx/async_memcpy.c +++ b/crypto/async_tx/async_memcpy.c @@ -36,7 +36,6 @@ * @offset: offset in pages to start transaction * @len: length in bytes * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK, - * ASYNC_TX_KMAP_SRC, ASYNC_TX_KMAP_DST * @depend_tx: memcpy depends on the result of this transaction * @cb_fn: function to call when the memcpy completes * @cb_param: parameter to pass to the callback routine @@ -88,23 +87,13 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset, __FUNCTION__); } - if (flags & ASYNC_TX_KMAP_DST) - dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset; - else - dest_buf = page_address(dest) + dest_offset; - - if (flags & ASYNC_TX_KMAP_SRC) - src_buf = kmap_atomic(src, KM_USER0) + src_offset; - else - src_buf = page_address(src) + src_offset; + dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset; + src_buf = kmap_atomic(src, KM_USER1) + src_offset; memcpy(dest_buf, src_buf, len); - if (flags & ASYNC_TX_KMAP_DST) - kunmap_atomic(dest_buf, KM_USER0); - - if (flags & ASYNC_TX_KMAP_SRC) - kunmap_atomic(src_buf, KM_USER0); + kunmap_atomic(dest_buf, KM_USER0); + kunmap_atomic(src_buf, KM_USER1); async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param); } diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c index 035007145e78..bc18cbb8ea79 100644 --- a/crypto/async_tx/async_tx.c +++ b/crypto/async_tx/async_tx.c @@ -80,6 +80,7 @@ dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) { enum dma_status status; struct dma_async_tx_descriptor *iter; + struct dma_async_tx_descriptor *parent; if (!tx) return DMA_SUCCESS; @@ -87,8 +88,15 @@ dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) /* poll through the dependency chain, return when tx is complete */ do { iter = tx; - while (iter->cookie == -EBUSY) - iter = iter->parent; + + /* find the root of the unsubmitted dependency chain */ + while (iter->cookie == -EBUSY) { + parent = iter->parent; + if (parent && parent->cookie == -EBUSY) + iter = iter->parent; + else + break; + } status = dma_sync_wait(iter->chan, iter->cookie); } while (status == DMA_IN_PROGRESS || (iter != tx)); diff --git a/crypto/authenc.c b/crypto/authenc.c new file mode 100644 index 000000000000..0b29a6ae673d --- /dev/null +++ b/crypto/authenc.c @@ -0,0 +1,400 @@ +/* + * Authenc: Simple AEAD wrapper for IPsec + * + * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ + +#include <crypto/algapi.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/spinlock.h> + +#include "scatterwalk.h" + +struct authenc_instance_ctx { + struct crypto_spawn auth; + struct crypto_spawn enc; + + unsigned int authsize; + unsigned int enckeylen; +}; + +struct crypto_authenc_ctx { + spinlock_t auth_lock; + struct crypto_hash *auth; + struct crypto_ablkcipher *enc; +}; + +static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key, + unsigned int keylen) +{ + struct authenc_instance_ctx *ictx = + crypto_instance_ctx(crypto_aead_alg_instance(authenc)); + unsigned int enckeylen = ictx->enckeylen; + unsigned int authkeylen; + struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); + struct crypto_hash *auth = ctx->auth; + struct crypto_ablkcipher *enc = ctx->enc; + int err = -EINVAL; + + if (keylen < enckeylen) { + crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN); + goto out; + } + authkeylen = keylen - enckeylen; + + crypto_hash_clear_flags(auth, CRYPTO_TFM_REQ_MASK); + crypto_hash_set_flags(auth, crypto_aead_get_flags(authenc) & + CRYPTO_TFM_REQ_MASK); + err = crypto_hash_setkey(auth, key, authkeylen); + crypto_aead_set_flags(authenc, crypto_hash_get_flags(auth) & + CRYPTO_TFM_RES_MASK); + + if (err) + goto out; + + crypto_ablkcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK); + crypto_ablkcipher_set_flags(enc, crypto_aead_get_flags(authenc) & + CRYPTO_TFM_REQ_MASK); + err = crypto_ablkcipher_setkey(enc, key + authkeylen, enckeylen); + crypto_aead_set_flags(authenc, crypto_ablkcipher_get_flags(enc) & + CRYPTO_TFM_RES_MASK); + +out: + return err; +} + +static int crypto_authenc_hash(struct aead_request *req) +{ + struct crypto_aead *authenc = crypto_aead_reqtfm(req); + struct authenc_instance_ctx *ictx = + crypto_instance_ctx(crypto_aead_alg_instance(authenc)); + struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); + struct crypto_hash *auth = ctx->auth; + struct hash_desc desc = { + .tfm = auth, + }; + u8 *hash = aead_request_ctx(req); + struct scatterlist *dst; + unsigned int cryptlen; + int err; + + hash = (u8 *)ALIGN((unsigned long)hash + crypto_hash_alignmask(auth), + crypto_hash_alignmask(auth) + 1); + + spin_lock_bh(&ctx->auth_lock); + err = crypto_hash_init(&desc); + if (err) + goto auth_unlock; + + err = crypto_hash_update(&desc, req->assoc, req->assoclen); + if (err) + goto auth_unlock; + + cryptlen = req->cryptlen; + dst = req->dst; + err = crypto_hash_update(&desc, dst, cryptlen); + if (err) + goto auth_unlock; + + err = crypto_hash_final(&desc, hash); +auth_unlock: + spin_unlock_bh(&ctx->auth_lock); + + if (err) + return err; + + scatterwalk_map_and_copy(hash, dst, cryptlen, ictx->authsize, 1); + return 0; +} + +static void crypto_authenc_encrypt_done(struct crypto_async_request *req, + int err) +{ + if (!err) + err = crypto_authenc_hash(req->data); + + aead_request_complete(req->data, err); +} + +static int crypto_authenc_encrypt(struct aead_request *req) +{ + struct crypto_aead *authenc = crypto_aead_reqtfm(req); + struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); + struct ablkcipher_request *abreq = aead_request_ctx(req); + int err; + + ablkcipher_request_set_tfm(abreq, ctx->enc); + ablkcipher_request_set_callback(abreq, aead_request_flags(req), + crypto_authenc_encrypt_done, req); + ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen, + req->iv); + + err = crypto_ablkcipher_encrypt(abreq); + if (err) + return err; + + return crypto_authenc_hash(req); +} + +static int crypto_authenc_verify(struct aead_request *req) +{ + struct crypto_aead *authenc = crypto_aead_reqtfm(req); + struct authenc_instance_ctx *ictx = + crypto_instance_ctx(crypto_aead_alg_instance(authenc)); + struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); + struct crypto_hash *auth = ctx->auth; + struct hash_desc desc = { + .tfm = auth, + .flags = aead_request_flags(req), + }; + u8 *ohash = aead_request_ctx(req); + u8 *ihash; + struct scatterlist *src; + unsigned int cryptlen; + unsigned int authsize; + int err; + + ohash = (u8 *)ALIGN((unsigned long)ohash + crypto_hash_alignmask(auth), + crypto_hash_alignmask(auth) + 1); + ihash = ohash + crypto_hash_digestsize(auth); + + spin_lock_bh(&ctx->auth_lock); + err = crypto_hash_init(&desc); + if (err) + goto auth_unlock; + + err = crypto_hash_update(&desc, req->assoc, req->assoclen); + if (err) + goto auth_unlock; + + cryptlen = req->cryptlen; + src = req->src; + err = crypto_hash_update(&desc, src, cryptlen); + if (err) + goto auth_unlock; + + err = crypto_hash_final(&desc, ohash); +auth_unlock: + spin_unlock_bh(&ctx->auth_lock); + + if (err) + return err; + + authsize = ictx->authsize; + scatterwalk_map_and_copy(ihash, src, cryptlen, authsize, 0); + return memcmp(ihash, ohash, authsize) ? -EINVAL : 0; +} + +static void crypto_authenc_decrypt_done(struct crypto_async_request *req, + int err) +{ + aead_request_complete(req->data, err); +} + +static int crypto_authenc_decrypt(struct aead_request *req) +{ + struct crypto_aead *authenc = crypto_aead_reqtfm(req); + struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); + struct ablkcipher_request *abreq = aead_request_ctx(req); + int err; + + err = crypto_authenc_verify(req); + if (err) + return err; + + ablkcipher_request_set_tfm(abreq, ctx->enc); + ablkcipher_request_set_callback(abreq, aead_request_flags(req), + crypto_authenc_decrypt_done, req); + ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen, + req->iv); + + return crypto_ablkcipher_decrypt(abreq); +} + +static int crypto_authenc_init_tfm(struct crypto_tfm *tfm) +{ + struct crypto_instance *inst = (void *)tfm->__crt_alg; + struct authenc_instance_ctx *ictx = crypto_instance_ctx(inst); + struct crypto_authenc_ctx *ctx = crypto_tfm_ctx(tfm); + struct crypto_hash *auth; + struct crypto_ablkcipher *enc; + unsigned int digestsize; + int err; + + auth = crypto_spawn_hash(&ictx->auth); + if (IS_ERR(auth)) + return PTR_ERR(auth); + + err = -EINVAL; + digestsize = crypto_hash_digestsize(auth); + if (ictx->authsize > digestsize) + goto err_free_hash; + + enc = crypto_spawn_ablkcipher(&ictx->enc); + err = PTR_ERR(enc); + if (IS_ERR(enc)) + goto err_free_hash; + + ctx->auth = auth; + ctx->enc = enc; + tfm->crt_aead.reqsize = max_t(unsigned int, + (crypto_hash_alignmask(auth) & + ~(crypto_tfm_ctx_alignment() - 1)) + + digestsize * 2, + sizeof(struct ablkcipher_request) + + crypto_ablkcipher_reqsize(enc)); + + spin_lock_init(&ctx->auth_lock); + + return 0; + +err_free_hash: + crypto_free_hash(auth); + return err; +} + +static void crypto_authenc_exit_tfm(struct crypto_tfm *tfm) +{ + struct crypto_authenc_ctx *ctx = crypto_tfm_ctx(tfm); + + crypto_free_hash(ctx->auth); + crypto_free_ablkcipher(ctx->enc); +} + +static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb) +{ + struct crypto_instance *inst; + struct crypto_alg *auth; + struct crypto_alg *enc; + struct authenc_instance_ctx *ctx; + unsigned int authsize; + unsigned int enckeylen; + int err; + + err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD); + if (err) + return ERR_PTR(err); + + auth = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH, + CRYPTO_ALG_TYPE_HASH_MASK); + if (IS_ERR(auth)) + return ERR_PTR(PTR_ERR(auth)); + + err = crypto_attr_u32(tb[2], &authsize); + inst = ERR_PTR(err); + if (err) + goto out_put_auth; + + enc = crypto_attr_alg(tb[3], CRYPTO_ALG_TYPE_BLKCIPHER, + CRYPTO_ALG_TYPE_MASK); + inst = ERR_PTR(PTR_ERR(enc)); + if (IS_ERR(enc)) + goto out_put_auth; + + err = crypto_attr_u32(tb[4], &enckeylen); + if (err) + goto out_put_enc; + + inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); + err = -ENOMEM; + if (!inst) + goto out_put_enc; + + err = -ENAMETOOLONG; + if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, + "authenc(%s,%u,%s,%u)", auth->cra_name, authsize, + enc->cra_name, enckeylen) >= CRYPTO_MAX_ALG_NAME) + goto err_free_inst; + + if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, + "authenc(%s,%u,%s,%u)", auth->cra_driver_name, + authsize, enc->cra_driver_name, enckeylen) >= + CRYPTO_MAX_ALG_NAME) + goto err_free_inst; + + ctx = crypto_instance_ctx(inst); + ctx->authsize = authsize; + ctx->enckeylen = enckeylen; + + err = crypto_init_spawn(&ctx->auth, auth, inst, CRYPTO_ALG_TYPE_MASK); + if (err) + goto err_free_inst; + + err = crypto_init_spawn(&ctx->enc, enc, inst, CRYPTO_ALG_TYPE_MASK); + if (err) + goto err_drop_auth; + + inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC; + inst->alg.cra_priority = enc->cra_priority * 10 + auth->cra_priority; + inst->alg.cra_blocksize = enc->cra_blocksize; + inst->alg.cra_alignmask = max(auth->cra_alignmask, enc->cra_alignmask); + inst->alg.cra_type = &crypto_aead_type; + + inst->alg.cra_aead.ivsize = enc->cra_blkcipher.ivsize; + inst->alg.cra_aead.authsize = authsize; + + inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_ctx); + + inst->alg.cra_init = crypto_authenc_init_tfm; + inst->alg.cra_exit = crypto_authenc_exit_tfm; + + inst->alg.cra_aead.setkey = crypto_authenc_setkey; + inst->alg.cra_aead.encrypt = crypto_authenc_encrypt; + inst->alg.cra_aead.decrypt = crypto_authenc_decrypt; + +out: + crypto_mod_put(enc); +out_put_auth: + crypto_mod_put(auth); + return inst; + +err_drop_auth: + crypto_drop_spawn(&ctx->auth); +err_free_inst: + kfree(inst); +out_put_enc: + inst = ERR_PTR(err); + goto out; +} + +static void crypto_authenc_free(struct crypto_instance *inst) +{ + struct authenc_instance_ctx *ctx = crypto_instance_ctx(inst); + + crypto_drop_spawn(&ctx->enc); + crypto_drop_spawn(&ctx->auth); + kfree(inst); +} + +static struct crypto_template crypto_authenc_tmpl = { + .name = "authenc", + .alloc = crypto_authenc_alloc, + .free = crypto_authenc_free, + .module = THIS_MODULE, +}; + +static int __init crypto_authenc_module_init(void) +{ + return crypto_register_template(&crypto_authenc_tmpl); +} + +static void __exit crypto_authenc_module_exit(void) +{ + crypto_unregister_template(&crypto_authenc_tmpl); +} + +module_init(crypto_authenc_module_init); +module_exit(crypto_authenc_module_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Simple AEAD wrapper for IPsec"); diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c index 40a3dcff15bb..f6c67f9d4e5c 100644 --- a/crypto/blkcipher.c +++ b/crypto/blkcipher.c @@ -59,11 +59,13 @@ static inline void blkcipher_unmap_dst(struct blkcipher_walk *walk) scatterwalk_unmap(walk->dst.virt.addr, 1); } +/* Get a spot of the specified length that does not straddle a page. + * The caller needs to ensure that there is enough space for this operation. + */ static inline u8 *blkcipher_get_spot(u8 *start, unsigned int len) { - if (offset_in_page(start + len) < len) - return (u8 *)((unsigned long)(start + len) & PAGE_MASK); - return start; + u8 *end_page = (u8 *)(((unsigned long)(start + len - 1)) & PAGE_MASK); + return max(start, end_page); } static inline unsigned int blkcipher_done_slow(struct crypto_blkcipher *tfm, @@ -82,8 +84,6 @@ static inline unsigned int blkcipher_done_slow(struct crypto_blkcipher *tfm, static inline unsigned int blkcipher_done_fast(struct blkcipher_walk *walk, unsigned int n) { - n = walk->nbytes - n; - if (walk->flags & BLKCIPHER_WALK_COPY) { blkcipher_map_dst(walk); memcpy(walk->dst.virt.addr, walk->page, n); @@ -107,13 +107,15 @@ int blkcipher_walk_done(struct blkcipher_desc *desc, unsigned int nbytes = 0; if (likely(err >= 0)) { - unsigned int bsize = crypto_blkcipher_blocksize(tfm); - unsigned int n; + unsigned int n = walk->nbytes - err; if (likely(!(walk->flags & BLKCIPHER_WALK_SLOW))) - n = blkcipher_done_fast(walk, err); - else - n = blkcipher_done_slow(tfm, walk, bsize); + n = blkcipher_done_fast(walk, n); + else if (WARN_ON(err)) { + err = -EINVAL; + goto err; + } else + n = blkcipher_done_slow(tfm, walk, n); nbytes = walk->total - n; err = 0; @@ -130,6 +132,7 @@ int blkcipher_walk_done(struct blkcipher_desc *desc, return blkcipher_walk_next(desc, walk); } +err: if (walk->iv != desc->info) memcpy(desc->info, walk->iv, crypto_blkcipher_ivsize(tfm)); if (walk->buffer != walk->page) @@ -147,6 +150,7 @@ static inline int blkcipher_next_slow(struct blkcipher_desc *desc, unsigned int alignmask) { unsigned int n; + unsigned aligned_bsize = ALIGN(bsize, alignmask + 1); if (walk->buffer) goto ok; @@ -155,7 +159,8 @@ static inline int blkcipher_next_slow(struct blkcipher_desc *desc, if (walk->buffer) goto ok; - n = bsize * 2 + (alignmask & ~(crypto_tfm_ctx_alignment() - 1)); + n = aligned_bsize * 3 - (alignmask + 1) + + (alignmask & ~(crypto_tfm_ctx_alignment() - 1)); walk->buffer = kmalloc(n, GFP_ATOMIC); if (!walk->buffer) return blkcipher_walk_done(desc, walk, -ENOMEM); @@ -164,8 +169,8 @@ ok: walk->dst.virt.addr = (u8 *)ALIGN((unsigned long)walk->buffer, alignmask + 1); walk->dst.virt.addr = blkcipher_get_spot(walk->dst.virt.addr, bsize); - walk->src.virt.addr = blkcipher_get_spot(walk->dst.virt.addr + bsize, - bsize); + walk->src.virt.addr = blkcipher_get_spot(walk->dst.virt.addr + + aligned_bsize, bsize); scatterwalk_copychunks(walk->src.virt.addr, &walk->in, bsize, 0); @@ -221,12 +226,12 @@ static int blkcipher_walk_next(struct blkcipher_desc *desc, { struct crypto_blkcipher *tfm = desc->tfm; unsigned int alignmask = crypto_blkcipher_alignmask(tfm); - unsigned int bsize = crypto_blkcipher_blocksize(tfm); + unsigned int bsize; unsigned int n; int err; n = walk->total; - if (unlikely(n < bsize)) { + if (unlikely(n < crypto_blkcipher_blocksize(tfm))) { desc->flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; return blkcipher_walk_done(desc, walk, -EINVAL); } @@ -243,6 +248,7 @@ static int blkcipher_walk_next(struct blkcipher_desc *desc, } } + bsize = min(walk->blocksize, n); n = scatterwalk_clamp(&walk->in, n); n = scatterwalk_clamp(&walk->out, n); @@ -273,9 +279,11 @@ static inline int blkcipher_copy_iv(struct blkcipher_walk *walk, struct crypto_blkcipher *tfm, unsigned int alignmask) { - unsigned bs = crypto_blkcipher_blocksize(tfm); + unsigned bs = walk->blocksize; unsigned int ivsize = crypto_blkcipher_ivsize(tfm); - unsigned int size = bs * 2 + ivsize + max(bs, ivsize) - (alignmask + 1); + unsigned aligned_bs = ALIGN(bs, alignmask + 1); + unsigned int size = aligned_bs * 2 + ivsize + max(aligned_bs, ivsize) - + (alignmask + 1); u8 *iv; size += alignmask & ~(crypto_tfm_ctx_alignment() - 1); @@ -284,8 +292,8 @@ static inline int blkcipher_copy_iv(struct blkcipher_walk *walk, return -ENOMEM; iv = (u8 *)ALIGN((unsigned long)walk->buffer, alignmask + 1); - iv = blkcipher_get_spot(iv, bs) + bs; - iv = blkcipher_get_spot(iv, bs) + bs; + iv = blkcipher_get_spot(iv, bs) + aligned_bs; + iv = blkcipher_get_spot(iv, bs) + aligned_bs; iv = blkcipher_get_spot(iv, ivsize); walk->iv = memcpy(iv, walk->iv, ivsize); @@ -296,6 +304,7 @@ int blkcipher_walk_virt(struct blkcipher_desc *desc, struct blkcipher_walk *walk) { walk->flags &= ~BLKCIPHER_WALK_PHYS; + walk->blocksize = crypto_blkcipher_blocksize(desc->tfm); return blkcipher_walk_first(desc, walk); } EXPORT_SYMBOL_GPL(blkcipher_walk_virt); @@ -304,6 +313,7 @@ int blkcipher_walk_phys(struct blkcipher_desc *desc, struct blkcipher_walk *walk) { walk->flags |= BLKCIPHER_WALK_PHYS; + walk->blocksize = crypto_blkcipher_blocksize(desc->tfm); return blkcipher_walk_first(desc, walk); } EXPORT_SYMBOL_GPL(blkcipher_walk_phys); @@ -336,7 +346,18 @@ static int blkcipher_walk_first(struct blkcipher_desc *desc, return blkcipher_walk_next(desc, walk); } -static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) +int blkcipher_walk_virt_block(struct blkcipher_desc *desc, + struct blkcipher_walk *walk, + unsigned int blocksize) +{ + walk->flags &= ~BLKCIPHER_WALK_PHYS; + walk->blocksize = blocksize; + return blkcipher_walk_first(desc, walk); +} +EXPORT_SYMBOL_GPL(blkcipher_walk_virt_block); + +static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen) { struct blkcipher_alg *cipher = &tfm->__crt_alg->cra_blkcipher; unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); @@ -352,13 +373,12 @@ static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key, unsigned int alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); memcpy(alignbuffer, key, keylen); ret = cipher->setkey(tfm, alignbuffer, keylen); - memset(alignbuffer, 0, absize); + memset(alignbuffer, 0, keylen); kfree(buffer); return ret; } -static int setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) +static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) { struct blkcipher_alg *cipher = &tfm->__crt_alg->cra_blkcipher; unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); diff --git a/crypto/cipher.c b/crypto/cipher.c index 0b2650c2014b..9a1a7316eeac 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -16,11 +16,12 @@ #include <linux/kernel.h> #include <linux/crypto.h> #include <linux/errno.h> -#include <linux/scatterlist.h> +#include <linux/slab.h> #include <linux/string.h> #include "internal.h" -static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) +static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen) { struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher; unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); @@ -36,7 +37,7 @@ static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key, unsigned int alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); memcpy(alignbuffer, key, keylen); ret = cia->cia_setkey(tfm, alignbuffer, keylen); - memset(alignbuffer, 0, absize); + memset(alignbuffer, 0, keylen); kfree(buffer); return ret; diff --git a/crypto/cryptd.c b/crypto/cryptd.c index ac6dce2e7596..8bf2da835f7b 100644 --- a/crypto/cryptd.c +++ b/crypto/cryptd.c @@ -131,7 +131,7 @@ static int cryptd_blkcipher_enqueue(struct ablkcipher_request *req, req->base.complete = complete; spin_lock_bh(&state->lock); - err = ablkcipher_enqueue_request(crypto_ablkcipher_alg(tfm), req); + err = ablkcipher_enqueue_request(&state->queue, req); spin_unlock_bh(&state->lock); wake_up_process(state->task); @@ -173,7 +173,8 @@ static void cryptd_blkcipher_exit_tfm(struct crypto_tfm *tfm) int active; mutex_lock(&state->mutex); - active = ablkcipher_tfm_in_queue(__crypto_ablkcipher_cast(tfm)); + active = ablkcipher_tfm_in_queue(&state->queue, + __crypto_ablkcipher_cast(tfm)); mutex_unlock(&state->mutex); BUG_ON(active); @@ -251,8 +252,6 @@ static struct crypto_instance *cryptd_alloc_blkcipher( inst->alg.cra_ablkcipher.encrypt = cryptd_blkcipher_encrypt_enqueue; inst->alg.cra_ablkcipher.decrypt = cryptd_blkcipher_decrypt_enqueue; - inst->alg.cra_ablkcipher.queue = &state->queue; - out_put_alg: crypto_mod_put(alg); return inst; diff --git a/crypto/cryptomgr.c b/crypto/cryptomgr.c index e5fb7cca5107..e5e3cf848d42 100644 --- a/crypto/cryptomgr.c +++ b/crypto/cryptomgr.c @@ -24,22 +24,26 @@ #include "internal.h" struct cryptomgr_param { - struct rtattr *tb[CRYPTOA_MAX]; + struct rtattr *tb[CRYPTO_MAX_ATTRS + 2]; struct { struct rtattr attr; struct crypto_attr_type data; } type; - struct { + union { struct rtattr attr; - struct crypto_attr_alg data; - } alg; - - struct { - char name[CRYPTO_MAX_ALG_NAME]; - } larval; - + struct { + struct rtattr attr; + struct crypto_attr_alg data; + } alg; + struct { + struct rtattr attr; + struct crypto_attr_u32 data; + } nu32; + } attrs[CRYPTO_MAX_ATTRS]; + + char larval[CRYPTO_MAX_ALG_NAME]; char template[CRYPTO_MAX_ALG_NAME]; }; @@ -72,7 +76,7 @@ out: module_put_and_exit(0); err: - crypto_larval_error(param->larval.name, param->type.data.type, + crypto_larval_error(param->larval, param->type.data.type, param->type.data.mask); goto out; } @@ -84,6 +88,7 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval) const char *name = larval->alg.cra_name; const char *p; unsigned int len; + int i; if (!try_module_get(THIS_MODULE)) goto err; @@ -101,33 +106,74 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval) memcpy(param->template, name, len); - name = p + 1; - len = 0; - for (p = name; *p; p++) { - for (; isalnum(*p) || *p == '-' || *p == '_' || *p == '('; p++) - ; + i = 0; + for (;;) { + int notnum = 0; - if (*p != ')') - goto err_free_param; + name = ++p; + len = 0; + + for (; isalnum(*p) || *p == '-' || *p == '_'; p++) + notnum |= !isdigit(*p); + + if (*p == '(') { + int recursion = 0; + + for (;;) { + if (!*++p) + goto err_free_param; + if (*p == '(') + recursion++; + else if (*p == ')' && !recursion--) + break; + } + + notnum = 1; + p++; + } len = p - name; + if (!len) + goto err_free_param; + + if (notnum) { + param->attrs[i].alg.attr.rta_len = + sizeof(param->attrs[i].alg); + param->attrs[i].alg.attr.rta_type = CRYPTOA_ALG; + memcpy(param->attrs[i].alg.data.name, name, len); + } else { + param->attrs[i].nu32.attr.rta_len = + sizeof(param->attrs[i].nu32); + param->attrs[i].nu32.attr.rta_type = CRYPTOA_U32; + param->attrs[i].nu32.data.num = + simple_strtol(name, NULL, 0); + } + + param->tb[i + 1] = ¶m->attrs[i].attr; + i++; + + if (i >= CRYPTO_MAX_ATTRS) + goto err_free_param; + + if (*p == ')') + break; + + if (*p != ',') + goto err_free_param; } - if (!len || name[len + 1]) + if (!i) goto err_free_param; + param->tb[i + 1] = NULL; + param->type.attr.rta_len = sizeof(param->type); param->type.attr.rta_type = CRYPTOA_TYPE; param->type.data.type = larval->alg.cra_flags; param->type.data.mask = larval->mask; - param->tb[CRYPTOA_TYPE - 1] = ¶m->type.attr; - - param->alg.attr.rta_len = sizeof(param->alg); - param->alg.attr.rta_type = CRYPTOA_ALG; - memcpy(param->alg.data.name, name, len); - param->tb[CRYPTOA_ALG - 1] = ¶m->alg.attr; + param->tb[0] = ¶m->type.attr; - memcpy(param->larval.name, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME); + memcpy(param->larval, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME); thread = kthread_run(cryptomgr_probe, param, "cryptomgr"); if (IS_ERR(thread)) diff --git a/crypto/des.c b/crypto/des_generic.c index 1df3a714fa47..59966d14b8e0 100644 --- a/crypto/des.c +++ b/crypto/des_generic.c @@ -1009,3 +1009,4 @@ module_exit(fini); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms"); MODULE_AUTHOR("Dag Arne Osvik <da@osvik.no>"); +MODULE_ALIAS("des"); diff --git a/crypto/gf128mul.c b/crypto/gf128mul.c index 0a2aadfa1d85..ecbeaa1f17e1 100644 --- a/crypto/gf128mul.c +++ b/crypto/gf128mul.c @@ -142,6 +142,17 @@ static void gf128mul_x_bbe(be128 *r, const be128 *x) r->b = cpu_to_be64((b << 1) ^ _tt); } +void gf128mul_x_ble(be128 *r, const be128 *x) +{ + u64 a = le64_to_cpu(x->a); + u64 b = le64_to_cpu(x->b); + u64 _tt = gf128mul_table_bbe[b >> 63]; + + r->a = cpu_to_le64((a << 1) ^ _tt); + r->b = cpu_to_le64((b << 1) | (a >> 63)); +} +EXPORT_SYMBOL(gf128mul_x_ble); + static void gf128mul_x8_lle(be128 *x) { u64 a = be64_to_cpu(x->a); diff --git a/crypto/hash.c b/crypto/hash.c index 4d75ca7b57b2..7dcff671c19b 100644 --- a/crypto/hash.c +++ b/crypto/hash.c @@ -12,6 +12,7 @@ #include <linux/errno.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/slab.h> #include <linux/seq_file.h> #include "internal.h" @@ -40,13 +41,13 @@ static int hash_setkey_unaligned(struct crypto_hash *crt, const u8 *key, alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); memcpy(alignbuffer, key, keylen); ret = alg->setkey(crt, alignbuffer, keylen); - memset(alignbuffer, 0, absize); + memset(alignbuffer, 0, keylen); kfree(buffer); return ret; } static int hash_setkey(struct crypto_hash *crt, const u8 *key, - unsigned int keylen) + unsigned int keylen) { struct crypto_tfm *tfm = crypto_hash_tfm(crt); struct hash_alg *alg = &tfm->__crt_alg->cra_hash; diff --git a/crypto/internal.h b/crypto/internal.h index 60acad9788c5..abb01f71f817 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -50,11 +50,16 @@ extern struct list_head crypto_alg_list; extern struct rw_semaphore crypto_alg_sem; extern struct blocking_notifier_head crypto_chain; -extern enum km_type crypto_km_types[]; - static inline enum km_type crypto_kmap_type(int out) { - return crypto_km_types[(in_softirq() ? 2 : 0) + out]; + enum km_type type; + + if (in_softirq()) + type = out * (KM_SOFTIRQ1 - KM_SOFTIRQ0) + KM_SOFTIRQ0; + else + type = out * (KM_USER1 - KM_USER0) + KM_USER0; + + return type; } static inline void *crypto_kmap(struct page *page, int out) diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c index 81afd1790a1d..3052f6507f53 100644 --- a/crypto/scatterwalk.c +++ b/crypto/scatterwalk.c @@ -23,14 +23,6 @@ #include "internal.h" #include "scatterwalk.h" -enum km_type crypto_km_types[] = { - KM_USER0, - KM_USER1, - KM_SOFTIRQ0, - KM_SOFTIRQ1, -}; -EXPORT_SYMBOL_GPL(crypto_km_types); - static inline void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out) { void *src = out ? buf : sgdata; @@ -107,3 +99,25 @@ void scatterwalk_copychunks(void *buf, struct scatter_walk *walk, } } EXPORT_SYMBOL_GPL(scatterwalk_copychunks); + +void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg, + unsigned int start, unsigned int nbytes, int out) +{ + struct scatter_walk walk; + unsigned int offset = 0; + + for (;;) { + scatterwalk_start(&walk, sg); + + if (start < offset + sg->length) + break; + + offset += sg->length; + sg = sg_next(sg); + } + + scatterwalk_advance(&walk, start - offset); + scatterwalk_copychunks(buf, &walk, nbytes, out); + scatterwalk_done(&walk, out, 0); +} +EXPORT_SYMBOL_GPL(scatterwalk_map_and_copy); diff --git a/crypto/scatterwalk.h b/crypto/scatterwalk.h index f1592cc2d0f4..500a220ad908 100644 --- a/crypto/scatterwalk.h +++ b/crypto/scatterwalk.h @@ -74,4 +74,7 @@ void scatterwalk_copychunks(void *buf, struct scatter_walk *walk, void *scatterwalk_map(struct scatter_walk *walk, int out); void scatterwalk_done(struct scatter_walk *walk, int out, int more); +void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg, + unsigned int start, unsigned int nbytes, int out); + #endif /* _CRYPTO_SCATTERWALK_H */ diff --git a/crypto/seed.c b/crypto/seed.c new file mode 100644 index 000000000000..d3e422f60556 --- /dev/null +++ b/crypto/seed.c @@ -0,0 +1,479 @@ +/* + * Cryptographic API. + * + * SEED Cipher Algorithm. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Documentation of SEED can be found in RFC 4269. + * Copyright (C) 2007 Korea Information Security Agency (KISA). + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/crypto.h> +#include <asm/byteorder.h> + +#define SEED_NUM_KCONSTANTS 16 +#define SEED_KEY_SIZE 16 +#define SEED_BLOCK_SIZE 16 +#define SEED_KEYSCHED_LEN 32 + +/* + * #define byte(x, nr) ((unsigned char)((x) >> (nr*8))) + */ +static inline u8 +byte(const u32 x, const unsigned n) +{ + return x >> (n << 3); +} + +struct seed_ctx { + u32 keysched[SEED_KEYSCHED_LEN]; +}; + +static const u32 SS0[256] = { + 0x2989a1a8, 0x05858184, 0x16c6d2d4, 0x13c3d3d0, + 0x14445054, 0x1d0d111c, 0x2c8ca0ac, 0x25052124, + 0x1d4d515c, 0x03434340, 0x18081018, 0x1e0e121c, + 0x11415150, 0x3cccf0fc, 0x0acac2c8, 0x23436360, + 0x28082028, 0x04444044, 0x20002020, 0x1d8d919c, + 0x20c0e0e0, 0x22c2e2e0, 0x08c8c0c8, 0x17071314, + 0x2585a1a4, 0x0f8f838c, 0x03030300, 0x3b4b7378, + 0x3b8bb3b8, 0x13031310, 0x12c2d2d0, 0x2ecee2ec, + 0x30407070, 0x0c8c808c, 0x3f0f333c, 0x2888a0a8, + 0x32023230, 0x1dcdd1dc, 0x36c6f2f4, 0x34447074, + 0x2ccce0ec, 0x15859194, 0x0b0b0308, 0x17475354, + 0x1c4c505c, 0x1b4b5358, 0x3d8db1bc, 0x01010100, + 0x24042024, 0x1c0c101c, 0x33437370, 0x18889098, + 0x10001010, 0x0cccc0cc, 0x32c2f2f0, 0x19c9d1d8, + 0x2c0c202c, 0x27c7e3e4, 0x32427270, 0x03838380, + 0x1b8b9398, 0x11c1d1d0, 0x06868284, 0x09c9c1c8, + 0x20406060, 0x10405050, 0x2383a3a0, 0x2bcbe3e8, + 0x0d0d010c, 0x3686b2b4, 0x1e8e929c, 0x0f4f434c, + 0x3787b3b4, 0x1a4a5258, 0x06c6c2c4, 0x38487078, + 0x2686a2a4, 0x12021210, 0x2f8fa3ac, 0x15c5d1d4, + 0x21416160, 0x03c3c3c0, 0x3484b0b4, 0x01414140, + 0x12425250, 0x3d4d717c, 0x0d8d818c, 0x08080008, + 0x1f0f131c, 0x19899198, 0x00000000, 0x19091118, + 0x04040004, 0x13435350, 0x37c7f3f4, 0x21c1e1e0, + 0x3dcdf1fc, 0x36467274, 0x2f0f232c, 0x27072324, + 0x3080b0b0, 0x0b8b8388, 0x0e0e020c, 0x2b8ba3a8, + 0x2282a2a0, 0x2e4e626c, 0x13839390, 0x0d4d414c, + 0x29496168, 0x3c4c707c, 0x09090108, 0x0a0a0208, + 0x3f8fb3bc, 0x2fcfe3ec, 0x33c3f3f0, 0x05c5c1c4, + 0x07878384, 0x14041014, 0x3ecef2fc, 0x24446064, + 0x1eced2dc, 0x2e0e222c, 0x0b4b4348, 0x1a0a1218, + 0x06060204, 0x21012120, 0x2b4b6368, 0x26466264, + 0x02020200, 0x35c5f1f4, 0x12829290, 0x0a8a8288, + 0x0c0c000c, 0x3383b3b0, 0x3e4e727c, 0x10c0d0d0, + 0x3a4a7278, 0x07474344, 0x16869294, 0x25c5e1e4, + 0x26062224, 0x00808080, 0x2d8da1ac, 0x1fcfd3dc, + 0x2181a1a0, 0x30003030, 0x37073334, 0x2e8ea2ac, + 0x36063234, 0x15051114, 0x22022220, 0x38083038, + 0x34c4f0f4, 0x2787a3a4, 0x05454144, 0x0c4c404c, + 0x01818180, 0x29c9e1e8, 0x04848084, 0x17879394, + 0x35053134, 0x0bcbc3c8, 0x0ecec2cc, 0x3c0c303c, + 0x31417170, 0x11011110, 0x07c7c3c4, 0x09898188, + 0x35457174, 0x3bcbf3f8, 0x1acad2d8, 0x38c8f0f8, + 0x14849094, 0x19495158, 0x02828280, 0x04c4c0c4, + 0x3fcff3fc, 0x09494148, 0x39093138, 0x27476364, + 0x00c0c0c0, 0x0fcfc3cc, 0x17c7d3d4, 0x3888b0b8, + 0x0f0f030c, 0x0e8e828c, 0x02424240, 0x23032320, + 0x11819190, 0x2c4c606c, 0x1bcbd3d8, 0x2484a0a4, + 0x34043034, 0x31c1f1f0, 0x08484048, 0x02c2c2c0, + 0x2f4f636c, 0x3d0d313c, 0x2d0d212c, 0x00404040, + 0x3e8eb2bc, 0x3e0e323c, 0x3c8cb0bc, 0x01c1c1c0, + 0x2a8aa2a8, 0x3a8ab2b8, 0x0e4e424c, 0x15455154, + 0x3b0b3338, 0x1cccd0dc, 0x28486068, 0x3f4f737c, + 0x1c8c909c, 0x18c8d0d8, 0x0a4a4248, 0x16465254, + 0x37477374, 0x2080a0a0, 0x2dcde1ec, 0x06464244, + 0x3585b1b4, 0x2b0b2328, 0x25456164, 0x3acaf2f8, + 0x23c3e3e0, 0x3989b1b8, 0x3181b1b0, 0x1f8f939c, + 0x1e4e525c, 0x39c9f1f8, 0x26c6e2e4, 0x3282b2b0, + 0x31013130, 0x2acae2e8, 0x2d4d616c, 0x1f4f535c, + 0x24c4e0e4, 0x30c0f0f0, 0x0dcdc1cc, 0x08888088, + 0x16061214, 0x3a0a3238, 0x18485058, 0x14c4d0d4, + 0x22426260, 0x29092128, 0x07070304, 0x33033330, + 0x28c8e0e8, 0x1b0b1318, 0x05050104, 0x39497178, + 0x10809090, 0x2a4a6268, 0x2a0a2228, 0x1a8a9298, +}; + +static const u32 SS1[256] = { + 0x38380830, 0xe828c8e0, 0x2c2d0d21, 0xa42686a2, + 0xcc0fcfc3, 0xdc1eced2, 0xb03383b3, 0xb83888b0, + 0xac2f8fa3, 0x60204060, 0x54154551, 0xc407c7c3, + 0x44044440, 0x6c2f4f63, 0x682b4b63, 0x581b4b53, + 0xc003c3c3, 0x60224262, 0x30330333, 0xb43585b1, + 0x28290921, 0xa02080a0, 0xe022c2e2, 0xa42787a3, + 0xd013c3d3, 0x90118191, 0x10110111, 0x04060602, + 0x1c1c0c10, 0xbc3c8cb0, 0x34360632, 0x480b4b43, + 0xec2fcfe3, 0x88088880, 0x6c2c4c60, 0xa82888a0, + 0x14170713, 0xc404c4c0, 0x14160612, 0xf434c4f0, + 0xc002c2c2, 0x44054541, 0xe021c1e1, 0xd416c6d2, + 0x3c3f0f33, 0x3c3d0d31, 0x8c0e8e82, 0x98188890, + 0x28280820, 0x4c0e4e42, 0xf436c6f2, 0x3c3e0e32, + 0xa42585a1, 0xf839c9f1, 0x0c0d0d01, 0xdc1fcfd3, + 0xd818c8d0, 0x282b0b23, 0x64264662, 0x783a4a72, + 0x24270723, 0x2c2f0f23, 0xf031c1f1, 0x70324272, + 0x40024242, 0xd414c4d0, 0x40014141, 0xc000c0c0, + 0x70334373, 0x64274763, 0xac2c8ca0, 0x880b8b83, + 0xf437c7f3, 0xac2d8da1, 0x80008080, 0x1c1f0f13, + 0xc80acac2, 0x2c2c0c20, 0xa82a8aa2, 0x34340430, + 0xd012c2d2, 0x080b0b03, 0xec2ecee2, 0xe829c9e1, + 0x5c1d4d51, 0x94148490, 0x18180810, 0xf838c8f0, + 0x54174753, 0xac2e8ea2, 0x08080800, 0xc405c5c1, + 0x10130313, 0xcc0dcdc1, 0x84068682, 0xb83989b1, + 0xfc3fcff3, 0x7c3d4d71, 0xc001c1c1, 0x30310131, + 0xf435c5f1, 0x880a8a82, 0x682a4a62, 0xb03181b1, + 0xd011c1d1, 0x20200020, 0xd417c7d3, 0x00020202, + 0x20220222, 0x04040400, 0x68284860, 0x70314171, + 0x04070703, 0xd81bcbd3, 0x9c1d8d91, 0x98198991, + 0x60214161, 0xbc3e8eb2, 0xe426c6e2, 0x58194951, + 0xdc1dcdd1, 0x50114151, 0x90108090, 0xdc1cccd0, + 0x981a8a92, 0xa02383a3, 0xa82b8ba3, 0xd010c0d0, + 0x80018181, 0x0c0f0f03, 0x44074743, 0x181a0a12, + 0xe023c3e3, 0xec2ccce0, 0x8c0d8d81, 0xbc3f8fb3, + 0x94168692, 0x783b4b73, 0x5c1c4c50, 0xa02282a2, + 0xa02181a1, 0x60234363, 0x20230323, 0x4c0d4d41, + 0xc808c8c0, 0x9c1e8e92, 0x9c1c8c90, 0x383a0a32, + 0x0c0c0c00, 0x2c2e0e22, 0xb83a8ab2, 0x6c2e4e62, + 0x9c1f8f93, 0x581a4a52, 0xf032c2f2, 0x90128292, + 0xf033c3f3, 0x48094941, 0x78384870, 0xcc0cccc0, + 0x14150511, 0xf83bcbf3, 0x70304070, 0x74354571, + 0x7c3f4f73, 0x34350531, 0x10100010, 0x00030303, + 0x64244460, 0x6c2d4d61, 0xc406c6c2, 0x74344470, + 0xd415c5d1, 0xb43484b0, 0xe82acae2, 0x08090901, + 0x74364672, 0x18190911, 0xfc3ecef2, 0x40004040, + 0x10120212, 0xe020c0e0, 0xbc3d8db1, 0x04050501, + 0xf83acaf2, 0x00010101, 0xf030c0f0, 0x282a0a22, + 0x5c1e4e52, 0xa82989a1, 0x54164652, 0x40034343, + 0x84058581, 0x14140410, 0x88098981, 0x981b8b93, + 0xb03080b0, 0xe425c5e1, 0x48084840, 0x78394971, + 0x94178793, 0xfc3cccf0, 0x1c1e0e12, 0x80028282, + 0x20210121, 0x8c0c8c80, 0x181b0b13, 0x5c1f4f53, + 0x74374773, 0x54144450, 0xb03282b2, 0x1c1d0d11, + 0x24250521, 0x4c0f4f43, 0x00000000, 0x44064642, + 0xec2dcde1, 0x58184850, 0x50124252, 0xe82bcbe3, + 0x7c3e4e72, 0xd81acad2, 0xc809c9c1, 0xfc3dcdf1, + 0x30300030, 0x94158591, 0x64254561, 0x3c3c0c30, + 0xb43686b2, 0xe424c4e0, 0xb83b8bb3, 0x7c3c4c70, + 0x0c0e0e02, 0x50104050, 0x38390931, 0x24260622, + 0x30320232, 0x84048480, 0x68294961, 0x90138393, + 0x34370733, 0xe427c7e3, 0x24240420, 0xa42484a0, + 0xc80bcbc3, 0x50134353, 0x080a0a02, 0x84078783, + 0xd819c9d1, 0x4c0c4c40, 0x80038383, 0x8c0f8f83, + 0xcc0ecec2, 0x383b0b33, 0x480a4a42, 0xb43787b3, +}; + +static const u32 SS2[256] = { + 0xa1a82989, 0x81840585, 0xd2d416c6, 0xd3d013c3, + 0x50541444, 0x111c1d0d, 0xa0ac2c8c, 0x21242505, + 0x515c1d4d, 0x43400343, 0x10181808, 0x121c1e0e, + 0x51501141, 0xf0fc3ccc, 0xc2c80aca, 0x63602343, + 0x20282808, 0x40440444, 0x20202000, 0x919c1d8d, + 0xe0e020c0, 0xe2e022c2, 0xc0c808c8, 0x13141707, + 0xa1a42585, 0x838c0f8f, 0x03000303, 0x73783b4b, + 0xb3b83b8b, 0x13101303, 0xd2d012c2, 0xe2ec2ece, + 0x70703040, 0x808c0c8c, 0x333c3f0f, 0xa0a82888, + 0x32303202, 0xd1dc1dcd, 0xf2f436c6, 0x70743444, + 0xe0ec2ccc, 0x91941585, 0x03080b0b, 0x53541747, + 0x505c1c4c, 0x53581b4b, 0xb1bc3d8d, 0x01000101, + 0x20242404, 0x101c1c0c, 0x73703343, 0x90981888, + 0x10101000, 0xc0cc0ccc, 0xf2f032c2, 0xd1d819c9, + 0x202c2c0c, 0xe3e427c7, 0x72703242, 0x83800383, + 0x93981b8b, 0xd1d011c1, 0x82840686, 0xc1c809c9, + 0x60602040, 0x50501040, 0xa3a02383, 0xe3e82bcb, + 0x010c0d0d, 0xb2b43686, 0x929c1e8e, 0x434c0f4f, + 0xb3b43787, 0x52581a4a, 0xc2c406c6, 0x70783848, + 0xa2a42686, 0x12101202, 0xa3ac2f8f, 0xd1d415c5, + 0x61602141, 0xc3c003c3, 0xb0b43484, 0x41400141, + 0x52501242, 0x717c3d4d, 0x818c0d8d, 0x00080808, + 0x131c1f0f, 0x91981989, 0x00000000, 0x11181909, + 0x00040404, 0x53501343, 0xf3f437c7, 0xe1e021c1, + 0xf1fc3dcd, 0x72743646, 0x232c2f0f, 0x23242707, + 0xb0b03080, 0x83880b8b, 0x020c0e0e, 0xa3a82b8b, + 0xa2a02282, 0x626c2e4e, 0x93901383, 0x414c0d4d, + 0x61682949, 0x707c3c4c, 0x01080909, 0x02080a0a, + 0xb3bc3f8f, 0xe3ec2fcf, 0xf3f033c3, 0xc1c405c5, + 0x83840787, 0x10141404, 0xf2fc3ece, 0x60642444, + 0xd2dc1ece, 0x222c2e0e, 0x43480b4b, 0x12181a0a, + 0x02040606, 0x21202101, 0x63682b4b, 0x62642646, + 0x02000202, 0xf1f435c5, 0x92901282, 0x82880a8a, + 0x000c0c0c, 0xb3b03383, 0x727c3e4e, 0xd0d010c0, + 0x72783a4a, 0x43440747, 0x92941686, 0xe1e425c5, + 0x22242606, 0x80800080, 0xa1ac2d8d, 0xd3dc1fcf, + 0xa1a02181, 0x30303000, 0x33343707, 0xa2ac2e8e, + 0x32343606, 0x11141505, 0x22202202, 0x30383808, + 0xf0f434c4, 0xa3a42787, 0x41440545, 0x404c0c4c, + 0x81800181, 0xe1e829c9, 0x80840484, 0x93941787, + 0x31343505, 0xc3c80bcb, 0xc2cc0ece, 0x303c3c0c, + 0x71703141, 0x11101101, 0xc3c407c7, 0x81880989, + 0x71743545, 0xf3f83bcb, 0xd2d81aca, 0xf0f838c8, + 0x90941484, 0x51581949, 0x82800282, 0xc0c404c4, + 0xf3fc3fcf, 0x41480949, 0x31383909, 0x63642747, + 0xc0c000c0, 0xc3cc0fcf, 0xd3d417c7, 0xb0b83888, + 0x030c0f0f, 0x828c0e8e, 0x42400242, 0x23202303, + 0x91901181, 0x606c2c4c, 0xd3d81bcb, 0xa0a42484, + 0x30343404, 0xf1f031c1, 0x40480848, 0xc2c002c2, + 0x636c2f4f, 0x313c3d0d, 0x212c2d0d, 0x40400040, + 0xb2bc3e8e, 0x323c3e0e, 0xb0bc3c8c, 0xc1c001c1, + 0xa2a82a8a, 0xb2b83a8a, 0x424c0e4e, 0x51541545, + 0x33383b0b, 0xd0dc1ccc, 0x60682848, 0x737c3f4f, + 0x909c1c8c, 0xd0d818c8, 0x42480a4a, 0x52541646, + 0x73743747, 0xa0a02080, 0xe1ec2dcd, 0x42440646, + 0xb1b43585, 0x23282b0b, 0x61642545, 0xf2f83aca, + 0xe3e023c3, 0xb1b83989, 0xb1b03181, 0x939c1f8f, + 0x525c1e4e, 0xf1f839c9, 0xe2e426c6, 0xb2b03282, + 0x31303101, 0xe2e82aca, 0x616c2d4d, 0x535c1f4f, + 0xe0e424c4, 0xf0f030c0, 0xc1cc0dcd, 0x80880888, + 0x12141606, 0x32383a0a, 0x50581848, 0xd0d414c4, + 0x62602242, 0x21282909, 0x03040707, 0x33303303, + 0xe0e828c8, 0x13181b0b, 0x01040505, 0x71783949, + 0x90901080, 0x62682a4a, 0x22282a0a, 0x92981a8a, +}; + +static const u32 SS3[256] = { + 0x08303838, 0xc8e0e828, 0x0d212c2d, 0x86a2a426, + 0xcfc3cc0f, 0xced2dc1e, 0x83b3b033, 0x88b0b838, + 0x8fa3ac2f, 0x40606020, 0x45515415, 0xc7c3c407, + 0x44404404, 0x4f636c2f, 0x4b63682b, 0x4b53581b, + 0xc3c3c003, 0x42626022, 0x03333033, 0x85b1b435, + 0x09212829, 0x80a0a020, 0xc2e2e022, 0x87a3a427, + 0xc3d3d013, 0x81919011, 0x01111011, 0x06020406, + 0x0c101c1c, 0x8cb0bc3c, 0x06323436, 0x4b43480b, + 0xcfe3ec2f, 0x88808808, 0x4c606c2c, 0x88a0a828, + 0x07131417, 0xc4c0c404, 0x06121416, 0xc4f0f434, + 0xc2c2c002, 0x45414405, 0xc1e1e021, 0xc6d2d416, + 0x0f333c3f, 0x0d313c3d, 0x8e828c0e, 0x88909818, + 0x08202828, 0x4e424c0e, 0xc6f2f436, 0x0e323c3e, + 0x85a1a425, 0xc9f1f839, 0x0d010c0d, 0xcfd3dc1f, + 0xc8d0d818, 0x0b23282b, 0x46626426, 0x4a72783a, + 0x07232427, 0x0f232c2f, 0xc1f1f031, 0x42727032, + 0x42424002, 0xc4d0d414, 0x41414001, 0xc0c0c000, + 0x43737033, 0x47636427, 0x8ca0ac2c, 0x8b83880b, + 0xc7f3f437, 0x8da1ac2d, 0x80808000, 0x0f131c1f, + 0xcac2c80a, 0x0c202c2c, 0x8aa2a82a, 0x04303434, + 0xc2d2d012, 0x0b03080b, 0xcee2ec2e, 0xc9e1e829, + 0x4d515c1d, 0x84909414, 0x08101818, 0xc8f0f838, + 0x47535417, 0x8ea2ac2e, 0x08000808, 0xc5c1c405, + 0x03131013, 0xcdc1cc0d, 0x86828406, 0x89b1b839, + 0xcff3fc3f, 0x4d717c3d, 0xc1c1c001, 0x01313031, + 0xc5f1f435, 0x8a82880a, 0x4a62682a, 0x81b1b031, + 0xc1d1d011, 0x00202020, 0xc7d3d417, 0x02020002, + 0x02222022, 0x04000404, 0x48606828, 0x41717031, + 0x07030407, 0xcbd3d81b, 0x8d919c1d, 0x89919819, + 0x41616021, 0x8eb2bc3e, 0xc6e2e426, 0x49515819, + 0xcdd1dc1d, 0x41515011, 0x80909010, 0xccd0dc1c, + 0x8a92981a, 0x83a3a023, 0x8ba3a82b, 0xc0d0d010, + 0x81818001, 0x0f030c0f, 0x47434407, 0x0a12181a, + 0xc3e3e023, 0xcce0ec2c, 0x8d818c0d, 0x8fb3bc3f, + 0x86929416, 0x4b73783b, 0x4c505c1c, 0x82a2a022, + 0x81a1a021, 0x43636023, 0x03232023, 0x4d414c0d, + 0xc8c0c808, 0x8e929c1e, 0x8c909c1c, 0x0a32383a, + 0x0c000c0c, 0x0e222c2e, 0x8ab2b83a, 0x4e626c2e, + 0x8f939c1f, 0x4a52581a, 0xc2f2f032, 0x82929012, + 0xc3f3f033, 0x49414809, 0x48707838, 0xccc0cc0c, + 0x05111415, 0xcbf3f83b, 0x40707030, 0x45717435, + 0x4f737c3f, 0x05313435, 0x00101010, 0x03030003, + 0x44606424, 0x4d616c2d, 0xc6c2c406, 0x44707434, + 0xc5d1d415, 0x84b0b434, 0xcae2e82a, 0x09010809, + 0x46727436, 0x09111819, 0xcef2fc3e, 0x40404000, + 0x02121012, 0xc0e0e020, 0x8db1bc3d, 0x05010405, + 0xcaf2f83a, 0x01010001, 0xc0f0f030, 0x0a22282a, + 0x4e525c1e, 0x89a1a829, 0x46525416, 0x43434003, + 0x85818405, 0x04101414, 0x89818809, 0x8b93981b, + 0x80b0b030, 0xc5e1e425, 0x48404808, 0x49717839, + 0x87939417, 0xccf0fc3c, 0x0e121c1e, 0x82828002, + 0x01212021, 0x8c808c0c, 0x0b13181b, 0x4f535c1f, + 0x47737437, 0x44505414, 0x82b2b032, 0x0d111c1d, + 0x05212425, 0x4f434c0f, 0x00000000, 0x46424406, + 0xcde1ec2d, 0x48505818, 0x42525012, 0xcbe3e82b, + 0x4e727c3e, 0xcad2d81a, 0xc9c1c809, 0xcdf1fc3d, + 0x00303030, 0x85919415, 0x45616425, 0x0c303c3c, + 0x86b2b436, 0xc4e0e424, 0x8bb3b83b, 0x4c707c3c, + 0x0e020c0e, 0x40505010, 0x09313839, 0x06222426, + 0x02323032, 0x84808404, 0x49616829, 0x83939013, + 0x07333437, 0xc7e3e427, 0x04202424, 0x84a0a424, + 0xcbc3c80b, 0x43535013, 0x0a02080a, 0x87838407, + 0xc9d1d819, 0x4c404c0c, 0x83838003, 0x8f838c0f, + 0xcec2cc0e, 0x0b33383b, 0x4a42480a, 0x87b3b437, +}; + +static const u32 KC[SEED_NUM_KCONSTANTS] = { + 0x9e3779b9, 0x3c6ef373, 0x78dde6e6, 0xf1bbcdcc, + 0xe3779b99, 0xc6ef3733, 0x8dde6e67, 0x1bbcdccf, + 0x3779b99e, 0x6ef3733c, 0xdde6e678, 0xbbcdccf1, + 0x779b99e3, 0xef3733c6, 0xde6e678d, 0xbcdccf1b, +}; + +#define OP(X1, X2, X3, X4, rbase) \ + t0 = X3 ^ ks[rbase]; \ + t1 = X4 ^ ks[rbase+1]; \ + t1 ^= t0; \ + t1 = SS0[byte(t1, 0)] ^ SS1[byte(t1, 1)] ^ \ + SS2[byte(t1, 2)] ^ SS3[byte(t1, 3)]; \ + t0 += t1; \ + t0 = SS0[byte(t0, 0)] ^ SS1[byte(t0, 1)] ^ \ + SS2[byte(t0, 2)] ^ SS3[byte(t0, 3)]; \ + t1 += t0; \ + t1 = SS0[byte(t1, 0)] ^ SS1[byte(t1, 1)] ^ \ + SS2[byte(t1, 2)] ^ SS3[byte(t1, 3)]; \ + t0 += t1; \ + X1 ^= t0; \ + X2 ^= t1; + +static int seed_set_key(struct crypto_tfm *tfm, const u8 *in_key, + unsigned int key_len) +{ + struct seed_ctx *ctx = crypto_tfm_ctx(tfm); + u32 *keyout = ctx->keysched; + const __be32 *key = (const __be32 *)in_key; + u32 i, t0, t1, x1, x2, x3, x4; + + x1 = be32_to_cpu(key[0]); + x2 = be32_to_cpu(key[1]); + x3 = be32_to_cpu(key[2]); + x4 = be32_to_cpu(key[3]); + + for (i = 0; i < SEED_NUM_KCONSTANTS; i++) { + t0 = x1 + x3 - KC[i]; + t1 = x2 + KC[i] - x4; + *(keyout++) = SS0[byte(t0, 0)] ^ SS1[byte(t0, 1)] ^ + SS2[byte(t0, 2)] ^ SS3[byte(t0, 3)]; + *(keyout++) = SS0[byte(t1, 0)] ^ SS1[byte(t1, 1)] ^ + SS2[byte(t1, 2)] ^ SS3[byte(t1, 3)]; + + if (i % 2 == 0) { + t0 = x1; + x1 = (x1 >> 8) ^ (x2 << 24); + x2 = (x2 >> 8) ^ (t0 << 24); + } else { + t0 = x3; + x3 = (x3 << 8) ^ (x4 >> 24); + x4 = (x4 << 8) ^ (t0 >> 24); + } + } + + return 0; +} + +/* encrypt a block of text */ + +static void seed_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +{ + const struct seed_ctx *ctx = crypto_tfm_ctx(tfm); + const __be32 *src = (const __be32 *)in; + __be32 *dst = (__be32 *)out; + u32 x1, x2, x3, x4, t0, t1; + const u32 *ks = ctx->keysched; + + x1 = be32_to_cpu(src[0]); + x2 = be32_to_cpu(src[1]); + x3 = be32_to_cpu(src[2]); + x4 = be32_to_cpu(src[3]); + + OP(x1, x2, x3, x4, 0); + OP(x3, x4, x1, x2, 2); + OP(x1, x2, x3, x4, 4); + OP(x3, x4, x1, x2, 6); + OP(x1, x2, x3, x4, 8); + OP(x3, x4, x1, x2, 10); + OP(x1, x2, x3, x4, 12); + OP(x3, x4, x1, x2, 14); + OP(x1, x2, x3, x4, 16); + OP(x3, x4, x1, x2, 18); + OP(x1, x2, x3, x4, 20); + OP(x3, x4, x1, x2, 22); + OP(x1, x2, x3, x4, 24); + OP(x3, x4, x1, x2, 26); + OP(x1, x2, x3, x4, 28); + OP(x3, x4, x1, x2, 30); + + dst[0] = cpu_to_be32(x3); + dst[1] = cpu_to_be32(x4); + dst[2] = cpu_to_be32(x1); + dst[3] = cpu_to_be32(x2); +} + +/* decrypt a block of text */ + +static void seed_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +{ + const struct seed_ctx *ctx = crypto_tfm_ctx(tfm); + const __be32 *src = (const __be32 *)in; + __be32 *dst = (__be32 *)out; + u32 x1, x2, x3, x4, t0, t1; + const u32 *ks = ctx->keysched; + + x1 = be32_to_cpu(src[0]); + x2 = be32_to_cpu(src[1]); + x3 = be32_to_cpu(src[2]); + x4 = be32_to_cpu(src[3]); + + OP(x1, x2, x3, x4, 30); + OP(x3, x4, x1, x2, 28); + OP(x1, x2, x3, x4, 26); + OP(x3, x4, x1, x2, 24); + OP(x1, x2, x3, x4, 22); + OP(x3, x4, x1, x2, 20); + OP(x1, x2, x3, x4, 18); + OP(x3, x4, x1, x2, 16); + OP(x1, x2, x3, x4, 14); + OP(x3, x4, x1, x2, 12); + OP(x1, x2, x3, x4, 10); + OP(x3, x4, x1, x2, 8); + OP(x1, x2, x3, x4, 6); + OP(x3, x4, x1, x2, 4); + OP(x1, x2, x3, x4, 2); + OP(x3, x4, x1, x2, 0); + + dst[0] = cpu_to_be32(x3); + dst[1] = cpu_to_be32(x4); + dst[2] = cpu_to_be32(x1); + dst[3] = cpu_to_be32(x2); +} + + +static struct crypto_alg seed_alg = { + .cra_name = "seed", + .cra_driver_name = "seed-generic", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = SEED_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct seed_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(seed_alg.cra_list), + .cra_u = { + .cipher = { + .cia_min_keysize = SEED_KEY_SIZE, + .cia_max_keysize = SEED_KEY_SIZE, + .cia_setkey = seed_set_key, + .cia_encrypt = seed_encrypt, + .cia_decrypt = seed_decrypt + } + } +}; + +static int __init seed_init(void) +{ + return crypto_register_alg(&seed_alg); +} + +static void __exit seed_fini(void) +{ + crypto_unregister_alg(&seed_alg); +} + +module_init(seed_init); +module_exit(seed_fini); + +MODULE_DESCRIPTION("SEED Cipher Algorithm"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Hye-Shik Chang <perky@FreeBSD.org>, Kim Hyun <hkim@kisa.or.kr>"); diff --git a/crypto/sha1.c b/crypto/sha1_generic.c index 1bba551e5b45..48a3c3e0bf5f 100644 --- a/crypto/sha1.c +++ b/crypto/sha1_generic.c @@ -22,12 +22,10 @@ #include <linux/crypto.h> #include <linux/cryptohash.h> #include <linux/types.h> +#include <crypto/sha.h> #include <asm/scatterlist.h> #include <asm/byteorder.h> -#define SHA1_DIGEST_SIZE 20 -#define SHA1_HMAC_BLOCK_SIZE 64 - struct sha1_ctx { u64 count; u32 state[5]; @@ -39,7 +37,7 @@ static void sha1_init(struct crypto_tfm *tfm) struct sha1_ctx *sctx = crypto_tfm_ctx(tfm); static const struct sha1_ctx initstate = { 0, - { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }, + { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 }, { 0, } }; @@ -111,7 +109,7 @@ static struct crypto_alg alg = { .cra_name = "sha1", .cra_driver_name= "sha1-generic", .cra_flags = CRYPTO_ALG_TYPE_DIGEST, - .cra_blocksize = SHA1_HMAC_BLOCK_SIZE, + .cra_blocksize = SHA1_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sha1_ctx), .cra_module = THIS_MODULE, .cra_alignmask = 3, @@ -139,4 +137,4 @@ module_exit(fini); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm"); -MODULE_ALIAS("sha1-generic"); +MODULE_ALIAS("sha1"); diff --git a/crypto/sha256.c b/crypto/sha256_generic.c index 716195bb54f2..5f4332edcf6b 100644 --- a/crypto/sha256.c +++ b/crypto/sha256_generic.c @@ -21,12 +21,10 @@ #include <linux/mm.h> #include <linux/crypto.h> #include <linux/types.h> +#include <crypto/sha.h> #include <asm/scatterlist.h> #include <asm/byteorder.h> -#define SHA256_DIGEST_SIZE 32 -#define SHA256_HMAC_BLOCK_SIZE 64 - struct sha256_ctx { u32 count[2]; u32 state[8]; @@ -48,15 +46,6 @@ static inline u32 Maj(u32 x, u32 y, u32 z) #define s0(x) (ror32(x, 7) ^ ror32(x,18) ^ (x >> 3)) #define s1(x) (ror32(x,17) ^ ror32(x,19) ^ (x >> 10)) -#define H0 0x6a09e667 -#define H1 0xbb67ae85 -#define H2 0x3c6ef372 -#define H3 0xa54ff53a -#define H4 0x510e527f -#define H5 0x9b05688c -#define H6 0x1f83d9ab -#define H7 0x5be0cd19 - static inline void LOAD_OP(int I, u32 *W, const u8 *input) { W[I] = __be32_to_cpu( ((__be32*)(input))[I] ); @@ -233,14 +222,14 @@ static void sha256_transform(u32 *state, const u8 *input) static void sha256_init(struct crypto_tfm *tfm) { struct sha256_ctx *sctx = crypto_tfm_ctx(tfm); - sctx->state[0] = H0; - sctx->state[1] = H1; - sctx->state[2] = H2; - sctx->state[3] = H3; - sctx->state[4] = H4; - sctx->state[5] = H5; - sctx->state[6] = H6; - sctx->state[7] = H7; + sctx->state[0] = SHA256_H0; + sctx->state[1] = SHA256_H1; + sctx->state[2] = SHA256_H2; + sctx->state[3] = SHA256_H3; + sctx->state[4] = SHA256_H4; + sctx->state[5] = SHA256_H5; + sctx->state[6] = SHA256_H6; + sctx->state[7] = SHA256_H7; sctx->count[0] = sctx->count[1] = 0; } @@ -311,7 +300,7 @@ static struct crypto_alg alg = { .cra_name = "sha256", .cra_driver_name= "sha256-generic", .cra_flags = CRYPTO_ALG_TYPE_DIGEST, - .cra_blocksize = SHA256_HMAC_BLOCK_SIZE, + .cra_blocksize = SHA256_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sha256_ctx), .cra_module = THIS_MODULE, .cra_alignmask = 3, @@ -339,4 +328,4 @@ module_exit(fini); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm"); -MODULE_ALIAS("sha256-generic"); +MODULE_ALIAS("sha256"); diff --git a/crypto/sha512.c b/crypto/sha512.c index 15eab9db9be4..e736596ca574 100644 --- a/crypto/sha512.c +++ b/crypto/sha512.c @@ -13,20 +13,15 @@ #include <linux/kernel.h> #include <linux/module.h> - #include <linux/mm.h> #include <linux/init.h> #include <linux/crypto.h> #include <linux/types.h> +#include <crypto/sha.h> #include <asm/scatterlist.h> #include <asm/byteorder.h> -#define SHA384_DIGEST_SIZE 48 -#define SHA512_DIGEST_SIZE 64 -#define SHA384_HMAC_BLOCK_SIZE 128 -#define SHA512_HMAC_BLOCK_SIZE 128 - struct sha512_ctx { u64 state[8]; u32 count[4]; @@ -84,26 +79,6 @@ static const u64 sha512_K[80] = { #define s0(x) (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7)) #define s1(x) (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6)) -/* H* initial state for SHA-512 */ -#define H0 0x6a09e667f3bcc908ULL -#define H1 0xbb67ae8584caa73bULL -#define H2 0x3c6ef372fe94f82bULL -#define H3 0xa54ff53a5f1d36f1ULL -#define H4 0x510e527fade682d1ULL -#define H5 0x9b05688c2b3e6c1fULL -#define H6 0x1f83d9abfb41bd6bULL -#define H7 0x5be0cd19137e2179ULL - -/* H'* initial state for SHA-384 */ -#define HP0 0xcbbb9d5dc1059ed8ULL -#define HP1 0x629a292a367cd507ULL -#define HP2 0x9159015a3070dd17ULL -#define HP3 0x152fecd8f70e5939ULL -#define HP4 0x67332667ffc00b31ULL -#define HP5 0x8eb44a8768581511ULL -#define HP6 0xdb0c2e0d64f98fa7ULL -#define HP7 0x47b5481dbefa4fa4ULL - static inline void LOAD_OP(int I, u64 *W, const u8 *input) { W[I] = __be64_to_cpu( ((__be64*)(input))[I] ); @@ -164,14 +139,14 @@ static void sha512_init(struct crypto_tfm *tfm) { struct sha512_ctx *sctx = crypto_tfm_ctx(tfm); - sctx->state[0] = H0; - sctx->state[1] = H1; - sctx->state[2] = H2; - sctx->state[3] = H3; - sctx->state[4] = H4; - sctx->state[5] = H5; - sctx->state[6] = H6; - sctx->state[7] = H7; + sctx->state[0] = SHA512_H0; + sctx->state[1] = SHA512_H1; + sctx->state[2] = SHA512_H2; + sctx->state[3] = SHA512_H3; + sctx->state[4] = SHA512_H4; + sctx->state[5] = SHA512_H5; + sctx->state[6] = SHA512_H6; + sctx->state[7] = SHA512_H7; sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0; } @@ -179,14 +154,14 @@ static void sha384_init(struct crypto_tfm *tfm) { struct sha512_ctx *sctx = crypto_tfm_ctx(tfm); - sctx->state[0] = HP0; - sctx->state[1] = HP1; - sctx->state[2] = HP2; - sctx->state[3] = HP3; - sctx->state[4] = HP4; - sctx->state[5] = HP5; - sctx->state[6] = HP6; - sctx->state[7] = HP7; + sctx->state[0] = SHA384_H0; + sctx->state[1] = SHA384_H1; + sctx->state[2] = SHA384_H2; + sctx->state[3] = SHA384_H3; + sctx->state[4] = SHA384_H4; + sctx->state[5] = SHA384_H5; + sctx->state[6] = SHA384_H6; + sctx->state[7] = SHA384_H7; sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0; } @@ -275,7 +250,7 @@ static void sha384_final(struct crypto_tfm *tfm, u8 *hash) static struct crypto_alg sha512 = { .cra_name = "sha512", .cra_flags = CRYPTO_ALG_TYPE_DIGEST, - .cra_blocksize = SHA512_HMAC_BLOCK_SIZE, + .cra_blocksize = SHA512_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sha512_ctx), .cra_module = THIS_MODULE, .cra_alignmask = 3, @@ -291,7 +266,7 @@ static struct crypto_alg sha512 = { static struct crypto_alg sha384 = { .cra_name = "sha384", .cra_flags = CRYPTO_ALG_TYPE_DIGEST, - .cra_blocksize = SHA384_HMAC_BLOCK_SIZE, + .cra_blocksize = SHA384_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sha512_ctx), .cra_alignmask = 3, .cra_module = THIS_MODULE, diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 11f935953816..18d489c8b935 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -78,7 +78,7 @@ static char *check[] = { "twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", "khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", "fcrypt", - "camellia", NULL + "camellia", "seed", NULL }; static void hexdump(unsigned char *buf, unsigned int len) @@ -955,6 +955,10 @@ static void do_test(void) AES_LRW_ENC_TEST_VECTORS); test_cipher("lrw(aes)", DECRYPT, aes_lrw_dec_tv_template, AES_LRW_DEC_TEST_VECTORS); + test_cipher("xts(aes)", ENCRYPT, aes_xts_enc_tv_template, + AES_XTS_ENC_TEST_VECTORS); + test_cipher("xts(aes)", DECRYPT, aes_xts_dec_tv_template, + AES_XTS_DEC_TEST_VECTORS); //CAST5 test_cipher("ecb(cast5)", ENCRYPT, cast5_enc_tv_template, @@ -1029,6 +1033,12 @@ static void do_test(void) camellia_cbc_dec_tv_template, CAMELLIA_CBC_DEC_TEST_VECTORS); + //SEED + test_cipher("ecb(seed)", ENCRYPT, seed_enc_tv_template, + SEED_ENC_TEST_VECTORS); + test_cipher("ecb(seed)", DECRYPT, seed_dec_tv_template, + SEED_DEC_TEST_VECTORS); + test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS); test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS); test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS); @@ -1132,6 +1142,10 @@ static void do_test(void) AES_LRW_ENC_TEST_VECTORS); test_cipher("lrw(aes)", DECRYPT, aes_lrw_dec_tv_template, AES_LRW_DEC_TEST_VECTORS); + test_cipher("xts(aes)", ENCRYPT, aes_xts_enc_tv_template, + AES_XTS_ENC_TEST_VECTORS); + test_cipher("xts(aes)", DECRYPT, aes_xts_dec_tv_template, + AES_XTS_DEC_TEST_VECTORS); break; case 11: @@ -1307,6 +1321,10 @@ static void do_test(void) aes_lrw_speed_template); test_cipher_speed("lrw(aes)", DECRYPT, sec, NULL, 0, aes_lrw_speed_template); + test_cipher_speed("xts(aes)", ENCRYPT, sec, NULL, 0, + aes_xts_speed_template); + test_cipher_speed("xts(aes)", DECRYPT, sec, NULL, 0, + aes_xts_speed_template); break; case 201: diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h index 887527bd5bc6..ec861388d9a0 100644 --- a/crypto/tcrypt.h +++ b/crypto/tcrypt.h @@ -2144,6 +2144,8 @@ static struct cipher_testvec cast6_dec_tv_template[] = { #define AES_CBC_DEC_TEST_VECTORS 2 #define AES_LRW_ENC_TEST_VECTORS 8 #define AES_LRW_DEC_TEST_VECTORS 8 +#define AES_XTS_ENC_TEST_VECTORS 4 +#define AES_XTS_DEC_TEST_VECTORS 4 static struct cipher_testvec aes_enc_tv_template[] = { { /* From FIPS-197 */ @@ -2784,6 +2786,400 @@ static struct cipher_testvec aes_lrw_dec_tv_template[] = { } }; +static struct cipher_testvec aes_xts_enc_tv_template[] = { + /* http://grouper.ieee.org/groups/1619/email/pdf00086.pdf */ + { /* XTS-AES 1 */ + .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .klen = 32, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .ilen = 32, + .result = { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec, + 0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92, + 0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85, + 0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e }, + .rlen = 32, + }, { /* XTS-AES 2 */ + .key = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, + .klen = 32, + .iv = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .input = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, + .ilen = 32, + .result = { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e, + 0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b, + 0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4, + 0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 }, + .rlen = 32, + }, { /* XTS-AES 3 */ + .key = { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, + .klen = 32, + .iv = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .input = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, + .ilen = 32, + .result = { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a, + 0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2, + 0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53, + 0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 }, + .rlen = 32, + }, { /* XTS-AES 4 */ + .key = { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95 }, + .klen = 32, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }, + .ilen = 512, + .result = { 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76, + 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2, + 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25, + 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c, + 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f, + 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00, + 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad, + 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12, + 0x32, 0x80, 0x63, 0xfd, 0x2a, 0xab, 0x53, 0xe5, + 0xea, 0x1e, 0x0a, 0x9f, 0x33, 0x25, 0x00, 0xa5, + 0xdf, 0x94, 0x87, 0xd0, 0x7a, 0x5c, 0x92, 0xcc, + 0x51, 0x2c, 0x88, 0x66, 0xc7, 0xe8, 0x60, 0xce, + 0x93, 0xfd, 0xf1, 0x66, 0xa2, 0x49, 0x12, 0xb4, + 0x22, 0x97, 0x61, 0x46, 0xae, 0x20, 0xce, 0x84, + 0x6b, 0xb7, 0xdc, 0x9b, 0xa9, 0x4a, 0x76, 0x7a, + 0xae, 0xf2, 0x0c, 0x0d, 0x61, 0xad, 0x02, 0x65, + 0x5e, 0xa9, 0x2d, 0xc4, 0xc4, 0xe4, 0x1a, 0x89, + 0x52, 0xc6, 0x51, 0xd3, 0x31, 0x74, 0xbe, 0x51, + 0xa1, 0x0c, 0x42, 0x11, 0x10, 0xe6, 0xd8, 0x15, + 0x88, 0xed, 0xe8, 0x21, 0x03, 0xa2, 0x52, 0xd8, + 0xa7, 0x50, 0xe8, 0x76, 0x8d, 0xef, 0xff, 0xed, + 0x91, 0x22, 0x81, 0x0a, 0xae, 0xb9, 0x9f, 0x91, + 0x72, 0xaf, 0x82, 0xb6, 0x04, 0xdc, 0x4b, 0x8e, + 0x51, 0xbc, 0xb0, 0x82, 0x35, 0xa6, 0xf4, 0x34, + 0x13, 0x32, 0xe4, 0xca, 0x60, 0x48, 0x2a, 0x4b, + 0xa1, 0xa0, 0x3b, 0x3e, 0x65, 0x00, 0x8f, 0xc5, + 0xda, 0x76, 0xb7, 0x0b, 0xf1, 0x69, 0x0d, 0xb4, + 0xea, 0xe2, 0x9c, 0x5f, 0x1b, 0xad, 0xd0, 0x3c, + 0x5c, 0xcf, 0x2a, 0x55, 0xd7, 0x05, 0xdd, 0xcd, + 0x86, 0xd4, 0x49, 0x51, 0x1c, 0xeb, 0x7e, 0xc3, + 0x0b, 0xf1, 0x2b, 0x1f, 0xa3, 0x5b, 0x91, 0x3f, + 0x9f, 0x74, 0x7a, 0x8a, 0xfd, 0x1b, 0x13, 0x0e, + 0x94, 0xbf, 0xf9, 0x4e, 0xff, 0xd0, 0x1a, 0x91, + 0x73, 0x5c, 0xa1, 0x72, 0x6a, 0xcd, 0x0b, 0x19, + 0x7c, 0x4e, 0x5b, 0x03, 0x39, 0x36, 0x97, 0xe1, + 0x26, 0x82, 0x6f, 0xb6, 0xbb, 0xde, 0x8e, 0xcc, + 0x1e, 0x08, 0x29, 0x85, 0x16, 0xe2, 0xc9, 0xed, + 0x03, 0xff, 0x3c, 0x1b, 0x78, 0x60, 0xf6, 0xde, + 0x76, 0xd4, 0xce, 0xcd, 0x94, 0xc8, 0x11, 0x98, + 0x55, 0xef, 0x52, 0x97, 0xca, 0x67, 0xe9, 0xf3, + 0xe7, 0xff, 0x72, 0xb1, 0xe9, 0x97, 0x85, 0xca, + 0x0a, 0x7e, 0x77, 0x20, 0xc5, 0xb3, 0x6d, 0xc6, + 0xd7, 0x2c, 0xac, 0x95, 0x74, 0xc8, 0xcb, 0xbc, + 0x2f, 0x80, 0x1e, 0x23, 0xe5, 0x6f, 0xd3, 0x44, + 0xb0, 0x7f, 0x22, 0x15, 0x4b, 0xeb, 0xa0, 0xf0, + 0x8c, 0xe8, 0x89, 0x1e, 0x64, 0x3e, 0xd9, 0x95, + 0xc9, 0x4d, 0x9a, 0x69, 0xc9, 0xf1, 0xb5, 0xf4, + 0x99, 0x02, 0x7a, 0x78, 0x57, 0x2a, 0xee, 0xbd, + 0x74, 0xd2, 0x0c, 0xc3, 0x98, 0x81, 0xc2, 0x13, + 0xee, 0x77, 0x0b, 0x10, 0x10, 0xe4, 0xbe, 0xa7, + 0x18, 0x84, 0x69, 0x77, 0xae, 0x11, 0x9f, 0x7a, + 0x02, 0x3a, 0xb5, 0x8c, 0xca, 0x0a, 0xd7, 0x52, + 0xaf, 0xe6, 0x56, 0xbb, 0x3c, 0x17, 0x25, 0x6a, + 0x9f, 0x6e, 0x9b, 0xf1, 0x9f, 0xdd, 0x5a, 0x38, + 0xfc, 0x82, 0xbb, 0xe8, 0x72, 0xc5, 0x53, 0x9e, + 0xdb, 0x60, 0x9e, 0xf4, 0xf7, 0x9c, 0x20, 0x3e, + 0xbb, 0x14, 0x0f, 0x2e, 0x58, 0x3c, 0xb2, 0xad, + 0x15, 0xb4, 0xaa, 0x5b, 0x65, 0x50, 0x16, 0xa8, + 0x44, 0x92, 0x77, 0xdb, 0xd4, 0x77, 0xef, 0x2c, + 0x8d, 0x6c, 0x01, 0x7d, 0xb7, 0x38, 0xb1, 0x8d, + 0xeb, 0x4a, 0x42, 0x7d, 0x19, 0x23, 0xce, 0x3f, + 0xf2, 0x62, 0x73, 0x57, 0x79, 0xa4, 0x18, 0xf2, + 0x0a, 0x28, 0x2d, 0xf9, 0x20, 0x14, 0x7b, 0xea, + 0xbe, 0x42, 0x1e, 0xe5, 0x31, 0x9d, 0x05, 0x68 }, + .rlen = 512, + } +}; + +static struct cipher_testvec aes_xts_dec_tv_template[] = { + /* http://grouper.ieee.org/groups/1619/email/pdf00086.pdf */ + { /* XTS-AES 1 */ + .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .klen = 32, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .input = { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec, + 0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92, + 0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85, + 0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e }, + .ilen = 32, + .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .rlen = 32, + }, { /* XTS-AES 2 */ + .key = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, + .klen = 32, + .iv = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .input = { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e, + 0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b, + 0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4, + 0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 }, + .ilen = 32, + .result = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, + .rlen = 32, + }, { /* XTS-AES 3 */ + .key = { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, + .klen = 32, + .iv = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .input = { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a, + 0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2, + 0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53, + 0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 }, + .ilen = 32, + .result = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, + .rlen = 32, + }, { /* XTS-AES 4 */ + .key = { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95 }, + .klen = 32, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .input = { 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76, + 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2, + 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25, + 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c, + 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f, + 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00, + 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad, + 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12, + 0x32, 0x80, 0x63, 0xfd, 0x2a, 0xab, 0x53, 0xe5, + 0xea, 0x1e, 0x0a, 0x9f, 0x33, 0x25, 0x00, 0xa5, + 0xdf, 0x94, 0x87, 0xd0, 0x7a, 0x5c, 0x92, 0xcc, + 0x51, 0x2c, 0x88, 0x66, 0xc7, 0xe8, 0x60, 0xce, + 0x93, 0xfd, 0xf1, 0x66, 0xa2, 0x49, 0x12, 0xb4, + 0x22, 0x97, 0x61, 0x46, 0xae, 0x20, 0xce, 0x84, + 0x6b, 0xb7, 0xdc, 0x9b, 0xa9, 0x4a, 0x76, 0x7a, + 0xae, 0xf2, 0x0c, 0x0d, 0x61, 0xad, 0x02, 0x65, + 0x5e, 0xa9, 0x2d, 0xc4, 0xc4, 0xe4, 0x1a, 0x89, + 0x52, 0xc6, 0x51, 0xd3, 0x31, 0x74, 0xbe, 0x51, + 0xa1, 0x0c, 0x42, 0x11, 0x10, 0xe6, 0xd8, 0x15, + 0x88, 0xed, 0xe8, 0x21, 0x03, 0xa2, 0x52, 0xd8, + 0xa7, 0x50, 0xe8, 0x76, 0x8d, 0xef, 0xff, 0xed, + 0x91, 0x22, 0x81, 0x0a, 0xae, 0xb9, 0x9f, 0x91, + 0x72, 0xaf, 0x82, 0xb6, 0x04, 0xdc, 0x4b, 0x8e, + 0x51, 0xbc, 0xb0, 0x82, 0x35, 0xa6, 0xf4, 0x34, + 0x13, 0x32, 0xe4, 0xca, 0x60, 0x48, 0x2a, 0x4b, + 0xa1, 0xa0, 0x3b, 0x3e, 0x65, 0x00, 0x8f, 0xc5, + 0xda, 0x76, 0xb7, 0x0b, 0xf1, 0x69, 0x0d, 0xb4, + 0xea, 0xe2, 0x9c, 0x5f, 0x1b, 0xad, 0xd0, 0x3c, + 0x5c, 0xcf, 0x2a, 0x55, 0xd7, 0x05, 0xdd, 0xcd, + 0x86, 0xd4, 0x49, 0x51, 0x1c, 0xeb, 0x7e, 0xc3, + 0x0b, 0xf1, 0x2b, 0x1f, 0xa3, 0x5b, 0x91, 0x3f, + 0x9f, 0x74, 0x7a, 0x8a, 0xfd, 0x1b, 0x13, 0x0e, + 0x94, 0xbf, 0xf9, 0x4e, 0xff, 0xd0, 0x1a, 0x91, + 0x73, 0x5c, 0xa1, 0x72, 0x6a, 0xcd, 0x0b, 0x19, + 0x7c, 0x4e, 0x5b, 0x03, 0x39, 0x36, 0x97, 0xe1, + 0x26, 0x82, 0x6f, 0xb6, 0xbb, 0xde, 0x8e, 0xcc, + 0x1e, 0x08, 0x29, 0x85, 0x16, 0xe2, 0xc9, 0xed, + 0x03, 0xff, 0x3c, 0x1b, 0x78, 0x60, 0xf6, 0xde, + 0x76, 0xd4, 0xce, 0xcd, 0x94, 0xc8, 0x11, 0x98, + 0x55, 0xef, 0x52, 0x97, 0xca, 0x67, 0xe9, 0xf3, + 0xe7, 0xff, 0x72, 0xb1, 0xe9, 0x97, 0x85, 0xca, + 0x0a, 0x7e, 0x77, 0x20, 0xc5, 0xb3, 0x6d, 0xc6, + 0xd7, 0x2c, 0xac, 0x95, 0x74, 0xc8, 0xcb, 0xbc, + 0x2f, 0x80, 0x1e, 0x23, 0xe5, 0x6f, 0xd3, 0x44, + 0xb0, 0x7f, 0x22, 0x15, 0x4b, 0xeb, 0xa0, 0xf0, + 0x8c, 0xe8, 0x89, 0x1e, 0x64, 0x3e, 0xd9, 0x95, + 0xc9, 0x4d, 0x9a, 0x69, 0xc9, 0xf1, 0xb5, 0xf4, + 0x99, 0x02, 0x7a, 0x78, 0x57, 0x2a, 0xee, 0xbd, + 0x74, 0xd2, 0x0c, 0xc3, 0x98, 0x81, 0xc2, 0x13, + 0xee, 0x77, 0x0b, 0x10, 0x10, 0xe4, 0xbe, 0xa7, + 0x18, 0x84, 0x69, 0x77, 0xae, 0x11, 0x9f, 0x7a, + 0x02, 0x3a, 0xb5, 0x8c, 0xca, 0x0a, 0xd7, 0x52, + 0xaf, 0xe6, 0x56, 0xbb, 0x3c, 0x17, 0x25, 0x6a, + 0x9f, 0x6e, 0x9b, 0xf1, 0x9f, 0xdd, 0x5a, 0x38, + 0xfc, 0x82, 0xbb, 0xe8, 0x72, 0xc5, 0x53, 0x9e, + 0xdb, 0x60, 0x9e, 0xf4, 0xf7, 0x9c, 0x20, 0x3e, + 0xbb, 0x14, 0x0f, 0x2e, 0x58, 0x3c, 0xb2, 0xad, + 0x15, 0xb4, 0xaa, 0x5b, 0x65, 0x50, 0x16, 0xa8, + 0x44, 0x92, 0x77, 0xdb, 0xd4, 0x77, 0xef, 0x2c, + 0x8d, 0x6c, 0x01, 0x7d, 0xb7, 0x38, 0xb1, 0x8d, + 0xeb, 0x4a, 0x42, 0x7d, 0x19, 0x23, 0xce, 0x3f, + 0xf2, 0x62, 0x73, 0x57, 0x79, 0xa4, 0x18, 0xf2, + 0x0a, 0x28, 0x2d, 0xf9, 0x20, 0x14, 0x7b, 0xea, + 0xbe, 0x42, 0x1e, 0xe5, 0x31, 0x9d, 0x05, 0x68 }, + .ilen = 512, + .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }, + .rlen = 512, + } +}; + /* Cast5 test vectors from RFC 2144 */ #define CAST5_ENC_TEST_VECTORS 3 #define CAST5_DEC_TEST_VECTORS 3 @@ -3832,6 +4228,96 @@ static struct cipher_testvec camellia_cbc_dec_tv_template[] = { }; /* + * SEED test vectors + */ +#define SEED_ENC_TEST_VECTORS 4 +#define SEED_DEC_TEST_VECTORS 4 + +static struct cipher_testvec seed_enc_tv_template[] = { + { + .key = { [0 ... 15] = 0x00 }, + .klen = 16, + .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .ilen = 16, + .result = { 0x5e, 0xba, 0xc6, 0xe0, 0x05, 0x4e, 0x16, 0x68, + 0x19, 0xaf, 0xf1, 0xcc, 0x6d, 0x34, 0x6c, 0xdb }, + .rlen = 16, + }, { + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .klen = 16, + .input = { [0 ... 15] = 0x00 }, + .ilen = 16, + .result = { 0xc1, 0x1f, 0x22, 0xf2, 0x01, 0x40, 0x50, 0x50, + 0x84, 0x48, 0x35, 0x97, 0xe4, 0x37, 0x0f, 0x43 }, + .rlen = 16, + }, { + .key = { 0x47, 0x06, 0x48, 0x08, 0x51, 0xe6, 0x1b, 0xe8, + 0x5d, 0x74, 0xbf, 0xb3, 0xfd, 0x95, 0x61, 0x85 }, + .klen = 16, + .input = { 0x83, 0xa2, 0xf8, 0xa2, 0x88, 0x64, 0x1f, 0xb9, + 0xa4, 0xe9, 0xa5, 0xcc, 0x2f, 0x13, 0x1c, 0x7d }, + .ilen = 16, + .result = { 0xee, 0x54, 0xd1, 0x3e, 0xbc, 0xae, 0x70, 0x6d, + 0x22, 0x6b, 0xc3, 0x14, 0x2c, 0xd4, 0x0d, 0x4a }, + .rlen = 16, + }, { + .key = { 0x28, 0xdb, 0xc3, 0xbc, 0x49, 0xff, 0xd8, 0x7d, + 0xcf, 0xa5, 0x09, 0xb1, 0x1d, 0x42, 0x2b, 0xe7 }, + .klen = 16, + .input = { 0xb4, 0x1e, 0x6b, 0xe2, 0xeb, 0xa8, 0x4a, 0x14, + 0x8e, 0x2e, 0xed, 0x84, 0x59, 0x3c, 0x5e, 0xc7 }, + .ilen = 16, + .result = { 0x9b, 0x9b, 0x7b, 0xfc, 0xd1, 0x81, 0x3c, 0xb9, + 0x5d, 0x0b, 0x36, 0x18, 0xf4, 0x0f, 0x51, 0x22 }, + .rlen = 16, + } +}; + +static struct cipher_testvec seed_dec_tv_template[] = { + { + .key = { [0 ... 15] = 0x00 }, + .klen = 16, + .input = { 0x5e, 0xba, 0xc6, 0xe0, 0x05, 0x4e, 0x16, 0x68, + 0x19, 0xaf, 0xf1, 0xcc, 0x6d, 0x34, 0x6c, 0xdb }, + .ilen = 16, + .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .rlen = 16, + }, { + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .klen = 16, + .input = { 0xc1, 0x1f, 0x22, 0xf2, 0x01, 0x40, 0x50, 0x50, + 0x84, 0x48, 0x35, 0x97, 0xe4, 0x37, 0x0f, 0x43 }, + .ilen = 16, + .result = { [0 ... 15] = 0x00 }, + .rlen = 16, + }, { + .key = { 0x47, 0x06, 0x48, 0x08, 0x51, 0xe6, 0x1b, 0xe8, + 0x5d, 0x74, 0xbf, 0xb3, 0xfd, 0x95, 0x61, 0x85 }, + .klen = 16, + .input = { 0xee, 0x54, 0xd1, 0x3e, 0xbc, 0xae, 0x70, 0x6d, + 0x22, 0x6b, 0xc3, 0x14, 0x2c, 0xd4, 0x0d, 0x4a }, + .ilen = 16, + .result = { 0x83, 0xa2, 0xf8, 0xa2, 0x88, 0x64, 0x1f, 0xb9, + 0xa4, 0xe9, 0xa5, 0xcc, 0x2f, 0x13, 0x1c, 0x7d }, + .rlen = 16, + }, { + .key = { 0x28, 0xdb, 0xc3, 0xbc, 0x49, 0xff, 0xd8, 0x7d, + 0xcf, 0xa5, 0x09, 0xb1, 0x1d, 0x42, 0x2b, 0xe7 }, + .klen = 16, + .input = { 0x9b, 0x9b, 0x7b, 0xfc, 0xd1, 0x81, 0x3c, 0xb9, + 0x5d, 0x0b, 0x36, 0x18, 0xf4, 0x0f, 0x51, 0x22 }, + .ilen = 16, + .result = { 0xb4, 0x1e, 0x6b, 0xe2, 0xeb, 0xa8, 0x4a, 0x14, + 0x8e, 0x2e, 0xed, 0x84, 0x59, 0x3c, 0x5e, 0xc7 }, + .rlen = 16, + } +}; + +/* * Compression stuff. */ #define COMP_BUF_SIZE 512 @@ -4193,6 +4679,27 @@ static struct cipher_speed aes_lrw_speed_template[] = { { .klen = 0, .blen = 0, } }; +static struct cipher_speed aes_xts_speed_template[] = { + { .klen = 32, .blen = 16, }, + { .klen = 32, .blen = 64, }, + { .klen = 32, .blen = 256, }, + { .klen = 32, .blen = 1024, }, + { .klen = 32, .blen = 8192, }, + { .klen = 48, .blen = 16, }, + { .klen = 48, .blen = 64, }, + { .klen = 48, .blen = 256, }, + { .klen = 48, .blen = 1024, }, + { .klen = 48, .blen = 8192, }, + { .klen = 64, .blen = 16, }, + { .klen = 64, .blen = 64, }, + { .klen = 64, .blen = 256, }, + { .klen = 64, .blen = 1024, }, + { .klen = 64, .blen = 8192, }, + + /* End marker */ + { .klen = 0, .blen = 0, } +}; + static struct cipher_speed des3_ede_speed_template[] = { { .klen = 24, .blen = 16, }, { .klen = 24, .blen = 64, }, diff --git a/crypto/xts.c b/crypto/xts.c new file mode 100644 index 000000000000..8eb08bfaf7c0 --- /dev/null +++ b/crypto/xts.c @@ -0,0 +1,292 @@ +/* XTS: as defined in IEEE1619/D16 + * http://grouper.ieee.org/groups/1619/email/pdf00086.pdf + * (sector sizes which are not a multiple of 16 bytes are, + * however currently unsupported) + * + * Copyright (c) 2007 Rik Snel <rsnel@cube.dyndns.org> + * + * Based om ecb.c + * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ +#include <crypto/algapi.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/scatterlist.h> +#include <linux/slab.h> + +#include <crypto/b128ops.h> +#include <crypto/gf128mul.h> + +struct priv { + struct crypto_cipher *child; + struct crypto_cipher *tweak; +}; + +static int setkey(struct crypto_tfm *parent, const u8 *key, + unsigned int keylen) +{ + struct priv *ctx = crypto_tfm_ctx(parent); + struct crypto_cipher *child = ctx->tweak; + u32 *flags = &parent->crt_flags; + int err; + + /* key consists of keys of equal size concatenated, therefore + * the length must be even */ + if (keylen % 2) { + /* tell the user why there was an error */ + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + /* we need two cipher instances: one to compute the inital 'tweak' + * by encrypting the IV (usually the 'plain' iv) and the other + * one to encrypt and decrypt the data */ + + /* tweak cipher, uses Key2 i.e. the second half of *key */ + crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); + crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) & + CRYPTO_TFM_REQ_MASK); + err = crypto_cipher_setkey(child, key + keylen/2, keylen/2); + if (err) + return err; + + crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) & + CRYPTO_TFM_RES_MASK); + + child = ctx->child; + + /* data cipher, uses Key1 i.e. the first half of *key */ + crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); + crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) & + CRYPTO_TFM_REQ_MASK); + err = crypto_cipher_setkey(child, key, keylen/2); + if (err) + return err; + + crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) & + CRYPTO_TFM_RES_MASK); + + return 0; +} + +struct sinfo { + be128 t; + struct crypto_tfm *tfm; + void (*fn)(struct crypto_tfm *, u8 *, const u8 *); +}; + +static inline void xts_round(struct sinfo *s, void *dst, const void *src) +{ + be128_xor(dst, &s->t, src); /* PP <- T xor P */ + s->fn(s->tfm, dst, dst); /* CC <- E(Key1,PP) */ + be128_xor(dst, dst, &s->t); /* C <- T xor CC */ +} + +static int crypt(struct blkcipher_desc *d, + struct blkcipher_walk *w, struct priv *ctx, + void (*tw)(struct crypto_tfm *, u8 *, const u8 *), + void (*fn)(struct crypto_tfm *, u8 *, const u8 *)) +{ + int err; + unsigned int avail; + const int bs = crypto_cipher_blocksize(ctx->child); + struct sinfo s = { + .tfm = crypto_cipher_tfm(ctx->child), + .fn = fn + }; + be128 *iv; + u8 *wsrc; + u8 *wdst; + + err = blkcipher_walk_virt(d, w); + if (!w->nbytes) + return err; + + avail = w->nbytes; + + wsrc = w->src.virt.addr; + wdst = w->dst.virt.addr; + + /* calculate first value of T */ + iv = (be128 *)w->iv; + tw(crypto_cipher_tfm(ctx->tweak), (void *)&s.t, w->iv); + + goto first; + + for (;;) { + do { + gf128mul_x_ble(&s.t, &s.t); + +first: + xts_round(&s, wdst, wsrc); + + wsrc += bs; + wdst += bs; + } while ((avail -= bs) >= bs); + + err = blkcipher_walk_done(d, w, avail); + if (!w->nbytes) + break; + + avail = w->nbytes; + + wsrc = w->src.virt.addr; + wdst = w->dst.virt.addr; + } + + return err; +} + +static int encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct priv *ctx = crypto_blkcipher_ctx(desc->tfm); + struct blkcipher_walk w; + + blkcipher_walk_init(&w, dst, src, nbytes); + return crypt(desc, &w, ctx, crypto_cipher_alg(ctx->tweak)->cia_encrypt, + crypto_cipher_alg(ctx->child)->cia_encrypt); +} + +static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct priv *ctx = crypto_blkcipher_ctx(desc->tfm); + struct blkcipher_walk w; + + blkcipher_walk_init(&w, dst, src, nbytes); + return crypt(desc, &w, ctx, crypto_cipher_alg(ctx->tweak)->cia_encrypt, + crypto_cipher_alg(ctx->child)->cia_decrypt); +} + +static int init_tfm(struct crypto_tfm *tfm) +{ + struct crypto_cipher *cipher; + struct crypto_instance *inst = (void *)tfm->__crt_alg; + struct crypto_spawn *spawn = crypto_instance_ctx(inst); + struct priv *ctx = crypto_tfm_ctx(tfm); + u32 *flags = &tfm->crt_flags; + + cipher = crypto_spawn_cipher(spawn); + if (IS_ERR(cipher)) + return PTR_ERR(cipher); + + if (crypto_cipher_blocksize(cipher) != 16) { + *flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; + crypto_free_cipher(cipher); + return -EINVAL; + } + + ctx->child = cipher; + + cipher = crypto_spawn_cipher(spawn); + if (IS_ERR(cipher)) { + crypto_free_cipher(ctx->child); + return PTR_ERR(cipher); + } + + /* this check isn't really needed, leave it here just in case */ + if (crypto_cipher_blocksize(cipher) != 16) { + crypto_free_cipher(cipher); + crypto_free_cipher(ctx->child); + *flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; + return -EINVAL; + } + + ctx->tweak = cipher; + + return 0; +} + +static void exit_tfm(struct crypto_tfm *tfm) +{ + struct priv *ctx = crypto_tfm_ctx(tfm); + crypto_free_cipher(ctx->child); + crypto_free_cipher(ctx->tweak); +} + +static struct crypto_instance *alloc(struct rtattr **tb) +{ + struct crypto_instance *inst; + struct crypto_alg *alg; + int err; + + err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER); + if (err) + return ERR_PTR(err); + + alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER, + CRYPTO_ALG_TYPE_MASK); + if (IS_ERR(alg)) + return ERR_PTR(PTR_ERR(alg)); + + inst = crypto_alloc_instance("xts", alg); + if (IS_ERR(inst)) + goto out_put_alg; + + inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER; + inst->alg.cra_priority = alg->cra_priority; + inst->alg.cra_blocksize = alg->cra_blocksize; + + if (alg->cra_alignmask < 7) + inst->alg.cra_alignmask = 7; + else + inst->alg.cra_alignmask = alg->cra_alignmask; + + inst->alg.cra_type = &crypto_blkcipher_type; + + inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize; + inst->alg.cra_blkcipher.min_keysize = + 2 * alg->cra_cipher.cia_min_keysize; + inst->alg.cra_blkcipher.max_keysize = + 2 * alg->cra_cipher.cia_max_keysize; + + inst->alg.cra_ctxsize = sizeof(struct priv); + + inst->alg.cra_init = init_tfm; + inst->alg.cra_exit = exit_tfm; + + inst->alg.cra_blkcipher.setkey = setkey; + inst->alg.cra_blkcipher.encrypt = encrypt; + inst->alg.cra_blkcipher.decrypt = decrypt; + +out_put_alg: + crypto_mod_put(alg); + return inst; +} + +static void free(struct crypto_instance *inst) +{ + crypto_drop_spawn(crypto_instance_ctx(inst)); + kfree(inst); +} + +static struct crypto_template crypto_tmpl = { + .name = "xts", + .alloc = alloc, + .free = free, + .module = THIS_MODULE, +}; + +static int __init crypto_module_init(void) +{ + return crypto_register_template(&crypto_tmpl); +} + +static void __exit crypto_module_exit(void) +{ + crypto_unregister_template(&crypto_tmpl); +} + +module_init(crypto_module_init); +module_exit(crypto_module_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("XTS block cipher mode"); |