summaryrefslogtreecommitdiff
path: root/crypto/asymmetric_keys/x509_cert_parser.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2014-09-16 17:38:07 +0100
committerDavid Howells <dhowells@redhat.com>2014-09-16 17:38:07 +0100
commite8ad2d9b5ee05ffc5c49d1dc2731330ad276ae20 (patch)
treeea50915321b345c3d2973fe5259038ccfceda9f8 /crypto/asymmetric_keys/x509_cert_parser.c
parent59d384b06776928f95a18d22efc1b9dfad4cc36e (diff)
parent4fa8d06586307c5403958f1c67120957b0d1ee81 (diff)
downloadlinux-crypto-e8ad2d9b5ee05ffc5c49d1dc2731330ad276ae20.tar.gz
linux-crypto-e8ad2d9b5ee05ffc5c49d1dc2731330ad276ae20.zip
Merge tag 'keys-pkcs7-20140916' into keys-next
Changes for next to improve the matching of asymmetric keys and to improve the handling of PKCS#7 certificates: (1) Provide a method to preparse the data supplied for matching a key. This permits they key type to extract out the bits it needs for matching once only. Further, the type of search (direct lookup or iterative) can be set and the function used to actually check the match can be set by preparse rather than being hard coded for the type. (2) Improves asymmetric keys identification. Keys derived from X.509 certs now get labelled with IDs derived from their issuer and certificate number (required to match PKCS#7) and from their SKID and subject (required to match X.509). IDs are now binary and match criterion preparsing is provided so that criteria can be turned into binary blobs to make matching faster. (3) Improves PKCS#7 message handling to permit PKCS#7 messages without X.509 cert lists to be matched to trusted keys, thereby allowing minimally sized PKCS#7 certs to be used. (4) Improves PKCS#7 message handling to better handle certificate chains that are broken due to unsupported crypto that can otherwise by used to intersect a trust keyring. These must go on top of the PKCS#7 parser cleanup fixes. Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'crypto/asymmetric_keys/x509_cert_parser.c')
-rw-r--r--crypto/asymmetric_keys/x509_cert_parser.c55
1 files changed, 33 insertions, 22 deletions
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index ac72348c..96151b2b 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -46,7 +46,8 @@ void x509_free_certificate(struct x509_certificate *cert)
public_key_destroy(cert->pub);
kfree(cert->issuer);
kfree(cert->subject);
- kfree(cert->fingerprint);
+ kfree(cert->id);
+ kfree(cert->skid);
kfree(cert->authority);
kfree(cert->sig.digest);
mpi_free(cert->sig.rsa.s);
@@ -62,6 +63,7 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
{
struct x509_certificate *cert;
struct x509_parse_context *ctx;
+ struct asymmetric_key_id *kid;
long ret;
ret = -ENOMEM;
@@ -89,6 +91,17 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
if (ret < 0)
goto error_decode;
+ /* Generate cert issuer + serial number key ID */
+ kid = asymmetric_key_generate_id(cert->raw_serial,
+ cert->raw_serial_size,
+ cert->raw_issuer,
+ cert->raw_issuer_size);
+ if (IS_ERR(kid)) {
+ ret = PTR_ERR(kid);
+ goto error_decode;
+ }
+ cert->id = kid;
+
kfree(ctx);
return cert;
@@ -407,36 +420,34 @@ int x509_process_extension(void *context, size_t hdrlen,
const void *value, size_t vlen)
{
struct x509_parse_context *ctx = context;
+ struct asymmetric_key_id *kid;
const unsigned char *v = value;
- char *f;
int i;
pr_debug("Extension: %u\n", ctx->last_oid);
if (ctx->last_oid == OID_subjectKeyIdentifier) {
/* Get hold of the key fingerprint */
- if (vlen < 3)
+ if (ctx->cert->skid || vlen < 3)
return -EBADMSG;
if (v[0] != ASN1_OTS || v[1] != vlen - 2)
return -EBADMSG;
v += 2;
vlen -= 2;
- f = kmalloc(vlen * 2 + 1, GFP_KERNEL);
- if (!f)
- return -ENOMEM;
- for (i = 0; i < vlen; i++)
- sprintf(f + i * 2, "%02x", v[i]);
- pr_debug("fingerprint %s\n", f);
- ctx->cert->fingerprint = f;
+ kid = asymmetric_key_generate_id(v, vlen,
+ ctx->cert->raw_subject,
+ ctx->cert->raw_subject_size);
+ if (IS_ERR(kid))
+ return PTR_ERR(kid);
+ ctx->cert->skid = kid;
+ pr_debug("subjkeyid %*phN\n", kid->len, kid->data);
return 0;
}
if (ctx->last_oid == OID_authorityKeyIdentifier) {
- size_t key_len;
-
/* Get hold of the CA key fingerprint */
- if (vlen < 5)
+ if (ctx->cert->authority || vlen < 5)
return -EBADMSG;
/* Authority Key Identifier must be a Constructed SEQUENCE */
@@ -454,7 +465,7 @@ int x509_process_extension(void *context, size_t hdrlen,
v[3] > vlen - 4)
return -EBADMSG;
- key_len = v[3];
+ vlen = v[3];
v += 4;
} else {
/* Long Form length */
@@ -476,17 +487,17 @@ int x509_process_extension(void *context, size_t hdrlen,
v[sub + 1] > vlen - 4 - sub)
return -EBADMSG;
- key_len = v[sub + 1];
+ vlen = v[sub + 1];
v += (sub + 2);
}
- f = kmalloc(key_len * 2 + 1, GFP_KERNEL);
- if (!f)
- return -ENOMEM;
- for (i = 0; i < key_len; i++)
- sprintf(f + i * 2, "%02x", v[i]);
- pr_debug("authority %s\n", f);
- ctx->cert->authority = f;
+ kid = asymmetric_key_generate_id(v, vlen,
+ ctx->cert->raw_issuer,
+ ctx->cert->raw_issuer_size);
+ if (IS_ERR(kid))
+ return PTR_ERR(kid);
+ pr_debug("authkeyid %*phN\n", kid->len, kid->data);
+ ctx->cert->authority = kid;
return 0;
}