aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Morris <james.l.morris@oracle.com>2015-08-13 22:08:39 -0400
committerJames Morris <james.l.morris@oracle.com>2015-08-13 22:08:39 -0400
commite4fc02f24c223ee8d668bf2d39bb8a2dbd61b40e (patch)
tree8ad26407ec8b8898f6ff5f396ff628919a56c624
parentaa62efff65ba572814511efa68cb158fe9e960c4 (diff)
parente9a5e8cc55286941503f36c5b7485a5aa923b3f1 (diff)
Merge tag 'modsign-pkcs7-20150812-3' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs into next
-rw-r--r--.gitignore1
-rw-r--r--Documentation/kbuild/kbuild.txt5
-rw-r--r--Documentation/module-signing.txt54
-rw-r--r--Makefile8
-rw-r--r--arch/x86/kernel/kexec-bzimage64.c4
-rw-r--r--crypto/asymmetric_keys/Makefile8
-rw-r--r--crypto/asymmetric_keys/asymmetric_type.c11
-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.c269
-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
-rw-r--r--include/crypto/pkcs7.h13
-rw-r--r--include/crypto/public_key.h18
-rw-r--r--include/keys/system_keyring.h7
-rw-r--r--include/linux/oid_registry.h4
-rw-r--r--include/linux/verify_pefile.h6
-rw-r--r--init/Kconfig59
-rw-r--r--kernel/Makefile112
-rw-r--r--kernel/module_signing.c213
-rw-r--r--kernel/system_certificates.S3
-rw-r--r--kernel/system_keyring.c53
-rw-r--r--scripts/Makefile4
-rw-r--r--scripts/Makefile.modinst2
-rw-r--r--scripts/asn1_compiler.c229
-rw-r--r--scripts/extract-cert.c166
-rwxr-xr-xscripts/sign-file421
-rwxr-xr-xscripts/sign-file.c260
35 files changed, 1597 insertions, 928 deletions
diff --git a/.gitignore b/.gitignore
index 4ad4a98b884b..17fa24dd7e46 100644
--- a/.gitignore
+++ b/.gitignore
@@ -97,6 +97,7 @@ GTAGS
97# Leavings from module signing 97# Leavings from module signing
98# 98#
99extra_certificates 99extra_certificates
100signing_key.pem
100signing_key.priv 101signing_key.priv
101signing_key.x509 102signing_key.x509
102x509.genkey 103x509.genkey
diff --git a/Documentation/kbuild/kbuild.txt b/Documentation/kbuild/kbuild.txt
index 6466704d47b5..0ff6a466a05b 100644
--- a/Documentation/kbuild/kbuild.txt
+++ b/Documentation/kbuild/kbuild.txt
@@ -174,6 +174,11 @@ The output directory is often set using "O=..." on the commandline.
174 174
175The value can be overridden in which case the default value is ignored. 175The value can be overridden in which case the default value is ignored.
176 176
177KBUILD_SIGN_PIN
178--------------------------------------------------
179This variable allows a passphrase or PIN to be passed to the sign-file
180utility when signing kernel modules, if the private key requires such.
181
177KBUILD_MODPOST_WARN 182KBUILD_MODPOST_WARN
178-------------------------------------------------- 183--------------------------------------------------
179KBUILD_MODPOST_WARN can be set to avoid errors in case of undefined 184KBUILD_MODPOST_WARN can be set to avoid errors in case of undefined
diff --git a/Documentation/module-signing.txt b/Documentation/module-signing.txt
index c72702ec1ded..02a9baf1c72f 100644
--- a/Documentation/module-signing.txt
+++ b/Documentation/module-signing.txt
@@ -89,6 +89,32 @@ This has a number of options available:
89 their signatures checked without causing a dependency loop. 89 their signatures checked without causing a dependency loop.
90 90
91 91
92 (4) "File name or PKCS#11 URI of module signing key" (CONFIG_MODULE_SIG_KEY)
93
94 Setting this option to something other than its default of
95 "signing_key.pem" will disable the autogeneration of signing keys and
96 allow the kernel modules to be signed with a key of your choosing.
97 The string provided should identify a file containing both a private
98 key and its corresponding X.509 certificate in PEM form, or — on
99 systems where the OpenSSL ENGINE_pkcs11 is functional — a PKCS#11 URI
100 as defined by RFC7512. In the latter case, the PKCS#11 URI should
101 reference both a certificate and a private key.
102
103 If the PEM file containing the private key is encrypted, or if the
104 PKCS#11 token requries a PIN, this can be provided at build time by
105 means of the KBUILD_SIGN_PIN variable.
106
107
108 (5) "Additional X.509 keys for default system keyring" (CONFIG_SYSTEM_TRUSTED_KEYS)
109
110 This option can be set to the filename of a PEM-encoded file containing
111 additional certificates which will be included in the system keyring by
112 default.
113
114Note that enabling module signing adds a dependency on the OpenSSL devel
115packages to the kernel build processes for the tool that does the signing.
116
117
92======================= 118=======================
93GENERATING SIGNING KEYS 119GENERATING SIGNING KEYS
94======================= 120=======================
@@ -100,11 +126,11 @@ it can be deleted or stored securely. The public key gets built into the
100kernel so that it can be used to check the signatures as the modules are 126kernel so that it can be used to check the signatures as the modules are
101loaded. 127loaded.
102 128
103Under normal conditions, the kernel build will automatically generate a new 129Under normal conditions, when CONFIG_MODULE_SIG_KEY is unchanged from its
104keypair using openssl if one does not exist in the files: 130default, the kernel build will automatically generate a new keypair using
131openssl if one does not exist in the file:
105 132
106 signing_key.priv 133 signing_key.pem
107 signing_key.x509
108 134
109during the building of vmlinux (the public part of the key needs to be built 135during the building of vmlinux (the public part of the key needs to be built
110into vmlinux) using parameters in the: 136into vmlinux) using parameters in the:
@@ -135,8 +161,12 @@ kernel sources tree and the openssl command. The following is an example to
135generate the public/private key files: 161generate the public/private key files:
136 162
137 openssl req -new -nodes -utf8 -sha256 -days 36500 -batch -x509 \ 163 openssl req -new -nodes -utf8 -sha256 -days 36500 -batch -x509 \
138 -config x509.genkey -outform DER -out signing_key.x509 \ 164 -config x509.genkey -outform PEM -out kernel_key.pem \
139 -keyout signing_key.priv 165 -keyout kernel_key.pem
166
167The full pathname for the resulting kernel_key.pem file can then be specified
168in the CONFIG_MODULE_SIG_KEY option, and the certificate and key therein will
169be used instead of an autogenerated keypair.
140 170
141 171
142========================= 172=========================
@@ -152,10 +182,9 @@ in a keyring called ".system_keyring" that can be seen by:
152 302d2d52 I------ 1 perm 1f010000 0 0 asymmetri Fedora kernel signing key: d69a84e6bce3d216b979e9505b3e3ef9a7118079: X509.RSA a7118079 [] 182 302d2d52 I------ 1 perm 1f010000 0 0 asymmetri Fedora kernel signing key: d69a84e6bce3d216b979e9505b3e3ef9a7118079: X509.RSA a7118079 []
153 ... 183 ...
154 184
155Beyond the public key generated specifically for module signing, any file 185Beyond the public key generated specifically for module signing, additional
156placed in the kernel source root directory or the kernel build root directory 186trusted certificates can be provided in a PEM-encoded file referenced by the
157whose name is suffixed with ".x509" will be assumed to be an X.509 public key 187CONFIG_SYSTEM_TRUSTED_KEYS configuration option.
158and will be added to the keyring.
159 188
160Further, the architecture code may take public keys from a hardware store and 189Further, the architecture code may take public keys from a hardware store and
161add those in also (e.g. from the UEFI key database). 190add those in also (e.g. from the UEFI key database).
@@ -181,7 +210,7 @@ To manually sign a module, use the scripts/sign-file tool available in
181the Linux kernel source tree. The script requires 4 arguments: 210the Linux kernel source tree. The script requires 4 arguments:
182 211
183 1. The hash algorithm (e.g., sha256) 212 1. The hash algorithm (e.g., sha256)
184 2. The private key filename 213 2. The private key filename or PKCS#11 URI
185 3. The public key filename 214 3. The public key filename
186 4. The kernel module to be signed 215 4. The kernel module to be signed
187 216
@@ -194,6 +223,9 @@ The hash algorithm used does not have to match the one configured, but if it
194doesn't, you should make sure that hash algorithm is either built into the 223doesn't, you should make sure that hash algorithm is either built into the
195kernel or can be loaded without requiring itself. 224kernel or can be loaded without requiring itself.
196 225
226If the private key requires a passphrase or PIN, it can be provided in the
227$KBUILD_SIGN_PIN environment variable.
228
197 229
198============================ 230============================
199SIGNED MODULES AND STRIPPING 231SIGNED MODULES AND STRIPPING
diff --git a/Makefile b/Makefile
index a9ad4908e870..6ab99d8cc23c 100644
--- a/Makefile
+++ b/Makefile
@@ -870,10 +870,10 @@ INITRD_COMPRESS-$(CONFIG_RD_LZ4) := lz4
870# export INITRD_COMPRESS := $(INITRD_COMPRESS-y) 870# export INITRD_COMPRESS := $(INITRD_COMPRESS-y)
871 871
872ifdef CONFIG_MODULE_SIG_ALL 872ifdef CONFIG_MODULE_SIG_ALL
873MODSECKEY = ./signing_key.priv 873MODSECKEY = $(CONFIG_MODULE_SIG_KEY)
874MODPUBKEY = ./signing_key.x509 874MODPUBKEY = ./signing_key.x509
875export MODPUBKEY 875export MODPUBKEY
876mod_sign_cmd = perl $(srctree)/scripts/sign-file $(CONFIG_MODULE_SIG_HASH) $(MODSECKEY) $(MODPUBKEY) 876mod_sign_cmd = scripts/sign-file $(CONFIG_MODULE_SIG_HASH) $(MODSECKEY) $(MODPUBKEY)
877else 877else
878mod_sign_cmd = true 878mod_sign_cmd = true
879endif 879endif
@@ -1173,8 +1173,8 @@ MRPROPER_DIRS += include/config usr/include include/generated \
1173 arch/*/include/generated .tmp_objdiff 1173 arch/*/include/generated .tmp_objdiff
1174MRPROPER_FILES += .config .config.old .version .old_version \ 1174MRPROPER_FILES += .config .config.old .version .old_version \
1175 Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS \ 1175 Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS \
1176 signing_key.priv signing_key.x509 x509.genkey \ 1176 signing_key.pem signing_key.priv signing_key.x509 \
1177 extra_certificates signing_key.x509.keyid \ 1177 x509.genkey extra_certificates signing_key.x509.keyid \
1178 signing_key.x509.signer vmlinux-gdb.py 1178 signing_key.x509.signer vmlinux-gdb.py
1179 1179
1180# clean - Delete most, but leave enough to build external modules 1180# clean - Delete most, but leave enough to build external modules
diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c
index ca83f7ac388b..fab22e72808c 100644
--- a/arch/x86/kernel/kexec-bzimage64.c
+++ b/arch/x86/kernel/kexec-bzimage64.c
@@ -536,7 +536,9 @@ static int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len)
536 int ret; 536 int ret;
537 537
538 ret = verify_pefile_signature(kernel, kernel_len, 538 ret = verify_pefile_signature(kernel, kernel_len,
539 system_trusted_keyring, &trusted); 539 system_trusted_keyring,
540 VERIFYING_KEXEC_PE_SIGNATURE,
541 &trusted);
540 if (ret < 0) 542 if (ret < 0)
541 return ret; 543 return ret;
542 if (!trusted) 544 if (!trusted)
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/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..e6298b7a945a 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
@@ -226,6 +257,100 @@ int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen,
226} 257}
227 258
228/* 259/*
260 * We only support signed data [RFC2315 sec 9].
261 */
262int pkcs7_check_content_type(void *context, size_t hdrlen,
263 unsigned char tag,
264 const void *value, size_t vlen)
265{
266 struct pkcs7_parse_context *ctx = context;
267
268 if (ctx->last_oid != OID_signed_data) {
269 pr_warn("Only support pkcs7_signedData type\n");
270 return -EINVAL;
271 }
272
273 return 0;
274}
275
276/*
277 * Note the SignedData version
278 */
279int pkcs7_note_signeddata_version(void *context, size_t hdrlen,
280 unsigned char tag,
281 const void *value, size_t vlen)
282{
283 struct pkcs7_parse_context *ctx = context;
284 unsigned version;
285
286 if (vlen != 1)
287 goto unsupported;
288
289 ctx->msg->version = version = *(const u8 *)value;
290 switch (version) {
291 case 1:
292 /* PKCS#7 SignedData [RFC2315 sec 9.1]
293 * CMS ver 1 SignedData [RFC5652 sec 5.1]
294 */
295 break;
296 case 3:
297 /* CMS ver 3 SignedData [RFC2315 sec 5.1] */
298 break;
299 default:
300 goto unsupported;
301 }
302
303 return 0;
304
305unsupported:
306 pr_warn("Unsupported SignedData version\n");
307 return -EINVAL;
308}
309
310/*
311 * Note the SignerInfo version
312 */
313int pkcs7_note_signerinfo_version(void *context, size_t hdrlen,
314 unsigned char tag,
315 const void *value, size_t vlen)
316{
317 struct pkcs7_parse_context *ctx = context;
318 unsigned version;
319
320 if (vlen != 1)
321 goto unsupported;
322
323 version = *(const u8 *)value;
324 switch (version) {
325 case 1:
326 /* PKCS#7 SignerInfo [RFC2315 sec 9.2]
327 * CMS ver 1 SignerInfo [RFC5652 sec 5.3]
328 */
329 if (ctx->msg->version != 1)
330 goto version_mismatch;
331 ctx->expect_skid = false;
332 break;
333 case 3:
334 /* CMS ver 3 SignerInfo [RFC2315 sec 5.3] */
335 if (ctx->msg->version == 1)
336 goto version_mismatch;
337 ctx->expect_skid = true;
338 break;
339 default:
340 goto unsupported;
341 }
342
343 return 0;
344
345unsupported:
346 pr_warn("Unsupported SignerInfo version\n");
347 return -EINVAL;
348version_mismatch:
349 pr_warn("SignedData-SignerInfo version mismatch\n");
350 return -EBADMSG;
351}
352
353/*
229 * Extract a certificate and store it in the context. 354 * Extract a certificate and store it in the context.
230 */ 355 */
231int pkcs7_extract_cert(void *context, size_t hdrlen, 356int pkcs7_extract_cert(void *context, size_t hdrlen,
@@ -284,6 +409,25 @@ int pkcs7_note_certificate_list(void *context, size_t hdrlen,
284} 409}
285 410
286/* 411/*
412 * Note the content type.
413 */
414int pkcs7_note_content(void *context, size_t hdrlen,
415 unsigned char tag,
416 const void *value, size_t vlen)
417{
418 struct pkcs7_parse_context *ctx = context;
419
420 if (ctx->last_oid != OID_data &&
421 ctx->last_oid != OID_msIndirectData) {
422 pr_warn("Unsupported data type %d\n", ctx->last_oid);
423 return -EINVAL;
424 }
425
426 ctx->msg->data_type = ctx->last_oid;
427 return 0;
428}
429
430/*
287 * Extract the data from the message and store that and its content type OID in 431 * Extract the data from the message and store that and its content type OID in
288 * the context. 432 * the context.
289 */ 433 */
@@ -298,45 +442,119 @@ int pkcs7_note_data(void *context, size_t hdrlen,
298 ctx->msg->data = value; 442 ctx->msg->data = value;
299 ctx->msg->data_len = vlen; 443 ctx->msg->data_len = vlen;
300 ctx->msg->data_hdrlen = hdrlen; 444 ctx->msg->data_hdrlen = hdrlen;
301 ctx->msg->data_type = ctx->last_oid;
302 return 0; 445 return 0;
303} 446}
304 447
305/* 448/*
306 * Parse authenticated attributes 449 * Parse authenticated attributes.
307 */ 450 */
308int pkcs7_sig_note_authenticated_attr(void *context, size_t hdrlen, 451int pkcs7_sig_note_authenticated_attr(void *context, size_t hdrlen,
309 unsigned char tag, 452 unsigned char tag,
310 const void *value, size_t vlen) 453 const void *value, size_t vlen)
311{ 454{
312 struct pkcs7_parse_context *ctx = context; 455 struct pkcs7_parse_context *ctx = context;
456 struct pkcs7_signed_info *sinfo = ctx->sinfo;
457 enum OID content_type;
313 458
314 pr_devel("AuthAttr: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value); 459 pr_devel("AuthAttr: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value);
315 460
316 switch (ctx->last_oid) { 461 switch (ctx->last_oid) {
462 case OID_contentType:
463 if (__test_and_set_bit(sinfo_has_content_type, &sinfo->aa_set))
464 goto repeated;
465 content_type = look_up_OID(value, vlen);
466 if (content_type != ctx->msg->data_type) {
467 pr_warn("Mismatch between global data type (%d) and sinfo %u (%d)\n",
468 ctx->msg->data_type, sinfo->index,
469 content_type);
470 return -EBADMSG;
471 }
472 return 0;
473
474 case OID_signingTime:
475 if (__test_and_set_bit(sinfo_has_signing_time, &sinfo->aa_set))
476 goto repeated;
477 /* Should we check that the signing time is consistent
478 * with the signer's X.509 cert?
479 */
480 return x509_decode_time(&sinfo->signing_time,
481 hdrlen, tag, value, vlen);
482
317 case OID_messageDigest: 483 case OID_messageDigest:
484 if (__test_and_set_bit(sinfo_has_message_digest, &sinfo->aa_set))
485 goto repeated;
318 if (tag != ASN1_OTS) 486 if (tag != ASN1_OTS)
319 return -EBADMSG; 487 return -EBADMSG;
320 ctx->sinfo->msgdigest = value; 488 sinfo->msgdigest = value;
321 ctx->sinfo->msgdigest_len = vlen; 489 sinfo->msgdigest_len = vlen;
490 return 0;
491
492 case OID_smimeCapabilites:
493 if (__test_and_set_bit(sinfo_has_smime_caps, &sinfo->aa_set))
494 goto repeated;
495 if (ctx->msg->data_type != OID_msIndirectData) {
496 pr_warn("S/MIME Caps only allowed with Authenticode\n");
497 return -EKEYREJECTED;
498 }
499 return 0;
500
501 /* Microsoft SpOpusInfo seems to be contain cont[0] 16-bit BE
502 * char URLs and cont[1] 8-bit char URLs.
503 *
504 * Microsoft StatementType seems to contain a list of OIDs that
505 * are also used as extendedKeyUsage types in X.509 certs.
506 */
507 case OID_msSpOpusInfo:
508 if (__test_and_set_bit(sinfo_has_ms_opus_info, &sinfo->aa_set))
509 goto repeated;
510 goto authenticode_check;
511 case OID_msStatementType:
512 if (__test_and_set_bit(sinfo_has_ms_statement_type, &sinfo->aa_set))
513 goto repeated;
514 authenticode_check:
515 if (ctx->msg->data_type != OID_msIndirectData) {
516 pr_warn("Authenticode AuthAttrs only allowed with Authenticode\n");
517 return -EKEYREJECTED;
518 }
519 /* I'm not sure how to validate these */
322 return 0; 520 return 0;
323 default: 521 default:
324 return 0; 522 return 0;
325 } 523 }
524
525repeated:
526 /* We permit max one item per AuthenticatedAttribute and no repeats */
527 pr_warn("Repeated/multivalue AuthAttrs not permitted\n");
528 return -EKEYREJECTED;
326} 529}
327 530
328/* 531/*
329 * Note the set of auth attributes for digestion purposes [RFC2315 9.3] 532 * Note the set of auth attributes for digestion purposes [RFC2315 sec 9.3]
330 */ 533 */
331int pkcs7_sig_note_set_of_authattrs(void *context, size_t hdrlen, 534int pkcs7_sig_note_set_of_authattrs(void *context, size_t hdrlen,
332 unsigned char tag, 535 unsigned char tag,
333 const void *value, size_t vlen) 536 const void *value, size_t vlen)
334{ 537{
335 struct pkcs7_parse_context *ctx = context; 538 struct pkcs7_parse_context *ctx = context;
539 struct pkcs7_signed_info *sinfo = ctx->sinfo;
540
541 if (!test_bit(sinfo_has_content_type, &sinfo->aa_set) ||
542 !test_bit(sinfo_has_message_digest, &sinfo->aa_set) ||
543 (ctx->msg->data_type == OID_msIndirectData &&
544 !test_bit(sinfo_has_ms_opus_info, &sinfo->aa_set))) {
545 pr_warn("Missing required AuthAttr\n");
546 return -EBADMSG;
547 }
548
549 if (ctx->msg->data_type != OID_msIndirectData &&
550 test_bit(sinfo_has_ms_opus_info, &sinfo->aa_set)) {
551 pr_warn("Unexpected Authenticode AuthAttr\n");
552 return -EBADMSG;
553 }
336 554
337 /* We need to switch the 'CONT 0' to a 'SET OF' when we digest */ 555 /* We need to switch the 'CONT 0' to a 'SET OF' when we digest */
338 ctx->sinfo->authattrs = value - (hdrlen - 1); 556 sinfo->authattrs = value - (hdrlen - 1);
339 ctx->sinfo->authattrs_len = vlen + (hdrlen - 1); 557 sinfo->authattrs_len = vlen + (hdrlen - 1);
340 return 0; 558 return 0;
341} 559}
342 560
@@ -367,6 +585,22 @@ int pkcs7_sig_note_issuer(void *context, size_t hdrlen,
367} 585}
368 586
369/* 587/*
588 * Note the issuing cert's subjectKeyIdentifier
589 */
590int pkcs7_sig_note_skid(void *context, size_t hdrlen,
591 unsigned char tag,
592 const void *value, size_t vlen)
593{
594 struct pkcs7_parse_context *ctx = context;
595
596 pr_devel("SKID: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value);
597
598 ctx->raw_skid = value;
599 ctx->raw_skid_size = vlen;
600 return 0;
601}
602
603/*
370 * Note the signature data 604 * Note the signature data
371 */ 605 */
372int pkcs7_sig_note_signature(void *context, size_t hdrlen, 606int pkcs7_sig_note_signature(void *context, size_t hdrlen,
@@ -398,14 +632,27 @@ int pkcs7_note_signed_info(void *context, size_t hdrlen,
398 struct pkcs7_signed_info *sinfo = ctx->sinfo; 632 struct pkcs7_signed_info *sinfo = ctx->sinfo;
399 struct asymmetric_key_id *kid; 633 struct asymmetric_key_id *kid;
400 634
635 if (ctx->msg->data_type == OID_msIndirectData && !sinfo->authattrs) {
636 pr_warn("Authenticode requires AuthAttrs\n");
637 return -EBADMSG;
638 }
639
401 /* Generate cert issuer + serial number key ID */ 640 /* Generate cert issuer + serial number key ID */
402 kid = asymmetric_key_generate_id(ctx->raw_serial, 641 if (!ctx->expect_skid) {
403 ctx->raw_serial_size, 642 kid = asymmetric_key_generate_id(ctx->raw_serial,
404 ctx->raw_issuer, 643 ctx->raw_serial_size,
405 ctx->raw_issuer_size); 644 ctx->raw_issuer,
645 ctx->raw_issuer_size);
646 } else {
647 kid = asymmetric_key_generate_id(ctx->raw_skid,
648 ctx->raw_skid_size,
649 "", 0);
650 }
406 if (IS_ERR(kid)) 651 if (IS_ERR(kid))
407 return PTR_ERR(kid); 652 return PTR_ERR(kid);
408 653
654 pr_devel("SINFO KID: %u [%*phN]\n", kid->len, kid->len, kid->data);
655
409 sinfo->signing_cert_id = kid; 656 sinfo->signing_cert_id = kid;
410 sinfo->index = ++ctx->sinfo_index; 657 sinfo->index = ++ctx->sinfo_index;
411 *ctx->ppsinfo = sinfo; 658 *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;
diff --git a/include/crypto/pkcs7.h b/include/crypto/pkcs7.h
index 691c79172a26..441aff9b5aa7 100644
--- a/include/crypto/pkcs7.h
+++ b/include/crypto/pkcs7.h
@@ -9,6 +9,11 @@
9 * 2 of the Licence, or (at your option) any later version. 9 * 2 of the Licence, or (at your option) any later version.
10 */ 10 */
11 11
12#ifndef _CRYPTO_PKCS7_H
13#define _CRYPTO_PKCS7_H
14
15#include <crypto/public_key.h>
16
12struct key; 17struct key;
13struct pkcs7_message; 18struct pkcs7_message;
14 19
@@ -33,4 +38,10 @@ extern int pkcs7_validate_trust(struct pkcs7_message *pkcs7,
33/* 38/*
34 * pkcs7_verify.c 39 * pkcs7_verify.c
35 */ 40 */
36extern int pkcs7_verify(struct pkcs7_message *pkcs7); 41extern int pkcs7_verify(struct pkcs7_message *pkcs7,
42 enum key_being_used_for usage);
43
44extern int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7,
45 const void *data, size_t datalen);
46
47#endif /* _CRYPTO_PKCS7_H */
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
index 54add2069901..067c242b1e15 100644
--- a/include/crypto/public_key.h
+++ b/include/crypto/public_key.h
@@ -33,12 +33,27 @@ extern const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST];
33enum pkey_id_type { 33enum pkey_id_type {
34 PKEY_ID_PGP, /* OpenPGP generated key ID */ 34 PKEY_ID_PGP, /* OpenPGP generated key ID */
35 PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */ 35 PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */
36 PKEY_ID_PKCS7, /* Signature in PKCS#7 message */
36 PKEY_ID_TYPE__LAST 37 PKEY_ID_TYPE__LAST
37}; 38};
38 39
39extern const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST]; 40extern const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST];
40 41
41/* 42/*
43 * The use to which an asymmetric key is being put.
44 */
45enum key_being_used_for {
46 VERIFYING_MODULE_SIGNATURE,
47 VERIFYING_FIRMWARE_SIGNATURE,
48 VERIFYING_KEXEC_PE_SIGNATURE,
49 VERIFYING_KEY_SIGNATURE,
50 VERIFYING_KEY_SELF_SIGNATURE,
51 VERIFYING_UNSPECIFIED_SIGNATURE,
52 NR__KEY_BEING_USED_FOR
53};
54extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR];
55
56/*
42 * Cryptographic data for the public-key subtype of the asymmetric key type. 57 * Cryptographic data for the public-key subtype of the asymmetric key type.
43 * 58 *
44 * Note that this may include private part of the key as well as the public 59 * Note that this may include private part of the key as well as the public
@@ -101,7 +116,8 @@ extern int verify_signature(const struct key *key,
101 116
102struct asymmetric_key_id; 117struct asymmetric_key_id;
103extern struct key *x509_request_asymmetric_key(struct key *keyring, 118extern struct key *x509_request_asymmetric_key(struct key *keyring,
104 const struct asymmetric_key_id *kid, 119 const struct asymmetric_key_id *id,
120 const struct asymmetric_key_id *skid,
105 bool partial); 121 bool partial);
106 122
107#endif /* _LINUX_PUBLIC_KEY_H */ 123#endif /* _LINUX_PUBLIC_KEY_H */
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
index 72665eb80692..b20cd885c1fd 100644
--- a/include/keys/system_keyring.h
+++ b/include/keys/system_keyring.h
@@ -15,6 +15,7 @@
15#ifdef CONFIG_SYSTEM_TRUSTED_KEYRING 15#ifdef CONFIG_SYSTEM_TRUSTED_KEYRING
16 16
17#include <linux/key.h> 17#include <linux/key.h>
18#include <crypto/public_key.h>
18 19
19extern struct key *system_trusted_keyring; 20extern struct key *system_trusted_keyring;
20static inline struct key *get_system_trusted_keyring(void) 21static inline struct key *get_system_trusted_keyring(void)
@@ -28,4 +29,10 @@ static inline struct key *get_system_trusted_keyring(void)
28} 29}
29#endif 30#endif
30 31
32#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
33extern int system_verify_data(const void *data, unsigned long len,
34 const void *raw_pkcs7, size_t pkcs7_len,
35 enum key_being_used_for usage);
36#endif
37
31#endif /* _KEYS_SYSTEM_KEYRING_H */ 38#endif /* _KEYS_SYSTEM_KEYRING_H */
diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h
index c2bbf672b84e..93e0ff92fb9b 100644
--- a/include/linux/oid_registry.h
+++ b/include/linux/oid_registry.h
@@ -41,7 +41,7 @@ enum OID {
41 OID_signed_data, /* 1.2.840.113549.1.7.2 */ 41 OID_signed_data, /* 1.2.840.113549.1.7.2 */
42 /* PKCS#9 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9)} */ 42 /* PKCS#9 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9)} */
43 OID_email_address, /* 1.2.840.113549.1.9.1 */ 43 OID_email_address, /* 1.2.840.113549.1.9.1 */
44 OID_content_type, /* 1.2.840.113549.1.9.3 */ 44 OID_contentType, /* 1.2.840.113549.1.9.3 */
45 OID_messageDigest, /* 1.2.840.113549.1.9.4 */ 45 OID_messageDigest, /* 1.2.840.113549.1.9.4 */
46 OID_signingTime, /* 1.2.840.113549.1.9.5 */ 46 OID_signingTime, /* 1.2.840.113549.1.9.5 */
47 OID_smimeCapabilites, /* 1.2.840.113549.1.9.15 */ 47 OID_smimeCapabilites, /* 1.2.840.113549.1.9.15 */
@@ -54,6 +54,8 @@ enum OID {
54 54
55 /* Microsoft Authenticode & Software Publishing */ 55 /* Microsoft Authenticode & Software Publishing */
56 OID_msIndirectData, /* 1.3.6.1.4.1.311.2.1.4 */ 56 OID_msIndirectData, /* 1.3.6.1.4.1.311.2.1.4 */
57 OID_msStatementType, /* 1.3.6.1.4.1.311.2.1.11 */
58 OID_msSpOpusInfo, /* 1.3.6.1.4.1.311.2.1.12 */
57 OID_msPeImageDataObjId, /* 1.3.6.1.4.1.311.2.1.15 */ 59 OID_msPeImageDataObjId, /* 1.3.6.1.4.1.311.2.1.15 */
58 OID_msIndividualSPKeyPurpose, /* 1.3.6.1.4.1.311.2.1.21 */ 60 OID_msIndividualSPKeyPurpose, /* 1.3.6.1.4.1.311.2.1.21 */
59 OID_msOutlookExpress, /* 1.3.6.1.4.1.311.16.4 */ 61 OID_msOutlookExpress, /* 1.3.6.1.4.1.311.16.4 */
diff --git a/include/linux/verify_pefile.h b/include/linux/verify_pefile.h
index ac34819214f9..da2049b5161c 100644
--- a/include/linux/verify_pefile.h
+++ b/include/linux/verify_pefile.h
@@ -12,7 +12,11 @@
12#ifndef _LINUX_VERIFY_PEFILE_H 12#ifndef _LINUX_VERIFY_PEFILE_H
13#define _LINUX_VERIFY_PEFILE_H 13#define _LINUX_VERIFY_PEFILE_H
14 14
15#include <crypto/public_key.h>
16
15extern int verify_pefile_signature(const void *pebuf, unsigned pelen, 17extern int verify_pefile_signature(const void *pebuf, unsigned pelen,
16 struct key *trusted_keyring, bool *_trusted); 18 struct key *trusted_keyring,
19 enum key_being_used_for usage,
20 bool *_trusted);
17 21
18#endif /* _LINUX_VERIFY_PEFILE_H */ 22#endif /* _LINUX_VERIFY_PEFILE_H */
diff --git a/init/Kconfig b/init/Kconfig
index af09b4fb43d2..5d1a703663ad 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1752,6 +1752,37 @@ config SYSTEM_TRUSTED_KEYRING
1752 1752
1753 Keys in this keyring are used by module signature checking. 1753 Keys in this keyring are used by module signature checking.
1754 1754
1755config SYSTEM_TRUSTED_KEYS
1756 string "Additional X.509 keys for default system keyring"
1757 depends on SYSTEM_TRUSTED_KEYRING
1758 help
1759 If set, this option should be the filename of a PEM-formatted file
1760 containing trusted X.509 certificates to be included in the default
1761 system keyring. Any certificate used for module signing is implicitly
1762 also trusted.
1763
1764 NOTE: If you previously provided keys for the system keyring in the
1765 form of DER-encoded *.x509 files in the top-level build directory,
1766 those are no longer used. You will need to set this option instead.
1767
1768config SYSTEM_DATA_VERIFICATION
1769 def_bool n
1770 select SYSTEM_TRUSTED_KEYRING
1771 select KEYS
1772 select CRYPTO
1773 select ASYMMETRIC_KEY_TYPE
1774 select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
1775 select PUBLIC_KEY_ALGO_RSA
1776 select ASN1
1777 select OID_REGISTRY
1778 select X509_CERTIFICATE_PARSER
1779 select PKCS7_MESSAGE_PARSER
1780 help
1781 Provide PKCS#7 message verification using the contents of the system
1782 trusted keyring to provide public keys. This then can be used for
1783 module verification, kexec image verification and firmware blob
1784 verification.
1785
1755config PROFILING 1786config PROFILING
1756 bool "Profiling support" 1787 bool "Profiling support"
1757 help 1788 help
@@ -1860,20 +1891,16 @@ config MODULE_SRCVERSION_ALL
1860config MODULE_SIG 1891config MODULE_SIG
1861 bool "Module signature verification" 1892 bool "Module signature verification"
1862 depends on MODULES 1893 depends on MODULES
1863 select SYSTEM_TRUSTED_KEYRING 1894 select SYSTEM_DATA_VERIFICATION
1864 select KEYS
1865 select CRYPTO
1866 select ASYMMETRIC_KEY_TYPE
1867 select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
1868 select PUBLIC_KEY_ALGO_RSA
1869 select ASN1
1870 select OID_REGISTRY
1871 select X509_CERTIFICATE_PARSER
1872 help 1895 help
1873 Check modules for valid signatures upon load: the signature 1896 Check modules for valid signatures upon load: the signature
1874 is simply appended to the module. For more information see 1897 is simply appended to the module. For more information see
1875 Documentation/module-signing.txt. 1898 Documentation/module-signing.txt.
1876 1899
1900 Note that this option adds the OpenSSL development packages as a
1901 kernel build dependency so that the signing tool can use its crypto
1902 library.
1903
1877 !!!WARNING!!! If you enable this option, you MUST make sure that the 1904 !!!WARNING!!! If you enable this option, you MUST make sure that the
1878 module DOES NOT get stripped after being signed. This includes the 1905 module DOES NOT get stripped after being signed. This includes the
1879 debuginfo strip done by some packagers (such as rpmbuild) and 1906 debuginfo strip done by some packagers (such as rpmbuild) and
@@ -1938,6 +1965,20 @@ config MODULE_SIG_HASH
1938 default "sha384" if MODULE_SIG_SHA384 1965 default "sha384" if MODULE_SIG_SHA384
1939 default "sha512" if MODULE_SIG_SHA512 1966 default "sha512" if MODULE_SIG_SHA512
1940 1967
1968config MODULE_SIG_KEY
1969 string "File name or PKCS#11 URI of module signing key"
1970 default "signing_key.pem"
1971 depends on MODULE_SIG
1972 help
1973 Provide the file name of a private key/certificate in PEM format,
1974 or a PKCS#11 URI according to RFC7512. The file should contain, or
1975 the URI should identify, both the certificate and its corresponding
1976 private key.
1977
1978 If this option is unchanged from its default "signing_key.pem",
1979 then the kernel will automatically generate the private key and
1980 certificate as described in Documentation/module-signing.txt
1981
1941config MODULE_COMPRESS 1982config MODULE_COMPRESS
1942 bool "Compress modules on installation" 1983 bool "Compress modules on installation"
1943 depends on MODULES 1984 depends on MODULES
diff --git a/kernel/Makefile b/kernel/Makefile
index 43c4c920f30a..65ef3846fbe8 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -114,46 +114,74 @@ $(obj)/config_data.h: $(obj)/config_data.gz FORCE
114 114
115############################################################################### 115###############################################################################
116# 116#
117# Roll all the X.509 certificates that we can find together and pull them into 117# When a Kconfig string contains a filename, it is suitable for
118# the kernel so that they get loaded into the system trusted keyring during 118# passing to shell commands. It is surrounded by double-quotes, and
119# boot. 119# any double-quotes or backslashes within it are escaped by
120# backslashes.
120# 121#
121# We look in the source root and the build root for all files whose name ends 122# This is no use for dependencies or $(wildcard). We need to strip the
122# in ".x509". Unfortunately, this will generate duplicate filenames, so we 123# surrounding quotes and the escaping from quotes and backslashes, and
123# have make canonicalise the pathnames and then sort them to discard the 124# we *do* need to escape any spaces in the string. So, for example:
124# duplicates. 125#
126# Usage: $(eval $(call config_filename,FOO))
127#
128# Defines FOO_FILENAME based on the contents of the CONFIG_FOO option,
129# transformed as described above to be suitable for use within the
130# makefile.
131#
132# Also, if the filename is a relative filename and exists in the source
133# tree but not the build tree, define FOO_SRCPREFIX as $(srctree)/ to
134# be prefixed to *both* command invocation and dependencies.
135#
136# Note: We also print the filenames in the quiet_cmd_foo text, and
137# perhaps ought to have a version specially escaped for that purpose.
138# But it's only cosmetic, and $(patsubst "%",%,$(CONFIG_FOO)) is good
139# enough. It'll strip the quotes in the common case where there's no
140# space and it's a simple filename, and it'll retain the quotes when
141# there's a space. There are some esoteric cases in which it'll print
142# the wrong thing, but we don't really care. The actual dependencies
143# and commands *do* get it right, with various combinations of single
144# and double quotes, backslashes and spaces in the filenames.
125# 145#
126############################################################################### 146###############################################################################
127ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y) 147#
128X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509) 148quote := $(firstword " ")
129X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += $(objtree)/signing_key.x509 149space :=
130X509_CERTIFICATES-raw := $(sort $(foreach CERT,$(X509_CERTIFICATES-y), \ 150space +=
131 $(or $(realpath $(CERT)),$(CERT)))) 151space_escape := %%%SPACE%%%
132X509_CERTIFICATES := $(subst $(realpath $(objtree))/,,$(X509_CERTIFICATES-raw)) 152#
133 153define config_filename
134ifeq ($(X509_CERTIFICATES),) 154ifneq ($$(CONFIG_$(1)),"")
135$(warning *** No X.509 certificates found ***) 155$(1)_FILENAME := $$(subst \\,\,$$(subst \$$(quote),$$(quote),$$(subst $$(space_escape),\$$(space),$$(patsubst "%",%,$$(subst $$(space),$$(space_escape),$$(CONFIG_$(1)))))))
156ifneq ($$(patsubst /%,%,$$(firstword $$($(1)_FILENAME))),$$(firstword $$($(1)_FILENAME)))
157else
158ifeq ($$(wildcard $$($(1)_FILENAME)),)
159ifneq ($$(wildcard $$(srctree)/$$($(1)_FILENAME)),)
160$(1)_SRCPREFIX := $(srctree)/
136endif 161endif
137
138ifneq ($(wildcard $(obj)/.x509.list),)
139ifneq ($(shell cat $(obj)/.x509.list),$(X509_CERTIFICATES))
140$(warning X.509 certificate list changed to "$(X509_CERTIFICATES)" from "$(shell cat $(obj)/.x509.list)")
141$(shell rm $(obj)/.x509.list)
142endif 162endif
143endif 163endif
164endif
165endef
166#
167###############################################################################
168
169ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y)
144 170
145kernel/system_certificates.o: $(obj)/x509_certificate_list 171$(eval $(call config_filename,SYSTEM_TRUSTED_KEYS))
146 172
147quiet_cmd_x509certs = CERTS $@ 173# GCC doesn't include .incbin files in -MD generated dependencies (PR#66871)
148 cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ $(foreach X509,$(X509_CERTIFICATES),; $(kecho) " - Including cert $(X509)") 174$(obj)/system_certificates.o: $(obj)/x509_certificate_list
149 175
150targets += $(obj)/x509_certificate_list 176# Cope with signing_key.x509 existing in $(srctree) not $(objtree)
151$(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list 177AFLAGS_system_certificates.o := -I$(srctree)
152 $(call if_changed,x509certs)
153 178
154targets += $(obj)/.x509.list 179quiet_cmd_extract_certs = EXTRACT_CERTS $(patsubst "%",%,$(2))
155$(obj)/.x509.list: 180 cmd_extract_certs = scripts/extract-cert $(2) $@ || ( rm $@; exit 1)
156 @echo $(X509_CERTIFICATES) >$@ 181
182targets += x509_certificate_list
183$(obj)/x509_certificate_list: scripts/extract-cert $(SYSTEM_TRUSTED_KEYS_SRCPREFIX)$(SYSTEM_TRUSTED_KEYS_FILENAME) FORCE
184 $(call if_changed,extract_certs,$(SYSTEM_TRUSTED_KEYS_SRCPREFIX)$(CONFIG_SYSTEM_TRUSTED_KEYS))
157endif 185endif
158 186
159clean-files := x509_certificate_list .x509.list 187clean-files := x509_certificate_list .x509.list
@@ -170,7 +198,11 @@ ifndef CONFIG_MODULE_SIG_HASH
170$(error Could not determine digest type to use from kernel config) 198$(error Could not determine digest type to use from kernel config)
171endif 199endif
172 200
173signing_key.priv signing_key.x509: x509.genkey 201# We do it this way rather than having a boolean option for enabling an
202# external private key, because 'make randconfig' might enable such a
203# boolean option and we unfortunately can't make it depend on !RANDCONFIG.
204ifeq ($(CONFIG_MODULE_SIG_KEY),"signing_key.pem")
205signing_key.pem: x509.genkey
174 @echo "###" 206 @echo "###"
175 @echo "### Now generating an X.509 key pair to be used for signing modules." 207 @echo "### Now generating an X.509 key pair to be used for signing modules."
176 @echo "###" 208 @echo "###"
@@ -181,8 +213,8 @@ signing_key.priv signing_key.x509: x509.genkey
181 @echo "###" 213 @echo "###"
182 openssl req -new -nodes -utf8 -$(CONFIG_MODULE_SIG_HASH) -days 36500 \ 214 openssl req -new -nodes -utf8 -$(CONFIG_MODULE_SIG_HASH) -days 36500 \
183 -batch -x509 -config x509.genkey \ 215 -batch -x509 -config x509.genkey \
184 -outform DER -out signing_key.x509 \ 216 -outform PEM -out signing_key.pem \
185 -keyout signing_key.priv 2>&1 217 -keyout signing_key.pem 2>&1
186 @echo "###" 218 @echo "###"
187 @echo "### Key pair generated." 219 @echo "### Key pair generated."
188 @echo "###" 220 @echo "###"
@@ -207,3 +239,17 @@ x509.genkey:
207 @echo >>x509.genkey "subjectKeyIdentifier=hash" 239 @echo >>x509.genkey "subjectKeyIdentifier=hash"
208 @echo >>x509.genkey "authorityKeyIdentifier=keyid" 240 @echo >>x509.genkey "authorityKeyIdentifier=keyid"
209endif 241endif
242
243$(eval $(call config_filename,MODULE_SIG_KEY))
244
245# If CONFIG_MODULE_SIG_KEY isn't a PKCS#11 URI, depend on it
246ifeq ($(patsubst pkcs11:%,%,$(firstword $(MODULE_SIG_KEY_FILENAME))),$(firstword $(MODULE_SIG_KEY_FILENAME)))
247X509_DEP := $(MODULE_SIG_KEY_SRCPREFIX)$(MODULE_SIG_KEY_FILENAME)
248endif
249
250# GCC PR#66871 again.
251$(obj)/system_certificates.o: signing_key.x509
252
253signing_key.x509: scripts/extract-cert include/config/module/sig/key.h $(X509_DEP)
254 $(call cmd,extract_certs,$(MODULE_SIG_KEY_SRCPREFIX)$(CONFIG_MODULE_SIG_KEY))
255endif
diff --git a/kernel/module_signing.c b/kernel/module_signing.c
index be5b8fac4bd0..bd62f5cda746 100644
--- a/kernel/module_signing.c
+++ b/kernel/module_signing.c
@@ -10,11 +10,8 @@
10 */ 10 */
11 11
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/err.h>
14#include <crypto/public_key.h>
15#include <crypto/hash.h>
16#include <keys/asymmetric-type.h>
17#include <keys/system_keyring.h> 13#include <keys/system_keyring.h>
14#include <crypto/public_key.h>
18#include "module-internal.h" 15#include "module-internal.h"
19 16
20/* 17/*
@@ -28,170 +25,22 @@
28 * - Information block 25 * - Information block
29 */ 26 */
30struct module_signature { 27struct module_signature {
31 u8 algo; /* Public-key crypto algorithm [enum pkey_algo] */ 28 u8 algo; /* Public-key crypto algorithm [0] */
32 u8 hash; /* Digest algorithm [enum hash_algo] */ 29 u8 hash; /* Digest algorithm [0] */
33 u8 id_type; /* Key identifier type [enum pkey_id_type] */ 30 u8 id_type; /* Key identifier type [PKEY_ID_PKCS7] */
34 u8 signer_len; /* Length of signer's name */ 31 u8 signer_len; /* Length of signer's name [0] */
35 u8 key_id_len; /* Length of key identifier */ 32 u8 key_id_len; /* Length of key identifier [0] */
36 u8 __pad[3]; 33 u8 __pad[3];
37 __be32 sig_len; /* Length of signature data */ 34 __be32 sig_len; /* Length of signature data */
38}; 35};
39 36
40/* 37/*
41 * Digest the module contents.
42 */
43static struct public_key_signature *mod_make_digest(enum hash_algo hash,
44 const void *mod,
45 unsigned long modlen)
46{
47 struct public_key_signature *pks;
48 struct crypto_shash *tfm;
49 struct shash_desc *desc;
50 size_t digest_size, desc_size;
51 int ret;
52
53 pr_devel("==>%s()\n", __func__);
54
55 /* Allocate the hashing algorithm we're going to need and find out how
56 * big the hash operational data will be.
57 */
58 tfm = crypto_alloc_shash(hash_algo_name[hash], 0, 0);
59 if (IS_ERR(tfm))
60 return (PTR_ERR(tfm) == -ENOENT) ? ERR_PTR(-ENOPKG) : ERR_CAST(tfm);
61
62 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
63 digest_size = crypto_shash_digestsize(tfm);
64
65 /* We allocate the hash operational data storage on the end of our
66 * context data and the digest output buffer on the end of that.
67 */
68 ret = -ENOMEM;
69 pks = kzalloc(digest_size + sizeof(*pks) + desc_size, GFP_KERNEL);
70 if (!pks)
71 goto error_no_pks;
72
73 pks->pkey_hash_algo = hash;
74 pks->digest = (u8 *)pks + sizeof(*pks) + desc_size;
75 pks->digest_size = digest_size;
76
77 desc = (void *)pks + sizeof(*pks);
78 desc->tfm = tfm;
79 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
80
81 ret = crypto_shash_init(desc);
82 if (ret < 0)
83 goto error;
84
85 ret = crypto_shash_finup(desc, mod, modlen, pks->digest);
86 if (ret < 0)
87 goto error;
88
89 crypto_free_shash(tfm);
90 pr_devel("<==%s() = ok\n", __func__);
91 return pks;
92
93error:
94 kfree(pks);
95error_no_pks:
96 crypto_free_shash(tfm);
97 pr_devel("<==%s() = %d\n", __func__, ret);
98 return ERR_PTR(ret);
99}
100
101/*
102 * Extract an MPI array from the signature data. This represents the actual
103 * signature. Each raw MPI is prefaced by a BE 2-byte value indicating the
104 * size of the MPI in bytes.
105 *
106 * RSA signatures only have one MPI, so currently we only read one.
107 */
108static int mod_extract_mpi_array(struct public_key_signature *pks,
109 const void *data, size_t len)
110{
111 size_t nbytes;
112 MPI mpi;
113
114 if (len < 3)
115 return -EBADMSG;
116 nbytes = ((const u8 *)data)[0] << 8 | ((const u8 *)data)[1];
117 data += 2;
118 len -= 2;
119 if (len != nbytes)
120 return -EBADMSG;
121
122 mpi = mpi_read_raw_data(data, nbytes);
123 if (!mpi)
124 return -ENOMEM;
125 pks->mpi[0] = mpi;
126 pks->nr_mpi = 1;
127 return 0;
128}
129
130/*
131 * Request an asymmetric key.
132 */
133static struct key *request_asymmetric_key(const char *signer, size_t signer_len,
134 const u8 *key_id, size_t key_id_len)
135{
136 key_ref_t key;
137 size_t i;
138 char *id, *q;
139
140 pr_devel("==>%s(,%zu,,%zu)\n", __func__, signer_len, key_id_len);
141
142 /* Construct an identifier. */
143 id = kmalloc(signer_len + 2 + key_id_len * 2 + 1, GFP_KERNEL);
144 if (!id)
145 return ERR_PTR(-ENOKEY);
146
147 memcpy(id, signer, signer_len);
148
149 q = id + signer_len;
150 *q++ = ':';
151 *q++ = ' ';
152 for (i = 0; i < key_id_len; i++) {
153 *q++ = hex_asc[*key_id >> 4];
154 *q++ = hex_asc[*key_id++ & 0x0f];
155 }
156
157 *q = 0;
158
159 pr_debug("Look up: \"%s\"\n", id);
160
161 key = keyring_search(make_key_ref(system_trusted_keyring, 1),
162 &key_type_asymmetric, id);
163 if (IS_ERR(key))
164 pr_warn("Request for unknown module key '%s' err %ld\n",
165 id, PTR_ERR(key));
166 kfree(id);
167
168 if (IS_ERR(key)) {
169 switch (PTR_ERR(key)) {
170 /* Hide some search errors */
171 case -EACCES:
172 case -ENOTDIR:
173 case -EAGAIN:
174 return ERR_PTR(-ENOKEY);
175 default:
176 return ERR_CAST(key);
177 }
178 }
179
180 pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key)));
181 return key_ref_to_ptr(key);
182}
183
184/*
185 * Verify the signature on a module. 38 * Verify the signature on a module.
186 */ 39 */
187int mod_verify_sig(const void *mod, unsigned long *_modlen) 40int mod_verify_sig(const void *mod, unsigned long *_modlen)
188{ 41{
189 struct public_key_signature *pks;
190 struct module_signature ms; 42 struct module_signature ms;
191 struct key *key;
192 const void *sig;
193 size_t modlen = *_modlen, sig_len; 43 size_t modlen = *_modlen, sig_len;
194 int ret;
195 44
196 pr_devel("==>%s(,%zu)\n", __func__, modlen); 45 pr_devel("==>%s(,%zu)\n", __func__, modlen);
197 46
@@ -205,46 +54,24 @@ int mod_verify_sig(const void *mod, unsigned long *_modlen)
205 if (sig_len >= modlen) 54 if (sig_len >= modlen)
206 return -EBADMSG; 55 return -EBADMSG;
207 modlen -= sig_len; 56 modlen -= sig_len;
208 if ((size_t)ms.signer_len + ms.key_id_len >= modlen)
209 return -EBADMSG;
210 modlen -= (size_t)ms.signer_len + ms.key_id_len;
211
212 *_modlen = modlen; 57 *_modlen = modlen;
213 sig = mod + modlen;
214
215 /* For the moment, only support RSA and X.509 identifiers */
216 if (ms.algo != PKEY_ALGO_RSA ||
217 ms.id_type != PKEY_ID_X509)
218 return -ENOPKG;
219 58
220 if (ms.hash >= PKEY_HASH__LAST || 59 if (ms.id_type != PKEY_ID_PKCS7) {
221 !hash_algo_name[ms.hash]) 60 pr_err("Module is not signed with expected PKCS#7 message\n");
222 return -ENOPKG; 61 return -ENOPKG;
223
224 key = request_asymmetric_key(sig, ms.signer_len,
225 sig + ms.signer_len, ms.key_id_len);
226 if (IS_ERR(key))
227 return PTR_ERR(key);
228
229 pks = mod_make_digest(ms.hash, mod, modlen);
230 if (IS_ERR(pks)) {
231 ret = PTR_ERR(pks);
232 goto error_put_key;
233 } 62 }
234 63
235 ret = mod_extract_mpi_array(pks, sig + ms.signer_len + ms.key_id_len, 64 if (ms.algo != 0 ||
236 sig_len); 65 ms.hash != 0 ||
237 if (ret < 0) 66 ms.signer_len != 0 ||
238 goto error_free_pks; 67 ms.key_id_len != 0 ||
239 68 ms.__pad[0] != 0 ||
240 ret = verify_signature(key, pks); 69 ms.__pad[1] != 0 ||
241 pr_devel("verify_signature() = %d\n", ret); 70 ms.__pad[2] != 0) {
71 pr_err("PKCS#7 signature info has unexpected non-zero params\n");
72 return -EBADMSG;
73 }
242 74
243error_free_pks: 75 return system_verify_data(mod, modlen, mod + modlen, sig_len,
244 mpi_free(pks->rsa.s); 76 VERIFYING_MODULE_SIGNATURE);
245 kfree(pks);
246error_put_key:
247 key_put(key);
248 pr_devel("<==%s() = %d\n", __func__, ret);
249 return ret;
250} 77}
diff --git a/kernel/system_certificates.S b/kernel/system_certificates.S
index 3e9868d47535..6ba2f75e7ba5 100644
--- a/kernel/system_certificates.S
+++ b/kernel/system_certificates.S
@@ -7,6 +7,9 @@
7 .globl VMLINUX_SYMBOL(system_certificate_list) 7 .globl VMLINUX_SYMBOL(system_certificate_list)
8VMLINUX_SYMBOL(system_certificate_list): 8VMLINUX_SYMBOL(system_certificate_list):
9__cert_list_start: 9__cert_list_start:
10#ifdef CONFIG_MODULE_SIG
11 .incbin "signing_key.x509"
12#endif
10 .incbin "kernel/x509_certificate_list" 13 .incbin "kernel/x509_certificate_list"
11__cert_list_end: 14__cert_list_end:
12 15
diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c
index 875f64e8935b..2570598b784d 100644
--- a/kernel/system_keyring.c
+++ b/kernel/system_keyring.c
@@ -16,7 +16,7 @@
16#include <linux/err.h> 16#include <linux/err.h>
17#include <keys/asymmetric-type.h> 17#include <keys/asymmetric-type.h>
18#include <keys/system_keyring.h> 18#include <keys/system_keyring.h>
19#include "module-internal.h" 19#include <crypto/pkcs7.h>
20 20
21struct key *system_trusted_keyring; 21struct key *system_trusted_keyring;
22EXPORT_SYMBOL_GPL(system_trusted_keyring); 22EXPORT_SYMBOL_GPL(system_trusted_keyring);
@@ -104,3 +104,54 @@ dodgy_cert:
104 return 0; 104 return 0;
105} 105}
106late_initcall(load_system_certificate_list); 106late_initcall(load_system_certificate_list);
107
108#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
109
110/**
111 * Verify a PKCS#7-based signature on system data.
112 * @data: The data to be verified.
113 * @len: Size of @data.
114 * @raw_pkcs7: The PKCS#7 message that is the signature.
115 * @pkcs7_len: The size of @raw_pkcs7.
116 * @usage: The use to which the key is being put.
117 */
118int system_verify_data(const void *data, unsigned long len,
119 const void *raw_pkcs7, size_t pkcs7_len,
120 enum key_being_used_for usage)
121{
122 struct pkcs7_message *pkcs7;
123 bool trusted;
124 int ret;
125
126 pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len);
127 if (IS_ERR(pkcs7))
128 return PTR_ERR(pkcs7);
129
130 /* The data should be detached - so we need to supply it. */
131 if (pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
132 pr_err("PKCS#7 signature with non-detached data\n");
133 ret = -EBADMSG;
134 goto error;
135 }
136
137 ret = pkcs7_verify(pkcs7, usage);
138 if (ret < 0)
139 goto error;
140
141 ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted);
142 if (ret < 0)
143 goto error;
144
145 if (!trusted) {
146 pr_err("PKCS#7 signature not signed with a trusted key\n");
147 ret = -ENOKEY;
148 }
149
150error:
151 pkcs7_free_message(pkcs7);
152 pr_devel("<==%s() = %d\n", __func__, ret);
153 return ret;
154}
155EXPORT_SYMBOL_GPL(system_verify_data);
156
157#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
diff --git a/scripts/Makefile b/scripts/Makefile
index 2016a64497ab..1b2661712d44 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -16,9 +16,13 @@ hostprogs-$(CONFIG_VT) += conmakehash
16hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount 16hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
17hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable 17hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable
18hostprogs-$(CONFIG_ASN1) += asn1_compiler 18hostprogs-$(CONFIG_ASN1) += asn1_compiler
19hostprogs-$(CONFIG_MODULE_SIG) += sign-file
20hostprogs-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert
19 21
20HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include 22HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include
21HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include 23HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
24HOSTLOADLIBES_sign-file = -lcrypto
25HOSTLOADLIBES_extract-cert = -lcrypto
22 26
23always := $(hostprogs-y) $(hostprogs-m) 27always := $(hostprogs-y) $(hostprogs-m)
24 28
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
index e48a4e9d8868..07650eeaaf06 100644
--- a/scripts/Makefile.modinst
+++ b/scripts/Makefile.modinst
@@ -22,7 +22,7 @@ quiet_cmd_modules_install = INSTALL $@
22 mkdir -p $(2) ; \ 22 mkdir -p $(2) ; \
23 cp $@ $(2) ; \ 23 cp $@ $(2) ; \
24 $(mod_strip_cmd) $(2)/$(notdir $@) ; \ 24 $(mod_strip_cmd) $(2)/$(notdir $@) ; \
25 $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD)) ; \ 25 $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD)) && \
26 $(mod_compress_cmd) $(2)/$(notdir $@) 26 $(mod_compress_cmd) $(2)/$(notdir $@)
27 27
28# Modules built outside the kernel source tree go into extra by default 28# Modules built outside the kernel source tree go into extra by default
diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c
index 1c75e22b6385..e000f44e37b8 100644
--- a/scripts/asn1_compiler.c
+++ b/scripts/asn1_compiler.c
@@ -13,6 +13,7 @@
13#include <stdio.h> 13#include <stdio.h>
14#include <stdlib.h> 14#include <stdlib.h>
15#include <stdint.h> 15#include <stdint.h>
16#include <stdbool.h>
16#include <string.h> 17#include <string.h>
17#include <ctype.h> 18#include <ctype.h>
18#include <unistd.h> 19#include <unistd.h>
@@ -293,8 +294,8 @@ static const char *const directives[NR__DIRECTIVES] = {
293 294
294struct action { 295struct action {
295 struct action *next; 296 struct action *next;
297 char *name;
296 unsigned char index; 298 unsigned char index;
297 char name[];
298}; 299};
299 300
300static struct action *action_list; 301static struct action *action_list;
@@ -305,15 +306,17 @@ struct token {
305 enum token_type token_type : 8; 306 enum token_type token_type : 8;
306 unsigned char size; 307 unsigned char size;
307 struct action *action; 308 struct action *action;
308 const char *value; 309 char *content;
309 struct type *type; 310 struct type *type;
310}; 311};
311 312
312static struct token *token_list; 313static struct token *token_list;
313static unsigned nr_tokens; 314static unsigned nr_tokens;
314static _Bool verbose; 315static bool verbose_opt;
316static bool debug_opt;
315 317
316#define debug(fmt, ...) do { if (verbose) printf(fmt, ## __VA_ARGS__); } while (0) 318#define verbose(fmt, ...) do { if (verbose_opt) printf(fmt, ## __VA_ARGS__); } while (0)
319#define debug(fmt, ...) do { if (debug_opt) printf(fmt, ## __VA_ARGS__); } while (0)
317 320
318static int directive_compare(const void *_key, const void *_pdir) 321static int directive_compare(const void *_key, const void *_pdir)
319{ 322{
@@ -325,11 +328,9 @@ static int directive_compare(const void *_key, const void *_pdir)
325 dlen = strlen(dir); 328 dlen = strlen(dir);
326 clen = (dlen < token->size) ? dlen : token->size; 329 clen = (dlen < token->size) ? dlen : token->size;
327 330
328 //debug("cmp(%*.*s,%s) = ", 331 //debug("cmp(%s,%s) = ", token->content, dir);
329 // (int)token->size, (int)token->size, token->value,
330 // dir);
331 332
332 val = memcmp(token->value, dir, clen); 333 val = memcmp(token->content, dir, clen);
333 if (val != 0) { 334 if (val != 0) {
334 //debug("%d [cmp]\n", val); 335 //debug("%d [cmp]\n", val);
335 return val; 336 return val;
@@ -349,7 +350,7 @@ static int directive_compare(const void *_key, const void *_pdir)
349static void tokenise(char *buffer, char *end) 350static void tokenise(char *buffer, char *end)
350{ 351{
351 struct token *tokens; 352 struct token *tokens;
352 char *line, *nl, *p, *q; 353 char *line, *nl, *start, *p, *q;
353 unsigned tix, lineno; 354 unsigned tix, lineno;
354 355
355 /* Assume we're going to have half as many tokens as we have 356 /* Assume we're going to have half as many tokens as we have
@@ -408,11 +409,11 @@ static void tokenise(char *buffer, char *end)
408 break; 409 break;
409 410
410 tokens[tix].line = lineno; 411 tokens[tix].line = lineno;
411 tokens[tix].value = p; 412 start = p;
412 413
413 /* Handle string tokens */ 414 /* Handle string tokens */
414 if (isalpha(*p)) { 415 if (isalpha(*p)) {
415 const char **dir; 416 const char **dir, *start = p;
416 417
417 /* Can be a directive, type name or element 418 /* Can be a directive, type name or element
418 * name. Find the end of the name. 419 * name. Find the end of the name.
@@ -423,10 +424,18 @@ static void tokenise(char *buffer, char *end)
423 tokens[tix].size = q - p; 424 tokens[tix].size = q - p;
424 p = q; 425 p = q;
425 426
427 tokens[tix].content = malloc(tokens[tix].size + 1);
428 if (!tokens[tix].content) {
429 perror(NULL);
430 exit(1);
431 }
432 memcpy(tokens[tix].content, start, tokens[tix].size);
433 tokens[tix].content[tokens[tix].size] = 0;
434
426 /* If it begins with a lowercase letter then 435 /* If it begins with a lowercase letter then
427 * it's an element name 436 * it's an element name
428 */ 437 */
429 if (islower(tokens[tix].value[0])) { 438 if (islower(tokens[tix].content[0])) {
430 tokens[tix++].token_type = TOKEN_ELEMENT_NAME; 439 tokens[tix++].token_type = TOKEN_ELEMENT_NAME;
431 continue; 440 continue;
432 } 441 }
@@ -455,6 +464,13 @@ static void tokenise(char *buffer, char *end)
455 q++; 464 q++;
456 tokens[tix].size = q - p; 465 tokens[tix].size = q - p;
457 p = q; 466 p = q;
467 tokens[tix].content = malloc(tokens[tix].size + 1);
468 if (!tokens[tix].content) {
469 perror(NULL);
470 exit(1);
471 }
472 memcpy(tokens[tix].content, start, tokens[tix].size);
473 tokens[tix].content[tokens[tix].size] = 0;
458 tokens[tix++].token_type = TOKEN_NUMBER; 474 tokens[tix++].token_type = TOKEN_NUMBER;
459 continue; 475 continue;
460 } 476 }
@@ -463,6 +479,7 @@ static void tokenise(char *buffer, char *end)
463 if (memcmp(p, "::=", 3) == 0) { 479 if (memcmp(p, "::=", 3) == 0) {
464 p += 3; 480 p += 3;
465 tokens[tix].size = 3; 481 tokens[tix].size = 3;
482 tokens[tix].content = "::=";
466 tokens[tix++].token_type = TOKEN_ASSIGNMENT; 483 tokens[tix++].token_type = TOKEN_ASSIGNMENT;
467 continue; 484 continue;
468 } 485 }
@@ -472,12 +489,14 @@ static void tokenise(char *buffer, char *end)
472 if (memcmp(p, "({", 2) == 0) { 489 if (memcmp(p, "({", 2) == 0) {
473 p += 2; 490 p += 2;
474 tokens[tix].size = 2; 491 tokens[tix].size = 2;
492 tokens[tix].content = "({";
475 tokens[tix++].token_type = TOKEN_OPEN_ACTION; 493 tokens[tix++].token_type = TOKEN_OPEN_ACTION;
476 continue; 494 continue;
477 } 495 }
478 if (memcmp(p, "})", 2) == 0) { 496 if (memcmp(p, "})", 2) == 0) {
479 p += 2; 497 p += 2;
480 tokens[tix].size = 2; 498 tokens[tix].size = 2;
499 tokens[tix].content = "})";
481 tokens[tix++].token_type = TOKEN_CLOSE_ACTION; 500 tokens[tix++].token_type = TOKEN_CLOSE_ACTION;
482 continue; 501 continue;
483 } 502 }
@@ -488,22 +507,27 @@ static void tokenise(char *buffer, char *end)
488 switch (*p) { 507 switch (*p) {
489 case '{': 508 case '{':
490 p += 1; 509 p += 1;
510 tokens[tix].content = "{";
491 tokens[tix++].token_type = TOKEN_OPEN_CURLY; 511 tokens[tix++].token_type = TOKEN_OPEN_CURLY;
492 continue; 512 continue;
493 case '}': 513 case '}':
494 p += 1; 514 p += 1;
515 tokens[tix].content = "}";
495 tokens[tix++].token_type = TOKEN_CLOSE_CURLY; 516 tokens[tix++].token_type = TOKEN_CLOSE_CURLY;
496 continue; 517 continue;
497 case '[': 518 case '[':
498 p += 1; 519 p += 1;
520 tokens[tix].content = "[";
499 tokens[tix++].token_type = TOKEN_OPEN_SQUARE; 521 tokens[tix++].token_type = TOKEN_OPEN_SQUARE;
500 continue; 522 continue;
501 case ']': 523 case ']':
502 p += 1; 524 p += 1;
525 tokens[tix].content = "]";
503 tokens[tix++].token_type = TOKEN_CLOSE_SQUARE; 526 tokens[tix++].token_type = TOKEN_CLOSE_SQUARE;
504 continue; 527 continue;
505 case ',': 528 case ',':
506 p += 1; 529 p += 1;
530 tokens[tix].content = ",";
507 tokens[tix++].token_type = TOKEN_COMMA; 531 tokens[tix++].token_type = TOKEN_COMMA;
508 continue; 532 continue;
509 default: 533 default:
@@ -518,22 +542,20 @@ static void tokenise(char *buffer, char *end)
518 } 542 }
519 543
520 nr_tokens = tix; 544 nr_tokens = tix;
521 debug("Extracted %u tokens\n", nr_tokens); 545 verbose("Extracted %u tokens\n", nr_tokens);
522 546
523#if 0 547#if 0
524 { 548 {
525 int n; 549 int n;
526 for (n = 0; n < nr_tokens; n++) 550 for (n = 0; n < nr_tokens; n++)
527 debug("Token %3u: '%*.*s'\n", 551 debug("Token %3u: '%s'\n", n, token_list[n].content);
528 n,
529 (int)token_list[n].size, (int)token_list[n].size,
530 token_list[n].value);
531 } 552 }
532#endif 553#endif
533} 554}
534 555
535static void build_type_list(void); 556static void build_type_list(void);
536static void parse(void); 557static void parse(void);
558static void dump_elements(void);
537static void render(FILE *out, FILE *hdr); 559static void render(FILE *out, FILE *hdr);
538 560
539/* 561/*
@@ -548,16 +570,27 @@ int main(int argc, char **argv)
548 char *kbuild_verbose; 570 char *kbuild_verbose;
549 int fd; 571 int fd;
550 572
573 kbuild_verbose = getenv("KBUILD_VERBOSE");
574 if (kbuild_verbose)
575 verbose_opt = atoi(kbuild_verbose);
576
577 while (argc > 4) {
578 if (strcmp(argv[1], "-v") == 0)
579 verbose_opt = true;
580 else if (strcmp(argv[1], "-d") == 0)
581 debug_opt = true;
582 else
583 break;
584 memmove(&argv[1], &argv[2], (argc - 2) * sizeof(char *));
585 argc--;
586 }
587
551 if (argc != 4) { 588 if (argc != 4) {
552 fprintf(stderr, "Format: %s <grammar-file> <c-file> <hdr-file>\n", 589 fprintf(stderr, "Format: %s [-v] [-d] <grammar-file> <c-file> <hdr-file>\n",
553 argv[0]); 590 argv[0]);
554 exit(2); 591 exit(2);
555 } 592 }
556 593
557 kbuild_verbose = getenv("KBUILD_VERBOSE");
558 if (kbuild_verbose)
559 verbose = atoi(kbuild_verbose);
560
561 filename = argv[1]; 594 filename = argv[1];
562 outputname = argv[2]; 595 outputname = argv[2];
563 headername = argv[3]; 596 headername = argv[3];
@@ -608,6 +641,7 @@ int main(int argc, char **argv)
608 tokenise(buffer, buffer + readlen); 641 tokenise(buffer, buffer + readlen);
609 build_type_list(); 642 build_type_list();
610 parse(); 643 parse();
644 dump_elements();
611 645
612 out = fopen(outputname, "w"); 646 out = fopen(outputname, "w");
613 if (!out) { 647 if (!out) {
@@ -693,7 +727,7 @@ static int type_index_compare(const void *_a, const void *_b)
693 if ((*a)->name->size != (*b)->name->size) 727 if ((*a)->name->size != (*b)->name->size)
694 return (*a)->name->size - (*b)->name->size; 728 return (*a)->name->size - (*b)->name->size;
695 else 729 else
696 return memcmp((*a)->name->value, (*b)->name->value, 730 return memcmp((*a)->name->content, (*b)->name->content,
697 (*a)->name->size); 731 (*a)->name->size);
698} 732}
699 733
@@ -706,7 +740,7 @@ static int type_finder(const void *_key, const void *_ti)
706 if (token->size != type->name->size) 740 if (token->size != type->name->size)
707 return token->size - type->name->size; 741 return token->size - type->name->size;
708 else 742 else
709 return memcmp(token->value, type->name->value, 743 return memcmp(token->content, type->name->content,
710 token->size); 744 token->size);
711} 745}
712 746
@@ -756,14 +790,11 @@ static void build_type_list(void)
756 790
757 qsort(type_index, nr, sizeof(type_index[0]), type_index_compare); 791 qsort(type_index, nr, sizeof(type_index[0]), type_index_compare);
758 792
759 debug("Extracted %u types\n", nr_types); 793 verbose("Extracted %u types\n", nr_types);
760#if 0 794#if 0
761 for (n = 0; n < nr_types; n++) { 795 for (n = 0; n < nr_types; n++) {
762 struct type *type = type_index[n]; 796 struct type *type = type_index[n];
763 debug("- %*.*s\n", 797 debug("- %*.*s\n", type->name->content);
764 (int)type->name->size,
765 (int)type->name->size,
766 type->name->value);
767 } 798 }
768#endif 799#endif
769} 800}
@@ -793,15 +824,14 @@ static void parse(void)
793 type->element->type_def = type; 824 type->element->type_def = type;
794 825
795 if (cursor != type[1].name) { 826 if (cursor != type[1].name) {
796 fprintf(stderr, "%s:%d: Parse error at token '%*.*s'\n", 827 fprintf(stderr, "%s:%d: Parse error at token '%s'\n",
797 filename, cursor->line, 828 filename, cursor->line, cursor->content);
798 (int)cursor->size, (int)cursor->size, cursor->value);
799 exit(1); 829 exit(1);
800 } 830 }
801 831
802 } while (type++, !(type->flags & TYPE_STOP_MARKER)); 832 } while (type++, !(type->flags & TYPE_STOP_MARKER));
803 833
804 debug("Extracted %u actions\n", nr_actions); 834 verbose("Extracted %u actions\n", nr_actions);
805} 835}
806 836
807static struct element *element_list; 837static struct element *element_list;
@@ -862,34 +892,31 @@ static struct element *parse_type(struct token **_cursor, struct token *end,
862 cursor++; 892 cursor++;
863 break; 893 break;
864 default: 894 default:
865 fprintf(stderr, "%s:%d: Unrecognised tag class token '%*.*s'\n", 895 fprintf(stderr, "%s:%d: Unrecognised tag class token '%s'\n",
866 filename, cursor->line, 896 filename, cursor->line, cursor->content);
867 (int)cursor->size, (int)cursor->size, cursor->value);
868 exit(1); 897 exit(1);
869 } 898 }
870 899
871 if (cursor >= end) 900 if (cursor >= end)
872 goto overrun_error; 901 goto overrun_error;
873 if (cursor->token_type != TOKEN_NUMBER) { 902 if (cursor->token_type != TOKEN_NUMBER) {
874 fprintf(stderr, "%s:%d: Missing tag number '%*.*s'\n", 903 fprintf(stderr, "%s:%d: Missing tag number '%s'\n",
875 filename, cursor->line, 904 filename, cursor->line, cursor->content);
876 (int)cursor->size, (int)cursor->size, cursor->value);
877 exit(1); 905 exit(1);
878 } 906 }
879 907
880 element->tag &= ~0x1f; 908 element->tag &= ~0x1f;
881 element->tag |= strtoul(cursor->value, &p, 10); 909 element->tag |= strtoul(cursor->content, &p, 10);
882 element->flags |= ELEMENT_TAG_SPECIFIED; 910 element->flags |= ELEMENT_TAG_SPECIFIED;
883 if (p - cursor->value != cursor->size) 911 if (p - cursor->content != cursor->size)
884 abort(); 912 abort();
885 cursor++; 913 cursor++;
886 914
887 if (cursor >= end) 915 if (cursor >= end)
888 goto overrun_error; 916 goto overrun_error;
889 if (cursor->token_type != TOKEN_CLOSE_SQUARE) { 917 if (cursor->token_type != TOKEN_CLOSE_SQUARE) {
890 fprintf(stderr, "%s:%d: Missing closing square bracket '%*.*s'\n", 918 fprintf(stderr, "%s:%d: Missing closing square bracket '%s'\n",
891 filename, cursor->line, 919 filename, cursor->line, cursor->content);
892 (int)cursor->size, (int)cursor->size, cursor->value);
893 exit(1); 920 exit(1);
894 } 921 }
895 cursor++; 922 cursor++;
@@ -989,9 +1016,8 @@ static struct element *parse_type(struct token **_cursor, struct token *end,
989 ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]), 1016 ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]),
990 type_finder); 1017 type_finder);
991 if (!ref) { 1018 if (!ref) {
992 fprintf(stderr, "%s:%d: Type '%*.*s' undefined\n", 1019 fprintf(stderr, "%s:%d: Type '%s' undefined\n",
993 filename, cursor->line, 1020 filename, cursor->line, cursor->content);
994 (int)cursor->size, (int)cursor->size, cursor->value);
995 exit(1); 1021 exit(1);
996 } 1022 }
997 cursor->type = *ref; 1023 cursor->type = *ref;
@@ -1040,9 +1066,8 @@ static struct element *parse_type(struct token **_cursor, struct token *end,
1040 break; 1066 break;
1041 1067
1042 default: 1068 default:
1043 fprintf(stderr, "%s:%d: Token '%*.*s' does not introduce a type\n", 1069 fprintf(stderr, "%s:%d: Token '%s' does not introduce a type\n",
1044 filename, cursor->line, 1070 filename, cursor->line, cursor->content);
1045 (int)cursor->size, (int)cursor->size, cursor->value);
1046 exit(1); 1071 exit(1);
1047 } 1072 }
1048 1073
@@ -1059,20 +1084,18 @@ static struct element *parse_type(struct token **_cursor, struct token *end,
1059 if (cursor >= end) 1084 if (cursor >= end)
1060 goto overrun_error; 1085 goto overrun_error;
1061 if (cursor->token_type != TOKEN_ELEMENT_NAME) { 1086 if (cursor->token_type != TOKEN_ELEMENT_NAME) {
1062 fprintf(stderr, "%s:%d: Token '%*.*s' is not an action function name\n", 1087 fprintf(stderr, "%s:%d: Token '%s' is not an action function name\n",
1063 filename, cursor->line, 1088 filename, cursor->line, cursor->content);
1064 (int)cursor->size, (int)cursor->size, cursor->value);
1065 exit(1); 1089 exit(1);
1066 } 1090 }
1067 1091
1068 action = malloc(sizeof(struct action) + cursor->size + 1); 1092 action = malloc(sizeof(struct action));
1069 if (!action) { 1093 if (!action) {
1070 perror(NULL); 1094 perror(NULL);
1071 exit(1); 1095 exit(1);
1072 } 1096 }
1073 action->index = 0; 1097 action->index = 0;
1074 memcpy(action->name, cursor->value, cursor->size); 1098 action->name = cursor->content;
1075 action->name[cursor->size] = 0;
1076 1099
1077 for (ppaction = &action_list; 1100 for (ppaction = &action_list;
1078 *ppaction; 1101 *ppaction;
@@ -1102,9 +1125,8 @@ static struct element *parse_type(struct token **_cursor, struct token *end,
1102 if (cursor >= end) 1125 if (cursor >= end)
1103 goto overrun_error; 1126 goto overrun_error;
1104 if (cursor->token_type != TOKEN_CLOSE_ACTION) { 1127 if (cursor->token_type != TOKEN_CLOSE_ACTION) {
1105 fprintf(stderr, "%s:%d: Missing close action, got '%*.*s'\n", 1128 fprintf(stderr, "%s:%d: Missing close action, got '%s'\n",
1106 filename, cursor->line, 1129 filename, cursor->line, cursor->content);
1107 (int)cursor->size, (int)cursor->size, cursor->value);
1108 exit(1); 1130 exit(1);
1109 } 1131 }
1110 cursor++; 1132 cursor++;
@@ -1114,9 +1136,8 @@ static struct element *parse_type(struct token **_cursor, struct token *end,
1114 return top; 1136 return top;
1115 1137
1116parse_error: 1138parse_error:
1117 fprintf(stderr, "%s:%d: Unexpected token '%*.*s'\n", 1139 fprintf(stderr, "%s:%d: Unexpected token '%s'\n",
1118 filename, cursor->line, 1140 filename, cursor->line, cursor->content);
1119 (int)cursor->size, (int)cursor->size, cursor->value);
1120 exit(1); 1141 exit(1);
1121 1142
1122overrun_error: 1143overrun_error:
@@ -1134,9 +1155,8 @@ static struct element *parse_compound(struct token **_cursor, struct token *end,
1134 struct token *cursor = *_cursor, *name; 1155 struct token *cursor = *_cursor, *name;
1135 1156
1136 if (cursor->token_type != TOKEN_OPEN_CURLY) { 1157 if (cursor->token_type != TOKEN_OPEN_CURLY) {
1137 fprintf(stderr, "%s:%d: Expected compound to start with brace not '%*.*s'\n", 1158 fprintf(stderr, "%s:%d: Expected compound to start with brace not '%s'\n",
1138 filename, cursor->line, 1159 filename, cursor->line, cursor->content);
1139 (int)cursor->size, (int)cursor->size, cursor->value);
1140 exit(1); 1160 exit(1);
1141 } 1161 }
1142 cursor++; 1162 cursor++;
@@ -1177,9 +1197,8 @@ static struct element *parse_compound(struct token **_cursor, struct token *end,
1177 children->flags &= ~ELEMENT_CONDITIONAL; 1197 children->flags &= ~ELEMENT_CONDITIONAL;
1178 1198
1179 if (cursor->token_type != TOKEN_CLOSE_CURLY) { 1199 if (cursor->token_type != TOKEN_CLOSE_CURLY) {
1180 fprintf(stderr, "%s:%d: Expected compound closure, got '%*.*s'\n", 1200 fprintf(stderr, "%s:%d: Expected compound closure, got '%s'\n",
1181 filename, cursor->line, 1201 filename, cursor->line, cursor->content);
1182 (int)cursor->size, (int)cursor->size, cursor->value);
1183 exit(1); 1202 exit(1);
1184 } 1203 }
1185 cursor++; 1204 cursor++;
@@ -1192,6 +1211,52 @@ overrun_error:
1192 exit(1); 1211 exit(1);
1193} 1212}
1194 1213
1214static void dump_element(const struct element *e, int level)
1215{
1216 const struct element *c;
1217 const struct type *t = e->type_def;
1218 const char *name = e->name ? e->name->content : ".";
1219 const char *tname = t && t->name ? t->name->content : ".";
1220 char tag[32];
1221
1222 if (e->class == 0 && e->method == 0 && e->tag == 0)
1223 strcpy(tag, "<...>");
1224 else if (e->class == ASN1_UNIV)
1225 sprintf(tag, "%s %s %s",
1226 asn1_classes[e->class],
1227 asn1_methods[e->method],
1228 asn1_universal_tags[e->tag]);
1229 else
1230 sprintf(tag, "%s %s %u",
1231 asn1_classes[e->class],
1232 asn1_methods[e->method],
1233 e->tag);
1234
1235 printf("%c%c%c%c%c %c %*s[*] \e[33m%s\e[m %s %s \e[35m%s\e[m\n",
1236 e->flags & ELEMENT_IMPLICIT ? 'I' : '-',
1237 e->flags & ELEMENT_EXPLICIT ? 'E' : '-',
1238 e->flags & ELEMENT_TAG_SPECIFIED ? 'T' : '-',
1239 e->flags & ELEMENT_SKIPPABLE ? 'S' : '-',
1240 e->flags & ELEMENT_CONDITIONAL ? 'C' : '-',
1241 "-tTqQcaro"[e->compound],
1242 level, "",
1243 tag,
1244 tname,
1245 name,
1246 e->action ? e->action->name : "");
1247 if (e->compound == TYPE_REF)
1248 dump_element(e->type->type->element, level + 3);
1249 else
1250 for (c = e->children; c; c = c->next)
1251 dump_element(c, level + 3);
1252}
1253
1254static void dump_elements(void)
1255{
1256 if (debug_opt)
1257 dump_element(type_list[0].element, 0);
1258}
1259
1195static void render_element(FILE *out, struct element *e, struct element *tag); 1260static void render_element(FILE *out, struct element *e, struct element *tag);
1196static void render_out_of_line_list(FILE *out); 1261static void render_out_of_line_list(FILE *out);
1197 1262
@@ -1293,7 +1358,7 @@ static void render(FILE *out, FILE *hdr)
1293 } 1358 }
1294 1359
1295 /* We do two passes - the first one calculates all the offsets */ 1360 /* We do two passes - the first one calculates all the offsets */
1296 debug("Pass 1\n"); 1361 verbose("Pass 1\n");
1297 nr_entries = 0; 1362 nr_entries = 0;
1298 root = &type_list[0]; 1363 root = &type_list[0];
1299 render_element(NULL, root->element, NULL); 1364 render_element(NULL, root->element, NULL);
@@ -1304,7 +1369,7 @@ static void render(FILE *out, FILE *hdr)
1304 e->flags &= ~ELEMENT_RENDERED; 1369 e->flags &= ~ELEMENT_RENDERED;
1305 1370
1306 /* And then we actually render */ 1371 /* And then we actually render */
1307 debug("Pass 2\n"); 1372 verbose("Pass 2\n");
1308 fprintf(out, "\n"); 1373 fprintf(out, "\n");
1309 fprintf(out, "static const unsigned char %s_machine[] = {\n", 1374 fprintf(out, "static const unsigned char %s_machine[] = {\n",
1310 grammar_name); 1375 grammar_name);
@@ -1390,9 +1455,7 @@ static void render_element(FILE *out, struct element *e, struct element *tag)
1390 outofline = 1; 1455 outofline = 1;
1391 1456
1392 if (e->type_def && out) { 1457 if (e->type_def && out) {
1393 render_more(out, "\t// %*.*s\n", 1458 render_more(out, "\t// %s\n", e->type_def->name->content);
1394 (int)e->type_def->name->size, (int)e->type_def->name->size,
1395 e->type_def->name->value);
1396 } 1459 }
1397 1460
1398 /* Render the operation */ 1461 /* Render the operation */
@@ -1404,9 +1467,7 @@ static void render_element(FILE *out, struct element *e, struct element *tag)
1404 render_opcode(out, "ASN1_OP_%sMATCH_ANY%s%s,", 1467 render_opcode(out, "ASN1_OP_%sMATCH_ANY%s%s,",
1405 cond, act, skippable ? "_OR_SKIP" : ""); 1468 cond, act, skippable ? "_OR_SKIP" : "");
1406 if (e->name) 1469 if (e->name)
1407 render_more(out, "\t\t// %*.*s", 1470 render_more(out, "\t\t// %s", e->name->content);
1408 (int)e->name->size, (int)e->name->size,
1409 e->name->value);
1410 render_more(out, "\n"); 1471 render_more(out, "\n");
1411 goto dont_render_tag; 1472 goto dont_render_tag;
1412 1473
@@ -1439,9 +1500,7 @@ static void render_element(FILE *out, struct element *e, struct element *tag)
1439 1500
1440 x = tag ?: e; 1501 x = tag ?: e;
1441 if (x->name) 1502 if (x->name)
1442 render_more(out, "\t\t// %*.*s", 1503 render_more(out, "\t\t// %s", x->name->content);
1443 (int)x->name->size, (int)x->name->size,
1444 x->name->value);
1445 render_more(out, "\n"); 1504 render_more(out, "\n");
1446 1505
1447 /* Render the tag */ 1506 /* Render the tag */
@@ -1479,10 +1538,8 @@ dont_render_tag:
1479 * skipability */ 1538 * skipability */
1480 render_opcode(out, "_jump_target(%u),", e->entry_index); 1539 render_opcode(out, "_jump_target(%u),", e->entry_index);
1481 if (e->type_def && e->type_def->name) 1540 if (e->type_def && e->type_def->name)
1482 render_more(out, "\t\t// --> %*.*s", 1541 render_more(out, "\t\t// --> %s",
1483 (int)e->type_def->name->size, 1542 e->type_def->name->content);
1484 (int)e->type_def->name->size,
1485 e->type_def->name->value);
1486 render_more(out, "\n"); 1543 render_more(out, "\n");
1487 if (!(e->flags & ELEMENT_RENDERED)) { 1544 if (!(e->flags & ELEMENT_RENDERED)) {
1488 e->flags |= ELEMENT_RENDERED; 1545 e->flags |= ELEMENT_RENDERED;
@@ -1507,10 +1564,8 @@ dont_render_tag:
1507 * skipability */ 1564 * skipability */
1508 render_opcode(out, "_jump_target(%u),", e->entry_index); 1565 render_opcode(out, "_jump_target(%u),", e->entry_index);
1509 if (e->type_def && e->type_def->name) 1566 if (e->type_def && e->type_def->name)
1510 render_more(out, "\t\t// --> %*.*s", 1567 render_more(out, "\t\t// --> %s",
1511 (int)e->type_def->name->size, 1568 e->type_def->name->content);
1512 (int)e->type_def->name->size,
1513 e->type_def->name->value);
1514 render_more(out, "\n"); 1569 render_more(out, "\n");
1515 if (!(e->flags & ELEMENT_RENDERED)) { 1570 if (!(e->flags & ELEMENT_RENDERED)) {
1516 e->flags |= ELEMENT_RENDERED; 1571 e->flags |= ELEMENT_RENDERED;
diff --git a/scripts/extract-cert.c b/scripts/extract-cert.c
new file mode 100644
index 000000000000..fd0db015c65c
--- /dev/null
+++ b/scripts/extract-cert.c
@@ -0,0 +1,166 @@
1/* Extract X.509 certificate in DER form from PKCS#11 or PEM.
2 *
3 * Copyright © 2014 Red Hat, Inc. All Rights Reserved.
4 * Copyright © 2015 Intel Corporation.
5 *
6 * Authors: David Howells <dhowells@redhat.com>
7 * David Woodhouse <dwmw2@infradead.org>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public Licence
11 * as published by the Free Software Foundation; either version
12 * 2 of the Licence, or (at your option) any later version.
13 */
14#define _GNU_SOURCE
15#include <stdio.h>
16#include <stdlib.h>
17#include <stdint.h>
18#include <stdbool.h>
19#include <string.h>
20#include <getopt.h>
21#include <err.h>
22#include <arpa/inet.h>
23#include <openssl/bio.h>
24#include <openssl/evp.h>
25#include <openssl/pem.h>
26#include <openssl/pkcs7.h>
27#include <openssl/err.h>
28#include <openssl/engine.h>
29
30#define PKEY_ID_PKCS7 2
31
32static __attribute__((noreturn))
33void format(void)
34{
35 fprintf(stderr,
36 "Usage: scripts/extract-cert <source> <dest>\n");
37 exit(2);
38}
39
40static void display_openssl_errors(int l)
41{
42 const char *file;
43 char buf[120];
44 int e, line;
45
46 if (ERR_peek_error() == 0)
47 return;
48 fprintf(stderr, "At main.c:%d:\n", l);
49
50 while ((e = ERR_get_error_line(&file, &line))) {
51 ERR_error_string(e, buf);
52 fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line);
53 }
54}
55
56static void drain_openssl_errors(void)
57{
58 const char *file;
59 int line;
60
61 if (ERR_peek_error() == 0)
62 return;
63 while (ERR_get_error_line(&file, &line)) {}
64}
65
66#define ERR(cond, fmt, ...) \
67 do { \
68 bool __cond = (cond); \
69 display_openssl_errors(__LINE__); \
70 if (__cond) { \
71 err(1, fmt, ## __VA_ARGS__); \
72 } \
73 } while(0)
74
75static const char *key_pass;
76static BIO *wb;
77static char *cert_dst;
78int kbuild_verbose;
79
80static void write_cert(X509 *x509)
81{
82 char buf[200];
83
84 if (!wb) {
85 wb = BIO_new_file(cert_dst, "wb");
86 ERR(!wb, "%s", cert_dst);
87 }
88 X509_NAME_oneline(X509_get_subject_name(x509), buf, sizeof(buf));
89 ERR(!i2d_X509_bio(wb, x509), cert_dst);
90 if (kbuild_verbose)
91 fprintf(stderr, "Extracted cert: %s\n", buf);
92}
93
94int main(int argc, char **argv)
95{
96 char *cert_src;
97
98 OpenSSL_add_all_algorithms();
99 ERR_load_crypto_strings();
100 ERR_clear_error();
101
102 kbuild_verbose = atoi(getenv("KBUILD_VERBOSE")?:"0");
103
104 key_pass = getenv("KBUILD_SIGN_PIN");
105
106 if (argc != 3)
107 format();
108
109 cert_src = argv[1];
110 cert_dst = argv[2];
111
112 if (!cert_src[0]) {
113 /* Invoked with no input; create empty file */
114 FILE *f = fopen(cert_dst, "wb");
115 ERR(!f, "%s", cert_dst);
116 fclose(f);
117 exit(0);
118 } else if (!strncmp(cert_src, "pkcs11:", 7)) {
119 ENGINE *e;
120 struct {
121 const char *cert_id;
122 X509 *cert;
123 } parms;
124
125 parms.cert_id = cert_src;
126 parms.cert = NULL;
127
128 ENGINE_load_builtin_engines();
129 drain_openssl_errors();
130 e = ENGINE_by_id("pkcs11");
131 ERR(!e, "Load PKCS#11 ENGINE");
132 if (ENGINE_init(e))
133 drain_openssl_errors();
134 else
135 ERR(1, "ENGINE_init");
136 if (key_pass)
137 ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), "Set PKCS#11 PIN");
138 ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &parms, NULL, 1);
139 ERR(!parms.cert, "Get X.509 from PKCS#11");
140 write_cert(parms.cert);
141 } else {
142 BIO *b;
143 X509 *x509;
144
145 b = BIO_new_file(cert_src, "rb");
146 ERR(!b, "%s", cert_src);
147
148 while (1) {
149 x509 = PEM_read_bio_X509(b, NULL, NULL, NULL);
150 if (wb && !x509) {
151 unsigned long err = ERR_peek_last_error();
152 if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
153 ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
154 ERR_clear_error();
155 break;
156 }
157 }
158 ERR(!x509, "%s", cert_src);
159 write_cert(x509);
160 }
161 }
162
163 BIO_free(wb);
164
165 return 0;
166}
diff --git a/scripts/sign-file b/scripts/sign-file
deleted file mode 100755
index 3906ee1e2f76..000000000000
--- a/scripts/sign-file
+++ /dev/null
@@ -1,421 +0,0 @@
1#!/usr/bin/perl -w
2#
3# Sign a module file using the given key.
4#
5
6my $USAGE =
7"Usage: scripts/sign-file [-v] <hash algo> <key> <x509> <module> [<dest>]\n" .
8" scripts/sign-file [-v] -s <raw sig> <hash algo> <x509> <module> [<dest>]\n";
9
10use strict;
11use FileHandle;
12use IPC::Open2;
13use Getopt::Std;
14
15my %opts;
16getopts('vs:', \%opts) or die $USAGE;
17my $verbose = $opts{'v'};
18my $signature_file = $opts{'s'};
19
20die $USAGE if ($#ARGV > 4);
21die $USAGE if (!$signature_file && $#ARGV < 3 || $signature_file && $#ARGV < 2);
22
23my $dgst = shift @ARGV;
24my $private_key;
25if (!$signature_file) {
26 $private_key = shift @ARGV;
27}
28my $x509 = shift @ARGV;
29my $module = shift @ARGV;
30my ($dest, $keep_orig);
31if (@ARGV) {
32 $dest = $ARGV[0];
33 $keep_orig = 1;
34} else {
35 $dest = $module . "~";
36}
37
38die "Can't read private key\n" if (!$signature_file && !-r $private_key);
39die "Can't read signature file\n" if ($signature_file && !-r $signature_file);
40die "Can't read X.509 certificate\n" unless (-r $x509);
41die "Can't read module\n" unless (-r $module);
42
43#
44# Function to read the contents of a file into a variable.
45#
46sub read_file($)
47{
48 my ($file) = @_;
49 my $contents;
50 my $len;
51
52 open(FD, "<$file") || die $file;
53 binmode FD;
54 my @st = stat(FD);
55 die $file if (!@st);
56 $len = read(FD, $contents, $st[7]) || die $file;
57 close(FD) || die $file;
58 die "$file: Wanted length ", $st[7], ", got ", $len, "\n"
59 if ($len != $st[7]);
60 return $contents;
61}
62
63###############################################################################
64#
65# First of all, we have to parse the X.509 certificate to find certain details
66# about it.
67#
68# We read the DER-encoded X509 certificate and parse it to extract the Subject
69# name and Subject Key Identifier. Theis provides the data we need to build
70# the certificate identifier.
71#
72# The signer's name part of the identifier is fabricated from the commonName,
73# the organizationName or the emailAddress components of the X.509 subject
74# name.
75#
76# The subject key ID is used to select which of that signer's certificates
77# we're intending to use to sign the module.
78#
79###############################################################################
80my $x509_certificate = read_file($x509);
81
82my $UNIV = 0 << 6;
83my $APPL = 1 << 6;
84my $CONT = 2 << 6;
85my $PRIV = 3 << 6;
86
87my $CONS = 0x20;
88
89my $BOOLEAN = 0x01;
90my $INTEGER = 0x02;
91my $BIT_STRING = 0x03;
92my $OCTET_STRING = 0x04;
93my $NULL = 0x05;
94my $OBJ_ID = 0x06;
95my $UTF8String = 0x0c;
96my $SEQUENCE = 0x10;
97my $SET = 0x11;
98my $UTCTime = 0x17;
99my $GeneralizedTime = 0x18;
100
101my %OIDs = (
102 pack("CCC", 85, 4, 3) => "commonName",
103 pack("CCC", 85, 4, 6) => "countryName",
104 pack("CCC", 85, 4, 10) => "organizationName",
105 pack("CCC", 85, 4, 11) => "organizationUnitName",
106 pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption",
107 pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption",
108 pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress",
109 pack("CCC", 85, 29, 35) => "authorityKeyIdentifier",
110 pack("CCC", 85, 29, 14) => "subjectKeyIdentifier",
111 pack("CCC", 85, 29, 19) => "basicConstraints"
112);
113
114###############################################################################
115#
116# Extract an ASN.1 element from a string and return information about it.
117#
118###############################################################################
119sub asn1_extract($$@)
120{
121 my ($cursor, $expected_tag, $optional) = @_;
122
123 return [ -1 ]
124 if ($cursor->[1] == 0 && $optional);
125
126 die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n"
127 if ($cursor->[1] < 2);
128
129 my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2));
130
131 if ($expected_tag != -1 && $tag != $expected_tag) {
132 return [ -1 ]
133 if ($optional);
134 die $x509, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag,
135 " not ", $expected_tag, ")\n";
136 }
137
138 $cursor->[0] += 2;
139 $cursor->[1] -= 2;
140
141 die $x509, ": ", $cursor->[0], ": ASN.1 long tag\n"
142 if (($tag & 0x1f) == 0x1f);
143 die $x509, ": ", $cursor->[0], ": ASN.1 indefinite length\n"
144 if ($len == 0x80);
145
146 if ($len > 0x80) {
147 my $l = $len - 0x80;
148 die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n"
149 if ($cursor->[1] < $l);
150
151 if ($l == 0x1) {
152 $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1));
153 } elsif ($l == 0x2) {
154 $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2));
155 } elsif ($l == 0x3) {
156 $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16;
157 $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2));
158 } elsif ($l == 0x4) {
159 $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4));
160 } else {
161 die $x509, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n";
162 }
163
164 $cursor->[0] += $l;
165 $cursor->[1] -= $l;
166 }
167
168 die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n"
169 if ($cursor->[1] < $len);
170
171 my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ];
172 $cursor->[0] += $len;
173 $cursor->[1] -= $len;
174
175 return $ret;
176}
177
178###############################################################################
179#
180# Retrieve the data referred to by a cursor
181#
182###############################################################################
183sub asn1_retrieve($)
184{
185 my ($cursor) = @_;
186 my ($offset, $len, $data) = @$cursor;
187 return substr($$data, $offset, $len);
188}
189
190###############################################################################
191#
192# Roughly parse the X.509 certificate
193#
194###############################################################################
195my $cursor = [ 0, length($x509_certificate), \$x509_certificate ];
196
197my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE);
198my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE);
199my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1);
200my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER);
201my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
202my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
203my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
204my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
205my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
206my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1);
207my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1);
208my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1);
209
210my $subject_key_id = ();
211my $authority_key_id = ();
212
213#
214# Parse the extension list
215#
216if ($extension_list->[0] != -1) {
217 my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE);
218
219 while ($extensions->[1]->[1] > 0) {
220 my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE);
221 my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID);
222 my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1);
223 my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING);
224
225 my $raw_oid = asn1_retrieve($x_oid->[1]);
226 next if (!exists($OIDs{$raw_oid}));
227 my $x_type = $OIDs{$raw_oid};
228
229 my $raw_value = asn1_retrieve($x_val->[1]);
230
231 if ($x_type eq "subjectKeyIdentifier") {
232 my $vcursor = [ 0, length($raw_value), \$raw_value ];
233
234 $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING);
235 }
236 }
237}
238
239###############################################################################
240#
241# Determine what we're going to use as the signer's name. In order of
242# preference, take one of: commonName, organizationName or emailAddress.
243#
244###############################################################################
245my $org = "";
246my $cn = "";
247my $email = "";
248
249while ($subject->[1]->[1] > 0) {
250 my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET);
251 my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE);
252 my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID);
253 my $n_val = asn1_extract($attr->[1], -1);
254
255 my $raw_oid = asn1_retrieve($n_oid->[1]);
256 next if (!exists($OIDs{$raw_oid}));
257 my $n_type = $OIDs{$raw_oid};
258
259 my $raw_value = asn1_retrieve($n_val->[1]);
260
261 if ($n_type eq "organizationName") {
262 $org = $raw_value;
263 } elsif ($n_type eq "commonName") {
264 $cn = $raw_value;
265 } elsif ($n_type eq "emailAddress") {
266 $email = $raw_value;
267 }
268}
269
270my $signers_name = $email;
271
272if ($org && $cn) {
273 # Don't use the organizationName if the commonName repeats it
274 if (length($org) <= length($cn) &&
275 substr($cn, 0, length($org)) eq $org) {
276 $signers_name = $cn;
277 goto got_id_name;
278 }
279
280 # Or a signifcant chunk of it
281 if (length($org) >= 7 &&
282 length($cn) >= 7 &&
283 substr($cn, 0, 7) eq substr($org, 0, 7)) {
284 $signers_name = $cn;
285 goto got_id_name;
286 }
287
288 $signers_name = $org . ": " . $cn;
289} elsif ($org) {
290 $signers_name = $org;
291} elsif ($cn) {
292 $signers_name = $cn;
293}
294
295got_id_name:
296
297die $x509, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n"
298 if (!$subject_key_id);
299
300my $key_identifier = asn1_retrieve($subject_key_id->[1]);
301
302###############################################################################
303#
304# Create and attach the module signature
305#
306###############################################################################
307
308#
309# Signature parameters
310#
311my $algo = 1; # Public-key crypto algorithm: RSA
312my $hash = 0; # Digest algorithm
313my $id_type = 1; # Identifier type: X.509
314
315#
316# Digest the data
317#
318my $prologue;
319if ($dgst eq "sha1") {
320 $prologue = pack("C*",
321 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
322 0x2B, 0x0E, 0x03, 0x02, 0x1A,
323 0x05, 0x00, 0x04, 0x14);
324 $hash = 2;
325} elsif ($dgst eq "sha224") {
326 $prologue = pack("C*",
327 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
328 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
329 0x05, 0x00, 0x04, 0x1C);
330 $hash = 7;
331} elsif ($dgst eq "sha256") {
332 $prologue = pack("C*",
333 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
334 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
335 0x05, 0x00, 0x04, 0x20);
336 $hash = 4;
337} elsif ($dgst eq "sha384") {
338 $prologue = pack("C*",
339 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
340 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
341 0x05, 0x00, 0x04, 0x30);
342 $hash = 5;
343} elsif ($dgst eq "sha512") {
344 $prologue = pack("C*",
345 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
346 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
347 0x05, 0x00, 0x04, 0x40);
348 $hash = 6;
349} else {
350 die "Unknown hash algorithm: $dgst\n";
351}
352
353my $signature;
354if ($signature_file) {
355 $signature = read_file($signature_file);
356} else {
357 #
358 # Generate the digest and read from openssl's stdout
359 #
360 my $digest;
361 $digest = readpipe("openssl dgst -$dgst -binary $module") || die "openssl dgst";
362
363 #
364 # Generate the binary signature, which will be just the integer that
365 # comprises the signature with no metadata attached.
366 #
367 my $pid;
368 $pid = open2(*read_from, *write_to,
369 "openssl rsautl -sign -inkey $private_key -keyform PEM") ||
370 die "openssl rsautl";
371 binmode write_to;
372 print write_to $prologue . $digest || die "pipe to openssl rsautl";
373 close(write_to) || die "pipe to openssl rsautl";
374
375 binmode read_from;
376 read(read_from, $signature, 4096) || die "pipe from openssl rsautl";
377 close(read_from) || die "pipe from openssl rsautl";
378 waitpid($pid, 0) || die;
379 die "openssl rsautl died: $?" if ($? >> 8);
380}
381$signature = pack("n", length($signature)) . $signature,
382
383#
384# Build the signed binary
385#
386my $unsigned_module = read_file($module);
387
388my $magic_number = "~Module signature appended~\n";
389
390my $info = pack("CCCCCxxxN",
391 $algo, $hash, $id_type,
392 length($signers_name),
393 length($key_identifier),
394 length($signature));
395
396if ($verbose) {
397 print "Size of unsigned module: ", length($unsigned_module), "\n";
398 print "Size of signer's name : ", length($signers_name), "\n";
399 print "Size of key identifier : ", length($key_identifier), "\n";
400 print "Size of signature : ", length($signature), "\n";
401 print "Size of information : ", length($info), "\n";
402 print "Size of magic number : ", length($magic_number), "\n";
403 print "Signer's name : '", $signers_name, "'\n";
404 print "Digest : $dgst\n";
405}
406
407open(FD, ">$dest") || die $dest;
408binmode FD;
409print FD
410 $unsigned_module,
411 $signers_name,
412 $key_identifier,
413 $signature,
414 $info,
415 $magic_number
416 ;
417close FD || die $dest;
418
419if (!$keep_orig) {
420 rename($dest, $module) || die $module;
421}
diff --git a/scripts/sign-file.c b/scripts/sign-file.c
new file mode 100755
index 000000000000..058bba3103e2
--- /dev/null
+++ b/scripts/sign-file.c
@@ -0,0 +1,260 @@
1/* Sign a module file using the given key.
2 *
3 * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#define _GNU_SOURCE
12#include <stdio.h>
13#include <stdlib.h>
14#include <stdint.h>
15#include <stdbool.h>
16#include <string.h>
17#include <getopt.h>
18#include <err.h>
19#include <arpa/inet.h>
20#include <openssl/bio.h>
21#include <openssl/evp.h>
22#include <openssl/pem.h>
23#include <openssl/cms.h>
24#include <openssl/err.h>
25#include <openssl/engine.h>
26
27struct module_signature {
28 uint8_t algo; /* Public-key crypto algorithm [0] */
29 uint8_t hash; /* Digest algorithm [0] */
30 uint8_t id_type; /* Key identifier type [PKEY_ID_PKCS7] */
31 uint8_t signer_len; /* Length of signer's name [0] */
32 uint8_t key_id_len; /* Length of key identifier [0] */
33 uint8_t __pad[3];
34 uint32_t sig_len; /* Length of signature data */
35};
36
37#define PKEY_ID_PKCS7 2
38
39static char magic_number[] = "~Module signature appended~\n";
40
41static __attribute__((noreturn))
42void format(void)
43{
44 fprintf(stderr,
45 "Usage: scripts/sign-file [-dp] <hash algo> <key> <x509> <module> [<dest>]\n");
46 exit(2);
47}
48
49static void display_openssl_errors(int l)
50{
51 const char *file;
52 char buf[120];
53 int e, line;
54
55 if (ERR_peek_error() == 0)
56 return;
57 fprintf(stderr, "At main.c:%d:\n", l);
58
59 while ((e = ERR_get_error_line(&file, &line))) {
60 ERR_error_string(e, buf);
61 fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line);
62 }
63}
64
65static void drain_openssl_errors(void)
66{
67 const char *file;
68 int line;
69
70 if (ERR_peek_error() == 0)
71 return;
72 while (ERR_get_error_line(&file, &line)) {}
73}
74
75#define ERR(cond, fmt, ...) \
76 do { \
77 bool __cond = (cond); \
78 display_openssl_errors(__LINE__); \
79 if (__cond) { \
80 err(1, fmt, ## __VA_ARGS__); \
81 } \
82 } while(0)
83
84static const char *key_pass;
85
86static int pem_pw_cb(char *buf, int len, int w, void *v)
87{
88 int pwlen;
89
90 if (!key_pass)
91 return -1;
92
93 pwlen = strlen(key_pass);
94 if (pwlen >= len)
95 return -1;
96
97 strcpy(buf, key_pass);
98
99 /* If it's wrong, don't keep trying it. */
100 key_pass = NULL;
101
102 return pwlen;
103}
104
105int main(int argc, char **argv)
106{
107 struct module_signature sig_info = { .id_type = PKEY_ID_PKCS7 };
108 char *hash_algo = NULL;
109 char *private_key_name, *x509_name, *module_name, *dest_name;
110 bool save_cms = false, replace_orig;
111 bool sign_only = false;
112 unsigned char buf[4096];
113 unsigned long module_size, cms_size;
114 unsigned int use_keyid = 0, use_signed_attrs = CMS_NOATTR;
115 const EVP_MD *digest_algo;
116 EVP_PKEY *private_key;
117 CMS_ContentInfo *cms;
118 X509 *x509;
119 BIO *b, *bd = NULL, *bm;
120 int opt, n;
121
122 OpenSSL_add_all_algorithms();
123 ERR_load_crypto_strings();
124 ERR_clear_error();
125
126 key_pass = getenv("KBUILD_SIGN_PIN");
127
128 do {
129 opt = getopt(argc, argv, "dpk");
130 switch (opt) {
131 case 'p': save_cms = true; break;
132 case 'd': sign_only = true; save_cms = true; break;
133 case 'k': use_keyid = CMS_USE_KEYID; break;
134 case -1: break;
135 default: format();
136 }
137 } while (opt != -1);
138
139 argc -= optind;
140 argv += optind;
141 if (argc < 4 || argc > 5)
142 format();
143
144 hash_algo = argv[0];
145 private_key_name = argv[1];
146 x509_name = argv[2];
147 module_name = argv[3];
148 if (argc == 5) {
149 dest_name = argv[4];
150 replace_orig = false;
151 } else {
152 ERR(asprintf(&dest_name, "%s.~signed~", module_name) < 0,
153 "asprintf");
154 replace_orig = true;
155 }
156
157 /* Read the private key and the X.509 cert the PKCS#7 message
158 * will point to.
159 */
160 if (!strncmp(private_key_name, "pkcs11:", 7)) {
161 ENGINE *e;
162
163 ENGINE_load_builtin_engines();
164 drain_openssl_errors();
165 e = ENGINE_by_id("pkcs11");
166 ERR(!e, "Load PKCS#11 ENGINE");
167 if (ENGINE_init(e))
168 drain_openssl_errors();
169 else
170 ERR(1, "ENGINE_init");
171 if (key_pass)
172 ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), "Set PKCS#11 PIN");
173 private_key = ENGINE_load_private_key(e, private_key_name, NULL,
174 NULL);
175 ERR(!private_key, "%s", private_key_name);
176 } else {
177 b = BIO_new_file(private_key_name, "rb");
178 ERR(!b, "%s", private_key_name);
179 private_key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb, NULL);
180 ERR(!private_key, "%s", private_key_name);
181 BIO_free(b);
182 }
183
184 b = BIO_new_file(x509_name, "rb");
185 ERR(!b, "%s", x509_name);
186 x509 = d2i_X509_bio(b, NULL); /* Binary encoded X.509 */
187 if (!x509) {
188 ERR(BIO_reset(b) != 1, "%s", x509_name);
189 x509 = PEM_read_bio_X509(b, NULL, NULL, NULL); /* PEM encoded X.509 */
190 if (x509)
191 drain_openssl_errors();
192 }
193 BIO_free(b);
194 ERR(!x509, "%s", x509_name);
195
196 /* Open the destination file now so that we can shovel the module data
197 * across as we read it.
198 */
199 if (!sign_only) {
200 bd = BIO_new_file(dest_name, "wb");
201 ERR(!bd, "%s", dest_name);
202 }
203
204 /* Digest the module data. */
205 OpenSSL_add_all_digests();
206 display_openssl_errors(__LINE__);
207 digest_algo = EVP_get_digestbyname(hash_algo);
208 ERR(!digest_algo, "EVP_get_digestbyname");
209
210 bm = BIO_new_file(module_name, "rb");
211 ERR(!bm, "%s", module_name);
212
213 /* Load the CMS message from the digest buffer. */
214 cms = CMS_sign(NULL, NULL, NULL, NULL,
215 CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | CMS_DETACHED | CMS_STREAM);
216 ERR(!cms, "CMS_sign");
217
218 ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo,
219 CMS_NOCERTS | CMS_BINARY | CMS_NOSMIMECAP |
220 use_keyid | use_signed_attrs),
221 "CMS_sign_add_signer");
222 ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) < 0,
223 "CMS_final");
224
225 if (save_cms) {
226 char *cms_name;
227
228 ERR(asprintf(&cms_name, "%s.p7s", module_name) < 0, "asprintf");
229 b = BIO_new_file(cms_name, "wb");
230 ERR(!b, "%s", cms_name);
231 ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) < 0, "%s", cms_name);
232 BIO_free(b);
233 }
234
235 if (sign_only)
236 return 0;
237
238 /* Append the marker and the PKCS#7 message to the destination file */
239 ERR(BIO_reset(bm) < 0, "%s", module_name);
240 while ((n = BIO_read(bm, buf, sizeof(buf))),
241 n > 0) {
242 ERR(BIO_write(bd, buf, n) < 0, "%s", dest_name);
243 }
244 ERR(n < 0, "%s", module_name);
245 module_size = BIO_number_written(bd);
246
247 ERR(i2d_CMS_bio_stream(bd, cms, NULL, 0) < 0, "%s", dest_name);
248 cms_size = BIO_number_written(bd) - module_size;
249 sig_info.sig_len = htonl(cms_size);
250 ERR(BIO_write(bd, &sig_info, sizeof(sig_info)) < 0, "%s", dest_name);
251 ERR(BIO_write(bd, magic_number, sizeof(magic_number) - 1) < 0, "%s", dest_name);
252
253 ERR(BIO_free(bd) < 0, "%s", dest_name);
254
255 /* Finally, if we're signing in place, replace the original. */
256 if (replace_orig)
257 ERR(rename(dest_name, module_name) < 0, "%s", dest_name);
258
259 return 0;
260}