@@ -32,7 +32,6 @@
#include <crypto/b128ops.h>
#include <crypto/chacha.h>
-#include <crypto/internal/cipher.h>
#include <crypto/internal/hash.h>
#include <crypto/internal/poly1305.h>
#include <crypto/internal/skcipher.h>
@@ -63,13 +62,13 @@
struct adiantum_instance_ctx {
struct crypto_skcipher_spawn streamcipher_spawn;
- struct crypto_cipher_spawn blockcipher_spawn;
+ struct crypto_lskcipher_spawn blockcipher_spawn;
struct crypto_shash_spawn hash_spawn;
};
struct adiantum_tfm_ctx {
struct crypto_skcipher *streamcipher;
- struct crypto_cipher *blockcipher;
+ struct crypto_lskcipher *blockcipher;
struct crypto_shash *hash;
struct poly1305_core_key header_hash_key;
};
@@ -157,12 +156,12 @@ static int adiantum_setkey(struct crypto_skcipher *tfm, const u8 *key,
keyp = data->derived_keys;
/* Set the block cipher key (K_E) */
- crypto_cipher_clear_flags(tctx->blockcipher, CRYPTO_TFM_REQ_MASK);
- crypto_cipher_set_flags(tctx->blockcipher,
- crypto_skcipher_get_flags(tfm) &
- CRYPTO_TFM_REQ_MASK);
- err = crypto_cipher_setkey(tctx->blockcipher, keyp,
- BLOCKCIPHER_KEY_SIZE);
+ crypto_lskcipher_clear_flags(tctx->blockcipher, CRYPTO_TFM_REQ_MASK);
+ crypto_lskcipher_set_flags(tctx->blockcipher,
+ crypto_skcipher_get_flags(tfm) &
+ CRYPTO_TFM_REQ_MASK);
+ err = crypto_lskcipher_setkey(tctx->blockcipher, keyp,
+ BLOCKCIPHER_KEY_SIZE);
if (err)
goto out;
keyp += BLOCKCIPHER_KEY_SIZE;
@@ -287,9 +286,14 @@ static int adiantum_finish(struct skcipher_request *req)
int err;
/* If decrypting, decrypt C_M with the block cipher to get P_M */
- if (!rctx->enc)
- crypto_cipher_decrypt_one(tctx->blockcipher, rctx->rbuf.bytes,
- rctx->rbuf.bytes);
+ if (!rctx->enc) {
+ err = crypto_lskcipher_decrypt(tctx->blockcipher,
+ rctx->rbuf.bytes,
+ rctx->rbuf.bytes,
+ BLOCKCIPHER_BLOCK_SIZE, NULL);
+ if (err)
+ return err;
+ }
/*
* Second hash step
@@ -379,9 +383,14 @@ static int adiantum_crypt(struct skcipher_request *req, bool enc)
le128_add(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest);
/* If encrypting, encrypt P_M with the block cipher to get C_M */
- if (enc)
- crypto_cipher_encrypt_one(tctx->blockcipher, rctx->rbuf.bytes,
- rctx->rbuf.bytes);
+ if (enc) {
+ err = crypto_lskcipher_encrypt(tctx->blockcipher,
+ rctx->rbuf.bytes,
+ rctx->rbuf.bytes,
+ BLOCKCIPHER_BLOCK_SIZE, NULL);
+ if (err)
+ return err;
+ }
/* Initialize the rest of the XChaCha IV (first part is C_M) */
BUILD_BUG_ON(BLOCKCIPHER_BLOCK_SIZE != 16);
@@ -430,7 +439,7 @@ static int adiantum_init_tfm(struct crypto_skcipher *tfm)
struct adiantum_instance_ctx *ictx = skcipher_instance_ctx(inst);
struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
struct crypto_skcipher *streamcipher;
- struct crypto_cipher *blockcipher;
+ struct crypto_lskcipher *blockcipher;
struct crypto_shash *hash;
unsigned int subreq_size;
int err;
@@ -439,7 +448,7 @@ static int adiantum_init_tfm(struct crypto_skcipher *tfm)
if (IS_ERR(streamcipher))
return PTR_ERR(streamcipher);
- blockcipher = crypto_spawn_cipher(&ictx->blockcipher_spawn);
+ blockcipher = crypto_spawn_lskcipher(&ictx->blockcipher_spawn);
if (IS_ERR(blockcipher)) {
err = PTR_ERR(blockcipher);
goto err_free_streamcipher;
@@ -470,7 +479,7 @@ static int adiantum_init_tfm(struct crypto_skcipher *tfm)
return 0;
err_free_blockcipher:
- crypto_free_cipher(blockcipher);
+ crypto_free_lskcipher(blockcipher);
err_free_streamcipher:
crypto_free_skcipher(streamcipher);
return err;
@@ -481,7 +490,7 @@ static void adiantum_exit_tfm(struct crypto_skcipher *tfm)
struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
crypto_free_skcipher(tctx->streamcipher);
- crypto_free_cipher(tctx->blockcipher);
+ crypto_free_lskcipher(tctx->blockcipher);
crypto_free_shash(tctx->hash);
}
@@ -490,7 +499,7 @@ static void adiantum_free_instance(struct skcipher_instance *inst)
struct adiantum_instance_ctx *ictx = skcipher_instance_ctx(inst);
crypto_drop_skcipher(&ictx->streamcipher_spawn);
- crypto_drop_cipher(&ictx->blockcipher_spawn);
+ crypto_drop_lskcipher(&ictx->blockcipher_spawn);
crypto_drop_shash(&ictx->hash_spawn);
kfree(inst);
}
@@ -500,17 +509,21 @@ static void adiantum_free_instance(struct skcipher_instance *inst)
* See the comment at the beginning of this file.
*/
static bool adiantum_supported_algorithms(struct skcipher_alg_common *streamcipher_alg,
- struct crypto_alg *blockcipher_alg,
+ struct lskcipher_alg *blockcipher_alg,
struct shash_alg *hash_alg)
{
if (strcmp(streamcipher_alg->base.cra_name, "xchacha12") != 0 &&
strcmp(streamcipher_alg->base.cra_name, "xchacha20") != 0)
return false;
- if (blockcipher_alg->cra_cipher.cia_min_keysize > BLOCKCIPHER_KEY_SIZE ||
- blockcipher_alg->cra_cipher.cia_max_keysize < BLOCKCIPHER_KEY_SIZE)
+ if (blockcipher_alg->co.min_keysize > BLOCKCIPHER_KEY_SIZE ||
+ blockcipher_alg->co.max_keysize < BLOCKCIPHER_KEY_SIZE)
return false;
- if (blockcipher_alg->cra_blocksize != BLOCKCIPHER_BLOCK_SIZE)
+ if (blockcipher_alg->co.base.cra_blocksize != BLOCKCIPHER_BLOCK_SIZE)
+ return false;
+ if (blockcipher_alg->co.ivsize)
+ return false;
+ if (blockcipher_alg->co.statesize)
return false;
if (strcmp(hash_alg->base.cra_name, "nhpoly1305") != 0)
@@ -526,8 +539,12 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
struct skcipher_instance *inst;
struct adiantum_instance_ctx *ictx;
struct skcipher_alg_common *streamcipher_alg;
- struct crypto_alg *blockcipher_alg;
+ char ecb_driver_name[CRYPTO_MAX_ALG_NAME];
+ struct lskcipher_alg *blockcipher_alg;
+ char ecb_name[CRYPTO_MAX_ALG_NAME];
+ const char *cipher_driver_name;
struct shash_alg *hash_alg;
+ const char *cipher_name;
int err;
err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SKCIPHER, &mask);
@@ -548,12 +565,27 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
streamcipher_alg = crypto_spawn_skcipher_alg_common(&ictx->streamcipher_spawn);
/* Block cipher, e.g. "aes" */
- err = crypto_grab_cipher(&ictx->blockcipher_spawn,
- skcipher_crypto_instance(inst),
- crypto_attr_alg_name(tb[2]), 0, mask);
+ cipher_name = crypto_attr_alg_name(tb[2]);
+ cipher_driver_name = cipher_name;
+ err = crypto_grab_lskcipher(&ictx->blockcipher_spawn,
+ skcipher_crypto_instance(inst),
+ cipher_name, 0, mask);
+
+ ecb_name[0] = 0;
+ if (err == -ENOENT) {
+ err = -ENAMETOOLONG;
+ if (snprintf(ecb_name, CRYPTO_MAX_ALG_NAME, "ecb(%s)",
+ cipher_name) >= CRYPTO_MAX_ALG_NAME)
+ goto err_free_inst;
+
+ err = crypto_grab_lskcipher(&ictx->blockcipher_spawn,
+ skcipher_crypto_instance(inst),
+ ecb_name, 0, mask);
+ }
+
if (err)
goto err_free_inst;
- blockcipher_alg = crypto_spawn_cipher_alg(&ictx->blockcipher_spawn);
+ blockcipher_alg = crypto_spawn_lskcipher_alg(&ictx->blockcipher_spawn);
/* NHPoly1305 ε-∆U hash function */
nhpoly1305_name = crypto_attr_alg_name(tb[3]);
@@ -571,22 +603,52 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
hash_alg)) {
pr_warn("Unsupported Adiantum instantiation: (%s,%s,%s)\n",
streamcipher_alg->base.cra_name,
- blockcipher_alg->cra_name, hash_alg->base.cra_name);
+ blockcipher_alg->co.base.cra_name,
+ hash_alg->base.cra_name);
err = -EINVAL;
goto err_free_inst;
}
/* Instance fields */
+ cipher_name = blockcipher_alg->co.base.cra_name;
+ cipher_driver_name = blockcipher_alg->co.base.cra_driver_name;
+ if (ecb_name[0]) {
+ int len;
+
+ err = -EINVAL;
+ len = strscpy(ecb_name, &blockcipher_alg->co.base.cra_name[4],
+ sizeof(ecb_name));
+ if (len < 2)
+ goto err_free_inst;
+
+ if (ecb_name[len - 1] != ')')
+ goto err_free_inst;
+
+ ecb_name[len - 1] = 0;
+ cipher_name = ecb_name;
+
+ len = strscpy(ecb_driver_name, &blockcipher_alg->co.base.cra_driver_name[4],
+ sizeof(ecb_driver_name));
+ if (len < 2)
+ goto err_free_inst;
+
+ if (ecb_driver_name[len - 1] != ')')
+ goto err_free_inst;
+
+ ecb_driver_name[len - 1] = 0;
+ cipher_driver_name = ecb_driver_name;
+ }
+
err = -ENAMETOOLONG;
if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
"adiantum(%s,%s)", streamcipher_alg->base.cra_name,
- blockcipher_alg->cra_name) >= CRYPTO_MAX_ALG_NAME)
+ cipher_name) >= CRYPTO_MAX_ALG_NAME)
goto err_free_inst;
if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
"adiantum(%s,%s,%s)",
streamcipher_alg->base.cra_driver_name,
- blockcipher_alg->cra_driver_name,
+ cipher_driver_name,
hash_alg->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
goto err_free_inst;
@@ -601,7 +663,7 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
*/
inst->alg.base.cra_priority = (4 * streamcipher_alg->base.cra_priority +
2 * hash_alg->base.cra_priority +
- blockcipher_alg->cra_priority) / 7;
+ blockcipher_alg->co.base.cra_priority) / 7;
inst->alg.setkey = adiantum_setkey;
inst->alg.encrypt = adiantum_encrypt;
@@ -611,6 +673,7 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
inst->alg.min_keysize = streamcipher_alg->min_keysize;
inst->alg.max_keysize = streamcipher_alg->max_keysize;
inst->alg.ivsize = TWEAK_SIZE;
+ inst->alg.co.twopass = true;
inst->free = adiantum_free_instance;
@@ -646,4 +709,3 @@ MODULE_DESCRIPTION("Adiantum length-preserving encryption mode");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Eric Biggers <ebiggers@google.com>");
MODULE_ALIAS_CRYPTO("adiantum");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
Use the new lskcipher interface for simple block cipher. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> --- crypto/adiantum.c | 130 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 96 insertions(+), 34 deletions(-)