19044d627SThiago Jung Bauermann // SPDX-License-Identifier: GPL-2.0+ 29044d627SThiago Jung Bauermann /* 39044d627SThiago Jung Bauermann * IMA support for appraising module-style appended signatures. 49044d627SThiago Jung Bauermann * 59044d627SThiago Jung Bauermann * Copyright (C) 2019 IBM Corporation 69044d627SThiago Jung Bauermann * 79044d627SThiago Jung Bauermann * Author: 89044d627SThiago Jung Bauermann * Thiago Jung Bauermann <bauerman@linux.ibm.com> 99044d627SThiago Jung Bauermann */ 109044d627SThiago Jung Bauermann 1139b07096SThiago Jung Bauermann #include <linux/types.h> 1239b07096SThiago Jung Bauermann #include <linux/module_signature.h> 1339b07096SThiago Jung Bauermann #include <keys/asymmetric-type.h> 1439b07096SThiago Jung Bauermann #include <crypto/pkcs7.h> 1539b07096SThiago Jung Bauermann 169044d627SThiago Jung Bauermann #include "ima.h" 179044d627SThiago Jung Bauermann 1839b07096SThiago Jung Bauermann struct modsig { 1939b07096SThiago Jung Bauermann struct pkcs7_message *pkcs7_msg; 2015588227SThiago Jung Bauermann 2115588227SThiago Jung Bauermann enum hash_algo hash_algo; 2215588227SThiago Jung Bauermann 2315588227SThiago Jung Bauermann /* This digest will go in the 'd-modsig' field of the IMA template. */ 2415588227SThiago Jung Bauermann const u8 *digest; 2515588227SThiago Jung Bauermann u32 digest_size; 2615588227SThiago Jung Bauermann 2715588227SThiago Jung Bauermann /* 2815588227SThiago Jung Bauermann * This is what will go to the measurement list if the template requires 2915588227SThiago Jung Bauermann * storing the signature. 3015588227SThiago Jung Bauermann */ 3115588227SThiago Jung Bauermann int raw_pkcs7_len; 3215588227SThiago Jung Bauermann u8 raw_pkcs7[]; 3339b07096SThiago Jung Bauermann }; 3439b07096SThiago Jung Bauermann 359044d627SThiago Jung Bauermann /** 369044d627SThiago Jung Bauermann * ima_hook_supports_modsig - can the policy allow modsig for this hook? 379044d627SThiago Jung Bauermann * 389044d627SThiago Jung Bauermann * modsig is only supported by hooks using ima_post_read_file(), because only 399044d627SThiago Jung Bauermann * they preload the contents of the file in a buffer. FILE_CHECK does that in 409044d627SThiago Jung Bauermann * some cases, but not when reached from vfs_open(). POLICY_CHECK can support 419044d627SThiago Jung Bauermann * it, but it's not useful in practice because it's a text file so deny. 429044d627SThiago Jung Bauermann */ 439044d627SThiago Jung Bauermann bool ima_hook_supports_modsig(enum ima_hooks func) 449044d627SThiago Jung Bauermann { 459044d627SThiago Jung Bauermann switch (func) { 469044d627SThiago Jung Bauermann case KEXEC_KERNEL_CHECK: 479044d627SThiago Jung Bauermann case KEXEC_INITRAMFS_CHECK: 489044d627SThiago Jung Bauermann case MODULE_CHECK: 499044d627SThiago Jung Bauermann return true; 509044d627SThiago Jung Bauermann default: 519044d627SThiago Jung Bauermann return false; 529044d627SThiago Jung Bauermann } 539044d627SThiago Jung Bauermann } 5439b07096SThiago Jung Bauermann 5539b07096SThiago Jung Bauermann /* 5639b07096SThiago Jung Bauermann * ima_read_modsig - Read modsig from buf. 5739b07096SThiago Jung Bauermann * 5839b07096SThiago Jung Bauermann * Return: 0 on success, error code otherwise. 5939b07096SThiago Jung Bauermann */ 6039b07096SThiago Jung Bauermann int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len, 6139b07096SThiago Jung Bauermann struct modsig **modsig) 6239b07096SThiago Jung Bauermann { 6339b07096SThiago Jung Bauermann const size_t marker_len = strlen(MODULE_SIG_STRING); 6439b07096SThiago Jung Bauermann const struct module_signature *sig; 6539b07096SThiago Jung Bauermann struct modsig *hdr; 6639b07096SThiago Jung Bauermann size_t sig_len; 6739b07096SThiago Jung Bauermann const void *p; 6839b07096SThiago Jung Bauermann int rc; 6939b07096SThiago Jung Bauermann 7039b07096SThiago Jung Bauermann if (buf_len <= marker_len + sizeof(*sig)) 7139b07096SThiago Jung Bauermann return -ENOENT; 7239b07096SThiago Jung Bauermann 7339b07096SThiago Jung Bauermann p = buf + buf_len - marker_len; 7439b07096SThiago Jung Bauermann if (memcmp(p, MODULE_SIG_STRING, marker_len)) 7539b07096SThiago Jung Bauermann return -ENOENT; 7639b07096SThiago Jung Bauermann 7739b07096SThiago Jung Bauermann buf_len -= marker_len; 7839b07096SThiago Jung Bauermann sig = (const struct module_signature *)(p - sizeof(*sig)); 7939b07096SThiago Jung Bauermann 8039b07096SThiago Jung Bauermann rc = mod_check_sig(sig, buf_len, func_tokens[func]); 8139b07096SThiago Jung Bauermann if (rc) 8239b07096SThiago Jung Bauermann return rc; 8339b07096SThiago Jung Bauermann 8439b07096SThiago Jung Bauermann sig_len = be32_to_cpu(sig->sig_len); 8539b07096SThiago Jung Bauermann buf_len -= sig_len + sizeof(*sig); 8639b07096SThiago Jung Bauermann 8715588227SThiago Jung Bauermann /* Allocate sig_len additional bytes to hold the raw PKCS#7 data. */ 8815588227SThiago Jung Bauermann hdr = kzalloc(sizeof(*hdr) + sig_len, GFP_KERNEL); 8939b07096SThiago Jung Bauermann if (!hdr) 9039b07096SThiago Jung Bauermann return -ENOMEM; 9139b07096SThiago Jung Bauermann 9239b07096SThiago Jung Bauermann hdr->pkcs7_msg = pkcs7_parse_message(buf + buf_len, sig_len); 9339b07096SThiago Jung Bauermann if (IS_ERR(hdr->pkcs7_msg)) { 94*556d971bSThiago Jung Bauermann rc = PTR_ERR(hdr->pkcs7_msg); 9539b07096SThiago Jung Bauermann kfree(hdr); 96*556d971bSThiago Jung Bauermann return rc; 9739b07096SThiago Jung Bauermann } 9839b07096SThiago Jung Bauermann 9915588227SThiago Jung Bauermann memcpy(hdr->raw_pkcs7, buf + buf_len, sig_len); 10015588227SThiago Jung Bauermann hdr->raw_pkcs7_len = sig_len; 10115588227SThiago Jung Bauermann 10215588227SThiago Jung Bauermann /* We don't know the hash algorithm yet. */ 10315588227SThiago Jung Bauermann hdr->hash_algo = HASH_ALGO__LAST; 10415588227SThiago Jung Bauermann 10539b07096SThiago Jung Bauermann *modsig = hdr; 10639b07096SThiago Jung Bauermann 10739b07096SThiago Jung Bauermann return 0; 10839b07096SThiago Jung Bauermann } 10939b07096SThiago Jung Bauermann 11015588227SThiago Jung Bauermann /** 11115588227SThiago Jung Bauermann * ima_collect_modsig - Calculate the file hash without the appended signature. 11215588227SThiago Jung Bauermann * 11315588227SThiago Jung Bauermann * Since the modsig is part of the file contents, the hash used in its signature 11415588227SThiago Jung Bauermann * isn't the same one ordinarily calculated by IMA. Therefore PKCS7 code 11515588227SThiago Jung Bauermann * calculates a separate one for signature verification. 11615588227SThiago Jung Bauermann */ 11715588227SThiago Jung Bauermann void ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size) 11815588227SThiago Jung Bauermann { 11915588227SThiago Jung Bauermann int rc; 12015588227SThiago Jung Bauermann 12115588227SThiago Jung Bauermann /* 12215588227SThiago Jung Bauermann * Provide the file contents (minus the appended sig) so that the PKCS7 12315588227SThiago Jung Bauermann * code can calculate the file hash. 12415588227SThiago Jung Bauermann */ 12515588227SThiago Jung Bauermann size -= modsig->raw_pkcs7_len + strlen(MODULE_SIG_STRING) + 12615588227SThiago Jung Bauermann sizeof(struct module_signature); 12715588227SThiago Jung Bauermann rc = pkcs7_supply_detached_data(modsig->pkcs7_msg, buf, size); 12815588227SThiago Jung Bauermann if (rc) 12915588227SThiago Jung Bauermann return; 13015588227SThiago Jung Bauermann 13115588227SThiago Jung Bauermann /* Ask the PKCS7 code to calculate the file hash. */ 13215588227SThiago Jung Bauermann rc = pkcs7_get_digest(modsig->pkcs7_msg, &modsig->digest, 13315588227SThiago Jung Bauermann &modsig->digest_size, &modsig->hash_algo); 13415588227SThiago Jung Bauermann } 13515588227SThiago Jung Bauermann 13639b07096SThiago Jung Bauermann int ima_modsig_verify(struct key *keyring, const struct modsig *modsig) 13739b07096SThiago Jung Bauermann { 13839b07096SThiago Jung Bauermann return verify_pkcs7_message_sig(NULL, 0, modsig->pkcs7_msg, keyring, 13939b07096SThiago Jung Bauermann VERIFYING_MODULE_SIGNATURE, NULL, NULL); 14039b07096SThiago Jung Bauermann } 14139b07096SThiago Jung Bauermann 1423878d505SThiago Jung Bauermann int ima_get_modsig_digest(const struct modsig *modsig, enum hash_algo *algo, 1433878d505SThiago Jung Bauermann const u8 **digest, u32 *digest_size) 1443878d505SThiago Jung Bauermann { 1453878d505SThiago Jung Bauermann *algo = modsig->hash_algo; 1463878d505SThiago Jung Bauermann *digest = modsig->digest; 1473878d505SThiago Jung Bauermann *digest_size = modsig->digest_size; 1483878d505SThiago Jung Bauermann 1493878d505SThiago Jung Bauermann return 0; 1503878d505SThiago Jung Bauermann } 1513878d505SThiago Jung Bauermann 1523878d505SThiago Jung Bauermann int ima_get_raw_modsig(const struct modsig *modsig, const void **data, 1533878d505SThiago Jung Bauermann u32 *data_len) 1543878d505SThiago Jung Bauermann { 1553878d505SThiago Jung Bauermann *data = &modsig->raw_pkcs7; 1563878d505SThiago Jung Bauermann *data_len = modsig->raw_pkcs7_len; 1573878d505SThiago Jung Bauermann 1583878d505SThiago Jung Bauermann return 0; 1593878d505SThiago Jung Bauermann } 1603878d505SThiago Jung Bauermann 16139b07096SThiago Jung Bauermann void ima_free_modsig(struct modsig *modsig) 16239b07096SThiago Jung Bauermann { 16339b07096SThiago Jung Bauermann if (!modsig) 16439b07096SThiago Jung Bauermann return; 16539b07096SThiago Jung Bauermann 16639b07096SThiago Jung Bauermann pkcs7_free_message(modsig->pkcs7_msg); 16739b07096SThiago Jung Bauermann kfree(modsig); 16839b07096SThiago Jung Bauermann } 169