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) | ||
