All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mimi Zohar <zohar@linux.ibm.com>
To: linux-integrity@vger.kernel.org
Cc: Mimi Zohar <zohar@linux.ibm.com>,
	Eric Biggers <ebiggers@kernel.org>,
	Stefan Berger <stefanb@linux.ibm.com>
Subject: [PATCH 1/3] ima: Define asymmetric_verify_v3() to verify IMA sigv3 signatures
Date: Tue, 24 Mar 2026 16:39:27 -0400	[thread overview]
Message-ID: <20260324203929.2475782-2-zohar@linux.ibm.com> (raw)
In-Reply-To: <20260324203929.2475782-1-zohar@linux.ibm.com>

Define asymmetric_verify_v3() to calculate the hash of the struct
ima_file_id, before calling asymmetric_verify() to verify the
signature.

Move and update the existing calc_file_id_hash() function with a
simpler, self contained version.  In addition to the existing hash
data and hash data length arguments, also pass the hash algorithm.

Suggested-by: Stefan Berger <stefanb@linux.ibm.com>
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
---
 security/integrity/digsig.c            |  8 ++--
 security/integrity/digsig_asymmetric.c | 58 ++++++++++++++++++++++++
 security/integrity/evm/evm_main.c      |  3 +-
 security/integrity/ima/ima_appraise.c  | 63 ++++++--------------------
 security/integrity/integrity.h         | 14 +++++-
 5 files changed, 90 insertions(+), 56 deletions(-)

diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index 75c684cce370..1ed686154d7a 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -59,7 +59,7 @@ static struct key *integrity_keyring_from_id(const unsigned int id)
 }
 
 int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
-			    const char *digest, int digestlen)
+			    const char *digest, int digestlen, u8 algo)
 {
 	struct key *keyring;
 
@@ -76,9 +76,11 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
 		return digsig_verify(keyring, sig + 1, siglen - 1, digest,
 				     digestlen);
 	case 2: /* regular file data hash based signature */
-	case 3: /* struct ima_file_id data based signature */
 		return asymmetric_verify(keyring, sig, siglen, digest,
-					 digestlen);
+					    digestlen);
+	case 3: /* struct ima_file_id data based signature */
+		return asymmetric_verify_v3(keyring, sig, siglen, digest,
+					    digestlen, algo);
 	}
 
 	return -EOPNOTSUPP;
diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c
index 87be85f477d1..dc5313746609 100644
--- a/security/integrity/digsig_asymmetric.c
+++ b/security/integrity/digsig_asymmetric.c
@@ -131,3 +131,61 @@ int asymmetric_verify(struct key *keyring, const char *sig,
 	pr_debug("%s() = %d\n", __func__, ret);
 	return ret;
 }
+
+/*
+ * calc_file_id_hash - calculate the hash of the ima_file_id struct data
+ * @type: xattr type [enum evm_ima_xattr_type]
+ * @algo: hash algorithm [enum hash_algo]
+ * @digest: pointer to the digest to be hashed
+ * @hash: (out) pointer to the hash
+ *
+ * IMA signature version 3 disambiguates the data that is signed by
+ * indirectly signing the hash of the ima_file_id structure data.
+ *
+ * Return 0 on success, error code otherwise.
+ */
+static int calc_file_id_hash(enum evm_ima_xattr_type type,
+			     enum hash_algo algo, const u8 *digest,
+			     struct ima_max_digest_data *hash)
+{
+	struct ima_file_id file_id = {.hash_type = type, .hash_algorithm = algo};
+	size_t digest_size = hash_digest_size[algo];
+	struct crypto_shash *tfm;
+	size_t file_id_size;
+	int rc;
+
+	if (type != IMA_VERITY_DIGSIG)
+		return -EINVAL;
+
+	tfm = crypto_alloc_shash(hash_algo_name[algo], 0, 0);
+	if (IS_ERR(tfm))
+		return PTR_ERR(tfm);
+
+	memcpy(file_id.hash, digest, digest_size);
+
+	/* Calculate the ima_file_id struct hash on the portion used. */
+	file_id_size = sizeof(file_id) - (HASH_MAX_DIGESTSIZE - digest_size);
+
+	hash->hdr.algo = algo;
+	hash->hdr.length = digest_size;
+	rc = crypto_shash_tfm_digest(tfm, (const u8 *)&file_id, file_id_size,
+				     hash->digest);
+
+	crypto_free_shash(tfm);
+	return rc;
+}
+
+int asymmetric_verify_v3(struct key *keyring, const char *sig, int siglen,
+			 const char *data, int datalen, u8 algo)
+{
+	struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig;
+	struct ima_max_digest_data hash;
+	int rc;
+
+	rc = calc_file_id_hash(hdr->type, algo, data, &hash);
+	if (rc)
+		return -EINVAL;
+
+	return asymmetric_verify(keyring, sig, siglen, hash.digest,
+				 hash.hdr.length);
+}
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 1b0089b4b796..b15d9d933b84 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -266,7 +266,8 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
 			break;
 		rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM,
 					(const char *)xattr_data, xattr_len,
