Hello community,

here is the log from the commit of package ima-evm-utils for openSUSE:Factory 
checked in at 2018-03-20 21:59:04
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ima-evm-utils (Old)
 and      /work/SRC/openSUSE:Factory/.ima-evm-utils.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ima-evm-utils"

Tue Mar 20 21:59:04 2018 rev:13 rq:587839 version:1.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/ima-evm-utils/ima-evm-utils.changes      
2017-11-27 22:18:57.293450564 +0100
+++ /work/SRC/openSUSE:Factory/.ima-evm-utils.new/ima-evm-utils.changes 
2018-03-20 21:59:29.147570643 +0100
@@ -1,0 +2,16 @@
+Fri Mar 16 09:23:01 UTC 2018 - [email protected]
+
+- Update to version 1.1
+  * Support the new openssl 1.1 api
+  * Support for validating multiple pcrs
+  * Verify the measurement list signature based on the list digest
+  * Verify the "ima-sig" measurement list using multiple keys
+  * Fixed parsing the measurement template data field length
+  * Portable & immutable EVM signatures (new format)
+  * Multiple fixes that have been lingering in the next branch. Some
+    are for experimental features that are not yet supported in the
+    kernel.
+- Drop ima-evm-utils-openssl1.patch (not needed any more as IMA got
+  backward compatible support for openssl 1.1).
+
+-------------------------------------------------------------------

Old:
----
  ima-evm-utils-1.0.tar.gz
  ima-evm-utils-openssl1.patch

New:
----
  ima-evm-utils-1.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ima-evm-utils.spec ++++++
--- /var/tmp/diff_new_pack.gXbrIK/_old  2018-03-20 21:59:29.875544433 +0100
+++ /var/tmp/diff_new_pack.gXbrIK/_new  2018-03-20 21:59:29.879544289 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package ima-evm-utils
 #
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -19,15 +19,14 @@
 %define sover 0
 %define libname libimaevm%{sover}
 Name:           ima-evm-utils
-Version:        1.0
+Version:        1.1
 Release:        0
 Summary:        IMA/EVM control utility
-License:        LGPL-2.1+
+License:        LGPL-2.1-or-later
 Group:          System/Base
 Url:            http://sourceforge.net/projects/linux-ima/
 Source0:        
http://downloads.sourceforge.net/project/linux-ima/ima-evm-utils/%{name}-%{version}.tar.gz
 Patch2:         ima-evm-utils-fix-docbook-xsl-directory.patch
-Patch3:         ima-evm-utils-openssl1.patch
 BuildRequires:  asciidoc
 BuildRequires:  autoconf
 BuildRequires:  automake
@@ -76,9 +75,6 @@
 %if 0%{?suse_version} >= 1315
 %patch2 -p1
 %endif
-if pkg-config --atleast-version=1.1 openssl; then
-%patch3 -p1
-fi
 
 %build
 autoreconf -fiv

++++++ ima-evm-utils-1.0.tar.gz -> ima-evm-utils-1.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ima-evm-utils-1.0/ChangeLog 
new/ima-evm-utils-1.1/ChangeLog
--- old/ima-evm-utils-1.0/ChangeLog     2015-07-30 20:28:53.000000000 +0200
+++ new/ima-evm-utils-1.1/ChangeLog     2018-02-15 14:02:19.000000000 +0100
@@ -1,3 +1,16 @@
+2018-01-28  Mimi Zohar <[email protected]>
+
+       version 1.1
+       * Support the new openssl 1.1 api
+       * Support for validating multiple pcrs
+       * Verify the measurement list signature based on the list digest
+       * Verify the "ima-sig" measurement list using multiple keys
+       * Fixed parsing the measurement template data field length
+       * Portable & immutable EVM signatures (new format)
+       * Multiple fixes that have been lingering in the next branch. Some
+         are for experimental features that are not yet supported in the
+         kernel.
+
 2014-07-30  Dmitry Kasatkin <[email protected]>
 
        version 1.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ima-evm-utils-1.0/README new/ima-evm-utils-1.1/README
--- old/ima-evm-utils-1.0/README        2015-07-30 20:28:53.000000000 +0200
+++ new/ima-evm-utils-1.1/README        2018-02-15 14:02:19.000000000 +0100
@@ -26,12 +26,12 @@
  --version
  help <command>
  import [--rsa] pubkey keyring
- sign [-r] [--imahash | --imasig ] [--key key] [--pass password] file
+ sign [-r] [--imahash | --imasig ] [--portable] [--key key] [--pass password] 
file
  verify file
  ima_sign [--sigfile] [--key key] [--pass password] file
  ima_verify file
  ima_hash file
- ima_measurement file
+ ima_measurement [--key "key1, key2, ..."] [--list] file
  ima_fix [-t fdsxm] path
  sign_hash [--key key] [--pass password]
  hmac [--imahash | --imasig ] file
@@ -46,6 +46,7 @@
   -f, --sigfile      store IMA signature in .sig file instead of xattr
       --rsa          use RSA key type and signing scheme v1
   -k, --key          path to signing key (default: 
/etc/keys/{privkey,pubkey}_evm.pem)
+  -o, --portable     generate portable EVM signatures
   -p, --pass         password for encrypted signing key
   -r, --recursive    recurse into directories (sign)
   -t, --type         file types to fix 'fdsxm' (f: file, d: directory, s: 
block/char/symlink)
@@ -95,7 +96,8 @@
 filesystem UUID into HMAC and enabled by default. Therefore evmctl also 
includes
 fsuuid by default. Providing '--uuid' option without parameter allows to 
disable
 usage of fs uuid. Providing '--uuid=UUID' option with parameter allows to use
-custom UUID.
+custom UUID. Providing the '--portable' option will disable usage of the fs 
uuid
+and also the inode number and generation.
 
 Kernel configuration option CONFIG_EVM_EXTRA_SMACK_XATTRS controls whether to
 include additional SMACK extended attributes into HMAC. They are following:
@@ -142,7 +144,7 @@
     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 add encrypted evm-key "new user:kmk 64" @u
     keyctl pipe `keyctl search @u encrypted evm-key` >/etc/keys/evm-key
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ima-evm-utils-1.0/build-static.sh 
new/ima-evm-utils-1.1/build-static.sh
--- old/ima-evm-utils-1.0/build-static.sh       1970-01-01 01:00:00.000000000 
+0100
+++ new/ima-evm-utils-1.1/build-static.sh       2018-02-15 14:02:19.000000000 
+0100
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+gcc -static -o evmctl.static -include config.h src/evmctl.c src/libimaevm.c 
-lcrypto -lkeyutils -ldl
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ima-evm-utils-1.0/configure.ac 
new/ima-evm-utils-1.1/configure.ac
--- old/ima-evm-utils-1.0/configure.ac  2015-07-30 20:28:53.000000000 +0200
+++ new/ima-evm-utils-1.1/configure.ac  2018-02-15 14:02:19.000000000 +0100
@@ -1,7 +1,7 @@
 # autoconf script
 
 AC_PREREQ([2.65])
