Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: rsa-pkcs1pad - Fix regression from leading zeros

As the software RSA implementation now produces fixed-length
output, we need to eliminate leading zeros in the calling code
instead.

This patch does just that for pkcs1pad signature verification.

Fixes: 9b45b7bba3d2 ("crypto: rsa - Generate fixed-length output")
Reported-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

+22 -16
+22 -16
crypto/rsa-pkcs1pad.c
··· 456 456 struct akcipher_instance *inst = akcipher_alg_instance(tfm); 457 457 struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst); 458 458 const struct rsa_asn1_template *digest_info = ictx->digest_info; 459 + unsigned int dst_len; 459 460 unsigned int pos; 460 - 461 - if (err == -EOVERFLOW) 462 - /* Decrypted value had no leading 0 byte */ 463 - err = -EINVAL; 461 + u8 *out_buf; 464 462 465 463 if (err) 466 464 goto done; 467 465 468 - if (req_ctx->child_req.dst_len != ctx->key_size - 1) { 469 - err = -EINVAL; 466 + err = -EINVAL; 467 + dst_len = req_ctx->child_req.dst_len; 468 + if (dst_len < ctx->key_size - 1) 470 469 goto done; 470 + 471 + out_buf = req_ctx->out_buf; 472 + if (dst_len == ctx->key_size) { 473 + if (out_buf[0] != 0x00) 474 + /* Decrypted value had no leading 0 byte */ 475 + goto done; 476 + 477 + dst_len--; 478 + out_buf++; 471 479 } 472 480 473 481 err = -EBADMSG; 474 - if (req_ctx->out_buf[0] != 0x01) 482 + if (out_buf[0] != 0x01) 475 483 goto done; 476 484 477 - for (pos = 1; pos < req_ctx->child_req.dst_len; pos++) 478 - if (req_ctx->out_buf[pos] != 0xff) 485 + for (pos = 1; pos < dst_len; pos++) 486 + if (out_buf[pos] != 0xff) 479 487 break; 480 488 481 - if (pos < 9 || pos == req_ctx->child_req.dst_len || 482 - req_ctx->out_buf[pos] != 0x00) 489 + if (pos < 9 || pos == dst_len || out_buf[pos] != 0x00) 483 490 goto done; 484 491 pos++; 485 492 486 - if (memcmp(req_ctx->out_buf + pos, digest_info->data, 487 - digest_info->size)) 493 + if (memcmp(out_buf + pos, digest_info->data, digest_info->size)) 488 494 goto done; 489 495 490 496 pos += digest_info->size; 491 497 492 498 err = 0; 493 499 494 - if (req->dst_len < req_ctx->child_req.dst_len - pos) 500 + if (req->dst_len < dst_len - pos) 495 501 err = -EOVERFLOW; 496 - req->dst_len = req_ctx->child_req.dst_len - pos; 502 + req->dst_len = dst_len - pos; 497 503 498 504 if (!err) 499 505 sg_copy_from_buffer(req->dst, 500 506 sg_nents_for_len(req->dst, req->dst_len), 501 - req_ctx->out_buf + pos, req->dst_len); 507 + out_buf + pos, req->dst_len); 502 508 done: 503 509 kzfree(req_ctx->out_buf); 504 510