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
Signed-off-by: Horia Geantă
---
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
-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
-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 == _ablkcipher_type) ||
+ (tfm->__crt_alg->cra_type == _givcipher_type)) {
+ struct ablkcipher_alg *alg;
+
+ alg = >__crt_alg->cra_ablkcipher;
+ min_keysize = alg->min_keysize;
+