2 * Copyright (C) 2016 Raptor Engineering, LLC
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #if defined(HAVE_CONFIG_H)
28 #include <sys/types.h>
31 #include <file/file.h>
32 #include <talloc/talloc.h>
34 #include <util/util.h>
35 #include <i18n/i18n.h>
40 * If --with-signed-boot is enabled lib/security provides the ability to handle
41 * gpg-signed and/or encrypted boot sources (kernel, initrd, etc).
42 * This can be used to enable a form of secure boot, but it is important to
43 * recognise that it depends on the security of the entire system, for example
44 * a full trusted-boot implementation. Petitboot can not and will not be able
45 * to guarantee secure boot by itself.
48 struct pb_url * gpg_get_signature_url(void *ctx, struct pb_url *base_file)
50 struct pb_url *signature_file = NULL;
52 signature_file = pb_url_copy(ctx, base_file);
53 talloc_free(signature_file->file);
54 signature_file->file = talloc_asprintf(signature_file,
55 "%s.sig", base_file->file);
56 talloc_free(signature_file->path);
57 signature_file->path = talloc_asprintf(signature_file,
58 "%s.sig", base_file->path);
60 return signature_file;
63 int decrypt_file(const char *filename,
64 FILE *authorized_signatures_handle, const char *keyring_path)
68 size_t bytes_read = 0;
69 unsigned char buffer[8192];
74 gpgme_signature_t verification_signatures;
75 gpgme_verify_result_t verification_result;
76 gpgme_data_t ciphertext_data;
77 gpgme_data_t plaintext_data;
78 gpgme_engine_info_t enginfo;
79 gpgme_ctx_t gpg_context;
82 /* Initialize gpgme */
83 setlocale (LC_ALL, "");
84 gpgme_check_version(NULL);
85 gpgme_set_locale(NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
86 err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
87 if (err != GPG_ERR_NO_ERROR) {
88 pb_log("%s: OpenPGP support not available\n", __func__);
91 err = gpgme_get_engine_info(&enginfo);
92 if (err != GPG_ERR_NO_ERROR) {
93 pb_log("%s: GPG engine failed to initialize\n", __func__);
96 err = gpgme_new(&gpg_context);
97 if (err != GPG_ERR_NO_ERROR) {
98 pb_log("%s: GPG context could not be created\n", __func__);
101 err = gpgme_set_protocol(gpg_context, GPGME_PROTOCOL_OpenPGP);
102 if (err != GPG_ERR_NO_ERROR) {
103 pb_log("%s: GPG protocol could not be set\n", __func__);
107 err = gpgme_ctx_set_engine_info (gpg_context,
108 GPGME_PROTOCOL_OpenPGP,
109 enginfo->file_name, keyring_path);
111 err = gpgme_ctx_set_engine_info (gpg_context,
112 GPGME_PROTOCOL_OpenPGP,
113 enginfo->file_name, enginfo->home_dir);
114 if (err != GPG_ERR_NO_ERROR) {
115 pb_log("%s: Could not set GPG engine information\n", __func__);
118 err = gpgme_data_new(&plaintext_data);
119 if (err != GPG_ERR_NO_ERROR) {
120 pb_log("%s: Could not create GPG plaintext data buffer\n",
124 err = gpgme_data_new_from_file(&ciphertext_data, filename, 1);
125 if (err != GPG_ERR_NO_ERROR) {
126 pb_log("%s: Could not create GPG ciphertext data buffer"
127 " from file '%s'\n", __func__, filename);
131 /* Decrypt and verify file */
132 err = gpgme_op_decrypt_verify(gpg_context, ciphertext_data,
134 if (err != GPG_ERR_NO_ERROR) {
135 pb_log("%s: Could not decrypt file\n", __func__);
138 verification_result = gpgme_op_verify_result(gpg_context);
139 verification_signatures = verification_result->signatures;
140 while (verification_signatures) {
141 if (verification_signatures->status == GPG_ERR_NO_ERROR) {
142 pb_log("%s: Good signature for key ID '%s' ('%s')\n",
144 verification_signatures->fpr, filename);
145 /* Verify fingerprint is present in authorized
148 char *auth_sig_line = NULL;
149 size_t auth_sig_len = 0;
150 ssize_t auth_sig_read;
151 rewind(authorized_signatures_handle);
152 while ((auth_sig_read = getline(&auth_sig_line,
154 authorized_signatures_handle)) != -1) {
155 auth_sig_len = strlen(auth_sig_line);
156 while ((auth_sig_line[auth_sig_len-1] == '\n')
157 || (auth_sig_line[auth_sig_len-1] == '\r'))
159 auth_sig_line[auth_sig_len] = 0;
160 if (strcmp(auth_sig_line,
161 verification_signatures->fpr) == 0)
167 pb_log("%s: Signature for key ID '%s' ('%s') invalid."
168 " Status: %08x\n", __func__,
169 verification_signatures->fpr, filename,
170 verification_signatures->status);
172 verification_signatures = verification_signatures->next;
175 gpgme_data_release(ciphertext_data);
178 /* Write decrypted file over ciphertext */
179 FILE *plaintext_file_handle = NULL;
180 plaintext_file_handle = fopen(filename, "wb");
181 if (!plaintext_file_handle) {
182 pb_log("%s: Could not create GPG plaintext file '%s'\n",
184 gpgme_data_release(plaintext_data);
185 gpgme_release(gpg_context);
188 gpgme_data_seek(plaintext_data, 0, SEEK_SET);
189 if (err != GPG_ERR_NO_ERROR) {
190 pb_log("%s: Could not seek in GPG plaintext buffer\n",
192 gpgme_data_release(plaintext_data);
193 gpgme_release(gpg_context);
194 fclose(plaintext_file_handle);
197 while ((bytes_read = gpgme_data_read(plaintext_data, buffer,
199 size_t l2 = fwrite(buffer, 1, bytes_read,
200 plaintext_file_handle);
201 if (l2 < bytes_read) {
202 if (ferror(plaintext_file_handle)) {
205 pb_log("%s: failed: unknown fault\n",
209 /* No space on destination device */
211 pb_log("%s: failed: temporary storage"
212 " full\n", __func__);
217 fclose(plaintext_file_handle);
221 gpgme_data_release(plaintext_data);
222 gpgme_release(gpg_context);
225 pb_log("%s: Incorrect GPG signature\n", __func__);
229 pb_log("%s: GPG signature for decrypted file '%s' verified\n",
235 int verify_file_signature(const char *plaintext_filename,
236 const char *signature_filename, FILE *authorized_signatures_handle,
237 const char *keyring_path)
240 gpgme_signature_t verification_signatures;
241 gpgme_verify_result_t verification_result;
242 gpgme_data_t plaintext_data;
243 gpgme_data_t signature_data;
244 gpgme_engine_info_t enginfo;
245 gpgme_ctx_t gpg_context;
248 if (signature_filename == NULL)
251 /* Initialize gpgme */
252 setlocale (LC_ALL, "");
253 gpgme_check_version(NULL);
254 gpgme_set_locale(NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
255 err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
256 if (err != GPG_ERR_NO_ERROR) {
257 pb_log("%s: OpenPGP support not available\n", __func__);
260 err = gpgme_get_engine_info(&enginfo);
261 if (err != GPG_ERR_NO_ERROR) {
262 pb_log("%s: GPG engine failed to initialize\n", __func__);
265 err = gpgme_new(&gpg_context);
266 if (err != GPG_ERR_NO_ERROR) {
267 pb_log("%s: GPG context could not be created\n", __func__);
270 err = gpgme_set_protocol(gpg_context, GPGME_PROTOCOL_OpenPGP);
271 if (err != GPG_ERR_NO_ERROR) {
272 pb_log("%s: GPG protocol could not be set\n", __func__);
276 err = gpgme_ctx_set_engine_info (gpg_context,
277 GPGME_PROTOCOL_OpenPGP, enginfo->file_name,
280 err = gpgme_ctx_set_engine_info (gpg_context,
281 GPGME_PROTOCOL_OpenPGP, enginfo->file_name,
283 if (err != GPG_ERR_NO_ERROR) {
284 pb_log("%s: Could not set GPG engine information\n", __func__);
287 err = gpgme_data_new_from_file(&plaintext_data, plaintext_filename, 1);
288 if (err != GPG_ERR_NO_ERROR) {
289 pb_log("%s: Could not create GPG plaintext data buffer"
290 " from file '%s'\n", __func__, plaintext_filename);
293 err = gpgme_data_new_from_file(&signature_data, signature_filename, 1);
294 if (err != GPG_ERR_NO_ERROR) {
295 pb_log("%s: Could not create GPG signature data buffer"
296 " from file '%s'\n", __func__, signature_filename);
300 /* Check signature */
301 err = gpgme_op_verify(gpg_context, signature_data, plaintext_data,
303 if (err != GPG_ERR_NO_ERROR) {
304 pb_log("%s: Could not verify file using GPG signature '%s'\n",
305 __func__, signature_filename);
308 verification_result = gpgme_op_verify_result(gpg_context);
309 verification_signatures = verification_result->signatures;
310 while (verification_signatures) {
311 if (verification_signatures->status != GPG_ERR_NO_ERROR) {
312 /* Signature verification failure */
313 pb_log("%s: Signature for key ID '%s' ('%s') invalid."
314 " Status: %08x\n", __func__,
315 verification_signatures->fpr,
317 verification_signatures->status);
318 verification_signatures = verification_signatures->next;
322 /* Signature check passed with no error */
323 pb_log("%s: Good signature for key ID '%s' ('%s')\n",
324 __func__, verification_signatures->fpr,
326 /* Verify fingerprint is present in
327 * authorized signatures file
329 char *auth_sig_line = NULL;
330 size_t auth_sig_len = 0;
331 ssize_t auth_sig_read;
332 rewind(authorized_signatures_handle);
333 while ((auth_sig_read = getline(&auth_sig_line,
335 authorized_signatures_handle)) != -1) {
336 auth_sig_len = strlen(auth_sig_line);
337 while ((auth_sig_line[auth_sig_len-1] == '\n')
338 || (auth_sig_line[auth_sig_len-1] == '\r'))
340 auth_sig_line[auth_sig_len] = '\0';
341 if (strcmp(auth_sig_line,
342 verification_signatures->fpr) == 0)
346 verification_signatures = verification_signatures->next;
350 gpgme_data_release(plaintext_data);
351 gpgme_data_release(signature_data);
352 gpgme_release(gpg_context);
355 pb_log("%s: Incorrect GPG signature\n", __func__);
359 pb_log("%s: GPG signature '%s' for file '%s' verified\n",
360 __func__, signature_filename, plaintext_filename);
365 int gpg_validate_boot_files(struct boot_task *boot_task) {
367 char *kernel_filename = NULL;
368 char *initrd_filename = NULL;
369 char *dtb_filename = NULL;
371 FILE *authorized_signatures_handle = NULL;
373 char cmdline_template[] = "/tmp/petitbootXXXXXX";
374 int cmdline_fd = mkstemp(cmdline_template);
375 FILE *cmdline_handle = NULL;
377 const char* local_initrd_signature = (boot_task->verify_signature) ?
378 boot_task->local_initrd_signature : NULL;
379 const char* local_dtb_signature = (boot_task->verify_signature) ?
380 boot_task->local_dtb_signature : NULL;
381 const char* local_image_signature = (boot_task->verify_signature) ?
382 boot_task->local_image_signature : NULL;
383 const char* local_cmdline_signature =
384 (boot_task->verify_signature || boot_task->decrypt_files) ?
385 boot_task->local_cmdline_signature : NULL;
387 if ((!boot_task->verify_signature) && (!boot_task->decrypt_files))
390 /* Load authorized signatures file */
391 authorized_signatures_handle = fopen(LOCKDOWN_FILE, "r");
392 if (!authorized_signatures_handle) {
393 pb_log("%s: unable to read lockdown file\n", __func__);
394 return KEXEC_LOAD_SIG_SETUP_INVALID;
397 /* Copy files to temporary directory for verification / boot */
398 result = copy_file_secure_dest(boot_task,
399 boot_task->local_image,
402 pb_log("%s: image copy failed: (%d)\n",
406 if (boot_task->local_initrd) {
407 result = copy_file_secure_dest(boot_task,
408 boot_task->local_initrd,
411 pb_log("%s: initrd copy failed: (%d)\n",
416 if (boot_task->local_dtb) {
417 result = copy_file_secure_dest(boot_task,
418 boot_task->local_dtb,
421 pb_log("%s: dtb copy failed: (%d)\n",
426 boot_task->local_image_override = talloc_strdup(boot_task,
428 if (boot_task->local_initrd)
429 boot_task->local_initrd_override = talloc_strdup(boot_task,
431 if (boot_task->local_dtb)
432 boot_task->local_dtb_override = talloc_strdup(boot_task,
435 /* Write command line to temporary file for verification */
436 if (cmdline_fd < 0) {
438 pb_log("%s: failed: unable to create command line"
439 " temporary file for verification\n",
444 cmdline_handle = fdopen(cmdline_fd, "w");
446 if (!cmdline_handle) {
447 /* Failed to open file */
448 pb_log("%s: failed: unable to write command line"
449 " temporary file for verification\n",
454 fwrite(boot_task->args, sizeof(char),
455 strlen(boot_task->args), cmdline_handle);
456 fflush(cmdline_handle);
459 if (boot_task->verify_signature) {
460 /* Check signatures */
461 if (verify_file_signature(kernel_filename,
462 local_image_signature,
463 authorized_signatures_handle,
465 result = KEXEC_LOAD_SIGNATURE_FAILURE;
466 if (verify_file_signature(cmdline_template,
467 local_cmdline_signature,
468 authorized_signatures_handle,
470 result = KEXEC_LOAD_SIGNATURE_FAILURE;
472 if (boot_task->local_initrd_signature)
473 if (verify_file_signature(initrd_filename,
474 local_initrd_signature,
475 authorized_signatures_handle,
477 result = KEXEC_LOAD_SIGNATURE_FAILURE;
478 if (boot_task->local_dtb_signature)
479 if (verify_file_signature(dtb_filename,
481 authorized_signatures_handle,
483 result = KEXEC_LOAD_SIGNATURE_FAILURE;
486 if (cmdline_handle) {
487 fclose(cmdline_handle);
488 unlink(cmdline_template);
490 fclose(authorized_signatures_handle);
491 } else if (boot_task->decrypt_files) {
493 if (decrypt_file(kernel_filename,
494 authorized_signatures_handle,
496 result = KEXEC_LOAD_DECRYPTION_FALURE;
497 if (verify_file_signature(cmdline_template,
498 local_cmdline_signature,
499 authorized_signatures_handle,
501 result = KEXEC_LOAD_SIGNATURE_FAILURE;
502 if (boot_task->local_initrd)
503 if (decrypt_file(initrd_filename,
504 authorized_signatures_handle,
506 result = KEXEC_LOAD_DECRYPTION_FALURE;
507 if (boot_task->local_dtb)
508 if (decrypt_file(dtb_filename,
509 authorized_signatures_handle,
511 result = KEXEC_LOAD_DECRYPTION_FALURE;
514 if (cmdline_handle) {
515 fclose(cmdline_handle);
516 unlink(cmdline_template);
518 fclose(authorized_signatures_handle);
524 void gpg_validate_boot_files_cleanup(struct boot_task *boot_task) {
525 if ((boot_task->verify_signature) || (boot_task->decrypt_files)) {
526 unlink(boot_task->local_image_override);
527 if (boot_task->local_initrd_override)
528 unlink(boot_task->local_initrd_override);
529 if (boot_task->local_dtb_override)
530 unlink(boot_task->local_dtb_override);
532 talloc_free(boot_task->local_image_override);
533 if (boot_task->local_initrd_override)
534 talloc_free(boot_task->local_initrd_override);
535 if (boot_task->local_dtb_override)
536 talloc_free(boot_task->local_dtb_override);
540 int lockdown_status() {
541 /* assume most restrictive lockdown type */
542 int ret = PB_LOCKDOWN_SIGN;
544 if (access(LOCKDOWN_FILE, F_OK) == -1)
545 return PB_LOCKDOWN_NONE;
547 /* determine lockdown type */
548 FILE *authorized_signatures_handle = NULL;
549 authorized_signatures_handle = fopen(LOCKDOWN_FILE, "r");
550 if (!authorized_signatures_handle)
553 char *auth_sig_line = NULL;
554 size_t auth_sig_len = 0;
555 ssize_t auth_sig_read;
556 rewind(authorized_signatures_handle);
557 if ((auth_sig_read = getline(&auth_sig_line,
559 authorized_signatures_handle)) != -1) {
560 auth_sig_len = strlen(auth_sig_line);
561 while ((auth_sig_line[auth_sig_len-1] == '\n')
562 || (auth_sig_line[auth_sig_len-1] == '\r'))
564 auth_sig_line[auth_sig_len] = 0;
565 if (strcmp(auth_sig_line, "ENCRYPTED") == 0) {
566 /* first line indicates encrypted files
567 * expected. enable decryption.
569 ret = PB_LOCKDOWN_DECRYPT;