xref: /aosp_15_r20/external/vboot_reference/tests/vb2_secdata_fwmp_tests.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  * Tests for firmware management parameters (FWMP) library.
6  */
7 
8 #include "2common.h"
9 #include "2misc.h"
10 #include "2secdata.h"
11 #include "2secdata_struct.h"
12 #include "common/tests.h"
13 
14 static uint8_t workbuf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE]
15 	__attribute__((aligned(VB2_WORKBUF_ALIGN)));
16 static struct vb2_context *ctx;
17 static struct vb2_gbb_header gbb;
18 static struct vb2_shared_data *sd;
19 static struct vb2_secdata_fwmp *sec;
20 
reset_common_data(void)21 static void reset_common_data(void)
22 {
23 	memset(workbuf, 0xaa, sizeof(workbuf));
24 	TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
25 		  "vb2api_init failed");
26 
27 	sd = vb2_get_sd(ctx);
28 	sd->status |= VB2_SD_STATUS_SECDATA_FWMP_INIT;
29 	sd->status |= VB2_SD_STATUS_RECOVERY_DECIDED;
30 
31 	memset(&gbb, 0, sizeof(gbb));
32 
33 	sec = (struct vb2_secdata_fwmp *)ctx->secdata_fwmp;
34 	sec->struct_size = VB2_SECDATA_FWMP_MIN_SIZE;
35 	sec->struct_version = VB2_SECDATA_FWMP_VERSION;
36 	sec->flags = 0;
37 	sec->crc8 = vb2_secdata_fwmp_crc(sec);
38 }
39 
40 /* Mocked functions */
41 
vb2_get_gbb(struct vb2_context * c)42 struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c)
43 {
44 	return &gbb;
45 }
46 
check_init_test(void)47 static void check_init_test(void)
48 {
49 	uint8_t size;
50 
51 	/* Check size constants */
52 	TEST_TRUE(sizeof(struct vb2_secdata_fwmp) >= VB2_SECDATA_FWMP_MIN_SIZE,
53 		  "Struct min size constant");
54 	TEST_TRUE(sizeof(struct vb2_secdata_fwmp) <= VB2_SECDATA_FWMP_MAX_SIZE,
55 		  "Struct max size constant");
56 
57 	/* struct_size too large */
58 	reset_common_data();
59 	sec->struct_size = VB2_SECDATA_FWMP_MAX_SIZE + 1;
60 	sec->crc8 = vb2_secdata_fwmp_crc(sec);
61 	size = sec->struct_size;
62 	TEST_EQ(vb2api_secdata_fwmp_check(ctx, &size),
63 		VB2_ERROR_SECDATA_FWMP_SIZE, "Check struct_size too large");
64 	TEST_EQ(vb2_secdata_fwmp_init(ctx),
65 		VB2_ERROR_SECDATA_FWMP_SIZE, "Init struct_size too large");
66 
67 	/* struct_size too small */
68 	reset_common_data();
69 	sec->struct_size = VB2_SECDATA_FWMP_MIN_SIZE - 1;
70 	sec->crc8 = vb2_secdata_fwmp_crc(sec);
71 	size = VB2_SECDATA_FWMP_MIN_SIZE;
72 	TEST_EQ(vb2api_secdata_fwmp_check(ctx, &size),
73 		VB2_ERROR_SECDATA_FWMP_SIZE, "Check struct_size too small");
74 
75 	/* Need more data to reach minimum size */
76 	reset_common_data();
77 	sec->struct_size = VB2_SECDATA_FWMP_MIN_SIZE - 1;
78 	sec->crc8 = vb2_secdata_fwmp_crc(sec);
79 	size = 0;
80 	TEST_EQ(vb2api_secdata_fwmp_check(ctx, &size),
81 		VB2_ERROR_SECDATA_FWMP_INCOMPLETE, "Check more to reach MIN");
82 	TEST_EQ(vb2_secdata_fwmp_init(ctx),
83 		VB2_ERROR_SECDATA_FWMP_INCOMPLETE, "Init more to reach MIN");
84 
85 	/* Need more data to reach full size */
86 	reset_common_data();
87 	sec->struct_size = VB2_SECDATA_FWMP_MIN_SIZE + 1;
88 	sec->crc8 = vb2_secdata_fwmp_crc(sec);
89 	size = VB2_SECDATA_FWMP_MIN_SIZE;
90 	TEST_EQ(vb2api_secdata_fwmp_check(ctx, &size),
91 		VB2_ERROR_SECDATA_FWMP_INCOMPLETE, "Check more for full size");
92 
93 	/* Bad data is invalid */
94 	reset_common_data();
95 	memset(&ctx->secdata_fwmp, 0xa6, sizeof(ctx->secdata_fwmp));
96 	sec->struct_size = VB2_SECDATA_FWMP_MIN_SIZE;
97 	size = sec->struct_size;
98 	TEST_EQ(vb2api_secdata_fwmp_check(ctx, &size),
99 		VB2_ERROR_SECDATA_FWMP_CRC, "Check bad data CRC");
100 	TEST_EQ(vb2_secdata_fwmp_init(ctx),
101 		VB2_ERROR_SECDATA_FWMP_CRC, "Init bad data CRC");
102 
103 	/* Bad CRC with corruption past minimum size */
104 	reset_common_data();
105 	sec->struct_size = VB2_SECDATA_FWMP_MIN_SIZE + 1;
106 	sec->crc8 = vb2_secdata_fwmp_crc(sec);
107 	size = sec->struct_size;
108 	*((uint8_t *)sec + sec->struct_size - 1) += 1;
109 	TEST_EQ(vb2api_secdata_fwmp_check(ctx, &size),
110 		VB2_ERROR_SECDATA_FWMP_CRC, "Check corruption CRC");
111 	TEST_EQ(vb2_secdata_fwmp_init(ctx),
112 		VB2_ERROR_SECDATA_FWMP_CRC, "Init corruption CRC");
113 
114 	/* Zeroed data is invalid */
115 	reset_common_data();
116 	memset(&ctx->secdata_fwmp, 0, sizeof(ctx->secdata_fwmp));
117 	sec->struct_size = VB2_SECDATA_FWMP_MIN_SIZE;
118 	size = sec->struct_size;
119 	TEST_EQ(vb2api_secdata_fwmp_check(ctx, &size),
120 		VB2_ERROR_SECDATA_FWMP_VERSION, "Check zeroed data CRC");
121 	TEST_EQ(vb2_secdata_fwmp_init(ctx),
122 		VB2_ERROR_SECDATA_FWMP_VERSION, "Init zeroed data CRC");
123 
124 	/* Major version too high */
125 	reset_common_data();
126 	sec->struct_version = ((VB2_SECDATA_FWMP_VERSION >> 4) + 1) << 4;
127 	sec->crc8 = vb2_secdata_fwmp_crc(sec);
128 	TEST_EQ(vb2api_secdata_fwmp_check(ctx, &size),
129 		VB2_ERROR_SECDATA_FWMP_VERSION, "Check major too high");
130 	TEST_EQ(vb2_secdata_fwmp_init(ctx),
131 		VB2_ERROR_SECDATA_FWMP_VERSION, "Init major too high");
132 
133 	/* Major version too low */
134 	reset_common_data();
135 	sec->struct_version = ((VB2_SECDATA_FWMP_VERSION >> 4) - 1) << 4;
136 	sec->crc8 = vb2_secdata_fwmp_crc(sec);
137 	TEST_EQ(vb2api_secdata_fwmp_check(ctx, &size),
138 		VB2_ERROR_SECDATA_FWMP_VERSION, "Check major too low");
139 	TEST_EQ(vb2_secdata_fwmp_init(ctx),
140 		VB2_ERROR_SECDATA_FWMP_VERSION, "Init major too low");
141 
142 	/* Minor version difference okay */
143 	reset_common_data();
144 	sec->struct_version += 1;
145 	sec->crc8 = vb2_secdata_fwmp_crc(sec);
146 	TEST_SUCC(vb2api_secdata_fwmp_check(ctx, &size), "Check minor okay");
147 	TEST_SUCC(vb2_secdata_fwmp_init(ctx), "Init minor okay");
148 
149 	/* Good FWMP data at minimum size */
150 	reset_common_data();
151 	TEST_SUCC(vb2api_secdata_fwmp_check(ctx, &size), "Check good (min)");
152 	TEST_SUCC(vb2_secdata_fwmp_init(ctx), "Init good (min)");
153 	TEST_NEQ(sd->status & VB2_SD_STATUS_SECDATA_FWMP_INIT, 0,
154 		 "Init flag set");
155 
156 	/* Good FWMP data at minimum + N size */
157 	reset_common_data();
158 	sec->struct_size = VB2_SECDATA_FWMP_MIN_SIZE + 1;
159 	sec->crc8 = vb2_secdata_fwmp_crc(sec);
160 	size = sec->struct_size;
161 	TEST_SUCC(vb2api_secdata_fwmp_check(ctx, &size), "Check good (min+N)");
162 	TEST_SUCC(vb2_secdata_fwmp_init(ctx), "Init good (min+N)");
163 	TEST_NEQ(sd->status & VB2_SD_STATUS_SECDATA_FWMP_INIT, 0,
164 		 "Init flag set");
165 
166 	/* Skip data check when NO_SECDATA_FWMP set */
167 	reset_common_data();
168 	memset(&ctx->secdata_fwmp, 0xa6, sizeof(ctx->secdata_fwmp));
169 	ctx->flags |= VB2_CONTEXT_NO_SECDATA_FWMP;
170 	TEST_EQ(vb2_secdata_fwmp_init(ctx), 0,
171 		"Init skip data check when NO_SECDATA_FWMP set");
172 	TEST_NEQ(sd->status & VB2_SD_STATUS_SECDATA_FWMP_INIT, 0,
173 		 "Init flag set");
174 }
175 
get_flag_test(void)176 static void get_flag_test(void)
177 {
178 	/* Successfully returns value */
179 	reset_common_data();
180 	sec->flags |= 1;
181 	TEST_EQ(vb2_secdata_fwmp_get_flag(ctx, 1), 1,
182 		"Successfully returns flag value");
183 
184 	/* NO_SECDATA_FWMP */
185 	reset_common_data();
186 	sec->flags |= 1;
187 	ctx->flags |= VB2_CONTEXT_NO_SECDATA_FWMP;
188 	TEST_EQ(vb2_secdata_fwmp_get_flag(ctx, 1), 0,
189 		"NO_SECDATA_FWMP forces default flag value");
190 
191 	/* FWMP hasn't been initialized (recovery mode) */
192 	reset_common_data();
193 	sd->status &= ~VB2_SD_STATUS_SECDATA_FWMP_INIT;
194 	ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
195 	TEST_EQ(vb2_secdata_fwmp_get_flag(ctx, 0), 0,
196 		"non-init in recovery mode forces default flag value");
197 
198 	/* FWMP hasn't been initialized (normal mode) */
199 	reset_common_data();
200 	sd->status &= ~VB2_SD_STATUS_SECDATA_FWMP_INIT;
201 	TEST_ABORT(vb2_secdata_fwmp_get_flag(ctx, 0),
202 		   "non-init in normal mode triggers abort");
203 
204 	/* FWMP hasn't been initialized (before recovery decision) */
205 	reset_common_data();
206 	sd->status &= ~VB2_SD_STATUS_SECDATA_FWMP_INIT;
207 	sd->status &= ~VB2_SD_STATUS_RECOVERY_DECIDED;
208 	TEST_EQ(vb2_secdata_fwmp_get_flag(ctx, 0), 0,
209 		"non-init in fw_phase1 forces default flag value");
210 }
211 
get_dev_key_hash_test(void)212 static void get_dev_key_hash_test(void)
213 {
214 	/* CONTEXT_NO_SECDATA_FWMP */
215 	reset_common_data();
216 	ctx->flags |= VB2_CONTEXT_NO_SECDATA_FWMP;
217 	TEST_TRUE(vb2_secdata_fwmp_get_dev_key_hash(ctx) == NULL,
218 		  "NO_SECDATA_FWMP forces NULL pointer");
219 
220 	/* FWMP hasn't been initialized (recovery mode) */
221 	reset_common_data();
222 	sd->status &= ~VB2_SD_STATUS_SECDATA_FWMP_INIT;
223 	ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
224 	TEST_TRUE(vb2_secdata_fwmp_get_dev_key_hash(ctx) == NULL,
225 		  "non-init in recovery mode forces NULL pointer");
226 
227 	/* FWMP hasn't been initialized (normal mode) */
228 	reset_common_data();
229 	sd->status &= ~VB2_SD_STATUS_SECDATA_FWMP_INIT;
230 	TEST_ABORT(vb2_secdata_fwmp_get_dev_key_hash(ctx),
231 		   "non-init in normal mode triggers abort");
232 
233 	/* FWMP hasn't been initialized (before recovery decision) */
234 	reset_common_data();
235 	sd->status &= ~VB2_SD_STATUS_SECDATA_FWMP_INIT;
236 	sd->status &= ~VB2_SD_STATUS_RECOVERY_DECIDED;
237 	TEST_TRUE(vb2_secdata_fwmp_get_dev_key_hash(ctx) == NULL,
238 		  "non-init in fw_phase1 forces NULL pointer");
239 
240 	/* Success case */
241 	reset_common_data();
242 	TEST_TRUE(vb2_secdata_fwmp_get_dev_key_hash(ctx) ==
243 		  sec->dev_key_hash, "proper dev_key_hash pointer returned");
244 }
245 
main(int argc,char * argv[])246 int main(int argc, char* argv[])
247 {
248 	check_init_test();
249 	get_flag_test();
250 	get_dev_key_hash_test();
251 
252 	return gTestSuccess ? 0 : 255;
253 }
254