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

Reply via email to