diff mbox series

[v2,4/5] keys: define build time generated ephemeral kernel CA key

Message ID 20210218220011.67625-5-nayna@linux.ibm.com (mailing list archive)
State New
Headers show
Series ima: kernel build support for loading the kernel module signing key | expand

Commit Message

Nayna Jain Feb. 18, 2021, 10 p.m. UTC
Certificates being loaded onto the IMA trusted keyring must be signed by
a key on either the builtin or secondary trusted keyring. Create and
include in the kernel image an ephemeral CA key at build time when
IMA_APPRAISE_MODSIG is enabled.

Reported-by: kernel test robot <lkp@intel.com> (redirect openssl stderr)
Signed-off-by: Nayna Jain <nayna@linux.ibm.com>
---
 Makefile                    |  2 ++
 certs/Makefile              | 68 ++++++++++++++++++++++++++++++++++---
 certs/system_certificates.S | 16 ++++++++-
 3 files changed, 80 insertions(+), 6 deletions(-)

Comments

Stefan Berger Feb. 19, 2021, 3:25 p.m. UTC | #1
On 2/18/21 5:00 PM, Nayna Jain wrote:
> Certificates being loaded onto the IMA trusted keyring must be signed by
> a key on either the builtin or secondary trusted keyring. Create and
> include in the kernel image an ephemeral CA key at build time when
> IMA_APPRAISE_MODSIG is enabled.
>
> Reported-by: kernel test robot <lkp@intel.com> (redirect openssl stderr)
> Signed-off-by: Nayna Jain <nayna@linux.ibm.com>
> ---
>   Makefile                    |  2 ++
>   certs/Makefile              | 68 ++++++++++++++++++++++++++++++++++---
>   certs/system_certificates.S | 16 ++++++++-
>   3 files changed, 80 insertions(+), 6 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index a971d4ae40bd..15e8344836b1 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1475,6 +1475,8 @@ MRPROPER_FILES += include/config include/generated          \
>   		  certs/signing_key.pem certs/signing_key.x509 \
>   		  certs/x509.genkey certs/signing_key.key \
>   		  certs/signing_key.crt certs/signing_key.csr \
> +		  certs/ca_signing_key.pem certs/ca_signing_key.x509 \
> +		  certs/ca_signing_key.srl \
>   		  vmlinux-gdb.py \
>   		  *.spec
>   
> diff --git a/certs/Makefile b/certs/Makefile
> index b2be7eb413d3..3fe6b73786fa 100644
> --- a/certs/Makefile
> +++ b/certs/Makefile
> @@ -32,6 +32,14 @@ endif # CONFIG_SYSTEM_TRUSTED_KEYRING
>   clean-files := x509_certificate_list .x509.list
>   
>   ifeq ($(CONFIG_MODULE_SIG),y)
> +SIGN_KEY = y
> +endif
> +
> +ifeq ($(CONFIG_IMA_APPRAISE_MODSIG),y)
> +SIGN_KEY = y
> +endif
> +
> +ifdef SIGN_KEY
>   ###############################################################################
>   #
>   # If module signing is requested, say by allyesconfig, but a key has not been
> @@ -51,6 +59,16 @@ silent_redirect_openssl = 2>/dev/null
>   # external private key, because 'make randconfig' might enable such a
>   # boolean option and we unfortunately can't make it depend on !RANDCONFIG.
>   ifeq ($(CONFIG_MODULE_SIG_KEY),"certs/signing_key.pem")
> +
> +ifeq ($(CONFIG_IMA_APPRAISE_MODSIG),y)
> +# openssl arguments for CA Signed certificate.
> +CA_KEY = certs/ca_signing_key.pem
> +SIGNER = -CA $(CA_KEY) -CAkey $(CA_KEY) -CAcreateserial
> +else
> +# openssl arguments for Self Signed certificate.
> +SIGNER = -signkey $(obj)/signing_key.key
> +endif # CONFIG_IMA_APPRAISE_MODSIG
> +
>   $(obj)/signing_key.pem: $(obj)/x509.genkey
>   	@$(kecho) "###"
>   	@$(kecho) "### Now generating an X.509 key pair to be used for signing modules."
> @@ -60,14 +78,23 @@ $(obj)/signing_key.pem: $(obj)/x509.genkey
>   	@$(kecho) "### needs to be run as root, and uses a hardware random"
>   	@$(kecho) "### number generator if one is available."
>   	@$(kecho) "###"
> +ifeq ($(CONFIG_IMA_APPRAISE_MODSIG),y)
> +	# Generate kernel build time CA Certificate.
> +	@$(Q)openssl req -new -nodes -utf8 \
> +		-$(CONFIG_MODULE_SIG_HASH) -days 36500 \
> +		-subj "/CN=Build time autogenerated kernel CA key" \
> +		-batch -x509 -config $(obj)/x509.genkey \
> +		-outform PEM -out $(CA_KEY) \
> +		-keyout $(CA_KEY) -extensions ca_ext \
> +		$($(quiet)redirect_openssl)
> +endif # CONFIG_IMA_APPRAISE_MODSIG
>   	$(Q)openssl req -new -nodes -utf8 \
>   		-batch -config $(obj)/x509.genkey \
>   		-outform PEM -out $(obj)/signing_key.csr \
>   		-keyout $(obj)/signing_key.key -extensions myexts \
>   		$($(quiet)redirect_openssl)
>   	$(Q)openssl x509 -req -days 36500 -in $(obj)/signing_key.csr \
> -		-outform PEM -out $(obj)/signing_key.crt \
> -		-signkey $(obj)/signing_key.key \
> +		-outform PEM -out $(obj)/signing_key.crt $(SIGNER) \
>   		-$(CONFIG_MODULE_SIG_HASH) -extensions myexts \
>   		-extfile $(obj)/x509.genkey \
>   		$($(quiet)redirect_openssl)
> @@ -95,19 +122,50 @@ $(obj)/x509.genkey:
>   	@echo >>$@ "keyUsage=digitalSignature"
>   	@echo >>$@ "subjectKeyIdentifier=hash"
>   	@echo >>$@ "authorityKeyIdentifier=keyid"
> +	@echo >>$@
> +	@echo >>$@ "[ ca_ext ]"
> +	@echo >>$@ "keyUsage=critical,keyCertSign"
> +	@echo >>$@ "basicConstraints=critical,CA:TRUE,pathlen:0"
> +	@echo >>$@ "subjectKeyIdentifier=hash"
> +	@echo >>$@ "authorityKeyIdentifier=keyid"
>   endif # CONFIG_MODULE_SIG_KEY
>   
>   $(eval $(call config_filename,MODULE_SIG_KEY))
> +SUBJECT=CN = Build time autogenerated kernel key
> +ISSUER=$(shell openssl x509 -in certs/signing_key.crt -noout -issuer $($(quiet)redirect_openssl))
>   
>   # If CONFIG_MODULE_SIG_KEY isn't a PKCS#11 URI, depend on it
> +
> +# GCC PR#66871 again.
> +ifeq ($(CONFIG_IMA_APPRAISE_MODSIG),y)
> +
> +# Remove existing keys if it is self-signed.
> +$(if $(findstring $(SUBJECT),$(ISSUER)),$(shell rm -f certs/signing_key.* certs/x509.genkey))
> +CA_KEY = certs/ca_signing_key.pem
> +
> +$(obj)/system_certificates.o: $(obj)/ca_signing_key.x509 $(obj)/signing_key.x509
> +
> +targets += ca_signing_key.x509
> +$(obj)/ca_signing_key.x509: $(obj)/signing_key.x509 scripts/extract-cert FORCE
> +	$(call if_changed,extract_certs,$(CA_KEY))
> +
> +targets += signing_key.x509
> +$(obj)/signing_key.x509: $(obj)/signing_key.pem scripts/extract-cert FORCE
> +	$(call if_changed,extract_certs,$(MODULE_SIG_KEY_SRCPREFIX)$(CONFIG_MODULE_SIG_KEY))
> +else
> +
> +# Remove existing keys if it is CA signed.
> +$(if $(findstring $(SUBJECT),$(ISSUER)),,$(shell rm -f certs/ca_signing_key.* certs/signing_key.* certs/x509.genkey))
> +
>   ifeq ($(patsubst pkcs11:%,%,$(firstword $(MODULE_SIG_KEY_FILENAME))),$(firstword $(MODULE_SIG_KEY_FILENAME)))
>   X509_DEP := $(MODULE_SIG_KEY_SRCPREFIX)$(MODULE_SIG_KEY_FILENAME)
>   endif
>   
> -# GCC PR#66871 again.

