summaryrefslogtreecommitdiff
path: root/firmware/2lib/2secdata_fwmp.c
blob: 170fc5c25c3f84d2514cfd9aca98524be546bc5c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/* 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"

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;
	vb2_error_t rv;

	/* Skip checking if NO_SECDATA_FWMP is set. */
	if (!(ctx->flags & VB2_CONTEXT_NO_SECDATA_FWMP)) {
		rv = vb2api_secdata_fwmp_check(ctx, &sec->struct_size);
		if (rv)
			return rv;
	}

	/* 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;
}