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 11*39b07096SThiago Jung Bauermann #include <linux/types.h> 12*39b07096SThiago Jung Bauermann #include <linux/module_signature.h> 13*39b07096SThiago Jung Bauermann #include <keys/asymmetric-type.h> 14*39b07096SThiago Jung Bauermann #include <crypto/pkcs7.h> 15*39b07096SThiago Jung Bauermann 169044d627SThiago Jung Bauermann #include "ima.h" 179044d627SThiago Jung Bauermann 18*39b07096SThiago Jung Bauermann struct modsig { 19*39b07096SThiago Jung Bauermann struct pkcs7_message *pkcs7_msg; 20*39b07096SThiago Jung Bauermann }; 21*39b07096SThiago Jung Bauermann 229044d627SThiago Jung Bauermann /** 239044d627SThiago Jung Bauermann * ima_hook_supports_modsig - can the policy allow modsig for this hook? 249044d627SThiago Jung Bauermann * 259044d627SThiago Jung Bauermann * modsig is only supported by hooks using ima_post_read_file(), because only 269044d627SThiago Jung Bauermann * they preload the contents of the file in a buffer. FILE_CHECK does that in 279044d627SThiago Jung Bauermann * some cases, but not when reached from vfs_open(). POLICY_CHECK can support 289044d627SThiago Jung Bauermann * it, but it's not useful in practice because it's a text file so deny. 299044d627SThiago Jung Bauermann */ 309044d627SThiago Jung Bauermann bool ima_hook_supports_modsig(enum ima_hooks func) 319044d627SThiago Jung Bauermann { 329044d627SThiago Jung Bauermann switch (func) { 339044d627SThiago Jung Bauermann case KEXEC_KERNEL_CHECK: 349044d627SThiago Jung Bauermann case KEXEC_INITRAMFS_CHECK: 359044d627SThiago Jung Bauermann case MODULE_CHECK: 369044d627SThiago Jung Bauermann return true; 379044d627SThiago Jung Bauermann default: 389044d627SThiago Jung Bauermann return false; 399044d627SThiago Jung Bauermann } 409044d627SThiago Jung Bauermann } 41*39b07096SThiago Jung Bauermann 42*39b07096SThiago Jung Bauermann /* 43*39b07096SThiago Jung Bauermann * ima_read_modsig - Read modsig from buf. 44*39b07096SThiago Jung Bauermann * 45*39b07096SThiago Jung Bauermann * Return: 0 on success, error code otherwise. 46*39b07096SThiago Jung Bauermann */ 47*39b07096SThiago Jung Bauermann int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len, 48*39b07096SThiago Jung Bauermann struct modsig **modsig) 49*39b07096SThiago Jung Bauermann { 50*39b07096SThiago Jung Bauermann const size_t marker_len = strlen(MODULE_SIG_STRING); 51*39b07096SThiago Jung Bauermann const struct module_signature *sig; 52*39b07096SThiago Jung Bauermann struct modsig *hdr; 53*39b07096SThiago Jung Bauermann size_t sig_len; 54*39b07096SThiago Jung Bauermann const void *p; 55*39b07096SThiago Jung Bauermann int rc; 56*39b07096SThiago Jung Bauermann 57*39b07096SThiago Jung Bauermann if (buf_len <= marker_len + sizeof(*sig)) 58*39b07096SThiago Jung Bauermann return -ENOENT; 59*39b07096SThiago Jung Bauermann 60*39b07096SThiago Jung Bauermann p = buf + buf_len - marker_len; 61*39b07096SThiago Jung Bauermann if (memcmp(p, MODULE_SIG_STRING, marker_len)) 62*39b07096SThiago Jung Bauermann return -ENOENT; 63*39b07096SThiago Jung Bauermann 64*39b07096SThiago Jung Bauermann buf_len -= marker_len; 65*39b07096SThiago Jung Bauermann sig = (const struct module_signature *)(p - sizeof(*sig)); 66*39b07096SThiago Jung Bauermann 67*39b07096SThiago Jung Bauermann rc = mod_check_sig(sig, buf_len, func_tokens[func]); 68*39b07096SThiago Jung Bauermann if (rc) 69*39b07096SThiago Jung Bauermann return rc; 70*39b07096SThiago Jung Bauermann 71*39b07096SThiago Jung Bauermann sig_len = be32_to_cpu(sig->sig_len); 72*39b07096SThiago Jung Bauermann buf_len -= sig_len + sizeof(*sig); 73*39b07096SThiago Jung Bauermann 74*39b07096SThiago Jung Bauermann hdr = kmalloc(sizeof(*hdr), GFP_KERNEL); 75*39b07096SThiago Jung Bauermann if (!hdr) 76*39b07096SThiago Jung Bauermann return -ENOMEM; 77*39b07096SThiago Jung Bauermann 78*39b07096SThiago Jung Bauermann hdr->pkcs7_msg = pkcs7_parse_message(buf + buf_len, sig_len); 79*39b07096SThiago Jung Bauermann if (IS_ERR(hdr->pkcs7_msg)) { 80*39b07096SThiago Jung Bauermann kfree(hdr); 81*39b07096SThiago Jung Bauermann return PTR_ERR(hdr->pkcs7_msg); 82*39b07096SThiago Jung Bauermann } 83*39b07096SThiago Jung Bauermann 84*39b07096SThiago Jung Bauermann *modsig = hdr; 85*39b07096SThiago Jung Bauermann 86*39b07096SThiago Jung Bauermann return 0; 87*39b07096SThiago Jung Bauermann } 88*39b07096SThiago Jung Bauermann 89*39b07096SThiago Jung Bauermann int ima_modsig_verify(struct key *keyring, const struct modsig *modsig) 90*39b07096SThiago Jung Bauermann { 91*39b07096SThiago Jung Bauermann return verify_pkcs7_message_sig(NULL, 0, modsig->pkcs7_msg, keyring, 92*39b07096SThiago Jung Bauermann VERIFYING_MODULE_SIGNATURE, NULL, NULL); 93*39b07096SThiago Jung Bauermann } 94*39b07096SThiago Jung Bauermann 95*39b07096SThiago Jung Bauermann void ima_free_modsig(struct modsig *modsig) 96*39b07096SThiago Jung Bauermann { 97*39b07096SThiago Jung Bauermann if (!modsig) 98*39b07096SThiago Jung Bauermann return; 99*39b07096SThiago Jung Bauermann 100*39b07096SThiago Jung Bauermann pkcs7_free_message(modsig->pkcs7_msg); 101*39b07096SThiago Jung Bauermann kfree(modsig); 102*39b07096SThiago Jung Bauermann } 103