-AC_INIT(ima-evm-utils, 1.0, [email protected])
+AC_INIT(ima-evm-utils, 1.1, [email protected])
 AM_INIT_AUTOMAKE
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_MACRO_DIR([m4])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ima-evm-utils-1.0/packaging/ima-evm-utils.spec 
new/ima-evm-utils-1.1/packaging/ima-evm-utils.spec
--- old/ima-evm-utils-1.0/packaging/ima-evm-utils.spec  2015-07-30 
20:28:53.000000000 +0200
+++ new/ima-evm-utils-1.1/packaging/ima-evm-utils.spec  2018-02-15 
14:02:19.000000000 +0100
@@ -1,5 +1,5 @@
 Name:          ima-evm-utils
-Version:       1.0
+Version:       1.1
 Release:       1%{?dist}
 Summary:       ima-evm-utils - IMA/EVM control utility
 Group:         System/Libraries
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ima-evm-utils-1.0/src/evmctl.c 
new/ima-evm-utils-1.1/src/evmctl.c
--- old/ima-evm-utils-1.0/src/evmctl.c  2015-07-30 20:28:53.000000000 +0200
+++ new/ima-evm-utils-1.1/src/evmctl.c  2018-02-15 14:02:19.000000000 +0100
@@ -104,15 +104,26 @@
 static int digsig;
 static int sigfile;
 static char *uuid_str;
+static char *ino_str;
+static char *uid_str;
+static char *gid_str;
+static char *mode_str;
+static char *generation_str;
+static char *caps_str;
+static char *ima_str;
+static char *selinux_str;
 static char *search_type;
+static int measurement_list;
 static int recursive;
 static int msize;
 static dev_t fs_dev;
 static bool evm_immutable;
+static bool evm_portable;
 
-#define HMAC_FLAG_UUID                 0x0001
-#define HMAC_FLAG_UUID_SET             0x0002
-static unsigned long hmac_flags = HMAC_FLAG_UUID;
+#define HMAC_FLAG_NO_UUID      0x0001
+#define HMAC_FLAG_CAPS_SET     0x0002
+
+static unsigned long hmac_flags;
 
 typedef int (*find_cb_t)(const char *path);
 static int find(const char *path, int dts, find_cb_t func);
@@ -200,7 +211,7 @@
        return -1;
 }
 
-static int hex2bin(uint8_t *dst, const char *src, size_t count)
+static int hex2bin(void *dst, const char *src, size_t count)
 {
        int hi, lo;
 
@@ -214,7 +225,7 @@
                if ((hi < 0) || (lo < 0))
                        return -1;
 
-               *dst++ = (hi << 4) | lo;
+               *(uint8_t *)dst++ = (hi << 4) | lo;
        }
        return 0;
 }
@@ -275,7 +286,7 @@
        FILE *fp;
        size_t len;
 
-       if (hmac_flags & HMAC_FLAG_UUID_SET)
+       if (uuid_str)
                return pack_uuid(uuid_str, uuid);
 
        dev = st->st_dev;
@@ -305,7 +316,7 @@
        struct stat st;
        int err;
        uint32_t generation = 0;
-       EVP_MD_CTX ctx;
+       EVP_MD_CTX *pctx;
        unsigned int mdlen;
        char **xattrname;
        char xattr_value[1024];
@@ -314,16 +325,33 @@
        char uuid[16];
        struct h_misc_64 hmac_misc;
        int hmac_size;
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+       EVP_MD_CTX ctx;
+       pctx = &ctx;
+#else
+       pctx = EVP_MD_CTX_new();
+#endif
 
        if (lstat(file, &st)) {
                log_err("Failed to stat: %s\n", file);
                return -1;
        }
 
