diff options
Diffstat (limited to 'lib/digsig.c')
| -rw-r--r-- | lib/digsig.c | 93 |
1 files changed, 34 insertions, 59 deletions
diff --git a/lib/digsig.c b/lib/digsig.c index 2f31e6a45f0a..9dd319c12c7d 100644 --- a/lib/digsig.c +++ b/lib/digsig.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2011 Nokia Corporation * Copyright (C) 2011 Intel Corporation @@ -6,10 +7,6 @@ * Dmitry Kasatkin <dmitry.kasatkin@nokia.com> * <dmitry.kasatkin@intel.com> * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2 of the License. - * * File: sign.c * implements signature (RSA) verification * pkcs decoding is based on LibTomCrypt code @@ -21,15 +18,11 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/key.h> -#include <linux/crypto.h> -#include <crypto/hash.h> -#include <crypto/sha.h> +#include <crypto/sha1.h> #include <keys/user-type.h> #include <linux/mpi.h> #include <linux/digsig.h> -static struct crypto_shash *shash; - static const char *pkcs_1_v1_5_decode_emsa(const unsigned char *msg, unsigned long msglen, unsigned long modulus_bitlen, @@ -79,12 +72,19 @@ static int digsig_verify_rsa(struct key *key, unsigned char *out1 = NULL; const char *m; MPI in = NULL, res = NULL, pkey[2]; - uint8_t *p, *datap, *endp; - struct user_key_payload *ukp; + uint8_t *p, *datap; + const uint8_t *endp; + const struct user_key_payload *ukp; struct pubkey_hdr *pkh; down_read(&key->sem); - ukp = key->payload.data; + ukp = user_key_payload_locked(key); + + if (!ukp) { + /* key was revoked before we acquired its semaphore */ + err = -EKEYREVOKED; + goto err1; + } if (ukp->datalen < sizeof(*pkh)) goto err1; @@ -103,21 +103,25 @@ static int digsig_verify_rsa(struct key *key, datap = pkh->mpi; endp = ukp->data + ukp->datalen; - err = -ENOMEM; - for (i = 0; i < pkh->nmpi; i++) { unsigned int remaining = endp - datap; pkey[i] = mpi_read_from_buffer(datap, &remaining); - if (!pkey[i]) + if (IS_ERR(pkey[i])) { + err = PTR_ERR(pkey[i]); goto err; + } datap += remaining; } mblen = mpi_get_nbits(pkey[0]); mlen = DIV_ROUND_UP(mblen, 8); - if (mlen == 0) + if (mlen == 0) { + err = -EINVAL; goto err; + } + + err = -ENOMEM; out1 = kzalloc(mlen, GFP_KERNEL); if (!out1) @@ -125,8 +129,10 @@ static int digsig_verify_rsa(struct key *key, nret = siglen; in = mpi_read_from_buffer(sig, &nret); - if (!in) + if (IS_ERR(in)) { + err = PTR_ERR(in); goto err; + } res = mpi_alloc(mpi_get_nlimbs(in) * 2); if (!res) @@ -149,7 +155,6 @@ static int digsig_verify_rsa(struct key *key, len = mlen; head = len - l; - memset(out1, 0, head); memcpy(out1 + head, p, l); kfree(p); @@ -175,10 +180,11 @@ err1: * digsig_verify() - digital signature verification with public key * @keyring: keyring to search key in * @sig: digital signature - * @sigen: length of the signature + * @siglen: length of the signature * @data: data * @datalen: length of the data - * @return: 0 on success, -EINVAL otherwise + * + * Returns 0 on success, -EINVAL otherwise * * Verifies data integrity against digital signature. * Currently only RSA is supported. @@ -188,12 +194,12 @@ err1: int digsig_verify(struct key *keyring, const char *sig, int siglen, const char *data, int datalen) { - int err = -ENOMEM; struct signature_hdr *sh = (struct signature_hdr *)sig; - struct shash_desc *desc = NULL; + struct sha1_ctx ctx; unsigned char hash[SHA1_DIGEST_SIZE]; struct key *key; char name[20]; + int err; if (siglen < sizeof(*sh) + 2) return -EINVAL; @@ -207,9 +213,9 @@ int digsig_verify(struct key *keyring, const char *sig, int siglen, /* search in specific keyring */ key_ref_t kref; kref = keyring_search(make_key_ref(keyring, 1UL), - &key_type_user, name); + &key_type_user, name, true); if (IS_ERR(kref)) - key = ERR_PTR(PTR_ERR(kref)); + key = ERR_CAST(kref); else key = key_ref_to_ptr(kref); } else { @@ -220,50 +226,19 @@ int digsig_verify(struct key *keyring, const char *sig, int siglen, return PTR_ERR(key); } - desc = kzalloc(sizeof(*desc) + crypto_shash_descsize(shash), - GFP_KERNEL); - if (!desc) - goto err; - - desc->tfm = shash; - desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; - - crypto_shash_init(desc); - crypto_shash_update(desc, data, datalen); - crypto_shash_update(desc, sig, sizeof(*sh)); - crypto_shash_final(desc, hash); - - kfree(desc); + sha1_init(&ctx); + sha1_update(&ctx, data, datalen); + sha1_update(&ctx, sig, sizeof(*sh)); + sha1_final(&ctx, hash); /* pass signature mpis address */ err = digsig_verify_rsa(key, sig + sizeof(*sh), siglen - sizeof(*sh), hash, sizeof(hash)); -err: key_put(key); return err ? -EINVAL : 0; } EXPORT_SYMBOL_GPL(digsig_verify); -static int __init digsig_init(void) -{ - shash = crypto_alloc_shash("sha1", 0, 0); - if (IS_ERR(shash)) { - pr_err("shash allocation failed\n"); - return PTR_ERR(shash); - } - - return 0; - -} - -static void __exit digsig_cleanup(void) -{ - crypto_free_shash(shash); -} - -module_init(digsig_init); -module_exit(digsig_cleanup); - MODULE_LICENSE("GPL"); |
