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; 20*15588227SThiago Jung Bauermann 21*15588227SThiago Jung Bauermann enum hash_algo hash_algo; 22*15588227SThiago Jung Bauermann 23*15588227SThiago Jung Bauermann /* This digest will go in the 'd-modsig' field of the IMA template. */ 24*15588227SThiago Jung Bauermann const u8 *digest; 25*15588227SThiago Jung Bauermann u32 digest_size; 26*15588227SThiago Jung Bauermann 27*15588227SThiago Jung Bauermann /* 28*15588227SThiago Jung Bauermann * This is what will go to the measurement list if the template requires 29*15588227SThiago Jung Bauermann * storing the signature. 30*15588227SThiago Jung Bauermann */ 31*15588227SThiago Jung Bauermann int raw_pkcs7_len; 32*15588227SThiago 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 87*15588227SThiago Jung Bauermann /* Allocate sig_len additional bytes to hold the raw PKCS#7 data. */ 88*15588227SThiago 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)) { 9439b07096SThiago Jung Bauermann kfree(hdr); 9539b07096SThiago Jung Bauermann return PTR_ERR(hdr->pkcs7_msg); 9639b07096SThiago Jung Bauermann } 9739b07096SThiago Jung Bauermann 98*15588227SThiago Jung Bauermann memcpy(hdr->raw_pkcs7, buf + buf_len, sig_len); 99*15588227SThiago Jung Bauermann hdr->raw_pkcs7_len = sig_len; 100*15588227SThiago Jung Bauermann 101*15588227SThiago Jung Bauermann /* We don't know the hash algorithm yet. */ 102*15588227SThiago Jung Bauermann hdr->hash_algo = HASH_ALGO__LAST; 103*15588227SThiago Jung Bauermann 10439b07096SThiago Jung Bauermann *modsig = hdr; 10539b07096SThiago Jung Bauermann 10639b07096SThiago Jung Bauermann return 0; 10739b07096SThiago Jung Bauermann } 10839b07096SThiago Jung Bauermann 109*15588227SThiago Jung Bauermann /** 110*15588227SThiago Jung Bauermann * ima_collect_modsig - Calculate the file hash without the appended signature. 111*15588227SThiago Jung Bauermann * 112*15588227SThiago Jung Bauermann * Since the modsig is part of the file contents, the hash used in its signature 113*15588227SThiago Jung Bauermann * isn't the same one ordinarily calculated by IMA. Therefore PKCS7 code 114*15588227SThiago Jung Bauermann * calculates a separate one for signature verification. 115*15588227SThiago Jung Bauermann */ 116*15588227SThiago Jung Bauermann void ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size) 117*15588227SThiago Jung Bauermann { 118*15588227SThiago Jung Bauermann int rc; 119*15588227SThiago Jung Bauermann 120*15588227SThiago Jung Bauermann /* 121*15588227SThiago Jung Bauermann * Provide the file contents (minus the appended sig) so that the PKCS7 122*15588227SThiago Jung Bauermann * code can calculate the file hash. 123*15588227SThiago Jung Bauermann */ 124*15588227SThiago Jung Bauermann size -= modsig->raw_pkcs7_len + strlen(MODULE_SIG_STRING) + 125*15588227SThiago Jung Bauermann sizeof(struct module_signature); 126*15588227SThiago Jung Bauermann rc = pkcs7_supply_detached_data(modsig->pkcs7_msg, buf, size); 127*15588227SThiago Jung Bauermann if (rc) 128*15588227SThiago Jung Bauermann return; 129*15588227SThiago Jung Bauermann 130*15588227SThiago Jung Bauermann /* Ask the PKCS7 code to calculate the file hash. */ 131*15588227SThiago Jung Bauermann rc = pkcs7_get_digest(modsig->pkcs7_msg, &modsig->digest, 132*15588227SThiago Jung Bauermann &modsig->digest_size, &modsig->hash_algo); 133*15588227SThiago Jung Bauermann } 134*15588227SThiago Jung Bauermann 13539b07096SThiago Jung Bauermann int ima_modsig_verify(struct key *keyring, const struct modsig *modsig) 13639b07096SThiago Jung Bauermann { 13739b07096SThiago Jung Bauermann return verify_pkcs7_message_sig(NULL, 0, modsig->pkcs7_msg, keyring, 13839b07096SThiago Jung Bauermann VERIFYING_MODULE_SIGNATURE, NULL, NULL); 13939b07096SThiago Jung Bauermann } 14039b07096SThiago Jung Bauermann 14139b07096SThiago Jung Bauermann void ima_free_modsig(struct modsig *modsig) 14239b07096SThiago Jung Bauermann { 14339b07096SThiago Jung Bauermann if (!modsig) 14439b07096SThiago Jung Bauermann return; 14539b07096SThiago Jung Bauermann 14639b07096SThiago Jung Bauermann pkcs7_free_message(modsig->pkcs7_msg); 14739b07096SThiago Jung Bauermann kfree(modsig); 14839b07096SThiago Jung Bauermann } 149