From b16a0209c34610f374d0714c8eeb6772e830f397 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 3 Apr 2017 16:07:25 +0100 Subject: X.509: Allow X.509 certs to be blacklisted Allow X.509 certs to be blacklisted based on their TBSCertificate hash. This is convenient since we have to determine this anyway to be able to check the signature on an X.509 certificate. This is also what UEFI uses in its blacklist. If a certificate built into the kernel is blacklisted, something like the following might then be seen during boot: X.509: Cert 123412341234c55c1dcc601ab8e172917706aa32fb5eaf826813547fdf02dd46 is blacklisted Problem loading in-kernel X.509 certificate (-129) where the hex string shown is the blacklisted hash. Signed-off-by: David Howells --- crypto/asymmetric_keys/x509_parser.h | 1 + crypto/asymmetric_keys/x509_public_key.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) (limited to 'crypto/asymmetric_keys') diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h index 05eef1c6..e373e748 100644 --- a/crypto/asymmetric_keys/x509_parser.h +++ b/crypto/asymmetric_keys/x509_parser.h @@ -42,6 +42,7 @@ struct x509_certificate { bool self_signed; /* T if self-signed (check unsupported_sig too) */ bool unsupported_key; /* T if key uses unsupported crypto */ bool unsupported_sig; /* T if signature uses unsupported crypto */ + bool blacklisted; }; /* diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index fb732296..eea71dc9 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -84,6 +84,16 @@ int x509_get_sig_params(struct x509_certificate *cert) goto error_2; might_sleep(); ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); + if (ret < 0) + goto error_2; + + ret = is_hash_blacklisted(sig->digest, sig->digest_size, "tbs"); + if (ret == -EKEYREJECTED) { + pr_err("Cert %*phN is blacklisted\n", + sig->digest_size, sig->digest); + cert->blacklisted = true; + ret = 0; + } error_2: kfree(desc); @@ -186,6 +196,11 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) cert->sig->pkey_algo, cert->sig->hash_algo); } + /* Don't permit addition of blacklisted keys */ + ret = -EKEYREJECTED; + if (cert->blacklisted) + goto error_free_cert; + /* Propose a description */ sulen = strlen(cert->subject); if (cert->raw_skid) { -- cgit v1.2.3 From f8e2a9fc05a28e5da43d19c4084c19a0d14679af Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 3 Apr 2017 16:07:25 +0100 Subject: PKCS#7: Handle blacklisted certificates PKCS#7: Handle certificates that are blacklisted when verifying the chain of trust on the signatures on a PKCS#7 message. Signed-off-by: David Howells --- crypto/asymmetric_keys/pkcs7_parser.h | 1 + crypto/asymmetric_keys/pkcs7_verify.c | 32 ++++++++++++++++++++++++-------- 2 files changed, 25 insertions(+), 8 deletions(-) (limited to 'crypto/asymmetric_keys') diff --git a/crypto/asymmetric_keys/pkcs7_parser.h b/crypto/asymmetric_keys/pkcs7_parser.h index f4e81074..ac341e19 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.h +++ b/crypto/asymmetric_keys/pkcs7_parser.h @@ -23,6 +23,7 @@ struct pkcs7_signed_info { struct x509_certificate *signer; /* Signing certificate (in msg->certs) */ unsigned index; bool unsupported_crypto; /* T if not usable due to missing crypto */ + bool blacklisted; /* Message digest - the digest of the Content Data (or NULL) */ const void *msgdigest; diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index 2ffd6976..2d93d9ec 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -190,6 +190,18 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, x509->subject, x509->raw_serial_size, x509->raw_serial); x509->seen = true; + + if (x509->blacklisted) { + /* If this cert is blacklisted, then mark everything + * that depends on this as blacklisted too. + */ + sinfo->blacklisted = true; + for (p = sinfo->signer; p != x509; p = p->signer) + p->blacklisted = true; + pr_debug("- blacklisted\n"); + return 0; + } + if (x509->unsupported_key) goto unsupported_crypto_in_x509; @@ -357,17 +369,19 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7, * * (*) -EBADMSG if some part of the message was invalid, or: * - * (*) -ENOPKG if none of the signature chains are verifiable because suitable - * crypto modules couldn't be found, or: + * (*) 0 if no signature chains were found to be blacklisted or to contain + * unsupported crypto, or: * - * (*) 0 if all the signature chains that don't incur -ENOPKG can be verified - * (note that a signature chain may be of zero length), or: + * (*) -EKEYREJECTED if a blacklisted key was encountered, or: + * + * (*) -ENOPKG if none of the signature chains are verifiable because suitable + * crypto modules couldn't be found. */ int pkcs7_verify(struct pkcs7_message *pkcs7, enum key_being_used_for usage) { struct pkcs7_signed_info *sinfo; - int enopkg = -ENOPKG; + int actual_ret = -ENOPKG; int ret; kenter(""); @@ -412,6 +426,8 @@ int pkcs7_verify(struct pkcs7_message *pkcs7, for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { ret = pkcs7_verify_one(pkcs7, sinfo); + if (sinfo->blacklisted && actual_ret == -ENOPKG) + actual_ret = -EKEYREJECTED; if (ret < 0) { if (ret == -ENOPKG) { sinfo->unsupported_crypto = true; @@ -420,11 +436,11 @@ int pkcs7_verify(struct pkcs7_message *pkcs7, kleave(" = %d", ret); return ret; } - enopkg = 0; + actual_ret = 0; } - kleave(" = %d", enopkg); - return enopkg; + kleave(" = %d", actual_ret); + return actual_ret; } EXPORT_SYMBOL_GPL(pkcs7_verify); -- cgit v1.2.3 From 8f35069f76d1cbd9fa83d80b0a80a431ee6e7db3 Mon Sep 17 00:00:00 2001 From: Mat Martineau Date: Tue, 30 Aug 2016 11:33:13 -0700 Subject: KEYS: Split role of the keyring pointer for keyring restrict functions The first argument to the restrict_link_func_t functions was a keyring pointer. These functions are called by the key subsystem with this argument set to the destination keyring, but restrict_link_by_signature expects a pointer to the relevant trusted keyring. Restrict functions may need something other than a single struct key pointer to allow or reject key linkage, so the data used to make that decision (such as the trust keyring) is moved to a new, fourth argument. The first argument is now always the destination keyring. Signed-off-by: Mat Martineau --- crypto/asymmetric_keys/restrict.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'crypto/asymmetric_keys') diff --git a/crypto/asymmetric_keys/restrict.c b/crypto/asymmetric_keys/restrict.c index 19d1afb9..a3afbf78 100644 --- a/crypto/asymmetric_keys/restrict.c +++ b/crypto/asymmetric_keys/restrict.c @@ -56,9 +56,10 @@ __setup("ca_keys=", ca_keys_setup); /** * restrict_link_by_signature - Restrict additions to a ring of public keys - * @trust_keyring: A ring of keys that can be used to vouch for the new cert. + * @dest_keyring: Keyring being linked to. * @type: The type of key being added. * @payload: The payload of the new key. + * @trust_keyring: A ring of keys that can be used to vouch for the new cert. * * Check the new certificate against the ones in the trust keyring. If one of * those is the signing key and validates the new certificate, then mark the @@ -69,9 +70,10 @@ __setup("ca_keys=", ca_keys_setup); * signature check fails or the key is blacklisted and some other error if * there is a matching certificate but the signature check cannot be performed. */ -int restrict_link_by_signature(struct key *trust_keyring, +int restrict_link_by_signature(struct key *dest_keyring, const struct key_type *type, - const union key_payload *payload) + const union key_payload *payload, + struct key *trust_keyring) { const struct public_key_signature *sig; struct key *key; -- cgit v1.2.3 From 19b15e919c65d5d76076c251c89d34d1227c6512 Mon Sep 17 00:00:00 2001 From: Mat Martineau Date: Fri, 6 May 2016 14:25:39 -0700 Subject: KEYS: Add a lookup_restriction function for the asymmetric key type Look up asymmetric keyring restriction information using the key-type lookup_restrict hook. Signed-off-by: Mat Martineau --- crypto/asymmetric_keys/asymmetric_type.c | 52 +++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 8 deletions(-) (limited to 'crypto/asymmetric_keys') diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c index 6600181d..2e3380d0 100644 --- a/crypto/asymmetric_keys/asymmetric_type.c +++ b/crypto/asymmetric_keys/asymmetric_type.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "asymmetric_keys.h" MODULE_LICENSE("GPL"); @@ -451,15 +452,50 @@ static void asymmetric_key_destroy(struct key *key) asymmetric_key_free_kids(kids); } +static struct key_restriction *asymmetric_restriction_alloc( + key_restrict_link_func_t check, + struct key *key) +{ + struct key_restriction *keyres = + kzalloc(sizeof(struct key_restriction), GFP_KERNEL); + + if (!keyres) + return ERR_PTR(-ENOMEM); + + keyres->check = check; + keyres->key = key; + keyres->keytype = &key_type_asymmetric; + + return keyres; +} + +/* + * look up keyring restrict functions for asymmetric keys + */ +static struct key_restriction *asymmetric_lookup_restriction( + const char *restriction) +{ + if (strcmp("builtin_trusted", restriction) == 0) + return asymmetric_restriction_alloc( + restrict_link_by_builtin_trusted, NULL); + + if (strcmp("builtin_and_secondary_trusted", restriction) == 0) + return asymmetric_restriction_alloc( + restrict_link_by_builtin_and_secondary_trusted, NULL); + + return ERR_PTR(-EINVAL); +} + struct key_type key_type_asymmetric = { - .name = "asymmetric", - .preparse = asymmetric_key_preparse, - .free_preparse = asymmetric_key_free_preparse, - .instantiate = generic_key_instantiate, - .match_preparse = asymmetric_key_match_preparse, - .match_free = asymmetric_key_match_free, - .destroy = asymmetric_key_destroy, - .describe = asymmetric_key_describe, + .name = "asymmetric", + .preparse = asymmetric_key_preparse, + .free_preparse = asymmetric_key_free_preparse, + .instantiate = generic_key_instantiate, + .match_preparse = asymmetric_key_match_preparse, + .match_free = asymmetric_key_match_free, + .destroy = asymmetric_key_destroy, + .describe = asymmetric_key_describe, + .lookup_restriction = asymmetric_lookup_restriction, }; EXPORT_SYMBOL_GPL(key_type_asymmetric); -- cgit v1.2.3 From 53b7a22cac5cf5144c1300bc033c23cf47930cf7 Mon Sep 17 00:00:00 2001 From: Mat Martineau Date: Mon, 27 Jun 2016 16:45:16 -0700 Subject: KEYS: Restrict asymmetric key linkage using a specific keychain Adds restrict_link_by_signature_keyring(), which uses the restrict_key member of the provided destination_keyring data structure as the key or keyring to search for signing keys. Signed-off-by: Mat Martineau --- crypto/asymmetric_keys/asymmetric_type.c | 35 +++++++++++++++- crypto/asymmetric_keys/restrict.c | 71 ++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) (limited to 'crypto/asymmetric_keys') diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c index 2e3380d0..72700ed8 100644 --- a/crypto/asymmetric_keys/asymmetric_type.c +++ b/crypto/asymmetric_keys/asymmetric_type.c @@ -475,6 +475,11 @@ static struct key_restriction *asymmetric_restriction_alloc( static struct key_restriction *asymmetric_lookup_restriction( const char *restriction) { + char *restrict_method; + char *parse_buf; + char *next; + struct key_restriction *ret = ERR_PTR(-EINVAL); + if (strcmp("builtin_trusted", restriction) == 0) return asymmetric_restriction_alloc( restrict_link_by_builtin_trusted, NULL); @@ -483,7 +488,35 @@ static struct key_restriction *asymmetric_lookup_restriction( return asymmetric_restriction_alloc( restrict_link_by_builtin_and_secondary_trusted, NULL); - return ERR_PTR(-EINVAL); + parse_buf = kstrndup(restriction, PAGE_SIZE, GFP_KERNEL); + if (!parse_buf) + return ERR_PTR(-ENOMEM); + + next = parse_buf; + restrict_method = strsep(&next, ":"); + + if ((strcmp(restrict_method, "key_or_keyring") == 0) && next) { + key_serial_t serial; + struct key *key; + + if (kstrtos32(next, 0, &serial) < 0) + goto out; + + key = key_lookup(serial); + if (IS_ERR(key)) { + ret = ERR_CAST(key); + goto out; + } + + ret = asymmetric_restriction_alloc( + restrict_link_by_key_or_keyring, key); + if (IS_ERR(ret)) + key_put(key); + } + +out: + kfree(parse_buf); + return ret; } struct key_type key_type_asymmetric = { diff --git a/crypto/asymmetric_keys/restrict.c b/crypto/asymmetric_keys/restrict.c index a3afbf78..183cb642 100644 --- a/crypto/asymmetric_keys/restrict.c +++ b/crypto/asymmetric_keys/restrict.c @@ -108,3 +108,74 @@ int restrict_link_by_signature(struct key *dest_keyring, key_put(key); return ret; } + +/** + * restrict_link_by_key_or_keyring - Restrict additions to a ring of public + * keys using the restrict_key information stored in the ring. + * @dest_keyring: Keyring being linked to. + * @type: The type of key being added. + * @payload: The payload of the new key. + * @trusted: A key or ring of keys that can be used to vouch for the new cert. + * + * Check the new certificate only against the key or keys passed in the data + * parameter. If one of those is the signing key and validates the new + * certificate, then mark the new certificate as being ok to link. + * + * Returns 0 if the new certificate was accepted, -ENOKEY if we + * couldn't find a matching parent certificate in the trusted list, + * -EKEYREJECTED if the signature check fails, and some other error if + * there is a matching certificate but the signature check cannot be + * performed. + */ +int restrict_link_by_key_or_keyring(struct key *dest_keyring, + const struct key_type *type, + const union key_payload *payload, + struct key *trusted) +{ + const struct public_key_signature *sig; + struct key *key; + int ret; + + pr_devel("==>%s()\n", __func__); + + if (!dest_keyring) + return -ENOKEY; + else if (dest_keyring->type != &key_type_keyring) + return -EOPNOTSUPP; + + if (!trusted) + return -ENOKEY; + + if (type != &key_type_asymmetric) + return -EOPNOTSUPP; + + sig = payload->data[asym_auth]; + if (!sig->auth_ids[0] && !sig->auth_ids[1]) + return -ENOKEY; + + if (trusted->type == &key_type_keyring) { + /* See if we have a key that signed this one. */ + key = find_asymmetric_key(trusted, sig->auth_ids[0], + sig->auth_ids[1], false); + if (IS_ERR(key)) + return -ENOKEY; + } else if (trusted->type == &key_type_asymmetric) { + const struct asymmetric_key_ids *kids; + + kids = asymmetric_key_ids(trusted); + + if (!asymmetric_key_id_same(kids->id[1], sig->auth_ids[0])) + return -ENOKEY; + + key = __key_get(trusted); + } else { + return -EOPNOTSUPP; + } + + ret = key_validate(key); + if (ret == 0) + ret = verify_signature(key, sig); + + key_put(key); + return ret; +} -- cgit v1.2.3 From c6abad0244ad8f5f9829e74fc9341d3e904be287 Mon Sep 17 00:00:00 2001 From: Mat Martineau Date: Tue, 4 Oct 2016 16:42:45 -0700 Subject: KEYS: Keyring asymmetric key restrict method with chaining Add a restrict_link_by_key_or_keyring_chain link restriction that searches for signing keys in the destination keyring in addition to the signing key or keyring designated when the destination keyring was created. Userspace enables this behavior by including the "chain" option in the keyring restriction: keyctl(KEYCTL_RESTRICT_KEYRING, keyring, "asymmetric", "key_or_keyring::chain"); Signed-off-by: Mat Martineau --- crypto/asymmetric_keys/asymmetric_type.c | 31 ++++-- crypto/asymmetric_keys/restrict.c | 158 +++++++++++++++++++++++-------- 2 files changed, 144 insertions(+), 45 deletions(-) (limited to 'crypto/asymmetric_keys') diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c index 72700ed8..e4b0ed38 100644 --- a/crypto/asymmetric_keys/asymmetric_type.c +++ b/crypto/asymmetric_keys/asymmetric_type.c @@ -496,20 +496,37 @@ static struct key_restriction *asymmetric_lookup_restriction( restrict_method = strsep(&next, ":"); if ((strcmp(restrict_method, "key_or_keyring") == 0) && next) { + char *key_text; key_serial_t serial; struct key *key; + key_restrict_link_func_t link_fn = + restrict_link_by_key_or_keyring; + bool allow_null_key = false; - if (kstrtos32(next, 0, &serial) < 0) - goto out; + key_text = strsep(&next, ":"); + + if (next) { + if (strcmp(next, "chain") != 0) + goto out; + + link_fn = restrict_link_by_key_or_keyring_chain; + allow_null_key = true; + } - key = key_lookup(serial); - if (IS_ERR(key)) { - ret = ERR_CAST(key); + if (kstrtos32(key_text, 0, &serial) < 0) goto out; + + if ((serial == 0) && allow_null_key) { + key = NULL; + } else { + key = key_lookup(serial); + if (IS_ERR(key)) { + ret = ERR_CAST(key); + goto out; + } } - ret = asymmetric_restriction_alloc( - restrict_link_by_key_or_keyring, key); + ret = asymmetric_restriction_alloc(link_fn, key); if (IS_ERR(ret)) key_put(key); } diff --git a/crypto/asymmetric_keys/restrict.c b/crypto/asymmetric_keys/restrict.c index 183cb642..86fb6850 100644 --- a/crypto/asymmetric_keys/restrict.c +++ b/crypto/asymmetric_keys/restrict.c @@ -109,31 +109,20 @@ int restrict_link_by_signature(struct key *dest_keyring, return ret; } -/** - * restrict_link_by_key_or_keyring - Restrict additions to a ring of public - * keys using the restrict_key information stored in the ring. - * @dest_keyring: Keyring being linked to. - * @type: The type of key being added. - * @payload: The payload of the new key. - * @trusted: A key or ring of keys that can be used to vouch for the new cert. - * - * Check the new certificate only against the key or keys passed in the data - * parameter. If one of those is the signing key and validates the new - * certificate, then mark the new certificate as being ok to link. - * - * Returns 0 if the new certificate was accepted, -ENOKEY if we - * couldn't find a matching parent certificate in the trusted list, - * -EKEYREJECTED if the signature check fails, and some other error if - * there is a matching certificate but the signature check cannot be - * performed. - */ -int restrict_link_by_key_or_keyring(struct key *dest_keyring, - const struct key_type *type, - const union key_payload *payload, - struct key *trusted) +static bool match_either_id(const struct asymmetric_key_ids *pair, + const struct asymmetric_key_id *single) +{ + return (asymmetric_key_id_same(pair->id[0], single) || + asymmetric_key_id_same(pair->id[1], single)); +} + +static int key_or_keyring_common(struct key *dest_keyring, + const struct key_type *type, + const union key_payload *payload, + struct key *trusted, bool check_dest) { const struct public_key_signature *sig; - struct key *key; + struct key *key = NULL; int ret; pr_devel("==>%s()\n", __func__); @@ -143,7 +132,7 @@ int restrict_link_by_key_or_keyring(struct key *dest_keyring, else if (dest_keyring->type != &key_type_keyring) return -EOPNOTSUPP; - if (!trusted) + if (!trusted && !check_dest) return -ENOKEY; if (type != &key_type_asymmetric) @@ -153,25 +142,64 @@ int restrict_link_by_key_or_keyring(struct key *dest_keyring, if (!sig->auth_ids[0] && !sig->auth_ids[1]) return -ENOKEY; - if (trusted->type == &key_type_keyring) { - /* See if we have a key that signed this one. */ - key = find_asymmetric_key(trusted, sig->auth_ids[0], - sig->auth_ids[1], false); - if (IS_ERR(key)) - return -ENOKEY; - } else if (trusted->type == &key_type_asymmetric) { - const struct asymmetric_key_ids *kids; + if (trusted) { + if (trusted->type == &key_type_keyring) { + /* See if we have a key that signed this one. */ + key = find_asymmetric_key(trusted, sig->auth_ids[0], + sig->auth_ids[1], false); + if (IS_ERR(key)) + key = NULL; + } else if (trusted->type == &key_type_asymmetric) { + const struct asymmetric_key_ids *signer_ids; - kids = asymmetric_key_ids(trusted); + signer_ids = asymmetric_key_ids(trusted); - if (!asymmetric_key_id_same(kids->id[1], sig->auth_ids[0])) - return -ENOKEY; + /* + * The auth_ids come from the candidate key (the + * one that is being considered for addition to + * dest_keyring) and identify the key that was + * used to sign. + * + * The signer_ids are identifiers for the + * signing key specified for dest_keyring. + * + * The first auth_id is the preferred id, and + * the second is the fallback. If only one + * auth_id is present, it may match against + * either signer_id. If two auth_ids are + * present, the first auth_id must match one + * signer_id and the second auth_id must match + * the second signer_id. + */ + if (!sig->auth_ids[0] || !sig->auth_ids[1]) { + const struct asymmetric_key_id *auth_id; - key = __key_get(trusted); - } else { - return -EOPNOTSUPP; + auth_id = sig->auth_ids[0] ?: sig->auth_ids[1]; + if (match_either_id(signer_ids, auth_id)) + key = __key_get(trusted); + + } else if (asymmetric_key_id_same(signer_ids->id[1], + sig->auth_ids[1]) && + match_either_id(signer_ids, + sig->auth_ids[0])) { + key = __key_get(trusted); + } + } else { + return -EOPNOTSUPP; + } } + if (check_dest && !key) { + /* See if the destination has a key that signed this one. */ + key = find_asymmetric_key(dest_keyring, sig->auth_ids[0], + sig->auth_ids[1], false); + if (IS_ERR(key)) + key = NULL; + } + + if (!key) + return -ENOKEY; + ret = key_validate(key); if (ret == 0) ret = verify_signature(key, sig); @@ -179,3 +207,57 @@ int restrict_link_by_key_or_keyring(struct key *dest_keyring, key_put(key); return ret; } + +/** + * restrict_link_by_key_or_keyring - Restrict additions to a ring of public + * keys using the restrict_key information stored in the ring. + * @dest_keyring: Keyring being linked to. + * @type: The type of key being added. + * @payload: The payload of the new key. + * @trusted: A key or ring of keys that can be used to vouch for the new cert. + * + * Check the new certificate only against the key or keys passed in the data + * parameter. If one of those is the signing key and validates the new + * certificate, then mark the new certificate as being ok to link. + * + * Returns 0 if the new certificate was accepted, -ENOKEY if we + * couldn't find a matching parent certificate in the trusted list, + * -EKEYREJECTED if the signature check fails, and some other error if + * there is a matching certificate but the signature check cannot be + * performed. + */ +int restrict_link_by_key_or_keyring(struct key *dest_keyring, + const struct key_type *type, + const union key_payload *payload, + struct key *trusted) +{ + return key_or_keyring_common(dest_keyring, type, payload, trusted, + false); +} + +/** + * restrict_link_by_key_or_keyring_chain - Restrict additions to a ring of + * public keys using the restrict_key information stored in the ring. + * @dest_keyring: Keyring being linked to. + * @type: The type of key being added. + * @payload: The payload of the new key. + * @trusted: A key or ring of keys that can be used to vouch for the new cert. + * + * Check the new certificate only against the key or keys passed in the data + * parameter. If one of those is the signing key and validates the new + * certificate, then mark the new certificate as being ok to link. + * + * Returns 0 if the new certificate was accepted, -ENOKEY if we + * couldn't find a matching parent certificate in the trusted list, + * -EKEYREJECTED if the signature check fails, and some other error if + * there is a matching certificate but the signature check cannot be + * performed. + */ +int restrict_link_by_key_or_keyring_chain(struct key *dest_keyring, + const struct key_type *type, + const union key_payload *payload, + struct key *trusted) +{ + return key_or_keyring_common(dest_keyring, type, payload, trusted, + true); +} -- cgit v1.2.3 From 548b37ff50e23c4d92f3878e70cebc12dd365352 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 18 May 2017 16:29:23 +0300 Subject: crypto: asymmetric_keys - handle EBUSY due to backlog correctly public_key_verify_signature() was passing the CRYPTO_TFM_REQ_MAY_BACKLOG flag to akcipher_request_set_callback() but was not handling correctly the case where a -EBUSY error could be returned from the call to crypto_akcipher_verify() if backlog was used, possibly casuing data corruption due to use-after-free of buffers. Resolve this by handling -EBUSY correctly. Signed-off-by: Gilad Ben-Yossef CC: stable@vger.kernel.org Signed-off-by: Herbert Xu --- crypto/asymmetric_keys/public_key.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crypto/asymmetric_keys') diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index d3a989e7..3cd6e12c 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -141,7 +141,7 @@ int public_key_verify_signature(const struct public_key *pkey, * signature and returns that to us. */ ret = crypto_akcipher_verify(req); - if (ret == -EINPROGRESS) { + if ((ret == -EINPROGRESS) || (ret == -EBUSY)) { wait_for_completion(&compl.completion); ret = compl.err; } -- cgit v1.2.3 From 7a957c7bf59b44f1982e438bc0465a108a1777fb Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 8 Jun 2017 14:47:49 +0100 Subject: X.509: Fix error code in x509_cert_parse() We forgot to set the error code on this path so it could result in returning NULL which leads to a NULL dereference. Fixes: 2f265d619107 ("crypto: KEYS: convert public key and digsig asym to the akcipher api") Signed-off-by: Dan Carpenter Signed-off-by: David Howells Signed-off-by: James Morris --- crypto/asymmetric_keys/x509_cert_parser.c | 1 + 1 file changed, 1 insertion(+) (limited to 'crypto/asymmetric_keys') diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index c80765b2..dd03fead 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -102,6 +102,7 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) } } + ret = -ENOMEM; cert->pub->key = kmemdup(ctx->key, ctx->key_size, GFP_KERNEL); if (!cert->pub->key) goto error_decode; -- cgit v1.2.3 From 0930c08c6bc50a3a62ee3c90fad305840affbaf2 Mon Sep 17 00:00:00 2001 From: Loganaden Velvindron Date: Thu, 8 Jun 2017 14:50:04 +0100 Subject: crypto : asymmetric_keys : verify_pefile:zero memory content before freeing Signed-off-by: Loganaden Velvindron Signed-off-by: Yasir Auleear Signed-off-by: David Howells Signed-off-by: James Morris --- crypto/asymmetric_keys/verify_pefile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'crypto/asymmetric_keys') diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c index 672a94c2..d178650f 100644 --- a/crypto/asymmetric_keys/verify_pefile.c +++ b/crypto/asymmetric_keys/verify_pefile.c @@ -381,7 +381,7 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen, } error: - kfree(desc); + kzfree(desc); error_no_desc: crypto_free_shash(tfm); kleave(" = %d", ret); @@ -450,6 +450,6 @@ int verify_pefile_signature(const void *pebuf, unsigned pelen, ret = pefile_digest_pe(pebuf, pelen, &ctx); error: - kfree(ctx.digest); + kzfree(ctx.digest); return ret; } -- cgit v1.2.3