From c7870e139556aa404578b575927d87fbc7148ab2 Mon Sep 17 00:00:00 2001 From: James Morris Date: Fri, 7 Mar 2003 19:44:09 -0800 Subject: [PATCH] [CRYPTO]: Add encrypt_iv() and decrypt_iv() methods. --- crypto/cipher.c | 74 ++++++++++++++++++++++++++++++++---------- include/linux/crypto.h | 28 ++++++++++++++++ 2 files changed, 85 insertions(+), 17 deletions(-) diff --git a/crypto/cipher.c b/crypto/cipher.c index ae45fe344c91e..335ff51a3d476 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -23,7 +23,8 @@ #include "internal.h" typedef void (cryptfn_t)(void *, u8 *, const u8 *); -typedef void (procfn_t)(struct crypto_tfm *, u8 *, u8*, cryptfn_t, int enc); +typedef void (procfn_t)(struct crypto_tfm *, u8 *, + u8*, cryptfn_t, int enc, void *); struct scatter_walk { struct scatterlist *sg; @@ -166,7 +167,8 @@ static int copy_chunks(void *buf, struct scatter_walk *walk, static int crypt(struct crypto_tfm *tfm, struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes, cryptfn_t crfn, procfn_t prfn, int enc) + unsigned int nbytes, cryptfn_t crfn, + procfn_t prfn, int enc, void *info) { struct scatter_walk walk_in, walk_out; const unsigned int bsize = crypto_tfm_alg_blocksize(tfm); @@ -196,7 +198,7 @@ static int crypt(struct crypto_tfm *tfm, copy_chunks(src_p, &walk_in, bsize, 0); - prfn(tfm, dst_p, src_p, crfn, enc); + prfn(tfm, dst_p, src_p, crfn, enc, info); scatter_done(&walk_in, 0, nbytes); @@ -211,33 +213,33 @@ static int crypt(struct crypto_tfm *tfm, } static void cbc_process(struct crypto_tfm *tfm, - u8 *dst, u8 *src, cryptfn_t fn, int enc) + u8 *dst, u8 *src, cryptfn_t fn, int enc, void *info) { + u8 *iv = info; + /* Null encryption */ - if (!tfm->crt_cipher.cit_iv) + if (!iv) return; if (enc) { - tfm->crt_u.cipher.cit_xor_block(tfm->crt_cipher.cit_iv, src); - fn(tfm->crt_ctx, dst, tfm->crt_cipher.cit_iv); - memcpy(tfm->crt_cipher.cit_iv, dst, - crypto_tfm_alg_blocksize(tfm)); + tfm->crt_u.cipher.cit_xor_block(iv, src); + fn(tfm->crt_ctx, dst, iv); + memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm)); } else { const int need_stack = (src == dst); u8 stack[need_stack ? crypto_tfm_alg_blocksize(tfm) : 0]; u8 *buf = need_stack ? stack : dst; fn(tfm->crt_ctx, buf, src); - tfm->crt_u.cipher.cit_xor_block(buf, tfm->crt_cipher.cit_iv); - memcpy(tfm->crt_cipher.cit_iv, src, - crypto_tfm_alg_blocksize(tfm)); + tfm->crt_u.cipher.cit_xor_block(buf, iv); + memcpy(iv, src, crypto_tfm_alg_blocksize(tfm)); if (buf != dst) memcpy(dst, buf, crypto_tfm_alg_blocksize(tfm)); } } static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src, - cryptfn_t fn, int enc) + cryptfn_t fn, int enc, void *info) { fn(tfm->crt_ctx, dst, src); } @@ -259,7 +261,8 @@ static int ecb_encrypt(struct crypto_tfm *tfm, struct scatterlist *src, unsigned int nbytes) { return crypt(tfm, dst, src, nbytes, - tfm->__crt_alg->cra_cipher.cia_encrypt, ecb_process, 1); + tfm->__crt_alg->cra_cipher.cia_encrypt, + ecb_process, 1, NULL); } static int ecb_decrypt(struct crypto_tfm *tfm, @@ -268,7 +271,8 @@ static int ecb_decrypt(struct crypto_tfm *tfm, unsigned int nbytes) { return crypt(tfm, dst, src, nbytes, - tfm->__crt_alg->cra_cipher.cia_decrypt, ecb_process, 1); + tfm->__crt_alg->cra_cipher.cia_decrypt, + ecb_process, 1, NULL); } static int cbc_encrypt(struct crypto_tfm *tfm, @@ -277,7 +281,18 @@ static int cbc_encrypt(struct crypto_tfm *tfm, unsigned int nbytes) { return crypt(tfm, dst, src, nbytes, - tfm->__crt_alg->cra_cipher.cia_encrypt, cbc_process, 1); + tfm->__crt_alg->cra_cipher.cia_encrypt, + cbc_process, 1, tfm->crt_cipher.cit_iv); +} + +static int cbc_encrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_encrypt, + cbc_process, 1, iv); } static int cbc_decrypt(struct crypto_tfm *tfm, @@ -286,7 +301,18 @@ static int cbc_decrypt(struct crypto_tfm *tfm, unsigned int nbytes) { return crypt(tfm, dst, src, nbytes, - tfm->__crt_alg->cra_cipher.cia_decrypt, cbc_process, 0); + tfm->__crt_alg->cra_cipher.cia_decrypt, + cbc_process, 0, tfm->crt_cipher.cit_iv); +} + +static int cbc_decrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_decrypt, + cbc_process, 0, iv); } static int nocrypt(struct crypto_tfm *tfm, @@ -297,6 +323,14 @@ static int nocrypt(struct crypto_tfm *tfm, return -ENOSYS; } +static int nocrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return -ENOSYS; +} + int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags) { u32 mode = flags & CRYPTO_TFM_MODE_MASK; @@ -325,16 +359,22 @@ int crypto_init_cipher_ops(struct crypto_tfm *tfm) case CRYPTO_TFM_MODE_CBC: ops->cit_encrypt = cbc_encrypt; ops->cit_decrypt = cbc_decrypt; + ops->cit_encrypt_iv = cbc_encrypt_iv; + ops->cit_decrypt_iv = cbc_decrypt_iv; break; case CRYPTO_TFM_MODE_CFB: ops->cit_encrypt = nocrypt; ops->cit_decrypt = nocrypt; + ops->cit_encrypt_iv = nocrypt_iv; + ops->cit_decrypt_iv = nocrypt_iv; break; case CRYPTO_TFM_MODE_CTR: ops->cit_encrypt = nocrypt; ops->cit_decrypt = nocrypt; + ops->cit_encrypt_iv = nocrypt_iv; + ops->cit_decrypt_iv = nocrypt_iv; break; default: diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 5178882ec4d14..5083e6b9c3b0a 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -134,10 +134,18 @@ struct cipher_tfm { struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes); + int (*cit_encrypt_iv)(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv); int (*cit_decrypt)(struct crypto_tfm *tfm, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes); + int (*cit_decrypt_iv)(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv); void (*cit_xor_block)(u8 *dst, const u8 *src); }; @@ -286,6 +294,16 @@ static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm, return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes); } +static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB); + return tfm->crt_cipher.cit_encrypt_iv(tfm, dst, src, nbytes, iv); +} + static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm, struct scatterlist *dst, struct scatterlist *src, @@ -295,6 +313,16 @@ static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm, return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes); } +static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB); + return tfm->crt_cipher.cit_decrypt_iv(tfm, dst, src, nbytes, iv); +} + static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm, const u8 *src, unsigned int len) { -- 2.53.0