ablkcipher API is not completely removed from kernels <= v4.9.
Thus it's still valid to use ablkcipher algorithms.

Fix the case when implementers register ablkcipher algorithms
and cryptodev casts them to skcipher without checking their type.

Note: alg returned by crypto_ablkcipher_alg() is no longer checked
to be non-NULL. This is guaranteed by the fact that ablkcipher_tfm
(out->async.s) is valid.

Fixes: cb186f682679 ("Support skcipher in addition to ablkcipher API")
Tested-by: Cristian Stoica <cristian.sto...@nxp.com>
Signed-off-by: Horia Geantă <horia.gea...@nxp.com>
---
 cipherapi.h |  4 ----
 cryptlib.c  | 56 ++++++++++++++++++++++++++++++++++++++++++++------------
 2 files changed, 44 insertions(+), 16 deletions(-)

diff --git a/cipherapi.h b/cipherapi.h
index 07d992333ad7..b6ed6c279350 100644
--- a/cipherapi.h
+++ b/cipherapi.h
@@ -6,12 +6,10 @@
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0))
 # include <linux/crypto.h>
 
-typedef struct ablkcipher_alg cryptodev_blkcipher_alg_t;
 typedef struct crypto_ablkcipher cryptodev_crypto_blkcipher_t;
 typedef struct ablkcipher_request cryptodev_blkcipher_request_t;
 
 # define cryptodev_crypto_alloc_blkcipher crypto_alloc_ablkcipher
-# define cryptodev_crypto_blkcipher_alg crypto_ablkcipher_alg
 # define cryptodev_crypto_blkcipher_blocksize crypto_ablkcipher_blocksize
 # define cryptodev_crypto_blkcipher_ivsize crypto_ablkcipher_ivsize
 # define cryptodev_crypto_blkcipher_alignmask crypto_ablkcipher_alignmask
@@ -37,12 +35,10 @@ static inline void 
cryptodev_blkcipher_request_free(cryptodev_blkcipher_request_
 #else
 #include <crypto/skcipher.h>
 
-typedef struct skcipher_alg cryptodev_blkcipher_alg_t;
 typedef struct crypto_skcipher cryptodev_crypto_blkcipher_t;
 typedef struct skcipher_request cryptodev_blkcipher_request_t;
 
 # define cryptodev_crypto_alloc_blkcipher crypto_alloc_skcipher
-# define cryptodev_crypto_blkcipher_alg crypto_skcipher_alg
 # define cryptodev_crypto_blkcipher_blocksize crypto_skcipher_blocksize
 # define cryptodev_crypto_blkcipher_ivsize crypto_skcipher_ivsize
 # define cryptodev_crypto_blkcipher_alignmask crypto_skcipher_alignmask
diff --git a/cryptlib.c b/cryptlib.c
index 5a6e0ba5fe88..2c6028ee2b23 100644
--- a/cryptlib.c
+++ b/cryptlib.c
@@ -38,6 +38,7 @@
 #include "cryptodev_int.h"
 #include "cipherapi.h"
 
+extern const struct crypto_type crypto_givcipher_type;
 
 static void cryptodev_complete(struct crypto_async_request *req, int err)
 {
@@ -121,6 +122,19 @@ error:
        return ret;
 }
 
+/* Was correct key length supplied? */
+static int check_key_size(size_t keylen, const char *alg_name,
+                         unsigned int min_keysize, unsigned int max_keysize)
+{
+       if (max_keysize > 0 && unlikely((keylen < min_keysize) ||
+                                       (keylen > max_keysize))) {
+               ddebug(1, "Wrong keylen '%zu' for algorithm '%s'. Use %u to 
%u.",
+                      keylen, alg_name, min_keysize, max_keysize);
+               return -EINVAL;
+       }
+
+       return 0;
+}
 
 int cryptodev_cipher_init(struct cipher_data *out, const char *alg_name,
                                uint8_t *keyp, size_t keylen, int stream, int 
aead)
@@ -128,7 +142,12 @@ int cryptodev_cipher_init(struct cipher_data *out, const 
char *alg_name,
        int ret;
 
        if (aead == 0) {
-               cryptodev_blkcipher_alg_t *alg;
+               unsigned int min_keysize, max_keysize;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
+               struct crypto_tfm *tfm;
+#else
+               struct ablkcipher_alg *alg;
+#endif
 
                out->async.s = cryptodev_crypto_alloc_blkcipher(alg_name, 0, 0);
                if (unlikely(IS_ERR(out->async.s))) {
@@ -136,18 +155,31 @@ int cryptodev_cipher_init(struct cipher_data *out, const 
char *alg_name,
                                return -EINVAL;
                }
 
-               alg = cryptodev_crypto_blkcipher_alg(out->async.s);
-               if (alg != NULL) {
-                       /* Was correct key length supplied? */
-                       if (alg->max_keysize > 0 &&
-                                       unlikely((keylen < alg->min_keysize) ||
-                                       (keylen > alg->max_keysize))) {
-                               ddebug(1, "Wrong keylen '%zu' for algorithm 
'%s'. Use %u to %u.",
-                                               keylen, alg_name, 
alg->min_keysize, alg->max_keysize);
-                               ret = -EINVAL;
-                               goto error;
-                       }
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
+               tfm = crypto_skcipher_tfm(out->async.s);
+               if ((tfm->__crt_alg->cra_type == &crypto_ablkcipher_type) ||
+                   (tfm->__crt_alg->cra_type == &crypto_givcipher_type)) {
+                       struct ablkcipher_alg *alg;
+
+                       alg = &tfm->__crt_alg->cra_ablkcipher;
+                       min_keysize = alg->min_keysize;
+                       max_keysize = alg->max_keysize;
+               } else {
+                       struct skcipher_alg *alg;
+
+                       alg = crypto_skcipher_alg(out->async.s);
+                       min_keysize = alg->min_keysize;
+                       max_keysize = alg->max_keysize;
                }
+#else
+               alg = crypto_ablkcipher_alg(out->async.s);
+               min_keysize = alg->min_keysize;
+               max_keysize = alg->max_keysize;
+#endif
+               ret = check_key_size(keylen, alg_name, min_keysize,
+                                    max_keysize);
+               if (ret)
+                       goto error;
 
                out->blocksize = 
cryptodev_crypto_blkcipher_blocksize(out->async.s);
                out->ivsize = cryptodev_crypto_blkcipher_ivsize(out->async.s);
-- 
2.4.4


_______________________________________________
Cryptodev-linux-devel mailing list
Cryptodev-linux-devel@gna.org
https://mail.gna.org/listinfo/cryptodev-linux-devel

Reply via email to