Re: [PATCH v2 2/3] ima-evm-utils: Allow manual setting keyid from a cert file

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

 




On 5/4/21 12:33 AM, Vitaly Chikunov wrote:
Allow user to specify `--keyid @/path/to/cert.pem' to extract keyid from
SKID of the certificate file. PEM or DER format is auto-detected.

`--keyid' option is reused instead of adding a new option (like possible
`--cert') to signify to the user it's only keyid extraction and nothing
more.

Signed-off-by: Vitaly Chikunov <vt@xxxxxxxxxxxx>
---
  README                 |  1 +
  src/evmctl.c           | 82 +++++++++++++++++++++++++++++++++++++++++++++++---
  tests/sign_verify.test |  1 +
  3 files changed, 79 insertions(+), 5 deletions(-)

diff --git a/README b/README
index 8cd66e0..0e1f6ba 100644
--- a/README
+++ b/README
@@ -49,6 +49,7 @@ OPTIONS
        --rsa          use RSA key type and signing scheme v1
    -k, --key          path to signing key (default: /etc/keys/{privkey,pubkey}_evm.pem)
        --keyid val    overwrite signature keyid with a value (for signing)
+                     val is a x509 cert file if prefixed with '@'
    -o, --portable     generate portable EVM signatures
    -p, --pass         password for encrypted signing key
    -r, --recursive    recurse into directories (sign)
diff --git a/src/evmctl.c b/src/evmctl.c
index 7983299..fdb0fb3 100644
--- a/src/evmctl.c
+++ b/src/evmctl.c
@@ -42,6 +42,7 @@
  #include <sys/param.h>
  #include <sys/stat.h>
  #include <sys/ioctl.h>
+#include <arpa/inet.h>
  #include <fcntl.h>
  #include <unistd.h>
  #include <stdlib.h>
@@ -57,12 +58,14 @@
  #include <termios.h>
  #include <assert.h>
+#include <openssl/asn1.h>
  #include <openssl/sha.h>
  #include <openssl/pem.h>
  #include <openssl/hmac.h>
  #include <openssl/err.h>
  #include <openssl/rsa.h>
  #include <openssl/engine.h>
+#include <openssl/x509v3.h>
  #include "hash_info.h"
  #include "pcr.h"
  #include "utils.h"
@@ -2447,6 +2450,7 @@ static void usage(void)
  		"      --rsa          use RSA key type and signing scheme v1\n"
  		"  -k, --key          path to signing key (default: /etc/keys/{privkey,pubkey}_evm.pem)\n"
  		"      --keyid val    overwrite signature keyid with a value (for signing)\n"
+		"                     val is a x509 cert file if prefixed with '@'\n"
  		"  -o, --portable     generate portable EVM signatures\n"
  		"  -p, --pass         password for encrypted signing key\n"
  		"  -r, --recursive    recurse into directories (sign)\n"
@@ -2567,12 +2571,71 @@ static char *get_password(void)
  	return pwd;
  }
+/* Return true if FILE is possibly PEM encoded (otherwise DER). */
+static int is_encoding_pem(FILE *in)
+{
+	char buf[6]; /* Room for the 5 minus signs and '\0'. */
+	int pem = 0;
+
+	if (fgets(buf, sizeof(buf), in) &&
+	    strspn(buf, "-") == sizeof(buf) - 1)
+		pem = 1;
+	rewind(in);
+	return pem;
+}
+
+/* Extract keyid from SKID of the cert. No return on error. */
+static unsigned long int extract_keyid(const char *certfile)
+{
+	uint32_t keyid_raw;
+	const ASN1_OCTET_STRING *skid;
+	int skid_len;
+	X509 *x = NULL;
+	int pem;
+	FILE *in;
+
+	if (!(in = fopen(certfile, "r"))) {
+		log_err("Cannot open cert file %s: %s\n", certfile,
+			strerror(errno));
+		exit(1);
+	}
+	if ((pem = is_encoding_pem(in)))


I think you should not try to detect PEM by '-----' at the beginning since it typically allows other text at the beginning of the file as well, such as a text dump of the cert. Instead search for '-----BEGIN CERTIFICATE-----' in the whole file or just try to read it as PEM first and then fall back to DER decoding if PEM failed.



+		x = PEM_read_X509(in, &x, NULL, NULL);
+	else
+		x = d2i_X509_fp(in, &x);
+	if (!x) {
+		ERR_print_errors_fp(stderr);
+		log_err("Cannot read x509 cert from %s file %s\n",
+			pem? "PEM" : "DER", certfile);
+		fclose(in);
+		exit(1);
+	}
+	fclose(in);
+
+	if (!(skid = X509_get0_subject_key_id(x))) {
+		log_err("%s: SKID not found\n", certfile);
+		goto err_free;
+	}
+	skid_len = ASN1_STRING_length(skid);
+	if (skid_len < sizeof(keyid_raw)) {
+		log_err("%s: SKID too short (len %d)\n", certfile, skid_len);
+		goto err_free;
+	}
+	memcpy(&keyid_raw, ASN1_STRING_get0_data(skid) + skid_len
+	       - sizeof(keyid_raw), sizeof(keyid_raw));
+	log_info("keyid %04x (from %s)\n", ntohl(keyid_raw), certfile);
+	return ntohl(keyid_raw);
+
+err_free:
+	X509_free(x);
+	exit(1);
+}
+
  int main(int argc, char *argv[])
  {
  	int err = 0, c, lind;
  	ENGINE *eng = NULL;
  	unsigned long int keyid;
-	char *eptr;
#if !(OPENSSL_VERSION_NUMBER < 0x10100000)
  	OPENSSL_init_crypto(
@@ -2718,10 +2781,19 @@ int main(int argc, char *argv[])
  			pcrfile[npcrfile++] = optarg;
  			break;
  		case 143:
-			errno = 0;
-			keyid = strtoul(optarg, &eptr, 16);
-			if (errno || eptr - optarg != strlen(optarg) ||
-			    keyid > UINT_MAX || keyid == 0) {
+			if (optarg[0] == '@') {
+				keyid = extract_keyid(optarg + 1);
+			} else {
+				char *eptr;
+
+				errno = 0;
+				keyid = strtoul(optarg, &eptr, 16);
+				if (eptr - optarg != strlen(optarg) || errno) {
+					log_err("Invalid keyid value.\n");
+					exit(1);
+				}
+			}
+			if (keyid > UINT_MAX || keyid == 0) {
  				log_err("Invalid keyid value.\n");
  				exit(1);
  			}
diff --git a/tests/sign_verify.test b/tests/sign_verify.test
index 2c21812..52ea33a 100755
--- a/tests/sign_verify.test
+++ b/tests/sign_verify.test
@@ -360,6 +360,7 @@ sign_verify  rsa1024  md5     0x030201:K:0080
  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=@test-rsa1024.cer
  sign_verify  rsa1024  sha256  0x030204:K:0080
    try_different_keys
    try_different_sigs



[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