diff options
author | David Howells <dhowells@redhat.com> | 2016-04-06 17:13:33 +0200 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2016-04-06 17:13:33 +0200 |
commit | 77d0910d153a7946df17cc15d3f423e534345f65 (patch) | |
tree | 2b32d94de42a5a2003b5bd5966e3e73f78d04934 /crypto/asymmetric_keys/x509_public_key.c | |
parent | KEYS: Add identifier pointers to public_key_signature struct (diff) | |
download | linux-77d0910d153a7946df17cc15d3f423e534345f65.tar.xz linux-77d0910d153a7946df17cc15d3f423e534345f65.zip |
X.509: Retain the key verification data
Retain the key verification data (ie. the struct public_key_signature)
including the digest and the key identifiers.
Note that this means that we need to take a separate copy of the digest in
x509_get_sig_params() rather than lumping it in with the crypto layer data.
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'crypto/asymmetric_keys/x509_public_key.c')
-rw-r--r-- | crypto/asymmetric_keys/x509_public_key.c | 61 |
1 files changed, 31 insertions, 30 deletions
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 2fcf707fb208..4cd102de174c 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -153,30 +153,29 @@ EXPORT_SYMBOL_GPL(x509_request_asymmetric_key); */ int x509_get_sig_params(struct x509_certificate *cert) { + struct public_key_signature *sig = cert->sig; struct crypto_shash *tfm; struct shash_desc *desc; - size_t digest_size, desc_size; - void *digest; + size_t desc_size; int ret; pr_devel("==>%s()\n", __func__); if (cert->unsupported_crypto) return -ENOPKG; - if (cert->sig.s) + if (sig->s) return 0; - cert->sig.s = kmemdup(cert->raw_sig, cert->raw_sig_size, - GFP_KERNEL); - if (!cert->sig.s) + sig->s = kmemdup(cert->raw_sig, cert->raw_sig_size, GFP_KERNEL); + if (!sig->s) return -ENOMEM; - cert->sig.s_size = cert->raw_sig_size; + sig->s_size = cert->raw_sig_size; /* Allocate the hashing algorithm we're going to need and find out how * big the hash operational data will be. */ - tfm = crypto_alloc_shash(cert->sig.hash_algo, 0, 0); + tfm = crypto_alloc_shash(sig->hash_algo, 0, 0); if (IS_ERR(tfm)) { if (PTR_ERR(tfm) == -ENOENT) { cert->unsupported_crypto = true; @@ -186,29 +185,28 @@ int x509_get_sig_params(struct x509_certificate *cert) } desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); - digest_size = crypto_shash_digestsize(tfm); + sig->digest_size = crypto_shash_digestsize(tfm); - /* We allocate the hash operational data storage on the end of the - * digest storage space. - */ ret = -ENOMEM; - digest = kzalloc(ALIGN(digest_size, __alignof__(*desc)) + desc_size, - GFP_KERNEL); - if (!digest) + sig->digest = kmalloc(sig->digest_size, GFP_KERNEL); + if (!sig->digest) goto error; - cert->sig.digest = digest; - cert->sig.digest_size = digest_size; + desc = kzalloc(desc_size, GFP_KERNEL); + if (!desc) + goto error; - desc = PTR_ALIGN(digest + digest_size, __alignof__(*desc)); desc->tfm = tfm; desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; ret = crypto_shash_init(desc); if (ret < 0) - goto error; + goto error_2; might_sleep(); - ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, digest); + ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); + +error_2: + kfree(desc); error: crypto_free_shash(tfm); pr_devel("<==%s() = %d\n", __func__, ret); @@ -230,7 +228,7 @@ int x509_check_signature(const struct public_key *pub, if (ret < 0) return ret; - ret = public_key_verify_signature(pub, &cert->sig); + ret = public_key_verify_signature(pub, cert->sig); if (ret == -ENOPKG) cert->unsupported_crypto = true; pr_debug("Cert Verification: %d\n", ret); @@ -250,17 +248,18 @@ EXPORT_SYMBOL_GPL(x509_check_signature); static int x509_validate_trust(struct x509_certificate *cert, struct key *trust_keyring) { + struct public_key_signature *sig = cert->sig; struct key *key; int ret = 1; if (!trust_keyring) return -EOPNOTSUPP; - if (ca_keyid && !asymmetric_key_id_partial(cert->akid_skid, ca_keyid)) + if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid)) return -EPERM; key = x509_request_asymmetric_key(trust_keyring, - cert->akid_id, cert->akid_skid, + sig->auth_ids[0], sig->auth_ids[1], false); if (!IS_ERR(key)) { if (!use_builtin_keys @@ -292,8 +291,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) pr_devel("Cert Subject: %s\n", cert->subject); if (!cert->pub->pkey_algo || - !cert->sig.pkey_algo || - !cert->sig.hash_algo) { + !cert->sig->pkey_algo || + !cert->sig->hash_algo) { ret = -ENOPKG; goto error_free_cert; } @@ -301,15 +300,15 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo); pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to); pr_devel("Cert Signature: %s + %s\n", - cert->sig.pkey_algo, - cert->sig.hash_algo); + cert->sig->pkey_algo, + cert->sig->hash_algo); cert->pub->id_type = "X509"; /* Check the signature on the key if it appears to be self-signed */ - if ((!cert->akid_skid && !cert->akid_id) || - asymmetric_key_id_same(cert->skid, cert->akid_skid) || - asymmetric_key_id_same(cert->id, cert->akid_id)) { + if ((!cert->sig->auth_ids[0] && !cert->sig->auth_ids[1]) || + asymmetric_key_id_same(cert->skid, cert->sig->auth_ids[1]) || + asymmetric_key_id_same(cert->id, cert->sig->auth_ids[0])) { ret = x509_check_signature(cert->pub, cert); /* self-signed */ if (ret < 0) goto error_free_cert; @@ -353,6 +352,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) prep->payload.data[asym_subtype] = &public_key_subtype; prep->payload.data[asym_key_ids] = kids; prep->payload.data[asym_crypto] = cert->pub; + prep->payload.data[asym_auth] = cert->sig; prep->description = desc; prep->quotalen = 100; @@ -360,6 +360,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) cert->pub = NULL; cert->id = NULL; cert->skid = NULL; + cert->sig = NULL; desc = NULL; ret = 0; |