/* * Copyright (C) 2014 Allwinner Ltd. * * Author: * Ryan Chen * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2 of the * License. * * File: fivm_crypto.c */ #include #include #include #include #include #include #include #include "fivm.h" static char *fivm_hash = "sha256"; static int init_desc(struct hash_desc *desc) { int rc; desc->tfm = crypto_alloc_hash(fivm_hash, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(desc->tfm)) { pr_info("FIVM: failed to load %s transform: %ld\n", fivm_hash, PTR_ERR(desc->tfm)); rc = PTR_ERR(desc->tfm); return rc; } desc->flags = 0; rc = crypto_hash_init(desc); if (rc) crypto_free_hash(desc->tfm); return rc; } int fivm_calc_hash(struct file *file, char *digest) { struct hash_desc desc; struct scatterlist sg[1]; loff_t i_size, offset = 0; char *rbuf; int rc; rc = init_desc(&desc); if (rc != 0) return rc; rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!rbuf) { rc = -ENOMEM; goto out; } i_size = i_size_read(file->f_path.dentry->d_inode); while (offset < i_size) { int rbuf_len; rbuf_len = kernel_read(file, offset, rbuf, PAGE_SIZE); if (rbuf_len < 0) { rc = rbuf_len; break; } if (rbuf_len == 0) break; offset += rbuf_len; sg_init_one(sg, rbuf, rbuf_len); rc = crypto_hash_update(&desc, sg, rbuf_len); if (rc) break; } kfree(rbuf); if (!rc) rc = crypto_hash_final(&desc, digest); out: crypto_free_hash(desc.tfm); return rc; }