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#include <linux/kernel.h>
  17#include <linux/file.h>
  18#include <linux/crypto.h>
  19#include <linux/scatterlist.h>
  20#include <linux/err.h>
  21#include "ima.h"
  22
  23static int init_desc(struct hash_desc *desc)
  24{
  25        int rc;
  26
  27        desc->tfm = crypto_alloc_hash(ima_hash, 0, CRYPTO_ALG_ASYNC);
  28        if (IS_ERR(desc->tfm)) {
  29                pr_info("failed to load %s transform: %ld\n",
  30                        ima_hash, PTR_ERR(desc->tfm));
  31                rc = PTR_ERR(desc->tfm);
  32                return rc;
  33        }
  34        desc->flags = 0;
  35        rc = crypto_hash_init(desc);
  36        if (rc)
  37                crypto_free_hash(desc->tfm);
  38        return rc;
  39}
  40
  41/*
  42 * Calculate the MD5/SHA1 file digest
  43 */
  44int ima_calc_hash(struct file *file, char *digest)
  45{
  46        struct hash_desc desc;
  47        struct scatterlist sg[1];
  48        loff_t i_size, offset = 0;
  49        char *rbuf;
  50        int rc;
  51
  52        rc = init_desc(&desc);
  53        if (rc != 0)
  54                return rc;
  55
  56        rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL);
  57        if (!rbuf) {
  58                rc = -ENOMEM;
  59                goto out;
  60        }
  61        i_size = i_size_read(file->f_dentry->d_inode);
  62        while (offset < i_size) {
  63                int rbuf_len;
  64
  65                rbuf_len = kernel_read(file, offset, rbuf, PAGE_SIZE);
  66                if (rbuf_len < 0) {
  67                        rc = rbuf_len;
  68                        break;
  69                }
  70                if (rbuf_len == 0)
  71                        break;
  72                offset += rbuf_len;
  73                sg_init_one(sg, rbuf, rbuf_len);
  74
  75                rc = crypto_hash_update(&desc, sg, rbuf_len);
  76                if (rc)
  77                        break;
  78        }
  79        kfree(rbuf);
  80        if (!rc)
  81                rc = crypto_hash_final(&desc, digest);
  82out:
  83        crypto_free_hash(desc.tfm);
  84        return rc;
  85}
  86
  87/*
  88 * Calculate the hash of a given template
  89 */
  90int ima_calc_template_hash(int template_len, void *template, char *digest)
  91{
  92        struct hash_desc desc;
  93        struct scatterlist sg[1];
  94        int rc;
  95
  96        rc = init_desc(&desc);
  97        if (rc != 0)
  98                return rc;
  99
 100        sg_init_one(sg, template, template_len);
 101        rc = crypto_hash_update(&desc, sg, template_len);
 102        if (!rc)
 103                rc = crypto_hash_final(&desc, digest);
 104        crypto_free_hash(desc.tfm);
 105        return rc;
 106}
 107
 108static void __init ima_pcrread(int idx, u8 *pcr)
 109{
 110        if (!ima_used_chip)
 111                return;
 112
 113        if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0)
 114                pr_err("Error Communicating to TPM chip\n");
 115}
 116
 117/*
 118 * Calculate the boot aggregate hash
 119 */
 120int __init ima_calc_boot_aggregate(char *digest)
 121{
 122        struct hash_desc desc;
 123        struct scatterlist sg;
 124        u8 pcr_i[IMA_DIGEST_SIZE];
 125        int rc, i;
 126
 127        rc = init_desc(&desc);
 128        if (rc != 0)
 129                return rc;
 130
 131        /* cumulative sha1 over tpm registers 0-7 */
 132        for (i = TPM_PCR0; i < TPM_PCR8; i++) {
 133                ima_pcrread(i, pcr_i);
 134                /* now accumulate with current aggregate */
 135                sg_init_one(&sg, pcr_i, IMA_DIGEST_SIZE);
 136                rc = crypto_hash_update(&desc, &sg, IMA_DIGEST_SIZE);
 137        }
 138        if (!rc)
 139                crypto_hash_final(&desc, digest);
 140        crypto_free_hash(desc.tfm);
 141        return rc;
 142}
 143