// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright 2019 Google LLC
 */
#include <crypto/sha.h>
#include <crypto/hash.h>
#include <linux/err.h>
#include <linux/version.h>

#include "integrity.h"

struct incfs_hash_alg *incfs_get_hash_alg(enum incfs_hash_tree_algorithm id)
{
	static struct incfs_hash_alg sha256 = {
		.name = "sha256",
		.digest_size = SHA256_DIGEST_SIZE,
		.id = INCFS_HASH_TREE_SHA256
	};
	struct incfs_hash_alg *result = NULL;
	struct crypto_shash *shash;

	if (id == INCFS_HASH_TREE_SHA256) {
		BUILD_BUG_ON(INCFS_MAX_HASH_SIZE < SHA256_DIGEST_SIZE);
		result = &sha256;
	}

	if (result == NULL)
		return ERR_PTR(-ENOENT);

	/* pairs with cmpxchg_release() below */
	shash = smp_load_acquire(&result->shash);
	if (shash)
		return result;

	shash = crypto_alloc_shash(result->name, 0, 0);
	if (IS_ERR(shash)) {
		int err = PTR_ERR(shash);

		pr_err("Can't allocate hash alg %s, error code:%d",
			result->name, err);
		return ERR_PTR(err);
	}

	/* pairs with smp_load_acquire() above */
	if (cmpxchg_release(&result->shash, NULL, shash) != NULL)
		crypto_free_shash(shash);

	return result;
}

struct signature_info {
	u32 version;
	enum incfs_hash_tree_algorithm hash_algorithm;
	u8 log2_blocksize;
	struct mem_range salt;
	struct mem_range root_hash;
};

static bool read_u32(u8 **p, u8 *top, u32 *result)
{
	if (*p + sizeof(u32) > top)
		return false;

	*result = le32_to_cpu(*(__le32 *)*p);
	*p += sizeof(u32);
	return true;
}

static bool read_u8(u8 **p, u8 *top, u8 *result)
{
	if (*p + sizeof(u8) > top)
		return false;

	*result = *(u8 *)*p;
	*p += sizeof(u8);
	return true;
}

static bool read_mem_range(u8 **p, u8 *top, struct mem_range *range)
{
	u32 len;

	if (!read_u32(p, top, &len) || *p + len > top)
		return false;

	range->len = len;
	range->data = *p;
	*p += len;
	return true;
}

static int incfs_parse_signature(struct mem_range signature,
				 struct signature_info *si)
{
	u8 *p = signature.data;
	u8 *top = signature.data + signature.len;
	u32 hash_section_size;

	if (signature.len > INCFS_MAX_SIGNATURE_SIZE)
		return -EINVAL;

	if (!read_u32(&p, top, &si->version) ||
	    si->version != INCFS_SIGNATURE_VERSION)
		return -EINVAL;

	if (!read_u32(&p, top, &hash_section_size) ||
	    p + hash_section_size > top)
		return -EINVAL;
	top = p + hash_section_size;

	if (!read_u32(&p, top, &si->hash_algorithm) ||
	    si->hash_algorithm != INCFS_HASH_TREE_SHA256)
		return -EINVAL;

	if (!read_u8(&p, top, &si->log2_blocksize) || si->log2_blocksize != 12)
		return -EINVAL;

	if (!read_mem_range(&p, top, &si->salt))
		return -EINVAL;

	if (!read_mem_range(&p, top, &si->root_hash))
		return -EINVAL;

	if (p != top)
		return -EINVAL;

	return 0;
}

struct mtree *incfs_alloc_mtree(struct mem_range signature,
				int data_block_count)
{
	int error;
	struct signature_info si;
	struct mtree *result = NULL;
	struct incfs_hash_alg *hash_alg = NULL;
	int hash_per_block;
	int lvl;
	int total_blocks = 0;
	int blocks_in_level[INCFS_MAX_MTREE_LEVELS];
	int blocks = data_block_count;

	if (data_block_count <= 0)
		return ERR_PTR(-EINVAL);

	error = incfs_parse_signature(signature, &si);
	if (error)
		return ERR_PTR(error);

	hash_alg = incfs_get_hash_alg(si.hash_algorithm);
	if (IS_ERR(hash_alg))
		return ERR_PTR(PTR_ERR(hash_alg));

	if (si.root_hash.len < hash_alg->digest_size)
		return ERR_PTR(-EINVAL);

	result = kzalloc(sizeof(*result), GFP_NOFS);
	if (!result)
		return ERR_PTR(-ENOMEM);

	result->alg = hash_alg;
	hash_per_block = INCFS_DATA_FILE_BLOCK_SIZE / result->alg->digest_size;

	/* Calculating tree geometry. */
	/* First pass: calculate how many blocks in each tree level. */
	for (lvl = 0; blocks > 1; lvl++) {
		if (lvl >= INCFS_MAX_MTREE_LEVELS) {
			pr_err("incfs: too much data in mtree");
			goto err;
		}

		blocks = (blocks + hash_per_block - 1) / hash_per_block;
		blocks_in_level[lvl] = blocks;
		total_blocks += blocks;
	}
	result->depth = lvl;
	result->hash_tree_area_size = total_blocks * INCFS_DATA_FILE_BLOCK_SIZE;
	if (result->hash_tree_area_size > INCFS_MAX_HASH_AREA_SIZE)
		goto err;

	blocks = 0;
	/* Second pass: calculate offset of each level. 0th level goes last. */
	for (lvl = 0; lvl < result->depth; lvl++) {
		u32 suboffset;

		blocks += blocks_in_level[lvl];
		suboffset = (total_blocks - blocks)
					* INCFS_DATA_FILE_BLOCK_SIZE;

		result->hash_level_suboffset[lvl] = suboffset;
	}

	/* Root hash is stored separately from the rest of the tree. */
	memcpy(result->root_hash, si.root_hash.data, hash_alg->digest_size);
	return result;

err:
	kfree(result);
	return ERR_PTR(-E2BIG);
}

void incfs_free_mtree(struct mtree *tree)
{
	kfree(tree);
}

int incfs_calc_digest(struct incfs_hash_alg *alg, struct mem_range data,
			struct mem_range digest)
{
	SHASH_DESC_ON_STACK(desc, alg->shash);

	if (!alg || !alg->shash || !data.data || !digest.data)
		return -EFAULT;

	if (alg->digest_size > digest.len)
		return -EINVAL;

	desc->tfm = alg->shash;

	if (data.len < INCFS_DATA_FILE_BLOCK_SIZE) {
		int err;
		void *buf = kzalloc(INCFS_DATA_FILE_BLOCK_SIZE, GFP_NOFS);

		if (!buf)
			return -ENOMEM;

		memcpy(buf, data.data, data.len);
		err = crypto_shash_digest(desc, buf, INCFS_DATA_FILE_BLOCK_SIZE,
					  digest.data);
		kfree(buf);
		return err;
	}
	return crypto_shash_digest(desc, data.data, data.len, digest.data);
}

