Security:IntegrityMeasurement/Preparing Tizen image protected by IMA/EVM
- 1 HOWTO: Preparing Tizen image protected by IMA/EVM
HOWTO: Preparing Tizen image protected by IMA/EVM
This instruction describes how to prepare Tizen image protected by IMA/EVM. Links for the newest tizen.org sources prepared to IMA/EVM (kernel, ima-evm-utils, etc.) you will find in "Development" section.
1. Install needed tools on your host machine
You will need:
You will probably need to build ima-evm-utils from sources. (Keyutils package is available for Ubuntu.) Ima-evm-utils mainline source can be found on: http://sourceforge.net/p/linux-ima/ima-evm-utils/ci/master/tree/. You can also use ima-evm-utils Tizen.org source.
2. Generate keys/certificates
Two keys/certificates will be needed:
- Kernel built-in self-signed CA x509 certificate.
- IMA x509 certificate - signed by the kernel built-in certificate.
To generate key 1. use script ima-gen-local-ca.sh:
#!/bin/sh GENKEY=ima-local-ca.genkey cat << __EOF__ >$GENKEY [ req ] default_bits = 2048 distinguished_name = req_distinguished_name prompt = no string_mask = utf8only x509_extensions = v3_ca [ req_distinguished_name ] O = IMA-CA CN = IMA/EVM certificate signing key emailAddress = ca@ima-ca [ v3_ca ] basicConstraints=CA:TRUE subjectKeyIdentifier=hash authorityKeyIdentifier=keyid:always,issuer # keyUsage = cRLSign, keyCertSign __EOF__ openssl req -new -x509 -utf8 -sha1 -days 3650 -batch -config $GENKEY \ -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
This script should generate ima-local-ca.x509 file - this file should be copied to main directory with tizen kernel sources. Name of the file isn't important - the only thing about the file name is: it have to have .x509 extension.
To generate key 2. use script:
#!/bin/sh GENKEY=ima.genkey cat << __EOF__ >$GENKEY [ req ] default_bits = 1024 distinguished_name = req_distinguished_name prompt = no string_mask = utf8only x509_extensions = v3_usr [ req_distinguished_name ] O = `hostname` CN = `whoami` signing key emailAddress = `whoami`@`hostname` [ v3_usr ] basicConstraints=critical,CA:FALSE #basicConstraints=CA:FALSE keyUsage=digitalSignature #keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectKeyIdentifier=hash authorityKeyIdentifier=keyid #authorityKeyIdentifier=keyid,issuer __EOF__ openssl req -new -nodes -utf8 -sha1 -days 365 -batch -config $GENKEY \ -out csr_ima.pem -keyout privkey_ima.pem openssl x509 -req -in csr_ima.pem -days 365 -extfile $GENKEY -extensions v3_usr \ -CA ima-local-ca.pem -CAkey ima-local-ca.priv -CAcreateserial \ -outform DER -out x509_ima.der
This script will generate a few files. Two files are important for you: x509_ima.der - this file contains certificate signed by key 1. privkey_ima.pem - private key for the x509_ima.der, this key will be used to sign files on the image. We leave these keys now. We will need it later.
3. Configuring and building the kernel
Build the kernel with these options:
SYSTEM_TRUSTED_KEYRING=y CONFIG_KEYS=y CONFIG_TRUSTED_KEYS=y CONFIG_ENCRYPTED_KEYS=y CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_SECURITY=y CONFIG_SECURITYFS=y CONFIG_SECURITY_SMACK=y CONFIG_INTEGRITY=y CONFIG_INTEGRITY_SIGNATURE=y CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y CONFIG_INTEGRITY_AUDIT=y CONFIG_INTEGRITY_LOAD_KEYS=y CONFIG_INTEGRITY_FILE_READ=y CONFIG_INTEGRITY_LOAD_X509=y CONFIG_INTEGRITY_TRUSTED_KEYRING=y CONFIG_IMA=y CONFIG_IMA_MEASURE_PCR_IDX=10 CONFIG_IMA_LSM_RULES=y CONFIG_IMA_NG_TEMPLATE=y CONFIG_IMA_DEFAULT_TEMPLATE="ima-ng" CONFIG_IMA_DEFAULT_HASH_SHA1=y CONFIG_IMA_DEFAULT_HASH="sha1" CONFIG_IMA_APPRAISE=y CONFIG_IMA_TRUSTED_KEYRING=y CONFIG_IMA_LOAD_X509=y CONFIG_IMA_X509_PATH="/etc/ima/x509_ima.der" CONFIG_IMA_POLICY_LOADER=y CONFIG_IMA_POLICY_REPLACEABLE=y CONFIG_IMA_LOAD_POLICY=y CONFIG_IMA_POLICY_PATH="/etc/ima/ima_policy" CONFIG_IMA_READABLE_POLICY_INTERFACE=y CONFIG_IMA_STATE_INTERFACE=y CONFIG_EVM=y CONFIG_EVM_ATTR_FSUUID=y # CONFIG_EVM_EXTRA_SMACK_XATTRS is not set # CONFIG_EVM_LOAD_KEY=y CONFIG_EVM_KEY_PATH="/etc/ima/evm-key" CONFIG_EVM_KMK_PATH="/etc/ima/evm-kmk" CONFIG_EVM_TRUSTED_KEYRING=y CONFIG_EVM_LOAD_X509=y CONFIG_EVM_X509_PATH="/etc/ima/x509_evm.der" CONFIG_EVM_STATE_INTERFACE=y CONFIG_CRYPTO=y
These option have to be set as above - although you can configure the path as you want. You can also check other IMA/EVM related options and enable if you'd like. Build the kernel. In build log you should see:
X.509 certificate list changed CERTS kernel/x509_certificate_list - Including cert ima-local-ca.x509
Which means that you Root CA was included in kernel.
4. Preparing the platform image
Let assume that you've got a Tizen platform image in .img format (e.g. tizen-platform.img). On the image these packages should be installed:
- ima-evm-reference-utils (as a reference solution - you should replace these tools by your own, or remove it)
To prepare the platform image you need to do a few things. First you need to choose your integrity policy - policy that describes for which files to check the integrity. Policy rules can be written based on the various criteria like:
- using function for opening file (read, exec, etc),
- mask (file permission, e.g. "may exec"),
- type of file system (fs magic),
- current process UID,
- file owner (UID),
- filesystem ID (FSUUID),
One policy rule descibes one of actions:
- don't measure,
- don't appraise.
The default policy (build-in into the kernel, file: security/integrity/ima/ima_policy.c) look like this:
DONT_MEASURE fsmagic=PROC_SUPER_MAGIC DONT_MEASURE fsmagic=SYSFS_MAGIC DONT_MEASURE fsmagic=DEBUGFS_MAGIC DONT_MEASURE fsmagic=TMPFS_MAGIC DONT_MEASURE fsmagic=DEVPTS_SUPER_MAGIC DONT_MEASURE fsmagic=BINFMTFS_MAGIC DONT_MEASURE fsmagic=SECURITYFS_MAGIC DONT_MEASURE fsmagic=SELINUX_MAGIC MEASURE func=MMAP_CHECK mask=MAY_EXEC MEASURE func=BPRM_CHECK mask=MAY_EXEC MEASURE func=FILE_CHECK mask=MAY_READ uid=GLOBAL_ROOT_UID, MEASURE func=MODULE_CHECK MEASURE func=FIRMWARE_CHECK DONT_APPRAISE fsmagic=PROC_SUPER_MAGIC DONT_APPRAISE fsmagic=SYSFS_MAGIC DONT_APPRAISE fsmagic=DEBUGFS_MAGIC DONT_APPRAISE fsmagic=TMPFS_MAGIC DONT_APPRAISE fsmagic=RAMFS_MAGIC DONT_APPRAISE fsmagic=DEVPTS_SUPER_MAGIC DONT_APPRAISE fsmagic=BINFMTFS_MAGIC DONT_APPRAISE fsmagic=SECURITYFS_MAGIC DONT_APPRAISE fsmagic=SELINUX_MAGIC DONT_APPRAISE fsmagic=CGROUP_SUPER_MAGIC APPRAISE fowner=GLOBAL_ROOT_UID
You can modify kernel source code, but it isn't necessary. Let's keep it as it is.
We can write our own policy (modifying the original):
dont_measure fsmagic=0x9fa0 dont_measure fsmagic=0x62656572 dont_measure fsmagic=0x64626720 dont_measure fsmagic=0x1021994 dont_measure fsmagic=0x1cd1 dont_measure fsmagic=0x42494e4d dont_measure fsmagic=0x73636673 dont_measure fsmagic=0xf97cff8c measure func=MMAP_CHECK mask=MAY_EXEC measure func=BPRM_CHECK mask=MAY_EXEC measure func=FILE_CHECK mask=MAY_READ uid=0 measure func=MODULE_CHECK measure path=vda:/usr/lib measure path=vda:/usr/bin measure path=vda:/usr/sbin measure path=vda:/lib measure path=vda:/bin measure path=vda:/sbin dont_appraise fsmagic=0x9fa0 dont_appraise fsmagic=0x62656572 dont_appraise fsmagic=0x64626720 dont_appraise fsmagic=0x1021994 dont_appraise fsmagic=0x858458f6 dont_appraise fsmagic=0x1cd1 dont_appraise fsmagic=0x42494e4d dont_appraise fsmagic=0x73636673 dont_appraise fsmagic=0xf97cff8c dont_appraise fsmagic=0x27e0eb appraise path=vda:/usr/lib appraise path=vda:/usr/bin appraise path=vda:/usr/sbin appraise path=vda:/lib appraise path=vda:/bin appraise path=vda:/sbin
Notice that all FSMAGIC defines are replaced with numbers. This isn't necessary, but easier for us to use policy in this shape (later you'll see why). Save this policy file on your host machine (e.g. in /home/user/policy). To load the policy into the kernel in runtime the policy must be provided together with signature. To generate signature you need the same key which you've used to sign the files on the image. To generate signature use:
evmctl ima_sign -f -k /path/to/privkey_ima.pem /home/user/policy
A new file will be created - this is the signature:
Now we need to sign the files that are included in policy and have set "appraise" action (all files in locations: /root, /usr/lib, etc.). Your should mount tizen platorm image on your host machine. You can use this command:
sudo mount -w -o loop tizen-image.img /home/user/img
Now you need to generate signature for files. For this you will need IMA private key (privkey_ima.pem). This may take a while.
sudo evmctl -r sign -s -k /path/to/privkey_ima.pem /home/user/img/root sudo evmctl -r sign -s -k /path/to/privkey_ima.pem /home/user/img/usr/lib sudo evmctl -r sign -s -k /path/to/privkey_ima.pem /home/user/img/usr/bin sudo evmctl -r sign -s -k /path/to/privkey_ima.pem /home/user/img/usr/sbin sudo evmctl -r sign -s -k /path/to/privkey_ima.pem /home/user/img/lib sudo evmctl -r sign -s -k /path/to/privkey_ima.pem /home/user/img/bin sudo evmctl -r sign -s -k /path/to/privkey_ima.pem /home/user/img/sbin
You can check if generating signatures succed, e.g.:
getfattr -d -m . /home/user/img/usr/bin/bash # file: /home/user/img/usr/bin/bash security.SMACK64="_" security.evm=0sAwICAYjv9ACAbW7Wad5Qdg+RMfcDl9Oq4lq+lu3YZJM8Uzvpcz97j7g62YFzB8PMjWWUty5Txy02TQWLHSv7CDJCCukcVxdjm69aQnh0Hfn2//RdhBSoCSlNkVNiySOcf1jOnUpSoV4Ducp4UWDw/GpvOimNpUbI8vSbv1gWkuvwMXYxQzTzzkM= security.ima=0sAwICAYjv9ACAHFarFFhNNuvR+v12AKiCmxfZdq5gNq2yZhCuSnb0cTgHl0omVqRk2vvSCPBthOf5OXmUlI+ncnqYBo/0lmW2RnJwROBLNKl659OqNJWNPuJexhTxrzcOm1mxzgby5bI/jgjvbmcXvbLjPWcC+OU+g0pa+Yl9zhG6Jdgc2wjqowg=
If you see the security.ima and security.evm attributes then everthing is OK. You can also verify the signature using evmctl.
Applaying your policy into the image.
When kernel starts it looks for policy in /etc/ima/ima_policy (this is default path - you can configure it in kernel config). So the signature should be in /etc/ima/ima_policy.sig. If kernel will find the policy there and if the signature is correct it replace the default policy at startup. So you can copy you own policy together with signature to the mounted platform image.
Copy x509 certificate.
Last thing we need to do on the image is to copy IMA x509 certificate to the image in the location set in kernel config. The dafault path is /etc/ima/x509_ima.der. This is the cerficate genrated in step 2. You can use the same certificate to EVM So do:
cp /path/to/x509_ima.der /home/user/img/etc/ima/x509_ima.der cp /path/to/x509_ima.der /home/user/img/etc/ima/x509_evm.der
Using the same certificate for IMA and EVM should have no bad consequences in this case. But in general case you should consider generate separate key for EVM - use the same script which you've used for generate IMA certificate.
Unmnount the image:
sodu umount /home/user/img
You can also consider labeling file system directly on the device - in IMA/EVM fix mode.
5. Running the system
To make IMA/EVM working you need to pass a few params to the kernel:
rootflags= i_version ima_tcb ima_appraise_tcb ima_template_fmt=d-ng|n-ng|status
If you did everthing correctly, then system should run properly. In case of any problem you can try to debug the system with:
rootflags= i_version ima_tcb ima_appraise=fix ima_appraise_tcb ima_template_fmt=d-ng|n-ng|status evm=fix
This will run the system with IMA/EVM fix mode.
The system is runnig. What next? In general that's all. If system is running in enforce mode then it means that you've done evething correctly. You may want to check or change a few things, e.g.: - check currently policy - update policy - check state of IMA or EVM - change state of IMA or EVM
All these things can be done by reading/writing kernel interfaces. All integrity-related interfaces are in
To check IMA state
You need to know what these number means - you can check it above (or in kernel souce ima.h and evm.h). To change IMA state do "disabled" write to the kernel interface:
echo "0 > /sys/kernel/security/ima/ima_state.
The same with EVM state:
cat /sys/kernel/security/evm echo "0" > /sys/kernel/security/evm
To to read current policy you can use:
Here you get FS magic-numbers instead of names. You can use the same format to load policy to the kernel, but remember - policy have to be signed to load it into the kernel (you know how to sign the policy from point 4.). To load policy type:
echo "/path/to/some_policy" > /sys/kernel/security/ima/policy
in this case signature should be located in:
Remeber to use full path - using reletive path will not work.
You can check list of files that have been cheked from last boot:
6. Reference tools.
In reference tools you can find: - service (ima-evm-server) - console tool (im-console)
These tools are to demonstrate some IMA/EVM features. First run the service:
Then you can use the im-console tool. Run the help to get more informations: