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>
This commit is contained in:
Jason Wessel
2019-10-23 07:29:44 -07:00
committed by Jia Zhang
parent 363c7a606a
commit 4a7afb4477
2 changed files with 69 additions and 24 deletions
+6 -24
View File
@@ -13,27 +13,13 @@ inherit sign_rpm user-key-store
GPG_DEP = "${@'' if d.getVar('GPG_BIN') else 'gnupg-native:do_populate_sysroot pinentry-native:do_populate_sysroot'}"
python check_rpm_public_key () {
gpg_path = d.getVar('GPG_PATH', True)
gpg_bin = d.getVar('GPG_BIN', True) or \
bb.utils.which(os.getenv('PATH'), 'gpg')
gpg_keyid = d.getVar('RPM_GPG_NAME', True)
# Check RPM_GPG_NAME and RPM_GPG_PASSPHRASE
cmd = "%s --homedir %s --list-keys %s" % \
(gpg_bin, gpg_path, gpg_keyid)
status, output = oe.utils.getstatusoutput(cmd)
if not status:
return
# Import RPM_GPG_NAME if not found
gpg_key = uks_rpm_keys_dir(d) + 'RPM-GPG-PRIVKEY-' + gpg_keyid
cmd = '%s --batch --homedir %s --passphrase %s --import %s' % \
(gpg_bin, gpg_path, d.getVar('RPM_GPG_PASSPHRASE', True), gpg_key)
status, output = oe.utils.getstatusoutput(cmd)
if status:
bb.fatal('Failed to import gpg key (%s): %s' % (gpg_key, output))
check_gpg_key('RPM', uks_rpm_keys_dir, d)
}
check_rpm_public_key[lockfiles] = "${TMPDIR}/check_rpm_public_key.lock"
check_rpm_public_key[lockfiles] = "${TMPDIR}/gpg_key.lock"
do_package_write_rpm[prefuncs] += "check_rpm_public_key"
do_rootfs[prefuncs] += "check_rpm_public_key"
check_rpm_public_key[prefuncs] += "check_deploy_keys"
do_package_write_rpm[depends] += "${GPG_DEP}"
do_rootfs[depends] += "${GPG_DEP}"
@@ -52,8 +38,4 @@ python () {
gpg_path = d.getVar('TMPDIR', True) + '/.gnupg'
d.setVar('GPG_PATH', gpg_path)
if not os.path.exists(gpg_path):
status, output = oe.utils.getstatusoutput('mkdir -m 0700 -p %s' % gpg_path)
if status:
bb.fatal('Failed to create gpg keying %s: %s' % (gpg_path, output))
}
@@ -42,6 +42,10 @@ def uks_rpm_keys_dir(d):
set_keys_dir('RPM', d)
return d.getVar('RPM_KEYS_DIR', True) + '/'
def uks_boot_keys_dir(d):
set_keys_dir('BOOT', d)
return d.getVar('BOOT_KEYS_DIR', True) + '/'
def sign_efi_image(key, cert, input, output, d):
import bb.process
@@ -460,3 +464,62 @@ python check_deploy_keys() {
}
check_deploy_keys[lockfiles] = "${TMPDIR}/check_deploy_keys.lock"
def check_gpg_key(basekeyname, keydirfunc, d):
gpg_path = d.getVar('GPG_PATH', True)
if not gpg_path:
gpg_path = d.getVar('TMPDIR', True) + '/.gnupg'
d.setVar('GPG_PATH', gpg_path)
if not os.path.exists(gpg_path):
status, output = oe.utils.getstatusoutput('mkdir -m 0700 -p %s' % gpg_path)
if status:
bb.fatal('Failed to create gpg keying %s: %s' % (gpg_path, output))
f = open(os.path.join(gpg_path, 'gpg-agent.conf'), 'w')
f.write('allow-loopback-pinentry\n')
f.write('auto-expand-secmem\n')
f.close()
gpg_bin = d.getVar('GPG_BIN', True) or \
bb.utils.which(os.getenv('PATH'), 'gpg')
gpg_keyid = d.getVar(basekeyname + '_GPG_NAME', True)
# Check for keyid
cmd = "%s --homedir %s --list-keys %s" % \
(gpg_bin, gpg_path, gpg_keyid)
status, output = oe.utils.getstatusoutput(cmd)
if not status:
return
# Import gpg key if not found
gpg_key = keydirfunc(d) + basekeyname + '-GPG-PRIVKEY-' + gpg_keyid
cmd = '%s --batch --homedir %s --passphrase %s --import %s' % \
(gpg_bin, gpg_path, d.getVar(basekeyname + '_GPG_PASSPHRASE', True), gpg_key)
status, output = oe.utils.getstatusoutput(cmd)
if status:
bb.fatal('Failed to import gpg key (%s): %s' % (gpg_key, output))
python check_boot_public_key () {
check_gpg_key('BOOT', uks_boot_keys_dir, d)
}
check_boot_public_key[lockfiles] = "${TMPDIR}/gpg_key.lock"
def boot_sign(input, d):
import bb.process
gpg_path = d.getVar('GPG_PATH', True)
gpg_keyid = d.getVar('BOOT_GPG_NAME', True)
gpg_pass = d.getVar('BOOT_GPG_PASSPHRASE', True)
gpg_bin = d.getVar('GPG_BIN', True) or \
bb.utils.which(os.getenv('PATH'), 'gpg')
if os.path.exists(input + '.sig'):
os.unlink(input + '.sig')
cmd = 'echo "%s" | %s --pinentry-mode loopback --batch --homedir %s -u "%s" --detach-sign --passphrase-fd 0 "%s"' % \
(gpg_pass, gpg_bin, gpg_path, gpg_keyid, input)
vprint("Running: %s" % cmd, d)
status, output = oe.utils.getstatusoutput(cmd)
if status:
bb.fatal('Failed to sign: %s' % (input))
def uks_boot_sign(input, d):
if d.getVar('GRUB_SIGN_VERIFY', True) == '1':
boot_sign(input, d)