Commit c7870e13 authored by James Morris's avatar James Morris Committed by David S. Miller

[CRYPTO]: Add encrypt_iv() and decrypt_iv() methods.

parent 1e031531
......@@ -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:
......
......@@ -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)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment