Blob Blame History Raw
From d14dce18a8fa31e2097d99a717d87b23539b9098 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 15 May 2019 15:55:17 -0400
Subject: [PATCH 14/42] Don't allow (or require) --module or --kernel with
 --ca.

If you're doing a CA/signer split setup, the CA shouldn't be allowed to
sign things other than other certificates.

Signed-off-by: Peter Jones <pjones@redhat.com>
---
 src/efikeygen.c | 55 ++++++++++++++++++++++++++++++++-----------------
 src/efikeygen.1 |  6 ++++--
 2 files changed, 40 insertions(+), 21 deletions(-)

diff --git a/src/efikeygen.c b/src/efikeygen.c
index 848480a9b01..b8b0c961739 100644
--- a/src/efikeygen.c
+++ b/src/efikeygen.c
@@ -54,6 +54,13 @@
 #include "cms_common.h"
 #include "oid.h"
 
+enum {
+	MODSIGN_EKU_NONE,
+	MODSIGN_EKU_KERNEL,
+	MODSIGN_EKU_MODULE,
+	MODSIGN_EKU_CA
+};
+
 typedef struct {
 	SECItem data;
 	SECAlgorithmID keytype;
@@ -183,8 +190,7 @@ add_key_usage(cms_context *cms, void *extHandle, int is_ca)
 
 	if (is_ca) {
 		usage = KU_KEY_CERT_SIGN |
-			KU_CRL_SIGN |
-			KU_DIGITAL_SIGNATURE;
+			KU_CRL_SIGN;
 	} else {
 		usage = KU_KEY_ENCIPHERMENT |
 			KU_DATA_ENCIPHERMENT |
@@ -252,7 +258,7 @@ add_basic_constraints(cms_context *cms, void *extHandle)
 }
 
 static int
-add_extended_key_usage(cms_context *cms, int modsign_only, void *extHandle)
+add_extended_key_usage(cms_context *cms, int modsign_eku, void *extHandle)
 {
 	SECItem values[2];
 	SECItem wrapped = { 0 };
@@ -260,7 +266,11 @@ add_extended_key_usage(cms_context *cms, int modsign_only, void *extHandle)
 	SECOidTag tag;
 	int rc;
 
-	if (modsign_only < 1 || modsign_only > 2)
+	if (modsign_eku == MODSIGN_EKU_CA)
+		return 0;
+
+	if (modsign_eku != MODSIGN_EKU_KERNEL
+	    && modsign_eku != MODSIGN_EKU_MODULE)
 		cmsreterr(-1, cms, "could not encode extended key usage");
 
 	rc = make_eku_oid(cms, &values[0], SEC_OID_EXT_KEY_USAGE_CODE_SIGN);
@@ -273,11 +283,10 @@ add_extended_key_usage(cms_context *cms, int modsign_only, void *extHandle)
 	if (rc < 0)
 		cmsreterr(-1, cms, "could not encode extended key usage");
 
-	rc = wrap_in_seq(cms, &wrapped, values, modsign_only);
+	rc = wrap_in_seq(cms, &wrapped, values, modsign_eku);
 	if (rc < 0)
 		cmsreterr(-1, cms, "could not encode extended key usage");
 
-
 	status = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE,
 					&wrapped, PR_FALSE, PR_TRUE);
 	if (status != SECSuccess)
@@ -311,7 +320,7 @@ static int
 add_extensions_to_crq(cms_context *cms, CERTCertificateRequest *crq,
 			int is_ca, int is_self_signed, SECKEYPublicKey *pubkey,
 			SECKEYPublicKey *spubkey,
-			char *url, int modsign_only)
+			char *url, int modsign_eku)
 {
 	void *mark = PORT_ArenaMark(cms->arena);
 
@@ -336,7 +345,7 @@ add_extensions_to_crq(cms_context *cms, CERTCertificateRequest *crq,
 	if (rc < 0)
 		cmsreterr(-1, cms, "could not generate certificate extensions");
 
-	rc = add_extended_key_usage(cms, modsign_only, extHandle);
+	rc = add_extended_key_usage(cms, modsign_eku, extHandle);
 	if (rc < 0)
 		cmsreterr(-1, cms, "could not generate certificate extensions");
 
@@ -486,7 +495,7 @@ int main(int argc, char *argv[])
 {
 	int is_ca = 0;
 	int is_self_signed = -1;
-	int modsign_only = 0;
+	int modsign_eku = MODSIGN_EKU_NONE;
 	char *tokenname = "NSS Certificate DB";
 	char *signer = NULL;
 	char *nickname = NULL;
@@ -543,14 +552,14 @@ int main(int argc, char *argv[])
 		{.longName = "kernel",
 		 .shortName = 'k',
 		 .argInfo = POPT_ARG_VAL|POPT_ARGFLAG_OR,
-		 .arg = &modsign_only,
-		 .val = 1,
+		 .arg = &modsign_eku,
+		 .val = MODSIGN_EKU_KERNEL,
 		 .descrip = "Generate a kernel-signing certificate" },
 		{.longName = "module",
 		 .shortName = 'm',
 		 .argInfo = POPT_ARG_VAL|POPT_ARGFLAG_OR,
-		 .arg = &modsign_only,
-		 .val = 2,
+		 .arg = &modsign_eku,
+		 .val = MODSIGN_EKU_MODULE,
 		 .descrip = "Generate a module-signing certificate" },
 		{.longName = "nickname",
 		 .shortName = 'n',
@@ -622,10 +631,12 @@ int main(int argc, char *argv[])
 	/*
 	 * Scenarios that are okay (x == valid combination)
 	 *
-	 *         is_ca        is_self_signed       pubkey
-	 * i_c     x            x                    x
-	 * i_s_s   x            x                    o
-	 * pubkey  x            o                    o
+	 *		is_ca   is_self_signed  pubkey	modules	kernel
+	 * i_c		x       x               x	o	o
+	 * i_s_s	x       x               o	o	o
+	 * pubkey	x       o               x	x	x
+	 * modules	o	x		x	x	x
+	 * kernel	o	x		x	x	x
 	 */
 
 	if (is_self_signed == -1)
@@ -660,8 +671,14 @@ int main(int argc, char *argv[])
 			liberr(1, "could not allocate cms context");
 	}
 
-	if (modsign_only < 1 || modsign_only > 2)
+	if (is_ca) {
+		if (modsign_eku != MODSIGN_EKU_NONE)
+			errx(1, "CA certificates cannot have kernel or module signing credentials.");
+		modsign_eku = MODSIGN_EKU_CA;
+	} else if (modsign_eku != MODSIGN_EKU_KERNEL
+		   && modsign_eku != MODSIGN_EKU_MODULE) {
 		errx(1, "either --kernel or --module must be used");
+	}
 
 	SECStatus status = NSS_InitReadWrite(dbdir);
 	if (status != SECSuccess)
@@ -752,7 +769,7 @@ int main(int argc, char *argv[])
 	crq = CERT_CreateCertificateRequest(name, spki, &attributes);
 
 	rc = add_extensions_to_crq(cms, crq, is_ca, is_self_signed, pubkey,
-					spubkey, url, modsign_only);
+					spubkey, url, modsign_eku);
 	if (rc < 0)
 		exit(1);
 
diff --git a/src/efikeygen.1 b/src/efikeygen.1
index 255fadc3979..88ee7c2f7c0 100644
--- a/src/efikeygen.1
+++ b/src/efikeygen.1
@@ -33,11 +33,13 @@ Nickname of certificate to be used to sign the generated certificate.
 
 .TP
 \fB-\-kernel\fR
-The generated certificate is to be used to sign kernels.
+The generated certificate is to be used to sign kernels.  Not to be used for CA
+certificates.
 
 .TP
 \fB-\-module\fR
-The generated certificate is to be used to sign kernel modules.
+The generated certificate is to be used to sign kernel modules.  Not to be used
+for CA certificates.
 
 .TP
 \fB-\-token\fR=\fItoken\fR
-- 
2.29.2