summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-09-08 15:41:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-08 15:41:25 -0400
commitb793c005ceabf6db0b17494b0ec67ade6796bb34 (patch)
tree080c884f04254403ec9564742f591a9fd9b7e95a /crypto
parent6f0a2fc1feb19bd142961a39dc118e7e55418b3f (diff)
parent07f081fb5057b2ea98baeca3a47bf0eb33e94aa1 (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris: "Highlights: - PKCS#7 support added to support signed kexec, also utilized for module signing. See comments in 3f1e1bea. ** NOTE: this requires linking against the OpenSSL library, which must be installed, e.g. the openssl-devel on Fedora ** - Smack - add IPv6 host labeling; ignore labels on kernel threads - support smack labeling mounts which use binary mount data - SELinux: - add ioctl whitelisting (see http://kernsec.org/files/lss2015/vanderstoep.pdf) - fix mprotect PROT_EXEC regression caused by mm change - Seccomp: - add ptrace options for suspend/resume" * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (57 commits) PKCS#7: Add OIDs for sha224, sha284 and sha512 hash algos and use them Documentation/Changes: Now need OpenSSL devel packages for module signing scripts: add extract-cert and sign-file to .gitignore modsign: Handle signing key in source tree modsign: Use if_changed rule for extracting cert from module signing key Move certificate handling to its own directory sign-file: Fix warning about BIO_reset() return value PKCS#7: Add MODULE_LICENSE() to test module Smack - Fix build error with bringup unconfigured sign-file: Document dependency on OpenSSL devel libraries PKCS#7: Appropriately restrict authenticated attributes and content type KEYS: Add a name for PKEY_ID_PKCS7 PKCS#7: Improve and export the X.509 ASN.1 time object decoder modsign: Use extract-cert to process CONFIG_SYSTEM_TRUSTED_KEYS extract-cert: Cope with multiple X.509 certificates in a single file sign-file: Generate CMS message as signature instead of PKCS#7 PKCS#7: Support CMS messages also [RFC5652] X.509: Change recorded SKID & AKID to not include Subject or Issuer PKCS#7: Check content type and versions MAINTAINERS: The keyrings mailing list has moved ...
Diffstat (limited to 'crypto')
-rw-r--r--crypto/Kconfig1
-rw-r--r--crypto/asymmetric_keys/Makefile8
-rw-r--r--crypto/asymmetric_keys/asymmetric_type.c11
-rw-r--r--crypto/asymmetric_keys/mscode_parser.c9
-rw-r--r--crypto/asymmetric_keys/pkcs7.asn122
-rw-r--r--crypto/asymmetric_keys/pkcs7_key_type.c17
-rw-r--r--crypto/asymmetric_keys/pkcs7_parser.c277
-rw-r--r--crypto/asymmetric_keys/pkcs7_parser.h20
-rw-r--r--crypto/asymmetric_keys/pkcs7_trust.c10
-rw-r--r--crypto/asymmetric_keys/pkcs7_verify.c145
-rw-r--r--crypto/asymmetric_keys/public_key.c1
-rw-r--r--crypto/asymmetric_keys/verify_pefile.c7
-rw-r--r--crypto/asymmetric_keys/x509_akid.asn135
-rw-r--r--crypto/asymmetric_keys/x509_cert_parser.c231
-rw-r--r--crypto/asymmetric_keys/x509_parser.h12
-rw-r--r--crypto/asymmetric_keys/x509_public_key.c95
16 files changed, 738 insertions, 163 deletions
diff --git a/crypto/Kconfig b/crypto/Kconfig
index b582ea7f78d3..48ee3e175dac 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1635,5 +1635,6 @@ config CRYPTO_HASH_INFO
1635 1635
1636source "drivers/crypto/Kconfig" 1636source "drivers/crypto/Kconfig"
1637source crypto/asymmetric_keys/Kconfig 1637source crypto/asymmetric_keys/Kconfig
1638source certs/Kconfig
1638 1639
1639endif # if CRYPTO 1640endif # if CRYPTO
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
15obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o 15obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o
16x509_key_parser-y := \ 16x509_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
26clean-files += x509-asn1.c x509-asn1.h 31clean-files += x509-asn1.c x509-asn1.h
32clean-files += x509_akid-asn1.c x509_akid-asn1.h
27clean-files += x509_rsakey-asn1.c x509_rsakey-asn1.h 33clean-files += x509_rsakey-asn1.c x509_rsakey-asn1.h
28 34
29# 35#
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index b0e4ed23d668..1916680ad81b 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -12,6 +12,7 @@
12 */ 12 */
13#include <keys/asymmetric-subtype.h> 13#include <keys/asymmetric-subtype.h>
14#include <keys/asymmetric-parser.h> 14#include <keys/asymmetric-parser.h>
15#include <crypto/public_key.h>
15#include <linux/seq_file.h> 16#include <linux/seq_file.h>
16#include <linux/module.h> 17#include <linux/module.h>
17#include <linux/slab.h> 18#include <linux/slab.h>
@@ -20,6 +21,16 @@
20 21
21MODULE_LICENSE("GPL"); 22MODULE_LICENSE("GPL");
22 23
24const char *const key_being_used_for[NR__KEY_BEING_USED_FOR] = {
25 [VERIFYING_MODULE_SIGNATURE] = "mod sig",
26 [VERIFYING_FIRMWARE_SIGNATURE] = "firmware sig",
27 [VERIFYING_KEXEC_PE_SIGNATURE] = "kexec PE sig",
28 [VERIFYING_KEY_SIGNATURE] = "key sig",
29 [VERIFYING_KEY_SELF_SIGNATURE] = "key self sig",
30 [VERIFYING_UNSPECIFIED_SIGNATURE] = "unspec sig",
31};
32EXPORT_SYMBOL_GPL(key_being_used_for);
33
23static LIST_HEAD(asymmetric_key_parsers); 34static LIST_HEAD(asymmetric_key_parsers);
24static DECLARE_RWSEM(asymmetric_key_parsers_sem); 35static DECLARE_RWSEM(asymmetric_key_parsers_sem);
25 36
diff --git a/crypto/asymmetric_keys/mscode_parser.c b/crypto/asymmetric_keys/mscode_parser.c
index 214a992123cd..adcef59eec0b 100644
--- a/crypto/asymmetric_keys/mscode_parser.c
+++ b/crypto/asymmetric_keys/mscode_parser.c
@@ -97,6 +97,15 @@ int mscode_note_digest_algo(void *context, size_t hdrlen,
97 case OID_sha256: 97 case OID_sha256:
98 ctx->digest_algo = HASH_ALGO_SHA256; 98 ctx->digest_algo = HASH_ALGO_SHA256;
99 break; 99 break;
100 case OID_sha384:
101 ctx->digest_algo = HASH_ALGO_SHA384;
102 break;
103 case OID_sha512:
104 ctx->digest_algo = HASH_ALGO_SHA512;
105 break;
106 case OID_sha224:
107 ctx->digest_algo = HASH_ALGO_SHA224;
108 break;
100 109
101 case OID__NR: 110 case OID__NR:
102 sprint_oid(value, vlen, buffer, sizeof(buffer)); 111 sprint_oid(value, vlen, buffer, sizeof(buffer));
diff --git a/crypto/asymmetric_keys/pkcs7.asn1 b/crypto/asymmetric_keys/pkcs7.asn1
index a5a14ef28c86..1eca740b816a 100644
--- a/crypto/asymmetric_keys/pkcs7.asn1
+++ b/crypto/asymmetric_keys/pkcs7.asn1
@@ -1,14 +1,14 @@
1PKCS7ContentInfo ::= SEQUENCE { 1PKCS7ContentInfo ::= SEQUENCE {
2 contentType ContentType, 2 contentType ContentType ({ pkcs7_check_content_type }),
3 content [0] EXPLICIT SignedData OPTIONAL 3 content [0] EXPLICIT SignedData OPTIONAL
4} 4}
5 5
6ContentType ::= OBJECT IDENTIFIER ({ pkcs7_note_OID }) 6ContentType ::= OBJECT IDENTIFIER ({ pkcs7_note_OID })
7 7
8SignedData ::= SEQUENCE { 8SignedData ::= SEQUENCE {
9 version INTEGER, 9 version INTEGER ({ pkcs7_note_signeddata_version }),
10 digestAlgorithms DigestAlgorithmIdentifiers, 10 digestAlgorithms DigestAlgorithmIdentifiers,
11 contentInfo ContentInfo, 11 contentInfo ContentInfo ({ pkcs7_note_content }),
12 certificates CHOICE { 12 certificates CHOICE {
13 certSet [0] IMPLICIT ExtendedCertificatesAndCertificates, 13 certSet [0] IMPLICIT ExtendedCertificatesAndCertificates,
14 certSequence [2] IMPLICIT Certificates 14 certSequence [2] IMPLICIT Certificates
@@ -21,7 +21,7 @@ SignedData ::= SEQUENCE {
21} 21}
22 22
23ContentInfo ::= SEQUENCE { 23ContentInfo ::= SEQUENCE {
24 contentType ContentType, 24 contentType ContentType ({ pkcs7_note_OID }),
25 content [0] EXPLICIT Data OPTIONAL 25 content [0] EXPLICIT Data OPTIONAL
26} 26}
27 27
@@ -68,8 +68,8 @@ SignerInfos ::= CHOICE {
68} 68}
69 69
70SignerInfo ::= SEQUENCE { 70SignerInfo ::= SEQUENCE {
71 version INTEGER, 71 version INTEGER ({ pkcs7_note_signerinfo_version }),
72 issuerAndSerialNumber IssuerAndSerialNumber, 72 sid SignerIdentifier, -- CMS variant, not PKCS#7
73 digestAlgorithm DigestAlgorithmIdentifier ({ pkcs7_sig_note_digest_algo }), 73 digestAlgorithm DigestAlgorithmIdentifier ({ pkcs7_sig_note_digest_algo }),
74 authenticatedAttributes CHOICE { 74 authenticatedAttributes CHOICE {
75 aaSet [0] IMPLICIT SetOfAuthenticatedAttribute 75 aaSet [0] IMPLICIT SetOfAuthenticatedAttribute
@@ -88,6 +88,12 @@ SignerInfo ::= SEQUENCE {
88 } OPTIONAL 88 } OPTIONAL
89} ({ pkcs7_note_signed_info }) 89} ({ pkcs7_note_signed_info })
90 90
91SignerIdentifier ::= CHOICE {
92 -- RFC5652 sec 5.3
93 issuerAndSerialNumber IssuerAndSerialNumber,
94 subjectKeyIdentifier [0] IMPLICIT SubjectKeyIdentifier
95}
96
91IssuerAndSerialNumber ::= SEQUENCE { 97IssuerAndSerialNumber ::= SEQUENCE {
92 issuer Name ({ pkcs7_sig_note_issuer }), 98 issuer Name ({ pkcs7_sig_note_issuer }),
93 serialNumber CertificateSerialNumber ({ pkcs7_sig_note_serial }) 99 serialNumber CertificateSerialNumber ({ pkcs7_sig_note_serial })
@@ -95,6 +101,8 @@ IssuerAndSerialNumber ::= SEQUENCE {
95 101
96CertificateSerialNumber ::= INTEGER 102CertificateSerialNumber ::= INTEGER
97 103
104SubjectKeyIdentifier ::= OCTET STRING ({ pkcs7_sig_note_skid })
105
98SetOfAuthenticatedAttribute ::= SET OF AuthenticatedAttribute 106SetOfAuthenticatedAttribute ::= SET OF AuthenticatedAttribute
99 107
100AuthenticatedAttribute ::= SEQUENCE { 108AuthenticatedAttribute ::= SEQUENCE {
@@ -103,7 +111,7 @@ AuthenticatedAttribute ::= SEQUENCE {
103} 111}
104 112
105UnauthenticatedAttribute ::= SEQUENCE { 113UnauthenticatedAttribute ::= SEQUENCE {
106 type OBJECT IDENTIFIER ({ pkcs7_note_OID }), 114 type OBJECT IDENTIFIER,
107 values SET OF ANY 115 values SET OF ANY
108} 116}
109 117
diff --git a/crypto/asymmetric_keys/pkcs7_key_type.c b/crypto/asymmetric_keys/pkcs7_key_type.c
index 3d13b042da73..e2d0edbbc71a 100644
--- a/crypto/asymmetric_keys/pkcs7_key_type.c
+++ b/crypto/asymmetric_keys/pkcs7_key_type.c
@@ -14,16 +14,26 @@
14#include <linux/err.h> 14#include <linux/err.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/key-type.h> 16#include <linux/key-type.h>
17#include <keys/asymmetric-type.h>
17#include <crypto/pkcs7.h> 18#include <crypto/pkcs7.h>
18#include <keys/user-type.h> 19#include <keys/user-type.h>
19#include <keys/system_keyring.h> 20#include <keys/system_keyring.h>
20#include "pkcs7_parser.h" 21#include "pkcs7_parser.h"
21 22
23MODULE_LICENSE("GPL");
24MODULE_DESCRIPTION("PKCS#7 testing key type");
25
26static unsigned pkcs7_usage;
27module_param_named(usage, pkcs7_usage, uint, S_IWUSR | S_IRUGO);
28MODULE_PARM_DESC(pkcs7_usage,
29 "Usage to specify when verifying the PKCS#7 message");
30
22/* 31/*
23 * Preparse a PKCS#7 wrapped and validated data blob. 32 * Preparse a PKCS#7 wrapped and validated data blob.
24 */ 33 */
25static int pkcs7_preparse(struct key_preparsed_payload *prep) 34static int pkcs7_preparse(struct key_preparsed_payload *prep)
26{ 35{
36 enum key_being_used_for usage = pkcs7_usage;
27 struct pkcs7_message *pkcs7; 37 struct pkcs7_message *pkcs7;
28 const void *data, *saved_prep_data; 38 const void *data, *saved_prep_data;
29 size_t datalen, saved_prep_datalen; 39 size_t datalen, saved_prep_datalen;
@@ -32,6 +42,11 @@ static int pkcs7_preparse(struct key_preparsed_payload *prep)
32 42
33 kenter(""); 43 kenter("");
34 44
45 if (usage >= NR__KEY_BEING_USED_FOR) {
46 pr_err("Invalid usage type %d\n", usage);
47 return -EINVAL;
48 }
49
35 saved_prep_data = prep->data; 50 saved_prep_data = prep->data;
36 saved_prep_datalen = prep->datalen; 51 saved_prep_datalen = prep->datalen;
37 pkcs7 = pkcs7_parse_message(saved_prep_data, saved_prep_datalen); 52 pkcs7 = pkcs7_parse_message(saved_prep_data, saved_prep_datalen);
@@ -40,7 +55,7 @@ static int pkcs7_preparse(struct key_preparsed_payload *prep)
40 goto error; 55 goto error;
41 } 56 }
42 57
43 ret = pkcs7_verify(pkcs7); 58 ret = pkcs7_verify(pkcs7, usage);
44 if (ret < 0) 59 if (ret < 0)
45 goto error_free; 60 goto error_free;
46 61
diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c
index 3bd5a1e4c493..758acabf2d81 100644
--- a/crypto/asymmetric_keys/pkcs7_parser.c
+++ b/crypto/asymmetric_keys/pkcs7_parser.c
@@ -33,6 +33,9 @@ struct pkcs7_parse_context {
33 unsigned raw_serial_size; 33 unsigned raw_serial_size;
34 unsigned raw_issuer_size; 34 unsigned raw_issuer_size;
35 const void *raw_issuer; 35 const void *raw_issuer;
36 const void *raw_skid;
37 unsigned raw_skid_size;
38 bool expect_skid;
36}; 39};
37 40
38/* 41/*
@@ -78,6 +81,30 @@ void pkcs7_free_message(struct pkcs7_message *pkcs7)
78} 81}
79EXPORT_SYMBOL_GPL(pkcs7_free_message); 82EXPORT_SYMBOL_GPL(pkcs7_free_message);
80 83
84/*
85 * Check authenticatedAttributes are provided or not provided consistently.
86 */
87static int pkcs7_check_authattrs(struct pkcs7_message *msg)
88{
89 struct pkcs7_signed_info *sinfo;
90 bool want;
91
92 sinfo = msg->signed_infos;
93 if (sinfo->authattrs) {
94 want = true;
95 msg->have_authattrs = true;
96 }
97
98 for (sinfo = sinfo->next; sinfo; sinfo = sinfo->next)
99 if (!!sinfo->authattrs != want)
100 goto inconsistent;
101 return 0;
102
103inconsistent:
104 pr_warn("Inconsistently supplied authAttrs\n");
105 return -EINVAL;
106}
107
81/** 108/**
82 * pkcs7_parse_message - Parse a PKCS#7 message 109 * pkcs7_parse_message - Parse a PKCS#7 message
83 * @data: The raw binary ASN.1 encoded message to be parsed 110 * @data: The raw binary ASN.1 encoded message to be parsed
@@ -110,6 +137,10 @@ struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen)
110 goto out; 137 goto out;
111 } 138 }
112 139
140 ret = pkcs7_check_authattrs(ctx->msg);
141 if (ret < 0)
142 goto out;
143
113 msg = ctx->msg; 144 msg = ctx->msg;
114 ctx->msg = NULL; 145 ctx->msg = NULL;
115 146
@@ -198,6 +229,14 @@ int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen,
198 case OID_sha256: 229 case OID_sha256:
199 ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA256; 230 ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA256;
200 break; 231 break;
232 case OID_sha384:
233 ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA384;
234 break;
235 case OID_sha512:
236 ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA512;
237 break;
238 case OID_sha224:
239 ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA224;
201 default: 240 default:
202 printk("Unsupported digest algo: %u\n", ctx->last_oid); 241 printk("Unsupported digest algo: %u\n", ctx->last_oid);
203 return -ENOPKG; 242 return -ENOPKG;
@@ -226,6 +265,100 @@ int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen,
226} 265}
227 266
228/* 267/*
268 * We only support signed data [RFC2315 sec 9].
269 */
270int pkcs7_check_content_type(void *context, size_t hdrlen,
271 unsigned char tag,
272 const void *value, size_t vlen)
273{
274 struct pkcs7_parse_context *ctx = context;
275
276 if (ctx->last_oid != OID_signed_data) {
277 pr_warn("Only support pkcs7_signedData type\n");
278 return -EINVAL;
279 }
280
281 return 0;
282}
283
284/*
285 * Note the SignedData version
286 */
287int pkcs7_note_signeddata_version(void *context, size_t hdrlen,
288 unsigned char tag,
289 const void *value, size_t vlen)
290{
291 struct pkcs7_parse_context *ctx = context;
292 unsigned version;
293
294 if (vlen != 1)
295 goto unsupported;
296
297 ctx->msg->version = version = *(const u8 *)value;
298 switch (version) {
299 case 1:
300 /* PKCS#7 SignedData [RFC2315 sec 9.1]
301 * CMS ver 1 SignedData [RFC5652 sec 5.1]
302 */
303 break;
304 case 3:
305 /* CMS ver 3 SignedData [RFC2315 sec 5.1] */
306 break;
307 default:
308 goto unsupported;
309 }
310
311 return 0;
312
313unsupported:
314 pr_warn("Unsupported SignedData version\n");
315 return -EINVAL;
316}
317
318/*
319 * Note the SignerInfo version
320 */
321int pkcs7_note_signerinfo_version(void *context, size_t hdrlen,
322 unsigned char tag,
323 const void *value, size_t vlen)
324{
325 struct pkcs7_parse_context *ctx = context;
326 unsigned version;
327
328 if (vlen != 1)
329 goto unsupported;
330
331 version = *(const u8 *)value;
332 switch (version) {
333 case 1:
334 /* PKCS#7 SignerInfo [RFC2315 sec 9.2]
335 * CMS ver 1 SignerInfo [RFC5652 sec 5.3]
336 */
337 if (ctx->msg->version != 1)
338 goto version_mismatch;
339 ctx->expect_skid = false;
340 break;
341 case 3:
342 /* CMS ver 3 SignerInfo [RFC2315 sec 5.3] */
343 if (ctx->msg->version == 1)
344 goto version_mismatch;
345 ctx->expect_skid = true;
346 break;
347 default:
348 goto unsupported;
349 }
350
351 return 0;
352
353unsupported:
354 pr_warn("Unsupported SignerInfo version\n");
355 return -EINVAL;
356version_mismatch:
357 pr_warn("SignedData-SignerInfo version mismatch\n");
358 return -EBADMSG;
359}
360
361/*
229 * Extract a certificate and store it in the context. 362 * Extract a certificate and store it in the context.
230 */ 363 */
231int pkcs7_extract_cert(void *context, size_t hdrlen, 364int pkcs7_extract_cert(void *context, size_t hdrlen,
@@ -284,6 +417,25 @@ int pkcs7_note_certificate_list(void *context, size_t hdrlen,
284} 417}
285 418
286/* 419/*
420 * Note the content type.
421 */
422int pkcs7_note_content(void *context, size_t hdrlen,
423 unsigned char tag,
424 const void *value, size_t vlen)
425{
426 struct pkcs7_parse_context *ctx = context;
427
428 if (ctx->last_oid != OID_data &&
429 ctx->last_oid != OID_msIndirectData) {
430 pr_warn("Unsupported data type %d\n", ctx->last_oid);
431 return -EINVAL;
432 }
433
434 ctx->msg->data_type = ctx->last_oid;
435 return 0;
436}
437
438/*
287 * Extract the data from the message and store that and its content type OID in 439 * Extract the data from the message and store that and its content type OID in
288 * the context. 440 * the context.
289 */ 441 */
@@ -298,45 +450,119 @@ int pkcs7_note_data(void *context, size_t hdrlen,
298 ctx->msg->data = value; 450 ctx->msg->data = value;
299 ctx->msg->data_len = vlen; 451 ctx->msg->data_len = vlen;
300 ctx->msg->data_hdrlen = hdrlen; 452 ctx->msg->data_hdrlen = hdrlen;
301 ctx->msg->data_type = ctx->last_oid;
302 return 0; 453 return 0;
303} 454}
304 455
305/* 456/*
306 * Parse authenticated attributes 457 * Parse authenticated attributes.
307 */ 458 */
308int pkcs7_sig_note_authenticated_attr(void *context, size_t hdrlen, 459int pkcs7_sig_note_authenticated_attr(void *context, size_t hdrlen,
309 unsigned char tag, 460 unsigned char tag,
310 const void *value, size_t vlen) 461 const void *value, size_t vlen)
311{ 462{
312 struct pkcs7_parse_context *ctx = context; 463 struct pkcs7_parse_context *ctx = context;
464 struct pkcs7_signed_info *sinfo = ctx->sinfo;
465 enum OID content_type;
313 466
314 pr_devel("AuthAttr: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value); 467 pr_devel("AuthAttr: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value);
315 468
316 switch (ctx->last_oid) { 469 switch (ctx->last_oid) {
470 case OID_contentType:
471 if (__test_and_set_bit(sinfo_has_content_type, &sinfo->aa_set))
472 goto repeated;
473 content_type = look_up_OID(value, vlen);
474 if (content_type != ctx->msg->data_type) {
475 pr_warn("Mismatch between global data type (%d) and sinfo %u (%d)\n",
476 ctx->msg->data_type, sinfo->index,
477 content_type);
478 return -EBADMSG;
479 }
480 return 0;
481
482 case OID_signingTime:
483 if (__test_and_set_bit(sinfo_has_signing_time, &sinfo->aa_set))
484 goto repeated;
485 /* Should we check that the signing time is consistent
486 * with the signer's X.509 cert?
487 */
488 return x509_decode_time(&sinfo->signing_time,
489 hdrlen, tag, value, vlen);
490
317 case OID_messageDigest: 491 case OID_messageDigest:
492 if (__test_and_set_bit(sinfo_has_message_digest, &sinfo->aa_set))
493 goto repeated;
318 if (tag != ASN1_OTS) 494 if (tag != ASN1_OTS)
319 return -EBADMSG; 495 return -EBADMSG;
320 ctx->sinfo->msgdigest = value; 496 sinfo->msgdigest = value;
321 ctx->sinfo->msgdigest_len = vlen; 497 sinfo->msgdigest_len = vlen;
498 return 0;
499
500 case OID_smimeCapabilites:
501 if (__test_and_set_bit(sinfo_has_smime_caps, &sinfo->aa_set))
502 goto repeated;
503 if (ctx->msg->data_type != OID_msIndirectData) {
504 pr_warn("S/MIME Caps only allowed with Authenticode\n");
505 return -EKEYREJECTED;
506 }
507 return 0;
508
509 /* Microsoft SpOpusInfo seems to be contain cont[0] 16-bit BE
510 * char URLs and cont[1] 8-bit char URLs.
511 *
512 * Microsoft StatementType seems to contain a list of OIDs that
513 * are also used as extendedKeyUsage types in X.509 certs.
514 */
515 case OID_msSpOpusInfo:
516 if (__test_and_set_bit(sinfo_has_ms_opus_info, &sinfo->aa_set))
517 goto repeated;
518 goto authenticode_check;
519 case OID_msStatementType:
520 if (__test_and_set_bit(sinfo_has_ms_statement_type, &sinfo->aa_set))
521 goto repeated;
522 authenticode_check:
523 if (ctx->msg->data_type != OID_msIndirectData) {
524 pr_warn("Authenticode AuthAttrs only allowed with Authenticode\n");
525 return -EKEYREJECTED;
526 }
527 /* I'm not sure how to validate these */
322 return 0; 528 return 0;
323 default: 529 default:
324 return 0; 530 return 0;
325 } 531 }
532
533repeated:
534 /* We permit max one item per AuthenticatedAttribute and no repeats */
535 pr_warn("Repeated/multivalue AuthAttrs not permitted\n");
536 return -EKEYREJECTED;
326} 537}
327 538
328/* 539/*
329 * Note the set of auth attributes for digestion purposes [RFC2315 9.3] 540 * Note the set of auth attributes for digestion purposes [RFC2315 sec 9.3]
330 */ 541 */
331int pkcs7_sig_note_set_of_authattrs(void *context, size_t hdrlen, 542int pkcs7_sig_note_set_of_authattrs(void *context, size_t hdrlen,
332 unsigned char tag, 543 unsigned char tag,
333 const void *value, size_t vlen) 544 const void *value, size_t vlen)
334{ 545{
335 struct pkcs7_parse_context *ctx = context; 546 struct pkcs7_parse_context *ctx = context;
547 struct pkcs7_signed_info *sinfo = ctx->sinfo;
548
549 if (!test_bit(sinfo_has_content_type, &sinfo->aa_set) ||
550 !test_bit(sinfo_has_message_digest, &sinfo->aa_set) ||
551 (ctx->msg->data_type == OID_msIndirectData &&
552 !test_bit(sinfo_has_ms_opus_info, &sinfo->aa_set))) {
553 pr_warn("Missing required AuthAttr\n");
554 return -EBADMSG;
555 }
556
557 if (ctx->msg->data_type != OID_msIndirectData &&
558 test_bit(sinfo_has_ms_opus_info, &sinfo->aa_set)) {
559 pr_warn("Unexpected Authenticode AuthAttr\n");
560 return -EBADMSG;
561 }
336 562
337 /* We need to switch the 'CONT 0' to a 'SET OF' when we digest */ 563 /* We need to switch the 'CONT 0' to a 'SET OF' when we digest */
338 ctx->sinfo->authattrs = value - (hdrlen - 1); 564 sinfo->authattrs = value - (hdrlen - 1);
339 ctx->sinfo->authattrs_len = vlen + (hdrlen - 1); 565 sinfo->authattrs_len = vlen + (hdrlen - 1);
340 return 0; 566 return 0;
341} 567}
342 568
@@ -367,6 +593,22 @@ int pkcs7_sig_note_issuer(void *context, size_t hdrlen,
367} 593}
368 594
369/* 595/*
596 * Note the issuing cert's subjectKeyIdentifier
597 */
598int pkcs7_sig_note_skid(void *context, size_t hdrlen,
599 unsigned char tag,
600 const void *value, size_t vlen)
601{
602 struct pkcs7_parse_context *ctx = context;
603
604 pr_devel("SKID: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value);
605
606 ctx->raw_skid = value;
607 ctx->raw_skid_size = vlen;
608 return 0;
609}
610
611/*
370 * Note the signature data 612 * Note the signature data
371 */ 613 */
372int pkcs7_sig_note_signature(void *context, size_t hdrlen, 614int pkcs7_sig_note_signature(void *context, size_t hdrlen,
@@ -398,14 +640,27 @@ int pkcs7_note_signed_info(void *context, size_t hdrlen,
398 struct pkcs7_signed_info *sinfo = ctx->sinfo; 640 struct pkcs7_signed_info *sinfo = ctx->sinfo;
399 struct asymmetric_key_id *kid; 641 struct asymmetric_key_id *kid;
400 642
643 if (ctx->msg->data_type == OID_msIndirectData && !sinfo->authattrs) {
644 pr_warn("Authenticode requires AuthAttrs\n");
645 return -EBADMSG;
646 }
647
401 /* Generate cert issuer + serial number key ID */ 648 /* Generate cert issuer + serial number key ID */
402 kid = asymmetric_key_generate_id(ctx->raw_serial, 649 if (!ctx->expect_skid) {
403 ctx->raw_serial_size, 650 kid = asymmetric_key_generate_id(ctx->raw_serial,
404 ctx->raw_issuer, 651 ctx->raw_serial_size,
405 ctx->raw_issuer_size); 652 ctx->raw_issuer,
653 ctx->raw_issuer_size);
654 } else {
655 kid = asymmetric_key_generate_id(ctx->raw_skid,
656 ctx->raw_skid_size,
657 "", 0);
658 }
406 if (IS_ERR(kid)) 659 if (IS_ERR(kid))
407 return PTR_ERR(kid); 660 return PTR_ERR(kid);
408 661
662 pr_devel("SINFO KID: %u [%*phN]\n", kid->len, kid->len, kid->data);
663
409 sinfo->signing_cert_id = kid; 664 sinfo->signing_cert_id = kid;
410 sinfo->index = ++ctx->sinfo_index; 665 sinfo->index = ++ctx->sinfo_index;
411 *ctx->ppsinfo = sinfo; 666 *ctx->ppsinfo = sinfo;
diff --git a/crypto/asymmetric_keys/pkcs7_parser.h b/crypto/asymmetric_keys/pkcs7_parser.h
index efc7dc9b8f9c..a66b19ebcf47 100644
--- a/crypto/asymmetric_keys/pkcs7_parser.h
+++ b/crypto/asymmetric_keys/pkcs7_parser.h
@@ -21,9 +21,9 @@
21struct pkcs7_signed_info { 21struct pkcs7_signed_info {
22 struct pkcs7_signed_info *next; 22 struct pkcs7_signed_info *next;
23 struct x509_certificate *signer; /* Signing certificate (in msg->certs) */ 23 struct x509_certificate *signer; /* Signing certificate (in msg->certs) */
24 unsigned index; 24 unsigned index;
25 bool trusted; 25 bool trusted;
26 bool unsupported_crypto; /* T if not usable due to missing crypto */ 26 bool unsupported_crypto; /* T if not usable due to missing crypto */
27 27
28 /* Message digest - the digest of the Content Data (or NULL) */ 28 /* Message digest - the digest of the Content Data (or NULL) */
29 const void *msgdigest; 29 const void *msgdigest;
@@ -32,8 +32,18 @@ struct pkcs7_signed_info {
32 /* Authenticated Attribute data (or NULL) */ 32 /* Authenticated Attribute data (or NULL) */
33 unsigned authattrs_len; 33 unsigned authattrs_len;
34 const void *authattrs; 34 const void *authattrs;
35 unsigned long aa_set;
36#define sinfo_has_content_type 0
37#define sinfo_has_signing_time 1
38#define sinfo_has_message_digest 2
39#define sinfo_has_smime_caps 3
40#define sinfo_has_ms_opus_info 4
41#define sinfo_has_ms_statement_type 5
42 time64_t signing_time;
35 43
36 /* Issuing cert serial number and issuer's name */ 44 /* Issuing cert serial number and issuer's name [PKCS#7 or CMS ver 1]
45 * or issuing cert's SKID [CMS ver 3].
46 */
37 struct asymmetric_key_id *signing_cert_id; 47 struct asymmetric_key_id *signing_cert_id;
38 48
39 /* Message signature. 49 /* Message signature.
@@ -50,6 +60,8 @@ struct pkcs7_message {
50 struct x509_certificate *certs; /* Certificate list */ 60 struct x509_certificate *certs; /* Certificate list */
51 struct x509_certificate *crl; /* Revocation list */ 61 struct x509_certificate *crl; /* Revocation list */
52 struct pkcs7_signed_info *signed_infos; 62 struct pkcs7_signed_info *signed_infos;
63 u8 version; /* Version of cert (1 -> PKCS#7 or CMS; 3 -> CMS) */
64 bool have_authattrs; /* T if have authattrs */
53 65
54 /* Content Data (or NULL) */ 66 /* Content Data (or NULL) */
55 enum OID data_type; /* Type of Data */ 67 enum OID data_type; /* Type of Data */
diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c
index 1d29376072da..90d6d47965b0 100644
--- a/crypto/asymmetric_keys/pkcs7_trust.c
+++ b/crypto/asymmetric_keys/pkcs7_trust.c
@@ -54,7 +54,8 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
54 /* Look to see if this certificate is present in the trusted 54 /* Look to see if this certificate is present in the trusted
55 * keys. 55 * keys.
56 */ 56 */
57 key = x509_request_asymmetric_key(trust_keyring, x509->id, 57 key = x509_request_asymmetric_key(trust_keyring,
58 x509->id, x509->skid,
58 false); 59 false);
59 if (!IS_ERR(key)) { 60 if (!IS_ERR(key)) {
60 /* One of the X.509 certificates in the PKCS#7 message 61 /* One of the X.509 certificates in the PKCS#7 message
@@ -85,8 +86,10 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
85 /* No match - see if the root certificate has a signer amongst the 86 /* No match - see if the root certificate has a signer amongst the
86 * trusted keys. 87 * trusted keys.
87 */ 88 */
88 if (last && last->authority) { 89 if (last && (last->akid_id || last->akid_skid)) {
89 key = x509_request_asymmetric_key(trust_keyring, last->authority, 90 key = x509_request_asymmetric_key(trust_keyring,
91 last->akid_id,
92 last->akid_skid,
90 false); 93 false);
91 if (!IS_ERR(key)) { 94 if (!IS_ERR(key)) {
92 x509 = last; 95 x509 = last;
@@ -103,6 +106,7 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
103 */ 106 */
104 key = x509_request_asymmetric_key(trust_keyring, 107 key = x509_request_asymmetric_key(trust_keyring,
105 sinfo->signing_cert_id, 108 sinfo->signing_cert_id,
109 NULL,
106 false); 110 false);
107 if (!IS_ERR(key)) { 111 if (!IS_ERR(key)) {
108 pr_devel("sinfo %u: Direct signer is key %x\n", 112 pr_devel("sinfo %u: Direct signer is key %x\n",
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index cd455450b069..d20c0b4b880e 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -70,9 +70,15 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
70 * message digest attribute amongst them which corresponds to the 70 * message digest attribute amongst them which corresponds to the
71 * digest we just calculated. 71 * digest we just calculated.
72 */ 72 */
73 if (sinfo->msgdigest) { 73 if (sinfo->authattrs) {
74 u8 tag; 74 u8 tag;
75 75
76 if (!sinfo->msgdigest) {
77 pr_warn("Sig %u: No messageDigest\n", sinfo->index);
78 ret = -EKEYREJECTED;
79 goto error;
80 }
81
76 if (sinfo->msgdigest_len != sinfo->sig.digest_size) { 82 if (sinfo->msgdigest_len != sinfo->sig.digest_size) {
77 pr_debug("Sig %u: Invalid digest size (%u)\n", 83 pr_debug("Sig %u: Invalid digest size (%u)\n",
78 sinfo->index, sinfo->msgdigest_len); 84 sinfo->index, sinfo->msgdigest_len);
@@ -170,6 +176,7 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
170 struct pkcs7_signed_info *sinfo) 176 struct pkcs7_signed_info *sinfo)
171{ 177{
172 struct x509_certificate *x509 = sinfo->signer, *p; 178 struct x509_certificate *x509 = sinfo->signer, *p;
179 struct asymmetric_key_id *auth;
173 int ret; 180 int ret;
174 181
175 kenter(""); 182 kenter("");
@@ -187,11 +194,14 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
187 goto maybe_missing_crypto_in_x509; 194 goto maybe_missing_crypto_in_x509;
188 195
189 pr_debug("- issuer %s\n", x509->issuer); 196 pr_debug("- issuer %s\n", x509->issuer);
190 if (x509->authority) 197 if (x509->akid_id)
191 pr_debug("- authkeyid %*phN\n", 198 pr_debug("- authkeyid.id %*phN\n",
192 x509->authority->len, x509->authority->data); 199 x509->akid_id->len, x509->akid_id->data);
193 200 if (x509->akid_skid)
194 if (!x509->authority || 201 pr_debug("- authkeyid.skid %*phN\n",
202 x509->akid_skid->len, x509->akid_skid->data);
203
204 if ((!x509->akid_id && !x509->akid_skid) ||
195 strcmp(x509->subject, x509->issuer) == 0) { 205 strcmp(x509->subject, x509->issuer) == 0) {
196 /* If there's no authority certificate specified, then 206 /* If there's no authority certificate specified, then
197 * the certificate must be self-signed and is the root 207 * the certificate must be self-signed and is the root
@@ -215,21 +225,42 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
215 /* Look through the X.509 certificates in the PKCS#7 message's 225 /* Look through the X.509 certificates in the PKCS#7 message's
216 * list to see if the next one is there. 226 * list to see if the next one is there.
217 */ 227 */
218 pr_debug("- want %*phN\n", 228 auth = x509->akid_id;
219 x509->authority->len, x509->authority->data); 229 if (auth) {
220 for (p = pkcs7->certs; p; p = p->next) { 230 pr_debug("- want %*phN\n", auth->len, auth->data);
221 if (!p->skid) 231 for (p = pkcs7->certs; p; p = p->next) {
222 continue; 232 pr_debug("- cmp [%u] %*phN\n",
223 pr_debug("- cmp [%u] %*phN\n", 233 p->index, p->id->len, p->id->data);
224 p->index, p->skid->len, p->skid->data); 234 if (asymmetric_key_id_same(p->id, auth))
225 if (asymmetric_key_id_same(p->skid, x509->authority)) 235 goto found_issuer_check_skid;
226 goto found_issuer; 236 }
237 } else {
238 auth = x509->akid_skid;
239 pr_debug("- want %*phN\n", auth->len, auth->data);
240 for (p = pkcs7->certs; p; p = p->next) {
241 if (!p->skid)
242 continue;
243 pr_debug("- cmp [%u] %*phN\n",
244 p->index, p->skid->len, p->skid->data);
245 if (asymmetric_key_id_same(p->skid, auth))
246 goto found_issuer;
247 }
227 } 248 }
228 249
229 /* We didn't find the root of this chain */ 250 /* We didn't find the root of this chain */
230 pr_debug("- top\n"); 251 pr_debug("- top\n");
231 return 0; 252 return 0;
232 253
254 found_issuer_check_skid:
255 /* We matched issuer + serialNumber, but if there's an
256 * authKeyId.keyId, that must match the CA subjKeyId also.
257 */
258 if (x509->akid_skid &&
259 !asymmetric_key_id_same(p->skid, x509->akid_skid)) {
260 pr_warn("Sig %u: X.509 chain contains auth-skid nonmatch (%u->%u)\n",
261 sinfo->index, x509->index, p->index);
262 return -EKEYREJECTED;
263 }
233 found_issuer: 264 found_issuer:
234 pr_debug("- subject %s\n", p->subject); 265 pr_debug("- subject %s\n", p->subject);
235 if (p->seen) { 266 if (p->seen) {
@@ -289,6 +320,18 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
289 pr_devel("Using X.509[%u] for sig %u\n", 320 pr_devel("Using X.509[%u] for sig %u\n",
290 sinfo->signer->index, sinfo->index); 321 sinfo->signer->index, sinfo->index);
291 322
323 /* Check that the PKCS#7 signing time is valid according to the X.509
324 * certificate. We can't, however, check against the system clock
325 * since that may not have been set yet and may be wrong.
326 */
327 if (test_bit(sinfo_has_signing_time, &sinfo->aa_set)) {
328 if (sinfo->signing_time < sinfo->signer->valid_from ||
329 sinfo->signing_time > sinfo->signer->valid_to) {
330 pr_warn("Message signed outside of X.509 validity window\n");
331 return -EKEYREJECTED;
332 }
333 }
334
292 /* Verify the PKCS#7 binary against the key */ 335 /* Verify the PKCS#7 binary against the key */
293 ret = public_key_verify_signature(sinfo->signer->pub, &sinfo->sig); 336 ret = public_key_verify_signature(sinfo->signer->pub, &sinfo->sig);
294 if (ret < 0) 337 if (ret < 0)
@@ -303,6 +346,7 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
303/** 346/**
304 * pkcs7_verify - Verify a PKCS#7 message 347 * pkcs7_verify - Verify a PKCS#7 message
305 * @pkcs7: The PKCS#7 message to be verified 348 * @pkcs7: The PKCS#7 message to be verified
349 * @usage: The use to which the key is being put
306 * 350 *
307 * Verify a PKCS#7 message is internally consistent - that is, the data digest 351 * Verify a PKCS#7 message is internally consistent - that is, the data digest
308 * matches the digest in the AuthAttrs and any signature in the message or one 352 * matches the digest in the AuthAttrs and any signature in the message or one
@@ -314,6 +358,9 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
314 * 358 *
315 * Returns, in order of descending priority: 359 * Returns, in order of descending priority:
316 * 360 *
361 * (*) -EKEYREJECTED if a key was selected that had a usage restriction at
362 * odds with the specified usage, or:
363 *
317 * (*) -EKEYREJECTED if a signature failed to match for which we found an 364 * (*) -EKEYREJECTED if a signature failed to match for which we found an
318 * appropriate X.509 certificate, or: 365 * appropriate X.509 certificate, or:
319 * 366 *
@@ -325,7 +372,8 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
325 * (*) 0 if all the signature chains that don't incur -ENOPKG can be verified 372 * (*) 0 if all the signature chains that don't incur -ENOPKG can be verified
326 * (note that a signature chain may be of zero length), or: 373 * (note that a signature chain may be of zero length), or:
327 */ 374 */
328int pkcs7_verify(struct pkcs7_message *pkcs7) 375int pkcs7_verify(struct pkcs7_message *pkcs7,
376 enum key_being_used_for usage)
329{ 377{
330 struct pkcs7_signed_info *sinfo; 378 struct pkcs7_signed_info *sinfo;
331 struct x509_certificate *x509; 379 struct x509_certificate *x509;
@@ -334,12 +382,48 @@ int pkcs7_verify(struct pkcs7_message *pkcs7)
334 382
335 kenter(""); 383 kenter("");
336 384
385 switch (usage) {
386 case VERIFYING_MODULE_SIGNATURE:
387 if (pkcs7->data_type != OID_data) {
388 pr_warn("Invalid module sig (not pkcs7-data)\n");
389 return -EKEYREJECTED;
390 }
391 if (pkcs7->have_authattrs) {
392 pr_warn("Invalid module sig (has authattrs)\n");
393 return -EKEYREJECTED;
394 }
395 break;
396 case VERIFYING_FIRMWARE_SIGNATURE:
397 if (pkcs7->data_type != OID_data) {
398 pr_warn("Invalid firmware sig (not pkcs7-data)\n");
399 return -EKEYREJECTED;
400 }
401 if (!pkcs7->have_authattrs) {
402 pr_warn("Invalid firmware sig (missing authattrs)\n");
403 return -EKEYREJECTED;
404 }
405 break;
406 case VERIFYING_KEXEC_PE_SIGNATURE:
407 if (pkcs7->data_type != OID_msIndirectData) {
408 pr_warn("Invalid kexec sig (not Authenticode)\n");
409 return -EKEYREJECTED;
410 }
411 /* Authattr presence checked in parser */
412 break;
413 case VERIFYING_UNSPECIFIED_SIGNATURE:
414 if (pkcs7->data_type != OID_data) {
415 pr_warn("Invalid unspecified sig (not pkcs7-data)\n");
416 return -EKEYREJECTED;
417 }
418 break;
419 default:
420 return -EINVAL;
421 }
422
337 for (n = 0, x509 = pkcs7->certs; x509; x509 = x509->next, n++) { 423 for (n = 0, x509 = pkcs7->certs; x509; x509 = x509->next, n++) {
338 ret = x509_get_sig_params(x509); 424 ret = x509_get_sig_params(x509);
339 if (ret < 0) 425 if (ret < 0)
340 return ret; 426 return ret;
341 pr_debug("X.509[%u] %*phN\n",
342 n, x509->authority->len, x509->authority->data);
343 } 427 }
344 428
345 for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { 429 for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
@@ -359,3 +443,28 @@ int pkcs7_verify(struct pkcs7_message *pkcs7)
359 return enopkg; 443 return enopkg;
360} 444}
361EXPORT_SYMBOL_GPL(pkcs7_verify); 445EXPORT_SYMBOL_GPL(pkcs7_verify);
446
447/**
448 * pkcs7_supply_detached_data - Supply the data needed to verify a PKCS#7 message
449 * @pkcs7: The PKCS#7 message
450 * @data: The data to be verified
451 * @datalen: The amount of data
452 *
453 * Supply the detached data needed to verify a PKCS#7 message. Note that no
454 * attempt to retain/pin the data is made. That is left to the caller. The
455 * data will not be modified by pkcs7_verify() and will not be freed when the
456 * PKCS#7 message is freed.
457 *
458 * Returns -EINVAL if data is already supplied in the message, 0 otherwise.
459 */
460int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7,
461 const void *data, size_t datalen)
462{
463 if (pkcs7->data) {
464 pr_debug("Data already supplied\n");
465 return -EINVAL;
466 }
467 pkcs7->data = data;
468 pkcs7->data_len = datalen;
469 return 0;
470}
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index 2f6e4fb1a1ea..81efccbe22d5 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -39,6 +39,7 @@ EXPORT_SYMBOL_GPL(pkey_algo);
39const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = { 39const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = {
40 [PKEY_ID_PGP] = "PGP", 40 [PKEY_ID_PGP] = "PGP",
41 [PKEY_ID_X509] = "X509", 41 [PKEY_ID_X509] = "X509",
42 [PKEY_ID_PKCS7] = "PKCS#7",
42}; 43};
43EXPORT_SYMBOL_GPL(pkey_id_type_name); 44EXPORT_SYMBOL_GPL(pkey_id_type_name);
44 45
diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c
index 2421f46184ce..897b734dabf9 100644
--- a/crypto/asymmetric_keys/verify_pefile.c
+++ b/crypto/asymmetric_keys/verify_pefile.c
@@ -393,6 +393,7 @@ error_no_desc:
393 * @pebuf: Buffer containing the PE binary image 393 * @pebuf: Buffer containing the PE binary image
394 * @pelen: Length of the binary image 394 * @pelen: Length of the binary image
395 * @trust_keyring: Signing certificates to use as starting points 395 * @trust_keyring: Signing certificates to use as starting points
396 * @usage: The use to which the key is being put.
396 * @_trusted: Set to true if trustworth, false otherwise 397 * @_trusted: Set to true if trustworth, false otherwise
397 * 398 *
398 * Validate that the certificate chain inside the PKCS#7 message inside the PE 399 * Validate that the certificate chain inside the PKCS#7 message inside the PE
@@ -417,7 +418,9 @@ error_no_desc:
417 * May also return -ENOMEM. 418 * May also return -ENOMEM.
418 */ 419 */
419int verify_pefile_signature(const void *pebuf, unsigned pelen, 420int verify_pefile_signature(const void *pebuf, unsigned pelen,
420 struct key *trusted_keyring, bool *_trusted) 421 struct key *trusted_keyring,
422 enum key_being_used_for usage,
423 bool *_trusted)
421{ 424{
422 struct pkcs7_message *pkcs7; 425 struct pkcs7_message *pkcs7;
423 struct pefile_context ctx; 426 struct pefile_context ctx;
@@ -462,7 +465,7 @@ int verify_pefile_signature(const void *pebuf, unsigned pelen,
462 if (ret < 0) 465 if (ret < 0)
463 goto error; 466 goto error;
464 467
465 ret = pkcs7_verify(pkcs7); 468 ret = pkcs7_verify(pkcs7, usage);
466 if (ret < 0) 469 if (ret < 0)
467 goto error; 470 goto error;
468 471
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
4AuthorityKeyIdentifier ::= SEQUENCE {
5 keyIdentifier [0] IMPLICIT KeyIdentifier OPTIONAL,
6 authorityCertIssuer [1] IMPLICIT GeneralNames OPTIONAL,
7 authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL
8 }
9
10KeyIdentifier ::= OCTET STRING ({ x509_akid_note_kid })
11
12CertificateSerialNumber ::= INTEGER ({ x509_akid_note_serial })
13
14GeneralNames ::= SEQUENCE OF GeneralName
15
16GeneralName ::= 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
28Name ::= SEQUENCE OF RelativeDistinguishedName
29
30RelativeDistinguishedName ::= SET OF AttributeValueAssertion
31
32AttributeValueAssertion ::= 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..af71878dc15b 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
23struct x509_parse_context { 24struct 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
@@ -437,9 +454,7 @@ int x509_process_extension(void *context, size_t hdrlen,
437 454
438 ctx->cert->raw_skid_size = vlen; 455 ctx->cert->raw_skid_size = vlen;
439 ctx->cert->raw_skid = v; 456 ctx->cert->raw_skid = v;
440 kid = asymmetric_key_generate_id(ctx->cert->raw_subject, 457 kid = asymmetric_key_generate_id(v, vlen, "", 0);
441 ctx->cert->raw_subject_size,
442 v, vlen);
443 if (IS_ERR(kid)) 458 if (IS_ERR(kid))
444 return PTR_ERR(kid); 459 return PTR_ERR(kid);
445 ctx->cert->skid = kid; 460 ctx->cert->skid = kid;
@@ -449,117 +464,113 @@ int x509_process_extension(void *context, size_t hdrlen,
449 464
450 if (ctx->last_oid == OID_authorityKeyIdentifier) { 465 if (ctx->last_oid == OID_authorityKeyIdentifier) {
451 /* Get hold of the CA key fingerprint */ 466 /* Get hold of the CA key fingerprint */
452 if (ctx->cert->authority || vlen < 5) 467 ctx->raw_akid = v;
453 return -EBADMSG; 468 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; 469 return 0;
504 } 470 }
505 471
506 return 0; 472 return 0;
507} 473}
508 474
509/* 475/**
510 * Record a certificate time. 476 * x509_decode_time - Decode an X.509 time ASN.1 object
477 * @_t: The time to fill in
478 * @hdrlen: The length of the object header
479 * @tag: The object tag
480 * @value: The object value
481 * @vlen: The size of the object value
482 *
483 * Decode an ASN.1 universal time or generalised time field into a struct the
484 * kernel can handle and check it for validity. The time is decoded thus:
485 *
486 * [RFC5280 §4.1.2.5]
487 * CAs conforming to this profile MUST always encode certificate validity
488 * dates through the year 2049 as UTCTime; certificate validity dates in
489 * 2050 or later MUST be encoded as GeneralizedTime. Conforming
490 * applications MUST be able to process validity dates that are encoded in
491 * either UTCTime or GeneralizedTime.
511 */ 492 */
512static int x509_note_time(struct tm *tm, size_t hdrlen, 493int x509_decode_time(time64_t *_t, size_t hdrlen,
513 unsigned char tag, 494 unsigned char tag,
514 const unsigned char *value, size_t vlen) 495 const unsigned char *value, size_t vlen)
515{ 496{
497 static const unsigned char month_lengths[] = { 31, 29, 31, 30, 31, 30,
498 31, 31, 30, 31, 30, 31 };
516 const unsigned char *p = value; 499 const unsigned char *p = value;
500 unsigned year, mon, day, hour, min, sec, mon_len;
517 501
518#define dec2bin(X) ((X) - '0') 502#define dec2bin(X) ({ unsigned char x = (X) - '0'; if (x > 9) goto invalid_time; x; })
519#define DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2; x; }) 503#define DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2; x; })
520 504
521 if (tag == ASN1_UNITIM) { 505 if (tag == ASN1_UNITIM) {
522 /* UTCTime: YYMMDDHHMMSSZ */ 506 /* UTCTime: YYMMDDHHMMSSZ */
523 if (vlen != 13) 507 if (vlen != 13)
524 goto unsupported_time; 508 goto unsupported_time;
525 tm->tm_year = DD2bin(p); 509 year = DD2bin(p);
526 if (tm->tm_year >= 50) 510 if (year >= 50)
527 tm->tm_year += 1900; 511 year += 1900;
528 else 512 else
529 tm->tm_year += 2000; 513 year += 2000;
530 } else if (tag == ASN1_GENTIM) { 514 } else if (tag == ASN1_GENTIM) {
531 /* GenTime: YYYYMMDDHHMMSSZ */ 515 /* GenTime: YYYYMMDDHHMMSSZ */
532 if (vlen != 15) 516 if (vlen != 15)
533 goto unsupported_time; 517 goto unsupported_time;
534 tm->tm_year = DD2bin(p) * 100 + DD2bin(p); 518 year = DD2bin(p) * 100 + DD2bin(p);
519 if (year >= 1950 && year <= 2049)
520 goto invalid_time;
535 } else { 521 } else {
536 goto unsupported_time; 522 goto unsupported_time;
537 } 523 }
538 524
539 tm->tm_year -= 1900; 525 mon = DD2bin(p);
540 tm->tm_mon = DD2bin(p) - 1; 526 day = DD2bin(p);
541 tm->tm_mday = DD2bin(p); 527 hour = DD2bin(p);
542 tm->tm_hour = DD2bin(p); 528 min = DD2bin(p);
543 tm->tm_min = DD2bin(p); 529 sec = DD2bin(p);
544 tm->tm_sec = DD2bin(p);
545 530
546 if (*p != 'Z') 531 if (*p != 'Z')
547 goto unsupported_time; 532 goto unsupported_time;
548 533
534 mon_len = month_lengths[mon];
535 if (mon == 2) {
536 if (year % 4 == 0) {
537 mon_len = 29;
538 if (year % 100 == 0) {
539 year /= 100;
540 if (year % 4 != 0)
541 mon_len = 28;
542 }
543 }
544 }
545
546 if (year < 1970 ||
547 mon < 1 || mon > 12 ||
548 day < 1 || day > mon_len ||
549 hour < 0 || hour > 23 ||
550 min < 0 || min > 59 ||
551 sec < 0 || sec > 59)
552 goto invalid_time;
553
554 *_t = mktime64(year, mon, day, hour, min, sec);
549 return 0; 555 return 0;
550 556
551unsupported_time: 557unsupported_time:
552 pr_debug("Got unsupported time [tag %02x]: '%*.*s'\n", 558 pr_debug("Got unsupported time [tag %02x]: '%*phN'\n",
553 tag, (int)vlen, (int)vlen, value); 559 tag, (int)vlen, value);
560 return -EBADMSG;
561invalid_time:
562 pr_debug("Got invalid time [tag %02x]: '%*phN'\n",
563 tag, (int)vlen, value);
554 return -EBADMSG; 564 return -EBADMSG;
555} 565}
566EXPORT_SYMBOL_GPL(x509_decode_time);
556 567
557int x509_note_not_before(void *context, size_t hdrlen, 568int x509_note_not_before(void *context, size_t hdrlen,
558 unsigned char tag, 569 unsigned char tag,
559 const void *value, size_t vlen) 570 const void *value, size_t vlen)
560{ 571{
561 struct x509_parse_context *ctx = context; 572 struct x509_parse_context *ctx = context;
562 return x509_note_time(&ctx->cert->valid_from, hdrlen, tag, value, vlen); 573 return x509_decode_time(&ctx->cert->valid_from, hdrlen, tag, value, vlen);
563} 574}
564 575
565int x509_note_not_after(void *context, size_t hdrlen, 576int x509_note_not_after(void *context, size_t hdrlen,
@@ -567,5 +578,71 @@ int x509_note_not_after(void *context, size_t hdrlen,
567 const void *value, size_t vlen) 578 const void *value, size_t vlen)
568{ 579{
569 struct x509_parse_context *ctx = context; 580 struct x509_parse_context *ctx = context;
570 return x509_note_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen); 581 return x509_decode_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen);
582}
583
584/*
585 * Note a key identifier-based AuthorityKeyIdentifier
586 */
587int x509_akid_note_kid(void *context, size_t hdrlen,
588 unsigned char tag,
589 const void *value, size_t vlen)
590{
591 struct x509_parse_context *ctx = context;
592 struct asymmetric_key_id *kid;
593
594 pr_debug("AKID: keyid: %*phN\n", (int)vlen, value);
595
596 if (ctx->cert->akid_skid)
597 return 0;
598
599 kid = asymmetric_key_generate_id(value, vlen, "", 0);
600 if (IS_ERR(kid))
601 return PTR_ERR(kid);
602 pr_debug("authkeyid %*phN\n", kid->len, kid->data);
603 ctx->cert->akid_skid = kid;
604 return 0;
605}
606
607/*
608 * Note a directoryName in an AuthorityKeyIdentifier
609 */
610int x509_akid_note_name(void *context, size_t hdrlen,
611 unsigned char tag,
612 const void *value, size_t vlen)
613{
614 struct x509_parse_context *ctx = context;
615
616 pr_debug("AKID: name: %*phN\n", (int)vlen, value);
617
618 ctx->akid_raw_issuer = value;
619 ctx->akid_raw_issuer_size = vlen;
620 return 0;
621}
622
623/*
624 * Note a serial number in an AuthorityKeyIdentifier
625 */
626int x509_akid_note_serial(void *context, size_t hdrlen,
627 unsigned char tag,
628 const void *value, size_t vlen)
629{
630 struct x509_parse_context *ctx = context;
631 struct asymmetric_key_id *kid;
632
633 pr_debug("AKID: serial: %*phN\n", (int)vlen, value);
634
635 if (!ctx->akid_raw_issuer || ctx->cert->akid_id)
636 return 0;
637
638 kid = asymmetric_key_generate_id(value,
639 vlen,
640 ctx->akid_raw_issuer,
641 ctx->akid_raw_issuer_size);
642 if (IS_ERR(kid))
643 return PTR_ERR(kid);
644
645 pr_debug("authkeyid %*phN\n", kid->len, kid->data);
646 ctx->cert->akid_id = kid;
647 return 0;
571} 648}
diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h
index 3dfe6b5d6f0b..1de01eaec884 100644
--- a/crypto/asymmetric_keys/x509_parser.h
+++ b/crypto/asymmetric_keys/x509_parser.h
@@ -19,11 +19,12 @@ 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 tm valid_from; 25 struct asymmetric_key_id *akid_skid; /* CA AuthKeyId matching ->skid (optional) */
26 struct tm valid_to; 26 time64_t valid_from;
27 time64_t valid_to;
27 const void *tbs; /* Signed data */ 28 const void *tbs; /* Signed data */
28 unsigned tbs_size; /* Size of signed data */ 29 unsigned tbs_size; /* Size of signed data */
29 unsigned raw_sig_size; /* Size of sigature */ 30 unsigned raw_sig_size; /* Size of sigature */
@@ -48,6 +49,9 @@ struct x509_certificate {
48 */ 49 */
49extern void x509_free_certificate(struct x509_certificate *cert); 50extern void x509_free_certificate(struct x509_certificate *cert);
50extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); 51extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen);
52extern int x509_decode_time(time64_t *_t, size_t hdrlen,
53 unsigned char tag,
54 const unsigned char *value, size_t vlen);
51 55
52/* 56/*
53 * x509_public_key.c 57 * x509_public_key.c
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 24f17e6c5904..6d88dd15c98d 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -65,23 +65,37 @@ __setup("ca_keys=", ca_keys_setup);
65/** 65/**
66 * x509_request_asymmetric_key - Request a key by X.509 certificate params. 66 * x509_request_asymmetric_key - Request a key by X.509 certificate params.
67 * @keyring: The keys to search. 67 * @keyring: The keys to search.
68 * @kid: The key ID. 68 * @id: The issuer & serialNumber to look for or NULL.
69 * @skid: The subjectKeyIdentifier to look for or NULL.
69 * @partial: Use partial match if true, exact if false. 70 * @partial: Use partial match if true, exact if false.
70 * 71 *
71 * Find a key in the given keyring by subject name and key ID. These might, 72 * Find a key in the given keyring by identifier. The preferred identifier is
72 * for instance, be the issuer name and the authority key ID of an X.509 73 * the issuer + serialNumber and the fallback identifier is the
73 * certificate that needs to be verified. 74 * subjectKeyIdentifier. If both are given, the lookup is by the former, but
75 * the latter must also match.
74 */ 76 */
75struct key *x509_request_asymmetric_key(struct key *keyring, 77struct key *x509_request_asymmetric_key(struct key *keyring,
76 const struct asymmetric_key_id *kid, 78 const struct asymmetric_key_id *id,
79 const struct asymmetric_key_id *skid,
77 bool partial) 80 bool partial)
78{ 81{
79 key_ref_t key; 82 struct key *key;
80 char *id, *p; 83 key_ref_t ref;
81 84 const char *lookup;
85 char *req, *p;
86 int len;
87
88 if (id) {
89 lookup = id->data;
90 len = id->len;
91 } else {
92 lookup = skid->data;
93 len = skid->len;
94 }
95
82 /* Construct an identifier "id:<keyid>". */ 96 /* Construct an identifier "id:<keyid>". */
83 p = id = kmalloc(2 + 1 + kid->len * 2 + 1, GFP_KERNEL); 97 p = req = kmalloc(2 + 1 + len * 2 + 1, GFP_KERNEL);
84 if (!id) 98 if (!req)
85 return ERR_PTR(-ENOMEM); 99 return ERR_PTR(-ENOMEM);
86 100
87 if (partial) { 101 if (partial) {
@@ -92,32 +106,48 @@ struct key *x509_request_asymmetric_key(struct key *keyring,
92 *p++ = 'x'; 106 *p++ = 'x';
93 } 107 }
94 *p++ = ':'; 108 *p++ = ':';
95 p = bin2hex(p, kid->data, kid->len); 109 p = bin2hex(p, lookup, len);
96 *p = 0; 110 *p = 0;
97 111
98 pr_debug("Look up: \"%s\"\n", id); 112 pr_debug("Look up: \"%s\"\n", req);
99 113
100 key = keyring_search(make_key_ref(keyring, 1), 114 ref = keyring_search(make_key_ref(keyring, 1),
101 &key_type_asymmetric, id); 115 &key_type_asymmetric, req);
102 if (IS_ERR(key)) 116 if (IS_ERR(ref))
103 pr_debug("Request for key '%s' err %ld\n", id, PTR_ERR(key)); 117 pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref));
104 kfree(id); 118 kfree(req);
105 119
106 if (IS_ERR(key)) { 120 if (IS_ERR(ref)) {
107 switch (PTR_ERR(key)) { 121 switch (PTR_ERR(ref)) {
108 /* Hide some search errors */ 122 /* Hide some search errors */
109 case -EACCES: 123 case -EACCES:
110 case -ENOTDIR: 124 case -ENOTDIR:
111 case -EAGAIN: 125 case -EAGAIN:
112 return ERR_PTR(-ENOKEY); 126 return ERR_PTR(-ENOKEY);
113 default: 127 default:
114 return ERR_CAST(key); 128 return ERR_CAST(ref);
129 }
130 }
131
132 key = key_ref_to_ptr(ref);
133 if (id && skid) {
134 const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
135 if (!kids->id[1]) {
136 pr_debug("issuer+serial match, but expected SKID missing\n");
137 goto reject;
138 }
139 if (!asymmetric_key_id_same(skid, kids->id[1])) {
140 pr_debug("issuer+serial match, but SKID does not\n");
141 goto reject;
115 } 142 }
116 } 143 }
144
145 pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key));
146 return key;
117 147
118 pr_devel("<==%s() = 0 [%x]\n", __func__, 148reject:
119 key_serial(key_ref_to_ptr(key))); 149 key_put(key);
120 return key_ref_to_ptr(key); 150 return ERR_PTR(-EKEYREJECTED);
121} 151}
122EXPORT_SYMBOL_GPL(x509_request_asymmetric_key); 152EXPORT_SYMBOL_GPL(x509_request_asymmetric_key);
123 153
@@ -227,10 +257,11 @@ static int x509_validate_trust(struct x509_certificate *cert,
227 if (!trust_keyring) 257 if (!trust_keyring)
228 return -EOPNOTSUPP; 258 return -EOPNOTSUPP;
229 259
230 if (ca_keyid && !asymmetric_key_id_partial(cert->authority, ca_keyid)) 260 if (ca_keyid && !asymmetric_key_id_partial(cert->akid_skid, ca_keyid))
231 return -EPERM; 261 return -EPERM;
232 262
233 key = x509_request_asymmetric_key(trust_keyring, cert->authority, 263 key = x509_request_asymmetric_key(trust_keyring,
264 cert->akid_id, cert->akid_skid,
234 false); 265 false);
235 if (!IS_ERR(key)) { 266 if (!IS_ERR(key)) {
236 if (!use_builtin_keys 267 if (!use_builtin_keys
@@ -271,14 +302,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
271 } 302 }
272 303
273 pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]); 304 pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]);
274 pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", 305 pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to);
275 cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1,
276 cert->valid_from.tm_mday, cert->valid_from.tm_hour,
277 cert->valid_from.tm_min, cert->valid_from.tm_sec);
278 pr_devel("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n",
279 cert->valid_to.tm_year + 1900, cert->valid_to.tm_mon + 1,
280 cert->valid_to.tm_mday, cert->valid_to.tm_hour,
281 cert->valid_to.tm_min, cert->valid_to.tm_sec);
282 pr_devel("Cert Signature: %s + %s\n", 306 pr_devel("Cert Signature: %s + %s\n",
283 pkey_algo_name[cert->sig.pkey_algo], 307 pkey_algo_name[cert->sig.pkey_algo],
284 hash_algo_name[cert->sig.pkey_hash_algo]); 308 hash_algo_name[cert->sig.pkey_hash_algo]);
@@ -287,8 +311,9 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
287 cert->pub->id_type = PKEY_ID_X509; 311 cert->pub->id_type = PKEY_ID_X509;
288 312
289 /* Check the signature on the key if it appears to be self-signed */ 313 /* Check the signature on the key if it appears to be self-signed */
290 if (!cert->authority || 314 if ((!cert->akid_skid && !cert->akid_id) ||
291 asymmetric_key_id_same(cert->skid, cert->authority)) { 315 asymmetric_key_id_same(cert->skid, cert->akid_skid) ||
316 asymmetric_key_id_same(cert->id, cert->akid_id)) {
292 ret = x509_check_signature(cert->pub, cert); /* self-signed */ 317 ret = x509_check_signature(cert->pub, cert); /* self-signed */
293 if (ret < 0) 318 if (ret < 0)
294 goto error_free_cert; 319 goto error_free_cert;