diff -drupN a/security/fivm/fivm_crypto.c b/security/fivm/fivm_crypto.c --- a/security/fivm/fivm_crypto.c 1970-01-01 03:00:00.000000000 +0300 +++ b/security/fivm/fivm_crypto.c 2022-06-12 05:28:14.000000000 +0300 @@ -0,0 +1,83 @@ +/* + * 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; +}