diff mbox series

[RFC,v3,9/9] ima: Support non-PKCS#7 modsig types

Message ID 20230720153247.3755856-10-roberto.sassu@huaweicloud.com (mailing list archive)
State RFC
Delegated to: Herbert Xu
Headers show
Series KEYS: Introduce user asymmetric keys and signatures | expand

Commit Message

Roberto Sassu July 20, 2023, 3:32 p.m. UTC
From: Roberto Sassu <roberto.sassu@huawei.com>

Add support for alternative signature formats through the newly introduced
user asymmetric key signatures. The corresponding API is invoked if the
signature type is not PKEY_ID_PKCS7. If the signature type is
PKEY_ID_PKCS7, nothing changes, the existing API is still invoked.

Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
---
 security/integrity/ima/ima_modsig.c | 79 +++++++++++++++++++++--------
 1 file changed, 59 insertions(+), 20 deletions(-)
diff mbox series

Patch

diff --git a/security/integrity/ima/ima_modsig.c b/security/integrity/ima/ima_modsig.c
index 3e7bee30080..7c96cb2613a 100644
--- a/security/integrity/ima/ima_modsig.c
+++ b/security/integrity/ima/ima_modsig.c
@@ -12,11 +12,14 @@ 
 #include <linux/module_signature.h>
 #include <keys/asymmetric-type.h>
 #include <crypto/pkcs7.h>
+#include <crypto/uasym_keys_sigs.h>
 
 #include "ima.h"
 
 struct modsig {
 	struct pkcs7_message *pkcs7_msg;
+	struct uasym_sig_message *uasym_sig;
+	u8 id_type;
 
 	enum hash_algo hash_algo;
 
@@ -28,8 +31,8 @@  struct modsig {
 	 * This is what will go to the measurement list if the template requires
 	 * storing the signature.
 	 */
-	int raw_pkcs7_len;
-	u8 raw_pkcs7[];
+	int raw_sig_len;
+	u8 raw_sig[];
 };
 
 /*
@@ -57,27 +60,43 @@  int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len,
 	buf_len -= marker_len;
 	sig = (const struct module_signature *)(p - sizeof(*sig));
 
-	rc = mod_check_sig(sig, buf_len, func_tokens[func]);
-	if (rc)
-		return rc;
+	if (sig->id_type == PKEY_ID_PKCS7) {
+		rc = mod_check_sig(sig, buf_len, func_tokens[func]);
+		if (rc)
+			return rc;
+	} else {
+		/* Same as mod_check_sig() but skipping the id_type check. */
+		if (sig->algo != 0 ||
+		    sig->hash != 0 ||
+		    sig->signer_len != 0 ||
+		    sig->key_id_len != 0 ||
+		    sig->__pad[0] != 0 ||
+		    sig->__pad[1] != 0 ||
+		    sig->__pad[2] != 0)
+			return -EBADMSG;
+	}
 
 	sig_len = be32_to_cpu(sig->sig_len);
 	buf_len -= sig_len + sizeof(*sig);
 
-	/* Allocate sig_len additional bytes to hold the raw PKCS#7 data. */
+	/* Allocate sig_len additional bytes to hold the raw sig data. */
 	hdr = kzalloc(sizeof(*hdr) + sig_len, GFP_KERNEL);
 	if (!hdr)
 		return -ENOMEM;
 
-	hdr->pkcs7_msg = pkcs7_parse_message(buf + buf_len, sig_len);
-	if (IS_ERR(hdr->pkcs7_msg)) {
-		rc = PTR_ERR(hdr->pkcs7_msg);
+	if (sig->id_type == PKEY_ID_PKCS7)
+		hdr->pkcs7_msg = pkcs7_parse_message(buf + buf_len, sig_len);
+	else
+		hdr->uasym_sig = uasym_sig_parse_message(buf + buf_len, sig_len);
+
+	if (IS_ERR(hdr->pkcs7_msg) || IS_ERR(hdr->uasym_sig)) {
 		kfree(hdr);
 		return rc;
 	}
 
-	memcpy(hdr->raw_pkcs7, buf + buf_len, sig_len);
-	hdr->raw_pkcs7_len = sig_len;
+	memcpy(hdr->raw_sig, buf + buf_len, sig_len);
+	hdr->raw_sig_len = sig_len;
+	hdr->id_type = sig->id_type;
 
 	/* We don't know the hash algorithm yet. */
 	hdr->hash_algo = HASH_ALGO__LAST;
@@ -105,21 +124,38 @@  void ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size)
 	 * Provide the file contents (minus the appended sig) so that the PKCS7
 	 * code can calculate the file hash.
 	 */
-	size -= modsig->raw_pkcs7_len + strlen(MODULE_SIG_STRING) +
+	size -= modsig->raw_sig_len + strlen(MODULE_SIG_STRING) +
 		sizeof(struct module_signature);
-	rc = pkcs7_supply_detached_data(modsig->pkcs7_msg, buf, size);
+	if (modsig->id_type == PKEY_ID_PKCS7)
+		rc = pkcs7_supply_detached_data(modsig->pkcs7_msg, buf, size);
+	else
+		rc = uasym_sig_supply_detached_data(modsig->uasym_sig, buf,
+						    size);
 	if (rc)
 		return;
 
 	/* Ask the PKCS7 code to calculate the file hash. */
-	rc = pkcs7_get_digest(modsig->pkcs7_msg, &modsig->digest,
-			      &modsig->digest_size, &modsig->hash_algo);
+	if (modsig->id_type == PKEY_ID_PKCS7)
+		rc = pkcs7_get_digest(modsig->pkcs7_msg, &modsig->digest,
+				      &modsig->digest_size, &modsig->hash_algo);
+	else
+		rc = uasym_sig_get_digest(modsig->uasym_sig, &modsig->digest,
+					  &modsig->digest_size,
+					  &modsig->hash_algo);
 }
 
 int ima_modsig_verify(struct key *keyring, const struct modsig *modsig)
 {
-	return verify_pkcs7_message_sig(NULL, 0, modsig->pkcs7_msg, keyring,
-					VERIFYING_MODULE_SIGNATURE, NULL, NULL);
+	if (modsig->id_type == PKEY_ID_PKCS7)
+		return verify_pkcs7_message_sig(NULL, 0, modsig->pkcs7_msg,
+						keyring,
+						VERIFYING_MODULE_SIGNATURE,
+						NULL, NULL);
+	else
+		return verify_uasym_sig_message(NULL, 0, modsig->uasym_sig,
+						keyring,
+						VERIFYING_MODULE_SIGNATURE,
+						NULL, NULL);
 }
 
 int ima_get_modsig_digest(const struct modsig *modsig, enum hash_algo *algo,
@@ -135,8 +171,8 @@  int ima_get_modsig_digest(const struct modsig *modsig, enum hash_algo *algo,
 int ima_get_raw_modsig(const struct modsig *modsig, const void **data,
 		       u32 *data_len)
 {
-	*data = &modsig->raw_pkcs7;
-	*data_len = modsig->raw_pkcs7_len;
+	*data = &modsig->raw_sig;
+	*data_len = modsig->raw_sig_len;
 
 	return 0;
 }
@@ -146,6 +182,9 @@  void ima_free_modsig(struct modsig *modsig)
 	if (!modsig)
 		return;
 
-	pkcs7_free_message(modsig->pkcs7_msg);
+	if (modsig->id_type == PKEY_ID_PKCS7)
+		pkcs7_free_message(modsig->pkcs7_msg);
+	else
+		uasym_sig_free_message(modsig->uasym_sig);
 	kfree(modsig);
 }