/* Copyright 2019 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * Firmware management parameters (FWMP) APIs
 */

#include "2common.h"
#include "2crc8.h"
#include "2misc.h"
#include "2secdata.h"
#include "2secdata_struct.h"

test_mockable
vb2_error_t vb2api_secdata_fwmp_check(struct vb2_context *ctx, uint8_t *size)
{
	struct vb2_secdata_fwmp *sec =
		(struct vb2_secdata_fwmp *)&ctx->secdata_fwmp;

	/* Verify that at least the minimum size has been read */
	if (*size < VB2_SECDATA_FWMP_MIN_SIZE) {
		VB2_DEBUG("FWMP: missing %d bytes for minimum size\n",
			  VB2_SECDATA_FWMP_MIN_SIZE - *size);
		*size = VB2_SECDATA_FWMP_MIN_SIZE;
		return VB2_ERROR_SECDATA_FWMP_INCOMPLETE;
	}

	/* Verify that struct_size is reasonable */
	if (sec->struct_size < VB2_SECDATA_FWMP_MIN_SIZE ||
	    sec->struct_size > VB2_SECDATA_FWMP_MAX_SIZE) {
		VB2_DEBUG("FWMP: invalid size: %d\n", sec->struct_size);
		return VB2_ERROR_SECDATA_FWMP_SIZE;
	}

	/* Verify that we have read full structure */
	if (*size < sec->struct_size) {
		VB2_DEBUG("FWMP: missing %d bytes\n", sec->struct_size - *size);
		*size = sec->struct_size;
		return VB2_ERROR_SECDATA_FWMP_INCOMPLETE;
	}
	*size = sec->struct_size;

	/* Verify CRC */
	if (sec->crc8 != vb2_secdata_fwmp_crc(sec)) {
		VB2_DEBUG("FWMP: bad CRC\n");
		return VB2_ERROR_SECDATA_FWMP_CRC;
	}

	/* Verify major version is compatible */
	if ((sec->struct_version >> 4) != (VB2_SECDATA_FWMP_VERSION >> 4)) {
		VB2_DEBUG("FWMP: major version incompatible\n");
		return VB2_ERROR_SECDATA_FWMP_VERSION;
	}

	/*
	 * If this were a 1.1+ reader and the source was a 1.0 struct,
	 * we would need to take care of initializing the extra fields
	 * added in 1.1+.  But that's not an issue yet.
	 */
	return VB2_SUCCESS;
}

vb2_error_t vb2_secdata_fwmp_init(struct vb2_context *ctx)
{
	struct vb2_shared_data *sd = vb2_get_sd(ctx);
	struct vb2_secdata_fwmp *sec =
		(struct vb2_secdata_fwmp *)&ctx->secdata_fwmp;

	/* Skip checking if NO_SECDATA_FWMP is set. */
	if (!(ctx->flags & VB2_CONTEXT_NO_SECDATA_FWMP))
		VB2_TRY(vb2api_secdata_fwmp_check(ctx, &sec->struct_size));

	/* Mark as initialized */
	sd->status |= VB2_SD_STATUS_SECDATA_FWMP_INIT;

	return VB2_SUCCESS;
}

int vb2_secdata_fwmp_get_flag(struct vb2_context *ctx,
			      enum vb2_secdata_fwmp_flags flag)
{
	struct vb2_shared_data *sd = vb2_get_sd(ctx);
	struct vb2_secdata_fwmp *sec =
		(struct vb2_secdata_fwmp *)&ctx->secdata_fwmp;

	if (!(sd->status & VB2_SD_STATUS_SECDATA_FWMP_INIT)) {
		VB2_REC_OR_DIE(ctx, "Must init FWMP before retrieving flag\n");
		return 0;
	}

	if (ctx->flags & VB2_CONTEXT_NO_SECDATA_FWMP)
		return 0;

	return !!(sec->flags & flag);
}

uint8_t *vb2_secdata_fwmp_get_dev_key_hash(struct vb2_context *ctx)
{
	struct vb2_shared_data *sd = vb2_get_sd(ctx);
	struct vb2_secdata_fwmp *sec =
		(struct vb2_secdata_fwmp *)&ctx->secdata_fwmp;

	if (!(sd->status & VB2_SD_STATUS_SECDATA_FWMP_INIT)) {
		VB2_REC_OR_DIE(ctx, "Must init FWMP before get dev key hash\n");
		return NULL;
	}

	if (ctx->flags & VB2_CONTEXT_NO_SECDATA_FWMP)
		return NULL;

	return sec->dev_key_hash;
}
