diff --git a/include/linux/evm.h b/include/linux/evm.h
index 4c374be70247..92856a7dbcab 100644
--- a/include/linux/evm.h
+++ b/include/linux/evm.h
@@ -11,6 +11,7 @@
 
 #include <linux/integrity.h>
 #include <linux/xattr.h>
+#include <crypto/hash_info.h>
 
 struct integrity_iint_cache;
 
@@ -42,6 +43,10 @@ extern int evm_protected_xattr_if_enabled(const char *req_xattr_name);
 extern int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
 				     int buffer_size, char type,
 				     bool canonical_fmt);
+extern int evm_get_hash(struct dentry *dentry, const char *req_xattr_name,
+			const char *req_xattr_value, size_t req_xattr_value_len,
+			char type, enum hash_algo algo, u8 *digest,
+			size_t digest_len);
 #ifdef CONFIG_FS_POSIX_ACL
 extern int posix_xattr_acl(const char *xattrname);
 #else
@@ -129,6 +134,15 @@ static inline int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
 {
 	return -EOPNOTSUPP;
 }
+static inline int evm_get_hash(struct dentry *dentry,
+			       const char *req_xattr_name,
+			       const char *req_xattr_value,
+			       size_t req_xattr_value_len, char type,
+			       enum hash_algo algo, u8 *digest,
+			       size_t digest_len)
+{
+	return -EOPNOTSUPP;
+}
 
 #endif /* CONFIG_EVM */
 #endif /* LINUX_EVM_H */
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index a8d7c761853e..3d45873f9266 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -429,6 +429,46 @@ enum integrity_status evm_verifyxattr(struct dentry *dentry,
 }
 EXPORT_SYMBOL_GPL(evm_verifyxattr);
 
+/**
+ * evm_get_hash - obtain the EVM digest calculated according to the passed type
+ * @dentry: object the EVM digest is calculated from
+ * @req_xattr_name: requested xattr
+ * @req_xattr_value: requested xattr value
+ * @req_xattr_value_len: requested xattr value length
+ * @type: requested security.evm type
+ * @algo: requested EVM digest algorithm
+ * @digest: the buffer the EVM digest is written to
+ * @digest_len: size of the buffer
+ *
+ * Calculate the EVM digest from metadata according to the passed security.evm
+ * type.
+ *
+ * Returns 0 if the digest has been calculated successfully, a negative value
+ * otherwise.
+ *
+ * This function requires the caller to lock the inode's i_mutex before it
+ * is executed.
+ */
+int evm_get_hash(struct dentry *dentry, const char *req_xattr_name,
+		 const char *req_xattr_value, size_t req_xattr_value_len,
+		 char type, enum hash_algo algo, u8 *digest, size_t digest_len)
+{
+	struct evm_digest evm_digest;
+	int rc;
+
+	if (digest_len < hash_digest_size[algo])
+		return -EINVAL;
+
+	evm_digest.hdr.algo = algo;
+	rc = evm_calc_hash(dentry, req_xattr_name, req_xattr_value,
+			   req_xattr_value_len, type, &evm_digest);
+	if (rc < 0)
+		return rc;
+
+	memcpy(digest, evm_digest.digest, hash_digest_size[algo]);
+	return 0;
+}
+
 /*
  * evm_verify_current_integrity - verify the dentry's metadata integrity
  * @dentry: pointer to the affected dentry
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index b32c4f8d19ea..84ccb76f6c3c 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/xattr.h>
 #include <linux/ima.h>
+#include <linux/evm.h>
 #include <linux/iversion.h>
 #include <linux/fs.h>
 
@@ -212,6 +213,44 @@ static void diglim_file_digest_lookup(struct file *file,
 			       COMPACT_FILE, modifiers, actions);
 }
 
+static void diglim_metadata_digest_lookup(struct file *file,
+					struct integrity_iint_cache *iint,
+					int action,
+					struct evm_ima_xattr_data *xattr_value,
+					int xattr_len, u16 *modifiers,
+					u8 *actions)
+{
+	u8 digest[IMA_MAX_DIGEST_SIZE];
+	struct evm_xattr fake_ima_xattr;
+	struct evm_ima_xattr_data *ima_xattr = xattr_value;
+	int rc;
+
+	if ((file->f_mode & FMODE_CREATED) && !i_size_read(file_inode(file)))
+		return;
+
+	if (!(iint->flags & IMA_COLLECTED))
+		return;
+
+	if (!xattr_value) {
+		fake_ima_xattr.data.type = IMA_XATTR_DIGEST_NG;
+		fake_ima_xattr.data.data[0] = iint->ima_hash->algo;
+		memcpy(&fake_ima_xattr.data.data[1], iint->ima_hash->digest,
+		       hash_digest_size[iint->ima_hash->algo]);
+		ima_xattr = &fake_ima_xattr.data;
+		xattr_len = 2 + hash_digest_size[iint->ima_hash->algo];
+	}
+
+	rc = evm_get_hash(file_dentry(file), XATTR_NAME_IMA,
+			  (const char *)ima_xattr, xattr_len,
+			  EVM_XATTR_PORTABLE_DIGSIG, iint->ima_hash->algo,
+			  digest, sizeof(digest));
+	if (rc < 0)
+		return;
+
+	diglim_digest_get_info(digest, iint->ima_hash->algo, COMPACT_METADATA,
+			       modifiers, actions);
+}
+
 static int process_measurement(struct file *file, const struct cred *cred,
 			       u32 secid, char *buf, loff_t size, int mask,
 			       enum ima_hooks func)
@@ -223,8 +262,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
 	char filename[NAME_MAX];
 	const char *pathname = NULL;
 	u64 action;
-	u16 file_modifiers = 0;
-	u8 file_actions = 0;
+	u16 file_modifiers = 0, metadata_modifiers = 0;
+	u8 file_actions = 0, metadata_actions = 0;
 	int rc = 0, must_appraise = 0;
 	int pcr = CONFIG_IMA_MEASURE_PCR_IDX;
 	struct evm_ima_xattr_data *xattr_value = NULL;
@@ -361,9 +400,15 @@ static int process_measurement(struct file *file, const struct cred *cred,
 		pathname = ima_d_path(&file->f_path, &pathbuf, filename);
 
 	if (iint->flags & IMA_USE_DIGLIM_MEASURE ||
-	    iint->flags & IMA_USE_DIGLIM_APPRAISE)
+	    iint->flags & IMA_USE_DIGLIM_APPRAISE) {
 		diglim_file_digest_lookup(file, iint, action, &file_modifiers,
 					  &file_actions);
+		inode_lock(inode);
+		diglim_metadata_digest_lookup(file, iint, action, xattr_value,
+					      xattr_len, &metadata_modifiers,
+					      &metadata_actions);
+		inode_unlock(inode);
+	}
 
 	if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) {
 		rc = ima_check_blacklist(iint, modsig, pcr);
