Path: blob/master/security/integrity/ima/ima_crypto.c
10820 views
/*1* Copyright (C) 2005,2006,2007,2008 IBM Corporation2*3* Authors:4* Mimi Zohar <[email protected]>5* Kylene Hall <[email protected]>6*7* This program is free software; you can redistribute it and/or modify8* it under the terms of the GNU General Public License as published by9* the Free Software Foundation, version 2 of the License.10*11* File: ima_crypto.c12* Calculates md5/sha1 file hash, template hash, boot-aggreate hash13*/1415#include <linux/kernel.h>16#include <linux/file.h>17#include <linux/crypto.h>18#include <linux/scatterlist.h>19#include <linux/err.h>20#include <linux/slab.h>21#include "ima.h"2223static int init_desc(struct hash_desc *desc)24{25int rc;2627desc->tfm = crypto_alloc_hash(ima_hash, 0, CRYPTO_ALG_ASYNC);28if (IS_ERR(desc->tfm)) {29pr_info("IMA: failed to load %s transform: %ld\n",30ima_hash, PTR_ERR(desc->tfm));31rc = PTR_ERR(desc->tfm);32return rc;33}34desc->flags = 0;35rc = crypto_hash_init(desc);36if (rc)37crypto_free_hash(desc->tfm);38return rc;39}4041/*42* Calculate the MD5/SHA1 file digest43*/44int ima_calc_hash(struct file *file, char *digest)45{46struct hash_desc desc;47struct scatterlist sg[1];48loff_t i_size, offset = 0;49char *rbuf;50int rc;5152rc = init_desc(&desc);53if (rc != 0)54return rc;5556rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL);57if (!rbuf) {58rc = -ENOMEM;59goto out;60}61i_size = i_size_read(file->f_dentry->d_inode);62while (offset < i_size) {63int rbuf_len;6465rbuf_len = kernel_read(file, offset, rbuf, PAGE_SIZE);66if (rbuf_len < 0) {67rc = rbuf_len;68break;69}70if (rbuf_len == 0)71break;72offset += rbuf_len;73sg_init_one(sg, rbuf, rbuf_len);7475rc = crypto_hash_update(&desc, sg, rbuf_len);76if (rc)77break;78}79kfree(rbuf);80if (!rc)81rc = crypto_hash_final(&desc, digest);82out:83crypto_free_hash(desc.tfm);84return rc;85}8687/*88* Calculate the hash of a given template89*/90int ima_calc_template_hash(int template_len, void *template, char *digest)91{92struct hash_desc desc;93struct scatterlist sg[1];94int rc;9596rc = init_desc(&desc);97if (rc != 0)98return rc;99100sg_init_one(sg, template, template_len);101rc = crypto_hash_update(&desc, sg, template_len);102if (!rc)103rc = crypto_hash_final(&desc, digest);104crypto_free_hash(desc.tfm);105return rc;106}107108static void __init ima_pcrread(int idx, u8 *pcr)109{110if (!ima_used_chip)111return;112113if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0)114pr_err("IMA: Error Communicating to TPM chip\n");115}116117/*118* Calculate the boot aggregate hash119*/120int __init ima_calc_boot_aggregate(char *digest)121{122struct hash_desc desc;123struct scatterlist sg;124u8 pcr_i[IMA_DIGEST_SIZE];125int rc, i;126127rc = init_desc(&desc);128if (rc != 0)129return rc;130131/* cumulative sha1 over tpm registers 0-7 */132for (i = TPM_PCR0; i < TPM_PCR8; i++) {133ima_pcrread(i, pcr_i);134/* now accumulate with current aggregate */135sg_init_one(&sg, pcr_i, IMA_DIGEST_SIZE);136rc = crypto_hash_update(&desc, &sg, IMA_DIGEST_SIZE);137}138if (!rc)139crypto_hash_final(&desc, digest);140crypto_free_hash(desc.tfm);141return rc;142}143144145