Skip to content

Commit 63ba4d6

Browse files
committed
KEYS: asymmetric: Use new crypto interface without scatterlists
Use the new akcipher and sig interfaces which no longer have scatterlists in them. Signed-off-by: Herbert Xu <[email protected]>
1 parent e5221fa commit 63ba4d6

File tree

1 file changed

+137
-97
lines changed

1 file changed

+137
-97
lines changed

crypto/asymmetric_keys/public_key.c

Lines changed: 137 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,17 @@
88
*/
99

1010
#define pr_fmt(fmt) "PKEY: "fmt
11-
#include <linux/module.h>
12-
#include <linux/export.h>
11+
#include <crypto/akcipher.h>
12+
#include <crypto/public_key.h>
13+
#include <crypto/sig.h>
14+
#include <keys/asymmetric-subtype.h>
15+
#include <linux/asn1.h>
16+
#include <linux/err.h>
1317
#include <linux/kernel.h>
14-
#include <linux/slab.h>
18+
#include <linux/module.h>
1519
#include <linux/seq_file.h>
16-
#include <linux/scatterlist.h>
17-
#include <linux/asn1.h>
18-
#include <keys/asymmetric-subtype.h>
19-
#include <crypto/public_key.h>
20-
#include <crypto/akcipher.h>
20+
#include <linux/slab.h>
21+
#include <linux/string.h>
2122

2223
MODULE_DESCRIPTION("In-software asymmetric public-key subtype");
2324
MODULE_AUTHOR("Red Hat, Inc.");
@@ -65,10 +66,13 @@ static void public_key_destroy(void *payload0, void *payload3)
6566
static int
6667
software_key_determine_akcipher(const struct public_key *pkey,
6768
const char *encoding, const char *hash_algo,
68-
char alg_name[CRYPTO_MAX_ALG_NAME])
69+
char alg_name[CRYPTO_MAX_ALG_NAME], bool *sig,
70+
enum kernel_pkey_operation op)
6971
{
7072
int n;
7173

74+
*sig = true;
75+
7276
if (!encoding)
7377
return -EINVAL;
7478

@@ -77,14 +81,18 @@ software_key_determine_akcipher(const struct public_key *pkey,
7781
* RSA signatures usually use EMSA-PKCS1-1_5 [RFC3447 sec 8.2].
7882
*/
7983
if (strcmp(encoding, "pkcs1") == 0) {
80-
if (!hash_algo)
84+
if (!hash_algo) {
85+
*sig = false;
8186
n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
8287
"pkcs1pad(%s)",
8388
pkey->pkey_algo);
84-
else
89+
} else {
90+
*sig = op == kernel_pkey_sign ||
91+
op == kernel_pkey_verify;
8592
n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
8693
"pkcs1pad(%s,%s)",
8794
pkey->pkey_algo, hash_algo);
95+
}
8896
return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
8997
}
9098
if (strcmp(encoding, "raw") != 0)
@@ -95,6 +103,7 @@ software_key_determine_akcipher(const struct public_key *pkey,
95103
*/
96104
if (hash_algo)
97105
return -EINVAL;
106+
*sig = false;
98107
} else if (strncmp(pkey->pkey_algo, "ecdsa", 5) == 0) {
99108
if (strcmp(encoding, "x962") != 0)
100109
return -EINVAL;
@@ -152,37 +161,70 @@ static int software_key_query(const struct kernel_pkey_params *params,
152161
struct crypto_akcipher *tfm;
153162
struct public_key *pkey = params->key->payload.data[asym_crypto];
154163
char alg_name[CRYPTO_MAX_ALG_NAME];
164+
struct crypto_sig *sig;
155165
u8 *key, *ptr;
156166
int ret, len;
167+
bool issig;
157168

158169
ret = software_key_determine_akcipher(pkey, params->encoding,
159-
params->hash_algo, alg_name);
170+
params->hash_algo, alg_name,
171+
&issig, kernel_pkey_sign);
160172
if (ret < 0)
161173
return ret;
162174

163-
tfm = crypto_alloc_akcipher(alg_name, 0, 0);
164-
if (IS_ERR(tfm))
165-
return PTR_ERR(tfm);
166-
167-
ret = -ENOMEM;
168175
key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
169176
GFP_KERNEL);
170177
if (!key)
171-
goto error_free_tfm;
178+
return -ENOMEM;
179+
172180
memcpy(key, pkey->key, pkey->keylen);
173181
ptr = key + pkey->keylen;
174182
ptr = pkey_pack_u32(ptr, pkey->algo);
175183
ptr = pkey_pack_u32(ptr, pkey->paramlen);
176184
memcpy(ptr, pkey->params, pkey->paramlen);
177185

