[PATCH v7 3/3] ima-evm-utils: Read keyid from the cert appended to the key file

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Allow to have certificate appended to the private key of `--key'
specified (PEM) file (for v2 signing) to facilitate reading of keyid
from the associated cert. This will allow users to have private and
public key as a single file and avoid the need of manually specifying
keyid. There is no check that public key form the cert matches
associated private key.

Signed-off-by: Vitaly Chikunov <vt@xxxxxxxxxxxx>
---
 README                 |  3 +++
 src/libimaevm.c        | 32 +++++++++++++++++++++++++++++---
 tests/gen-keys.sh      | 25 +++++++++++++++++++++----
 tests/sign_verify.test |  1 +
 4 files changed, 54 insertions(+), 7 deletions(-)

diff --git a/README b/README
index a130519..23e7d17 100644
--- a/README
+++ b/README
@@ -128,6 +128,9 @@ for signing and importing the key.
 Second key format uses X509 DER encoded public key certificates and uses asymmetric key support
 in the kernel (since kernel 3.9). CONFIG_INTEGRITY_ASYMMETRIC_KEYS must be enabled (default).
 
+For v2 signatures x509 certificate (containing the public key) could be appended to the
+private key (they both are in PEM format) to automatically extract keyid from its Subject
+Key Identifier (SKID).
 
 Integrity keyrings
 ----------------
diff --git a/src/libimaevm.c b/src/libimaevm.c
index c8a320e..15f702b 100644
--- a/src/libimaevm.c
+++ b/src/libimaevm.c
@@ -852,6 +852,28 @@ uint32_t imaevm_read_keyid(const char *certfile)
 	return ntohl(keyid_be);
 }
 
+/**
+ * read_keyid_from_key() - Read 32-bit keyid from the key file
+ * @keyid_be:   Pointer to 32-bit value in network order (BE, unaligned).
+ * @keyfile:    PEM file with private key with optionally appended x509 cert.
+ * Return:      0 on success and keyid_be is written;
+ *              -1 on error, logged error message, and keyid_be isn't written.
+ */
+static int read_keyid_from_key(uint32_t *keyid_be, const char *keyfile)
+{
+	X509 *x;
+
+	/* false: to try to read optional PEM cert. */
+	if (!(x = read_cert(keyfile, false)))
+		return -1;
+	if (extract_keyid(keyid_be, x, keyfile)) {
+		X509_free(x);
+		return -1;
+	}
+	X509_free(x);
+	return 0;
+}
+
 static EVP_PKEY *read_priv_pkey(const char *keyfile, const char *keypass)
 {
 	FILE *fp;
@@ -1036,10 +1058,14 @@ static int sign_hash_v2(const char *algo, const unsigned char *hash,
 		return -1;
 	}
 
-	if (imaevm_params.keyid)
+	if (imaevm_params.keyid) {
 		hdr->keyid = htonl(imaevm_params.keyid);
-	else
-		calc_keyid_v2(&hdr->keyid, name, pkey);
+	} else {
+		int keyid_read_failed = read_keyid_from_key(&hdr->keyid, keyfile);
+
+		if (keyid_read_failed)
+			calc_keyid_v2(&hdr->keyid, name, pkey);
+	}
 
 	st = "EVP_PKEY_CTX_new";
 	if (!(ctx = EVP_PKEY_CTX_new(pkey, NULL)))
diff --git a/tests/gen-keys.sh b/tests/gen-keys.sh
index 46130cf..d604c96 100755
--- a/tests/gen-keys.sh
+++ b/tests/gen-keys.sh
@@ -20,7 +20,7 @@ PATH=../src:$PATH
 type openssl
 
 log() {
-  echo - "$*"
+  echo >&2 - "$*"
   eval "$@"
 }
 
@@ -43,26 +43,43 @@ cat > test-ca.conf <<- EOF
 	basicConstraints=CA:TRUE
 	subjectKeyIdentifier=hash
 	authorityKeyIdentifier=keyid:always,issuer
+
+	[ skid ]
+	basicConstraints=CA:TRUE
+	subjectKeyIdentifier=12345678
+	authorityKeyIdentifier=keyid:always,issuer
 EOF
 fi
 
 # RSA
 # Second key will be used for wrong key tests.
-for m in 1024 2048; do
+for m in 1024 1024_skid 2048; do
   if [ "$1" = clean ] || [ "$1" = force ]; then
     rm -f test-rsa$m.cer test-rsa$m.key test-rsa$m.pub
   fi
   if [ "$1" = clean ]; then
     continue
   fi
+  if [ -z "${m%%*_*}" ]; then
+    # Add named extension.
+    bits=${m%_*}
+    ext="-extensions ${m#*_}"
+  else
+    bits=$m
+    ext=
+  fi
   if [ ! -e test-rsa$m.key ]; then
-    log openssl req -verbose -new -nodes -utf8 -sha1 -days 10000 -batch -x509 \
+    log openssl req -verbose -new -nodes -utf8 -sha1 -days 10000 -batch -x509 $ext \
       -config test-ca.conf \
-      -newkey rsa:$m \
+      -newkey rsa:$bits \
       -out test-rsa$m.cer -outform DER \
       -keyout test-rsa$m.key
     # for v1 signatures
     log openssl pkey -in test-rsa$m.key -out test-rsa$m.pub -pubout
+    if [ $m = 1024_skid ]; then
+      # Create combined key+cert.
+      log openssl x509 -inform DER -in test-rsa$m.cer >> test-rsa$m.key
+    fi
   fi
 done
 
diff --git a/tests/sign_verify.test b/tests/sign_verify.test
index 1fdd786..df4304a 100755
--- a/tests/sign_verify.test
+++ b/tests/sign_verify.test
@@ -367,6 +367,7 @@ sign_verify  rsa1024  sha1    0x030202:K:0080
 sign_verify  rsa1024  sha224  0x030207:K:0080
 expect_pass check_sign TYPE=ima KEY=rsa1024 ALG=sha256 PREFIX=0x030204aabbccdd0080 OPTS=--keyid=aabbccdd
 expect_pass check_sign TYPE=ima KEY=rsa1024 ALG=sha256 PREFIX=0x030204:K:0080 OPTS=--keyid-from-cert=test-rsa1024.cer
+expect_pass check_sign TYPE=ima KEY=rsa1024_skid ALG=sha256 PREFIX=0x030204123456780080
 sign_verify  rsa1024  sha256  0x030204:K:0080
   try_different_keys
   try_different_sigs
-- 
2.11.0




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux Kernel]     [Linux Kernel Hardening]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux