From: Stefan Berger <stef...@us.ibm.com> Add a script for loading the EVM (extended verification module) key. Either a symmetric key or an x.509 certificate can be loaded using the scripts.
A config file /etc/default/evm allows to configure parameters of the key. Signed-off-by: Stefan Berger <stef...@linux.vnet.ibm.com> --- hooks/evm | 20 ++++++ scripts/init-top/evm | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100755 hooks/evm create mode 100755 scripts/init-top/evm diff --git a/hooks/evm b/hooks/evm new file mode 100755 index 0000000..0961bab --- /dev/null +++ b/hooks/evm @@ -0,0 +1,20 @@ +#!/bin/sh + +PREREQ="masterkey" + +prereqs() +{ + echo "$PREREQ" +} + +case $1 in +prereqs) + prereqs + exit 0 + ;; +esac + +. /usr/share/initramfs-tools/hook-functions +copy_exec /bin/findmnt +copy_exec /bin/keyctl +copy_exec /usr/bin/evmctl diff --git a/scripts/init-top/evm b/scripts/init-top/evm new file mode 100755 index 0000000..236139b --- /dev/null +++ b/scripts/init-top/evm @@ -0,0 +1,176 @@ +#!/bin/sh + +# Licensed under the GPLv2 +# +# Copyright (C) 2011 Politecnico di Torino, Italy +# TORSEC group -- http://security.polito.it +# Roberto Sassu <roberto.sa...@polito.it> +# +# +# (c) Copyright IBM Corporation 2016,2017 +# +# Stefan Berger <stef...@linux.vnet.ibm.com> +# +# This file has been derived from Dracut's 98integrity/evm-enable.sh +# + +PREREQ="masterkey" + +prereqs() +{ + echo "$PREREQ" +} + +case $1 in +# get pre-requisites +prereqs) + prereqs + exit 0 + ;; +esac + +. /scripts/functions + +SECURITYFSDIR=`findmnt -t securityfs -n -o TARGET` +if [ ! $SECURITYFSDIR ]; then + SECURITYFSDIR="/sys/kernel/security" + mount -t securityfs -o nosuid,noexec,nodev securityfs ${SECURITYFSDIR} >/dev/null 2>&1 +fi + +NEWROOT="${rootmnt}" +EVMSECFILE="${SECURITYFSDIR}/evm" +EVMCONFIG="${NEWROOT}/etc/default/evm" +EVMKEYDESC="evm-key" +EVMKEYTYPE="encrypted" +EVMKEYID="" + +getarg() +{ + att=$1 + + sed -n 's/.*'${att}'\([^ ]\+\).*/\1/p' /proc/cmdline +} + +load_evm_key() +{ + # read the configuration from the config file + [ -f "${EVMCONFIG}" ] && \ + . ${EVMCONFIG} + + # override the EVM key path name from the 'evmkey=' parameter in the kernel + # command line + EVMKEYARG=$(getarg evmkey=) + [ -n "${EVMKEYARG}" ] && \ + EVMKEY=${EVMKEYARG} + + # set the default value + [ -z "${EVMKEY}" ] && \ + EVMKEY="/etc/keys/evm-trusted.blob"; + + # set the EVM key path name + EVMKEYPATH="${NEWROOT}${EVMKEY}" + + # check for EVM encrypted key's existence + if [ ! -f "${EVMKEYPATH}" ]; then + [ "$quiet" != "y" ] && _log_msg "integrity: EVM encrypted key file not found: ${EVMKEYPATH}\n" + return 1 + fi + + # read the EVM encrypted key blob + KEYBLOB=$(cat ${EVMKEYPATH}) + + # load the EVM encrypted key + EVMKEYID=$(keyctl add ${EVMKEYTYPE} ${EVMKEYDESC} "load ${KEYBLOB}" @u) + [ $? -eq 0 ] || { + _log_msg "integrity: failed to load the EVM encrypted key: ${EVMKEYDESC}\n"; + return 1; + } + + _log_msg "integrity: Loaded EVM key ${EVMKEYPATH}\n" + + return 0 +} + +load_evm_x509() +{ + [ "$quiet" != "y" ] && _log_msg "integrity: Load EVM IMA X509\n" + + # override the EVM key path name from the 'evmx509=' parameter in + # the kernel command line + EVMX509ARG=$(getarg evmx509=) + [ -n "${EVMX509ARG}" ] && \ + EVMX509=${EVMX509ARG} + + # set the default value + [ -z "${EVMX509}" ] && \ + EVMX509="/etc/keys/x509_evm.der"; + + # set the EVM public key path name + EVMX509PATH="${NEWROOT}${EVMX509}" + + # check for EVM public key's existence + if [ ! -f "${EVMX509PATH}" ]; then + [ "$quiet" != "y" ] && _log_msg "integrity: EVM x509 cert file not found: ${EVMX509PATH}\n" + return 1 + fi + + # load the EVM public key onto the EVM keyring + line="$(sed -n 's/\([^ ]\+\).*keyring\s\+\.evm:.*/\1/p' /proc/keys)" + if [ -n "$line" ]; then + evm_pubid=$(printf "%d" "0x$line") + else + evm_pubid=`keyctl search $u keyring _evm` + if [ -z "${evm_pubid}" ]; then + evm_pubid=`keyctl newring _evm @u` + fi + fi + EVMX509ID=$(evmctl import ${EVMX509PATH} ${evm_pubid} 2>/dev/null) + if [ $? -ne 0 ]; then + [ "$quiet" != "y" ] && _log_msg "integrity: failed to load the EVM X509 cert ${EVMX509PATH}\n" + return 1 + fi + + _log_msg "integrity: Loaded EVM x509 cert ${EVMX509PATH}\n" + + [ "$quiet" != "y" ] && keyctl show @u + + return 0 +} + +unload_evm_key() +{ + # unlink the EVM encrypted key + keyctl unlink ${EVMKEYID} @u || { + _log_msg "integrity: failed to unlink the EVM encrypted key: ${EVMKEYDESC}\n"; + return 1; + } + + return 0 +} + +enable_evm() +{ + # check kernel support for EVM + if [ ! -e "${EVMSECFILE}" ]; then + [ "$quiet" != "y" ] && _log_msg "integrity: EVM kernel support is disabled\n" + return 0 + fi + + # load the EVM encrypted key + load_evm_key || return 1 + + # load the EVM public key, if it exists + load_evm_x509 + + # initialize EVM + echo 1 > ${EVMSECFILE} + [ $? -ne 0 ] && _log_msg "integrity: Could not enable EVM\n" \ + || _log_msg "integrity: Enabled EVM\n" + + # unload the EVM encrypted key + unload_evm_key || return 1 + + return 0 +} + +enable_evm -- 2.8.3