aboutsummaryrefslogtreecommitdiffstats
path: root/recipes-kernel/cryptodev/sdk_patches/0093-Fix-ablkcipher-algorithms-usage-in-v4.8-kernels.patch
blob: fcf2a3ee680596276de7d8a7c1c4341969d6c1e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
From 871ecc5c5ebfbb9c6e1b17a7ff7a531ed1fab644 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Horia=20Geant=C4=83?= <horia.geanta@nxp.com>
Date: Wed, 16 Nov 2016 15:38:39 +0200
Subject: [PATCH 093/104] Fix ablkcipher algorithms usage in v4.8+ kernels
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

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")
Signed-off-by: Horia Geantă <horia.geanta@nxp.com>
---
 cipherapi.h |  4 ----
 cryptlib.c  | 56 ++++++++++++++++++++++++++++++++++++++++++++------------
 2 files changed, 44 insertions(+), 16 deletions(-)

diff --git a/cipherapi.h b/cipherapi.h
index 07d9923..b6ed6c2 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 558d4b8..dcac3ec 100644
--- a/cryptlib.c
+++ b/cryptlib.c
@@ -39,6 +39,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)
 {
@@ -122,6 +123,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)
@@ -129,7 +143,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))) {
@@ -137,18 +156,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.10.2