summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVitaly Chikunov <vt@altlinux.org>2019-04-11 11:51:15 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2019-04-18 10:15:02 -0400
commitc7381b01287240abe942a081729203e26782d981 (patch)
treef70bd59c5b8b110b9116d1660d5fe03033ed3596
parent3ecc97259934489e7e03cbeb1d70f6a23cccb3ae (diff)
crypto: akcipher - new verify API for public key algorithms
Previous akcipher .verify() just `decrypts' (using RSA encrypt which is using public key) signature to uncover message hash, which was then compared in upper level public_key_verify_signature() with the expected hash value, which itself was never passed into verify(). This approach was incompatible with EC-DSA family of algorithms, because, to verify a signature EC-DSA algorithm also needs a hash value as input; then it's used (together with a signature divided into halves `r||s') to produce a witness value, which is then compared with `r' to determine if the signature is correct. Thus, for EC-DSA, nor requirements of .verify() itself, nor its output expectations in public_key_verify_signature() wasn't sufficient. Make improved .verify() call which gets hash value as input and produce complete signature check without any output besides status. Now for the top level verification only crypto_akcipher_verify() needs to be called and its return value inspected. Make sure that `digest' is in kmalloc'd memory (in place of `output`) in {public,tpm}_key_verify_signature() as insisted by Herbert Xu, and will be changed in the following commit. Cc: David Howells <dhowells@redhat.com> Cc: keyrings@vger.kernel.org Signed-off-by: Vitaly Chikunov <vt@altlinux.org> Reviewed-by: Denis Kenzior <denkenz@gmail.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--crypto/asymmetric_keys/asym_tpm.c34
-rw-r--r--crypto/asymmetric_keys/public_key.c34
-rw-r--r--crypto/rsa-pkcs1pad.c29
-rw-r--r--crypto/testmgr.c50
-rw-r--r--include/crypto/akcipher.h36
5 files changed, 92 insertions, 91 deletions
diff --git a/crypto/asymmetric_keys/asym_tpm.c b/crypto/asymmetric_keys/asym_tpm.c
index 5d4c270463f6..4e5b6fb57a94 100644
--- a/crypto/asymmetric_keys/asym_tpm.c
+++ b/crypto/asymmetric_keys/asym_tpm.c
@@ -744,12 +744,11 @@ static int tpm_key_verify_signature(const struct key *key,
744 struct crypto_wait cwait; 744 struct crypto_wait cwait;
745 struct crypto_akcipher *tfm; 745 struct crypto_akcipher *tfm;
746 struct akcipher_request *req; 746 struct akcipher_request *req;
747 struct scatterlist sig_sg, digest_sg; 747 struct scatterlist src_sg[2];
748 char alg_name[CRYPTO_MAX_ALG_NAME]; 748 char alg_name[CRYPTO_MAX_ALG_NAME];
749 uint8_t der_pub_key[PUB_KEY_BUF_SIZE]; 749 uint8_t der_pub_key[PUB_KEY_BUF_SIZE];
750 uint32_t der_pub_key_len; 750 uint32_t der_pub_key_len;
751 void *output; 751 void *digest;
752 unsigned int outlen;
753 int ret; 752 int ret;
754 753
755 pr_devel("==>%s()\n", __func__); 754 pr_devel("==>%s()\n", __func__);
@@ -782,35 +781,22 @@ static int tpm_key_verify_signature(const struct key *key,
782 goto error_free_tfm; 781 goto error_free_tfm;
783 782
784 ret = -ENOMEM; 783 ret = -ENOMEM;
785 outlen = crypto_akcipher_maxsize(tfm); 784 digest = kmemdup(sig->digest, sig->digest_size, GFP_KERNEL);
786 output = kmalloc(outlen, GFP_KERNEL); 785 if (!digest)
787 if (!output)
788 goto error_free_req; 786 goto error_free_req;
789 787
790 sg_init_one(&sig_sg, sig->s, sig->s_size); 788 sg_init_table(src_sg, 2);
791 sg_init_one(&digest_sg, output, outlen); 789 sg_set_buf(&src_sg[0], sig->s, sig->s_size);
792 akcipher_request_set_crypt(req, &sig_sg, &digest_sg, sig->s_size, 790 sg_set_buf(&src_sg[1], digest, sig->digest_size);
793 outlen); 791 akcipher_request_set_crypt(req, src_sg, NULL, sig->s_size,
792 sig->digest_size);
794 crypto_init_wait(&cwait); 793 crypto_init_wait(&cwait);
795 akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | 794 akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
796 CRYPTO_TFM_REQ_MAY_SLEEP, 795 CRYPTO_TFM_REQ_MAY_SLEEP,
797 crypto_req_done, &cwait); 796 crypto_req_done, &cwait);
798
799 /* Perform the verification calculation. This doesn't actually do the
800 * verification, but rather calculates the hash expected by the
801 * signature and returns that to us.
802 */
803 ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait); 797 ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait);
804 if (ret)
805 goto out_free_output;
806
807 /* Do the actual verification step. */
808 if (req->dst_len != sig->digest_size ||
809 memcmp(sig->digest, output, sig->digest_size) != 0)
810 ret = -EKEYREJECTED;
811 798
812out_free_output: 799 kfree(digest);
813 kfree(output);
814error_free_req: 800error_free_req:
815 akcipher_request_free(req); 801 akcipher_request_free(req);
816error_free_tfm: 802error_free_tfm:
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index f5d85b47fcc6..0c069fe8a59c 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -227,10 +227,9 @@ int public_key_verify_signature(const struct public_key *pkey,
227 struct crypto_wait cwait; 227 struct crypto_wait cwait;
228 struct crypto_akcipher *tfm; 228 struct crypto_akcipher *tfm;
229 struct akcipher_request *req; 229 struct akcipher_request *req;
230 struct scatterlist sig_sg, digest_sg; 230 struct scatterlist src_sg[2];
231 char alg_name[CRYPTO_MAX_ALG_NAME]; 231 char alg_name[CRYPTO_MAX_ALG_NAME];
232 void *output; 232 void *digest;
233 unsigned int outlen;
234 int ret; 233 int ret;
235 234
236 pr_devel("==>%s()\n", __func__); 235 pr_devel("==>%s()\n", __func__);
@@ -264,35 +263,22 @@ int public_key_verify_signature(const struct public_key *pkey,
264 goto error_free_req; 263 goto error_free_req;
265 264
266 ret = -ENOMEM; 265 ret = -ENOMEM;
267 outlen = crypto_akcipher_maxsize(tfm); 266 digest = kmemdup(sig->digest, sig->digest_size, GFP_KERNEL);
268 output = kmalloc(outlen, GFP_KERNEL); 267 if (!digest)
269 if (!output)
270 goto error_free_req; 268 goto error_free_req;
271 269
272 sg_init_one(&sig_sg, sig->s, sig->s_size); 270 sg_init_table(src_sg, 2);
273 sg_init_one(&digest_sg, output, outlen); 271 sg_set_buf(&src_sg[0], sig->s, sig->s_size);
274 akcipher_request_set_crypt(req, &sig_sg, &digest_sg, sig->s_size, 272 sg_set_buf(&src_sg[1], digest, sig->digest_size);
275 outlen); 273 akcipher_request_set_crypt(req, src_sg, NULL, sig->s_size,
274 sig->digest_size);
276 crypto_init_wait(&cwait); 275 crypto_init_wait(&cwait);
277 akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | 276 akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
278 CRYPTO_TFM_REQ_MAY_SLEEP, 277 CRYPTO_TFM_REQ_MAY_SLEEP,
279 crypto_req_done, &cwait); 278 crypto_req_done, &cwait);
280
281 /* Perform the verification calculation. This doesn't actually do the
282 * verification, but rather calculates the hash expected by the
283 * signature and returns that to us.
284 */
285 ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait); 279 ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait);
286 if (ret)
287 goto out_free_output;
288
289 /* Do the actual verification step. */
290 if (req->dst_len != sig->digest_size ||
291 memcmp(sig->digest, output, sig->digest_size) != 0)
292 ret = -EKEYREJECTED;
293 280
294out_free_output: 281 kfree(digest);
295 kfree(output);
296error_free_req: 282error_free_req:
297 akcipher_request_free(req); 283 akcipher_request_free(req);
298error_free_tfm: 284error_free_tfm:
diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index 94382fa2c6ac..29c336068dc0 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -488,14 +488,21 @@ static int pkcs1pad_verify_complete(struct akcipher_request *req, int err)
488 488
489 err = 0; 489 err = 0;
490 490
491 if (req->dst_len < dst_len - pos) 491 if (req->dst_len != dst_len - pos) {
492 err = -EOVERFLOW; 492 err = -EKEYREJECTED;
493 req->dst_len = dst_len - pos; 493 req->dst_len = dst_len - pos;
494 494 goto done;
495 if (!err) 495 }
496 sg_copy_from_buffer(req->dst, 496 /* Extract appended digest. */
497 sg_nents_for_len(req->dst, req->dst_len), 497 sg_pcopy_to_buffer(req->src,
498 out_buf + pos, req->dst_len); 498 sg_nents_for_len(req->src,
499 req->src_len + req->dst_len),
500 req_ctx->out_buf + ctx->key_size,
501 req->dst_len, ctx->key_size);
502 /* Do the actual verification step. */
503 if (memcmp(req_ctx->out_buf + ctx->key_size, out_buf + pos,
504 req->dst_len) != 0)
505 err = -EKEYREJECTED;
499done: 506done:
500 kzfree(req_ctx->out_buf); 507 kzfree(req_ctx->out_buf);
501 508
@@ -532,10 +539,12 @@ static int pkcs1pad_verify(struct akcipher_request *req)
532 struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req); 539 struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
533 int err; 540 int err;
534 541
535 if (!ctx->key_size || req->src_len < ctx->key_size) 542 if (WARN_ON(req->dst) ||
543 WARN_ON(!req->dst_len) ||
544 !ctx->key_size || req->src_len < ctx->key_size)
536 return -EINVAL; 545 return -EINVAL;
537 546
538 req_ctx->out_buf = kmalloc(ctx->key_size, GFP_KERNEL); 547 req_ctx->out_buf = kmalloc(ctx->key_size + req->dst_len, GFP_KERNEL);
539 if (!req_ctx->out_buf) 548 if (!req_ctx->out_buf)
540 return -ENOMEM; 549 return -ENOMEM;
541 550
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 0f6bfb6ce6a4..21b27996508a 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -2595,7 +2595,7 @@ static int test_akcipher_one(struct crypto_akcipher *tfm,
2595 struct crypto_wait wait; 2595 struct crypto_wait wait;
2596 unsigned int out_len_max, out_len = 0; 2596 unsigned int out_len_max, out_len = 0;
2597 int err = -ENOMEM; 2597 int err = -ENOMEM;
2598 struct scatterlist src, dst, src_tab[2]; 2598 struct scatterlist src, dst, src_tab[3];
2599 const char *m, *c; 2599 const char *m, *c;
2600 unsigned int m_size, c_size; 2600 unsigned int m_size, c_size;
2601 const char *op; 2601 const char *op;
@@ -2618,13 +2618,12 @@ static int test_akcipher_one(struct crypto_akcipher *tfm,
2618 if (err) 2618 if (err)
2619 goto free_req; 2619 goto free_req;
2620 2620
2621 err = -ENOMEM;
2622 out_len_max = crypto_akcipher_maxsize(tfm);
2623
2624 /* 2621 /*
2625 * First run test which do not require a private key, such as 2622 * First run test which do not require a private key, such as
2626 * encrypt or verify. 2623 * encrypt or verify.
2627 */ 2624 */
2625 err = -ENOMEM;
2626 out_len_max = crypto_akcipher_maxsize(tfm);
2628 outbuf_enc = kzalloc(out_len_max, GFP_KERNEL); 2627 outbuf_enc = kzalloc(out_len_max, GFP_KERNEL);
2629 if (!outbuf_enc) 2628 if (!outbuf_enc)
2630 goto free_req; 2629 goto free_req;
@@ -2650,12 +2649,20 @@ static int test_akcipher_one(struct crypto_akcipher *tfm,
2650 goto free_all; 2649 goto free_all;
2651 memcpy(xbuf[0], m, m_size); 2650 memcpy(xbuf[0], m, m_size);
2652 2651
2653 sg_init_table(src_tab, 2); 2652 sg_init_table(src_tab, 3);
2654 sg_set_buf(&src_tab[0], xbuf[0], 8); 2653 sg_set_buf(&src_tab[0], xbuf[0], 8);
2655 sg_set_buf(&src_tab[1], xbuf[0] + 8, m_size - 8); 2654 sg_set_buf(&src_tab[1], xbuf[0] + 8, m_size - 8);
2656 sg_init_one(&dst, outbuf_enc, out_len_max); 2655 if (vecs->siggen_sigver_test) {
2657 akcipher_request_set_crypt(req, src_tab, &dst, m_size, 2656 if (WARN_ON(c_size > PAGE_SIZE))
2658 out_len_max); 2657 goto free_all;
2658 memcpy(xbuf[1], c, c_size);
2659 sg_set_buf(&src_tab[2], xbuf[1], c_size);
2660 akcipher_request_set_crypt(req, src_tab, NULL, m_size, c_size);
2661 } else {
2662 sg_init_one(&dst, outbuf_enc, out_len_max);
2663 akcipher_request_set_crypt(req, src_tab, &dst, m_size,
2664 out_len_max);
2665 }
2659 akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 2666 akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
2660 crypto_req_done, &wait); 2667 crypto_req_done, &wait);
2661 2668
@@ -2668,18 +2675,21 @@ static int test_akcipher_one(struct crypto_akcipher *tfm,
2668 pr_err("alg: akcipher: %s test failed. err %d\n", op, err); 2675 pr_err("alg: akcipher: %s test failed. err %d\n", op, err);
2669 goto free_all; 2676 goto free_all;
2670 } 2677 }
2671 if (req->dst_len != c_size) { 2678 if (!vecs->siggen_sigver_test) {
2672 pr_err("alg: akcipher: %s test failed. Invalid output len\n", 2679 if (req->dst_len != c_size) {
2673 op); 2680 pr_err("alg: akcipher: %s test failed. Invalid output len\n",
2674 err = -EINVAL; 2681 op);
2675 goto free_all; 2682 err = -EINVAL;
2676 } 2683 goto free_all;
2677 /* verify that encrypted message is equal to expected */ 2684 }
2678 if (memcmp(c, outbuf_enc, c_size)) { 2685 /* verify that encrypted message is equal to expected */
2679 pr_err("alg: akcipher: %s test failed. Invalid output\n", op); 2686 if (memcmp(c, outbuf_enc, c_size) != 0) {
2680 hexdump(outbuf_enc, c_size); 2687 pr_err("alg: akcipher: %s test failed. Invalid output\n",
2681 err = -EINVAL; 2688 op);
2682 goto free_all; 2689 hexdump(outbuf_enc, c_size);
2690 err = -EINVAL;
2691 goto free_all;
2692 }
2683 } 2693 }
2684 2694
2685 /* 2695 /*
diff --git a/include/crypto/akcipher.h b/include/crypto/akcipher.h
index 2d690494568c..2d26939fff51 100644
--- a/include/crypto/akcipher.h
+++ b/include/crypto/akcipher.h
@@ -19,14 +19,20 @@
19 * 19 *
20 * @base: Common attributes for async crypto requests 20 * @base: Common attributes for async crypto requests
21 * @src: Source data 21 * @src: Source data
22 * @dst: Destination data 22 * For verify op this is signature + digest, in that case
23 * total size of @src is @src_len + @dst_len.
24 * @dst: Destination data (Should be NULL for verify op)
23 * @src_len: Size of the input buffer 25 * @src_len: Size of the input buffer
24 * @dst_len: Size of the output buffer. It needs to be at least 26 * For verify op it's size of signature part of @src, this part
25 * as big as the expected result depending on the operation 27 * is supposed to be operated by cipher.
28 * @dst_len: Size of @dst buffer (for all ops except verify).
29 * It needs to be at least as big as the expected result
30 * depending on the operation.
26 * After operation it will be updated with the actual size of the 31 * After operation it will be updated with the actual size of the
27 * result. 32 * result.
28 * In case of error where the dst sgl size was insufficient, 33 * In case of error where the dst sgl size was insufficient,
29 * it will be updated to the size required for the operation. 34 * it will be updated to the size required for the operation.
35 * For verify op this is size of digest part in @src.
30 * @__ctx: Start of private context data 36 * @__ctx: Start of private context data
31 */ 37 */
32struct akcipher_request { 38struct akcipher_request {
@@ -55,10 +61,9 @@ struct crypto_akcipher {
55 * algorithm. In case of error, where the dst_len was insufficient, 61 * algorithm. In case of error, where the dst_len was insufficient,
56 * the req->dst_len will be updated to the size required for the 62 * the req->dst_len will be updated to the size required for the
57 * operation 63 * operation
58 * @verify: Function performs a sign operation as defined by public key 64 * @verify: Function performs a complete verify operation as defined by
59 * algorithm. In case of error, where the dst_len was insufficient, 65 * public key algorithm, returning verification status. Requires
60 * the req->dst_len will be updated to the size required for the 66 * digest value as input parameter.
61 * operation
62 * @encrypt: Function performs an encrypt operation as defined by public key 67 * @encrypt: Function performs an encrypt operation as defined by public key
63 * algorithm. In case of error, where the dst_len was insufficient, 68 * algorithm. In case of error, where the dst_len was insufficient,
64 * the req->dst_len will be updated to the size required for the 69 * the req->dst_len will be updated to the size required for the
@@ -238,9 +243,10 @@ static inline void akcipher_request_set_callback(struct akcipher_request *req,
238 * 243 *
239 * @req: public key request 244 * @req: public key request
240 * @src: ptr to input scatter list 245 * @src: ptr to input scatter list
241 * @dst: ptr to output scatter list 246 * @dst: ptr to output scatter list or NULL for verify op
242 * @src_len: size of the src input scatter list to be processed 247 * @src_len: size of the src input scatter list to be processed
243 * @dst_len: size of the dst output scatter list 248 * @dst_len: size of the dst output scatter list or size of signature
249 * portion in @src for verify op
244 */ 250 */
245static inline void akcipher_request_set_crypt(struct akcipher_request *req, 251static inline void akcipher_request_set_crypt(struct akcipher_request *req,
246 struct scatterlist *src, 252 struct scatterlist *src,
@@ -343,14 +349,18 @@ static inline int crypto_akcipher_sign(struct akcipher_request *req)
343} 349}
344 350
345/** 351/**
346 * crypto_akcipher_verify() - Invoke public key verify operation 352 * crypto_akcipher_verify() - Invoke public key signature verification
347 * 353 *
348 * Function invokes the specific public key verify operation for a given 354 * Function invokes the specific public key signature verification operation
349 * public key algorithm 355 * for a given public key algorithm.
350 * 356 *
351 * @req: asymmetric key request 357 * @req: asymmetric key request
352 * 358 *
353 * Return: zero on success; error code in case of error 359 * Note: req->dst should be NULL, req->src should point to SG of size
360 * (req->src_size + req->dst_size), containing signature (of req->src_size
361 * length) with appended digest (of req->dst_size length).
362 *
363 * Return: zero on verification success; error code in case of error.
354 */ 364 */
355static inline int crypto_akcipher_verify(struct akcipher_request *req) 365static inline int crypto_akcipher_verify(struct akcipher_request *req)
356{ 366{