178-
if (pkey->key_is_private)
179-
ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
180-
else
181-
ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen);
182-
if (ret < 0)
183-
goto error_free_key;
186+
if (issig) {
187+
sig = crypto_alloc_sig(alg_name, 0, 0);
188+
if (IS_ERR(sig))
189+
goto error_free_key;
190+
191+
if (pkey->key_is_private)
192+
ret = crypto_sig_set_privkey(sig, key, pkey->keylen);
193+
else
194+
ret = crypto_sig_set_pubkey(sig, key, pkey->keylen);
195+
if (ret < 0)
196+
goto error_free_tfm;
197+
198+
len = crypto_sig_maxsize(sig);
199+
200+
info->supported_ops = KEYCTL_SUPPORTS_VERIFY;
201+
if (pkey->key_is_private)
202+
info->supported_ops |= KEYCTL_SUPPORTS_SIGN;
203+
204+
if (strcmp(params->encoding, "pkcs1") == 0) {
205+
info->supported_ops |= KEYCTL_SUPPORTS_ENCRYPT;
206+
if (pkey->key_is_private)
207+
info->supported_ops |= KEYCTL_SUPPORTS_DECRYPT;
208+
}
209+
} else {
210+
tfm = crypto_alloc_akcipher(alg_name, 0, 0);
211+
if (IS_ERR(tfm))
212+
goto error_free_key;
213+
214+
if (pkey->key_is_private)
215+
ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
216+
else
217+
ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen);
218+
if (ret < 0)
219+
goto error_free_tfm;
220+
221+
len = crypto_akcipher_maxsize(tfm);
222+
223+
info->supported_ops = KEYCTL_SUPPORTS_ENCRYPT;
224+
if (pkey->key_is_private)
225+
info->supported_ops |= KEYCTL_SUPPORTS_DECRYPT;
226+
}
184227

185-
len = crypto_akcipher_maxsize(tfm);
186228
info->key_size = len * 8;
187229

188230
if (strncmp(pkey->pkey_algo, "ecdsa", 5) == 0) {
@@ -208,17 +250,16 @@ static int software_key_query(const struct kernel_pkey_params *params,
208250

209251
info->max_enc_size = len;
210252
info->max_dec_size = len;
211-
info->supported_ops = (KEYCTL_SUPPORTS_ENCRYPT |
212-
KEYCTL_SUPPORTS_VERIFY);
213-
if (pkey->key_is_private)
214-
info->supported_ops |= (KEYCTL_SUPPORTS_DECRYPT |
215-
KEYCTL_SUPPORTS_SIGN);
253+
216254
ret = 0;
217255

256+
error_free_tfm:
257+
if (issig)
258+
crypto_free_sig(sig);
259+
else
260+
crypto_free_akcipher(tfm);
218261
error_free_key:
219262
kfree(key);
220-
error_free_tfm:
221-
crypto_free_akcipher(tfm);
222263
pr_devel("<==%s() = %d\n", __func__, ret);
223264
return ret;
224265
}
@@ -230,82 +271,97 @@ static int software_key_eds_op(struct kernel_pkey_params *params,
230271
const void *in, void *out)
231272
{
232273
const struct public_key *pkey = params->key->payload.data[asym_crypto];
233-
struct akcipher_request *req;
234-
struct crypto_akcipher *tfm;
235-
struct crypto_wait cwait;
236-
struct scatterlist in_sg, out_sg;
237274
char alg_name[CRYPTO_MAX_ALG_NAME];
275+
struct crypto_akcipher *tfm;
276+
struct crypto_sig *sig;
238277
char *key, *ptr;
278+
bool issig;
279+
int ksz;
239280
int ret;
240281

241282
pr_devel("==>%s()\n", __func__);
242283

243284
ret = software_key_determine_akcipher(pkey, params->encoding,
244-
params->hash_algo, alg_name);
285+
params->hash_algo, alg_name,
286+
&issig, params->op);
245287
if (ret < 0)
246288
return ret;
247289

248-
tfm = crypto_alloc_akcipher(alg_name, 0, 0);
249-
if (IS_ERR(tfm))
250-
return PTR_ERR(tfm);
251-
252-
ret = -ENOMEM;
253-
req = akcipher_request_alloc(tfm, GFP_KERNEL);
254-
if (!req)
255-
goto error_free_tfm;
256-
257290
key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
258291
GFP_KERNEL);
259292
if (!key)
260-
goto error_free_req;
293+
return -ENOMEM;
261294