+       if (generation_str)
+               generation = strtoul(generation_str, NULL, 10);
+       if (ino_str)
+               st.st_ino = strtoul(ino_str, NULL, 10);
+       if (uid_str)
+               st.st_uid = strtoul(uid_str, NULL, 10);
+       if (gid_str)
+               st.st_gid = strtoul(gid_str, NULL, 10);
+       if (mode_str)
+               st.st_mode = strtoul(mode_str, NULL, 10);
+
        if (!evm_immutable) {
-               if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) {
-                       /* we cannot at the momement to get generation of 
special files..
-                        * kernel API does not support it */
+               if ((S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) && 
!generation_str) {
+                       /* we cannot at the momement to get generation of
+                          special files kernel API does not support it */
                        int fd = open(file, 0);
 
                        if (fd < 0) {
@@ -332,6 +360,7 @@
                        }
                        if (ioctl(fd, FS_IOC_GETVERSION, &generation)) {
                                log_err("ioctl() failed\n");
+                               close(fd);
                                return -1;
                        }
                        close(fd);
@@ -345,26 +374,39 @@
                return -1;
        }
 
-       err = EVP_DigestInit(&ctx, EVP_sha1());
+       err = EVP_DigestInit(pctx, EVP_sha1());
        if (!err) {
                log_err("EVP_DigestInit() failed\n");
                return 1;
        }
 
        for (xattrname = evm_config_xattrnames; *xattrname != NULL; 
xattrname++) {
-               err = lgetxattr(file, *xattrname, xattr_value, 
sizeof(xattr_value));
-               if (err < 0) {
-                       log_info("no xattr: %s\n", *xattrname);
-                       continue;
-               }
-               if (!find_xattr(list, list_size, *xattrname)) {
-                       log_info("skipping xattr: %s\n", *xattrname);
-                       continue;
+               if (!strcmp(*xattrname, XATTR_NAME_SELINUX) && selinux_str) {
+                       strcpy(xattr_value, selinux_str);
+                       err = strlen(selinux_str) + 1;
+               } else if (!strcmp(*xattrname, XATTR_NAME_IMA) && ima_str) {
+                       hex2bin(xattr_value, ima_str, strlen(ima_str) / 2);
+                       err = strlen(ima_str) / 2;
+               } else if (!strcmp(*xattrname, XATTR_NAME_CAPS) && (hmac_flags 
& HMAC_FLAG_CAPS_SET)) {
+                       if (!caps_str)
+                               continue;
+                       strcpy(xattr_value, caps_str);
+                       err = strlen(caps_str);
+               } else {
+                       err = lgetxattr(file, *xattrname, xattr_value, 
sizeof(xattr_value));
+                       if (err < 0) {
+                               log_info("no xattr: %s\n", *xattrname);
+                               continue;
+                       }
+                       if (!find_xattr(list, list_size, *xattrname)) {
+                               log_info("skipping xattr: %s\n", *xattrname);
+                               continue;
+                       }
                }
                /*log_debug("name: %s, value: %s, size: %d\n", *xattrname, 
xattr_value, err);*/
                log_info("name: %s, size: %d\n", *xattrname, err);
                log_debug_dump(xattr_value, err);
-               err = EVP_DigestUpdate(&ctx, xattr_value, err);
+               err = EVP_DigestUpdate(pctx, xattr_value, err);
                if (!err) {
                        log_err("EVP_DigestUpdate() failed\n");
                        return 1;
@@ -384,8 +426,10 @@
                struct h_misc *hmac = (struct h_misc *)&hmac_misc;
 
                hmac_size = sizeof(*hmac);
-               hmac->ino = st.st_ino;
-               hmac->generation = generation;
+               if (!evm_portable) {
+                       hmac->ino = st.st_ino;
+                       hmac->generation = generation;
+               }
                hmac->uid = st.st_uid;
                hmac->gid = st.st_gid;
                hmac->mode = st.st_mode;
@@ -393,8 +437,10 @@
                struct h_misc_64 *hmac = (struct h_misc_64 *)&hmac_misc;
 
                hmac_size = sizeof(*hmac);
-               hmac->ino = st.st_ino;
-               hmac->generation = generation;
+               if (!evm_portable) {
+                       hmac->ino = st.st_ino;
+                       hmac->generation = generation;
+               }
                hmac->uid = st.st_uid;
                hmac->gid = st.st_gid;
                hmac->mode = st.st_mode;
@@ -402,8 +448,10 @@
                struct h_misc_32 *hmac = (struct h_misc_32 *)&hmac_misc;
 
                hmac_size = sizeof(*hmac);
-               hmac->ino = st.st_ino;
-               hmac->generation = generation;
+               if (!evm_portable) {
+                       hmac->ino = st.st_ino;
+                       hmac->generation = generation;
+               }
                hmac->uid = st.st_uid;
                hmac->gid = st.st_gid;
                hmac->mode = st.st_mode;
@@ -412,25 +460,26 @@
        log_debug("hmac_misc (%d): ", hmac_size);
        log_debug_dump(&hmac_misc, hmac_size);
 
-       err = EVP_DigestUpdate(&ctx, &hmac_misc, hmac_size);
+       err = EVP_DigestUpdate(pctx, &hmac_misc, hmac_size);
        if (!err) {
                log_err("EVP_DigestUpdate() failed\n");
                return 1;
        }
 
-       if (!evm_immutable && (hmac_flags & HMAC_FLAG_UUID)) {
+       if (!evm_immutable && !evm_portable &&
+           !(hmac_flags & HMAC_FLAG_NO_UUID)) {
                err = get_uuid(&st, uuid);
                if (err)
                        return -1;
 
-               err = EVP_DigestUpdate(&ctx, (const unsigned char *)uuid, 
sizeof(uuid));
+               err = EVP_DigestUpdate(pctx, (const unsigned char *)uuid, 
sizeof(uuid));
                if (!err) {
                        log_err("EVP_DigestUpdate() failed\n");
                        return 1;
                }
        }
 
-       err = EVP_DigestFinal(&ctx, hash, &mdlen);
+       err = EVP_DigestFinal(pctx, hash, &mdlen);
        if (!err) {
                log_err("EVP_DigestFinal() failed\n");
                return 1;
@@ -455,7 +504,10 @@
 
        /* add header */
        len++;
-       sig[0] = EVM_IMA_XATTR_DIGSIG;
+       if (evm_portable)
+               sig[0] = EVM_XATTR_PORTABLE_DIGSIG;
+       else
+               sig[0] = EVM_IMA_XATTR_DIGSIG;
 
        if (evm_immutable)
                sig[1] = 3; /* immutable signature version */
@@ -713,12 +765,13 @@
                return -1;
        }
 
-       return verify_hash(hash, sizeof(hash), sig + 1, len - 1);
+       return verify_hash(file, hash, sizeof(hash), sig + 1, len - 1);
 }
 
 static int cmd_verify_evm(struct command *cmd)
 {
        char *file = g_argv[optind++];
+       int err;
 
        if (!file) {
                log_err("Parameters missing\n");
@@ -726,7 +779,10 @@
                return -1;
        }
 
-       return verify_evm(file);
+       err = verify_evm(file);
+       if (!err && params.verbose >= LOG_INFO)
+               log_info("%s: verification is OK\n", file);
+       return err;
 }
 
 static int verify_ima(const char *file)
@@ -734,35 +790,69 @@
        unsigned char sig[1024];
        int len;
 
-       if (xattr) {
-               len = lgetxattr(file, "security.ima", sig, sizeof(sig));
-               if (len < 0) {
-                       log_err("getxattr failed: %s\n", file);
-                       return len;
-               }
-       }
-
        if (sigfile) {
                void *tmp = file2bin(file, "sig", &len);
 
                memcpy(sig, tmp, len);
                free(tmp);
+       } else {
+               len = lgetxattr(file, "security.ima", sig, sizeof(sig));
+               if (len < 0) {
+                       log_err("getxattr failed: %s\n", file);
+                       return len;
+               }
        }
 
-       return ima_verify_signature(file, sig, len);
+       return ima_verify_signature(file, sig, len, NULL, 0);
 }
 
 static int cmd_verify_ima(struct command *cmd)
 {
        char *file = g_argv[optind++];
+       int err;
 
+       errno = 0;
        if (!file) {
                log_err("Parameters missing\n");
                print_usage(cmd);
                return -1;
        }
 
-       return verify_ima(file);
+       err = verify_ima(file);
+       if (!err && params.verbose >= LOG_INFO)
+               log_info("%s: verification is OK\n", file);
+       return err;
+}
+
+static int cmd_convert(struct command *cmd)
+{
+       char *inkey;
+       unsigned char _pub[1024], *pub = _pub;
+       int len, err = 0;
+       char name[20];
+       uint8_t keyid[8];
+       RSA *key;
+
+       params.x509 = 0;
+
+       inkey = g_argv[optind++];
+       if (!inkey) {
+               inkey = params.x509 ? "/etc/keys/x509_evm.der" :
+                                     "/etc/keys/pubkey_evm.pem";
+       }
+
+       key = read_pub_key(inkey, params.x509);
+       if (!key)
+               return 1;
+
+       len = key2bin(key, pub);
+       calc_keyid_v1(keyid, name, pub, len);
+
+       bin2file(inkey, "bin", pub, len);
+       bin2file(inkey, "keyid", (const unsigned char *)name, strlen(name));
+
+       RSA_free(key);
+       return err;
 }
 
 static int cmd_import(struct command *cmd)
@@ -837,6 +927,42 @@
        return err;
 }
 
+static int setxattr_ima(const char *file, char *sig_file)
+{
+       unsigned char *sig;
+       int len, err;
+
+       if (sig_file)
+               sig = file2bin(sig_file, NULL, &len);
+       else
+               sig = file2bin(file, "sig", &len);
+       if (!sig)
+               return 0;
+
+       err = lsetxattr(file, "security.ima", sig, len, 0);
+       if (err < 0)
+               log_err("setxattr failed: %s\n", file);
+       free(sig);
+       return err;
+}
+
+static int cmd_setxattr_ima(struct command *cmd)
+{
+       char *file, *sig = NULL;
+
+       if (sigfile)
+               sig = g_argv[optind++];
+       file =  g_argv[optind++];
+
+       if (!file) {
+               log_err("Parameters missing\n");
+               print_usage(cmd);
+               return -1;
+       }
+
+       return setxattr_ima(file, sig);
+}
+
 #define MAX_KEY_SIZE 128
 
 static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char 
*hash)
@@ -844,7 +970,7 @@
        struct stat st;
        int err = -1;
        uint32_t generation = 0;
-       HMAC_CTX ctx;
+       HMAC_CTX *pctx;
        unsigned int mdlen;
        char **xattrname;
        unsigned char xattr_value[1024];
@@ -855,6 +981,12 @@
        ssize_t list_size;
        struct h_misc_64 hmac_misc;
        int hmac_size;
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+       HMAC_CTX ctx;
+       pctx = &ctx;
+#else
+       pctx = HMAC_CTX_new();
+#endif
 
        key = file2bin(keyfile, NULL, &keylen);
        if (!key) {
@@ -887,6 +1019,7 @@
                }
                if (ioctl(fd, FS_IOC_GETVERSION, &generation)) {
                        log_err("ioctl() failed\n");
+                       close(fd);
                        goto out;
                }
                close(fd);
@@ -900,7 +1033,7 @@
                goto out;
        }
 
