Initial commit
This commit is contained in:
@@ -0,0 +1,270 @@
|
||||
This README file contains information on the contents of the
|
||||
integrity layer.
|
||||
|
||||
|
||||
The bbappend files for some recipes (e.g. linux-yocto) in this layer need
|
||||
to have 'integrity' in DISTRO_FEATURES to have effect.
|
||||
To enable them, add in configuration file the following line.
|
||||
|
||||
DISTRO_FEATURES:append = " integrity"
|
||||
|
||||
If meta-integrity is included, but integrity is not enabled as a
|
||||
distro feature a warning is printed at parse time:
|
||||
|
||||
You have included the meta-integritry layer, but
|
||||
'integrity' has not been enabled in your DISTRO_FEATURES. Some bbappend files
|
||||
and preferred version setting may not take effect.
|
||||
|
||||
If you know what you are doing, this warning can be disabled by setting the following
|
||||
variable in your configuration:
|
||||
|
||||
SKIP_META_INTEGRITY_SANITY_CHECK = 1
|
||||
|
||||
Dependencies
|
||||
============
|
||||
|
||||
This layer depends on:
|
||||
|
||||
URI: git://git.openembedded.org/bitbake
|
||||
branch: master
|
||||
|
||||
URI: git://git.openembedded.org/openembedded-core
|
||||
layers: meta
|
||||
branch: master
|
||||
|
||||
URI: git://github.com/01org/meta-security/meta-integrate
|
||||
layers: security-framework
|
||||
branch: master
|
||||
|
||||
|
||||
Patches
|
||||
=======
|
||||
|
||||
For discussion or patch submission via email, use the
|
||||
yocto@yoctoproject.org mailing list. When submitting patches that way,
|
||||
make sure to copy the maintainer and add a "[meta-integrity]"
|
||||
prefix to the subject of the mails.
|
||||
|
||||
Maintainer: Armin Kuster <akuster808@gmail.com>
|
||||
|
||||
|
||||
Table of Contents
|
||||
=================
|
||||
|
||||
1. Adding the integrity layer to your build
|
||||
2. Usage
|
||||
3. Known Issues
|
||||
|
||||
|
||||
1. Adding the integrity layer to your build
|
||||
===========================================
|
||||
|
||||
In order to use this layer, you need to make the build system aware of
|
||||
it.
|
||||
|
||||
Assuming the security repository exists at the top-level of your
|
||||
yocto build tree, you can add it to the build system by adding the
|
||||
location of the integrity layer to bblayers.conf, along with any
|
||||
other layers needed. e.g.:
|
||||
|
||||
BBLAYERS ?= " \
|
||||
/path/to/yocto/meta \
|
||||
/path/to/yocto/meta-yocto \
|
||||
/path/to/yocto/meta-yocto-bsp \
|
||||
/path/to/yocto/meta-security/meta-integrity \
|
||||
"
|
||||
|
||||
It has some dependencies on a suitable BSP; in particular the kernel
|
||||
must have a recent enough IMA/EVM subsystem. The layer was tested with
|
||||
Linux 6.1 and uses some features (like loading X509 certificates
|
||||
directly from the kernel) which were added in that release. Your
|
||||
mileage may vary with older kernels.
|
||||
|
||||
The necessary kernel configuration parameters are added to all kernel
|
||||
versions by this layer. Watch out for QA warnings about unused kernel
|
||||
configuration parameters: those indicate that the kernel used by the BSP
|
||||
does not have the necessary IMA/EVM features.
|
||||
|
||||
Adding the layer only enables IMA (see below regarding EVM) during
|
||||
compilation of the Linux kernel. To also activate it when building
|
||||
the image, enable image signing in the local.conf like this:
|
||||
|
||||
DISTRO_FEATURES:append = " integrity ima"
|
||||
|
||||
IMAGE_CLASSES += "ima-evm-rootfs"
|
||||
|
||||
IMA_EVM_KEY_DIR = "${INTEGRITY_BASE}/data/debug-keys"
|
||||
IMA_EVM_PRIVKEY = "${IMA_EVM_KEY_DIR}/privkey_ima.pem"
|
||||
IMA_EVM_X509 = "${IMA_EVM_KEY_DIR}/x509_ima.der"
|
||||
IMA_EVM_ROOT_CA = "${IMA_EVM_KEY_DIR}/ima-local-ca.pem"
|
||||
|
||||
# The following policy enforces IMA & EVM signatures
|
||||
IMA_EVM_POLICY = "${INTEGRITY_BASE}/recipes-security/ima_policy_appraise_all/files/ima_policy_appraise_all"
|
||||
|
||||
This uses the default keys provided in the "data" directory of the layer.
|
||||
Because everyone has access to these private keys, such an image
|
||||
should never be used in production!
|
||||
|
||||
For that, create your own keys first. All tools and scripts required
|
||||
for that are included in the layer. This is also how the
|
||||
``debug-keys`` were generated:
|
||||
|
||||
# Choose a directory for storing keys. Preserve this
|
||||
# across builds and keep its private keys secret!
|
||||
export IMA_EVM_KEY_DIR=/tmp/imaevm
|
||||
mkdir -p $IMA_EVM_KEY_DIR
|
||||
# Build the required tools.
|
||||
bitbake openssl-native
|
||||
# Set up shell for use of the tools.
|
||||
bitbake -c devshell openssl-native
|
||||
cd $IMA_EVM_KEY_DIR
|
||||
# In that shell, create the keys. Several options exist:
|
||||
|
||||
# 1. Keys signed by a new CA.
|
||||
# When asked for a PEM passphrase, that will be for the root CA.
|
||||
# Signing images then will not require entering that passphrase,
|
||||
# only creating new certificates does. Most likely the default
|
||||
# attributes for these certificates need to be adapted; modify
|
||||
# the scripts as needed.
|
||||
# $INTEGRITY_BASE/scripts/ima-gen-local-ca.sh
|
||||
# $INTEGRITY_BASE/scripts/ima-gen-CA-signed.sh
|
||||
|
||||
# 2. Keys signed by an existing CA.
|
||||
# $INTEGRITY_BASE/scripts/ima-gen-CA-signed.sh <CA.pem> <CA.priv>
|
||||
exit
|
||||
|
||||
The ``ima-gen-local-ca.sh`` and ``ima-gen.sh`` scripts create a root CA
|
||||
and sign the signing keys with it. The ``ima-evm-rootfs.bbclass`` then
|
||||
supports adding tha CA's public key to the kernel's system keyring by
|
||||
compiling it directly into the kernel. Because it is unknown whether
|
||||
that is necessary (for example, the CA might also get added to the
|
||||
system key ring via UEFI Secure Boot), one has to enable compilation
|
||||
into the kernel explicitly in a local.conf with:
|
||||
|
||||
IMA_EVM_ROOT_CA = "<path to .x509 file, for example the ima-local-ca.x509 created by ima-gen-local-ca.sh>"
|
||||
|
||||
|
||||
|
||||
|
||||
To use the personal keys, override the default IMA_EVM_KEY_DIR in your
|
||||
local.conf and/or override the individual variables from
|
||||
ima-evm-rootfs.bbclass:
|
||||
|
||||
IMA_EVM_KEY_DIR = "<full path>"
|
||||
IMA_EVM_PRIVKEY = "<some other path/privkey_ima.pem>"
|
||||
|
||||
By default, the entire file system gets signed. When using a policy which
|
||||
does not require that, the set of files to be labelled can be chosen
|
||||
by overriding the default "find" expression, for example like this:
|
||||
|
||||
IMA_EVM_ROOTFS_FILES = "usr sbin bin lib -type f"
|
||||
|
||||
|
||||
2. Usage
|
||||
========
|
||||
|
||||
After creating an image with IMA/EVM enabled, one needs to enable
|
||||
the built-in policies before IMA/EVM is active at runtime. To do this,
|
||||
add one or both of these boot parameters:
|
||||
|
||||
ima_tcb # measures all files read as root and all files executed
|
||||
ima_appraise_tcb # appraises all files owned by root, beware of
|
||||
# the known issue mentioned below
|
||||
|
||||
Instead of booting with default policies, one can also activate custom
|
||||
policies in different ways. First, boot without any IMA policy and
|
||||
then cat a policy file into
|
||||
`/sys/kernel/security/ima/policy`. This can only be done once
|
||||
after booting and is useful for debugging.
|
||||
|
||||
In production, the long term goal is to load a verified policy
|
||||
directly from the kernel, using a patch which still needs to be
|
||||
included upstream ("ima: load policy from the kernel",
|
||||
<https://lwn.net/Articles/595759/>).
|
||||
|
||||
Loading via systemd also works with systemd, but is considered less
|
||||
secure (policy file is not checked before activating it). Beware that
|
||||
IMA policy loading became broken in systemd 2.18. The modified systemd
|
||||
2.19 in meta-security-smack has a patch reverting the broken
|
||||
changes. To activate policy loading via systemd, place a policy file
|
||||
in `/etc/ima/ima-policy`, for example with:
|
||||
|
||||
IMA_EVM_POLICY = "${INTEGRITY_BASE}/data/ima_policy_simple"
|
||||
|
||||
To check that measuring works, look at `/sys/kernel/security/ima/ascii_runtime_measurements`
|
||||
|
||||
To check that appraisal works, try modifying executables and ensure
|
||||
that executing them fails:
|
||||
|
||||
echo "foobar" >>/usr/bin/rpm
|
||||
evmctl ima_verify /usr/bin/rpm
|
||||
rpm --version
|
||||
|
||||
Depending on the current appraisal policy, the `echo` command may
|
||||
already fail because writing is not allowed. If the file was modified
|
||||
and the current appraisal policy allows reading, then `evmctl` will
|
||||
report (the errno value seems to be printed always and is unrelated to
|
||||
the actual verification failure here):
|
||||
|
||||
Verification failed: 35
|
||||
errno: No such file or directory (2)
|
||||
|
||||
After enabling a suitable IMA appraisal policy, reading and/or
|
||||
executing the file is no longer allowed:
|
||||
|
||||
# evmctl ima_verify /usr/bin/rpm
|
||||
Failed to open: /usr/bin/rpm
|
||||
errno: Permission denied (13)
|
||||
# rpm --version
|
||||
-sh: /usr/bin/rpm: Permission denied
|
||||
|
||||
Enabling the audit kernel subsystem may help to debug appraisal
|
||||
issues. Enable it by adding the meta-security-framework layer and
|
||||
changing your local.conf:
|
||||
SRC_URI:append:pn-linux-yocto = " file://audit.cfg"
|
||||
CORE_IMAGE_EXTRA_INSTALL += "auditd"
|
||||
|
||||
Then boot with "ima_appraise=log ima_appraise_tcb".
|
||||
|
||||
Adding auditd is not strictly necessary but helps to capture a
|
||||
more complete set of events in /var/log/audit/ and search in
|
||||
them with ausearch.
|
||||
|
||||
|
||||
3. Known Issues
|
||||
===============
|
||||
|
||||
EVM is not enabled, for multiple reasons:
|
||||
* Signing files in advance with a X509 certificate and then not having
|
||||
any confidential keys on the device would be the most useful mode,
|
||||
but is not supported by EVM [1].
|
||||
* EVM signing in advance would only work on the final file system and thus
|
||||
will require further integration work with image creation. The content
|
||||
of the files can be signed for IMA in the rootfs, with the extended
|
||||
attributes remaining valid when copying the files to the final image.
|
||||
But for EVM that copy operation changes relevant parameters (for example,
|
||||
inode) and thus invalidates the EVM hash.
|
||||
* On device creation of EVM hashes depends on secure key handling on the
|
||||
device (TPM) and booting at least once in a special mode (file system
|
||||
writable, evm=fix as boot parameter, reboot after opening all files);
|
||||
such a mode is too device specific to be implemented in a generic way.
|
||||
|
||||
IMA appraisal with "ima_appraise_tcb" enables rules which are too strict
|
||||
for most distros. For example, systemd needs to write certain files
|
||||
as root, which is prevented by the ima_appraise_tcb appraise rules. As
|
||||
a result, the system fails to boot:
|
||||
|
||||
[FAILED] Failed to start Commit a transient machine-id on disk.
|
||||
See "systemctl status systemd-machine-id-commit.service" for details.
|
||||
...
|
||||
[FAILED] Failed to start Network Service.
|
||||
See "systemctl status systemd-networkd.service" for details.
|
||||
[FAILED] Failed to start Login Service.
|
||||
See "systemctl status systemd-logind.service" for details.
|
||||
|
||||
No package manager is integrated with IMA/EVM. When updating packages,
|
||||
files will end up getting installed without correct IMA/EVM attributes
|
||||
and thus will not be usable when appraisal is turned on.
|
||||
|
||||
[1] http://permalink.gmane.org/gmane.comp.handhelds.tizen.devel/6281
|
||||
[2] http://permalink.gmane.org/gmane.comp.handhelds.tizen.devel/6275
|
||||
@@ -0,0 +1,107 @@
|
||||
# No default! Either this or IMA_EVM_PRIVKEY/IMA_EVM_X509 have to be
|
||||
# set explicitly in a local.conf before activating ima-evm-rootfs.
|
||||
# To use the insecure (because public) example keys, use
|
||||
# IMA_EVM_KEY_DIR = "${INTEGRITY_BASE}/data/debug-keys"
|
||||
IMA_EVM_KEY_DIR ?= "IMA_EVM_KEY_DIR_NOT_SET"
|
||||
|
||||
# Private key for IMA signing. The default is okay when
|
||||
# using the example key directory.
|
||||
IMA_EVM_PRIVKEY ?= "${IMA_EVM_KEY_DIR}/privkey_ima.pem"
|
||||
|
||||
# Public part of certificates (used for both IMA and EVM).
|
||||
# The default is okay when using the example key directory.
|
||||
IMA_EVM_X509 ?= "${IMA_EVM_KEY_DIR}/x509_ima.der"
|
||||
|
||||
# Root CA to be compiled into the kernel, none by default.
|
||||
# Must be the absolute path to a der-encoded x509 CA certificate
|
||||
# with a .x509 suffix. See linux-%.bbappend for details.
|
||||
#
|
||||
# ima-local-ca.x509 is what ima-gen-local-ca.sh creates.
|
||||
IMA_EVM_ROOT_CA ?= "${IMA_EVM_KEY_DIR}/ima-local-ca.pem"
|
||||
|
||||
# Sign all regular files by default.
|
||||
IMA_EVM_ROOTFS_SIGNED ?= ". -type f"
|
||||
# Hash nothing by default.
|
||||
IMA_EVM_ROOTFS_HASHED ?= ". -depth 0 -false"
|
||||
|
||||
# Mount these file systems (identified via their mount point) with
|
||||
# the iversion flags (needed by IMA when allowing writing).
|
||||
IMA_EVM_ROOTFS_IVERSION ?= ""
|
||||
|
||||
# Avoid re-generating fstab when ima is enabled.
|
||||
WIC_CREATE_EXTRA_ARGS:append = "${@bb.utils.contains('DISTRO_FEATURES', 'ima', ' --no-fstab-update', '', d)}"
|
||||
|
||||
# Add necessary tools (e.g., keyctl) to image
|
||||
IMAGE_INSTALL:append = "${@bb.utils.contains('DISTRO_FEATURES', 'ima', ' ima-evm-utils', '', d)}"
|
||||
|
||||
ima_evm_sign_rootfs () {
|
||||
cd ${IMAGE_ROOTFS}
|
||||
|
||||
# Beware that all operations below must also work when
|
||||
# ima_evm_sign_rootfs was already called earlier for the same
|
||||
# rootfs. That's because do_image might again run for various
|
||||
# reasons (including a change of the signing keys) without also
|
||||
# re-running do_rootfs.
|
||||
|
||||
# Fix /etc/fstab: it must include the "i_version" mount option for
|
||||
# those file systems where writing files is allowed, otherwise
|
||||
# these changes will not get detected at runtime.
|
||||
#
|
||||
# Note that "i_version" is documented in "man mount" only for ext4,
|
||||
# whereas "iversion" is said to be filesystem-independent. In practice,
|
||||
# there is only one MS_I_VERSION flag in the syscall and ext2/ext3/ext4
|
||||
# all support it.
|
||||
#
|
||||
# coreutils translates "iversion" into MS_I_VERSION. busybox rejects
|
||||
# "iversion" and only understands "i_version". systemd only understands
|
||||
# "iversion". We pick "iversion" here for systemd, whereas rootflags
|
||||
# for initramfs must use "i_version" for busybox.
|
||||
#
|
||||
# Deduplicates iversion in case that this gets called more than once.
|
||||
if [ -f etc/fstab ]; then
|
||||
perl -pi -e 's;(\S+)(\s+)(${@"|".join((d.getVar("IMA_EVM_ROOTFS_IVERSION", True) or "no-such-mount-point").split())})(\s+)(\S+)(\s+)(\S+);\1\2\3\4\5\6\7,iversion;; s/(,iversion)+/,iversion/;' etc/fstab
|
||||
fi
|
||||
|
||||
# Detect 32bit target to pass --m32 to evmctl by looking at libc
|
||||
tmp="$(file "${IMAGE_ROOTFS}/lib/libc.so.6" | grep -o 'ELF .*-bit')"
|
||||
if [ "${tmp}" = "ELF 32-bit" ]; then
|
||||
evmctl_param="--m32"
|
||||
elif [ "${tmp}" = "ELF 64-bit" ]; then
|
||||
evmctl_param=""
|
||||
else
|
||||
bberror "Unknown target architecture bitness: '${tmp}'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
bbnote "IMA/EVM: Signing root filesystem at ${IMAGE_ROOTFS} with key ${IMA_EVM_PRIVKEY}"
|
||||
evmctl sign --imasig ${evmctl_param} --portable -a sha256 --key ${IMA_EVM_PRIVKEY} -r "${IMAGE_ROOTFS}"
|
||||
|
||||
# check signing key and signature verification key
|
||||
evmctl ima_verify ${evmctl_param} --key "${IMA_EVM_X509}" "${IMAGE_ROOTFS}/lib/libc.so.6" || exit 1
|
||||
evmctl verify ${evmctl_param} --key "${IMA_EVM_X509}" "${IMAGE_ROOTFS}/lib/libc.so.6" || exit 1
|
||||
|
||||
# Optionally install custom policy for loading by systemd.
|
||||
if [ "${IMA_EVM_POLICY}" ]; then
|
||||
install -d ./${sysconfdir}/ima
|
||||
rm -f ./${sysconfdir}/ima/ima-policy
|
||||
install "${IMA_EVM_POLICY}" ./${sysconfdir}/ima/ima-policy
|
||||
|
||||
bbnote "IMA/EVM: Signing IMA policy with key ${IMA_EVM_PRIVKEY}"
|
||||
evmctl sign --imasig ${evmctl_param} --portable -a sha256 --key "${IMA_EVM_PRIVKEY}" "${IMAGE_ROOTFS}/etc/ima/ima-policy"
|
||||
fi
|
||||
}
|
||||
|
||||
# Signing must run as late as possible in the do_rootfs task.
|
||||
# To guarantee that, we append it to IMAGE_PREPROCESS_COMMAND in
|
||||
# RecipePreFinalise event handler, this ensures it's the last
|
||||
# function in IMAGE_PREPROCESS_COMMAND.
|
||||
python ima_evm_sign_handler () {
|
||||
if not e.data or 'ima' not in e.data.getVar('DISTRO_FEATURES').split():
|
||||
return
|
||||
|
||||
e.data.appendVar('IMAGE_PREPROCESS_COMMAND', ' ima_evm_sign_rootfs; ')
|
||||
e.data.appendVar('IMAGE_INSTALL', ' ima-evm-keys')
|
||||
e.data.appendVarFlag('do_rootfs', 'depends', ' ima-evm-utils-native:do_populate_sysroot')
|
||||
}
|
||||
addhandler ima_evm_sign_handler
|
||||
ima_evm_sign_handler[eventmask] = "bb.event.RecipePreFinalise"
|
||||
@@ -0,0 +1,31 @@
|
||||
# No default! Either this or MODSIGN_PRIVKEY/MODSIGN_X509 have to be
|
||||
# set explicitly in a local.conf before activating kernel-modsign.
|
||||
# To use the insecure (because public) example keys, use
|
||||
# MODSIGN_KEY_DIR = "${INTEGRITY_BASE}/data/debug-keys"
|
||||
MODSIGN_KEY_DIR ??= "MODSIGN_KEY_DIR_NOT_SET"
|
||||
|
||||
# Private key for modules signing. The default is okay when
|
||||
# using the example key directory.
|
||||
MODSIGN_PRIVKEY ?= "${MODSIGN_KEY_DIR}/privkey_modsign.pem"
|
||||
|
||||
# Public part of certificates used for modules signing.
|
||||
# The default is okay when using the example key directory.
|
||||
MODSIGN_X509 ?= "${MODSIGN_KEY_DIR}/x509_modsign.crt"
|
||||
|
||||
# If this class is enabled, disable stripping signatures from modules
|
||||
# as well disable the debug symbols split
|
||||
INHIBIT_PACKAGE_STRIP = "1"
|
||||
INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
|
||||
|
||||
kernel_do_configure:prepend() {
|
||||
if [ -f "${MODSIGN_PRIVKEY}" -a -f "${MODSIGN_X509}" ]; then
|
||||
cat "${MODSIGN_PRIVKEY}" "${MODSIGN_X509}" \
|
||||
> "${B}/modsign_key.pem"
|
||||
else
|
||||
bberror "Either modsign key or certificate are invalid"
|
||||
fi
|
||||
}
|
||||
|
||||
do_shared_workdir:append() {
|
||||
cp modsign_key.pem $kerneldir/
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
addhandler integrity_bbappend_distrocheck
|
||||
integrity_bbappend_distrocheck[eventmask] = "bb.event.SanityCheck"
|
||||
python integrity_bbappend_distrocheck() {
|
||||
skip_check = e.data.getVar('SKIP_META_INTEGRITY_SANITY_CHECK') == "1"
|
||||
if 'integrity' not in e.data.getVar('DISTRO_FEATURES').split() and not skip_check:
|
||||
bb.warn("You have included the meta-integrity layer, but \
|
||||
'integrity' has not been enabled in your DISTRO_FEATURES. Some bbappend files \
|
||||
and preferred version setting may not take effect. See the meta-integrity README \
|
||||
for details on enabling integrity support.")
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
# We have a conf and classes directory, add to BBPATH
|
||||
BBPATH =. "${LAYERDIR}:"
|
||||
|
||||
# We have a packages directory, add to BBFILES
|
||||
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
|
||||
${LAYERDIR}/recipes-*/*/*.bbappend"
|
||||
|
||||
BBFILE_COLLECTIONS += "integrity"
|
||||
BBFILE_PATTERN_integrity := "^${LAYERDIR}/"
|
||||
BBFILE_PRIORITY_integrity = "6"
|
||||
|
||||
# Set a variable to get to the top of the metadata location. Needed
|
||||
# for finding scripts (when following the README.md instructions) and
|
||||
# default debug keys (in ima-evm-rootfs.bbclass).
|
||||
INTEGRITY_BASE := '${LAYERDIR}'
|
||||
|
||||
# We must not export this path to all shell scripts (as in "export
|
||||
# INTEGRITY_BASE"), because that causes problems with sstate (becames
|
||||
# dependent on location of the layer). Exporting it to just the
|
||||
# interactive shell is enough.
|
||||
OE_TERMINAL_EXPORTS += "INTEGRITY_BASE"
|
||||
|
||||
LAYERSERIES_COMPAT_integrity = "mickledore"
|
||||
# ima-evm-utils depends on keyutils from meta-oe
|
||||
LAYERDEPENDS_integrity = "core openembedded-layer"
|
||||
|
||||
BBLAYERS_LAYERINDEX_NAME_integrity = "meta-integrity"
|
||||
|
||||
# Sanity check for meta-integrity layer.
|
||||
# Setting SKIP_META_INTEGRITY_SANITY_CHECK to "1" would skip the bbappend files check.
|
||||
INHERIT += "sanity-meta-integrity"
|
||||
|
||||
BBFILES_DYNAMIC += " \
|
||||
networking-layer:${LAYERDIR}/dynamic-layers/meta-networking/recipes-*/*/*.bbappend \
|
||||
"
|
||||
|
||||
addpylib ${LAYERDIR}/lib oeqa
|
||||
@@ -0,0 +1,17 @@
|
||||
# EVM & IMA keys
|
||||
|
||||
The following IMA & EVM debug/test keys are in this directory
|
||||
|
||||
- ima-local-ca.priv: The CA's private key (password: 1234)
|
||||
- ima-local-ca.pem: The CA's self-signed certificate
|
||||
- privkey_ima.pem: IMA & EVM private key used for signing files
|
||||
- x509_ima.der: Certificate containing public key (of privkey_ima.pem) to verify signatures
|
||||
|
||||
The CA's (self-signed) certificate can be used to verify the validity of
|
||||
the x509_ima.der certificate. Since the CA certificate will be built into
|
||||
the Linux kernel, any key (x509_ima.der) loaded onto the .ima keyring must
|
||||
pass this test:
|
||||
|
||||
```
|
||||
openssl verify -CAfile ima-local-ca.pem x509_ima.der
|
||||
````
|
||||
@@ -0,0 +1,15 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICWzCCAgCgAwIBAgITYMKT7/z5qI+hLfNC6Jy6hhBCWDAKBggqhkjOPQQDAjB9
|
||||
MRQwEgYDVQQKDAtleGFtcGxlLmNvbTFAMD4GA1UEAww3bWV0YS1pbnRlbC1pb3Qt
|
||||
c2VjdXJpdHkgZXhhbXBsZSBjZXJ0aWZpY2F0ZSBzaWduaW5nIGtleTEjMCEGCSqG
|
||||
SIb3DQEJARYUam9obi5kb2VAZXhhbXBsZS5jb20wIBcNMjMwNDI2MTYyNjExWhgP
|
||||
MjEyMzA0MDIxNjI2MTFaMH0xFDASBgNVBAoMC2V4YW1wbGUuY29tMUAwPgYDVQQD
|
||||
DDdtZXRhLWludGVsLWlvdC1zZWN1cml0eSBleGFtcGxlIGNlcnRpZmljYXRlIHNp
|
||||
Z25pbmcga2V5MSMwIQYJKoZIhvcNAQkBFhRqb2huLmRvZUBleGFtcGxlLmNvbTBZ
|
||||
MBMGByqGSM49AgEGCCqGSM49AwEHA0IABCiC+YIbCoOhyLy63lOGbiK+DPkW7gMU
|
||||
rmfVLIb4oTmKxZS5/L8VE6hjKDcLa7OauyuW2nd4fnFAautFxpw/Q0yjXTBbMAwG
|
||||
A1UdEwQFMAMBAf8wHQYDVR0OBBYEFL/PiFFjjlzVtExXMb2uXOfIgeIEMB8GA1Ud
|
||||
IwQYMBaAFL/PiFFjjlzVtExXMb2uXOfIgeIEMAsGA1UdDwQEAwIBBjAKBggqhkjO
|
||||
PQQDAgNJADBGAiEA0HOxloLMr87yDoH3CljWDWb7M2zLA+BQFXLN511qDl0CIQDu
|
||||
clewWaJHw4Wq8IN3JsrNDDw2GfrN3sx4hfWUK/0SPw==
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,7 @@
|
||||
-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||
MIHjME4GCSqGSIb3DQEFDTBBMCkGCSqGSIb3DQEFDDAcBAhinM5KnV2x5wICCAAw
|
||||
DAYIKoZIhvcNAgkFADAUBggqhkiG9w0DBwQI4Xbw/W1pgH0EgZCiurgCTUEIDbiK
|
||||
x5kw3/Rg1/ZLwk5TEiMoIa9CmXEyuSRUla/Ta4o/rZEzKAp6vwkcupviirtWYems
|
||||
lZNfggfzITWNEWtkU6BrhZgJ7kaeZrIbuAO7YUJy6Z2MQfgaKI9BE2EEgKJ+X5gY
|
||||
LjkobSAtEqDjuheLgaXIMQ7/qT0MGmi6LmzwMEhu8ZXlNGg8udw=
|
||||
-----END ENCRYPTED PRIVATE KEY-----
|
||||
@@ -0,0 +1,5 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgmbPxV5LYZ530IfGm
|
||||
SMpfPQFgoIkKPMRuNWLyVn+wiAOhRANCAAQ31W5ZQZdcwidgpyls2oO5rSsHLlqj
|
||||
cKYaDF2fveMN5L/wBwEi84ubzz2+MkM9q7RaOSC4TPYHnhVvYcH+SsFv
|
||||
-----END PRIVATE KEY-----
|
||||
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDEWsJjB2pA5Ih6
|
||||
EelXvVjwWY1ix1azMciNRNPPQN1AMXF0K/VUkfOYbaPajg1cQYEf9gk3q7OZ5Axk
|
||||
UY/e5piZORaPcsmj0lV0L+NSlRYydR5M/QxtEz26585FgqRGdAe6umStPmVKdqa2
|
||||
d68O4PgQgJJtVuz6ndm+0uNEUDCVLwhkGQSwNB3qBbZAUX9escZ/a8eUiBfMYKaO
|
||||
k8JRyM+2br9dgpTFg4UfBYexgNSQo8g5TIBGc8KgQiKCuFj1fQEhV5z4RusHthjc
|
||||
NYXa3RHmdclxyrGeYr5ZRc47HqE1gd5NDR0WeHn4C4YKcfK1rZZz/2+6hfsIRfGx
|
||||
6cQKk23hAgMBAAECggEAJ0ULiWirPG04SkmYxF5vEiqm1zGMymvTc0VnoxSS60q4
|
||||
KQa9mvtRn5OV6JjuXRwQqga30zV4xvdP7yRMxMSTkllThL7tSuE/C+yj5xlABjlc
|
||||
JQOa35mwh9fibg5xslF0Vkj+55MKCPlv4CBRl4Uwt4QvRMTUwk6dhMeCgmATR1J1
|
||||
2/7AipjtfFYreDx7sLbRVvSzUhmZS0iCbNOhtTWPLNW+9YKHTOffKa04HzNtnAXq
|
||||
OjJ0IRZD/C6LfkBUsnHg2eEiA97QXh/Srsl9nc8DaUK1IXRywEdmYIoNMWMav2Hm
|
||||
RO8kkU30BqKW+/EO2ZbH2GmkxvwWd0ocBnLC3FRWEQKBgQDu4T8CB3YsOcVjqem4
|
||||
iBlaSht/b46YQc7A1SOqZCimehmmXNSxQOkapIG3wlIr5edtXQA+xv09+WrproUB
|
||||
SjAnqaH6pYeCvbNlY5k344gtYs+Kco2rq5GYa+LumAeX2Sam8F7u4LxvEogCecX7
|
||||
e4rnG3lt3AVuuRE7zpCQtaWcJQKBgQDSbUvea9pcYli9pssTl+ijQKkgG9DdaYbA
|
||||
I5w5bY1TPYZ/Ocysljefv/ssaHFh4DPxE1MQ5JHwZgZRo1EICxxYzGsLjyR/fmjz
|
||||
1c/NJlTtalCNtLvWaf7b02ag/abnP8neiSpLL5xqHvGo5ikWwgYQD+9HVKGvL3S1
|
||||
kI7x/ziADQKBgQCqFbkuMa/jh3LTJp0iZc1fa1qu3vhx0pFq3Zeab9w9xLxUps5O
|
||||
MwCGltFBzNuDJBwm00wkZrzTjq6gGkHbjD5DT1XkyE13OqjsLQFgOOKyJiPN2Qik
|
||||
TfHJzC91YMwvQ09xF78QaPXiRBiRYrEkAXACY56PKVS45I6vvcFTN/Ll/QKBgA9m
|
||||
KDMyuVwhZlUaq6nXaBLqXHYZEwPhARd2g6xANCNvUTRmSnAm3hM2vW7WhdWfzq1J
|
||||
uL53u6ZYEQZQaVGpXn2xF/RUmVsrKQsPDpH4yCZHrXVxUH20bA4yPkRxy5EIvgEn
|
||||
EI1IAq5RbWXq0f70W/U49U3HB74GPwg6d/uFreDRAoGAN+v9gMQA6A1vM7LvbYR8
|
||||
5CwwyqS/CfI9zKPLn53QstguXC/ObafIYQzVRqGb9lCQgtlmmKw4jMY0B/lDzpcH
|
||||
zS8rqoyvDj/m7i17NYkqXErJKLRQ0ptXKdLXHlG0u185e7Y5p4O3Z5dk8bACkpHi
|
||||
hp764y+BtU4qIcVaPsPK4uU=
|
||||
-----END PRIVATE KEY-----
|
||||
Binary file not shown.
@@ -0,0 +1,22 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDnjCCAoagAwIBAgIUUqmBj5Q8edHMMTXsoGVGEEKdwV4wDQYJKoZIhvcNAQEL
|
||||
BQAwZzEqMCgGA1UEAxMhbWV0YS1zZWN1cml0eSBtb2R1bGVzIHNpZ25pbmcga2V5
|
||||
MRQwEgYDVQQKEwtleGFtcGxlLmNvbTEjMCEGCSqGSIb3DQEJARYUam9obi5kb2VA
|
||||
ZXhhbXBsZS5jb20wIBcNMTkwNzI3MjIzOTA3WhgPMjExOTA3MjcyMjM5MTVaMGcx
|
||||
KjAoBgNVBAMTIW1ldGEtc2VjdXJpdHkgbW9kdWxlcyBzaWduaW5nIGtleTEUMBIG
|
||||
A1UEChMLZXhhbXBsZS5jb20xIzAhBgkqhkiG9w0BCQEWFGpvaG4uZG9lQGV4YW1w
|
||||
bGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxFrCYwdqQOSI
|
||||
ehHpV71Y8FmNYsdWszHIjUTTz0DdQDFxdCv1VJHzmG2j2o4NXEGBH/YJN6uzmeQM
|
||||
ZFGP3uaYmTkWj3LJo9JVdC/jUpUWMnUeTP0MbRM9uufORYKkRnQHurpkrT5lSnam
|
||||
tnevDuD4EICSbVbs+p3ZvtLjRFAwlS8IZBkEsDQd6gW2QFF/XrHGf2vHlIgXzGCm
|
||||
jpPCUcjPtm6/XYKUxYOFHwWHsYDUkKPIOUyARnPCoEIigrhY9X0BIVec+EbrB7YY
|
||||
3DWF2t0R5nXJccqxnmK+WUXOOx6hNYHeTQ0dFnh5+AuGCnHyta2Wc/9vuoX7CEXx
|
||||
senECpNt4QIDAQABo0AwPjAMBgNVHRMBAf8EAjAAMA8GA1UdDwEB/wQFAwMHgAAw
|
||||
HQYDVR0OBBYEFDa35X9LnPlrd76inh/cYgeXh6X4MA0GCSqGSIb3DQEBCwUAA4IB
|
||||
AQBTPTh7zY9BrfZW9Izk9JSZYNigwUDwjrhNBSLr5NKi2A/LmZ0jjdCDkwaCn5io
|
||||
xrAq5oxPCAkwlzKwY2ootcL3+En4Pq2e5U+n9kRrpDpKKiR5/0S0d9vpgg4eZR0R
|
||||
kxqE9APCQ5SFU3PgnJ5H5y2SPXzle3bgUsWxNGD81zXFn5clJj4XHvJDWTQ/jG7C
|
||||
FTQ1o1HXtzda4EmKIzrSU/ayVbpPg5fPEBJjk/hHPT45kfzVZBuxwBLXVbe/YyWi
|
||||
NTFWCbJwjZwVRKrsQ3HFpYMWvugtcsSHo7vGi06FvUHcS2sUZH5sFn7hulcIGICt
|
||||
EztTO8Q+yhZujZbmEyJmxqZv
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,127 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Authors: Cristina Moraru <cristina.moraru@intel.com>
|
||||
# Alexandru Cornea <alexandru.cornea@intel.com>
|
||||
|
||||
import string
|
||||
from time import sleep
|
||||
from oeqa.runtime.case import OERuntimeTestCase
|
||||
from oeqa.core.decorator.depends import OETestDepends
|
||||
from oeqa.runtime.decorator.package import OEHasPackage
|
||||
from oeqa.core.decorator.data import skipIfNotFeature
|
||||
from oeqa.core.decorator.data import skipIfDataVar, skipIfNotDataVar
|
||||
import bb
|
||||
blacklist = ["/usr/bin/uz", "/bin/su.shadow"]
|
||||
|
||||
class IMACheck(OERuntimeTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
locations = ["/bin", "/usr/bin"]
|
||||
cls.binaries = []
|
||||
for l in locations:
|
||||
status, output = cls.tc.target.run("find %s -type f" % l)
|
||||
cls.binaries.extend(output.split("\n"))
|
||||
|
||||
cls.total = len(cls.binaries)
|
||||
|
||||
|
||||
@OETestDepends(['ssh.SSHTest.test_ssh'])
|
||||
def test_ima_enabled(self):
|
||||
''' Test if IMA policy is loaded before systemd starts'''
|
||||
|
||||
ima_search = "ima: "
|
||||
systemd_search = "systemd .* running"
|
||||
status, output = self.target.run("dmesg | grep -n '%s'" % ima_search)
|
||||
self.assertEqual( status, 0, "Did not find '%s' in dmesg" % ima_search)
|
||||
|
||||
|
||||
@skipIfNotFeature('systemd',
|
||||
'Test requires systemd to be in DISTRO_FEATURES')
|
||||
@skipIfNotDataVar('VIRTUAL-RUNTIME_init_manager', 'systemd',
|
||||
'systemd is not the init manager for this image')
|
||||
@OETestDepends(['ima.IMACheck.test_ima_enabled'])
|
||||
def test_ima_before_systemd(self):
|
||||
''' Test if IMA policy is loaded before systemd starts'''
|
||||
ima_search = "ima: "
|
||||
systemd_search = "systemd .* running"
|
||||
status, output = self.target.run("dmesg | grep -n '%s'" % ima_search)
|
||||
self.assertEqual( status, 0, "Did not find '%s' in dmesg" % ima_search)
|
||||
ima_id = int(output.split(":")[0])
|
||||
status, output = self.target.run("dmesg | grep -n '%s'" % systemd_search)
|
||||
self.assertEqual(status, 0, "Did not find '%s' in dmesg" % systemd_search)
|
||||
init_id = int(output.split(":")[0])
|
||||
if ima_id > init_id:
|
||||
self.fail("IMA does not start before systemd")
|
||||
|
||||
|
||||
@OETestDepends(['ima.IMACheck.test_ima_enabled'])
|
||||
def test_ima_hash(self):
|
||||
''' Test if IMA stores correct file hash '''
|
||||
filename = "/etc/ld.so.cache"
|
||||
ima_measure_file = "/sys/kernel/security/ima/ascii_runtime_measurements"
|
||||
|
||||
# wait for the IMA system to update the entry
|
||||
maximum_tries = 3
|
||||
tries = 0
|
||||
status, output = self.target.run("sha256sum %s" %filename)
|
||||
sleep(2)
|
||||
current_hash = output.split()[0]
|
||||
ima_hash = ""
|
||||
|
||||
while tries < maximum_tries:
|
||||
status, output = self.target.run("cat %s | grep -e '%s'" \
|
||||
% (ima_measure_file, filename))
|
||||
# get last entry, 4th field
|
||||
if status == 0:
|
||||
tokens = output.split("\n")[-1].split()[3]
|
||||
ima_hash = tokens.split(":")[1]
|
||||
if ima_hash == current_hash:
|
||||
break
|
||||
|
||||
tries += 1
|
||||
sleep(1)
|
||||
|
||||
# clean target
|
||||
self.target.run("rm %s" % filename)
|
||||
if ima_hash != current_hash:
|
||||
self.fail("Hash stored by IMA does not match actual hash")
|
||||
|
||||
|
||||
@OETestDepends(['ima.IMACheck.test_ima_enabled'])
|
||||
def test_ima_signature(self):
|
||||
''' Test if IMA stores correct signature for system binaries'''
|
||||
passed = 0
|
||||
failed = 0
|
||||
for b in self.binaries:
|
||||
if b in blacklist:
|
||||
continue
|
||||
status, output = self.target.run("evmctl ima_verify %s" % b)
|
||||
if status != 0:
|
||||
failed += 1
|
||||
else:
|
||||
passed += 1
|
||||
|
||||
if failed == self.total:
|
||||
self.fail("Signature verifications failed (%s)" % self.total)
|
||||
|
||||
#bb.warn("pass: %s, fail: %s, Total: %s" % (passed, failed, total))
|
||||
|
||||
@OETestDepends(['ima.IMACheck.test_ima_enabled'])
|
||||
def test_ima_overwrite(self):
|
||||
''' Test if IMA prevents overwriting signed files '''
|
||||
passed = 0
|
||||
failed = 0
|
||||
for b in self.binaries:
|
||||
if b in blacklist:
|
||||
continue
|
||||
self.target.run("echo 'foo' >> %s" % b )
|
||||
status, output = self.target.run("evmctl ima_verify %s" % b)
|
||||
|
||||
if status != 0:
|
||||
failed += 1
|
||||
else:
|
||||
passed += 1
|
||||
|
||||
if failed == self.total:
|
||||
self.fail("Overwritting verifications failed (%s)" % self.total)
|
||||
@@ -0,0 +1,5 @@
|
||||
# Append iversion option for auto types
|
||||
do_install:append() {
|
||||
sed -i 's/\s*auto\s*defaults/&,iversion/' "${D}${sysconfdir}/fstab"
|
||||
echo 'securityfs /sys/kernel/security securityfs defaults 0 0' >> "${D}${sysconfdir}/fstab"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
require ${@bb.utils.contains('DISTRO_FEATURES', 'ima', 'base-files-ima.inc', '', d)}
|
||||
@@ -0,0 +1,21 @@
|
||||
DESCRIPTION = "An image as an exmaple for Ima support"
|
||||
|
||||
IMAGE_FEATURES += "ssh-server-openssh"
|
||||
|
||||
|
||||
IMAGE_INSTALL = "\
|
||||
packagegroup-base \
|
||||
packagegroup-core-boot \
|
||||
packagegroup-ima-evm-utils \
|
||||
os-release"
|
||||
|
||||
|
||||
LICENSE = "MIT"
|
||||
|
||||
inherit core-image
|
||||
|
||||
export IMAGE_BASENAME = "integrity-image-minimal"
|
||||
|
||||
INHERIT += "ima-evm-rootfs"
|
||||
|
||||
QB_KERNEL_CMDLINE_APPEND:append = " ima_policy=tcb ima_appraise=fix"
|
||||
@@ -0,0 +1,36 @@
|
||||
# This recipe creates a module for the initramfs-framework in OE-core
|
||||
# which initializes IMA by loading a policy before transferring
|
||||
# control to the init process in the rootfs. The advantage over having
|
||||
# that init process doing the policy loading (which systemd could do)
|
||||
# is that already the integrity of the init binary itself will be
|
||||
# checked by the kernel.
|
||||
|
||||
SUMMARY = "IMA module for the modular initramfs system"
|
||||
LICENSE = "MIT"
|
||||
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
|
||||
|
||||
# This policy file will get installed as /etc/ima/ima-policy.
|
||||
# It is located via the normal file search path, so a .bbappend
|
||||
# to this recipe can just point towards one of its own files.
|
||||
IMA_POLICY ?= "ima-policy-hashed"
|
||||
|
||||
# Force proceed IMA procedure even 'no_ima' boot parameter is available.
|
||||
IMA_FORCE ?= "false"
|
||||
|
||||
SRC_URI = " file://ima"
|
||||
|
||||
inherit features_check
|
||||
REQUIRED_DISTRO_FEATURES = "ima"
|
||||
|
||||
do_install () {
|
||||
install -d ${D}/${sysconfdir}/ima
|
||||
install -d ${D}/init.d
|
||||
install ${WORKDIR}/ima ${D}/init.d/20-ima
|
||||
|
||||
sed -i "s/@@FORCE_IMA@@/${IMA_FORCE}/g" ${D}/init.d/20-ima
|
||||
}
|
||||
|
||||
FILES:${PN} = "/init.d ${sysconfdir}"
|
||||
|
||||
RDEPENDS:${PN} = "keyutils ima-evm-keys ${IMA_POLICY}"
|
||||
RDEPENDS:${PN} += "initramfs-framework-base"
|
||||
@@ -0,0 +1,58 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Loads IMA policy into the kernel.
|
||||
|
||||
force_ima=@@FORCE_IMA@@
|
||||
|
||||
ima_enabled() {
|
||||
if [ "$force_ima" = "true" ]; then
|
||||
return 0
|
||||
elif [ "$bootparam_no_ima" = "true" ]; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
ima_run() {
|
||||
info "Initializing IMA (can be skipped with no_ima boot parameter)."
|
||||
if ! grep -w securityfs /proc/mounts >/dev/null; then
|
||||
if ! mount -t securityfs securityfs /sys/kernel/security; then
|
||||
fatal "Could not mount securityfs."
|
||||
fi
|
||||
fi
|
||||
if [ ! -d /sys/kernel/security/ima ]; then
|
||||
fatal "No /sys/kernel/security/ima. Cannot proceed without IMA enabled in the kernel."
|
||||
fi
|
||||
|
||||
# Instead of depending on the kernel to load the IMA X.509 certificate,
|
||||
# use keyctl. This avoids a bug in certain kernels (https://lkml.org/lkml/2015/9/10/492)
|
||||
# where the loaded key was not checked sufficiently. We use keyctl here because it is
|
||||
# slightly smaller than evmctl and is needed anyway.
|
||||
# (see http://sourceforge.net/p/linux-ima/ima-evm-utils/ci/v0.9/tree/README#l349).
|
||||
for kind in ima evm; do
|
||||
key=/etc/keys/x509_$kind.der
|
||||
if [ -s $key ]; then
|
||||
id=$(grep -w -e "\.$kind" /proc/keys | cut -d ' ' -f1 | head -n 1)
|
||||
if [ "$id" ]; then
|
||||
id=$(printf "%d" 0x$id)
|
||||
fi
|
||||
if [ -z "$id" ]; then
|
||||
id=`keyctl search @u keyring _$kind 2>/dev/null`
|
||||
if [ -z "$id" ]; then
|
||||
id=`keyctl newring _$kind @u`
|
||||
fi
|
||||
fi
|
||||
info "Loading $key into $kind keyring $id"
|
||||
keyctl padd asymmetric "" $id <$key
|
||||
fi
|
||||
done
|
||||
|
||||
# In theory, a simple "cat" should be enough. In practice, loading sometimes fails randomly
|
||||
# ("[Linux-ima-user] IMA policy loading via cat") and we get better error reporting when
|
||||
# checking the write of each line. To minimize the risk of policy loading going wrong we
|
||||
# also remove comments and blank lines ourselves.
|
||||
if ! (set -e; while read i; do if echo "$i" | grep -q -e '^#' -e '^ *$'; then debug "Skipping IMA policy: $i"; else debug "Writing IMA policy: $i"; if echo $i; then sleep ${bootparam_ima_delay:-0}; else fatal "Invalid line in IMA policy: $i"; exit 1; fi; fi; done) </etc/ima/ima-policy >/sys/kernel/security/ima/policy; then
|
||||
fatal "Could not load IMA policy."
|
||||
fi
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
SUMMARY = "IMA/EVM userspace tools"
|
||||
LICENSE = "MIT"
|
||||
|
||||
inherit packagegroup features_check
|
||||
|
||||
REQUIRED_DISTRO_FEATURES = "ima"
|
||||
|
||||
# Only one at the moment, but perhaps more will come in the future.
|
||||
RDEPENDS:${PN} = " \
|
||||
ima-evm-utils \
|
||||
"
|
||||
@@ -0,0 +1,2 @@
|
||||
[Service]
|
||||
ExecStartPost=/bin/sync
|
||||
@@ -0,0 +1,3 @@
|
||||
[Service]
|
||||
ExecStopPost=/bin/sync
|
||||
ExecStartPost=/bin/sync
|
||||
@@ -0,0 +1,13 @@
|
||||
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
|
||||
|
||||
SRC_URI += " \
|
||||
file://machine-id-commit-sync.conf \
|
||||
file://random-seed-sync.conf \
|
||||
"
|
||||
|
||||
do_install:append () {
|
||||
for i in machine-id-commit random-seed; do
|
||||
install -d ${D}/${systemd_system_unitdir}/systemd-$i.service.d
|
||||
install -m 0644 ${WORKDIR}/$i-sync.conf ${D}/${systemd_system_unitdir}/systemd-$i.service.d
|
||||
done
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
require ${@bb.utils.contains_any('DISTRO_FEATURES', 'integrity ', 'linux_ima.inc', '', d)}
|
||||
@@ -0,0 +1,45 @@
|
||||
CONFIG_KEYS=y
|
||||
CONFIG_ASYMMETRIC_KEY_TYPE=y
|
||||
CONFIG_SYSTEM_TRUSTED_KEYRING=y
|
||||
CONFIG_SYSTEM_TRUSTED_KEYS="${IMA_EVM_ROOT_CA}"
|
||||
CONFIG_SECONDARY_TRUSTED_KEYRING=y
|
||||
CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
|
||||
CONFIG_X509_CERTIFICATE_PARSER=y
|
||||
CONFIG_PKCS8_PRIVATE_KEY_PARSER=y
|
||||
CONFIG_CRYPTO_ECDSA=y
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITYFS=y
|
||||
CONFIG_INTEGRITY=y
|
||||
CONFIG_INTEGRITY_SIGNATURE=y
|
||||
CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
|
||||
CONFIG_INTEGRITY_TRUSTED_KEYRING=y
|
||||
CONFIG_IMA=y
|
||||
CONFIG_IMA_MEASURE_PCR_IDX=10
|
||||
CONFIG_IMA_LSM_RULES=y
|
||||
# CONFIG_IMA_TEMPLATE is not set
|
||||
# CONFIG_IMA_NG_TEMPLATE is not set
|
||||
CONFIG_IMA_SIG_TEMPLATE=y
|
||||
CONFIG_IMA_DEFAULT_TEMPLATE="ima-sig"
|
||||
# CONFIG_IMA_DEFAULT_HASH_SHA1 is not set
|
||||
CONFIG_IMA_DEFAULT_HASH_SHA256=y
|
||||
# CONFIG_IMA_DEFAULT_HASH_SHA512 is not set
|
||||
CONFIG_IMA_DEFAULT_HASH="sha256"
|
||||
CONFIG_IMA_WRITE_POLICY=y
|
||||
CONFIG_IMA_READ_POLICY=y
|
||||
CONFIG_IMA_APPRAISE=y
|
||||
CONFIG_IMA_ARCH_POLICY=y
|
||||
CONFIG_IMA_APPRAISE_BUILD_POLICY=y
|
||||
CONFIG_IMA_APPRAISE_REQUIRE_POLICY_SIGS=y
|
||||
# CONFIG_IMA_APPRAISE_BOOTPARAM is not set
|
||||
# CONFIG_IMA_APPRAISE_MODSIG is not set
|
||||
CONFIG_IMA_TRUSTED_KEYRING=y
|
||||
CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY=y
|
||||
# CONFIG_IMA_BLACKLIST_KEYRING is not set
|
||||
# CONFIG_IMA_LOAD_X509 is not set
|
||||
CONFIG_IMA_APPRAISE_SIGNED_INIT=y
|
||||
CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS=y
|
||||
CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS=y
|
||||
CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT=y
|
||||
# CONFIG_IMA_DISABLE_HTABLE is not set
|
||||
CONFIG_EVM=y
|
||||
# CONFIG_EVM_LOAD_X509 is not set
|
||||
@@ -0,0 +1,4 @@
|
||||
define KFEATURE_DESCRIPTION "Enable IMA"
|
||||
|
||||
kconf non-hardware ima.cfg
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
FILESEXTRAPATHS:append := "${THISDIR}/linux:"
|
||||
|
||||
SRC_URI += " \
|
||||
${@bb.utils.contains('DISTRO_FEATURES', 'ima', 'file://ima.scc', '', d)} \
|
||||
"
|
||||
|
||||
do_configure:append() {
|
||||
if [ "${@bb.utils.contains('DISTRO_FEATURES', 'ima', 'yes', '', d)}" = "yes" ] && [ -f .config ] ; then
|
||||
sed -i "s|^CONFIG_SYSTEM_TRUSTED_KEYS=.*|CONFIG_SYSTEM_TRUSTED_KEYS=\"${IMA_EVM_ROOT_CA}\"|" .config
|
||||
fi
|
||||
}
|
||||
|
||||
KERNEL_FEATURES:append = " ${@bb.utils.contains('DISTRO_FEATURES', 'modsign', ' features/ima/modsign.scc', '', d)}"
|
||||
|
||||
inherit ${@bb.utils.contains('DISTRO_FEATURES', 'modsign', 'kernel-modsign', '', d)}
|
||||
@@ -0,0 +1,17 @@
|
||||
SUMMARY = "IMA/EMV public keys"
|
||||
LICENSE = "MIT"
|
||||
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
|
||||
|
||||
inherit features_check
|
||||
REQUIRED_DISTRO_FEATURES = "ima"
|
||||
|
||||
ALLOW_EMPTY:${PN} = "1"
|
||||
|
||||
do_install () {
|
||||
if [ -e "${IMA_EVM_X509}" ]; then
|
||||
install -d ${D}/${sysconfdir}/keys
|
||||
install "${IMA_EVM_X509}" ${D}${sysconfdir}/keys/x509_evm.der
|
||||
ln -rs ${D}${sysconfdir}/keys/x509_evm.der ${D}${sysconfdir}/keys/x509_ima.der
|
||||
fi
|
||||
}
|
||||
do_install[file-checksums] += "${@'${IMA_EVM_X509}:%s' % os.path.exists('${IMA_EVM_X509}')}"
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
From 00ace817c5134d9844db387cadb9517ebad43808 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Berger <stefanb@linux.ibm.com>
|
||||
Date: Tue, 18 Apr 2023 11:43:55 -0400
|
||||
Subject: [PATCH] Do not get generation using ioctl when evm_portable is true
|
||||
|
||||
If a signatures is detected as being portable do not attempt to read the
|
||||
generation with the ioctl since in some cases this may not be supported
|
||||
by the filesystem and is also not needed for computing a portable
|
||||
signature.
|
||||
|
||||
This avoids the current work-around of passing --generation 0 when the
|
||||
ioctl is not supported by the filesystem.
|
||||
|
||||
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||
---
|
||||
Upstream-Status: Pending
|
||||
|
||||
src/evmctl.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/evmctl.c b/src/evmctl.c
|
||||
index 6d2bb67..c35a28c 100644
|
||||
--- a/src/evmctl.c
|
||||
+++ b/src/evmctl.c
|
||||
@@ -376,7 +376,7 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
|
||||
if (mode_str)
|
||||
st.st_mode = strtoul(mode_str, NULL, 10);
|
||||
|
||||
- if (!evm_immutable) {
|
||||
+ if (!evm_immutable && !evm_portable) {
|
||||
if (S_ISREG(st.st_mode) && !generation_str) {
|
||||
int fd = open(file, 0);
|
||||
|
||||
---
|
||||
Upstream-Status: Pending
|
||||
|
||||
2.39.2
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
DESCRIPTION = "IMA/EVM control utility"
|
||||
LICENSE = "GPL-2.0-with-OpenSSL-exception"
|
||||
LIC_FILES_CHKSUM = "file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263"
|
||||
|
||||
DEPENDS += "openssl attr keyutils"
|
||||
|
||||
DEPENDS:class-native += "openssl-native keyutils-native"
|
||||
|
||||
FILESEXTRAPATHS:append := "${THISDIR}/${PN}:"
|
||||
|
||||
SRC_URI = " \
|
||||
https://github.com/mimizohar/ima-evm-utils/releases/download/v${PV}/${BP}.tar.gz \
|
||||
file://0001-Do-not-get-generation-using-ioctl-when-evm_portable-.patch \
|
||||
"
|
||||
SRC_URI[sha256sum] = "45f1caa3ad59ec59a1d6a74ea5df38c413488cd952ab62d98cf893c15e6f246d"
|
||||
|
||||
inherit pkgconfig autotools features_check
|
||||
|
||||
REQUIRED_DISTRO_FEATURES = "ima"
|
||||
REQUIRED_DISTRO_FEATURES:class-native = ""
|
||||
|
||||
EXTRA_OECONF += "MANPAGE_DOCBOOK_XSL=0"
|
||||
EXTRA_OECONF:append:class-target = " --with-kernel-headers=${STAGING_KERNEL_BUILDDIR}"
|
||||
|
||||
# blkid is called by evmctl when creating evm checksums.
|
||||
# This is less useful when signing files on the build host,
|
||||
# so disable it when compiling on the host.
|
||||
RDEPENDS:${PN}:append:class-target = " util-linux-blkid libcrypto attr libattr keyutils"
|
||||
|
||||
BBCLASSEXTEND = "native nativesdk"
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
#
|
||||
# Integrity measure policy (http://sourceforge.net/p/linux-ima/wiki/Home/#measure-nothing-appraise-everything)
|
||||
#
|
||||
# Do not measure anything, but appraise everything
|
||||
#
|
||||
# PROC_SUPER_MAGIC
|
||||
dont_appraise fsmagic=0x9fa0
|
||||
# SYSFS_MAGIC
|
||||
dont_appraise fsmagic=0x62656572
|
||||
# DEBUGFS_MAGIC
|
||||
dont_appraise fsmagic=0x64626720
|
||||
# TMPFS_MAGIC
|
||||
dont_appraise fsmagic=0x01021994
|
||||
# RAMFS_MAGIC
|
||||
dont_appraise fsmagic=0x858458f6
|
||||
# DEVPTS_SUPER_MAGIC
|
||||
dont_appraise fsmagic=0x1cd1
|
||||
# BIFMT
|
||||
dont_appraise fsmagic=0x42494e4d
|
||||
# SECURITYFS_MAGIC
|
||||
dont_appraise fsmagic=0x73636673
|
||||
# SELINUXFS_MAGIC
|
||||
dont_appraise fsmagic=0xf97cff8c
|
||||
# NSFS_MAGIC (introduced in 3.19, see cd025f7 and e149ed2 in the upstream Linux kernel)
|
||||
dont_appraise fsmagic=0x6e736673
|
||||
# EFIVARFS_MAGIC
|
||||
dont_appraise fsmagic=0xde5e81e4
|
||||
# Cgroup
|
||||
dont_appraise fsmagic=0x27e0eb
|
||||
# Cgroup2
|
||||
dont_appraise fsmagic=0x63677270
|
||||
|
||||
# Appraise libraries
|
||||
appraise func=MMAP_CHECK mask=MAY_EXEC
|
||||
# Appraise executables
|
||||
appraise func=BPRM_CHECK
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
SUMMARY = "IMA sample simple appraise policy "
|
||||
LICENSE = "MIT"
|
||||
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
|
||||
|
||||
SRC_URI = " file://ima_policy_appraise_all"
|
||||
|
||||
inherit features_check
|
||||
REQUIRED_DISTRO_FEATURES = "ima"
|
||||
|
||||
do_install () {
|
||||
install -d ${D}/${sysconfdir}/ima
|
||||
install ${WORKDIR}/ima_policy_appraise_all ${D}/${sysconfdir}/ima/ima-policy
|
||||
}
|
||||
|
||||
FILES:${PN} = "${sysconfdir}/ima"
|
||||
RDEPENDS:${PN} = "ima-evm-utils"
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
# With this policy, all files on regular partitions are
|
||||
# appraised. Files with signed IMA hash and normal hash are
|
||||
# accepted. Signed files cannot be modified while hashed files can be
|
||||
# (which will also update the hash). However, signed files can
|
||||
# be deleted, so in practice it is still possible to replace them
|
||||
# with a modified version.
|
||||
#
|
||||
# Without EVM, this is obviously not very secure, so this policy is
|
||||
# just an example and/or basis for further improvements. For that
|
||||
# purpose, some comments show what could be added to make the policy
|
||||
# more secure.
|
||||
#
|
||||
# With EVM the situation might be different because access
|
||||
# to the EVM key can be restricted.
|
||||
#
|
||||
# Files which are appraised are also measured. This allows
|
||||
# debugging whether a file is in policy by looking at
|
||||
# /sys/kernel/security/ima/ascii_runtime_measurements
|
||||
|
||||
# PROC_SUPER_MAGIC
|
||||
dont_appraise fsmagic=0x9fa0
|
||||
dont_measure fsmagic=0x9fa0
|
||||
# SYSFS_MAGIC
|
||||
dont_appraise fsmagic=0x62656572
|
||||
dont_measure fsmagic=0x62656572
|
||||
# DEBUGFS_MAGIC
|
||||
dont_appraise fsmagic=0x64626720
|
||||
dont_measure fsmagic=0x64626720
|
||||
# TMPFS_MAGIC
|
||||
dont_appraise fsmagic=0x01021994
|
||||
dont_measure fsmagic=0x01021994
|
||||
# RAMFS_MAGIC
|
||||
dont_appraise fsmagic=0x858458f6
|
||||
dont_measure fsmagic=0x858458f6
|
||||
# DEVPTS_SUPER_MAGIC
|
||||
dont_appraise fsmagic=0x1cd1
|
||||
dont_measure fsmagic=0x1cd1
|
||||
# BIFMT
|
||||
dont_appraise fsmagic=0x42494e4d
|
||||
dont_measure fsmagic=0x42494e4d
|
||||
# SECURITYFS_MAGIC
|
||||
dont_appraise fsmagic=0x73636673
|
||||
dont_measure fsmagic=0x73636673
|
||||
# SELINUXFS_MAGIC
|
||||
dont_appraise fsmagic=0xf97cff8c
|
||||
dont_measure fsmagic=0xf97cff8c
|
||||
# NSFS_MAGIC (introduced in 3.19, see cd025f7 and e149ed2 in the upstream Linux kernel)
|
||||
dont_appraise fsmagic=0x6e736673
|
||||
dont_measure fsmagic=0x6e736673
|
||||
# SMACK_MAGIC
|
||||
dont_appraise fsmagic=0x43415d53
|
||||
dont_measure fsmagic=0x43415d53
|
||||
# CGROUP_SUPER_MAGIC
|
||||
dont_appraise fsmagic=0x27e0eb
|
||||
dont_measure fsmagic=0x27e0eb
|
||||
# CGROUP2_SUPER_MAGIC
|
||||
dont_appraise fsmagic=0x63677270
|
||||
dont_measure fsmagic=0x63677270
|
||||
# EFIVARFS_MAGIC
|
||||
dont_appraise fsmagic=0xde5e81e4
|
||||
dont_measure fsmagic=0xde5e81e4
|
||||
|
||||
# Special partition, no checking done.
|
||||
# dont_measure fsuuid=a11234...
|
||||
# dont_appraise fsuuid=a11243...
|
||||
|
||||
# Special immutable group.
|
||||
# appraise appraise_type=imasig func=FILE_CHECK mask=MAY_READ fgroup=200
|
||||
|
||||
# All executables must be signed - too strict, we need to
|
||||
# allow installing executables on the device.
|
||||
# appraise appraise_type=imasig func=FILE_MMAP mask=MAY_EXEC
|
||||
# appraise appraise_type=imasig func=BPRM_CHECK mask=MAY_EXEC
|
||||
|
||||
# Default rule. Would be needed also when other rules were added that
|
||||
# determine what to do in case of reading (mask=MAY_READ or
|
||||
# mask=MAY_EXEC) because otherwise writing does not update the file
|
||||
# hash.
|
||||
appraise
|
||||
measure
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
SUMMARY = "IMA sample hash policy"
|
||||
LICENSE = "MIT"
|
||||
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
|
||||
|
||||
SRC_URI = " \
|
||||
file://ima_policy_hashed \
|
||||
"
|
||||
|
||||
inherit features_check
|
||||
REQUIRED_DISTRO_FEATURES = "ima"
|
||||
|
||||
do_install () {
|
||||
install -d ${D}/${sysconfdir}/ima
|
||||
install ${WORKDIR}/ima_policy_hashed ${D}/${sysconfdir}/ima/ima-policy
|
||||
}
|
||||
|
||||
FILES:${PN} = "${sysconfdir}/ima"
|
||||
RDEPENDS:${PN} = "ima-evm-utils"
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
# Very simple policy demonstrating the systemd policy loading bug
|
||||
# (policy with one line works, two lines don't).
|
||||
dont_appraise fsmagic=0x9fa0
|
||||
dont_appraise fsmagic=0x62656572
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
SUMMARY = "IMA sample simple policy"
|
||||
LICENSE = "MIT"
|
||||
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
|
||||
|
||||
SRC_URI = " file://ima_policy_simple"
|
||||
|
||||
inherit features_check
|
||||
REQUIRED_DISTRO_FEATURES = "ima"
|
||||
|
||||
do_install () {
|
||||
install -d ${D}/${sysconfdir}/ima
|
||||
install ${WORKDIR}/ima_policy_simple ${D}/${sysconfdir}/ima/ima-policy
|
||||
}
|
||||
|
||||
FILES:${PN} = "${sysconfdir}/ima"
|
||||
RDEPENDS:${PN} = "ima-evm-utils"
|
||||
@@ -0,0 +1,49 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copied from ima-evm-utils.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# version 2 as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
GENKEY=ima.genkey
|
||||
CA=${1:-ima-local-ca.pem}
|
||||
CAKEY=${2:-ima-local-ca.priv}
|
||||
|
||||
cat << __EOF__ >$GENKEY
|
||||
[ req ]
|
||||
distinguished_name = req_distinguished_name
|
||||
prompt = no
|
||||
string_mask = utf8only
|
||||
x509_extensions = v3_usr
|
||||
|
||||
[ req_distinguished_name ]
|
||||
O = example.com
|
||||
CN = meta-intel-iot-security example signing key
|
||||
emailAddress = john.doe@example.com
|
||||
|
||||
[ v3_usr ]
|
||||
basicConstraints=critical,CA:FALSE
|
||||
#basicConstraints=CA:FALSE
|
||||
keyUsage=digitalSignature
|
||||
#keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
extendedKeyUsage=critical,codeSigning
|
||||
subjectKeyIdentifier=hash
|
||||
authorityKeyIdentifier=keyid
|
||||
#authorityKeyIdentifier=keyid,issuer
|
||||
__EOF__
|
||||
|
||||
openssl req -new -nodes -utf8 -sha256 -days 36500 -batch -config $GENKEY \
|
||||
-out csr_ima.pem -keyout privkey_ima.pem \
|
||||
-newkey ec -pkeyopt ec_paramgen_curve:prime256v1
|
||||
openssl x509 -req -in csr_ima.pem -days 36500 -extfile $GENKEY -extensions v3_usr \
|
||||
-CA $CA -CAkey $CAKEY -CAcreateserial \
|
||||
-outform DER -out x509_ima.der
|
||||
@@ -0,0 +1,42 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copied from ima-evm-utils.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# version 2 as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
GENKEY=ima-local-ca.genkey
|
||||
|
||||
cat << __EOF__ >$GENKEY
|
||||
[ req ]
|
||||
distinguished_name = req_distinguished_name
|
||||
prompt = no
|
||||
string_mask = utf8only
|
||||
x509_extensions = v3_ca
|
||||
|
||||
[ req_distinguished_name ]
|
||||
O = example.com
|
||||
CN = meta-intel-iot-security example certificate signing key
|
||||
emailAddress = john.doe@example.com
|
||||
|
||||
[ v3_ca ]
|
||||
basicConstraints=CA:TRUE
|
||||
subjectKeyIdentifier=hash
|
||||
authorityKeyIdentifier=keyid:always,issuer
|
||||
keyUsage = cRLSign, keyCertSign
|
||||
__EOF__
|
||||
|
||||
openssl req -new -x509 -utf8 -sha256 -days 36500 -batch -config $GENKEY \
|
||||
-newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \
|
||||
-outform DER -out ima-local-ca.x509 -keyout ima-local-ca.priv
|
||||
|
||||
openssl x509 -inform DER -in ima-local-ca.x509 -out ima-local-ca.pem
|
||||
Reference in New Issue
Block a user