[v3,07/10] KEYS: X.509: Flag Intermediate CA certs as endorsed
Commit Message
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
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
@@ -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);
@@ -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,
@@ -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);
@@ -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);