[v3,07/10] KEYS: X.509: Flag Intermediate CA certs as endorsed

Message ID 20221214003401.4086781-8-eric.snowberg@oracle.com
State New
Headers
Series Add CA enforcement keyring restrictions |

Commit Message

Eric Snowberg Dec. 14, 2022, 12:33 a.m. UTC
  Currently X.509 intermediate certs with the CA flag set to false do not
have the endorsed CA (KEY_FLAG_ECA) set. Allow these intermediate certs to
be added.  Requirements for an intermediate include: Usage extension
defined as keyCertSign, Basic Constrains for CA is false, and the
intermediate cert is signed by a current endorsed CA.

Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
---
 crypto/asymmetric_keys/x509_public_key.c | 14 ++++++++++++--
 include/linux/ima.h                      | 11 +++++++++++
 include/linux/key-type.h                 |  1 +
 security/keys/key.c                      |  5 +++++
 4 files changed, 29 insertions(+), 2 deletions(-)
  

Comments

Mimi Zohar Dec. 15, 2022, 10:21 a.m. UTC | #1
Hi Eric,

On Tue, 2022-12-13 at 19:33 -0500, Eric Snowberg wrote:
> Currently X.509 intermediate certs with the CA flag set to false do not
> have the endorsed CA (KEY_FLAG_ECA) set. Allow these intermediate certs to
> be added.  Requirements for an intermediate include: Usage extension
> defined as keyCertSign, Basic Constrains for CA is false, and the
> intermediate cert is signed by a current endorsed CA.

Intermediary keys should have the CA flag enabled as well.   Why is
this needed?    At least for the new Kconfig, please keep it simple as
to which certificates may be added to the machine keyring.

thanks,

Mimi
  

Patch

diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index fd1d7d6e68e7..75699987a6b1 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -208,8 +208,18 @@  static int x509_key_preparse(struct key_preparsed_payload *prep)
 		goto error_free_kids;
 	}
 
-	if (cert->kcs_set && cert->root_ca)
-		prep->payload_flags |= KEY_ALLOC_PECA;
+	if (cert->kcs_set) {
+		if (cert->root_ca)
+			prep->payload_flags |= KEY_ALLOC_PECA;
+		/*
+		 * In this case it could be an Intermediate CA.  Set
+		 * KEY_MAYBE_PECA for now.  If the restriction check
+		 * passes later, the key will be allocated with the
+		 * correct CA flag
+		 */
+		else
+			prep->payload_flags |= KEY_MAYBE_PECA;
+	}
 
 	/* We're pinning the module by being linked against it */
 	__module_get(public_key_subtype.owner);
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 81708ca0ebc7..6597081b6b1a 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -12,6 +12,7 @@ 
 #include <linux/security.h>
 #include <linux/kexec.h>
 #include <crypto/hash_info.h>
+#include <keys/system_keyring.h>
 struct linux_binprm;
 
 #ifdef CONFIG_IMA
@@ -181,6 +182,16 @@  static inline void ima_post_key_create_or_update(struct key *keyring,
 						 bool create) {}
 #endif  /* CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS */
 
+#ifdef CONFIG_ASYMMETRIC_KEY_TYPE
+#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
+#define ima_validate_builtin_ca restrict_link_by_ca_builtin_and_secondary_trusted
+#else
+#define ima_validate_builtin_ca restrict_link_by_ca_builtin_trusted
+#endif
+#else
+#define ima_validate_builtin_ca restrict_link_reject
+#endif
+
 #ifdef CONFIG_IMA_APPRAISE
 extern bool is_ima_appraise_enabled(void);
 extern void ima_inode_post_setattr(struct user_namespace *mnt_userns,
diff --git a/include/linux/key-type.h b/include/linux/key-type.h
index 0b500578441c..0d2f95f6b8a1 100644
--- a/include/linux/key-type.h
+++ b/include/linux/key-type.h
@@ -38,6 +38,7 @@  struct key_preparsed_payload {
 	time64_t	expiry;		/* Expiry time of key */
 	unsigned int	payload_flags;  /* Proposed payload flags */
 #define KEY_ALLOC_PECA	0x0001		/* Proposed Endorsed CA (ECA) key */
+#define KEY_MAYBE_PECA	0x0002		/* Proposed possible ECA key */
 } __randomize_layout;
 
 typedef int (*request_key_actor_t)(struct key *auth_key, void *aux);
diff --git a/security/keys/key.c b/security/keys/key.c
index e6b4946aca70..69d5f143683f 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -900,6 +900,11 @@  key_ref_t key_create_or_update(key_ref_t keyring_ref,
 		}
 	}
 
+	/* Previous restriction check passed therefore try to validate endorsed ca */
+	if ((prep.payload_flags & KEY_MAYBE_PECA) &&
+	   !(ima_validate_builtin_ca(keyring, index_key.type, &prep.payload, NULL)))
+		prep.payload_flags |= KEY_ALLOC_PECA;
+
 	/* if we're going to allocate a new key, we're going to have
 	 * to modify the keyring */
 	ret = key_permission(keyring_ref, KEY_NEED_WRITE);