lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Thu, 04 Dec 2014 14:14:44 +0200
From:	Dmitry Kasatkin <d.kasatkin@...sung.com>
To:	David Howells <dhowells@...hat.com>, rusty@...tcorp.com.au
Cc:	mmarek@...e.cz, keyrings@...ux-nfs.org,
	linux-kernel@...r.kernel.org,
	linux-security-module@...r.kernel.org, zohar@...ux.vnet.ibm.com
Subject: Re: [PATCH 1/5] X.509: Extract both parts of the
 AuthorityKeyIdentifier [ver #2]

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 <dhowells@...hat.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 majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