ima-evm-utils - IMA/EVM signing utility
=========================================

Contents:

   1. Key and signature formats
   2. Key generation
   3. Initialization
   4. Signing


Key and signature formats
-------------------------

EVM support (v2) in latest version of the kernel adds the file system UUID to
the HMAC calculation. It is controlled by the CONFIG_EVM_HMAC_VERSION and
version 2 is enabled by default. In this version default UUID is included by
default. Custom value can be supplied via '--uuid=UUID' or '-uUUID' parameter
to the 'sign' command. To use old format HMAC format use '-' as a parameter.

Latest kernel got IMA/EVM support for using X509 certificates and asymmetric key
support for verifying digital signatures. This version uses x509 format by default.
Use '--rsa' or '-1' parameter to use old signature format and API.


Key generation
--------------

Generate private key in plain text format

    $ openssl genrsa -out privkey_evm.pem 1024

Generate encrypted private key

    $ openssl genrsa -des3 -out privkey_evm.pem 1024

Make encrypted private key from unencrypted

    $ openssl rsa -in /etc/keys/privkey_evm.pem -out privkey_evm_enc.pem -des3

Generate self-signed X509 certificate and private key for using kernel asymmetric
keys support

	$ openssl req -new -nodes -utf8 -sha1 -days 36500 -batch \
	      -x509 -config x509_evm.genkey \
	      -outform DER -out x509_evm.der -keyout privkey_evm.pem

Configuration file x509_evm.genkey:

	# Begining of the file
	[ req ]
	default_bits = 1024
	distinguished_name = req_distinguished_name
	prompt = no
	string_mask = utf8only
	x509_extensions = myexts

	[ req_distinguished_name ]
	O = Magrathea
	CN = Glacier signing key
	emailAddress = slartibartfast@magrathea.h2g2

	[ myexts ]
	basicConstraints=critical,CA:FALSE
	keyUsage=digitalSignature
	subjectKeyIdentifier=hash
	authorityKeyIdentifier=keyid
	# EOF


Get public key

    $ openssl rsa -pubout -in privkey_evm.pem -out pubkey_evm.pem

Copy keys to /etc/keys

    $ cp pubkey_evm.pem /etc/keys
    $ scp pubkey_evm.pem target:/etc/keys

or
    $ cp x509_evm.pem /etc/keys
    $ scp x509_evm.pem target:/etc/keys


Generation of EVM keys

    $ # create and save the kernel master key (user type)
    $ keyctl add user kmk "`dd if=/dev/urandom bs=1 count=32 2>/dev/null`" @u
    $ keyctl pipe `keyctl search @u user kmk` > /etc/keys/kmk
    $ # create the EVM encrypted key
    $ keyctl add encrypted evm-key "new user:kmk 32" @u
    $ keyctl pipe `keyctl search @u encrypted evm-key` >/etc/keys/evm-key


Initialization
--------------

IMA/EVM initialization should be normally done from initial RAM file system
before mounting root filesystem.

Here is an example script /etc/initramfs-tools/scripts/local-top/ima.sh

    # import EVM HMAC key
    keyctl clear @u
    cat /etc/keys/kmk | keyctl padd user kmk @u
    keyctl add encrypted evm-key "load `cat /etc/keys/evm-key`" @u

    # import IMA public key
    ima_id=`keyctl newring _ima @u`
    evmctl --rsa import /etc/keys/pubkey_evm.pem $ima_id

    # import EVM public key
    evm_id=`keyctl newring _evm @u`
    evmctl --rsa import /etc/keys/pubkey_evm.pem $evm_id

    # enable EVM
    echo "1" > /sys/kernel/security/evm


Import X509 certificate into the kernel keyring (since kernel 3.9?)

    $ evmctl import /etc/keys/x509_evm.der `keyctl search @u keyring _ima`
    $ evmctl import /etc/keys/x509_evm.der `keyctl search @u keyring _evm`


Signing
-------

Default public key: /etc/keys/pubkey_evm.pem
Default private key: /etc/keys/privkey_evm.pem
Default X509 certificate: /etc/keys/x509_evm.der

Signing for using old RSA format is done using '-1' or '--rsa' parameter.
Signing for using old EVM HMAC format is done using '-u-' or '--uuid=-' parameter.

Sign file with EVM signature and use hash value for IMA - common case

    $ evmctl sign [-u] [-1] --imahash test.txt

Sign file with both IMA and EVM signatures - for immutable files

    $ evmctl sign [-u] [-1] --imasig test.txt

Sign file with IMA signature - for immutable files

    $ evmctl ima_sign [-1] test.txt

Label whole filesystem with EVM signatures

    $ find / \( -fstype rootfs -o -fstype ext4 \) -exec evmctl sign [-u] [-1] --imahash '{}' \;

Label filesystem in fix mode - kernel sets correct values to IMA and EVM xattrs

    $ find / \( -fstype rootfs -o -fstype ext4 \) -exec sh -c "< '{}'" \;