262295
memcpy(key, pkey->key, pkey->keylen);
263296
ptr = key + pkey->keylen;
264297
ptr = pkey_pack_u32(ptr, pkey->algo);
265298
ptr = pkey_pack_u32(ptr, pkey->paramlen);
266299
memcpy(ptr, pkey->params, pkey->paramlen);
267300

268-
if (pkey->key_is_private)
269-
ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
270-
else
271-
ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen);
272-
if (ret)
273-
goto error_free_key;
301+
if (issig) {
302+
sig = crypto_alloc_sig(alg_name, 0, 0);
303+
if (IS_ERR(sig))
304+
goto error_free_key;
305+
306+
if (pkey->key_is_private)
307+
ret = crypto_sig_set_privkey(sig, key, pkey->keylen);
308+
else
309+
ret = crypto_sig_set_pubkey(sig, key, pkey->keylen);
310+
if (ret)
311+
goto error_free_tfm;
312+
313+
ksz = crypto_sig_maxsize(sig);
314+
} else {
315+
tfm = crypto_alloc_akcipher(alg_name, 0, 0);
316+
if (IS_ERR(tfm))
317+
goto error_free_key;
318+
319+
if (pkey->key_is_private)
320+
ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
321+
else
322+
ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen);
323+
if (ret)
324+
goto error_free_tfm;
325+
326+
ksz = crypto_akcipher_maxsize(tfm);
327+
}
274328

275-
sg_init_one(&in_sg, in, params->in_len);
276-
sg_init_one(&out_sg, out, params->out_len);
277-
akcipher_request_set_crypt(req, &in_sg, &out_sg, params->in_len,
278-
params->out_len);
279-
crypto_init_wait(&cwait);
280-
akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
281-
CRYPTO_TFM_REQ_MAY_SLEEP,
282-
crypto_req_done, &cwait);
329+
ret = -EINVAL;
283330

284331
/* Perform the encryption calculation. */
285332
switch (params->op) {
286333
case kernel_pkey_encrypt:
287-
ret = crypto_akcipher_encrypt(req);
334+
if (issig)
335+
break;
336+
ret = crypto_akcipher_sync_encrypt(tfm, in, params->in_len,
337+
out, params->out_len);
288338
break;
289339
case kernel_pkey_decrypt:
290-
ret = crypto_akcipher_decrypt(req);
340+
if (issig)
341+
break;
342+
ret = crypto_akcipher_sync_decrypt(tfm, in, params->in_len,
343+
out, params->out_len);
291344
break;
292345
case kernel_pkey_sign:
293-
ret = crypto_akcipher_sign(req);
346+
if (!issig)
347+
break;
348+
ret = crypto_sig_sign(sig, in, params->in_len,
349+
out, params->out_len);
294350
break;
295351
default:
296352
BUG();
297353
}
298354

299-
ret = crypto_wait_req(ret, &cwait);
300355
if (ret == 0)
301-
ret = req->dst_len;
356+
ret = ksz;
302357

358+
error_free_tfm:
359+
if (issig)
360+
crypto_free_sig(sig);
361+
else
362+
crypto_free_akcipher(tfm);
303363
error_free_key:
304364
kfree(key);
305-
error_free_req:
306-
akcipher_request_free(req);
307-
error_free_tfm:
308-
crypto_free_akcipher(tfm);
309365
pr_devel("<==%s() = %d\n", __func__, ret);
310366
return ret;
311367
}
@@ -316,12 +372,10 @@ static int software_key_eds_op(struct kernel_pkey_params *params,
316372
int public_key_verify_signature(const struct public_key *pkey,
317373
const struct public_key_signature *sig)
318374
{
319-
struct crypto_wait cwait;
320-
struct crypto_akcipher *tfm;
321-
struct akcipher_request *req;
322-
struct scatterlist src_sg[2];
323375
char alg_name[CRYPTO_MAX_ALG_NAME];
376+
struct crypto_sig *tfm;
324377
char *key, *ptr;
378+
bool issig;
325379
int ret;
326380

327381
pr_devel("==>%s()\n", __func__);
@@ -346,23 +400,19 @@ int public_key_verify_signature(const struct public_key *pkey,
346400
}
347401

348402
ret = software_key_determine_akcipher(pkey, sig->encoding,
349-
sig->hash_algo, alg_name);
403+
sig->hash_algo, alg_name,
404+
&issig, kernel_pkey_verify);
350405
if (ret < 0)
351406
return ret;
352407

353-
tfm = crypto_alloc_akcipher(alg_name, 0, 0);
408+
tfm = crypto_alloc_sig(alg_name, 0, 0);
354409
if (IS_ERR(tfm))
355410
return PTR_ERR(tfm);
356411

357-
ret = -ENOMEM;
358-
req = akcipher_request_alloc(tfm, GFP_KERNEL);
359-
if (!req)
360-
goto error_free_tfm;
361-
362412
key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
363413
GFP_KERNEL);
364414
if (!key)
365-
goto error_free_req;
415+
goto error_free_tfm;
366416

367417
memcpy(key, pkey->key, pkey->keylen);
368418
ptr = key + pkey->keylen;
@@ -371,29 +421,19 @@ int public_key_verify_signature(const struct public_key *pkey,
371421
memcpy(ptr, pkey->params, pkey->paramlen);
372422

373423
if (pkey->key_is_private)
374-
ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
424+
ret = crypto_sig_set_privkey(tfm, key, pkey->keylen);
375425
else
376-
ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen);
426+
ret = crypto_sig_set_pubkey(tfm, key, pkey->keylen);
377427
if (ret)
378428
goto error_free_key;
379429

380-
sg_init_table(src_sg, 2);
381-
sg_set_buf(&src_sg[0], sig->s, sig->s_size);
382-
sg_set_buf(&src_sg[1], sig->digest, sig->digest_size);
383-
akcipher_request_set_crypt(req, src_sg, NULL, sig->s_size,
384-
sig->digest_size);
385-
crypto_init_wait(&cwait);
386-
akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
387-
CRYPTO_TFM_REQ_MAY_SLEEP,
388-
crypto_req_done, &cwait);
389-
ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait);
430+
ret = crypto_sig_verify(tfm, sig->s, sig->s_size,
431+
sig->digest, sig->digest_size);
390432

391433
error_free_key:
392434
kfree(key);
393-
error_free_req:
394-
akcipher_request_free(req);
395435
error_free_tfm:
396-
crypto_free_akcipher(tfm);
436+
crypto_free_sig(tfm);
397437
pr_devel("<==%s() = %d\n", __func__, ret);
398438
if (WARN_ON_ONCE(ret > 0))
399439
ret = -EINVAL;

0 commit comments

Comments
 (0)