diff options
Diffstat (limited to 'crypto/asymmetric_keys')
-rw-r--r-- | crypto/asymmetric_keys/Makefile | 8 | ||||
-rw-r--r-- | crypto/asymmetric_keys/pkcs7_trust.c | 4 | ||||
-rw-r--r-- | crypto/asymmetric_keys/pkcs7_verify.c | 12 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_akid.asn1 | 35 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_cert_parser.c | 142 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_parser.h | 5 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_public_key.c | 8 |
7 files changed, 145 insertions, 69 deletions
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 | |||
15 | obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o | 15 | obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o |
16 | x509_key_parser-y := \ | 16 | x509_key_parser-y := \ |
17 | x509-asn1.o \ | 17 | x509-asn1.o \ |
18 | x509_akid-asn1.o \ | ||
18 | x509_rsakey-asn1.o \ | 19 | x509_rsakey-asn1.o \ |
19 | x509_cert_parser.o \ | 20 | x509_cert_parser.o \ |
20 | x509_public_key.o | 21 | x509_public_key.o |
21 | 22 | ||
22 | $(obj)/x509_cert_parser.o: $(obj)/x509-asn1.h $(obj)/x509_rsakey-asn1.h | 23 | $(obj)/x509_cert_parser.o: \ |
24 | $(obj)/x509-asn1.h \ | ||
25 | $(obj)/x509_akid-asn1.h \ | ||
26 | $(obj)/x509_rsakey-asn1.h | ||
23 | $(obj)/x509-asn1.o: $(obj)/x509-asn1.c $(obj)/x509-asn1.h | 27 | $(obj)/x509-asn1.o: $(obj)/x509-asn1.c $(obj)/x509-asn1.h |
28 | $(obj)/x509_akid-asn1.o: $(obj)/x509_akid-asn1.c $(obj)/x509_akid-asn1.h | ||
24 | $(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h | 29 | $(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h |
25 | 30 | ||
26 | clean-files += x509-asn1.c x509-asn1.h | 31 | clean-files += x509-asn1.c x509-asn1.h |
32 | clean-files += x509_akid-asn1.c x509_akid-asn1.h | ||
27 | clean-files += x509_rsakey-asn1.c x509_rsakey-asn1.h | 33 | clean-files += x509_rsakey-asn1.c x509_rsakey-asn1.h |
28 | 34 | ||
29 | # | 35 | # |
diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c index 1d29376072da..0f6463b6692b 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, | |||
85 | /* No match - see if the root certificate has a signer amongst the | 85 | /* No match - see if the root certificate has a signer amongst the |
86 | * trusted keys. | 86 | * trusted keys. |
87 | */ | 87 | */ |
88 | if (last && last->authority) { | 88 | if (last && last->akid_skid) { |
89 | key = x509_request_asymmetric_key(trust_keyring, last->authority, | 89 | key = x509_request_asymmetric_key(trust_keyring, last->akid_skid, |
90 | false); | 90 | false); |
91 | if (!IS_ERR(key)) { | 91 | if (!IS_ERR(key)) { |
92 | x509 = last; | 92 | x509 = last; |
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index cd455450b069..a4d083f7e9e1 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, | |||
187 | goto maybe_missing_crypto_in_x509; | 187 | goto maybe_missing_crypto_in_x509; |
188 | 188 | ||
189 | pr_debug("- issuer %s\n", x509->issuer); | 189 | pr_debug("- issuer %s\n", x509->issuer); |
190 | if (x509->authority) | 190 | if (x509->akid_skid) |
191 | pr_debug("- authkeyid %*phN\n", | 191 | pr_debug("- authkeyid %*phN\n", |
192 | x509->authority->len, x509->authority->data); | 192 | x509->akid_skid->len, x509->akid_skid->data); |
193 | 193 | ||
194 | if (!x509->authority || | 194 | if (!x509->akid_skid || |
195 | strcmp(x509->subject, x509->issuer) == 0) { | 195 | strcmp(x509->subject, x509->issuer) == 0) { |
196 | /* If there's no authority certificate specified, then | 196 | /* If there's no authority certificate specified, then |
197 | * the certificate must be self-signed and is the root | 197 | * the certificate must be self-signed and is the root |
@@ -216,13 +216,13 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, | |||
216 | * list to see if the next one is there. | 216 | * list to see if the next one is there. |
217 | */ | 217 | */ |
218 | pr_debug("- want %*phN\n", | 218 | pr_debug("- want %*phN\n", |
219 | x509->authority->len, x509->authority->data); | 219 | x509->akid_skid->len, x509->akid_skid->data); |
220 | for (p = pkcs7->certs; p; p = p->next) { | 220 | for (p = pkcs7->certs; p; p = p->next) { |
221 | if (!p->skid) | 221 | if (!p->skid) |
222 | continue; | 222 | continue; |
223 | pr_debug("- cmp [%u] %*phN\n", | 223 | pr_debug("- cmp [%u] %*phN\n", |
224 | p->index, p->skid->len, p->skid->data); | 224 | p->index, p->skid->len, p->skid->data); |
225 | if (asymmetric_key_id_same(p->skid, x509->authority)) | 225 | if (asymmetric_key_id_same(p->skid, x509->akid_skid)) |
226 | goto found_issuer; | 226 | goto found_issuer; |
227 | } | 227 | } |
228 | 228 | ||
@@ -338,8 +338,6 @@ int pkcs7_verify(struct pkcs7_message *pkcs7) | |||
338 | ret = x509_get_sig_params(x509); | 338 | ret = x509_get_sig_params(x509); |
339 | if (ret < 0) | 339 | if (ret < 0) |
340 | return ret; | 340 | return ret; |
341 | pr_debug("X.509[%u] %*phN\n", | ||
342 | n, x509->authority->len, x509->authority->data); | ||
343 | } | 341 | } |
344 | 342 | ||
345 | for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { | 343 | 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 @@ | |||
1 | -- X.509 AuthorityKeyIdentifier | ||
2 | -- rfc5280 section 4.2.1.1 | ||
3 | |||
4 | AuthorityKeyIdentifier ::= SEQUENCE { | ||
5 | keyIdentifier [0] IMPLICIT KeyIdentifier OPTIONAL, | ||
6 | authorityCertIssuer [1] IMPLICIT GeneralNames OPTIONAL, | ||
7 | authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL | ||
8 | } | ||
9 | |||
10 | KeyIdentifier ::= OCTET STRING ({ x509_akid_note_kid }) | ||
11 | |||
12 | CertificateSerialNumber ::= INTEGER ({ x509_akid_note_serial }) | ||
13 | |||
14 | GeneralNames ::= SEQUENCE OF GeneralName | ||
15 | |||
16 | GeneralName ::= CHOICE { | ||
17 | otherName [0] ANY, | ||
18 | rfc822Name [1] IA5String, | ||
19 | dNSName [2] IA5String, | ||
20 | x400Address [3] ANY, | ||
21 | directoryName [4] Name ({ x509_akid_note_name }), | ||
22 | ediPartyName [5] ANY, | ||
23 | uniformResourceIdentifier [6] IA5String, | ||
24 | iPAddress [7] OCTET STRING, | ||
25 | registeredID [8] OBJECT IDENTIFIER | ||
26 | } | ||
27 | |||
28 | Name ::= SEQUENCE OF RelativeDistinguishedName | ||
29 | |||
30 | RelativeDistinguishedName ::= SET OF AttributeValueAssertion | ||
31 | |||
32 | AttributeValueAssertion ::= SEQUENCE { | ||
33 | attributeType OBJECT IDENTIFIER ({ x509_note_OID }), | ||
34 | attributeValue ANY ({ x509_extract_name_segment }) | ||
35 | } | ||
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index a668d90302d3..6c130dd56f35 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include "public_key.h" | 18 | #include "public_key.h" |
19 | #include "x509_parser.h" | 19 | #include "x509_parser.h" |
20 | #include "x509-asn1.h" | 20 | #include "x509-asn1.h" |
21 | #include "x509_akid-asn1.h" | ||
21 | #include "x509_rsakey-asn1.h" | 22 | #include "x509_rsakey-asn1.h" |
22 | 23 | ||
23 | struct x509_parse_context { | 24 | struct x509_parse_context { |
@@ -35,6 +36,10 @@ struct x509_parse_context { | |||
35 | u16 o_offset; /* Offset of organizationName (O) */ | 36 | u16 o_offset; /* Offset of organizationName (O) */ |
36 | u16 cn_offset; /* Offset of commonName (CN) */ | 37 | u16 cn_offset; /* Offset of commonName (CN) */ |
37 | u16 email_offset; /* Offset of emailAddress */ | 38 | u16 email_offset; /* Offset of emailAddress */ |
39 | unsigned raw_akid_size; | ||
40 | const void *raw_akid; /* Raw authorityKeyId in ASN.1 */ | ||
41 | const void *akid_raw_issuer; /* Raw directoryName in authorityKeyId */ | ||
42 | unsigned akid_raw_issuer_size; | ||
38 | }; | 43 | }; |
39 | 44 | ||
40 | /* | 45 | /* |
@@ -48,7 +53,8 @@ void x509_free_certificate(struct x509_certificate *cert) | |||
48 | kfree(cert->subject); | 53 | kfree(cert->subject); |
49 | kfree(cert->id); | 54 | kfree(cert->id); |
50 | kfree(cert->skid); | 55 | kfree(cert->skid); |
51 | kfree(cert->authority); | 56 | kfree(cert->akid_id); |
57 | kfree(cert->akid_skid); | ||
52 | kfree(cert->sig.digest); | 58 | kfree(cert->sig.digest); |
53 | mpi_free(cert->sig.rsa.s); | 59 | mpi_free(cert->sig.rsa.s); |
54 | kfree(cert); | 60 | kfree(cert); |
@@ -85,6 +91,18 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) | |||
85 | if (ret < 0) | 91 | if (ret < 0) |
86 | goto error_decode; | 92 | goto error_decode; |
87 | 93 | ||
94 | /* Decode the AuthorityKeyIdentifier */ | ||
95 | if (ctx->raw_akid) { | ||
96 | pr_devel("AKID: %u %*phN\n", | ||
97 | ctx->raw_akid_size, ctx->raw_akid_size, ctx->raw_akid); | ||
98 | ret = asn1_ber_decoder(&x509_akid_decoder, ctx, | ||
99 | ctx->raw_akid, ctx->raw_akid_size); | ||
100 | if (ret < 0) { | ||
101 | pr_warn("Couldn't decode AuthKeyIdentifier\n"); | ||
102 | goto error_decode; | ||
103 | } | ||
104 | } | ||
105 | |||
88 | /* Decode the public key */ | 106 | /* Decode the public key */ |
89 | ret = asn1_ber_decoder(&x509_rsakey_decoder, ctx, | 107 | ret = asn1_ber_decoder(&x509_rsakey_decoder, ctx, |
90 | ctx->key, ctx->key_size); | 108 | ctx->key, ctx->key_size); |
@@ -422,7 +440,6 @@ int x509_process_extension(void *context, size_t hdrlen, | |||
422 | struct x509_parse_context *ctx = context; | 440 | struct x509_parse_context *ctx = context; |
423 | struct asymmetric_key_id *kid; | 441 | struct asymmetric_key_id *kid; |
424 | const unsigned char *v = value; | 442 | const unsigned char *v = value; |
425 | int i; | ||
426 | 443 | ||
427 | pr_debug("Extension: %u\n", ctx->last_oid); | 444 | pr_debug("Extension: %u\n", ctx->last_oid); |
428 | 445 | ||
@@ -449,57 +466,8 @@ int x509_process_extension(void *context, size_t hdrlen, | |||
449 | 466 | ||
450 | if (ctx->last_oid == OID_authorityKeyIdentifier) { | 467 | if (ctx->last_oid == OID_authorityKeyIdentifier) { |
451 | /* Get hold of the CA key fingerprint */ | 468 | /* Get hold of the CA key fingerprint */ |
452 | if (ctx->cert->authority || vlen < 5) | 469 | ctx->raw_akid = v; |
453 | return -EBADMSG; | 470 | ctx->raw_akid_size = vlen; |
454 | |||
455 | /* Authority Key Identifier must be a Constructed SEQUENCE */ | ||
456 | if (v[0] != (ASN1_SEQ | (ASN1_CONS << 5))) | ||
457 | return -EBADMSG; | ||
458 | |||
459 | /* Authority Key Identifier is not indefinite length */ | ||
460 | if (unlikely(vlen == ASN1_INDEFINITE_LENGTH)) | ||
461 | return -EBADMSG; | ||
462 | |||
463 | if (vlen < ASN1_INDEFINITE_LENGTH) { | ||
464 | /* Short Form length */ | ||
465 | if (v[1] != vlen - 2 || | ||
466 | v[2] != SEQ_TAG_KEYID || | ||
467 | v[3] > vlen - 4) | ||
468 | return -EBADMSG; | ||
469 | |||
470 | vlen = v[3]; | ||
471 | v += 4; | ||
472 | } else { | ||
473 | /* Long Form length */ | ||
474 | size_t seq_len = 0; | ||
475 | size_t sub = v[1] - ASN1_INDEFINITE_LENGTH; | ||
476 | |||
477 | if (sub > 2) | ||
478 | return -EBADMSG; | ||
479 | |||
480 | /* calculate the length from subsequent octets */ | ||
481 | v += 2; | ||
482 | for (i = 0; i < sub; i++) { | ||
483 | seq_len <<= 8; | ||
484 | seq_len |= v[i]; | ||
485 | } | ||
486 | |||
487 | if (seq_len != vlen - 2 - sub || | ||
488 | v[sub] != SEQ_TAG_KEYID || | ||
489 | v[sub + 1] > vlen - 4 - sub) | ||
490 | return -EBADMSG; | ||
491 | |||
492 | vlen = v[sub + 1]; | ||
493 | v += (sub + 2); | ||
494 | } | ||
495 | |||
496 | kid = asymmetric_key_generate_id(ctx->cert->raw_issuer, | ||
497 | ctx->cert->raw_issuer_size, | ||
498 | v, vlen); | ||
499 | if (IS_ERR(kid)) | ||
500 | return PTR_ERR(kid); | ||
501 | pr_debug("authkeyid %*phN\n", kid->len, kid->data); | ||
502 | ctx->cert->authority = kid; | ||
503 | return 0; | 471 | return 0; |
504 | } | 472 | } |
505 | 473 | ||
@@ -569,3 +537,71 @@ int x509_note_not_after(void *context, size_t hdrlen, | |||
569 | struct x509_parse_context *ctx = context; | 537 | struct x509_parse_context *ctx = context; |
570 | return x509_note_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen); | 538 | return x509_note_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen); |
571 | } | 539 | } |
540 | |||
541 | /* | ||
542 | * Note a key identifier-based AuthorityKeyIdentifier | ||
543 | */ | ||
544 | int x509_akid_note_kid(void *context, size_t hdrlen, | ||
545 | unsigned char tag, | ||
546 | const void *value, size_t vlen) | ||
547 | { | ||
548 | struct x509_parse_context *ctx = context; | ||
549 | struct asymmetric_key_id *kid; | ||
550 | |||
551 | pr_debug("AKID: keyid: %*phN\n", (int)vlen, value); | ||
552 | |||
553 | if (ctx->cert->akid_skid) | ||
554 | return 0; | ||
555 | |||
556 | kid = asymmetric_key_generate_id(ctx->cert->raw_issuer, | ||
557 | ctx->cert->raw_issuer_size, | ||
558 | value, vlen); | ||
559 | if (IS_ERR(kid)) | ||
560 | return PTR_ERR(kid); | ||
561 | pr_debug("authkeyid %*phN\n", kid->len, kid->data); | ||
562 | ctx->cert->akid_skid = kid; | ||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | /* | ||
567 | * Note a directoryName in an AuthorityKeyIdentifier | ||
568 | */ | ||
569 | int x509_akid_note_name(void *context, size_t hdrlen, | ||
570 | unsigned char tag, | ||
571 | const void *value, size_t vlen) | ||
572 | { | ||
573 | struct x509_parse_context *ctx = context; | ||
574 | |||
575 | pr_debug("AKID: name: %*phN\n", (int)vlen, value); | ||
576 | |||
577 | ctx->akid_raw_issuer = value; | ||
578 | ctx->akid_raw_issuer_size = vlen; | ||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | /* | ||
583 | * Note a serial number in an AuthorityKeyIdentifier | ||
584 | */ | ||
585 | int x509_akid_note_serial(void *context, size_t hdrlen, | ||
586 | unsigned char tag, | ||
587 | const void *value, size_t vlen) | ||
588 | { | ||
589 | struct x509_parse_context *ctx = context; | ||
590 | struct asymmetric_key_id *kid; | ||
591 | |||
592 | pr_debug("AKID: serial: %*phN\n", (int)vlen, value); | ||
593 | |||
594 | if (!ctx->akid_raw_issuer || ctx->cert->akid_id) | ||
595 | return 0; | ||
596 | |||
597 | kid = asymmetric_key_generate_id(value, | ||
598 | vlen, | ||
599 | ctx->akid_raw_issuer, | ||
600 | ctx->akid_raw_issuer_size); | ||
601 | if (IS_ERR(kid)) | ||
602 | return PTR_ERR(kid); | ||
603 | |||
604 | pr_debug("authkeyid %*phN\n", kid->len, kid->data); | ||
605 | ctx->cert->akid_id = kid; | ||
606 | return 0; | ||
607 | } | ||
diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h index 3dfe6b5d6f0b..dcdb5c94f514 100644 --- a/crypto/asymmetric_keys/x509_parser.h +++ b/crypto/asymmetric_keys/x509_parser.h | |||
@@ -19,9 +19,10 @@ struct x509_certificate { | |||
19 | struct public_key_signature sig; /* Signature parameters */ | 19 | struct public_key_signature sig; /* Signature parameters */ |
20 | char *issuer; /* Name of certificate issuer */ | 20 | char *issuer; /* Name of certificate issuer */ |
21 | char *subject; /* Name of certificate subject */ | 21 | char *subject; /* Name of certificate subject */ |
22 | struct asymmetric_key_id *id; /* Serial number + issuer */ | 22 | struct asymmetric_key_id *id; /* Issuer + Serial number */ |
23 | struct asymmetric_key_id *skid; /* Subject + subjectKeyId (optional) */ | 23 | struct asymmetric_key_id *skid; /* Subject + subjectKeyId (optional) */ |
24 | struct asymmetric_key_id *authority; /* Authority key identifier (optional) */ | 24 | struct asymmetric_key_id *akid_id; /* CA AuthKeyId matching ->id (optional) */ |
25 | struct asymmetric_key_id *akid_skid; /* CA AuthKeyId matching ->skid (optional) */ | ||
25 | struct tm valid_from; | 26 | struct tm valid_from; |
26 | struct tm valid_to; | 27 | struct tm valid_to; |
27 | const void *tbs; /* Signed data */ | 28 | const void *tbs; /* Signed data */ |
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 24f17e6c5904..bb55d6074d5f 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c | |||
@@ -227,10 +227,10 @@ static int x509_validate_trust(struct x509_certificate *cert, | |||
227 | if (!trust_keyring) | 227 | if (!trust_keyring) |
228 | return -EOPNOTSUPP; | 228 | return -EOPNOTSUPP; |
229 | 229 | ||
230 | if (ca_keyid && !asymmetric_key_id_partial(cert->authority, ca_keyid)) | 230 | if (ca_keyid && !asymmetric_key_id_partial(cert->akid_skid, ca_keyid)) |
231 | return -EPERM; | 231 | return -EPERM; |
232 | 232 | ||
233 | key = x509_request_asymmetric_key(trust_keyring, cert->authority, | 233 | key = x509_request_asymmetric_key(trust_keyring, cert->akid_skid, |
234 | false); | 234 | false); |
235 | if (!IS_ERR(key)) { | 235 | if (!IS_ERR(key)) { |
236 | if (!use_builtin_keys | 236 | if (!use_builtin_keys |
@@ -287,8 +287,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) | |||
287 | cert->pub->id_type = PKEY_ID_X509; | 287 | cert->pub->id_type = PKEY_ID_X509; |
288 | 288 | ||
289 | /* Check the signature on the key if it appears to be self-signed */ | 289 | /* Check the signature on the key if it appears to be self-signed */ |
290 | if (!cert->authority || | 290 | if (!cert->akid_skid || |
291 | asymmetric_key_id_same(cert->skid, cert->authority)) { | 291 | asymmetric_key_id_same(cert->skid, cert->akid_skid)) { |
292 | ret = x509_check_signature(cert->pub, cert); /* self-signed */ | 292 | ret = x509_check_signature(cert->pub, cert); /* self-signed */ |
293 | if (ret < 0) | 293 | if (ret < 0) |
294 | goto error_free_cert; | 294 | goto error_free_cert; |