I think you should keep this comment at this place here.


>   $(obj)/system_certificates.o: $(obj)/signing_key.x509
>   
>   targets += signing_key.x509
> -$(obj)/signing_key.x509: scripts/extract-cert $(X509_DEP) FORCE
> +$(obj)/signing_key.x509: certs/signing_key.pem scripts/extract-cert $(X509_DEP) FORCE
>   	$(call if_changed,extract_certs,$(MODULE_SIG_KEY_SRCPREFIX)$(CONFIG_MODULE_SIG_KEY))
> -endif # CONFIG_MODULE_SIG
> +
> +endif # CONFIG_IMA_APPRAISE_MODSIG
> +endif # SIGN_KEY
> diff --git a/certs/system_certificates.S b/certs/system_certificates.S
> index 8f29058adf93..e10043800a7e 100644
> --- a/certs/system_certificates.S
> +++ b/certs/system_certificates.S
> @@ -8,8 +8,13 @@
>   	.globl system_certificate_list
>   system_certificate_list:
>   __cert_list_start:
> -#ifdef CONFIG_MODULE_SIG
> +__module_cert_start:
> +#if defined(CONFIG_MODULE_SIG) || defined(CONFIG_IMA_APPRAISE_MODSIG)
>   	.incbin "certs/signing_key.x509"
> +#endif
> +__module_cert_end:
> +#ifdef CONFIG_IMA_APPRAISE_MODSIG
> +	.incbin "certs/ca_signing_key.x509"
>   #endif
>   	.incbin "certs/x509_certificate_list"
>   __cert_list_end:
> @@ -35,3 +40,12 @@ system_certificate_list_size:
>   #else
>   	.long __cert_list_end - __cert_list_start
>   #endif
> +
> +	.align 8
> +	.globl module_cert_size
> +	module_cert_size:
> +#ifdef CONFIG_64BIT
> +	.quad __module_cert_end - __module_cert_start
> +#else
> +	.long __module_cert_end - __module_cert_start
> +#endif
diff mbox series

Patch

diff --git a/Makefile b/Makefile
index a971d4ae40bd..15e8344836b1 100644
--- a/Makefile
+++ b/Makefile
@@ -1475,6 +1475,8 @@  MRPROPER_FILES += include/config include/generated          \
 		  certs/signing_key.pem certs/signing_key.x509 \
 		  certs/x509.genkey certs/signing_key.key \
 		  certs/signing_key.crt certs/signing_key.csr \
+		  certs/ca_signing_key.pem certs/ca_signing_key.x509 \
+		  certs/ca_signing_key.srl \
 		  vmlinux-gdb.py \
 		  *.spec
 
diff --git a/certs/Makefile b/certs/Makefile
index b2be7eb413d3..3fe6b73786fa 100644
--- a/certs/Makefile
+++ b/certs/Makefile
@@ -32,6 +32,14 @@  endif # CONFIG_SYSTEM_TRUSTED_KEYRING
 clean-files := x509_certificate_list .x509.list
 
 ifeq ($(CONFIG_MODULE_SIG),y)
+SIGN_KEY = y
+endif
+
+ifeq ($(CONFIG_IMA_APPRAISE_MODSIG),y)
+SIGN_KEY = y
+endif
+
+ifdef SIGN_KEY
 ###############################################################################
 #
 # If module signing is requested, say by allyesconfig, but a key has not been
@@ -51,6 +59,16 @@  silent_redirect_openssl = 2>/dev/null
 # external private key, because 'make randconfig' might enable such a
 # boolean option and we unfortunately can't make it depend on !RANDCONFIG.
 ifeq ($(CONFIG_MODULE_SIG_KEY),"certs/signing_key.pem")
+
+ifeq ($(CONFIG_IMA_APPRAISE_MODSIG),y)
+# openssl arguments for CA Signed certificate.
+CA_KEY = certs/ca_signing_key.pem
+SIGNER = -CA $(CA_KEY) -CAkey $(CA_KEY) -CAcreateserial
+else
+# openssl arguments for Self Signed certificate.
+SIGNER = -signkey $(obj)/signing_key.key
+endif # CONFIG_IMA_APPRAISE_MODSIG
+
 $(obj)/signing_key.pem: $(obj)/x509.genkey
 	@$(kecho) "###"
 	@$(kecho) "### Now generating an X.509 key pair to be used for signing modules."
@@ -60,14 +78,23 @@  $(obj)/signing_key.pem: $(obj)/x509.genkey
 	@$(kecho) "### needs to be run as root, and uses a hardware random"
 	@$(kecho) "### number generator if one is available."
 	@$(kecho) "###"
+ifeq ($(CONFIG_IMA_APPRAISE_MODSIG),y)
+	# Generate kernel build time CA Certificate.
+	@$(Q)openssl req -new -nodes -utf8 \
+		-$(CONFIG_MODULE_SIG_HASH) -days 36500 \
+		-subj "/CN=Build time autogenerated kernel CA key" \
+		-batch -x509 -config $(obj)/x509.genkey \
+		-outform PEM -out $(CA_KEY) \
+		-keyout $(CA_KEY) -extensions ca_ext \
+		$($(quiet)redirect_openssl)
+endif # CONFIG_IMA_APPRAISE_MODSIG
 	$(Q)openssl req -new -nodes -utf8 \
 		-batch -config $(obj)/x509.genkey \
 		-outform PEM -out $(obj)/signing_key.csr \
 		-keyout $(obj)/signing_key.key -extensions myexts \
 		$($(quiet)redirect_openssl)
 	$(Q)openssl x509 -req -days 36500 -in $(obj)/signing_key.csr \
