root/security/integrity/ima/ima_modsig.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ima_hook_supports_modsig
  2. ima_read_modsig
  3. ima_collect_modsig
  4. ima_modsig_verify
  5. ima_get_modsig_digest
  6. ima_get_raw_modsig
  7. ima_free_modsig

   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 }

/* [<][>][^][v][top][bottom][index][help] */