-					digest.digest, digest.hdr.length);
+					digest.digest, digest.hdr.length,
+					digest.hdr.algo);
 		if (!rc) {
 			if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG) {
 				if (iint)
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 0d41d102626a..5b42307ac254 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -234,40 +234,6 @@ int ima_read_xattr(struct dentry *dentry,
 	return ret;
 }
 
-/*
- * calc_file_id_hash - calculate the hash of the ima_file_id struct data
- * @type: xattr type [enum evm_ima_xattr_type]
- * @algo: hash algorithm [enum hash_algo]
- * @digest: pointer to the digest to be hashed
- * @hash: (out) pointer to the hash
- *
- * IMA signature version 3 disambiguates the data that is signed by
- * indirectly signing the hash of the ima_file_id structure data.
- *
- * Signing the ima_file_id struct is currently only supported for
- * IMA_VERITY_DIGSIG type xattrs.
- *
- * Return 0 on success, error code otherwise.
- */
-static int calc_file_id_hash(enum evm_ima_xattr_type type,
-			     enum hash_algo algo, const u8 *digest,
-			     struct ima_digest_data *hash)
-{
-	struct ima_file_id file_id = {
-		.hash_type = IMA_VERITY_DIGSIG, .hash_algorithm = algo};
-	unsigned int unused = HASH_MAX_DIGESTSIZE - hash_digest_size[algo];
-
-	if (type != IMA_VERITY_DIGSIG)
-		return -EINVAL;
-
-	memcpy(file_id.hash, digest, hash_digest_size[algo]);
-
-	hash->algo = algo;
-	hash->length = hash_digest_size[algo];
-
-	return ima_calc_buffer_hash(&file_id, sizeof(file_id) - unused, hash);
-}
-
 /*
  * xattr_verify - verify xattr digest or signature
  *
@@ -279,7 +245,6 @@ static int xattr_verify(enum ima_hooks func, struct ima_iint_cache *iint,
 			struct evm_ima_xattr_data *xattr_value, int xattr_len,
 			enum integrity_status *status, const char **cause)
 {
-	struct ima_max_digest_data hash;
 	struct signature_v2_hdr *sig;
 	int rc = -EINVAL, hash_start = 0;
 	int mask;
@@ -341,7 +306,8 @@ static int xattr_verify(enum ima_hooks func, struct ima_iint_cache *iint,
 					     (const char *)xattr_value,
 					     xattr_len,
 					     iint->ima_hash->digest,
-					     iint->ima_hash->length);
+					     iint->ima_hash->length,
+					     iint->ima_hash->algo);
 		if (rc == -EOPNOTSUPP) {
 			*status = INTEGRITY_UNKNOWN;
 			break;
@@ -352,7 +318,9 @@ static int xattr_verify(enum ima_hooks func, struct ima_iint_cache *iint,
 						     (const char *)xattr_value,
 						     xattr_len,
 						     iint->ima_hash->digest,
-						     iint->ima_hash->length);
+						     iint->ima_hash->length,
+						     iint->ima_hash->algo);
+
 		if (rc) {
 			*cause = "invalid-signature";
 			*status = INTEGRITY_FAIL;
@@ -378,21 +346,16 @@ static int xattr_verify(enum ima_hooks func, struct ima_iint_cache *iint,
 			break;
 		}
 
-		rc = calc_file_id_hash(IMA_VERITY_DIGSIG, iint->ima_hash->algo,
-				       iint->ima_hash->digest,
-				       container_of(&hash.hdr,
-					       struct ima_digest_data, hdr));
-		if (rc) {
-			*cause = "sigv3-hashing-error";
-			*status = INTEGRITY_FAIL;
-			break;
-		}
-
 		rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
 					     (const char *)xattr_value,
-					     xattr_len, hash.digest,
-					     hash.hdr.length);
-		if (rc) {
+					     xattr_len,
+					     iint->ima_hash->digest,
+					     iint->ima_hash->length,
+					     iint->ima_hash->algo);
+		if (rc == -EOPNOTSUPP) {
+			*status = INTEGRITY_UNKNOWN;
+			break;
+		} else if (rc) {
 			*cause = "invalid-verity-signature";
 			*status = INTEGRITY_FAIL;
 		} else {
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 4636629533af..0c581c03c5da 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -131,7 +131,7 @@ struct modsig;
 #ifdef CONFIG_INTEGRITY_SIGNATURE
 
 int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
-			    const char *digest, int digestlen);
+			    const char *digest, int digestlen, u8 algo);
 int integrity_modsig_verify(unsigned int id, const struct modsig *modsig);
 
 int __init integrity_init_keyring(const unsigned int id);
@@ -142,7 +142,8 @@ int __init integrity_load_cert(const unsigned int id, const char *source,
 
 static inline int integrity_digsig_verify(const unsigned int id,
 					  const char *sig, int siglen,
-					  const char *digest, int digestlen)
+					  const char *digest, int digestlen,
+					  u8 algo)
 {
 	return -EOPNOTSUPP;
 }
@@ -170,12 +171,21 @@ static inline int __init integrity_load_cert(const unsigned int id,
 #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
 int asymmetric_verify(struct key *keyring, const char *sig,
 		      int siglen, const char *data, int datalen);
+int asymmetric_verify_v3(struct key *keyring, const char *sig,
+			 int siglen, const char *data, int datalen, u8 algo);
 #else
 static inline int asymmetric_verify(struct key *keyring, const char *sig,
 				    int siglen, const char *data, int datalen)
 {
 	return -EOPNOTSUPP;
 }
+
+static inline int asymmetric_verify_v3(struct key *keyring,
+				       const char *sig, int siglen,
+				       const char *data, int datalen, u8 algo)
+{
+	return -EOPNOTSUPP;
+}
 #endif
 
 #ifdef CONFIG_IMA_APPRAISE_MODSIG
-- 
2.53.0


  reply	other threads:[~2026-03-24 20:39 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-24 20:39 [PATCH 0/3] ima: add regular file data hash support for sigv3 Mimi Zohar
2026-03-24 20:39 ` Mimi Zohar [this message]
2026-03-30 20:13   ` [PATCH 1/3] ima: Define asymmetric_verify_v3() to verify IMA sigv3 signatures Eric Biggers
2026-04-05  9:46     ` Mimi Zohar
2026-03-24 20:39 ` [PATCH 2/3] ima: add regular file data hash signature version 3 support Mimi Zohar
2026-03-24 20:39 ` [PATCH 3/3] ima: add support to require IMA sigv3 signatures Mimi Zohar
2026-03-25  0:15 ` [PATCH 0/3] ima: add regular file data hash support for sigv3 Stefan Berger
2026-03-30 20:16 ` Eric Biggers
2026-04-27 12:57 ` Kamlesh Kumar
2026-04-27 13:30   ` Mimi Zohar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260324203929.2475782-2-zohar@linux.ibm.com \
    --to=zohar@linux.ibm.com \
    --cc=ebiggers@kernel.org \
    --cc=linux-integrity@vger.kernel.org \
    --cc=stefanb@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.