0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/types.h>
0012 #include <linux/module_signature.h>
0013 #include <keys/asymmetric-type.h>
0014 #include <crypto/pkcs7.h>
0015
0016 #include "ima.h"
0017
0018 struct modsig {
0019 struct pkcs7_message *pkcs7_msg;
0020
0021 enum hash_algo hash_algo;
0022
0023
0024 const u8 *digest;
0025 u32 digest_size;
0026
0027
0028
0029
0030
0031 int raw_pkcs7_len;
0032 u8 raw_pkcs7[];
0033 };
0034
0035
0036
0037
0038
0039
0040 int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len,
0041 struct modsig **modsig)
0042 {
0043 const size_t marker_len = strlen(MODULE_SIG_STRING);
0044 const struct module_signature *sig;
0045 struct modsig *hdr;
0046 size_t sig_len;
0047 const void *p;
0048 int rc;
0049
0050 if (buf_len <= marker_len + sizeof(*sig))
0051 return -ENOENT;
0052
0053 p = buf + buf_len - marker_len;
0054 if (memcmp(p, MODULE_SIG_STRING, marker_len))
0055 return -ENOENT;
0056
0057 buf_len -= marker_len;
0058 sig = (const struct module_signature *)(p - sizeof(*sig));
0059
0060 rc = mod_check_sig(sig, buf_len, func_tokens[func]);
0061 if (rc)
0062 return rc;
0063
0064 sig_len = be32_to_cpu(sig->sig_len);
0065 buf_len -= sig_len + sizeof(*sig);
0066
0067
0068 hdr = kzalloc(sizeof(*hdr) + sig_len, GFP_KERNEL);
0069 if (!hdr)
0070 return -ENOMEM;
0071
0072 hdr->pkcs7_msg = pkcs7_parse_message(buf + buf_len, sig_len);
0073 if (IS_ERR(hdr->pkcs7_msg)) {
0074 rc = PTR_ERR(hdr->pkcs7_msg);
0075 kfree(hdr);
0076 return rc;
0077 }
0078
0079 memcpy(hdr->raw_pkcs7, buf + buf_len, sig_len);
0080 hdr->raw_pkcs7_len = sig_len;
0081
0082
0083 hdr->hash_algo = HASH_ALGO__LAST;
0084
0085 *modsig = hdr;
0086
0087 return 0;
0088 }
0089
0090
0091
0092
0093
0094
0095
0096
0097 void ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size)
0098 {
0099 int rc;
0100
0101
0102
0103
0104
0105 size -= modsig->raw_pkcs7_len + strlen(MODULE_SIG_STRING) +
0106 sizeof(struct module_signature);
0107 rc = pkcs7_supply_detached_data(modsig->pkcs7_msg, buf, size);
0108 if (rc)
0109 return;
0110
0111
0112 rc = pkcs7_get_digest(modsig->pkcs7_msg, &modsig->digest,
0113 &modsig->digest_size, &modsig->hash_algo);
0114 }
0115
0116 int ima_modsig_verify(struct key *keyring, const struct modsig *modsig)
0117 {
0118 return verify_pkcs7_message_sig(NULL, 0, modsig->pkcs7_msg, keyring,
0119 VERIFYING_MODULE_SIGNATURE, NULL, NULL);
0120 }
0121
0122 int ima_get_modsig_digest(const struct modsig *modsig, enum hash_algo *algo,
0123 const u8 **digest, u32 *digest_size)
0124 {
0125 *algo = modsig->hash_algo;
0126 *digest = modsig->digest;
0127 *digest_size = modsig->digest_size;
0128
0129 return 0;
0130 }
0131
0132 int ima_get_raw_modsig(const struct modsig *modsig, const void **data,
0133 u32 *data_len)
0134 {
0135 *data = &modsig->raw_pkcs7;
0136 *data_len = modsig->raw_pkcs7_len;
0137
0138 return 0;
0139 }
0140
0141 void ima_free_modsig(struct modsig *modsig)
0142 {
0143 if (!modsig)
0144 return;
0145
0146 pkcs7_free_message(modsig->pkcs7_msg);
0147 kfree(modsig);
0148 }