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