-       err = !HMAC_Init(&ctx, evmkey, sizeof(evmkey), EVP_sha1());
+       err = !HMAC_Init_ex(pctx, evmkey, sizeof(evmkey), EVP_sha1(), NULL);
        if (err) {
                log_err("HMAC_Init() failed\n");
                goto out;
@@ -919,7 +1052,7 @@
                /*log_debug("name: %s, value: %s, size: %d\n", *xattrname, 
xattr_value, err);*/
                log_info("name: %s, size: %d\n", *xattrname, err);
                log_debug_dump(xattr_value, err);
-               err = !HMAC_Update(&ctx, xattr_value, err);
+               err = !HMAC_Update(pctx, xattr_value, err);
                if (err) {
                        log_err("HMAC_Update() failed\n");
                        goto out_ctx_cleanup;
@@ -960,16 +1093,20 @@
        log_debug("hmac_misc (%d): ", hmac_size);
        log_debug_dump(&hmac_misc, hmac_size);
 
-       err = !HMAC_Update(&ctx, (const unsigned char *)&hmac_misc, hmac_size);
+       err = !HMAC_Update(pctx, (const unsigned char *)&hmac_misc, hmac_size);
        if (err) {
                log_err("HMAC_Update() failed\n");
                goto out_ctx_cleanup;
        }
-       err = !HMAC_Final(&ctx, hash, &mdlen);
+       err = !HMAC_Final(pctx, hash, &mdlen);
        if (err)
                log_err("HMAC_Final() failed\n");
 out_ctx_cleanup:
-       HMAC_CTX_cleanup(&ctx);
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+       HMAC_CTX_cleanup(pctx);
+#else
+       HMAC_CTX_free(pctx);
+#endif
 out:
        free(key);
        return err ?: mdlen;
@@ -1137,18 +1274,23 @@
        return do_cmd(cmd, ima_clear);
 }
 
-static char *pcrs = "/sys/class/misc/tpm0/device/pcrs";
+static char *pcrs = "/sys/class/tpm/tpm0/device/pcrs";  /* Kernels >= 4.0 */
+static char *misc_pcrs = "/sys/class/misc/tpm0/device/pcrs";
 
 static int tpm_pcr_read(int idx, uint8_t *pcr, int len)
 {
        FILE *fp;
        char *p, pcr_str[7], buf[70]; /* length of the TPM string */
+       int result = -1;
 
        sprintf(pcr_str, "PCR-%d", idx);
 
        fp = fopen(pcrs, "r");
+       if (!fp)
+               fp = fopen(misc_pcrs, "r");
+
        if (!fp) {
-               log_err("Unable to open %s\n", pcrs);
+               log_err("Unable to open %s or %s\n", pcrs, misc_pcrs);
                return -1;
        }
 
@@ -1158,11 +1300,12 @@
                        break;
                if (!strncmp(p, pcr_str, 6)) {
                        hex2bin(pcr, p + 7, len);
-                       return 0;
+                       result = 0;
+                       break;
                }
        }
        fclose(fp);
-       return -1;
+       return result;
 }
 
 #define TCG_EVENT_NAME_LEN_MAX 255
@@ -1197,7 +1340,7 @@
        SHA1_Final(pcr, &ctx);
 }
 
