From: Eric Biggers ebiggers@google.com
commit 4b34968e77ad09628cfb3c4a7daf2adc2cefc6e8 upstream. [Please apply to 4.9-stable. I dropped the portion of the patch pertaining to KEYCTL_RESTRICT_KEYRING which was added in v4.12.]
The asymmetric key type allows an X.509 certificate to be added even if its signature's hash algorithm is not available in the crypto API. In that case 'payload.data[asym_auth]' will be NULL. But the key restriction code failed to check for this case before trying to use the signature, resulting in a NULL pointer dereference in key_or_keyring_common() or in restrict_link_by_signature().
Fix this by returning -ENOPKG when the signature is unsupported.
Reproducer when all the CONFIG_CRYPTO_SHA512* options are disabled and keyctl has support for the 'restrict_keyring' command:
keyctl new_session keyctl restrict_keyring @s asymmetric builtin_trusted openssl req -new -sha512 -x509 -batch -nodes -outform der \ | keyctl padd asymmetric desc @s
Fixes: a511e1af8b12 ("KEYS: Move the point of trust determination to __key_link()") Cc: stable@vger.kernel.org # v4.7+ Signed-off-by: Eric Biggers ebiggers@google.com Signed-off-by: David Howells dhowells@redhat.com --- crypto/asymmetric_keys/restrict.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/crypto/asymmetric_keys/restrict.c b/crypto/asymmetric_keys/restrict.c index 19d1afb9890f..09b1374dc619 100644 --- a/crypto/asymmetric_keys/restrict.c +++ b/crypto/asymmetric_keys/restrict.c @@ -66,8 +66,9 @@ __setup("ca_keys=", ca_keys_setup); * * 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 or the key is blacklisted and some other error if - * there is a matching certificate but the signature check cannot be performed. + * signature check fails or the key is blacklisted, -ENOPKG if the signature + * uses unsupported crypto, or 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, const struct key_type *type, @@ -86,6 +87,8 @@ int restrict_link_by_signature(struct key *trust_keyring, return -EOPNOTSUPP;
sig = payload->data[asym_auth]; + if (!sig) + return -ENOPKG; if (!sig->auth_ids[0] && !sig->auth_ids[1]) return -ENOKEY;