diff --git a/certs/system_keyring.c b/certs/system_keyring.c
index c05c29ae4d5d..fc7147db4222 100644
--- a/certs/system_keyring.c
+++ b/certs/system_keyring.c
@@ -287,3 +287,10 @@ void __init set_platform_trusted_keys(struct key 
*keyring)
  	platform_trusted_keys = keyring;
  }
  #endif
+
+#ifdef CONFIG_IMA_MEASURE_TRUSTED_KEYS
+struct key *get_builtin_trusted_keys(void)
+{
+	return builtin_trusted_keys;
+}
+#endif /* CONFIG_IMA_MEASURE_TRUSTED_KEYS */
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
index 42a93eda331c..0378355513a9 100644
--- a/include/keys/system_keyring.h
+++ b/include/keys/system_keyring.h
@@ -70,4 +70,13 @@ static inline void set_platform_trusted_keys(struct 
key *keyring)
  }
  #endif

+#ifdef CONFIG_IMA_MEASURE_TRUSTED_KEYS
+extern struct key *get_builtin_trusted_keys(void);
+#else
+static struct key *get_builtin_trusted_keys(void)
+{
+	return NULL;
+}
+#endif /* CONFIG_IMA_MEASURE_TRUSTED_KEYS */
+
  #endif /* _KEYS_SYSTEM_KEYRING_H */
diff --git a/include/linux/key.h b/include/linux/key.h
index 7099985e35a9..3afcc26fa4dc 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -349,6 +349,38 @@ extern void key_set_timeout(struct key *, unsigned);
  extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags,
  				 key_perm_t perm);

+/*
+ * Context data used to iterate through the keys in a keyring
+ * and read the key references into an array.
+ *
+ *  keyring_keys_count - Number of keys in keyring_keys array
+ *  keyring_keys_size - Max number of keys in keyring_keys array
+ *  keyring_keys - Array containing keys read from the keyring
+ */
+struct keyring_keys_read_context {
+	size_t keyring_keys_size;
+	size_t keyring_keys_count;
+	const struct key *keyring_keys[0];
+};
+
+#ifdef CONFIG_IMA_MEASURE_TRUSTED_KEYS
+extern long keyring_read_keys(const struct key *keyring,
+				struct keyring_keys_read_context **ctx);
+extern long keyring_read_builtin_trusted_keys(
+				struct keyring_keys_read_context **ctx);
+#else
+static inline long keyring_read_keys(const struct key *keyring,
+			 struct keyring_keys_read_context **ctx)
+{
+	return -EOPNOTSUPP;
+}
+static inline long keyring_read_builtin_trusted_keys(
+	struct keyring_keys_read_context **ctx)
+{
+	return -EOPNOTSUPP;
+}
+#endif /* CONFIG_IMA_MEASURE_TRUSTED_KEYS */
+
  /*
   * The permissions required on a key that we're looking up.
   */
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index e19c2eb72c51..7e0423478d30 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -179,3 +179,61 @@ int __init integrity_load_cert(const unsigned int 
id, const char *source,
  	pr_info("Loading X.509 certificate: %s\n", source);
  	return integrity_add_key(id, data, len, perm);
  }