-static int ima_verify_tamplate_hash(struct template_entry *entry)
+static int ima_verify_template_hash(struct template_entry *entry)
 {
        uint8_t digest[SHA_DIGEST_LENGTH];
 
@@ -1227,9 +1370,10 @@
        int total_len = entry->template_len, digest_len, len, sig_len;
        uint8_t *digest, *sig = NULL;
        char *algo, *path;
+       int err;
 
        /* get binary digest */
-       field_len = *(uint8_t *)fieldp;
+       field_len = *(uint32_t *)fieldp;
        fieldp += sizeof(field_len);
        total_len -= sizeof(field_len);
 
@@ -1243,7 +1387,7 @@
        total_len -= field_len;
 
        /* get path */
-       field_len = *(uint8_t *)fieldp;
+       field_len = *(uint32_t *)fieldp;
        fieldp += sizeof(field_len);
        total_len -= sizeof(field_len);
 
@@ -1255,7 +1399,7 @@
 
        if (!strcmp(entry->name, "ima-sig")) {
                /* get signature */
-               field_len = *(uint8_t *)fieldp;
+               field_len = *(uint32_t *)fieldp;
                fieldp += sizeof(field_len);
                total_len -= sizeof(field_len);
 
@@ -1270,18 +1414,30 @@
        }
 
        /* ascii_runtime_measurements */
-       log_info("%d ", entry->header.pcr);
-       log_dump_n(entry->header.digest, sizeof(entry->header.digest));
-       log_info(" %s %s", entry->name, algo);
-       log_dump_n(digest, digest_len);
-       log_info(" %s", path);
+       if (params.verbose > LOG_INFO) {
+               log_info("%d ", entry->header.pcr);
+               log_dump_n(entry->header.digest, sizeof(entry->header.digest));
+               log_info(" %s %s", entry->name, algo);
+               log_dump_n(digest, digest_len);
+               log_info(" %s", path);
+       }
 
        if (sig) {
-               log_info(" ");
-               log_dump(sig, sig_len);
-               ima_verify_signature(path, sig, sig_len);
-       } else
-               log_info("\n");
+               if (params.verbose > LOG_INFO) {
+                       log_info(" ");
+                       log_dump(sig, sig_len);
+               }
+               if (measurement_list)
+                       err = ima_verify_signature(path, sig, sig_len,
+                                                  digest, digest_len);
+               else
+                       err = ima_verify_signature(path, sig, sig_len, NULL, 0);
+               if (!err && params.verbose > LOG_INFO)
+                       log_info("%s: verification is OK\n", path);
+       } else {
+               if (params.verbose > LOG_INFO)
+                       log_info("\n");
+       }
 
        if (total_len)
                log_err("Remain unprocessed data: %d\n", total_len);
@@ -1289,12 +1445,16 @@
 
 static int ima_measurement(const char *file)
 {
-       uint8_t pcr[SHA_DIGEST_LENGTH] = {0,};
-       uint8_t pcr10[SHA_DIGEST_LENGTH];
+       uint8_t pcr[NUM_PCRS][SHA_DIGEST_LENGTH] = {{0}};
+       uint8_t hwpcr[SHA_DIGEST_LENGTH];
        struct template_entry entry = { .template = 0 };
        FILE *fp;
        int err = -1;
+       bool verify_failed = false;
+       int i;
 
+       errno = 0;
+       memset(zero, 0, SHA_DIGEST_LENGTH);
        memset(fox, 0xff, SHA_DIGEST_LENGTH);
 
        log_debug("Initial PCR value: ");
@@ -1306,8 +1466,13 @@
                return -1;
        }
 
+       /* Support multiple public keys */
+       if (params.keyfile)
+               init_public_keys(params.keyfile);
+
        while (fread(&entry.header, sizeof(entry.header), 1, fp)) {
-               ima_extend_pcr(pcr, entry.header.digest, SHA_DIGEST_LENGTH);
+               ima_extend_pcr(pcr[entry.header.pcr], entry.header.digest,
+                              SHA_DIGEST_LENGTH);
 
                if (!fread(entry.name, entry.header.name_len, 1, fp)) {
                        log_err("Unable to read template name\n");
@@ -1333,7 +1498,7 @@
                }
 
                if (validate)
-                       ima_verify_tamplate_hash(&entry);
+                       ima_verify_template_hash(&entry);
 
                if (!strcmp(entry.name, "ima"))
                        ima_show(&entry);
@@ -1341,23 +1506,29 @@
                        ima_ng_show(&entry);
        }
 
-       tpm_pcr_read(10, pcr10, sizeof(pcr10));
 
-       log_info("PCRAgg: ");
-       log_dump(pcr, sizeof(pcr));
+       for (i = 0; i < NUM_PCRS; i++) {
+               if (memcmp(pcr[i], zero, SHA_DIGEST_LENGTH) == 0)
+                       continue;
 
-       log_info("PCR-10: ");
-       log_dump(pcr10, sizeof(pcr10));
+               log_info("PCRAgg %.2d: ", i);
+               log_dump(pcr[i], SHA_DIGEST_LENGTH);
 
-       if (memcmp(pcr, pcr10, sizeof(pcr))) {
-               log_err("PCRAgg does not match PCR-10\n");
-               goto out;
+               tpm_pcr_read(i, hwpcr, sizeof(hwpcr));
+               log_info("HW PCR-%d: ", i);
+               log_dump(hwpcr, sizeof(hwpcr));
+
+               if (memcmp(pcr[i], hwpcr, sizeof(SHA_DIGEST_LENGTH)) != 0) {
+                       log_err("PCRAgg %d does not match HW PCR-%d\n", i, i);
+
+                       verify_failed = true;
+               }
        }
 
-       err = 0;
+       if (!verify_failed)
+               err = 0;
 out:
        fclose(fp);
-
        return err;
 }
 
@@ -1450,6 +1621,7 @@
                "  -f, --sigfile      store IMA signature in .sig file instead 
of xattr\n"
                "      --rsa          use RSA key type and signing scheme v1\n"
                "  -k, --key          path to signing key (default: 
/etc/keys/{privkey,pubkey}_evm.pem)\n"
+               "  -o, --portable     generate portable EVM signatures\n"
                "  -p, --pass         password for encrypted signing key\n"
                "  -r, --recursive    recurse into directories (sign)\n"
                "  -t, --type         file types to fix 'fdsxm' (f: file, d: 
directory, s: block/char/symlink)\n"
@@ -1460,6 +1632,15 @@
                "      --smack        use extra SMACK xattrs for EVM\n"
                "      --m32          force EVM hmac/signature for 32 bit 
target system\n"
                "      --m64          force EVM hmac/signature for 64 bit 
target system\n"
+               "      --ino          use custom inode for EVM\n"
+               "      --uid          use custom UID for EVM\n"
+               "      --gid          use custom GID for EVM\n"
+               "      --mode         use custom Mode for EVM\n"
+               "      --generation   use custom Generation for 
EVM(unspecified: from FS, empty: use 0)\n"
+               "      --ima          use custom IMA signature for EVM\n"
+               "      --selinux      use custom Selinux label for EVM\n"
+               "      --caps         use custom Capabilities for 
EVM(unspecified: from FS, empty: do not use)\n"
+               "      --list         measurement list verification\n"
                "  -v                 increase verbosity level\n"
                "  -h, --help         display this help and exit\n"
                "\n");
