linux/crypto/asymmetric_keys
Andrew Zaborowski 7d30198ee2 keys: X.509 public key issuer lookup without AKID
There are non-root X.509 v3 certificates in use out there that contain
no Authority Key Identifier extension (RFC5280 section 4.2.1.1).  For
trust verification purposes the kernel asymmetric key type keeps two
struct asymmetric_key_id instances that the key can be looked up by,
and another two to look up the key's issuer.  The x509 public key type
and the PKCS7 type generate them from the SKID and AKID extensions in
the certificate.  In effect current code has no way to look up the
issuer certificate for verification without the AKID.

To remedy this, add a third asymmetric_key_id blob to the arrays in
both asymmetric_key_id's (for certficate subject) and in the
public_keys_signature's auth_ids (for issuer lookup), using just raw
subject and issuer DNs from the certificate.  Adapt
asymmetric_key_ids() and its callers to use the third ID for lookups
when none of the other two are available.  Attempt to keep the logic
intact when they are, to minimise behaviour changes.  Adapt the
restrict functions' NULL-checks to include that ID too.  Do not modify
the lookup logic in pkcs7_verify.c, the AKID extensions are still
required there.

Internally use a new "dn:" prefix to the search specifier string
generated for the key lookup in find_asymmetric_key().  This tells
asymmetric_key_match_preparse to only match the data against the raw
DN in the third ID and shouldn't conflict with search specifiers
already in use.

In effect implement what (2) in the struct asymmetric_key_id comment
(include/keys/asymmetric-type.h) is probably talking about already, so
do not modify that comment.  It is also how "openssl verify" looks up
issuer certificates without the AKID available.  Lookups by the raw
DN are unambiguous only provided that the CAs respect the condition in
RFC5280 4.2.1.1 that the AKID may only be omitted if the CA uses
a single signing key.

The following is an example of two things that this change enables.
A self-signed ceritficate is generated following the example from
https://letsencrypt.org/docs/certificates-for-localhost/, and can be
looked up by an identifier and verified against itself by linking to a
restricted keyring -- both things not possible before due to the missing
AKID extension:

$ openssl req -x509 -out localhost.crt -outform DER -keyout localhost.key \
  -newkey rsa:2048 -nodes -sha256 \
  -subj '/CN=localhost' -extensions EXT -config <( \
   echo -e "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\n" \
          "subjectAltName=DNS:localhost\nkeyUsage=digitalSignature\n" \
	  "extendedKeyUsage=serverAuth")
$ keyring=`keyctl newring test @u`
$ trusted=`keyctl padd asymmetric trusted $keyring < localhost.crt`; \
  echo $trusted
39726322
$ keyctl search $keyring asymmetric dn:3112301006035504030c096c6f63616c686f7374
39726322
$ keyctl restrict_keyring $keyring asymmetric key_or_keyring:$trusted
$ keyctl padd asymmetric verified $keyring < localhost.crt

Signed-off-by: Andrew Zaborowski <andrew.zaborowski@intel.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Acked-by: Jarkko Sakkinen <jarkko@kernel.org>
Acked-by: David Howells <dhowells@redhat.com>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
2022-01-09 00:18:42 +02:00
..
asym_tpm.c crypto: asym_tpm: correct zero out potential secrets 2020-12-31 10:48:53 +01:00
asymmetric_keys.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 36 2019-05-24 17:27:11 +02:00
asymmetric_type.c keys: X.509 public key issuer lookup without AKID 2022-01-09 00:18:42 +02:00
Kconfig crypto: asymmetric_keys - select CRYPTO_HASH where needed 2019-06-27 14:28:01 +08:00
Makefile X.509: Fix modular build of public_key_sm2 2020-10-08 16:39:14 +11:00
mscode.asn1 pefile: Parse the "Microsoft individual code signing" data blob 2014-07-09 14:58:37 +01:00
mscode_parser.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 36 2019-05-24 17:27:11 +02:00
pkcs7.asn1 PKCS#7: Appropriately restrict authenticated attributes and content type 2015-08-12 17:01:01 +01:00
pkcs7_key_type.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 36 2019-05-24 17:27:11 +02:00
pkcs7_parser.c certs: Add support for using elliptic curve keys for signing modules 2021-08-23 19:55:42 +03:00
pkcs7_parser.h crypto: asymmetric_keys: fix some comments in pkcs7_parser.h 2021-01-21 16:16:09 +00:00
pkcs7_trust.c keys: X.509 public key issuer lookup without AKID 2022-01-09 00:18:42 +02:00
pkcs7_verify.c crypto: pkcs7: Use match_string() helper to simplify the code 2021-01-21 16:16:09 +00:00
pkcs8.asn1 KEYS: Implement PKCS#8 RSA Private Key parser [ver #2] 2018-10-26 09:30:46 +01:00
pkcs8_parser.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 36 2019-05-24 17:27:11 +02:00
public_key.c x509: Add support for parsing x509 certs with ECDSA keys 2021-03-26 19:41:59 +11:00
restrict.c keys: X.509 public key issuer lookup without AKID 2022-01-09 00:18:42 +02:00
signature.c docs: crypto: convert asymmetric-keys.txt to ReST 2020-06-19 14:03:46 -06:00
tpm.asn1 KEYS: Add parser for TPM-based keys [ver #2] 2018-10-26 09:30:46 +01:00
tpm_parser.c KEYS: Add parser for TPM-based keys [ver #2] 2018-10-26 09:30:46 +01:00
verify_pefile.c mm, treewide: rename kzfree() to kfree_sensitive() 2020-08-07 11:33:22 -07:00
verify_pefile.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 36 2019-05-24 17:27:11 +02:00
x509.asn1 X.509: parse public key parameters from x509 for akcipher 2019-04-18 22:15:02 +08:00
x509_akid.asn1 X.509: Extract both parts of the AuthorityKeyIdentifier 2015-08-07 16:26:13 +01:00
x509_cert_parser.c keys: X.509 public key issuer lookup without AKID 2022-01-09 00:18:42 +02:00
x509_parser.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 36 2019-05-24 17:27:11 +02:00
x509_public_key.c keys: X.509 public key issuer lookup without AKID 2022-01-09 00:18:42 +02:00