diff mbox series

[3/3] ima-evm-utils: Allow to use Streebog hash function

Message ID 20181126043953.1126-3-vt@altlinux.org (mailing list archive)
State Superseded
Headers show
Series [1/3] ima-avm-utils: Fix hash buffer overflow in verify_evm | expand

Commit Message

Vitaly Chikunov Nov. 26, 2018, 4:39 a.m. UTC
There are two methods of using GOST algorithms in OpenSSL: via config
extension and via --engine option. Both require gost-engine to be
installed.

Signed-off-by: Vitaly Chikunov <vt@altlinux.org>
---
 src/evmctl.c    | 27 ++++++++++++++++++++++++---
 src/imaevm.h    | 13 +++++++++++++
 src/libimaevm.c | 15 +++++++++++----
 3 files changed, 48 insertions(+), 7 deletions(-)

Comments

Mimi Zohar Nov. 27, 2018, 11:56 a.m. UTC | #1
On Mon, 2018-11-26 at 07:39 +0300, Vitaly Chikunov wrote:
> There are two methods of using GOST algorithms in OpenSSL: via config
> extension and via --engine option. Both require gost-engine to be
> installed.

Splitting this patch based on the "--engine" option, will make it
easier to review.

> 
> Signed-off-by: Vitaly Chikunov <vt@altlinux.org>
> ---
>  src/evmctl.c    | 27 ++++++++++++++++++++++++---
>  src/imaevm.h    | 13 +++++++++++++
>  src/libimaevm.c | 15 +++++++++++----
>  3 files changed, 48 insertions(+), 7 deletions(-)

<snip>

