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 --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); }