@@ -1469,10 +1650,12 @@
        {"--version", NULL, 0, ""},
        {"help", cmd_help, 0, "<command>"},
        {"import", cmd_import, 0, "[--rsa] pubkey keyring", "Import public key 
into the keyring.\n"},
+       {"convert", cmd_convert, 0, "key", "convert public key into the 
keyring.\n"},
        {"sign", cmd_sign_evm, 0, "[-r] [--imahash | --imasig ] [--key key] 
[--pass [password] file", "Sign file metadata.\n"},
        {"verify", cmd_verify_evm, 0, "file", "Verify EVM signature (for 
debugging).\n"},
        {"ima_sign", cmd_sign_ima, 0, "[--sigfile] [--key key] [--pass 
[password] file", "Make file content signature.\n"},
        {"ima_verify", cmd_verify_ima, 0, "file", "Verify IMA signature (for 
debugging).\n"},
+       {"ima_setxattr", cmd_setxattr_ima, 0, "[--sigfile file]", "Set IMA 
signature from sigfile\n"},
        {"ima_hash", cmd_hash_ima, 0, "file", "Make file content hash.\n"},
        {"ima_measurement", cmd_ima_measurement, 0, "file", "Verify measurement 
list (experimental).\n"},
        {"ima_fix", cmd_ima_fix, 0, "[-t fdsxm] path", "Recursively fix IMA/EVM 
xattrs in fix mode.\n"},
@@ -1498,8 +1681,18 @@
        {"recursive", 0, 0, 'r'},
        {"m32", 0, 0, '3'},
        {"m64", 0, 0, '6'},
-       {"smack", 0, 0, 256},
-       {"version", 0, 0, 257},
+       {"portable", 0, 0, 'o'},
+       {"smack", 0, 0, 128},
+       {"version", 0, 0, 129},
+       {"inode", 1, 0, 130},
+       {"uid", 1, 0, 131},
+       {"gid", 1, 0, 132},
+       {"mode", 1, 0, 133},
+       {"generation", 1, 0, 134},
+       {"ima", 1, 0, 135},
+       {"selinux", 1, 0, 136},
+       {"caps", 2, 0, 137},
+       {"list", 0, 0, 138},
        {}
 
 };
@@ -1546,7 +1739,7 @@
        g_argc = argc;
 
        while (1) {
-               c = getopt_long(argc, argv, "hvnsda:p::fu::k:t:ri", opts, 
&lind);
+               c = getopt_long(argc, argv, "hvnsda:op::fu::k:t:ri", opts, 
&lind);
                if (c == -1)
                        break;
 
@@ -1580,14 +1773,11 @@
                        break;
                case 'f':
                        sigfile = 1;
-                       xattr = 0;
                        break;
                case 'u':
                        uuid_str = optarg;
-                       if (uuid_str)
-                               hmac_flags |= HMAC_FLAG_UUID_SET;
-                       else
-                               hmac_flags &= ~HMAC_FLAG_UUID;
+                       if (!uuid_str)
+                               hmac_flags |= HMAC_FLAG_NO_UUID;
                        break;
                case '1':
                        params.x509 = 0;
@@ -1596,7 +1786,16 @@
                        params.keyfile = optarg;
                        break;
                case 'i':
-                       evm_immutable = true;
+                       if (evm_portable)
+                               log_err("Portable and immutable options are 
exclusive, ignoring immutable option.");
+                       else
+                               evm_immutable = true;
+                       break;
+               case 'o':
+                       if (evm_immutable)
+                               log_err("Portable and immutable options are 
exclusive, ignoring portable option.");
+                       else
+                               evm_portable = true;
                        break;
                case 't':
                        search_type = optarg;
@@ -1610,13 +1809,41 @@
                case '6':
                        msize = 64;
                        break;
-               case 256:
+               case 128:
                        evm_config_xattrnames = evm_extra_smack_xattrs;
                        break;
-               case 257:
+               case 129:
                        printf("evmctl %s\n", VERSION);
                        exit(0);
                        break;
+               case 130:
+                       ino_str = optarg;
+                       break;
+               case 131:
+                       uid_str = optarg;
+                       break;
+               case 132:
+                       gid_str = optarg;
+                       break;
+               case 133:
+                       mode_str = optarg;
+                       break;
+               case 134:
+                       generation_str = optarg;
+                       break;
+               case 135:
+                       ima_str = optarg;
+                       break;
+               case 136:
+                       selinux_str = optarg;
+                       break;
+               case 137:
+                       caps_str = optarg;
+                       hmac_flags |= HMAC_FLAG_CAPS_SET;
+                       break;
+               case 138:
+                       measurement_list = 1;
+                       break;
                case '?':
                        exit(1);
                        break;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ima-evm-utils-1.0/src/imaevm.h 
new/ima-evm-utils-1.1/src/imaevm.h
--- old/ima-evm-utils-1.0/src/imaevm.h  2015-07-30 20:28:53.000000000 +0200
+++ new/ima-evm-utils-1.1/src/imaevm.h  2018-02-15 14:02:19.000000000 +0100
@@ -82,6 +82,7 @@
        EVM_XATTR_HMAC,
        EVM_IMA_XATTR_DIGSIG,
        IMA_XATTR_DIGEST_NG,
+       EVM_XATTR_PORTABLE_DIGSIG,
 };
 
 struct h_misc {
@@ -172,7 +173,7 @@
 } __packed;
 
 
-typedef int (*verify_hash_fn_t)(const unsigned char *hash, int size, unsigned 
char *sig, int siglen, const char *keyfile);
+typedef int (*verify_hash_fn_t)(const char *file, const unsigned char *hash, 
int size, unsigned char *sig, int siglen, const char *keyfile);
 
 struct libevm_params {
        int verbose;
@@ -187,6 +188,9 @@
        size_t size;
 };
 
+#define        NUM_PCRS 20
+#define DEFAULT_PCR 10
+
 extern const struct RSA_ASN1_template RSA_ASN1_templates[PKEY_HASH__LAST];
 extern struct libevm_params params;
 
@@ -202,7 +206,8 @@
 int key2bin(RSA *key, unsigned char *pub);
 
 int sign_hash(const char *algo, const unsigned char *hash, int size, const 
char *keyfile, const char *keypass, unsigned char *sig);
-int verify_hash(const unsigned char *hash, int size, unsigned char *sig, int 
siglen);
-int ima_verify_signature(const char *file, unsigned char *sig, int siglen);
+int verify_hash(const char *file, const unsigned char *hash, int size, 
unsigned char *sig, int siglen);
+int ima_verify_signature(const char *file, unsigned char *sig, int siglen, 
unsigned char *digest, int digestlen);
+void init_public_keys(const char *keyfiles);
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ima-evm-utils-1.0/src/libimaevm.c 
new/ima-evm-utils-1.1/src/libimaevm.c
--- old/ima-evm-utils-1.0/src/libimaevm.c       2015-07-30 20:28:53.000000000 
+0200
+++ new/ima-evm-utils-1.1/src/libimaevm.c       2018-02-15 14:02:19.000000000 
+0100
@@ -214,6 +214,7 @@
        DIR *dir;
        unsigned long long ino, off;
        unsigned int type;
+       int result = 0;
 
        dir = opendir(file);
        if (!dir) {
@@ -233,13 +234,14 @@
                err |= EVP_DigestUpdate(ctx, &type, sizeof(type));
                if (!err) {
                        log_err("EVP_DigestUpdate() failed\n");
-                       return 1;
+                       result = 1;
+                       break;
                }
        }
 
        closedir(dir);
 
-       return 0;
+       return result;
 }
 
 static int add_link_hash(const char *path, EVP_MD_CTX *ctx)
@@ -269,9 +271,15 @@
 {
        const EVP_MD *md;
        struct stat st;
-       EVP_MD_CTX ctx;
+       EVP_MD_CTX *pctx;
        unsigned int mdlen;
        int err;
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+       EVP_MD_CTX ctx;
+       pctx = &ctx;
+#else
+       pctx = EVP_MD_CTX_new();
+#endif
 
        /*  Need to know the file length */
        err = lstat(file, &st);
@@ -286,7 +294,7 @@
                return 1;
        }
 
-       err = EVP_DigestInit(&ctx, md);
+       err = EVP_DigestInit(pctx, md);
        if (!err) {
                log_err("EVP_DigestInit() failed\n");
                return 1;
@@ -294,17 +302,17 @@
 
        switch (st.st_mode & S_IFMT) {
        case S_IFREG:
-               err = add_file_hash(file, &ctx);
+               err = add_file_hash(file, pctx);
                break;
        case S_IFDIR:
-               err = add_dir_hash(file, &ctx);
+               err = add_dir_hash(file, pctx);
                break;
        case S_IFLNK:
-               err = add_link_hash(file, &ctx);
+               err = add_link_hash(file, pctx);
                break;
        case S_IFIFO: case S_IFSOCK:
        case S_IFCHR: case S_IFBLK:
-               err = add_dev_hash(&st, &ctx);
+               err = add_dev_hash(&st, pctx);
                break;
        default:
                log_errno("Unsupported file type");
@@ -314,7 +322,7 @@
        if (err)
                return err;
 
-       err = EVP_DigestFinal(&ctx, hash, &mdlen);
+       err = EVP_DigestFinal(pctx, hash, &mdlen);
        if (!err) {
                log_err("EVP_DigestFinal() failed\n");
                return 1;
@@ -364,7 +372,8 @@
        return key;
 }
 
-int verify_hash_v1(const unsigned char *hash, int size, unsigned char *sig, 
int siglen, const char *keyfile)
+int verify_hash_v1(const char *file, const unsigned char *hash, int size,
+                  unsigned char *sig, int siglen, const char *keyfile)
 {
        int err, len;
        SHA_CTX ctx;
@@ -373,7 +382,7 @@
        unsigned char sighash[20];
        struct signature_hdr *hdr = (struct signature_hdr *)sig;
 
-       log_info("hash: ");
+       log_info("hash-v1: ");
        log_dump(hash, size);
 
        key = read_pub_key(keyfile, 0);
@@ -390,24 +399,77 @@
        err = RSA_public_decrypt(siglen - sizeof(*hdr) - 2, sig + sizeof(*hdr) 
+ 2, out, key, RSA_PKCS1_PADDING);
        RSA_free(key);
        if (err < 0) {
-               log_err("RSA_public_decrypt() failed: %d\n", err);
+               log_err("%s: RSA_public_decrypt() failed: %d\n", file, err);
                return 1;
        }
 
        len = err;
 
        if (len != sizeof(sighash) || memcmp(out, sighash, len) != 0) {
-               log_err("Verification failed: %d\n", err);
+               log_err("%s: verification failed: %d\n", file, err);
                return -1;
-       } else {
-               /*log_info("Verification is OK\n");*/
-               printf("Verification is OK\n");
        }
 
        return 0;
 }
 
-int verify_hash_v2(const unsigned char *hash, int size, unsigned char *sig, 
int siglen, const char *keyfile)
+struct public_key_entry {
+       struct public_key_entry *next;
+       uint32_t keyid;
+       char name[9];
+       RSA *key;
+};
+static struct public_key_entry *public_keys = NULL;
+
+static RSA *find_keyid(uint32_t keyid)
+{
+       struct public_key_entry *entry;
+
+       for (entry = public_keys; entry != NULL; entry = entry->next) {
+               if (entry->keyid == keyid)
+                       return entry->key;
+       }
+       return NULL;
+}
+
+void init_public_keys(const char *keyfiles)
+{
+       struct public_key_entry *entry;
+       char *tmp_keyfiles;
+       char *keyfile;
+       int i = 1;
+
+       tmp_keyfiles = strdup(keyfiles);
+
+       while ((keyfile = strsep(&tmp_keyfiles, ", \t")) != NULL) {
+               if (!keyfile)
+                       break;
+               if ((*keyfile == '\0') || (*keyfile == ' ') ||
+                   (*keyfile == '\t'))
+                       continue;
+
+               entry = malloc(sizeof(struct public_key_entry));
+               if (!entry) {
+                       perror("malloc");
+                       break;
+               }
+
+               entry->key = read_pub_key(keyfile, 1);
+               if (!entry->key) {
+                       free(entry);
+                       continue;
+               }
+
+               calc_keyid_v2(&entry->keyid, entry->name, entry->key);
+               sprintf(entry->name, "%x", __be32_to_cpup(&entry->keyid));
+               log_info("key %d: %s %s\n", i++, entry->name, keyfile);
+               entry->next = public_keys;
+               public_keys = entry;
+       }
+}
+
+int verify_hash_v2(const char *file, const unsigned char *hash, int size,
+                  unsigned char *sig, int siglen, const char *keyfile)
 {
        int err, len;
        unsigned char out[1024];
@@ -415,17 +477,29 @@
        struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig;
        const struct RSA_ASN1_template *asn1;
 
-       log_info("hash: ");
-       log_dump(hash, size);
+       if (params.verbose > LOG_INFO) {
+               log_info("hash: ");
+               log_dump(hash, size);
+       }
 
-       key = read_pub_key(keyfile, 1);
-       if (!key)
-               return 1;
+       if (public_keys) {
+               key = find_keyid(hdr->keyid);
+               if (!key) {
+                       log_err("%s: unknown keyid: %x\n", file,
+                               __be32_to_cpup(&hdr->keyid));
+                       return -1;
+               }
+       } else {
+               key = read_pub_key(keyfile, 1);
+               if (!key)
+                       return 1;
+       }
 
-       err = RSA_public_decrypt(siglen - sizeof(*hdr), sig + sizeof(*hdr), 
out, key, RSA_PKCS1_PADDING);
-       RSA_free(key);
+
+       err = RSA_public_decrypt(siglen - sizeof(*hdr), sig + sizeof(*hdr),
+                                out, key, RSA_PKCS1_PADDING);
        if (err < 0) {
-               log_err("RSA_public_decrypt() failed: %d\n", err);
+               log_err("%s: RSA_public_decrypt() failed: %d\n", file, err);
                return 1;
        }
 
@@ -434,20 +508,17 @@
        asn1 = &RSA_ASN1_templates[hdr->hash_algo];
 
        if (len < asn1->size || memcmp(out, asn1->data, asn1->size)) {
-               log_err("Verification failed: %d\n", err);
+               log_err("%s: verification failed: %d\n", file, err);
                return -1;
        }
 
        len -= asn1->size;
 
        if (len != size || memcmp(out + asn1->size, hash, len)) {
-               log_err("Verification failed: %d\n", err);
+               log_err("%s: verification failed: %d\n", file, err);
                return -1;
        }
 
-       /*log_info("Verification is OK\n");*/
-       printf("Verification is OK\n");
-
        return 0;
 }
 
@@ -489,7 +560,8 @@
                return -1;
 }
 
-int verify_hash(const unsigned char *hash, int size, unsigned char *sig, int 
siglen)
+int verify_hash(const char *file, const unsigned char *hash, int size, 
unsigned char *sig,
+               int siglen)
 {
        const char *key;
        int x509;
@@ -512,10 +584,11 @@
                        "/etc/keys/x509_evm.der" :
                        "/etc/keys/pubkey_evm.pem";
 
-       return verify_hash(hash, size, sig, siglen, key);
+       return verify_hash(file, hash, size, sig, siglen, key);
 }
 
-int ima_verify_signature(const char *file, unsigned char *sig, int siglen)
+int ima_verify_signature(const char *file, unsigned char *sig, int siglen,
+                        unsigned char *digest, int digestlen)
 {
        unsigned char hash[64];
        int hashlen, sig_hash_algo;
@@ -533,11 +606,18 @@
        /* Use hash algorithm as retrieved from signature */
        params.hash_algo = pkey_hash_algo[sig_hash_algo];
 
+       /*
+        * Validate the signature based on the digest included in the
+        * measurement list, not by calculating the local file digest.
+        */
+       if (digestlen > 0)
+           return verify_hash(file, digest, digestlen, sig + 1, siglen - 1);
+
        hashlen = ima_calc_hash(file, hash);
        if (hashlen <= 1)
                return hashlen;
 
-       return verify_hash(hash, hashlen, sig + 1, siglen - 1);
+       return verify_hash(file, hash, hashlen, sig + 1, siglen - 1);
 }
 
 /*
@@ -547,6 +627,14 @@
 {
        int len, b, offset = 0;
        struct pubkey_hdr *pkh = (struct pubkey_hdr *)pub;
+       const BIGNUM *n, *e;
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+       n = key->n;
+       e = key->e;
+#else
+       RSA_get0_key(key, &n, &e, NULL);
+#endif
 
        /* add key header */
        pkh->version = 1;
@@ -556,18 +644,18 @@
 
        offset += sizeof(*pkh);
 
-       len = BN_num_bytes(key->n);
-       b = BN_num_bits(key->n);
+       len = BN_num_bytes(n);
+       b = BN_num_bits(n);
        pub[offset++] = b >> 8;
        pub[offset++] = b & 0xff;
-       BN_bn2bin(key->n, &pub[offset]);
+       BN_bn2bin(n, &pub[offset]);
        offset += len;
 
-       len = BN_num_bytes(key->e);
-       b = BN_num_bits(key->e);
+       len = BN_num_bytes(e);
+       b = BN_num_bits(e);
        pub[offset++] = b >> 8;
        pub[offset++] = b & 0xff;
-       BN_bn2bin(key->e, &pub[offset]);
+       BN_bn2bin(e, &pub[offset]);
        offset += len;
 
        return offset;
@@ -585,9 +673,11 @@
        log_debug("keyid: ");
        log_debug_dump(keyid, 8);
 
-       id = __be64_to_cpup((__be64 *) keyid);
-       sprintf(str, "%llX", (unsigned long long)id);
-       log_info("keyid: %s\n", str);
+       if (params.verbose > LOG_INFO) {
+               id = __be64_to_cpup((__be64 *) keyid);
+               sprintf(str, "%llX", (unsigned long long)id);
+               log_info("keyid-v1: %s\n", str);
+       }
 }
 
 void calc_keyid_v2(uint32_t *keyid, char *str, RSA *key)
@@ -605,8 +695,10 @@
        log_debug("keyid: ");
        log_debug_dump(keyid, 4);
 
-       sprintf(str, "%x", __be32_to_cpup(keyid));
-       log_info("keyid: %s\n", str);
+       if (params.verbose > LOG_INFO) {
+               sprintf(str, "%x", __be32_to_cpup(keyid));
+               log_info("keyid: %s\n", str);
+       }
 
        free(pkey);
 }
@@ -719,7 +811,7 @@
        blen = (uint16_t *) (sig + sizeof(*hdr));
        *blen = __cpu_to_be16(len << 3);
        len += sizeof(*hdr) + 2;
-       log_info("evm/ima signature: %d bytes\n", len);
+       log_info("evm/ima signature-v1: %d bytes\n", len);
 out:
        RSA_free(key);
        return len;


Reply via email to