> diff --git a/src/imaevm.h b/src/imaevm.h
> index 1bafaad..1a5ebbe 100644
> --- a/src/imaevm.h
> +++ b/src/imaevm.h
> @@ -149,6 +149,7 @@ struct signature_hdr {
>  	char mpi[0];
>  } __packed;
> 
> +/* reflect enum hash_algo from include/uapi/linux/hash_info.h */
>  enum pkey_hash_algo {
>  	PKEY_HASH_MD4,
>  	PKEY_HASH_MD5,
> @@ -158,6 +159,18 @@ enum pkey_hash_algo {
>  	PKEY_HASH_SHA384,
>  	PKEY_HASH_SHA512,
>  	PKEY_HASH_SHA224,
> +	PKEY_HASH_RIPE_MD_128,
> +	PKEY_HASH_RIPE_MD_256,
> +	PKEY_HASH_RIPE_MD_320,
> +	PKEY_HASH_WP_256,
> +	PKEY_HASH_WP_384,
> +	PKEY_HASH_WP_512,
> +	PKEY_HASH_TGR_128,
> +	PKEY_HASH_TGR_160,
> +	PKEY_HASH_TGR_192,
> +	PKEY_HASH_SM3_256,
> +	PKEY_HASH_STREEBOG_256,
> +	PKEY_HASH_STREEBOG_512,
>  	PKEY_HASH__LAST
>  };
> 
> diff --git a/src/libimaevm.c b/src/libimaevm.c
> index 714f1ac..8f74660 100644
> --- a/src/libimaevm.c
> +++ b/src/libimaevm.c
> @@ -50,6 +50,7 @@
>  #include <string.h>
>  #include <stdio.h>
> 
> +#include <openssl/crypto.h>
>  #include <openssl/pem.h>
>  #include <openssl/evp.h>
>  #include <openssl/x509.h>
> @@ -66,6 +67,8 @@ const char *const pkey_hash_algo[PKEY_HASH__LAST] = {
>  	[PKEY_HASH_SHA384]	= "sha384",
>  	[PKEY_HASH_SHA512]	= "sha512",
>  	[PKEY_HASH_SHA224]	= "sha224",
> +	[PKEY_HASH_STREEBOG_256] = "streebog256",
> +	[PKEY_HASH_STREEBOG_512] = "streebog512",
>  };

hash_info.h is now included in kernel-headers package.

Anyone using the hash_algo enumeration defined in hash_info.h, will
probably also want to use an associated algorithm name.  It would make
more sense to keep the hash_algo enumeration, hash_algo_name[], and
perhaps the hash_digest_size[] together.  Maybe using macros to keep
them in sync (eg. kernel_read_file_id/kernel_read_file_str).

As new algorithms are added to hash_info.h, nothing would need to be
done here in ima-evm-utils, other than updating the maximum digest
size.

What do you think?

Mimi
Vitaly Chikunov Nov. 27, 2018, 1:08 p.m. UTC | #2
Mimi,

On Tue, Nov 27, 2018 at 06:56:51AM -0500, Mimi Zohar wrote:
> On Mon, 2018-11-26 at 07:39 +0300, Vitaly Chikunov wrote:
> <snip>
> > diff --git a/src/imaevm.h b/src/imaevm.h
> > index 1bafaad..1a5ebbe 100644
> > --- a/src/imaevm.h
> > +++ b/src/imaevm.h
> > @@ -149,6 +149,7 @@ struct signature_hdr {
> >  	char mpi[0];
> >  } __packed;
> > 
> > +/* reflect enum hash_algo from include/uapi/linux/hash_info.h */
> >  enum pkey_hash_algo {
> >  	PKEY_HASH_MD4,
> >  	PKEY_HASH_MD5,
> > @@ -158,6 +159,18 @@ enum pkey_hash_algo {
> >  	PKEY_HASH_SHA384,
> >  	PKEY_HASH_SHA512,
> >  	PKEY_HASH_SHA224,
> > +	PKEY_HASH_RIPE_MD_128,
> > +	PKEY_HASH_RIPE_MD_256,
> > +	PKEY_HASH_RIPE_MD_320,
> > +	PKEY_HASH_WP_256,
> > +	PKEY_HASH_WP_384,
> > +	PKEY_HASH_WP_512,
> > +	PKEY_HASH_TGR_128,
> > +	PKEY_HASH_TGR_160,
> > +	PKEY_HASH_TGR_192,
> > +	PKEY_HASH_SM3_256,
> > +	PKEY_HASH_STREEBOG_256,
> > +	PKEY_HASH_STREEBOG_512,
> >  	PKEY_HASH__LAST
> >  };
> > 
> > diff --git a/src/libimaevm.c b/src/libimaevm.c
> > index 714f1ac..8f74660 100644
> > --- a/src/libimaevm.c
> > +++ b/src/libimaevm.c
> > @@ -50,6 +50,7 @@
> >  #include <string.h>
> >  #include <stdio.h>
> > 
> > +#include <openssl/crypto.h>
> >  #include <openssl/pem.h>
> >  #include <openssl/evp.h>
> >  #include <openssl/x509.h>
> > @@ -66,6 +67,8 @@ const char *const pkey_hash_algo[PKEY_HASH__LAST] = {
> >  	[PKEY_HASH_SHA384]	= "sha384",
> >  	[PKEY_HASH_SHA512]	= "sha512",
> >  	[PKEY_HASH_SHA224]	= "sha224",
> > +	[PKEY_HASH_STREEBOG_256] = "streebog256",
> > +	[PKEY_HASH_STREEBOG_512] = "streebog512",
> >  };
> 
> hash_info.h is now included in kernel-headers package.

I think, first it should not be coincided with the new algo adding and
being follow-up patch (if any).

> Anyone using the hash_algo enumeration defined in hash_info.h, will
> probably also want to use an associated algorithm name.  It would make
> more sense to keep the hash_algo enumeration, hash_algo_name[], and
> perhaps the hash_digest_size[] together.  Maybe using macros to keep
> them in sync (eg. kernel_read_file_id/kernel_read_file_str).

On the first sight this sounds good, but...

It sounds like it will require patching kernel's hash_info.h, so it will
be not possible to transfer smoothly on the new scheme without breaking
some compatibility (of the newer ima-evm-utils with older kernels). Also,
it is possible that ima-evm-utils is used on the older stable box (where some
reliable and stable build system run) which does not have such modification
and/or new algorithms in the kernel but willing to generate signatures.

So, I think code duplication between projects is good in this case.

Some hash algorithms may be wished to be compatible with rsa pkcs1
signature scheme, which is also defined in kernel in
crypto/rsa-pkcs1pad.c and in ima-evm-utils in src/libimaevm.c so code
duplication and adding algorithms in both sources will happen anyway.

Thanks,


> As new algorithms are added to hash_info.h, nothing would need to be
> done here in ima-evm-utils, other than updating the maximum digest
> size.
> 
> What do you think?
> 
> Mimi
Mimi Zohar Nov. 27, 2018, 1:33 p.m. UTC | #3
On Tue, 2018-11-27 at 16:08 +0300, Vitaly Chikunov wrote:

> > hash_info.h is now included in kernel-headers package.
> 
> I think, first it should not be coincided with the new algo adding and
> being follow-up patch (if any).
> 
> > Anyone using the hash_algo enumeration defined in hash_info.h, will
> > probably also want to use an associated algorithm name.  It would make
> > more sense to keep the hash_algo enumeration, hash_algo_name[], and
> > perhaps the hash_digest_size[] together.  Maybe using macros to keep
> > them in sync (eg. kernel_read_file_id/kernel_read_file_str).
> 
> On the first sight this sounds good, but...
> 
> It sounds like it will require patching kernel's hash_info.h, so it will
> be not possible to transfer smoothly on the new scheme without breaking
> some compatibility (of the newer ima-evm-utils with older kernels).  Also,
> it is possible that ima-evm-utils is used on the older stable box (where some
> reliable and stable build system run) which does not have such modification
> and/or new algorithms in the kernel but willing to generate signatures.
> 
> So, I think code duplication between projects is good in this case.

The sooner the kernel's hash_info.h is updated, the better.  For the
time being, ima-evm-utils could define these definitions in a separate
file that is/isn't included based on autotools/buildtime option.

> 
> Some hash algorithms may be wished to be compatible with rsa pkcs1
> signature scheme, which is also defined in kernel in
> crypto/rsa-pkcs1pad.c and in ima-evm-utils in src/libimaevm.c so code
> duplication and adding algorithms in both sources will happen anyway.
> 
> Thanks,

There might be multiple problems, but fixing one is better than not
fixing either.

Mimi
diff mbox series

Patch

diff --git a/src/evmctl.c b/src/evmctl.c
index 032ea9d..5b4d8d9 100644
--- a/src/evmctl.c
+++ b/src/evmctl.c
@@ -62,6 +62,7 @@ 
 #include <openssl/hmac.h>
 #include <openssl/err.h>
 #include <openssl/rsa.h>
+#include <openssl/engine.h>
 
 #ifndef XATTR_APPAARMOR_SUFFIX
 #define XATTR_APPARMOR_SUFFIX "apparmor"
@@ -388,7 +389,7 @@  static int calc_evm_hash(const char *file, unsigned char *hash)
 
 	md = EVP_get_digestbyname(params.hash_algo);
 	if (!md) {
-		log_err("EVP_get_digestbyname() failed\n");
+		log_err("EVP_get_digestbyname(%s) failed\n", params.hash_algo);
 		return 1;
 	}
 
@@ -1056,7 +1057,7 @@  static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char *h
 
 	md = EVP_get_digestbyname(params.hash_algo);
 	if (!md) {
-		log_err("EVP_get_digestbyname() failed\n");
+		log_err("EVP_get_digestbyname(%s) failed\n", params.hash_algo);
 		goto out;
 	}
 
@@ -1643,7 +1644,7 @@  static void usage(void)
 
 	printf(
 		"\n"
-		"  -a, --hashalgo     sha1 (default), sha224, sha256, sha384, sha512\n"
+		"  -a, --hashalgo     sha1 (default), sha224, sha256, sha384, sha512, streebog256, streebog512\n"
 		"  -s, --imasig       make IMA signature\n"
 		"  -d, --imahash      make IMA hash\n"
 		"  -f, --sigfile      store IMA signature in .sig file instead of xattr\n"
@@ -1669,6 +1670,7 @@  static void usage(void)
 		"      --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"
+		"      --engine e     preload OpenSSL engine e\n"
 		"  -v                 increase verbosity level\n"
 		"  -h, --help         display this help and exit\n"
 		"\n");
@@ -1721,6 +1723,7 @@  static struct option opts[] = {
 	{"selinux", 1, 0, 136},
 	{"caps", 2, 0, 137},
 	{"list", 0, 0, 138},
+	{"engine", 1, 0, 139},
 	{"xattr-user", 0, 0, 140},
 	{}
 
@@ -1763,6 +1766,7 @@  static char *get_password(void)
 int main(int argc, char *argv[])
 {
 	int err = 0, c, lind;
+	ENGINE *eng = NULL;
 
 	g_argv = argv;
 	g_argc = argc;
@@ -1873,6 +1877,16 @@  int main(int argc, char *argv[])
 		case 138:
 			measurement_list = 1;
 			break;
+		case 139: /* --engine e */
+			eng = ENGINE_by_id(optarg);
+			if (!eng)
+				log_err("engine %s isn't available\n", optarg);
+			else if (!ENGINE_init(eng)) {
+				log_err("engine %s init failed\n", optarg);
+				ENGINE_free(eng);
+				eng = NULL;
+			}
+			break;
 		case 140: /* --xattr-user */
 			xattr_ima = "user.ima";
 			xattr_evm = "user.evm";
@@ -1903,6 +1917,13 @@  int main(int argc, char *argv[])
 		}
 	}
 
+	if (eng) {
+		ENGINE_finish(eng);
+		ENGINE_free(eng);
+#if OPENSSL_API_COMPAT < 0x10100000L
+		ENGINE_cleanup();
+#endif
+	}
 	ERR_free_strings();
 	EVP_cleanup();
 	BIO_free(NULL);
diff --git a/src/imaevm.h b/src/imaevm.h
index 1bafaad..1a5ebbe 100644
--- a/src/imaevm.h
+++ b/src/imaevm.h
@@ -149,6 +149,7 @@  struct signature_hdr {
 	char mpi[0];
 } __packed;
 
+/* reflect enum hash_algo from include/uapi/linux/hash_info.h */
 enum pkey_hash_algo {
 	PKEY_HASH_MD4,
 	PKEY_HASH_MD5,
@@ -158,6 +159,18 @@  enum pkey_hash_algo {
 	PKEY_HASH_SHA384,
 	PKEY_HASH_SHA512,
 	PKEY_HASH_SHA224,
+	PKEY_HASH_RIPE_MD_128,
+	PKEY_HASH_RIPE_MD_256,
+	PKEY_HASH_RIPE_MD_320,
+	PKEY_HASH_WP_256,
+	PKEY_HASH_WP_384,
+	PKEY_HASH_WP_512,
+	PKEY_HASH_TGR_128,
+	PKEY_HASH_TGR_160,
+	PKEY_HASH_TGR_192,
+	PKEY_HASH_SM3_256,
+	PKEY_HASH_STREEBOG_256,
+	PKEY_HASH_STREEBOG_512,
 	PKEY_HASH__LAST
 };
 
diff --git a/src/libimaevm.c b/src/libimaevm.c
index 714f1ac..8f74660 100644
--- a/src/libimaevm.c
+++ b/src/libimaevm.c
@@ -50,6 +50,7 @@ 
 #include <string.h>
 #include <stdio.h>
 
+#include <openssl/crypto.h>
 #include <openssl/pem.h>
 #include <openssl/evp.h>
 #include <openssl/x509.h>
@@ -66,6 +67,8 @@  const char *const pkey_hash_algo[PKEY_HASH__LAST] = {
 	[PKEY_HASH_SHA384]	= "sha384",
 	[PKEY_HASH_SHA512]	= "sha512",
 	[PKEY_HASH_SHA224]	= "sha224",
+	[PKEY_HASH_STREEBOG_256] = "streebog256",
+	[PKEY_HASH_STREEBOG_512] = "streebog512",
 };
 
 /*
@@ -290,7 +293,7 @@  int ima_calc_hash(const char *file, uint8_t *hash)
 
 	md = EVP_get_digestbyname(params.hash_algo);
 	if (!md) {
-		log_err("EVP_get_digestbyname() failed\n");
+		log_err("EVP_get_digestbyname(%s) failed\n", params.hash_algo);
 		return 1;
 	}
 
@@ -508,14 +511,16 @@  int verify_hash_v2(const char *file, const unsigned char *hash, int size,
 	asn1 = &RSA_ASN1_templates[hdr->hash_algo];
 
 	if (len < asn1->size || memcmp(out, asn1->data, asn1->size)) {
-		log_err("%s: verification failed: %d\n", file, err);
+		log_err("%s: verification failed: %d (asn1 mismatch)\n",
+			file, err);
 		return -1;
 	}
 
 	len -= asn1->size;
 
 	if (len != size || memcmp(out + asn1->size, hash, len)) {
-		log_err("%s: verification failed: %d\n", file, err);
+		log_err("%s: verification failed: %d (digest mismatch)\n",
+			file, err);
 		return -1;
 	}
 
@@ -527,7 +532,8 @@  int get_hash_algo(const char *algo)
 	int i;
 
 	for (i = 0; i < PKEY_HASH__LAST; i++)
-		if (!strcmp(algo, pkey_hash_algo[i]))
+		if (pkey_hash_algo[i] &&
+		    !strcmp(algo, pkey_hash_algo[i]))
 			return i;
 
 	return PKEY_HASH_SHA1;
@@ -899,5 +905,6 @@  int sign_hash(const char *hashalgo, const unsigned char *hash, int size, const c
 static void libinit()
 {
 	OpenSSL_add_all_algorithms();
+	OPENSSL_add_all_algorithms_conf();
 	ERR_load_crypto_strings();
 }