summaryrefslogtreecommitdiff
path: root/firmware/2lib/2secdata_fwmp.c
blob: 1d5abd836802857785b22225acc25ab41d82f924 (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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* 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;
}

uint32_t vb2api_secdata_fwmp_create(struct vb2_context *ctx)
{
	struct vb2_secdata_fwmp *sec = (void *)&ctx->secdata_fwmp;

	/* Clear the entire struct */
	memset(sec, 0, sizeof(*sec));

	/* Set to current version */
	sec->struct_version = VB2_SECDATA_FWMP_VERSION;

	/* Set the structure size */
	sec->struct_size = sizeof(*sec);

	/* Calculate initial CRC */
	sec->crc8 = vb2_secdata_fwmp_crc(sec);

	return sizeof(*sec);
}

test_mockable
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;
}