1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * IMA support for appraising module-style appended signatures. 4 * 5 * Copyright (C) 2019 IBM Corporation 6 * 7 * Author: 8 * Thiago Jung Bauermann <bauerman@linux.ibm.com> 9 */ 10 11 #include <linux/types.h> 12 #include <linux/module_signature.h> 13 #include <keys/asymmetric-type.h> 14 #include <crypto/pkcs7.h> 15 16 #include "ima.h" 17 18 struct modsig { 19 struct pkcs7_message *pkcs7_msg; 20 21 enum hash_algo hash_algo; 22 23 /* This digest will go in the 'd-modsig' field of the IMA template. */ 24 const u8 *digest; 25 u32 digest_size; 26 27 /* 28 * This is what will go to the measurement list if the template requires 29 * storing the signature. 30 */ 31 int raw_pkcs7_len; 32 u8 raw_pkcs7[]; 33 }; 34 35 /** 36 * ima_hook_supports_modsig - can the policy allow modsig for this hook? 37 * 38 * modsig is only supported by hooks using ima_post_read_file(), because only 39 * they preload the contents of the file in a buffer. FILE_CHECK does that in 40 * some cases, but not when reached from vfs_open(). POLICY_CHECK can support 41 * it, but it's not useful in practice because it's a text file so deny. 42 */ 43 bool ima_hook_supports_modsig(enum ima_hooks func) 44 { 45 switch (func) { 46 case KEXEC_KERNEL_CHECK: 47 case KEXEC_INITRAMFS_CHECK: 48 case MODULE_CHECK: 49 return true; 50 default: 51 return false; 52 } 53 } 54 55 /* 56 * ima_read_modsig - Read modsig from buf. 57 * 58 * Return: 0 on success, error code otherwise. 59 */ 60 int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len, 61 struct modsig **modsig) 62 { 63 const size_t marker_len = strlen(MODULE_SIG_STRING); 64 const struct module_signature *sig; 65 struct modsig *hdr; 66 size_t sig_len; 67 const void *p; 68 int rc; 69 70 if (buf_len <= marker_len + sizeof(*sig)) 71 return -ENOENT; 72 73 p = buf + buf_len - marker_len; 74 if (memcmp(p, MODULE_SIG_STRING, marker_len)) 75 return -ENOENT; 76 77 buf_len -= marker_len; 78 sig = (const struct module_signature *)(p - sizeof(*sig)); 79 80 rc = mod_check_sig(sig, buf_len, func_tokens[func]); 81 if (rc) 82 return rc; 83 84 sig_len = be32_to_cpu(sig->sig_len); 85 buf_len -= sig_len + sizeof(*sig); 86 87 /* Allocate sig_len additional bytes to hold the raw PKCS#7 data. */ 88 hdr = kzalloc(sizeof(*hdr) + sig_len, GFP_KERNEL); 89 if (!hdr) 90 return -ENOMEM; 91 92 hdr->pkcs7_msg = pkcs7_parse_message(buf + buf_len, sig_len); 93 if (IS_ERR(hdr->pkcs7_msg)) { 94 rc = PTR_ERR(hdr->pkcs7_msg); 95 kfree(hdr); 96 return rc; 97 } 98 99 memcpy(hdr->raw_pkcs7, buf + buf_len, sig_len); 100 hdr->raw_pkcs7_len = sig_len; 101 102 /* We don't know the hash algorithm yet. */ 103 hdr->hash_algo = HASH_ALGO__LAST; 104 105 *modsig = hdr; 106 107 return 0; 108 } 109 110 /** 111 * ima_collect_modsig - Calculate the file hash without the appended signature. 112 * 113 * Since the modsig is part of the file contents, the hash used in its signature 114 * isn't the same one ordinarily calculated by IMA. Therefore PKCS7 code 115 * calculates a separate one for signature verification. 116 */ 117 void ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size) 118 { 119 int rc; 120 121 /* 122 * Provide the file contents (minus the appended sig) so that the PKCS7 123 * code can calculate the file hash. 124 */ 125 size -= modsig->raw_pkcs7_len + strlen(MODULE_SIG_STRING) + 126 sizeof(struct module_signature); 127 rc = pkcs7_supply_detached_data(modsig->pkcs7_msg, buf, size); 128 if (rc) 129 return; 130 131 /* Ask the PKCS7 code to calculate the file hash. */ 132 rc = pkcs7_get_digest(modsig->pkcs7_msg, &modsig->digest, 133 &modsig->digest_size, &modsig->hash_algo); 134 } 135 136 int ima_modsig_verify(struct key *keyring, const struct modsig *modsig) 137 { 138 return verify_pkcs7_message_sig(NULL, 0, modsig->pkcs7_msg, keyring, 139 VERIFYING_MODULE_SIGNATURE, NULL, NULL); 140 } 141 142 int ima_get_modsig_digest(const struct modsig *modsig, enum hash_algo *algo, 143 const u8 **digest, u32 *digest_size) 144 { 145 *algo = modsig->hash_algo; 146 *digest = modsig->digest; 147 *digest_size = modsig->digest_size; 148 149 return 0; 150 } 151 152 int ima_get_raw_modsig(const struct modsig *modsig, const void **data, 153 u32 *data_len) 154 { 155 *data = &modsig->raw_pkcs7; 156 *data_len = modsig->raw_pkcs7_len; 157 158 return 0; 159 } 160 161 void ima_free_modsig(struct modsig *modsig) 162 { 163 if (!modsig) 164 return; 165 166 pkcs7_free_message(modsig->pkcs7_msg); 167 kfree(modsig); 168 } 169