+
+#ifdef CONFIG_IMA_MEASURE_TRUSTED_KEYS
+static int __init store_trusted_keyring_keys(
+			struct keyring_keys_read_context *ctx,
+			int (*store_trusted_key)(
+				void *key,
+				u32 keylen,
+				const char *key_description))
+{
+	int rc = 0;
+	size_t inx;
+
+	for (inx = 0; inx < ctx->keyring_keys_count; inx++) {
+		const struct key *trusted_key = ctx->keyring_keys[inx];
+		const struct public_key *pk;
+
+		pk = query_public_key(trusted_key);
+		if (pk != NULL) {
+			rc = store_trusted_key(pk->key, pk->keylen,
+						trusted_key->description);
+
+			if (rc < 0)
+				break;
+		}
+	}
+
+	return rc;
+}
+
+int __init ima_add_trusted_keyring_keys(int (*store_trusted_key)(
+			void *key,
+			u32 keylen,
+			const char *key_description))
+{
+	struct keyring_keys_read_context *ctx = NULL;
+	int rc;
+
+	// First measure keys from "BuiltIn_Trusted_Keys" keyring
+	rc = keyring_read_builtin_trusted_keys(&ctx);
+	if (rc < 0)
+		return rc;
+	store_trusted_keyring_keys(ctx, store_trusted_key);
+	kfree(ctx);
+	ctx = NULL;
+
+	// Next measure keys from IMA keyring
+	if (keyring[INTEGRITY_KEYRING_IMA]) {
+		rc = keyring_read_keys(keyring[INTEGRITY_KEYRING_IMA], &ctx);
+		if (rc < 0)
+			return rc;
+		store_trusted_keyring_keys(ctx, store_trusted_key);
+		kfree(ctx);
+		ctx = NULL;
+	}
+
+	return 0;
+}
+#endif
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index a18f8c6d13b5..4c1f1a794a6c 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -295,3 +295,12 @@ config IMA_APPRAISE_SIGNED_INIT
  	default n
  	help
  	   This option requires user-space init to be signed.
+
+config IMA_MEASURE_TRUSTED_KEYS
+	bool "Measure the public keys of trusted keys"
+	depends on IMA
+	default n
+	help
+	   This option enables keys in keyrings such as
+	   Builtin Trusted Keys, IMA, Platform, etc. to
+	   be measured during IMA initialization
diff --git a/security/integrity/ima/ima_init.c 
b/security/integrity/ima/ima_init.c
index 6c9295449751..4ad0cf4825b8 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -93,6 +93,61 @@ static int __init ima_add_boot_aggregate(void)
  	return result;
  }

+#ifdef CONFIG_IMA_MEASURE_TRUSTED_KEYS
+int __init store_trusted_keyring_key(void *key,
+					u32 keylen, const char *key_description)
+{
+	static const char op[] = "store_trusted_keyring_key";
+	const char *audit_cause = "ENOMEM";
+	struct ima_template_entry *entry;
+	struct integrity_iint_cache tmp_iint, *iint = &tmp_iint;
+	struct ima_event_data event_data = {iint, NULL, key_description,
+					    NULL, 0, NULL};
+	int result = -ENOMEM;
+	int violation = 0;
+	struct {
+		struct ima_digest_data hdr;
+		char digest[TPM_DIGEST_SIZE];
+	} hash;
+
+	if (key == NULL || keylen == 0)
+		return 0;
+
+	memset(iint, 0, sizeof(*iint));
+	memset(&hash, 0, sizeof(hash));
+	iint->ima_hash = &hash.hdr;
+	iint->ima_hash->algo = HASH_ALGO_SHA1;
+	iint->ima_hash->length = SHA1_DIGEST_SIZE;
+
+	result = ima_calc_buffer_hash(key, keylen, &hash.hdr);
+	if (result < 0) {
+		audit_cause = "hashing_error";
+		goto err_out;
+	}
+
+	result = ima_alloc_init_template(&event_data, &entry);
+	if (result < 0) {
+		audit_cause = "alloc_entry";
+		goto err_out;
+	}
+
+	result = ima_store_template(entry, violation, NULL,
+					key_description,
+					CONFIG_IMA_MEASURE_PCR_IDX);
+	if (result < 0) {
+		ima_free_template_entry(entry);
+		audit_cause = "store_entry";
+		goto err_out;
+	}
+	return 0;
+err_out:
+	integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL,
+				key_description, op,
+				audit_cause, result, 0);
+	return result;
+}
+#endif /* CONFIG_IMA_MEASURE_TRUSTED_KEYS */
+
  #ifdef CONFIG_IMA_LOAD_X509
  void __init ima_load_x509(void)
  {
@@ -133,6 +188,13 @@ int __init ima_init(void)
  	if (rc != 0)
  		return rc;

+#ifdef CONFIG_IMA_MEASURE_TRUSTED_KEYS
+	/* Measure keys from trusted keyrings */
+	rc = ima_add_trusted_keyring_keys(store_trusted_keyring_key);
+	if (rc != 0)
+		return rc;
+#endif /* CONFIG_IMA_MEASURE_TRUSTED_KEYS */
+
  	ima_init_policy();

  	return ima_fs_init();
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 7de59f44cba3..050edde06fcf 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -242,3 +242,28 @@ static inline void __init 
add_to_platform_keyring(const char *source,
  {
  }
  #endif
+
+#ifdef CONFIG_IMA_MEASURE_TRUSTED_KEYS
+int __init ima_add_trusted_keyring_keys(int (*store_trusted_key)(
+			void *key,
+			u32 keylen,
+			const char *key_description));
+
+int __init store_trusted_keyring_key(void *key,
+					u32 keylen,
+					const char *key_description);
+#else
+static int __init ima_add_trusted_keyring_keys(int (*store_trusted_key)(
+			void *key,
+			u32 keylen,
+			const char *key_description))
+{
+	return -EOPNOTSUPP;
+}
+static int __init store_trusted_keyring_key(void *key,
+					u32 keylen,
+					const char *key_description)
+{
+	return -EOPNOTSUPP;
+}
+#endif /* CONFIG_IMA_MEASURE_TRUSTED_KEYS */
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index e14f09e3a4b0..37865ff2b234 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -20,6 +20,7 @@
  #include <keys/user-type.h>
  #include <linux/assoc_array_priv.h>
  #include <linux/uaccess.h>
+#include <keys/system_keyring.h>
  #include "internal.h"

  /*
@@ -1583,3 +1584,84 @@ void keyring_restriction_gc(struct key *keyring, 
struct key_type *dead_type)

  	kleave(" [restriction gc]");
  }
+
+#ifdef CONFIG_IMA_MEASURE_TRUSTED_KEYS
+static int keyring_keys_iterator(const void *object, void *data)
+{
+	struct keyring_keys_read_context *ctx = data;
+	const struct key *key = keyring_ptr_to_key(object);
+
+	if (ctx->keyring_keys_count >= ctx->keyring_keys_size)
+		return 1;
+
+	ctx->keyring_keys[ctx->keyring_keys_count++] = key;
+	return 0;
+}
+
+/*
+ * Read a list of keys from the given keyring.
+ *  keyring - Keyring to read the list of keys from
+ *  ctx - Keyring data is returned in this.
+ *
+ * Memory for keyring_keys_read_context is allocated here.
+ * Caller is responsible for freeing this buffer.
+ */
+long keyring_read_keys(const struct key *keyring,
+			 struct keyring_keys_read_context **ctx)
+{
+	long ret;
+	long keycount;
+
+	kenter("{%d}", key_serial(keyring));
+
+	if (ctx == NULL) {
+		kleave(" = %ld [invalid ctx]", ret);
+		return -EINVAL;
+	}
+
+	rcu_read_lock();
+	keycount = keyring->keys.nr_leaves_on_tree;
+	rcu_read_unlock();
+
+	// Allocate context data. Caller must free this memory
+	*ctx = kzalloc(sizeof(struct keyring_keys_read_context) +
+			keycount * sizeof(struct key *), GFP_KERNEL);
+	if (*ctx == NULL) {
+		kleave(" = %ld [no memory]", ret);
+		return -ENOMEM;
+	}
+
+	(*ctx)->keyring_keys_size = keycount;
+	(*ctx)->keyring_keys_count = 0;
+
+	if (keycount == 0) {
+		kleave(" = %ld [keyring empty]", ret);
+		return 0;
+	}
+
+	rcu_read_lock();
+	ret = assoc_array_iterate(&keyring->keys,
+					  keyring_keys_iterator, *ctx);
+	if (ret == 0)
+		kleave(" = %ld [ok]", ret);
+	else
+		kleave(" = %ld [error]", ret);
+	rcu_read_unlock();
+
+	return ret;
+}
+
+/*
+ * Read a list of keys from builtin_trusted_keys keyring.
+ *  ctx - Keyring data is returned in this.
+ *
+ * Memory for keyring_keys_read_context is allocated here.
+ * Caller is responsible for freeing this buffer.
+ */
+long keyring_read_builtin_trusted_keys(
+	struct keyring_keys_read_context **ctx)
+{
+	return keyring_read_keys(get_builtin_trusted_keys(), ctx);
+}
+
