xref: /aosp_15_r20/external/vboot_reference/firmware/2lib/2secdata_fwmp.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1 /* Copyright 2019 The ChromiumOS Authors
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  *
5  * Firmware management parameters (FWMP) APIs
6  */
7 
8 #include "2common.h"
9 #include "2crc8.h"
10 #include "2misc.h"
11 #include "2secdata.h"
12 #include "2secdata_struct.h"
13 
14 test_mockable
vb2api_secdata_fwmp_check(struct vb2_context * ctx,uint8_t * size)15 vb2_error_t vb2api_secdata_fwmp_check(struct vb2_context *ctx, uint8_t *size)
16 {
17 	struct vb2_secdata_fwmp *sec =
18 		(struct vb2_secdata_fwmp *)&ctx->secdata_fwmp;
19 
20 	/* Verify that at least the minimum size has been read */
21 	if (*size < VB2_SECDATA_FWMP_MIN_SIZE) {
22 		VB2_DEBUG("FWMP: missing %d bytes for minimum size\n",
23 			  VB2_SECDATA_FWMP_MIN_SIZE - *size);
24 		*size = VB2_SECDATA_FWMP_MIN_SIZE;
25 		return VB2_ERROR_SECDATA_FWMP_INCOMPLETE;
26 	}
27 
28 	/* Verify that struct_size is reasonable */
29 	if (sec->struct_size < VB2_SECDATA_FWMP_MIN_SIZE ||
30 	    sec->struct_size > VB2_SECDATA_FWMP_MAX_SIZE) {
31 		VB2_DEBUG("FWMP: invalid size: %d\n", sec->struct_size);
32 		return VB2_ERROR_SECDATA_FWMP_SIZE;
33 	}
34 
35 	/* Verify that we have read full structure */
36 	if (*size < sec->struct_size) {
37 		VB2_DEBUG("FWMP: missing %d bytes\n", sec->struct_size - *size);
38 		*size = sec->struct_size;
39 		return VB2_ERROR_SECDATA_FWMP_INCOMPLETE;
40 	}
41 	*size = sec->struct_size;
42 
43 	/* Verify CRC */
44 	if (sec->crc8 != vb2_secdata_fwmp_crc(sec)) {
45 		VB2_DEBUG("FWMP: bad CRC\n");
46 		return VB2_ERROR_SECDATA_FWMP_CRC;
47 	}
48 
49 	/* Verify major version is compatible */
50 	if ((sec->struct_version >> 4) != (VB2_SECDATA_FWMP_VERSION >> 4)) {
51 		VB2_DEBUG("FWMP: major version incompatible\n");
52 		return VB2_ERROR_SECDATA_FWMP_VERSION;
53 	}
54 
55 	/*
56 	 * If this were a 1.1+ reader and the source was a 1.0 struct,
57 	 * we would need to take care of initializing the extra fields
58 	 * added in 1.1+.  But that's not an issue yet.
59 	 */
60 	return VB2_SUCCESS;
61 }
62 
vb2api_secdata_fwmp_create(struct vb2_context * ctx)63 uint32_t vb2api_secdata_fwmp_create(struct vb2_context *ctx)
64 {
65 	struct vb2_secdata_fwmp *sec = (void *)&ctx->secdata_fwmp;
66 
67 	/* Clear the entire struct */
68 	memset(sec, 0, sizeof(*sec));
69 
70 	/* Set to current version */
71 	sec->struct_version = VB2_SECDATA_FWMP_VERSION;
72 
73 	/* Set the structure size */
74 	sec->struct_size = sizeof(*sec);
75 
76 	/* Calculate initial CRC */
77 	sec->crc8 = vb2_secdata_fwmp_crc(sec);
78 
79 	return sizeof(*sec);
80 }
81 
82 test_mockable
vb2_secdata_fwmp_init(struct vb2_context * ctx)83 vb2_error_t vb2_secdata_fwmp_init(struct vb2_context *ctx)
84 {
85 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
86 	struct vb2_secdata_fwmp *sec =
87 		(struct vb2_secdata_fwmp *)&ctx->secdata_fwmp;
88 
89 	/* Skip checking if NO_SECDATA_FWMP is set. */
90 	if (!(ctx->flags & VB2_CONTEXT_NO_SECDATA_FWMP))
91 		VB2_TRY(vb2api_secdata_fwmp_check(ctx, &sec->struct_size));
92 
93 	/* Mark as initialized */
94 	sd->status |= VB2_SD_STATUS_SECDATA_FWMP_INIT;
95 
96 	return VB2_SUCCESS;
97 }
98 
vb2_secdata_fwmp_get_flag(struct vb2_context * ctx,enum vb2_secdata_fwmp_flags flag)99 int vb2_secdata_fwmp_get_flag(struct vb2_context *ctx,
100 			      enum vb2_secdata_fwmp_flags flag)
101 {
102 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
103 	struct vb2_secdata_fwmp *sec =
104 		(struct vb2_secdata_fwmp *)&ctx->secdata_fwmp;
105 
106 	if (!(sd->status & VB2_SD_STATUS_SECDATA_FWMP_INIT)) {
107 		VB2_REC_OR_DIE(ctx, "Must init FWMP before retrieving flag\n");
108 		return 0;
109 	}
110 
111 	if (ctx->flags & VB2_CONTEXT_NO_SECDATA_FWMP)
112 		return 0;
113 
114 	return !!(sec->flags & flag);
115 }
116 
vb2_secdata_fwmp_get_dev_key_hash(struct vb2_context * ctx)117 uint8_t *vb2_secdata_fwmp_get_dev_key_hash(struct vb2_context *ctx)
118 {
119 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
120 	struct vb2_secdata_fwmp *sec =
121 		(struct vb2_secdata_fwmp *)&ctx->secdata_fwmp;
122 
123 	if (!(sd->status & VB2_SD_STATUS_SECDATA_FWMP_INIT)) {
124 		VB2_REC_OR_DIE(ctx, "Must init FWMP before get dev key hash\n");
125 		return NULL;
126 	}
127 
128 	if (ctx->flags & VB2_CONTEXT_NO_SECDATA_FWMP)
129 		return NULL;
130 
131 	return sec->dev_key_hash;
132 }
133