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 3539b07096SThiago Jung Bauermann /* 3639b07096SThiago Jung Bauermann * ima_read_modsig - Read modsig from buf. 3739b07096SThiago Jung Bauermann * 3839b07096SThiago Jung Bauermann * Return: 0 on success, error code otherwise. 3939b07096SThiago Jung Bauermann */ 4039b07096SThiago Jung Bauermann int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len, 4139b07096SThiago Jung Bauermann struct modsig **modsig) 4239b07096SThiago Jung Bauermann { 4339b07096SThiago Jung Bauermann const size_t marker_len = strlen(MODULE_SIG_STRING); 4439b07096SThiago Jung Bauermann const struct module_signature *sig; 4539b07096SThiago Jung Bauermann struct modsig *hdr; 4639b07096SThiago Jung Bauermann size_t sig_len; 4739b07096SThiago Jung Bauermann const void *p; 4839b07096SThiago Jung Bauermann int rc; 4939b07096SThiago Jung Bauermann 5039b07096SThiago Jung Bauermann if (buf_len <= marker_len + sizeof(*sig)) 5139b07096SThiago Jung Bauermann return -ENOENT; 5239b07096SThiago Jung Bauermann 5339b07096SThiago Jung Bauermann p = buf + buf_len - marker_len; 5439b07096SThiago Jung Bauermann if (memcmp(p, MODULE_SIG_STRING, marker_len)) 5539b07096SThiago Jung Bauermann return -ENOENT; 5639b07096SThiago Jung Bauermann 5739b07096SThiago Jung Bauermann buf_len -= marker_len; 5839b07096SThiago Jung Bauermann sig = (const struct module_signature *)(p - sizeof(*sig)); 5939b07096SThiago Jung Bauermann 6039b07096SThiago Jung Bauermann rc = mod_check_sig(sig, buf_len, func_tokens[func]); 6139b07096SThiago Jung Bauermann if (rc) 6239b07096SThiago Jung Bauermann return rc; 6339b07096SThiago Jung Bauermann 6439b07096SThiago Jung Bauermann sig_len = be32_to_cpu(sig->sig_len); 6539b07096SThiago Jung Bauermann buf_len -= sig_len + sizeof(*sig); 6639b07096SThiago Jung Bauermann 6715588227SThiago Jung Bauermann /* Allocate sig_len additional bytes to hold the raw PKCS#7 data. */ 6815588227SThiago Jung Bauermann hdr = kzalloc(sizeof(*hdr) + sig_len, GFP_KERNEL); 6939b07096SThiago Jung Bauermann if (!hdr) 7039b07096SThiago Jung Bauermann return -ENOMEM; 7139b07096SThiago Jung Bauermann 7239b07096SThiago Jung Bauermann hdr->pkcs7_msg = pkcs7_parse_message(buf + buf_len, sig_len); 7339b07096SThiago Jung Bauermann if (IS_ERR(hdr->pkcs7_msg)) { 74556d971bSThiago Jung Bauermann rc = PTR_ERR(hdr->pkcs7_msg); 7539b07096SThiago Jung Bauermann kfree(hdr); 76556d971bSThiago Jung Bauermann return rc; 7739b07096SThiago Jung Bauermann } 7839b07096SThiago Jung Bauermann 7915588227SThiago Jung Bauermann memcpy(hdr->raw_pkcs7, buf + buf_len, sig_len); 8015588227SThiago Jung Bauermann hdr->raw_pkcs7_len = sig_len; 8115588227SThiago Jung Bauermann 8215588227SThiago Jung Bauermann /* We don't know the hash algorithm yet. */ 8315588227SThiago Jung Bauermann hdr->hash_algo = HASH_ALGO__LAST; 8415588227SThiago Jung Bauermann 8539b07096SThiago Jung Bauermann *modsig = hdr; 8639b07096SThiago Jung Bauermann 8739b07096SThiago Jung Bauermann return 0; 8839b07096SThiago Jung Bauermann } 8939b07096SThiago Jung Bauermann 9015588227SThiago Jung Bauermann /** 9115588227SThiago Jung Bauermann * ima_collect_modsig - Calculate the file hash without the appended signature. 92*95526d13SRoberto Sassu * @modsig: parsed module signature 93*95526d13SRoberto Sassu * @buf: data to verify the signature on 94*95526d13SRoberto Sassu * @size: data size 9515588227SThiago Jung Bauermann * 9615588227SThiago Jung Bauermann * Since the modsig is part of the file contents, the hash used in its signature 9715588227SThiago Jung Bauermann * isn't the same one ordinarily calculated by IMA. Therefore PKCS7 code 9815588227SThiago Jung Bauermann * calculates a separate one for signature verification. 9915588227SThiago Jung Bauermann */ 10015588227SThiago Jung Bauermann void ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size) 10115588227SThiago Jung Bauermann { 10215588227SThiago Jung Bauermann int rc; 10315588227SThiago Jung Bauermann 10415588227SThiago Jung Bauermann /* 10515588227SThiago Jung Bauermann * Provide the file contents (minus the appended sig) so that the PKCS7 10615588227SThiago Jung Bauermann * code can calculate the file hash. 10715588227SThiago Jung Bauermann */ 10815588227SThiago Jung Bauermann size -= modsig->raw_pkcs7_len + strlen(MODULE_SIG_STRING) + 10915588227SThiago Jung Bauermann sizeof(struct module_signature); 11015588227SThiago Jung Bauermann rc = pkcs7_supply_detached_data(modsig->pkcs7_msg, buf, size); 11115588227SThiago Jung Bauermann if (rc) 11215588227SThiago Jung Bauermann return; 11315588227SThiago Jung Bauermann 11415588227SThiago Jung Bauermann /* Ask the PKCS7 code to calculate the file hash. */ 11515588227SThiago Jung Bauermann rc = pkcs7_get_digest(modsig->pkcs7_msg, &modsig->digest, 11615588227SThiago Jung Bauermann &modsig->digest_size, &modsig->hash_algo); 11715588227SThiago Jung Bauermann } 11815588227SThiago Jung Bauermann 11939b07096SThiago Jung Bauermann int ima_modsig_verify(struct key *keyring, const struct modsig *modsig) 12039b07096SThiago Jung Bauermann { 12139b07096SThiago Jung Bauermann return verify_pkcs7_message_sig(NULL, 0, modsig->pkcs7_msg, keyring, 12239b07096SThiago Jung Bauermann VERIFYING_MODULE_SIGNATURE, NULL, NULL); 12339b07096SThiago Jung Bauermann } 12439b07096SThiago Jung Bauermann 1253878d505SThiago Jung Bauermann int ima_get_modsig_digest(const struct modsig *modsig, enum hash_algo *algo, 1263878d505SThiago Jung Bauermann const u8 **digest, u32 *digest_size) 1273878d505SThiago Jung Bauermann { 1283878d505SThiago Jung Bauermann *algo = modsig->hash_algo; 1293878d505SThiago Jung Bauermann *digest = modsig->digest; 1303878d505SThiago Jung Bauermann *digest_size = modsig->digest_size; 1313878d505SThiago Jung Bauermann 1323878d505SThiago Jung Bauermann return 0; 1333878d505SThiago Jung Bauermann } 1343878d505SThiago Jung Bauermann 1353878d505SThiago Jung Bauermann int ima_get_raw_modsig(const struct modsig *modsig, const void **data, 1363878d505SThiago Jung Bauermann u32 *data_len) 1373878d505SThiago Jung Bauermann { 1383878d505SThiago Jung Bauermann *data = &modsig->raw_pkcs7; 1393878d505SThiago Jung Bauermann *data_len = modsig->raw_pkcs7_len; 1403878d505SThiago Jung Bauermann 1413878d505SThiago Jung Bauermann return 0; 1423878d505SThiago Jung Bauermann } 1433878d505SThiago Jung Bauermann 14439b07096SThiago Jung Bauermann void ima_free_modsig(struct modsig *modsig) 14539b07096SThiago Jung Bauermann { 14639b07096SThiago Jung Bauermann if (!modsig) 14739b07096SThiago Jung Bauermann return; 14839b07096SThiago Jung Bauermann 14939b07096SThiago Jung Bauermann pkcs7_free_message(modsig->pkcs7_msg); 15039b07096SThiago Jung Bauermann kfree(modsig); 15139b07096SThiago Jung Bauermann } 152