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 GBB library.
6 */
7
8 #include "2common.h"
9 #include "2misc.h"
10 #include "common/tests.h"
11
12 /* Mock data */
13 static char gbb_data[4096 + sizeof(struct vb2_gbb_header)];
14 static struct vb2_gbb_header *gbb = (struct vb2_gbb_header *)gbb_data;
15 static struct vb2_packed_key *rootkey;
16 static struct vb2_context *ctx;
17 static struct vb2_workbuf wb;
18 static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
19 __attribute__((aligned(VB2_WORKBUF_ALIGN)));
20
set_gbb_hwid(const char * hwid,size_t size)21 static void set_gbb_hwid(const char *hwid, size_t size)
22 {
23 memcpy(gbb_data + gbb->hwid_offset, hwid, size);
24 gbb->hwid_size = size;
25 }
26
reset_common_data(void)27 static void reset_common_data(void)
28 {
29 int gbb_used;
30
31 memset(gbb_data, 0, sizeof(gbb_data));
32 gbb->header_size = sizeof(*gbb);
33 gbb->major_version = VB2_GBB_MAJOR_VER;
34 gbb->minor_version = VB2_GBB_MINOR_VER;
35 gbb->flags = 0;
36 gbb_used = sizeof(struct vb2_gbb_header);
37
38 gbb->recovery_key_offset = gbb_used;
39 gbb->recovery_key_size = 64;
40 gbb_used += gbb->recovery_key_size;
41 gbb->rootkey_offset = gbb_used;
42 gbb->rootkey_size = sizeof(struct vb2_packed_key);
43 gbb_used += gbb->rootkey_size;
44
45 rootkey = ((void *)gbb + gbb->rootkey_offset);
46 rootkey->key_offset = sizeof(*rootkey);
47
48 gbb->hwid_offset = gbb_used;
49 const char hwid_src[] = "Test HWID";
50 set_gbb_hwid(hwid_src, sizeof(hwid_src));
51
52 TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
53 "vb2api_init failed");
54 vb2_workbuf_from_ctx(ctx, &wb);
55 }
56
57 /* Mocks */
vb2_get_gbb(struct vb2_context * c)58 struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c)
59 {
60 return gbb;
61 }
62
vb2ex_read_resource(struct vb2_context * c,enum vb2_resource_index index,uint32_t offset,void * buf,uint32_t size)63 vb2_error_t vb2ex_read_resource(struct vb2_context *c,
64 enum vb2_resource_index index, uint32_t offset,
65 void *buf, uint32_t size)
66 {
67 uint8_t *rptr;
68 uint32_t rsize;
69
70 switch(index) {
71 case VB2_RES_GBB:
72 rptr = (uint8_t *)&gbb_data;
73 rsize = sizeof(gbb_data);
74 break;
75 default:
76 return VB2_ERROR_EX_READ_RESOURCE_INDEX;
77 }
78
79 if (offset + size >= rsize)
80 return VB2_ERROR_EX_READ_RESOURCE_SIZE;
81
82 memcpy(buf, rptr + offset, size);
83 return VB2_SUCCESS;
84 }
85
86 /* Tests */
flag_tests(void)87 static void flag_tests(void)
88 {
89 reset_common_data();
90 gbb->flags = 0xdeadbeef;
91 TEST_EQ(vb2api_gbb_get_flags(ctx), gbb->flags,
92 "retrieve GBB flags");
93 }
94
key_tests(void)95 static void key_tests(void)
96 {
97 /* Assume that root key and recovery key are dealt with using the same
98 code in our GBB library functions. */
99 struct vb2_packed_key *keyp;
100 struct vb2_workbuf wborig;
101 const char key_data[] = "HELLOWORLD";
102 uint32_t size;
103
104 /* gbb.offset < sizeof(vb2_gbb_header) */
105 reset_common_data();
106 wborig = wb;
107 gbb->rootkey_offset = sizeof(*gbb) - 1;
108 TEST_EQ(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
109 VB2_ERROR_GBB_INVALID,
110 "gbb.rootkey offset too small");
111 TEST_TRUE(wb.buf == wborig.buf,
112 " workbuf restored on error");
113
114 /* gbb.offset > gbb_data */
115 reset_common_data();
116 wborig = wb;
117 gbb->rootkey_offset = sizeof(gbb_data) + 1;
118 TEST_EQ(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
119 VB2_ERROR_EX_READ_RESOURCE_SIZE,
120 "gbb.rootkey offset too large");
121 TEST_TRUE(wb.buf == wborig.buf,
122 " workbuf restored on error");
123
124 /* gbb.size < sizeof(vb2_packed_key) */
125 reset_common_data();
126 wborig = wb;
127 gbb->rootkey_size = sizeof(*rootkey) - 1;
128 TEST_EQ(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
129 VB2_ERROR_GBB_INVALID,
130 "gbb.rootkey size too small");
131 TEST_TRUE(wb.buf == wborig.buf,
132 " workbuf restored on error");
133
134 /* sizeof(vb2_packed_key) > workbuf.size */
135 reset_common_data();
136 wborig = wb;
137 wb.size = sizeof(*rootkey) - 1;
138 TEST_EQ(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
139 VB2_ERROR_GBB_WORKBUF,
140 "workbuf size too small for vb2_packed_key header");
141 TEST_TRUE(wb.buf == wborig.buf,
142 " workbuf restored on error");
143
144 /* packed_key.offset < sizeof(vb2_packed_key) */
145 reset_common_data();
146 wborig = wb;
147 rootkey->key_size = 1;
148 rootkey->key_offset = sizeof(*rootkey) - 1;
149 TEST_EQ(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
150 VB2_ERROR_INSIDE_DATA_OVERLAP,
151 "rootkey offset too small");
152 TEST_TRUE(wb.buf == wborig.buf,
153 " workbuf restored on error");
154
155 /* packed_key.offset > gbb_data */
156 reset_common_data();
157 wborig = wb;
158 rootkey->key_size = 1;
159 rootkey->key_offset = sizeof(gbb_data) + 1;
160 gbb->rootkey_size = rootkey->key_offset + rootkey->key_size;
161 TEST_EQ(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
162 VB2_ERROR_EX_READ_RESOURCE_SIZE,
163 "rootkey size too large");
164 TEST_TRUE(wb.buf == wborig.buf,
165 " workbuf restored on error");
166
167 /* packed_key.size > workbuf.size */
168 reset_common_data();
169 wborig = wb;
170 rootkey->key_size = wb.size + 1;
171 gbb->rootkey_size = rootkey->key_offset + rootkey->key_size + 1;
172 TEST_EQ(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
173 VB2_ERROR_GBB_WORKBUF,
174 "workbuf size too small for vb2_packed_key contents");
175 TEST_TRUE(wb.buf == wborig.buf,
176 " workbuf restored on error");
177
178 /* gbb.size < sizeof(vb2_packed_key) + packed_key.size */
179 reset_common_data();
180 wborig = wb;
181 rootkey->key_size = 2;
182 gbb->rootkey_size = rootkey->key_offset + rootkey->key_size - 1;
183 TEST_EQ(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
184 VB2_ERROR_INSIDE_DATA_OUTSIDE,
185 "rootkey size exceeds gbb.rootkey size");
186 TEST_TRUE(wb.buf == wborig.buf,
187 " workbuf restored on error");
188
189 /* gbb.size == sizeof(vb2_packed_key) + packed_key.size */
190 reset_common_data();
191 wborig = wb;
192 rootkey->key_size = sizeof(key_data);
193 memcpy((void *)rootkey + rootkey->key_offset,
194 key_data, sizeof(key_data));
195 gbb->rootkey_size = rootkey->key_offset + rootkey->key_size;
196 TEST_SUCC(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
197 "succeeds when gbb.rootkey and rootkey sizes agree");
198 TEST_TRUE(wb.size < wborig.size,
199 " workbuf shrank on success");
200 TEST_EQ(memcmp(rootkey, keyp, rootkey->key_offset + rootkey->key_size),
201 0, " copied key data successfully");
202 TEST_EQ(size, rootkey->key_offset + rootkey->key_size,
203 " correct size returned");
204
205 /* gbb.size > sizeof(vb2_packed_key) + packed_key.size
206 packed_key.offset = +0 */
207 reset_common_data();
208 wborig = wb;
209 rootkey->key_size = 1;
210 gbb->rootkey_size = rootkey->key_offset + rootkey->key_size + 1;
211 TEST_SUCC(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
212 "succeeds when gbb.rootkey is padded after key");
213 TEST_TRUE(wb.size < wborig.size,
214 " workbuf shrank on success");
215 TEST_EQ(size, rootkey->key_offset + rootkey->key_size,
216 " correct size returned");
217
218 /* gbb.size > sizeof(vb2_packed_key) + packed_key.size
219 packed_key.offset = +1 */
220 reset_common_data();
221 wborig = wb;
222 rootkey->key_offset = sizeof(*rootkey) + 1;
223 rootkey->key_size = 1;
224 gbb->rootkey_size = rootkey->key_offset + rootkey->key_size;
225 TEST_SUCC(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
226 "succeeds when gbb.rootkey is padded before key");
227 TEST_TRUE(wb.size < wborig.size,
228 " workbuf shrank on success");
229 TEST_EQ(size, rootkey->key_offset + rootkey->key_size,
230 " correct size returned");
231
232 /* packed_key.size = 0, packed_key.offset = +1 */
233 reset_common_data();
234 wborig = wb;
235 rootkey->key_offset = sizeof(*rootkey) + 1;
236 rootkey->key_size = 0;
237 gbb->rootkey_size = rootkey->key_offset + rootkey->key_size + 1;
238 TEST_SUCC(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
239 "succeeds when gbb.rootkey is padded; empty test key");
240 TEST_TRUE(wb.size < wborig.size,
241 " workbuf shrank on success");
242 TEST_EQ(size, rootkey->key_offset + rootkey->key_size,
243 " correct size returned");
244
245 /* packed_key.size = 0, packed_key.offset = -1 */
246 reset_common_data();
247 wborig = wb;
248 rootkey->key_offset = sizeof(*rootkey) - 1;
249 rootkey->key_size = 0;
250 gbb->rootkey_size = sizeof(*rootkey) + rootkey->key_size + 1;
251 TEST_SUCC(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
252 "succeeds when gbb.rootkey is padded; empty test key");
253 TEST_TRUE(wb.size < wborig.size,
254 " workbuf shrank on success");
255 TEST_EQ(size, sizeof(*rootkey), " correct size returned");
256 }
257
hwid_tests(void)258 static void hwid_tests(void)
259 {
260 char hwid[VB2_GBB_HWID_MAX_SIZE];
261 uint32_t size;
262
263 /* GBB HWID size = 0 */
264 {
265 reset_common_data();
266 gbb->hwid_size = 0;
267 size = VB2_GBB_HWID_MAX_SIZE;
268 TEST_EQ(vb2api_gbb_read_hwid(ctx, hwid, &size),
269 VB2_ERROR_GBB_INVALID,
270 "GBB HWID size invalid (HWID missing)");
271 }
272
273 /* GBB HWID offset > GBB size */
274 {
275 reset_common_data();
276 gbb->hwid_offset = sizeof(gbb_data) + 1;
277 size = VB2_GBB_HWID_MAX_SIZE;
278 TEST_EQ(vb2api_gbb_read_hwid(ctx, hwid, &size),
279 VB2_ERROR_EX_READ_RESOURCE_SIZE,
280 "GBB HWID offset invalid");
281 }
282
283 /* buffer size < HWID size */
284 {
285 const char hwid_src[] = "Test HWID";
286 reset_common_data();
287 set_gbb_hwid(hwid_src, sizeof(hwid_src));
288 size = sizeof(hwid_src) - 1;
289 TEST_EQ(vb2api_gbb_read_hwid(ctx, hwid, &size),
290 VB2_ERROR_INVALID_PARAMETER,
291 "HWID too large for buffer");
292 }
293
294 /* GBB HWID size < HWID size */
295 {
296 const char hwid_src[] = "Test HWID";
297 reset_common_data();
298 set_gbb_hwid(hwid_src, sizeof(hwid_src) - 1);
299 size = sizeof(hwid_src);
300 TEST_EQ(vb2api_gbb_read_hwid(ctx, hwid, &size),
301 VB2_ERROR_INVALID_PARAMETER,
302 "HWID larger than GBB HWID size");
303 }
304
305 /* buffer size == HWID size */
306 {
307 const char hwid_src[] = "Test HWID";
308 reset_common_data();
309 set_gbb_hwid(hwid_src, sizeof(hwid_src));
310 size = sizeof(hwid_src);
311 TEST_SUCC(vb2api_gbb_read_hwid(ctx, hwid, &size),
312 "read normal HWID");
313 TEST_EQ(strcmp(hwid, "Test HWID"), 0, " HWID correct");
314 TEST_EQ(strlen(hwid) + 1, size, " HWID size consistent");
315 TEST_EQ(strlen(hwid), strlen("Test HWID"),
316 " HWID size correct");
317 }
318
319 /* buffer size > HWID size */
320 {
321 const char hwid_src[] = "Test HWID";
322 reset_common_data();
323 set_gbb_hwid(hwid_src, sizeof(hwid_src));
324 size = sizeof(hwid_src) + 1;
325 TEST_SUCC(vb2api_gbb_read_hwid(ctx, hwid, &size),
326 "read normal HWID");
327 TEST_EQ(strcmp(hwid, "Test HWID"), 0, " HWID correct");
328 TEST_EQ(strlen(hwid) + 1, size, " HWID size consistent");
329 TEST_EQ(strlen(hwid), strlen("Test HWID"),
330 " HWID size correct");
331 }
332
333 /* HWID with garbage */
334 {
335 const char hwid_src[] = "Test HWID\0garbagegarbage";
336 reset_common_data();
337 set_gbb_hwid(hwid_src, sizeof(hwid_src));
338 size = VB2_GBB_HWID_MAX_SIZE;
339 TEST_SUCC(vb2api_gbb_read_hwid(ctx, hwid, &size),
340 "read HWID with garbage");
341 TEST_EQ(strcmp(hwid, "Test HWID"), 0, " HWID correct");
342 TEST_EQ(strlen(hwid) + 1, size, " HWID size consistent");
343 TEST_EQ(strlen(hwid), strlen("Test HWID"),
344 " HWID size correct");
345 }
346 }
347
main(int argc,char * argv[])348 int main(int argc, char* argv[])
349 {
350 flag_tests();
351 key_tests();
352 hwid_tests();
353
354 return gTestSuccess ? 0 : 255;
355 }
356