linux/security/integrity/ima/ima_crypto.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2005,2006,2007,2008 IBM Corporation
   3 *
   4 * Authors:
   5 * Mimi Zohar <zohar@us.ibm.com>
   6 * Kylene Hall <kjhall@us.ibm.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation, version 2 of the License.
  11 *
  12 * File: ima_crypto.c
  13 *      Calculates md5/sha1 file hash, template hash, boot-aggreate hash
  14 */
  15
  16#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  17
  18#include <linux/kernel.h>
  19#include <linux/file.h>
  20#include <linux/crypto.h>
  21#include <linux/scatterlist.h>
  22#include <linux/err.h>
  23#include <linux/slab.h>
  24#include <crypto/hash.h>
  25#include <crypto/hash_info.h>
  26#include "ima.h"
  27
  28static struct crypto_shash *ima_shash_tfm;
  29
  30/**
  31 * ima_kernel_read - read file content
  32 *
  33 * This is a function for reading file content instead of kernel_read().
  34 * It does not perform locking checks to ensure it cannot be blocked.
  35 * It does not perform security checks because it is irrelevant for IMA.
  36 *
  37 */
  38static int ima_kernel_read(struct file *file, loff_t offset,
  39                           char *addr, unsigned long count)
  40{
  41        mm_segment_t old_fs;
  42        char __user *buf = addr;
  43        ssize_t ret;
  44
  45        if (!(file->f_mode & FMODE_READ))
  46                return -EBADF;
  47        if (!file->f_op->read && !file->f_op->aio_read)
  48                return -EINVAL;
  49
  50        old_fs = get_fs();
  51        set_fs(get_ds());
  52        if (file->f_op->read)
  53                ret = file->f_op->read(file, buf, count, &offset);
  54        else
  55                ret = do_sync_read(file, buf, count, &offset);
  56        set_fs(old_fs);
  57        return ret;
  58}
  59
  60int ima_init_crypto(void)
  61{
  62        long rc;
  63
  64        ima_shash_tfm = crypto_alloc_shash(hash_algo_name[ima_hash_algo], 0, 0);
  65        if (IS_ERR(ima_shash_tfm)) {
  66                rc = PTR_ERR(ima_shash_tfm);
  67                pr_err("Can not allocate %s (reason: %ld)\n",
  68                       hash_algo_name[ima_hash_algo], rc);
  69                return rc;
  70        }
  71        return 0;
  72}
  73
  74static struct crypto_shash *ima_alloc_tfm(enum hash_algo algo)
  75{
  76        struct crypto_shash *tfm = ima_shash_tfm;
  77        int rc;
  78
  79        if (algo != ima_hash_algo && algo < HASH_ALGO__LAST) {
  80                tfm = crypto_alloc_shash(hash_algo_name[algo], 0, 0);
  81                if (IS_ERR(tfm)) {
  82                        rc = PTR_ERR(tfm);
  83                        pr_err("Can not allocate %s (reason: %d)\n",
  84                               hash_algo_name[algo], rc);
  85                }
  86        }
  87        return tfm;
  88}
  89
  90static void ima_free_tfm(struct crypto_shash *tfm)
  91{
  92        if (tfm != ima_shash_tfm)
  93                crypto_free_shash(tfm);
  94}
  95
  96/*
  97 * Calculate the MD5/SHA1 file digest
  98 */
  99static int ima_calc_file_hash_tfm(struct file *file,
 100                                  struct ima_digest_data *hash,
 101                                  struct crypto_shash *tfm)
 102{
 103        loff_t i_size, offset = 0;
 104        char *rbuf;
 105        int rc, read = 0;
 106        struct {
 107                struct shash_desc shash;
 108                char ctx[crypto_shash_descsize(tfm)];
 109        } desc;
 110
 111        desc.shash.tfm = tfm;
 112        desc.shash.flags = 0;
 113
 114        hash->length = crypto_shash_digestsize(tfm);
 115
 116        rc = crypto_shash_init(&desc.shash);
 117        if (rc != 0)
 118                return rc;
 119
 120        i_size = i_size_read(file_inode(file));
 121
 122        if (i_size == 0)
 123                goto out;
 124
 125        rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL);
 126        if (!rbuf)
 127                return -ENOMEM;
 128
 129        if (!(file->f_mode & FMODE_READ)) {
 130                file->f_mode |= FMODE_READ;
 131                read = 1;
 132        }
 133
 134        while (offset < i_size) {
 135                int rbuf_len;
 136
 137                rbuf_len = ima_kernel_read(file, offset, rbuf, PAGE_SIZE);
 138                if (rbuf_len < 0) {
 139                        rc = rbuf_len;
 140                        break;
 141                }
 142                if (rbuf_len == 0)
 143                        break;
 144                offset += rbuf_len;
 145
 146                rc = crypto_shash_update(&desc.shash, rbuf, rbuf_len);
 147                if (rc)
 148                        break;
 149        }
 150        if (read)
 151                file->f_mode &= ~FMODE_READ;
 152        kfree(rbuf);
 153out:
 154        if (!rc)
 155                rc = crypto_shash_final(&desc.shash, hash->digest);
 156        return rc;
 157}
 158
 159int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash)
 160{
 161        struct crypto_shash *tfm;
 162        int rc;
 163
 164        tfm = ima_alloc_tfm(hash->algo);
 165        if (IS_ERR(tfm))
 166                return PTR_ERR(tfm);
 167
 168        rc = ima_calc_file_hash_tfm(file, hash, tfm);
 169
 170        ima_free_tfm(tfm);
 171
 172        return rc;
 173}
 174
 175/*
 176 * Calculate the hash of template data
 177 */
 178static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,
 179                                         struct ima_template_desc *td,
 180                                         int num_fields,
 181                                         struct ima_digest_data *hash,
 182                                         struct crypto_shash *tfm)
 183{
 184        struct {
 185                struct shash_desc shash;
 186                char ctx[crypto_shash_descsize(tfm)];
 187        } desc;
 188        int rc, i;
 189
 190        desc.shash.tfm = tfm;
 191        desc.shash.flags = 0;
 192
 193        hash->length = crypto_shash_digestsize(tfm);
 194
 195        rc = crypto_shash_init(&desc.shash);
 196        if (rc != 0)
 197                return rc;
 198
 199        for (i = 0; i < num_fields; i++) {
 200                u8 buffer[IMA_EVENT_NAME_LEN_MAX + 1] = { 0 };
 201                u8 *data_to_hash = field_data[i].data;
 202                u32 datalen = field_data[i].len;
 203
 204                if (strcmp(td->name, IMA_TEMPLATE_IMA_NAME) != 0) {
 205                        rc = crypto_shash_update(&desc.shash,
 206                                                (const u8 *) &field_data[i].len,
 207                                                sizeof(field_data[i].len));
 208                        if (rc)
 209                                break;
 210                } else if (strcmp(td->fields[i]->field_id, "n") == 0) {
 211                        memcpy(buffer, data_to_hash, datalen);
 212                        data_to_hash = buffer;
 213                        datalen = IMA_EVENT_NAME_LEN_MAX + 1;
 214                }
 215                rc = crypto_shash_update(&desc.shash, data_to_hash, datalen);
 216                if (rc)
 217                        break;
 218        }
 219
 220        if (!rc)
 221                rc = crypto_shash_final(&desc.shash, hash->digest);
 222
 223        return rc;
 224}
 225
 226int ima_calc_field_array_hash(struct ima_field_data *field_data,
 227                              struct ima_template_desc *desc, int num_fields,
 228                              struct ima_digest_data *hash)
 229{
 230        struct crypto_shash *tfm;
 231        int rc;
 232
 233        tfm = ima_alloc_tfm(hash->algo);
 234        if (IS_ERR(tfm))
 235                return PTR_ERR(tfm);
 236
 237        rc = ima_calc_field_array_hash_tfm(field_data, desc, num_fields,
 238                                           hash, tfm);
 239
 240        ima_free_tfm(tfm);
 241
 242        return rc;
 243}
 244
 245static void __init ima_pcrread(int idx, u8 *pcr)
 246{
 247        if (!ima_used_chip)
 248                return;
 249
 250        if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0)
 251                pr_err("Error Communicating to TPM chip\n");
 252}
 253
 254/*
 255 * Calculate the boot aggregate hash
 256 */
 257static int __init ima_calc_boot_aggregate_tfm(char *digest,
 258                                              struct crypto_shash *tfm)
 259{
 260        u8 pcr_i[TPM_DIGEST_SIZE];
 261        int rc, i;
 262        struct {
 263                struct shash_desc shash;
 264                char ctx[crypto_shash_descsize(tfm)];
 265        } desc;
 266
 267        desc.shash.tfm = tfm;
 268        desc.shash.flags = 0;
 269
 270        rc = crypto_shash_init(&desc.shash);
 271        if (rc != 0)
 272                return rc;
 273
 274        /* cumulative sha1 over tpm registers 0-7 */
 275        for (i = TPM_PCR0; i < TPM_PCR8; i++) {
 276                ima_pcrread(i, pcr_i);
 277                /* now accumulate with current aggregate */
 278                rc = crypto_shash_update(&desc.shash, pcr_i, TPM_DIGEST_SIZE);
 279        }
 280        if (!rc)
 281                crypto_shash_final(&desc.shash, digest);
 282        return rc;
 283}
 284
 285int __init ima_calc_boot_aggregate(struct ima_digest_data *hash)
 286{
 287        struct crypto_shash *tfm;
 288        int rc;
 289
 290        tfm = ima_alloc_tfm(hash->algo);
 291        if (IS_ERR(tfm))
 292                return PTR_ERR(tfm);
 293
 294        hash->length = crypto_shash_digestsize(tfm);
 295        rc = ima_calc_boot_aggregate_tfm(hash->digest, tfm);
 296
 297        ima_free_tfm(tfm);
 298
 299        return rc;
 300}
 301