summaryrefslogtreecommitdiffstats
path: root/modules.d/98integrity
diff options
context:
space:
mode:
Diffstat (limited to 'modules.d/98integrity')
-rw-r--r--modules.d/98integrity/README68
-rwxr-xr-xmodules.d/98integrity/evm-enable.sh169
-rwxr-xr-xmodules.d/98integrity/ima-keys-load.sh60
-rwxr-xr-xmodules.d/98integrity/ima-policy-load.sh40
-rwxr-xr-xmodules.d/98integrity/module-setup.sh20
5 files changed, 357 insertions, 0 deletions
diff --git a/modules.d/98integrity/README b/modules.d/98integrity/README
new file mode 100644
index 0000000..b16c6b6
--- /dev/null
+++ b/modules.d/98integrity/README
@@ -0,0 +1,68 @@
+# Directions for creating the encrypted key that will be used to initialize
+# the EVM software.
+
+# Create the EVM key (encrypted key type)
+#
+# The encrypted key is a random number encrypted/decrypted using the
+# kernel master key. The encrypted key is only exposed to userspace
+# as an encrypted datablob.
+$ keyctl add encrypted evm-key "new trusted:kmk-trusted 32" @u
+782117972
+
+# Save the encrypted key
+$ su -c 'keyctl pipe `keyctl search @u encrypted evm-key` > /etc/keys/evm-trusted.blob'
+
+# The EVM key path name can be set in one of the following ways (specified in
+# the order in which the variable is overwritten):
+
+1) use the default value:
+--------------------------------------------------------------------------
+EVMKEY="/etc/keys/evm-trusted.blob"
+--------------------------------------------------------------------------
+
+2) create the configuration file '/etc/sysconfig/evm' and set the EVMKEY variable;
+
+3) specify the EVM key path name in the 'evmkey=' parameter of the kernel command
+line.
+
+
+# Directions for loading a custom IMA policy.
+
+# Write the policy following the instructions provided in the file
+# 'Documentation/ABI/testing/ima_policy' of the kernel documentation.
+
+# Save the policy in a file.
+
+# Create the configuration file '/etc/sysconfig/ima' to override the path name of
+# the IMA custom policy.
+------------- '/etc/sysconfig/ima' (with the default value) -------------
+IMAPOLICY="/etc/sysconfig/ima-policy"
+-------------------------------------------------------------------------
+
+
+# Information on loading distro, third party or local keys on the trusted IMA keyring
+
+# Loading distro, third party or local keys on the trusted IMA keyring requires
+# creating a local certificate authority(local-CA), installing the local-CA's
+# public key on the system-keyring and signing the certificates with the local-CA
+# key.
+#
+# Many directions for creating a mini certificate authority exist on the web
+# (eg. openssl, yubikey). (Reminder: safely storing the private key offline is
+# really important, especially in the case of the local-CA's private key.) The
+# local-CA's public key can be loaded onto the system keyring either by building
+# the key into the kernel or, on Fedora, storing it in the UEFI/Mok keyring. (As
+# of writing, the patches for loading the UEFI/Mok keys on the system-keyring
+# have not been upstreamed.)
+#
+# To view the system keyring: keyctl show %keyring:.system_keyring
+#
+# Most on-line directions for signing certificates requires creating a Certificate
+# Signing Request (CSR). Creating such a request requires access to the private
+# key, which would not be available when signing distro or 3rd party certificates.
+# Openssl provides the "-ss_cert" option for directly signing certificates.
+
+# 98integrity/ima-keys-load.sh script loads the signed certificates stored
+# in the $IMAKEYSDIR onto the trusted IMA keyring. The default $IMAKEYSDIR
+# directory is /etc/keys/ima, but can be specified in the /etc/sysconfig/ima
+# policy.
diff --git a/modules.d/98integrity/evm-enable.sh b/modules.d/98integrity/evm-enable.sh
new file mode 100755
index 0000000..fbae5f3
--- /dev/null
+++ b/modules.d/98integrity/evm-enable.sh
@@ -0,0 +1,169 @@
+#!/bin/sh
+
+# Licensed under the GPLv2
+#
+# Copyright (C) 2011 Politecnico di Torino, Italy
+# TORSEC group -- http://security.polito.it
+# Roberto Sassu <roberto.sassu@polito.it>
+
+EVMSECFILE="${SECURITYFSDIR}/evm"
+EVMCONFIG="${NEWROOT}/etc/sysconfig/evm"
+EVMKEYDESC="evm-key"
+EVMKEYTYPE="encrypted"
+EVMKEYID=""
+EVM_ACTIVATION_BITS=0
+
+# The following variables can be set in /etc/sysconfig/evm:
+# EVMKEY: path to the symmetric key; defaults to /etc/keys/evm-trusted.blob
+# EVMKEYDESC: Description of the symmetric key; default is 'evm-key'
+# EVMKEYTYPE: Type of the symmetric key; default is 'encrypted'
+# EVMX509: path to x509 cert; default is /etc/keys/x509_evm.der
+# EVM_ACTIVATION_BITS: additional EVM activation bits, such as
+# EVM_SETUP_COMPLETE; default is 0
+# EVMKEYSDIR: Directory with more x509 certs; default is /etc/keys/evm/
+
+load_evm_key() {
+ # read the configuration from the config file
+ # shellcheck disable=SC1090
+ [ -f "${EVMCONFIG}" ] \
+ && . "${EVMCONFIG}"
+
+ # override the EVM key path name from the 'evmkey=' parameter in the kernel
+ # command line
+ if EVMKEYARG=$(getarg evmkey=); then
+ EVMKEY=${EVMKEYARG}
+ fi
+
+ # 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
+ if [ "${RD_DEBUG}" = "yes" ]; then
+ info "integrity: EVM encrypted key file not found: ${EVMKEYPATH}"
+ fi
+ return 1
+ fi
+
+ # read the EVM encrypted key blob
+ read -r KEYBLOB < "${EVMKEYPATH}"
+
+ # load the EVM encrypted key
+ if ! EVMKEYID=$(keyctl add ${EVMKEYTYPE} ${EVMKEYDESC} "load ${KEYBLOB}" @u); then
+ info "integrity: failed to load the EVM encrypted key: ${EVMKEYDESC}"
+ return 1
+ fi
+ return 0
+}
+
+load_evm_x509() {
+ info "Load EVM IMA X509"
+
+ # override the EVM key path name from the 'evmx509=' parameter in
+ # the kernel command line
+ if EVMX509ARG=$(getarg evmx509=); then
+ EVMX509=${EVMX509ARG}
+ fi
+
+ # 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
+ EVMX509PATH=""
+ fi
+
+ local evm_pubid line
+ if line=$(keyctl describe %keyring:.evm); then
+ # the kernel already setup a trusted .evm keyring so use that one
+ evm_pubid=${line%%:*}
+ else
+ # look for an existing regular keyring
+ evm_pubid=$(keyctl search @u keyring _evm)
+ if [ -z "${evm_pubid}" ]; then
+ # create a new regular _evm keyring
+ evm_pubid=$(keyctl newring _evm @u)
+ fi
+ fi
+
+ if [ -z "${EVMKEYSDIR}" ]; then
+ EVMKEYSDIR="/etc/keys/evm"
+ fi
+ # load the default EVM public key onto the EVM keyring along
+ # with all the other ones in $EVMKEYSDIR
+ local key_imported=1
+ for PUBKEY in ${EVMX509PATH} "${NEWROOT}${EVMKEYSDIR}"/*; do
+ if [ ! -f "${PUBKEY}" ]; then
+ if [ "${RD_DEBUG}" = "yes" ]; then
+ info "integrity: EVM x509 cert file not found: ${PUBKEY}"
+ fi
+ continue
+ fi
+ if ! evmctl import "${PUBKEY}" "${evm_pubid}"; then
+ info "integrity: failed to load the EVM X509 cert ${PUBKEY}"
+ return 1
+ fi
+ key_imported=0
+ done
+
+ if [ "${RD_DEBUG}" = "yes" ]; then
+ keyctl show @u
+ fi
+
+ return ${key_imported}
+}
+
+unload_evm_key() {
+ # unlink the EVM encrypted key
+ keyctl unlink "${EVMKEYID}" @u || {
+ info "integrity: failed to unlink the EVM encrypted key: ${EVMKEYDESC}"
+ return 1
+ }
+
+ return 0
+}
+
+enable_evm() {
+ # check kernel support for EVM
+ if [ ! -e "${EVMSECFILE}" ]; then
+ if [ "${RD_DEBUG}" = "yes" ]; then
+ info "integrity: EVM kernel support is disabled"
+ fi
+ return 0
+ fi
+
+ local evm_configured=0
+ local EVM_INIT_HMAC=1 EVM_INIT_X509=2
+
+ # try to load the EVM encrypted key
+ load_evm_key && evm_configured=${EVM_INIT_HMAC}
+
+ # try to load the EVM public key
+ load_evm_x509 && evm_configured=$((evm_configured | EVM_INIT_X509))
+
+ # only enable EVM if a key or x509 certificate could be loaded
+ if [ $evm_configured -eq 0 ]; then
+ return 1
+ fi
+
+ # initialize EVM
+ info "Enabling EVM"
+ echo $((evm_configured | EVM_ACTIVATION_BITS)) > "${EVMSECFILE}"
+
+ if [ "$((evm_configured & EVM_INIT_HMAC))" -ne 0 ]; then
+ # unload the EVM encrypted key
+ unload_evm_key || return 1
+ fi
+
+ return 0
+}
+
+enable_evm
diff --git a/modules.d/98integrity/ima-keys-load.sh b/modules.d/98integrity/ima-keys-load.sh
new file mode 100755
index 0000000..2374550
--- /dev/null
+++ b/modules.d/98integrity/ima-keys-load.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+SECURITYFSDIR="/sys/kernel/security"
+IMASECDIR="${SECURITYFSDIR}/ima"
+IMACONFIG="${NEWROOT}/etc/sysconfig/ima"
+
+load_x509_keys() {
+ KEYRING_ID=$1
+
+ # override the default configuration
+ if [ -f "${IMACONFIG}" ]; then
+ # shellcheck disable=SC1090
+ . "${IMACONFIG}"
+ fi
+
+ if [ -z "${IMAKEYSDIR}" ]; then
+ IMAKEYSDIR="/etc/keys/ima"
+ fi
+
+ for PUBKEY in "${NEWROOT}${IMAKEYSDIR}"/*; do
+ # check for public key's existence
+ if [ ! -f "${PUBKEY}" ]; then
+ if [ "${RD_DEBUG}" = "yes" ]; then
+ info "integrity: IMA x509 cert file not found: ${PUBKEY}"
+ fi
+ continue
+ fi
+
+ if ! evmctl import "${PUBKEY}" "${KEYRING_ID}"; then
+ info "integrity: IMA x509 cert not loaded on keyring: ${PUBKEY}"
+ fi
+ done
+
+ if [ "${RD_DEBUG}" = "yes" ]; then
+ keyctl show "${KEYRING_ID}"
+ fi
+ return 0
+}
+
+# check kernel support for IMA
+if [ ! -e "${IMASECDIR}" ]; then
+ if [ "${RD_DEBUG}" = "yes" ]; then
+ info "integrity: IMA kernel support is disabled"
+ fi
+ return 0
+fi
+
+# get the IMA keyring id
+
+if line=$(keyctl describe %keyring:.ima); then
+ _ima_id=${line%%:*}
+else
+ _ima_id=$(keyctl search @u keyring _ima)
+ if [ -z "${_ima_id}" ]; then
+ _ima_id=$(keyctl newring _ima @u)
+ fi
+fi
+
+# load the IMA public key(s)
+load_x509_keys "${_ima_id}"
diff --git a/modules.d/98integrity/ima-policy-load.sh b/modules.d/98integrity/ima-policy-load.sh
new file mode 100755
index 0000000..a1fbb4d
--- /dev/null
+++ b/modules.d/98integrity/ima-policy-load.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+# Licensed under the GPLv2
+#
+# Copyright (C) 2011 Politecnico di Torino, Italy
+# TORSEC group -- http://security.polito.it
+# Roberto Sassu <roberto.sassu@polito.it>
+
+IMASECDIR="${SECURITYFSDIR}/ima"
+IMACONFIG="${NEWROOT}/etc/sysconfig/ima"
+IMAPOLICY="/etc/sysconfig/ima-policy"
+
+load_ima_policy() {
+ # check kernel support for IMA
+ if [ ! -e "${IMASECDIR}" ]; then
+ if [ "${RD_DEBUG}" = "yes" ]; then
+ info "integrity: IMA kernel support is disabled"
+ fi
+ return 0
+ fi
+
+ # override the default configuration
+ # shellcheck disable=SC1090
+ [ -f "${IMACONFIG}" ] \
+ && . "${IMACONFIG}"
+
+ # set the IMA policy path name
+ IMAPOLICYPATH="${NEWROOT}${IMAPOLICY}"
+
+ # check the existence of the IMA policy file
+ [ -f "${IMAPOLICYPATH}" ] && {
+ info "Loading the provided IMA custom policy"
+ printf '%s' "${IMAPOLICYPATH}" > "${IMASECDIR}"/policy \
+ || cat "${IMAPOLICYPATH}" > "${IMASECDIR}"/policy
+ }
+
+ return 0
+}
+
+load_ima_policy
diff --git a/modules.d/98integrity/module-setup.sh b/modules.d/98integrity/module-setup.sh
new file mode 100755
index 0000000..fb2badf
--- /dev/null
+++ b/modules.d/98integrity/module-setup.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ return 255
+}
+
+# called by dracut
+depends() {
+ echo masterkey securityfs
+ return 0
+}
+
+# called by dracut
+install() {
+ dracut_install evmctl keyctl
+ inst_hook pre-pivot 61 "$moddir/evm-enable.sh"
+ inst_hook pre-pivot 61 "$moddir/ima-keys-load.sh"
+ inst_hook pre-pivot 62 "$moddir/ima-policy-load.sh"
+}