Skip to content

Commit

Permalink
Merge tag 'asym-keys-fix-for-linus-v6.4-rc5' of https://github.com/ro…
Browse files Browse the repository at this point in the history
…bertosassu/linux

Pull asymmetric keys fix from Roberto Sassu:
 "Here is a small fix to make an unconditional copy of the buffer passed
  to crypto operations, to take into account the case of the stack not
  in the linear mapping area.

  It has been tested and verified to fix the bug"

Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Acked-by: David Howells <dhowells@redhat.com>

* tag 'asym-keys-fix-for-linus-v6.4-rc5' of https://github.com/robertosassu/linux:
  KEYS: asymmetric: Copy sig and digest in public_key_verify_signature()
  • Loading branch information
Linus Torvalds committed Jun 5, 2023
2 parents 9561de3 + c3d03e8 commit f8dba31
Showing 1 changed file with 21 additions and 17 deletions.
38 changes: 21 additions & 17 deletions crypto/asymmetric_keys/public_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,10 @@ int public_key_verify_signature(const struct public_key *pkey,
struct crypto_wait cwait;
struct crypto_akcipher *tfm;
struct akcipher_request *req;
struct scatterlist src_sg[2];
struct scatterlist src_sg;
char alg_name[CRYPTO_MAX_ALG_NAME];
char *key, *ptr;
char *buf, *ptr;
size_t buf_len;
int ret;

pr_devel("==>%s()\n", __func__);
Expand Down Expand Up @@ -420,43 +421,46 @@ int public_key_verify_signature(const struct public_key *pkey,
if (!req)
goto error_free_tfm;

key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
GFP_KERNEL);
if (!key)
buf_len = max_t(size_t, pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
sig->s_size + sig->digest_size);

buf = kmalloc(buf_len, GFP_KERNEL);
if (!buf)
goto error_free_req;

memcpy(key, pkey->key, pkey->keylen);
ptr = key + pkey->keylen;
memcpy(buf, pkey->key, pkey->keylen);
ptr = buf + pkey->keylen;
ptr = pkey_pack_u32(ptr, pkey->algo);
ptr = pkey_pack_u32(ptr, pkey->paramlen);
memcpy(ptr, pkey->params, pkey->paramlen);

if (pkey->key_is_private)
ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
ret = crypto_akcipher_set_priv_key(tfm, buf, pkey->keylen);
else
ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen);
ret = crypto_akcipher_set_pub_key(tfm, buf, pkey->keylen);
if (ret)
goto error_free_key;
goto error_free_buf;

if (strcmp(pkey->pkey_algo, "sm2") == 0 && sig->data_size) {
ret = cert_sig_digest_update(sig, tfm);
if (ret)
goto error_free_key;
goto error_free_buf;
}

sg_init_table(src_sg, 2);
sg_set_buf(&src_sg[0], sig->s, sig->s_size);
sg_set_buf(&src_sg[1], sig->digest, sig->digest_size);
akcipher_request_set_crypt(req, src_sg, NULL, sig->s_size,
memcpy(buf, sig->s, sig->s_size);
memcpy(buf + sig->s_size, sig->digest, sig->digest_size);

sg_init_one(&src_sg, buf, sig->s_size + sig->digest_size);
akcipher_request_set_crypt(req, &src_sg, NULL, sig->s_size,
sig->digest_size);
crypto_init_wait(&cwait);
akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
CRYPTO_TFM_REQ_MAY_SLEEP,
crypto_req_done, &cwait);
ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait);

error_free_key:
kfree(key);
error_free_buf:
kfree(buf);
error_free_req:
akcipher_request_free(req);
error_free_tfm:
Expand Down

0 comments on commit f8dba31

Please sign in to comment.