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