diff options
author | Jason Wessel <jason.wessel@windriver.com> | 2019-10-23 07:29:44 -0700 |
---|---|---|
committer | Jia Zhang <zhang.jia@linux.alibaba.com> | 2019-11-08 13:27:23 +0800 |
commit | 4a7afb4477449178d853272ba1a6040c20043b71 (patch) | |
tree | fa6d813693993448c0333d276b5dbb7a5e22eb42 | |
parent | 363c7a606ad234a08f3e7c489518b0abf18f356a (diff) | |
download | meta-secure-core-4a7afb4477449178d853272ba1a6040c20043b71.tar.gz |
sign_rpm_ext.bbclass, user-key-store.bbclass: Add boot loader signing
This changes the rpm signing setup to use a generic routine
check_gpg_key(), in order that the boot loader gpg signing can use the
same infrastructure.
For now the boot loader gpg signing will only support grub and
introduces the variable:
GRUB_SIGN_VERIFY = "1"
This variable is a control point to activate the code in grub-efi to
perform file verification of any file it loads against a gpg key which
is linked into the boot loader with grub-mkimage. It will also cause
all the other files such as the kernel, initramfs and LockDown.efi to
be signed such that grub will verify the files.
[ Issue: LINUXEXEC-2450 ]
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
-rw-r--r-- | meta-integrity/classes/sign_rpm_ext.bbclass | 30 | ||||
-rw-r--r-- | meta-signing-key/classes/user-key-store.bbclass | 63 |
2 files changed, 69 insertions, 24 deletions
diff --git a/meta-integrity/classes/sign_rpm_ext.bbclass b/meta-integrity/classes/sign_rpm_ext.bbclass index d9a7f34..1d72d15 100644 --- a/meta-integrity/classes/sign_rpm_ext.bbclass +++ b/meta-integrity/classes/sign_rpm_ext.bbclass | |||
@@ -13,27 +13,13 @@ inherit sign_rpm user-key-store | |||
13 | GPG_DEP = "${@'' if d.getVar('GPG_BIN') else 'gnupg-native:do_populate_sysroot pinentry-native:do_populate_sysroot'}" | 13 | GPG_DEP = "${@'' if d.getVar('GPG_BIN') else 'gnupg-native:do_populate_sysroot pinentry-native:do_populate_sysroot'}" |
14 | 14 | ||
15 | python check_rpm_public_key () { | 15 | python check_rpm_public_key () { |
16 | gpg_path = d.getVar('GPG_PATH', True) | 16 | check_gpg_key('RPM', uks_rpm_keys_dir, d) |
17 | gpg_bin = d.getVar('GPG_BIN', True) or \ | ||
18 | bb.utils.which(os.getenv('PATH'), 'gpg') | ||
19 | gpg_keyid = d.getVar('RPM_GPG_NAME', True) | ||
20 | |||
21 | # Check RPM_GPG_NAME and RPM_GPG_PASSPHRASE | ||
22 | cmd = "%s --homedir %s --list-keys %s" % \ | ||
23 | (gpg_bin, gpg_path, gpg_keyid) | ||
24 | status, output = oe.utils.getstatusoutput(cmd) | ||
25 | if not status: | ||
26 | return | ||
27 | |||
28 | # Import RPM_GPG_NAME if not found | ||
29 | gpg_key = uks_rpm_keys_dir(d) + 'RPM-GPG-PRIVKEY-' + gpg_keyid | ||
30 | cmd = '%s --batch --homedir %s --passphrase %s --import %s' % \ | ||
31 | (gpg_bin, gpg_path, d.getVar('RPM_GPG_PASSPHRASE', True), gpg_key) | ||
32 | status, output = oe.utils.getstatusoutput(cmd) | ||
33 | if status: | ||
34 | bb.fatal('Failed to import gpg key (%s): %s' % (gpg_key, output)) | ||
35 | } | 17 | } |
36 | check_rpm_public_key[lockfiles] = "${TMPDIR}/check_rpm_public_key.lock" | 18 | |
19 | check_rpm_public_key[lockfiles] = "${TMPDIR}/gpg_key.lock" | ||
20 | do_package_write_rpm[prefuncs] += "check_rpm_public_key" | ||
21 | do_rootfs[prefuncs] += "check_rpm_public_key" | ||
22 | |||
37 | check_rpm_public_key[prefuncs] += "check_deploy_keys" | 23 | check_rpm_public_key[prefuncs] += "check_deploy_keys" |
38 | do_package_write_rpm[depends] += "${GPG_DEP}" | 24 | do_package_write_rpm[depends] += "${GPG_DEP}" |
39 | do_rootfs[depends] += "${GPG_DEP}" | 25 | do_rootfs[depends] += "${GPG_DEP}" |
@@ -52,8 +38,4 @@ python () { | |||
52 | gpg_path = d.getVar('TMPDIR', True) + '/.gnupg' | 38 | gpg_path = d.getVar('TMPDIR', True) + '/.gnupg' |
53 | d.setVar('GPG_PATH', gpg_path) | 39 | d.setVar('GPG_PATH', gpg_path) |
54 | 40 | ||
55 | if not os.path.exists(gpg_path): | ||
56 | status, output = oe.utils.getstatusoutput('mkdir -m 0700 -p %s' % gpg_path) | ||
57 | if status: | ||
58 | bb.fatal('Failed to create gpg keying %s: %s' % (gpg_path, output)) | ||
59 | } | 41 | } |
diff --git a/meta-signing-key/classes/user-key-store.bbclass b/meta-signing-key/classes/user-key-store.bbclass index 88d7290..7abe1cf 100644 --- a/meta-signing-key/classes/user-key-store.bbclass +++ b/meta-signing-key/classes/user-key-store.bbclass | |||
@@ -42,6 +42,10 @@ def uks_rpm_keys_dir(d): | |||
42 | set_keys_dir('RPM', d) | 42 | set_keys_dir('RPM', d) |
43 | return d.getVar('RPM_KEYS_DIR', True) + '/' | 43 | return d.getVar('RPM_KEYS_DIR', True) + '/' |
44 | 44 | ||
45 | def uks_boot_keys_dir(d): | ||
46 | set_keys_dir('BOOT', d) | ||
47 | return d.getVar('BOOT_KEYS_DIR', True) + '/' | ||
48 | |||
45 | def sign_efi_image(key, cert, input, output, d): | 49 | def sign_efi_image(key, cert, input, output, d): |
46 | import bb.process | 50 | import bb.process |
47 | 51 | ||
@@ -460,3 +464,62 @@ python check_deploy_keys() { | |||
460 | } | 464 | } |
461 | 465 | ||
462 | check_deploy_keys[lockfiles] = "${TMPDIR}/check_deploy_keys.lock" | 466 | check_deploy_keys[lockfiles] = "${TMPDIR}/check_deploy_keys.lock" |
467 | |||
468 | def check_gpg_key(basekeyname, keydirfunc, d): | ||
469 | gpg_path = d.getVar('GPG_PATH', True) | ||
470 | if not gpg_path: | ||
471 | gpg_path = d.getVar('TMPDIR', True) + '/.gnupg' | ||
472 | d.setVar('GPG_PATH', gpg_path) | ||
473 | if not os.path.exists(gpg_path): | ||
474 | status, output = oe.utils.getstatusoutput('mkdir -m 0700 -p %s' % gpg_path) | ||
475 | if status: | ||
476 | bb.fatal('Failed to create gpg keying %s: %s' % (gpg_path, output)) | ||
477 | f = open(os.path.join(gpg_path, 'gpg-agent.conf'), 'w') | ||
478 | f.write('allow-loopback-pinentry\n') | ||
479 | f.write('auto-expand-secmem\n') | ||
480 | f.close() | ||
481 | gpg_bin = d.getVar('GPG_BIN', True) or \ | ||
482 | bb.utils.which(os.getenv('PATH'), 'gpg') | ||
483 | gpg_keyid = d.getVar(basekeyname + '_GPG_NAME', True) | ||
484 | |||
485 | # Check for keyid | ||
486 | cmd = "%s --homedir %s --list-keys %s" % \ | ||
487 | (gpg_bin, gpg_path, gpg_keyid) | ||
488 | status, output = oe.utils.getstatusoutput(cmd) | ||
489 | if not status: | ||
490 | return | ||
491 | |||
492 | # Import gpg key if not found | ||
493 | gpg_key = keydirfunc(d) + basekeyname + '-GPG-PRIVKEY-' + gpg_keyid | ||
494 | cmd = '%s --batch --homedir %s --passphrase %s --import %s' % \ | ||
495 | (gpg_bin, gpg_path, d.getVar(basekeyname + '_GPG_PASSPHRASE', True), gpg_key) | ||
496 | status, output = oe.utils.getstatusoutput(cmd) | ||
497 | if status: | ||
498 | bb.fatal('Failed to import gpg key (%s): %s' % (gpg_key, output)) | ||
499 | |||
500 | python check_boot_public_key () { | ||
501 | check_gpg_key('BOOT', uks_boot_keys_dir, d) | ||
502 | } | ||
503 | |||
504 | check_boot_public_key[lockfiles] = "${TMPDIR}/gpg_key.lock" | ||
505 | |||
506 | def boot_sign(input, d): | ||
507 | import bb.process | ||
508 | |||
509 | gpg_path = d.getVar('GPG_PATH', True) | ||
510 | gpg_keyid = d.getVar('BOOT_GPG_NAME', True) | ||
511 | gpg_pass = d.getVar('BOOT_GPG_PASSPHRASE', True) | ||
512 | gpg_bin = d.getVar('GPG_BIN', True) or \ | ||
513 | bb.utils.which(os.getenv('PATH'), 'gpg') | ||
514 | if os.path.exists(input + '.sig'): | ||
515 | os.unlink(input + '.sig') | ||
516 | cmd = 'echo "%s" | %s --pinentry-mode loopback --batch --homedir %s -u "%s" --detach-sign --passphrase-fd 0 "%s"' % \ | ||
517 | (gpg_pass, gpg_bin, gpg_path, gpg_keyid, input) | ||
518 | vprint("Running: %s" % cmd, d) | ||
519 | status, output = oe.utils.getstatusoutput(cmd) | ||
520 | if status: | ||
521 | bb.fatal('Failed to sign: %s' % (input)) | ||
522 | |||
523 | def uks_boot_sign(input, d): | ||
524 | if d.getVar('GRUB_SIGN_VERIFY', True) == '1': | ||
525 | boot_sign(input, d) | ||