diff options
Diffstat (limited to 'modules.d/98integrity')
-rw-r--r-- | modules.d/98integrity/README | 68 | ||||
-rwxr-xr-x | modules.d/98integrity/evm-enable.sh | 169 | ||||
-rwxr-xr-x | modules.d/98integrity/ima-keys-load.sh | 60 | ||||
-rwxr-xr-x | modules.d/98integrity/ima-policy-load.sh | 40 | ||||
-rwxr-xr-x | modules.d/98integrity/module-setup.sh | 20 |
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" +} |