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 @@ ...@@ -23,7 +23,8 @@
#include "internal.h" #include "internal.h"
typedef void (cryptfn_t)(void *, u8 *, const u8 *); 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 scatter_walk {
struct scatterlist *sg; struct scatterlist *sg;
...@@ -166,7 +167,8 @@ static int copy_chunks(void *buf, struct scatter_walk *walk, ...@@ -166,7 +167,8 @@ static int copy_chunks(void *buf, struct scatter_walk *walk,
static int crypt(struct crypto_tfm *tfm, static int crypt(struct crypto_tfm *tfm,
struct scatterlist *dst, struct scatterlist *dst,
struct scatterlist *src, 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; struct scatter_walk walk_in, walk_out;
const unsigned int bsize = crypto_tfm_alg_blocksize(tfm); const unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
...@@ -196,7 +198,7 @@ static int crypt(struct crypto_tfm *tfm, ...@@ -196,7 +198,7 @@ static int crypt(struct crypto_tfm *tfm,
copy_chunks(src_p, &walk_in, bsize, 0); 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); scatter_done(&walk_in, 0, nbytes);
...@@ -211,33 +213,33 @@ static int crypt(struct crypto_tfm *tfm, ...@@ -211,33 +213,33 @@ static int crypt(struct crypto_tfm *tfm,
} }
static void cbc_process(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 */ /* Null encryption */
if (!tfm->crt_cipher.cit_iv) if (!iv)
return; return;
if (enc) { if (enc) {
tfm->crt_u.cipher.cit_xor_block(tfm->crt_cipher.cit_iv, src); tfm->crt_u.cipher.cit_xor_block(iv, src);
fn(tfm->crt_ctx, dst, tfm->crt_cipher.cit_iv); fn(tfm->crt_ctx, dst, iv);
memcpy(tfm->crt_cipher.cit_iv, dst, memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm));
crypto_tfm_alg_blocksize(tfm));
} else { } else {
const int need_stack = (src == dst); const int need_stack = (src == dst);
u8 stack[need_stack ? crypto_tfm_alg_blocksize(tfm) : 0]; u8 stack[need_stack ? crypto_tfm_alg_blocksize(tfm) : 0];
u8 *buf = need_stack ? stack : dst; u8 *buf = need_stack ? stack : dst;
fn(tfm->crt_ctx, buf, src); fn(tfm->crt_ctx, buf, src);
tfm->crt_u.cipher.cit_xor_block(buf, tfm->crt_cipher.cit_iv); tfm->crt_u.cipher.cit_xor_block(buf, iv);
memcpy(tfm->crt_cipher.cit_iv, src, memcpy(iv, src, crypto_tfm_alg_blocksize(tfm));
crypto_tfm_alg_blocksize(tfm));
if (buf != dst) if (buf != dst)
memcpy(dst, buf, crypto_tfm_alg_blocksize(tfm)); memcpy(dst, buf, crypto_tfm_alg_blocksize(tfm));
} }
} }
static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src, 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); fn(tfm->crt_ctx, dst, src);
} }
...@@ -259,7 +261,8 @@ static int ecb_encrypt(struct crypto_tfm *tfm, ...@@ -259,7 +261,8 @@ static int ecb_encrypt(struct crypto_tfm *tfm,
struct scatterlist *src, unsigned int nbytes) struct scatterlist *src, unsigned int nbytes)
{ {
return crypt(tfm, dst, src, 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, static int ecb_decrypt(struct crypto_tfm *tfm,
...@@ -268,7 +271,8 @@ static int ecb_decrypt(struct crypto_tfm *tfm, ...@@ -268,7 +271,8 @@ static int ecb_decrypt(struct crypto_tfm *tfm,
unsigned int nbytes) unsigned int nbytes)
{ {
return crypt(tfm, dst, src, 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, static int cbc_encrypt(struct crypto_tfm *tfm,
...@@ -277,7 +281,18 @@ static int cbc_encrypt(struct crypto_tfm *tfm, ...@@ -277,7 +281,18 @@ static int cbc_encrypt(struct crypto_tfm *tfm,
unsigned int nbytes) unsigned int nbytes)
{ {
return crypt(tfm, dst, src, 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, static int cbc_decrypt(struct crypto_tfm *tfm,
...@@ -286,7 +301,18 @@ static int cbc_decrypt(struct crypto_tfm *tfm, ...@@ -286,7 +301,18 @@ static int cbc_decrypt(struct crypto_tfm *tfm,
unsigned int nbytes) unsigned int nbytes)
{ {
return crypt(tfm, dst, src, 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, static int nocrypt(struct crypto_tfm *tfm,
...@@ -297,6 +323,14 @@ static int nocrypt(struct crypto_tfm *tfm, ...@@ -297,6 +323,14 @@ static int nocrypt(struct crypto_tfm *tfm,
return -ENOSYS; 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) int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags)
{ {
u32 mode = flags & CRYPTO_TFM_MODE_MASK; u32 mode = flags & CRYPTO_TFM_MODE_MASK;
...@@ -325,16 +359,22 @@ int crypto_init_cipher_ops(struct crypto_tfm *tfm) ...@@ -325,16 +359,22 @@ int crypto_init_cipher_ops(struct crypto_tfm *tfm)
case CRYPTO_TFM_MODE_CBC: case CRYPTO_TFM_MODE_CBC:
ops->cit_encrypt = cbc_encrypt; ops->cit_encrypt = cbc_encrypt;
ops->cit_decrypt = cbc_decrypt; ops->cit_decrypt = cbc_decrypt;
ops->cit_encrypt_iv = cbc_encrypt_iv;
ops->cit_decrypt_iv = cbc_decrypt_iv;
break; break;
case CRYPTO_TFM_MODE_CFB: case CRYPTO_TFM_MODE_CFB:
ops->cit_encrypt = nocrypt; ops->cit_encrypt = nocrypt;
ops->cit_decrypt = nocrypt; ops->cit_decrypt = nocrypt;
ops->cit_encrypt_iv = nocrypt_iv;
ops->cit_decrypt_iv = nocrypt_iv;
break; break;
case CRYPTO_TFM_MODE_CTR: case CRYPTO_TFM_MODE_CTR:
ops->cit_encrypt = nocrypt; ops->cit_encrypt = nocrypt;
ops->cit_decrypt = nocrypt; ops->cit_decrypt = nocrypt;
ops->cit_encrypt_iv = nocrypt_iv;
ops->cit_decrypt_iv = nocrypt_iv;
break; break;
default: default:
......
...@@ -134,10 +134,18 @@ struct cipher_tfm { ...@@ -134,10 +134,18 @@ struct cipher_tfm {
struct scatterlist *dst, struct scatterlist *dst,
struct scatterlist *src, struct scatterlist *src,
unsigned int nbytes); 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, int (*cit_decrypt)(struct crypto_tfm *tfm,
struct scatterlist *dst, struct scatterlist *dst,
struct scatterlist *src, struct scatterlist *src,
unsigned int nbytes); 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); void (*cit_xor_block)(u8 *dst, const u8 *src);
}; };
...@@ -286,6 +294,16 @@ static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm, ...@@ -286,6 +294,16 @@ static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm,
return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes); 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, static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm,
struct scatterlist *dst, struct scatterlist *dst,
struct scatterlist *src, struct scatterlist *src,
...@@ -295,6 +313,16 @@ static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm, ...@@ -295,6 +313,16 @@ static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm,
return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes); 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, static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm,
const u8 *src, unsigned int len) 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