ima-evm-utils: Extract digest algorithms from hash_info.h
PATCH 6/7 ima-evm-utils: Extract digest algorithms from hash_info.h
If configured with "--with-kernel-headers=PATH" try to extract hash algorithms from "hash_info.h" from the kernel source tree or kernel-headers package located in the specified path. (Otherwise, it will be tried to get from the installed kernel.)
This also introduces two algorithm lists, one is built-in and another is from the kernel source. (They should never contain conflicting algorithm IDs by their append-only nature.) If the digest is not found in the built-in list it will be searched in the list from kernel's "hash_info.h".
This patch will allow evmctl to be just recompiled to work with digest algorithms introduced in the newer kernels.
---
Changes since v1:
- New patch.
Changes since v2:
- Mark PATH portion of "--with-kernel-headers=PATH" non-optional and change description to reflect correct behavior.
configure.ac | 6 ++++++ src/Makefile.am | 6 ++++++ src/hash_info.gen | 43 +++++++++++++++++++++++++++++++++++++++++++ src/libimaevm.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 98 insertions(+), 1 deletion(-) create mode 100755 src/hash_info.gen
configure.ac +6 -0
@@ -27,12 +27,18 @@ AC_HEADER_STDC PKG_CHECK_MODULES(OPENSSL, [ openssl >= 0.9.8 ]) AC_SUBST(OPENSSL_CFLAGS) AC_SUBST(OPENSSL_LIBS) +AC_SUBST(KERNEL_HEADERS) AC_CHECK_HEADER(unistd.h) AC_CHECK_HEADERS(openssl/conf.h) AC_CHECK_HEADERS(sys/xattr.h, , [AC_MSG_ERROR([sys/xattr.h header not found. You need the c-library development package.])]) AC_CHECK_HEADERS(keyutils.h, , [AC_MSG_ERROR([keyutils.h header not found. You need the libkeyutils development package.])]) +AC_ARG_WITH(kernel_headers, [AS_HELP_STRING([--with-kernel-headers=PATH], + [specifies the Linux kernel-headers package location or kernel root directory you want to use])], + [KERNEL_HEADERS="$withval"], + [KERNEL_HEADERS=/lib/modules/$(uname -r)/source]) + #debug support - yes for a while PKG_ARG_ENABLE(debug, "yes", DEBUG, [Enable Debug support]) if test $pkg_cv_enable_debug = yes; then
src/Makefile.am +6 -0
@@ -9,6 +9,11 @@ libimaevm_la_LIBADD = $(OPENSSL_LIBS) include_HEADERS = imaevm.h +nodist_libimaevm_la_SOURCES = hash_info.h +BUILT_SOURCES = hash_info.h +hash_info.h: Makefile + ./hash_info.gen $(KERNEL_HEADERS) >$@ + bin_PROGRAMS = evmctl evmctl_SOURCES = evmctl.c
@@ -18,5 +23,6 @@ evmctl_LDADD = $(OPENSSL_LIBS) -lkeyutils libimaevm.la INCLUDES = -I$(top_srcdir) -include config.h +CLEANFILES = hash_info.h DISTCLEANFILES = @DISTCLEANFILES@
src/hash_info.gen new file +43 -0
43 lines not on this page · raw message
src/libimaevm.c +43 -1
83 lines not on this page · raw message
Signature · 1 line
2.11.0
Mimi Zohar
maintainerQuoted 14 lines · Vitaly Chikunov
If configured with "--with-kernel-headers=PATH" try to extract hash algorithms from "
hash_info.h" from the kernel source tree or kernel-headers package located in the specified path. (Otherwise, it will be tried to get from the installed kernel.)This also introduces two algorithm lists, one is built-in and another is from the kernel source. (They should never contain conflicting algorithm IDs by their append-only nature.) If the digest is not found in the built-in list it will be searched in the list from kernel's "
hash_info.h".This patch will allow evmctl to be just recompiled to work with digest algorithms introduced in the newer kernels.
Quoted 8 lines
Suggested-by Mimi Zohar <[email protected]>Signed-off-by Vitaly Chikunov <[email protected]>---
Changes since v1:
- New patch.
Changes since v2:
- Mark PATH portion of "--with-kernel-headers=PATH" non-optional and change description to reflect correct behavior.
Defaulting to the currently running kernel build tree would have been nice.
Quoted 93 lines
configure.ac | 6 ++++++ src/Makefile.am | 6 ++++++ src/hash_info.gen | 43 +++++++++++++++++++++++++++++++++++++++++++ src/libimaevm.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 98 insertions(+), 1 deletion(-) create mode 100755 src/hash_info.genconfigure.ac +6
-0@@ -27,12 +27,18 @@ AC_HEADER_STDC PKG_CHECK_MODULES(OPENSSL, [ openssl >= 0.9.8 ]) AC_SUBST(OPENSSL_CFLAGS) AC_SUBST(OPENSSL_LIBS) +AC_SUBST(KERNEL_HEADERS) AC_CHECK_HEADER(unistd.h) AC_CHECK_HEADERS(openssl/conf.h) AC_CHECK_HEADERS(sys/xattr.h, , [AC_MSG_ERROR([sys/xattr.h header not found. You need the c-library development package.])]) AC_CHECK_HEADERS(keyutils.h, , [AC_MSG_ERROR([keyutils.h header not found. You need the libkeyutils development package.])]) +AC_ARG_WITH(kernel_headers, [AS_HELP_STRING([--with-kernel-headers=PATH], + [specifies the Linux kernel-headers package location or kernel root directory you want to use])], + [KERNEL_HEADERS="$withval"], + [KERNEL_HEADERS=/lib/modules/$(uname -r)/source]) + #debug support - yes for a while PKG_ARG_ENABLE(debug, "yes", DEBUG, [Enable Debug support]) if test $pkg_cv_enable_debug = yes; thensrc/Makefile.am +6
-0@@ -9,6 +9,11 @@ libimaevm_la_LIBADD = $(OPENSSL_LIBS) include_HEADERS = imaevm.h +nodist_libimaevm_la_SOURCES = hash_info.h +BUILT_SOURCES = hash_info.h +hash_info.h: Makefile + ./hash_info.gen $(KERNEL_HEADERS) >$@ + bin_PROGRAMS = evmctl evmctl_SOURCES = evmctl.c@@ -18,5 +23,6 @@ evmctl_LDADD = $(OPENSSL_LIBS) -lkeyutils libimaevm.la INCLUDES = -I$(top_srcdir) -include config.h +CLEANFILES = hash_info.h DISTCLEANFILES = @DISTCLEANFILES@src/hash_info.gen new file +33
-0@@ -0,0 +1,43 @@ +#!/bin/sh +# +# Generate hash_info.h from kernel headers +# +# Copyright (C) 2018 <[email protected]> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# 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. + +KERNEL_HEADERS=$1 +HASH_INFO_H=uapi/linux/hash_info.h +HASH_INFO=$KERNEL_HEADERS/include/$HASH_INFO_H + +# Allow to specify kernel-headers past include/ +if [ ! -e $HASH_INFO ]; then + HASH_INFO2=$KERNEL_HEADERS/$HASH_INFO_H + if [ -e $HASH_INFO2 ]; then + HASH_INFO=$HASH_INFO2 + fi +fi + +if [ ! -e $HASH_INFO ]; then + echo "/* $HASH_INFO is not found */" + HASH_INFO=/dev/null +else + echo "/* $HASH_INFO is found */"
src/hash_info.gen line 43
Quoted 10 lines
src/hash_info.gen new file +10
-0+fi + +echo "enum hash_algo {" +grep HASH_ALGO_.*, $HASH_INFO +printf "\tHASH_ALGO__LAST\n" +echo "};" + +echo "const char *const hash_algo_name[HASH_ALGO__LAST] = {" +sed -n 's/HASH_ALGO_\(.*\),/[HASH_ALGO_\1] = "\L\1\E",/p' $HASH_INFO +echo "};"
Almost perfectly matches crypto/hash_crypto.c! Waiting to see if/how the next patch addresses the differences...
Quoted 68 lines
src/libimaevm.c +34
-0@@ -50,6 +50,7 @@#include <string.h> #include <stdio.h> #include <assert.h> +#include <ctype.h> #include <openssl/crypto.h> #include <openssl/pem.h> @@ -58,6 +59,7 @@#include <openssl/err.h> #include "imaevm.h" +#include "hash_info.h" const char *const pkey_hash_algo[PKEY_HASH__LAST ] = { [PKEY_HASH_MD4 ] ="md4" ,@@ -153,6 +155,17 @@ void dump(const void *ptr, int len)do_dump (stdout, ptr, len, true); } +const char *get_hash_algo_by_id (int algo) +{ +if (algo <PKEY_HASH__LAST ) +return pkey_hash_algo[algo]; +if (algo <HASH_ALGO__LAST ) +return hash_algo_name[algo]; + +log_err ("digest %d not found\n" , algo); +return "unknown" ; +} +int get_filesize (const char *filename) {struct stat stats;@@ -528,15 +541,44 @@ int verify_hash_v2(const char *file, const unsigned char *hash, int size,return 0 ; } +/* compare algo names case insensitively and ignoring separators */ +static int algocmp (const char *a,const char *b) +{ +while (*a && *b) { +int cha, chb; + + cha =tolower ((unsigned char )*a++); +if (!isalnum (cha)) +continue ; + chb =tolower ((unsigned char )*b++); +if (!isalnum (chb)) { + a--; +continue ; + } +if (cha != chb) +return -1 ; + } +return *a || *b; +} +int get_hash_algo (const char *algo) {int i; +/* first iterate over builtin algorithms */ for (i =0 ; i <PKEY_HASH__LAST ; i++)
src/libimaevm.c int verify_hash_v2(const char *file, const unsigned char *hash, int size, · line 579
Quoted 10 lines
src/libimaevm.c +6
-0if (pkey_hash_algo[i] && !strcmp (algo, pkey_hash_algo[i]))return i; +/* iterate over algorithms provided by kernel-headers */ +for (i =0 ; i <HASH_ALGO__LAST ; i++) { +if (hash_algo_name[i] && + !algocmp (algo, hash_algo_name[i])) +return i; + }
Assuming the two lists are in sync, which they should be, "i" could be set to PKEY_HASH__LAST.
Mimi
Quoted 14 lines
src/libimaevm.c +3
-1+ +log_info ("digest %s not found, fall back to sha1\n" , algo);return PKEY_HASH_SHA1 ; }@@ -611,7 +653,7 @@ int ima_verify_signature(const char *file, unsigned char *sig, int siglen,return -1 ; }/* Use hash algorithm as retrieved from signature */ - params.hash_algo = pkey_hash_algo[sig_hash_algo]; + params.hash_algo =get_hash_algo_by_id (sig_hash_algo);/* * Validate the signature based on the digest included in the
Mimi Zohar
maintainerQuoted 23 lines · Mimi Zohar
Quoted 14 lines · Vitaly Chikunov
If configured with "--with-kernel-headers=PATH" try to extract hash algorithms from "
hash_info.h" from the kernel source tree or kernel-headers package located in the specified path. (Otherwise, it will be tried to get from the installed kernel.)This also introduces two algorithm lists, one is built-in and another is from the kernel source. (They should never contain conflicting algorithm IDs by their append-only nature.) If the digest is not found in the built-in list it will be searched in the list from kernel's "
hash_info.h".This patch will allow evmctl to be just recompiled to work with digest algorithms introduced in the newer kernels.
Quoted 8 lines
Suggested-by Mimi Zohar <[email protected]>Signed-off-by Vitaly Chikunov <[email protected]>---
Changes since v1:
- New patch.
Changes since v2:
- Mark PATH portion of "--with-kernel-headers=PATH" non-optional and change description to reflect correct behavior.
Quoted 2 lines
Defaulting to the currently running kernel build tree would have been nice.
Then you could extract "hash_algo_name[]" from crypto/hash_info.c directly.
Mimi
Quoted 24 lines · Mimi Zohar
Quoted 14 lines · Vitaly Chikunov
If configured with "--with-kernel-headers=PATH" try to extract hash algorithms from "
hash_info.h" from the kernel source tree or kernel-headers package located in the specified path. (Otherwise, it will be tried to get from the installed kernel.)This also introduces two algorithm lists, one is built-in and another is from the kernel source. (They should never contain conflicting algorithm IDs by their append-only nature.) If the digest is not found in the built-in list it will be searched in the list from kernel's "
hash_info.h".This patch will allow evmctl to be just recompiled to work with digest algorithms introduced in the newer kernels.
Quoted 8 lines
Suggested-by Mimi Zohar <[email protected]>Signed-off-by Vitaly Chikunov <[email protected]>---
Changes since v1:
- New patch.
Changes since v2:
- Mark PATH portion of "--with-kernel-headers=PATH" non-optional and change description to reflect correct behavior.
Quoted 2 lines
Defaulting to the currently running kernel build tree would have been nice.
It already does. As description states "(Otherwise, it will be tried to get from the installed kernel.)" Also:
Quoted 4 lines
configure.ac AC_HEADER_STDC · line 40
Quoted 4 lines
configure.ac +4
-0+AC_ARG_WITH(kernel_headers, [AS_HELP_STRING([--with-kernel-headers=PATH], + [specifies the Linux kernel-headers package location or kernel root directory you want to use])], + [KERNEL_HEADERS="$withval"], + [KERNEL_HEADERS=/lib/modules/$(uname -r)/source])
if "--with-kernel-headers" is not specified it will default to /lib/modules/$(uname -r)/source which points to the kernel-headers or kernel source tree root.
Quoted 2 lines
Then you could extract "hash_algo_name[]" from
crypto/hash_info.cdirectly.
I could add this, BUT this will mean that developer with kernel tree (very small amount of users) will have slightly different algos list than a common person with a kernel-headers package. And I don't know a single distro which packs full kernel source (with crypto/hash_info.c) as easy to install package, and which would link appropriately into /lib/modules/. So this is highly doubtful that user will be inclined to install kernel source via usually complicated procedure just to compile evmctl.
I already tried to address this possible difference issue by algocmp() which would not compare _ and - chars, which is the only difference from hash_algo_name in the kernel and in ima-evm-utils and OpenSSL. So, even without this feature (of parsing crypto/hash_info.c) added, user already can specify any algo from crypto/hash_info.c and it will just work.
Quoted 11 lines
src/hash_info.gen line 43
Quoted 8 lines
src/hash_info.gen new file +8
-0+echo "enum hash_algo {" +grep HASH_ALGO_.*, $HASH_INFO +printf "\tHASH_ALGO__LAST\n" +echo "};" + +echo "const char *const hash_algo_name[HASH_ALGO__LAST] = {" +sed -n 's/HASH_ALGO_\(.*\),/[HASH_ALGO_\1] = "\L\1\E",/p' $HASH_INFO +echo "};"Almost perfectly matches
crypto/hash_crypto.c! Waiting to see if/how the next patch addresses the differences...
Could you elaborate again on what I should do with this suggestion? I guessed crypto/hash_crypto.c is crypto/hash_info.c, but what differences you expecting?
Quoted 6 lines
Quoted 6 lines
src/libimaevm.c +1
-0+/* first iterate over builtin algorithms */ for (i =0 ; i <PKEY_HASH__LAST ; i++)if (pkey_hash_algo[i] && !strcmp (algo, pkey_hash_algo[i]))return i;
Quoted 9 lines
src/libimaevm.c int verify_hash_v2(const char *file, const unsigned char *hash, int size, · line 579
Quoted 6 lines
src/libimaevm.c +6
-0+/* iterate over algorithms provided by kernel-headers */ +for (i =0 ; i <HASH_ALGO__LAST ; i++) { +if (hash_algo_name[i] && + !algocmp (algo, hash_algo_name[i])) +return i; + }Assuming the two lists are in sync, which they should be, "i" could be set to
PKEY_HASH__LAST.
Can not do that, since pkey_hash_algo is currently sparse array and could skip entries which are present in hash_algo_name.
Note, that since "[PATCH v2 7/7] ima-evm-utils: Try to load digest by its alias" lists will have different semantics: the pkey_hash_algo list is compared algo names with strmatch which supports algo aliases, and the hash_algo_name list is compared using algocmp which does not compare non-alphanumeric chars such as _ and -, so streebog-512, streebog_512 or just streebog512 all would work (to match algo id).
Concluding, if you would not insist on parsing crypto/hash_info.c, I don't need fixing anything in this patch.
Thanks,
Mimi Zohar
maintainerQuoted 31 lines · Vitaly Chikunov
Quoted 24 lines · Mimi Zohar
Quoted 14 lines · Vitaly Chikunov
If configured with "--with-kernel-headers=PATH" try to extract hash algorithms from "
hash_info.h" from the kernel source tree or kernel-headers package located in the specified path. (Otherwise, it will be tried to get from the installed kernel.)This also introduces two algorithm lists, one is built-in and another is from the kernel source. (They should never contain conflicting algorithm IDs by their append-only nature.) If the digest is not found in the built-in list it will be searched in the list from kernel's "
hash_info.h".This patch will allow evmctl to be just recompiled to work with digest algorithms introduced in the newer kernels.
Quoted 8 lines
Suggested-by Mimi Zohar <[email protected]>Signed-off-by Vitaly Chikunov <[email protected]>---
Changes since v1:
- New patch.
Changes since v2:
- Mark PATH portion of "--with-kernel-headers=PATH" non-optional and change description to reflect correct behavior.Quoted 2 lines
Defaulting to the currently running kernel build tree would have been nice.
It already does. As description states "(Otherwise, it will be tried to get from the installed kernel.)" Also:
Quoted 8 lines
Quoted 4 lines
configure.ac AC_HEADER_STDC · line 40
Quoted 4 lines
configure.ac +4
-0+AC_ARG_WITH(kernel_headers, [AS_HELP_STRING([--with-kernel-headers=PATH], + [specifies the Linux kernel-headers package location or kernel root directory you want to use])], + [KERNEL_HEADERS="$withval"], + [KERNEL_HEADERS=/lib/modules/$(uname -r)/source])if "--with-kernel-headers" is not specified it will default to
/lib/modules/$(uname -r)/sourcewhich points to the kernel-headers or kernel source tree root.
I missed that.
<snip>
Quoted 16 lines
Quoted 6 lines
Quoted 6 lines
src/libimaevm.c +1
-0+/* first iterate over builtin algorithms */ for (i =0 ; i <PKEY_HASH__LAST ; i++)if (pkey_hash_algo[i] && !strcmp (algo, pkey_hash_algo[i]))return i;Quoted 9 lines
src/libimaevm.c int verify_hash_v2(const char *file, const unsigned char *hash, int size, · line 579
Quoted 6 lines
src/libimaevm.c +6
-0+/* iterate over algorithms provided by kernel-headers */ +for (i =0 ; i <HASH_ALGO__LAST ; i++) { +if (hash_algo_name[i] && + !algocmp (algo, hash_algo_name[i])) +return i; + }Assuming the two lists are in sync, which they should be, "i" could be set to
PKEY_HASH__LAST.
Quoted 2 lines
Can not do that, since
pkey_hash_algois currently sparse array and could skip entries which are present inhash_algo_name.
Missed that too.
Quoted 10 lines
Note, that since "[PATCH v2 7/7] ima-evm-utils: Try to load digest by its alias" lists will have different semantics: the
pkey_hash_algolist is compared algo names with strmatch which supports algo aliases, and thehash_algo_namelist is compared using algocmp which does not compare non-alphanumeric chars such as_and-, so streebog-512,streebog_512or just streebog512 all would work (to match algo id).Concluding, if you would not insist on parsing
crypto/hash_info.c, I don't need fixing anything in this patch.
Agreed, the patch looks fine as is.
Mimi