#include "internal.h"
 #include "scatterwalk.h"
 
-struct cipher_desc {
-       struct crypto_tfm *tfm;
-       void (*crfn)(void *ctx, u8 *dst, const u8 *src);
-       unsigned int (*prfn)(const struct cipher_desc *desc, u8 *dst,
-                            const u8 *src, unsigned int nbytes);
-       void *info;
-};
-
 static inline void xor_64(u8 *a, const u8 *b)
 {
        ((u32 *)a)[0] ^= ((u32 *)b)[0];
                        struct scatterlist *src, unsigned int nbytes)
 {
        struct cipher_desc desc;
+       struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;
 
        desc.tfm = tfm;
-       desc.crfn = tfm->__crt_alg->cra_cipher.cia_encrypt;
-       desc.prfn = ecb_process;
+       desc.crfn = cipher->cia_encrypt;
+       desc.prfn = cipher->cia_encrypt_ecb ?: ecb_process;
 
        return crypt(&desc, dst, src, nbytes);
 }
                       unsigned int nbytes)
 {
        struct cipher_desc desc;
+       struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;
 
        desc.tfm = tfm;
-       desc.crfn = tfm->__crt_alg->cra_cipher.cia_decrypt;
-       desc.prfn = ecb_process;
+       desc.crfn = cipher->cia_decrypt;
+       desc.prfn = cipher->cia_decrypt_ecb ?: ecb_process;
 
        return crypt(&desc, dst, src, nbytes);
 }
                       unsigned int nbytes)
 {
        struct cipher_desc desc;
+       struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;
 
        desc.tfm = tfm;
-       desc.crfn = tfm->__crt_alg->cra_cipher.cia_encrypt;
-       desc.prfn = cbc_process_encrypt;
+       desc.crfn = cipher->cia_encrypt;
+       desc.prfn = cipher->cia_encrypt_cbc ?: cbc_process_encrypt;
        desc.info = tfm->crt_cipher.cit_iv;
 
        return crypt(&desc, dst, src, nbytes);
                           unsigned int nbytes, u8 *iv)
 {
        struct cipher_desc desc;
+       struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;
 
        desc.tfm = tfm;
-       desc.crfn = tfm->__crt_alg->cra_cipher.cia_encrypt;
-       desc.prfn = cbc_process_encrypt;
+       desc.crfn = cipher->cia_encrypt;
+       desc.prfn = cipher->cia_encrypt_cbc ?: cbc_process_encrypt;
        desc.info = iv;
 
        return crypt(&desc, dst, src, nbytes);
                       unsigned int nbytes)
 {
        struct cipher_desc desc;
+       struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;
 
        desc.tfm = tfm;
-       desc.crfn = tfm->__crt_alg->cra_cipher.cia_decrypt;
-       desc.prfn = cbc_process_decrypt;
+       desc.crfn = cipher->cia_decrypt;
+       desc.prfn = cipher->cia_decrypt_cbc ?: cbc_process_decrypt;
        desc.info = tfm->crt_cipher.cit_iv;
 
        return crypt(&desc, dst, src, nbytes);
                           unsigned int nbytes, u8 *iv)
 {
        struct cipher_desc desc;
+       struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;
 
        desc.tfm = tfm;
-       desc.crfn = tfm->__crt_alg->cra_cipher.cia_decrypt;
-       desc.prfn = cbc_process_decrypt;
+       desc.crfn = cipher->cia_decrypt;
+       desc.prfn = cipher->cia_decrypt_cbc ?: cbc_process_decrypt;
        desc.info = iv;
 
        return crypt(&desc, dst, src, nbytes);
 
 #define CRYPTO_DIR_DECRYPT             0
 
 struct scatterlist;
+struct crypto_tfm;
+
+struct cipher_desc {
+       struct crypto_tfm *tfm;
+       void (*crfn)(void *ctx, u8 *dst, const u8 *src);
+       unsigned int (*prfn)(const struct cipher_desc *desc, u8 *dst,
+                            const u8 *src, unsigned int nbytes);
+       void *info;
+};
 
 /*
  * Algorithms: modular crypto algorithm implementations, managed
                          unsigned int keylen, u32 *flags);
        void (*cia_encrypt)(void *ctx, u8 *dst, const u8 *src);
        void (*cia_decrypt)(void *ctx, u8 *dst, const u8 *src);
+
+       unsigned int (*cia_encrypt_ecb)(const struct cipher_desc *desc,
+                                       u8 *dst, const u8 *src,
+                                       unsigned int nbytes);
+       unsigned int (*cia_decrypt_ecb)(const struct cipher_desc *desc,
+                                       u8 *dst, const u8 *src,
+                                       unsigned int nbytes);
+       unsigned int (*cia_encrypt_cbc)(const struct cipher_desc *desc,
+                                       u8 *dst, const u8 *src,
+                                       unsigned int nbytes);
+       unsigned int (*cia_decrypt_cbc)(const struct cipher_desc *desc,
+                                       u8 *dst, const u8 *src,
+                                       unsigned int nbytes);
 };
 
 struct digest_alg {
  * and core processing logic.  Managed via crypto_alloc_tfm() and
  * crypto_free_tfm(), as well as the various helpers below.
  */
-struct crypto_tfm;
 
 struct cipher_tfm {
        void *cit_iv;
        return tfm->__crt_alg->cra_digest.dia_digestsize;
 }
 
+static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm)
+{
+       return (void *)&tfm[1];
+}
+
 /*
  * API wrappers.
  */