Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/* Sign a module file using the given key.
2 *
3 * Copyright © 2014-2016 Red Hat, Inc. All Rights Reserved.
4 * Copyright © 2015 Intel Corporation.
5 * Copyright © 2016 Hewlett Packard Enterprise Development LP
6 *
7 * Authors: David Howells <dhowells@redhat.com>
8 * David Woodhouse <dwmw2@infradead.org>
9 * Juerg Haefliger <juerg.haefliger@hpe.com>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the licence, or (at your option) any later version.
15 */
16#define _GNU_SOURCE
17#include <stdio.h>
18#include <stdlib.h>
19#include <stdint.h>
20#include <stdbool.h>
21#include <string.h>
22#include <getopt.h>
23#include <err.h>
24#include <arpa/inet.h>
25#include <openssl/opensslv.h>
26#include <openssl/bio.h>
27#include <openssl/cms.h>
28#include <openssl/evp.h>
29#include <openssl/pem.h>
30#include <openssl/err.h>
31#if OPENSSL_VERSION_NUMBER >= 0x30000000L
32# define USE_PKCS11_PROVIDER
33# include <openssl/provider.h>
34# include <openssl/store.h>
35#else
36# if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0)
37# define USE_PKCS11_ENGINE
38# include <openssl/engine.h>
39# endif
40#endif
41#include "ssl-common.h"
42
43#include <linux/module_signature.h>
44
45static __attribute__((noreturn))
46void format(void)
47{
48 fprintf(stderr,
49 "Usage: scripts/sign-file [-dp] <hash algo> <key> <x509> <module> [<dest>]\n");
50 fprintf(stderr,
51 " scripts/sign-file -s <raw sig> <hash algo> <x509> <module> [<dest>]\n");
52 exit(2);
53}
54
55static const char *key_pass;
56
57static int pem_pw_cb(char *buf, int len, int w, void *v)
58{
59 int pwlen;
60
61 if (!key_pass)
62 return -1;
63
64 pwlen = strlen(key_pass);
65 if (pwlen >= len)
66 return -1;
67
68 strcpy(buf, key_pass);
69
70 /* If it's wrong, don't keep trying it. */
71 key_pass = NULL;
72
73 return pwlen;
74}
75
76static EVP_PKEY *read_private_key_pkcs11(const char *private_key_name)
77{
78 EVP_PKEY *private_key = NULL;
79#ifdef USE_PKCS11_PROVIDER
80 OSSL_STORE_CTX *store;
81
82 if (!OSSL_PROVIDER_try_load(NULL, "pkcs11", true))
83 ERR(1, "OSSL_PROVIDER_try_load(pkcs11)");
84 if (!OSSL_PROVIDER_try_load(NULL, "default", true))
85 ERR(1, "OSSL_PROVIDER_try_load(default)");
86
87 store = OSSL_STORE_open(private_key_name, NULL, NULL, NULL, NULL);
88 ERR(!store, "OSSL_STORE_open");
89
90 while (!OSSL_STORE_eof(store)) {
91 OSSL_STORE_INFO *info = OSSL_STORE_load(store);
92
93 if (!info) {
94 drain_openssl_errors(__LINE__, 0);
95 continue;
96 }
97 if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY) {
98 private_key = OSSL_STORE_INFO_get1_PKEY(info);
99 ERR(!private_key, "OSSL_STORE_INFO_get1_PKEY");
100 }
101 OSSL_STORE_INFO_free(info);
102 if (private_key)
103 break;
104 }
105 OSSL_STORE_close(store);
106#elif defined(USE_PKCS11_ENGINE)
107 ENGINE *e;
108
109 ENGINE_load_builtin_engines();
110 drain_openssl_errors(__LINE__, 1);
111 e = ENGINE_by_id("pkcs11");
112 ERR(!e, "Load PKCS#11 ENGINE");
113 if (ENGINE_init(e))
114 drain_openssl_errors(__LINE__, 1);
115 else
116 ERR(1, "ENGINE_init");
117 if (key_pass)
118 ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), "Set PKCS#11 PIN");
119 private_key = ENGINE_load_private_key(e, private_key_name, NULL, NULL);
120 ERR(!private_key, "%s", private_key_name);
121#else
122 fprintf(stderr, "no pkcs11 engine/provider available\n");
123 exit(1);
124#endif
125 return private_key;
126}
127
128static EVP_PKEY *read_private_key(const char *private_key_name)
129{
130 if (!strncmp(private_key_name, "pkcs11:", 7)) {
131 return read_private_key_pkcs11(private_key_name);
132 } else {
133 EVP_PKEY *private_key;
134 BIO *b;
135
136 b = BIO_new_file(private_key_name, "rb");
137 ERR(!b, "%s", private_key_name);
138 private_key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb,
139 NULL);
140 ERR(!private_key, "%s", private_key_name);
141 BIO_free(b);
142
143 return private_key;
144 }
145}
146
147static X509 *read_x509(const char *x509_name)
148{
149 unsigned char buf[2];
150 X509 *x509;
151 BIO *b;
152 int n;
153
154 b = BIO_new_file(x509_name, "rb");
155 ERR(!b, "%s", x509_name);
156
157 /* Look at the first two bytes of the file to determine the encoding */
158 n = BIO_read(b, buf, 2);
159 if (n != 2) {
160 if (BIO_should_retry(b)) {
161 fprintf(stderr, "%s: Read wanted retry\n", x509_name);
162 exit(1);
163 }
164 if (n >= 0) {
165 fprintf(stderr, "%s: Short read\n", x509_name);
166 exit(1);
167 }
168 ERR(1, "%s", x509_name);
169 }
170
171 ERR(BIO_reset(b) != 0, "%s", x509_name);
172
173 if (buf[0] == 0x30 && buf[1] >= 0x81 && buf[1] <= 0x84)
174 /* Assume raw DER encoded X.509 */
175 x509 = d2i_X509_bio(b, NULL);
176 else
177 /* Assume PEM encoded X.509 */
178 x509 = PEM_read_bio_X509(b, NULL, NULL, NULL);
179
180 BIO_free(b);
181 ERR(!x509, "%s", x509_name);
182
183 return x509;
184}
185
186int main(int argc, char **argv)
187{
188 struct module_signature sig_info = { .id_type = MODULE_SIGNATURE_TYPE_PKCS7 };
189 char *hash_algo = NULL;
190 char *private_key_name = NULL, *raw_sig_name = NULL;
191 char *x509_name, *module_name, *dest_name;
192 bool save_sig = false, replace_orig;
193 bool sign_only = false;
194 bool raw_sig = false;
195 unsigned char buf[4096];
196 unsigned long module_size, sig_size;
197 const EVP_MD *digest_algo;
198 EVP_PKEY *private_key;
199 CMS_ContentInfo *cms = NULL;
200 unsigned int use_keyid = 0;
201 X509 *x509;
202 BIO *bd, *bm;
203 int opt, n;
204 OpenSSL_add_all_algorithms();
205 ERR_load_crypto_strings();
206 ERR_clear_error();
207
208 key_pass = getenv("KBUILD_SIGN_PIN");
209
210 do {
211 opt = getopt(argc, argv, "sdpk");
212 switch (opt) {
213 case 's': raw_sig = true; break;
214 case 'p': save_sig = true; break;
215 case 'd': sign_only = true; save_sig = true; break;
216 case 'k': use_keyid = CMS_USE_KEYID; break;
217 case -1: break;
218 default: format();
219 }
220 } while (opt != -1);
221
222 argc -= optind;
223 argv += optind;
224 if (argc < 4 || argc > 5)
225 format();
226
227 if (raw_sig) {
228 raw_sig_name = argv[0];
229 hash_algo = argv[1];
230 } else {
231 hash_algo = argv[0];
232 private_key_name = argv[1];
233 }
234 x509_name = argv[2];
235 module_name = argv[3];
236 if (argc == 5 && strcmp(argv[3], argv[4]) != 0) {
237 dest_name = argv[4];
238 replace_orig = false;
239 } else {
240 ERR(asprintf(&dest_name, "%s.~signed~", module_name) < 0,
241 "asprintf");
242 replace_orig = true;
243 }
244
245 /* Open the module file */
246 bm = BIO_new_file(module_name, "rb");
247 ERR(!bm, "%s", module_name);
248
249 if (!raw_sig) {
250 /* Read the private key and the X.509 cert the PKCS#7 message
251 * will point to.
252 */
253 private_key = read_private_key(private_key_name);
254 x509 = read_x509(x509_name);
255
256 /* Digest the module data. */
257 OpenSSL_add_all_digests();
258 drain_openssl_errors(__LINE__, 0);
259 digest_algo = EVP_get_digestbyname(hash_algo);
260 ERR(!digest_algo, "EVP_get_digestbyname");
261
262 unsigned int flags =
263 CMS_NOCERTS |
264 CMS_NOATTR |
265 CMS_PARTIAL |
266 CMS_BINARY |
267 CMS_DETACHED |
268 CMS_STREAM |
269 CMS_NOSMIMECAP |
270#ifdef CMS_NO_SIGNING_TIME
271 CMS_NO_SIGNING_TIME |
272#endif
273 use_keyid;
274
275#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_VERSION_NUMBER < 0x40000000L
276 if (EVP_PKEY_is_a(private_key, "ML-DSA-44") ||
277 EVP_PKEY_is_a(private_key, "ML-DSA-65") ||
278 EVP_PKEY_is_a(private_key, "ML-DSA-87")) {
279 /* ML-DSA + CMS_NOATTR is not supported in openssl-3.5
280 * and before.
281 */
282 flags &= ~CMS_NOATTR;
283 }
284#endif
285
286 /* Load the signature message from the digest buffer. */
287 cms = CMS_sign(NULL, NULL, NULL, NULL, flags);
288 ERR(!cms, "CMS_sign");
289
290 ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo, flags),
291 "CMS_add1_signer");
292 ERR(CMS_final(cms, bm, NULL, flags) != 1,
293 "CMS_final");
294
295 if (save_sig) {
296 char *sig_file_name;
297 BIO *b;
298
299 ERR(asprintf(&sig_file_name, "%s.p7s", module_name) < 0,
300 "asprintf");
301 b = BIO_new_file(sig_file_name, "wb");
302 ERR(!b, "%s", sig_file_name);
303 ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) != 1,
304 "%s", sig_file_name);
305 BIO_free(b);
306 }
307
308 if (sign_only) {
309 BIO_free(bm);
310 return 0;
311 }
312 }
313
314 /* Open the destination file now so that we can shovel the module data
315 * across as we read it.
316 */
317 bd = BIO_new_file(dest_name, "wb");
318 ERR(!bd, "%s", dest_name);
319
320 /* Append the marker and the PKCS#7 message to the destination file */
321 ERR(BIO_reset(bm) < 0, "%s", module_name);
322 while ((n = BIO_read(bm, buf, sizeof(buf))),
323 n > 0) {
324 ERR(BIO_write(bd, buf, n) < 0, "%s", dest_name);
325 }
326 BIO_free(bm);
327 ERR(n < 0, "%s", module_name);
328 module_size = BIO_number_written(bd);
329
330 if (!raw_sig) {
331 ERR(i2d_CMS_bio_stream(bd, cms, NULL, 0) != 1, "%s", dest_name);
332 } else {
333 BIO *b;
334
335 /* Read the raw signature file and write the data to the
336 * destination file
337 */
338 b = BIO_new_file(raw_sig_name, "rb");
339 ERR(!b, "%s", raw_sig_name);
340 while ((n = BIO_read(b, buf, sizeof(buf))), n > 0)
341 ERR(BIO_write(bd, buf, n) < 0, "%s", dest_name);
342 BIO_free(b);
343 }
344
345 sig_size = BIO_number_written(bd) - module_size;
346 sig_info.sig_len = htonl(sig_size);
347 ERR(BIO_write(bd, &sig_info, sizeof(sig_info)) < 0, "%s", dest_name);
348 ERR(BIO_write(bd, MODULE_SIGNATURE_MARKER, sizeof(MODULE_SIGNATURE_MARKER) - 1) < 0,
349 "%s", dest_name);
350
351 ERR(BIO_free(bd) != 1, "%s", dest_name);
352
353 /* Finally, if we're signing in place, replace the original. */
354 if (replace_orig)
355 ERR(rename(dest_name, module_name) < 0, "%s", dest_name);
356
357 return 0;
358}