On 26/11/14 16:17, David Howells wrote:
> Extract both parts of the AuthorityKeyIdentifier, not just the keyIdentifier,
> as the second part can be used to match X.509 certificates by issuer and
> serialNumber.
>
> Signed-off-by: David Howells <dhowe...@redhat.com>
> ---
>
>  crypto/asymmetric_keys/Makefile           |    8 +-
>  crypto/asymmetric_keys/pkcs7_trust.c      |    4 -
>  crypto/asymmetric_keys/pkcs7_verify.c     |   12 +-
>  crypto/asymmetric_keys/x509_akid.asn1     |   35 +++++++
>  crypto/asymmetric_keys/x509_cert_parser.c |  142 
> ++++++++++++++++++-----------
>  crypto/asymmetric_keys/x509_parser.h      |    5 +
>  crypto/asymmetric_keys/x509_public_key.c  |    8 +-
>  7 files changed, 145 insertions(+), 69 deletions(-)
>  create mode 100644 crypto/asymmetric_keys/x509_akid.asn1
>
> diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
> index e47fcd9ac5e8..cd1406f9b14a 100644
> --- a/crypto/asymmetric_keys/Makefile
> +++ b/crypto/asymmetric_keys/Makefile
> @@ -15,15 +15,21 @@ obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o
>  obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o
>  x509_key_parser-y := \
>       x509-asn1.o \
> +     x509_akid-asn1.o \
>       x509_rsakey-asn1.o \
>       x509_cert_parser.o \
>       x509_public_key.o
>  
> -$(obj)/x509_cert_parser.o: $(obj)/x509-asn1.h $(obj)/x509_rsakey-asn1.h
> +$(obj)/x509_cert_parser.o: \
> +     $(obj)/x509-asn1.h \
> +     $(obj)/x509_akid-asn1.h \
> +     $(obj)/x509_rsakey-asn1.h
>  $(obj)/x509-asn1.o: $(obj)/x509-asn1.c $(obj)/x509-asn1.h
> +$(obj)/x509_akid-asn1.o: $(obj)/x509_akid-asn1.c $(obj)/x509_akid-asn1.h
>  $(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c 
> $(obj)/x509_rsakey-asn1.h
>  
>  clean-files  += x509-asn1.c x509-asn1.h
> +clean-files  += x509_akid-asn1.c x509_akid-asn1.h
>  clean-files  += x509_rsakey-asn1.c x509_rsakey-asn1.h
>  
>  #
> diff --git a/crypto/asymmetric_keys/pkcs7_trust.c 
> b/crypto/asymmetric_keys/pkcs7_trust.c
> index 1d29376072da..f802cf118053 100644
> --- a/crypto/asymmetric_keys/pkcs7_trust.c
> +++ b/crypto/asymmetric_keys/pkcs7_trust.c
> @@ -85,8 +85,8 @@ static int pkcs7_validate_trust_one(struct pkcs7_message 
> *pkcs7,
>       /* No match - see if the root certificate has a signer amongst the
>        * trusted keys.
>        */
> -     if (last && last->authority) {
> -             key = x509_request_asymmetric_key(trust_keyring, 
> last->authority,
> +     if (last && last->auth_skid) {
> +             key = x509_request_asymmetric_key(trust_keyring, 
> last->auth_skid,
>                                                 false);
>               if (!IS_ERR(key)) {
>                       x509 = last;
> diff --git a/crypto/asymmetric_keys/pkcs7_verify.c 
> b/crypto/asymmetric_keys/pkcs7_verify.c
> index cd455450b069..5e956c5b9071 100644
> --- a/crypto/asymmetric_keys/pkcs7_verify.c
> +++ b/crypto/asymmetric_keys/pkcs7_verify.c
> @@ -187,11 +187,11 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message 
> *pkcs7,
>                       goto maybe_missing_crypto_in_x509;
>  
>               pr_debug("- issuer %s\n", x509->issuer);
> -             if (x509->authority)
> +             if (x509->auth_skid)
>                       pr_debug("- authkeyid %*phN\n",
> -                              x509->authority->len, x509->authority->data);
> +                              x509->auth_skid->len, x509->auth_skid->data);
>  
> -             if (!x509->authority ||
> +             if (!x509->auth_skid ||
>                   strcmp(x509->subject, x509->issuer) == 0) {
>                       /* If there's no authority certificate specified, then
>                        * the certificate must be self-signed and is the root
> @@ -216,13 +216,13 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message 
> *pkcs7,
>                * list to see if the next one is there.
>                */
>               pr_debug("- want %*phN\n",
> -                      x509->authority->len, x509->authority->data);
> +                      x509->auth_skid->len, x509->auth_skid->data);
>               for (p = pkcs7->certs; p; p = p->next) {
>                       if (!p->skid)
>                               continue;
>                       pr_debug("- cmp [%u] %*phN\n",
>                                p->index, p->skid->len, p->skid->data);
> -                     if (asymmetric_key_id_same(p->skid, x509->authority))
> +                     if (asymmetric_key_id_same(p->skid, x509->auth_skid))
>                               goto found_issuer;
>               }
>  
> @@ -338,8 +338,6 @@ int pkcs7_verify(struct pkcs7_message *pkcs7)
>               ret = x509_get_sig_params(x509);
>               if (ret < 0)
>                       return ret;
> -             pr_debug("X.509[%u] %*phN\n",
> -                      n, x509->authority->len, x509->authority->data);
>       }
>  
>       for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
> diff --git a/crypto/asymmetric_keys/x509_akid.asn1 
> b/crypto/asymmetric_keys/x509_akid.asn1
> new file mode 100644
> index 000000000000..1a33231a75a8
> --- /dev/null
> +++ b/crypto/asymmetric_keys/x509_akid.asn1
> @@ -0,0 +1,35 @@
> +-- X.509 AuthorityKeyIdentifier
> +-- rfc5280 section 4.2.1.1
> +
> +AuthorityKeyIdentifier ::= SEQUENCE {
> +     keyIdentifier                   [0] IMPLICIT KeyIdentifier              
> OPTIONAL,
> +     authorityCertIssuer             [1] IMPLICIT GeneralNames               
> OPTIONAL,
> +     authorityCertSerialNumber       [2] IMPLICIT CertificateSerialNumber    
> OPTIONAL
> +     }
> +
> +KeyIdentifier ::= OCTET STRING ({ x509_akid_note_kid })
> +
> +CertificateSerialNumber ::= INTEGER ({ x509_akid_note_serial })
> +
> +GeneralNames ::= SEQUENCE OF GeneralName
> +
> +GeneralName ::= CHOICE {
> +     otherName                       [0] ANY,
> +     rfc822Name                      [1] IA5String,
> +     dNSName                         [2] IA5String,
> +     x400Address                     [3] ANY,
> +     directoryName                   [4] Name ({ x509_akid_note_name }),
> +     ediPartyName                    [5] ANY,
> +     uniformResourceIdentifier       [6] IA5String,
> +     iPAddress                       [7] OCTET STRING,
> +     registeredID                    [8] OBJECT IDENTIFIER
> +     }
> +
> +Name ::= SEQUENCE OF RelativeDistinguishedName
> +
> +RelativeDistinguishedName ::= SET OF AttributeValueAssertion
> +
> +AttributeValueAssertion ::= SEQUENCE {
> +     attributeType           OBJECT IDENTIFIER ({ x509_note_OID }),
> +     attributeValue          ANY ({ x509_extract_name_segment })
> +     }
> diff --git a/crypto/asymmetric_keys/x509_cert_parser.c 
> b/crypto/asymmetric_keys/x509_cert_parser.c
> index a668d90302d3..e9d6586fdf89 100644
> --- a/crypto/asymmetric_keys/x509_cert_parser.c
> +++ b/crypto/asymmetric_keys/x509_cert_parser.c
> @@ -18,6 +18,7 @@
>  #include "public_key.h"
>  #include "x509_parser.h"
>  #include "x509-asn1.h"
> +#include "x509_akid-asn1.h"
>  #include "x509_rsakey-asn1.h"
>  
>  struct x509_parse_context {
> @@ -35,6 +36,10 @@ struct x509_parse_context {
>       u16             o_offset;               /* Offset of organizationName 
> (O) */
>       u16             cn_offset;              /* Offset of commonName (CN) */
>       u16             email_offset;           /* Offset of emailAddress */
> +     unsigned        raw_akid_size;
> +     const void      *raw_akid;              /* Raw authorityKeyId in ASN.1 
> */
> +     const void      *akid_raw_issuer;       /* Raw directoryName in 
> authorityKeyId */
> +     unsigned        akid_raw_issuer_size;
>  };
>  
>  /*
> @@ -48,7 +53,8 @@ void x509_free_certificate(struct x509_certificate *cert)
>               kfree(cert->subject);
>               kfree(cert->id);
>               kfree(cert->skid);
> -             kfree(cert->authority);
> +             kfree(cert->auth_id);
> +             kfree(cert->auth_skid);
>               kfree(cert->sig.digest);
>               mpi_free(cert->sig.rsa.s);
>               kfree(cert);
> @@ -85,6 +91,18 @@ struct x509_certificate *x509_cert_parse(const void *data, 
> size_t datalen)
>       if (ret < 0)
>               goto error_decode;
>  
> +     /* Decode the AuthorityKeyIdentifier */
> +     if (ctx->raw_akid) {
> +             pr_devel("AKID: %u %*phN\n",
> +                      ctx->raw_akid_size, ctx->raw_akid_size, ctx->raw_akid);
> +             ret = asn1_ber_decoder(&x509_akid_decoder, ctx,
> +                                    ctx->raw_akid, ctx->raw_akid_size);
> +             if (ret < 0) {
> +                     pr_warn("Couldn't decode AuthKeyIdentifier\n");
> +                     goto error_decode;
> +             }
> +     }
> +
>       /* Decode the public key */
>       ret = asn1_ber_decoder(&x509_rsakey_decoder, ctx,
>                              ctx->key, ctx->key_size);
> @@ -422,7 +440,6 @@ int x509_process_extension(void *context, size_t hdrlen,
>       struct x509_parse_context *ctx = context;
>       struct asymmetric_key_id *kid;
>       const unsigned char *v = value;
> -     int i;
>  
>       pr_debug("Extension: %u\n", ctx->last_oid);
>  
> @@ -449,57 +466,8 @@ int x509_process_extension(void *context, size_t hdrlen,
>  
>       if (ctx->last_oid == OID_authorityKeyIdentifier) {
>               /* Get hold of the CA key fingerprint */
> -             if (ctx->cert->authority || vlen < 5)
> -                     return -EBADMSG;
> -
> -             /* Authority Key Identifier must be a Constructed SEQUENCE */
> -             if (v[0] != (ASN1_SEQ | (ASN1_CONS << 5)))
> -                     return -EBADMSG;
> -
> -             /* Authority Key Identifier is not indefinite length */
> -             if (unlikely(vlen == ASN1_INDEFINITE_LENGTH))
> -                     return -EBADMSG;
> -
> -             if (vlen < ASN1_INDEFINITE_LENGTH) {
> -                     /* Short Form length */
> -                     if (v[1] != vlen - 2 ||
> -                         v[2] != SEQ_TAG_KEYID ||
> -                         v[3] > vlen - 4)
> -                             return -EBADMSG;
> -
> -                     vlen = v[3];
> -                     v += 4;
> -             } else {
> -                     /* Long Form length */
> -                     size_t seq_len = 0;
> -                     size_t sub = v[1] - ASN1_INDEFINITE_LENGTH;
> -
> -                     if (sub > 2)
> -                             return -EBADMSG;
> -
> -                     /* calculate the length from subsequent octets */
> -                     v += 2;
> -                     for (i = 0; i < sub; i++) {
> -                             seq_len <<= 8;
> -                             seq_len |= v[i];
> -                     }
> -
> -                     if (seq_len != vlen - 2 - sub ||
> -                         v[sub] != SEQ_TAG_KEYID ||
> -                         v[sub + 1] > vlen - 4 - sub)
> -                             return -EBADMSG;
> -
> -                     vlen = v[sub + 1];
> -                     v += (sub + 2);
> -             }
> -
> -             kid = asymmetric_key_generate_id(ctx->cert->raw_issuer,
> -                                              ctx->cert->raw_issuer_size,
> -                                              v, vlen);
> -             if (IS_ERR(kid))
> -                     return PTR_ERR(kid);
> -             pr_debug("authkeyid %*phN\n", kid->len, kid->data);
> -             ctx->cert->authority = kid;
> +             ctx->raw_akid = v;
> +             ctx->raw_akid_size = vlen;
>               return 0;
>       }
>  
> @@ -569,3 +537,71 @@ int x509_note_not_after(void *context, size_t hdrlen,
>       struct x509_parse_context *ctx = context;
>       return x509_note_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen);
>  }
> +
> +/*
> + * Note a key identifier-based AuthorityKeyIdentifier
> + */
> +int x509_akid_note_kid(void *context, size_t hdrlen,
> +                    unsigned char tag,
> +                    const void *value, size_t vlen)
> +{
> +     struct x509_parse_context *ctx = context;
> +     struct asymmetric_key_id *kid;
> +
> +     pr_debug("AKID: keyid: %*phN\n", (int)vlen, value);
> +
> +     if (ctx->cert->auth_skid)
> +             return 0;
> +
> +     kid = asymmetric_key_generate_id(ctx->cert->raw_issuer,
> +                                      ctx->cert->raw_issuer_size,
> +                                      value, vlen);
> +     if (IS_ERR(kid))
> +             return PTR_ERR(kid);
> +     pr_debug("authkeyid %*phN\n", kid->len, kid->data);
> +     ctx->cert->auth_skid = kid;
> +     return 0;
> +}
> +
> +/*
> + * Note a directoryName in an AuthorityKeyIdentifier
> + */
> +int x509_akid_note_name(void *context, size_t hdrlen,
> +                     unsigned char tag,
> +                     const void *value, size_t vlen)
> +{
> +     struct x509_parse_context *ctx = context;
> +
> +     pr_debug("AKID: name: %*phN\n", (int)vlen, value);
> +
> +     ctx->akid_raw_issuer = value;
> +     ctx->akid_raw_issuer_size = vlen;
> +     return 0;
> +}
> +
> +/*
> + * Note a serial number in an AuthorityKeyIdentifier
> + */
> +int x509_akid_note_serial(void *context, size_t hdrlen,
> +                       unsigned char tag,
> +                       const void *value, size_t vlen)
> +{
> +     struct x509_parse_context *ctx = context;
> +     struct asymmetric_key_id *kid;
> +
> +     pr_debug("AKID: serial: %*phN\n", (int)vlen, value);
> +
> +     if (!ctx->akid_raw_issuer || ctx->cert->auth_id)
> +             return 0;
> +
> +     kid = asymmetric_key_generate_id(value,
> +                                      vlen,
> +                                      ctx->akid_raw_issuer,
> +                                      ctx->akid_raw_issuer_size);
> +     if (IS_ERR(kid))
> +             return PTR_ERR(kid);
> +
> +     pr_debug("authkeyid %*phN\n", kid->len, kid->data);
> +     ctx->cert->auth_id = kid;
> +     return 0;
> +}
> diff --git a/crypto/asymmetric_keys/x509_parser.h 
> b/crypto/asymmetric_keys/x509_parser.h
> index 3dfe6b5d6f0b..c4d16ddbc2cb 100644
> --- a/crypto/asymmetric_keys/x509_parser.h
> +++ b/crypto/asymmetric_keys/x509_parser.h
> @@ -19,9 +19,10 @@ struct x509_certificate {
>       struct public_key_signature sig;        /* Signature parameters */
>       char            *issuer;                /* Name of certificate issuer */
>       char            *subject;               /* Name of certificate subject 
> */
> -     struct asymmetric_key_id *id;           /* Serial number + issuer */
> +     struct asymmetric_key_id *id;           /* Issuer + Serial number */
>       struct asymmetric_key_id *skid;         /* Subject + subjectKeyId 
> (optional) */
> -     struct asymmetric_key_id *authority;    /* Authority key identifier 
> (optional) */
> +     struct asymmetric_key_id *auth_id;      /* CA AuthKeyId matching ->id 
> (optional) */
> +     struct asymmetric_key_id *auth_skid;    /* CA AuthKeyId matching ->skid 
> (optional) */

Hi David,

Why do you call it "auth_skid", not just akid in similar way as 'skid'?
Why it is "auth & skid"?

- Dmitry

>       struct tm       valid_from;
>       struct tm       valid_to;
>       const void      *tbs;                   /* Signed data */
> diff --git a/crypto/asymmetric_keys/x509_public_key.c 
> b/crypto/asymmetric_keys/x509_public_key.c
> index a6c42031628e..a3d9ba999da5 100644
> --- a/crypto/asymmetric_keys/x509_public_key.c
> +++ b/crypto/asymmetric_keys/x509_public_key.c
> @@ -214,10 +214,10 @@ static int x509_validate_trust(struct x509_certificate 
> *cert,
>       if (!trust_keyring)
>               return -EOPNOTSUPP;
>  
> -     if (ca_keyid && !asymmetric_key_id_partial(cert->authority, ca_keyid))
> +     if (ca_keyid && !asymmetric_key_id_partial(cert->auth_skid, ca_keyid))
>               return -EPERM;
>  
> -     key = x509_request_asymmetric_key(trust_keyring, cert->authority,
> +     key = x509_request_asymmetric_key(trust_keyring, cert->auth_skid,
>                                         false);
>       if (!IS_ERR(key))  {
>               if (!use_builtin_keys
> @@ -274,8 +274,8 @@ static int x509_key_preparse(struct key_preparsed_payload 
> *prep)
>       cert->pub->id_type = PKEY_ID_X509;
>  
>       /* Check the signature on the key if it appears to be self-signed */
> -     if (!cert->authority ||
> -         asymmetric_key_id_same(cert->skid, cert->authority)) {
> +     if (!cert->auth_skid ||
> +         asymmetric_key_id_same(cert->skid, cert->auth_skid)) {
>               ret = x509_check_signature(cert->pub, cert); /* self-signed */
>               if (ret < 0)
>                       goto error_free_cert;
>
>

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to