• Andrew Zaborowski's avatar
    keys: X.509 public key issuer lookup without AKID · 7d30198e
    Andrew Zaborowski authored
    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: default avatarAndrew Zaborowski <andrew.zaborowski@intel.com>
    Reviewed-by: default avatarJarkko Sakkinen <jarkko@kernel.org>
    Acked-by: default avatarJarkko Sakkinen <jarkko@kernel.org>
    Acked-by: default avatarDavid Howells <dhowells@redhat.com>
    Signed-off-by: default avatarJarkko Sakkinen <jarkko@kernel.org>
    7d30198e
public_key.h 2.38 KB