-		-outform PEM -out $(obj)/signing_key.crt \
-		-signkey $(obj)/signing_key.key \
+		-outform PEM -out $(obj)/signing_key.crt $(SIGNER) \
 		-$(CONFIG_MODULE_SIG_HASH) -extensions myexts \
 		-extfile $(obj)/x509.genkey \
 		$($(quiet)redirect_openssl)
@@ -95,19 +122,50 @@  $(obj)/x509.genkey:
 	@echo >>$@ "keyUsage=digitalSignature"
 	@echo >>$@ "subjectKeyIdentifier=hash"
 	@echo >>$@ "authorityKeyIdentifier=keyid"
+	@echo >>$@
+	@echo >>$@ "[ ca_ext ]"
+	@echo >>$@ "keyUsage=critical,keyCertSign"
+	@echo >>$@ "basicConstraints=critical,CA:TRUE,pathlen:0"
+	@echo >>$@ "subjectKeyIdentifier=hash"
+	@echo >>$@ "authorityKeyIdentifier=keyid"
 endif # CONFIG_MODULE_SIG_KEY
 
 $(eval $(call config_filename,MODULE_SIG_KEY))
+SUBJECT=CN = Build time autogenerated kernel key
+ISSUER=$(shell openssl x509 -in certs/signing_key.crt -noout -issuer $($(quiet)redirect_openssl))
 
 # If CONFIG_MODULE_SIG_KEY isn't a PKCS#11 URI, depend on it
+
+# GCC PR#66871 again.
+ifeq ($(CONFIG_IMA_APPRAISE_MODSIG),y)
+
+# Remove existing keys if it is self-signed.
+$(if $(findstring $(SUBJECT),$(ISSUER)),$(shell rm -f certs/signing_key.* certs/x509.genkey))
+CA_KEY = certs/ca_signing_key.pem
+
+$(obj)/system_certificates.o: $(obj)/ca_signing_key.x509 $(obj)/signing_key.x509
+
+targets += ca_signing_key.x509
+$(obj)/ca_signing_key.x509: $(obj)/signing_key.x509 scripts/extract-cert FORCE
+	$(call if_changed,extract_certs,$(CA_KEY))
+
+targets += signing_key.x509
+$(obj)/signing_key.x509: $(obj)/signing_key.pem scripts/extract-cert FORCE
+	$(call if_changed,extract_certs,$(MODULE_SIG_KEY_SRCPREFIX)$(CONFIG_MODULE_SIG_KEY))
+else
+
+# Remove existing keys if it is CA signed.
+$(if $(findstring $(SUBJECT),$(ISSUER)),,$(shell rm -f certs/ca_signing_key.* certs/signing_key.* certs/x509.genkey))
+
 ifeq ($(patsubst pkcs11:%,%,$(firstword $(MODULE_SIG_KEY_FILENAME))),$(firstword $(MODULE_SIG_KEY_FILENAME)))
 X509_DEP := $(MODULE_SIG_KEY_SRCPREFIX)$(MODULE_SIG_KEY_FILENAME)
 endif
 
-# GCC PR#66871 again.
 $(obj)/system_certificates.o: $(obj)/signing_key.x509
 
 targets += signing_key.x509
-$(obj)/signing_key.x509: scripts/extract-cert $(X509_DEP) FORCE
+$(obj)/signing_key.x509: certs/signing_key.pem scripts/extract-cert $(X509_DEP) FORCE
 	$(call if_changed,extract_certs,$(MODULE_SIG_KEY_SRCPREFIX)$(CONFIG_MODULE_SIG_KEY))
-endif # CONFIG_MODULE_SIG
+
+endif # CONFIG_IMA_APPRAISE_MODSIG
+endif # SIGN_KEY
diff --git a/certs/system_certificates.S b/certs/system_certificates.S
index 8f29058adf93..e10043800a7e 100644
--- a/certs/system_certificates.S
+++ b/certs/system_certificates.S
@@ -8,8 +8,13 @@ 
 	.globl system_certificate_list
 system_certificate_list:
 __cert_list_start:
-#ifdef CONFIG_MODULE_SIG
+__module_cert_start:
+#if defined(CONFIG_MODULE_SIG) || defined(CONFIG_IMA_APPRAISE_MODSIG)
 	.incbin "certs/signing_key.x509"
+#endif
+__module_cert_end:
+#ifdef CONFIG_IMA_APPRAISE_MODSIG
+	.incbin "certs/ca_signing_key.x509"
 #endif
 	.incbin "certs/x509_certificate_list"
 __cert_list_end:
@@ -35,3 +40,12 @@  system_certificate_list_size:
 #else
 	.long __cert_list_end - __cert_list_start
 #endif
+
+	.align 8
+	.globl module_cert_size
+	module_cert_size:
+#ifdef CONFIG_64BIT
+	.quad __module_cert_end - __module_cert_start
+#else
+	.long __module_cert_end - __module_cert_start
+#endif