1 
2 /*
3  * (C) Copyright 2018, Linaro Limited
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include <avb_verify.h>
9 #include <command.h>
10 #include <env.h>
11 #include <image.h>
12 #include <malloc.h>
13 #include <mmc.h>
14 
15 #define AVB_BOOTARGS	"avb_bootargs"
16 static struct AvbOps *avb_ops;
17 
do_avb_init(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])18 int do_avb_init(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
19 {
20 	unsigned long mmc_dev;
21 
22 	if (argc != 2)
23 		return CMD_RET_USAGE;
24 
25 	mmc_dev = simple_strtoul(argv[1], NULL, 16);
26 
27 	if (avb_ops)
28 		avb_ops_free(avb_ops);
29 
30 	avb_ops = avb_ops_alloc(mmc_dev);
31 	if (avb_ops)
32 		return CMD_RET_SUCCESS;
33 
34 	printf("Failed to initialize avb2\n");
35 
36 	return CMD_RET_FAILURE;
37 }
38 
do_avb_read_part(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])39 int do_avb_read_part(struct cmd_tbl *cmdtp, int flag, int argc,
40 		     char *const argv[])
41 {
42 	const char *part;
43 	s64 offset;
44 	size_t bytes, bytes_read = 0;
45 	void *buffer;
46 
47 	if (!avb_ops) {
48 		printf("AVB 2.0 is not initialized, please run 'avb init'\n");
49 		return CMD_RET_USAGE;
50 	}
51 
52 	if (argc != 5)
53 		return CMD_RET_USAGE;
54 
55 	part = argv[1];
56 	offset = simple_strtoul(argv[2], NULL, 16);
57 	bytes = simple_strtoul(argv[3], NULL, 16);
58 	buffer = (void *)simple_strtoul(argv[4], NULL, 16);
59 
60 	if (avb_ops->read_from_partition(avb_ops, part, offset, bytes,
61 					 buffer, &bytes_read) ==
62 					 AVB_IO_RESULT_OK) {
63 		printf("Read %zu bytes\n", bytes_read);
64 		return CMD_RET_SUCCESS;
65 	}
66 
67 	printf("Failed to read from partition\n");
68 
69 	return CMD_RET_FAILURE;
70 }
71 
do_avb_read_part_hex(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])72 int do_avb_read_part_hex(struct cmd_tbl *cmdtp, int flag, int argc,
73 			 char *const argv[])
74 {
75 	const char *part;
76 	s64 offset;
77 	size_t bytes, bytes_read = 0;
78 	char *buffer;
79 
80 	if (!avb_ops) {
81 		printf("AVB 2.0 is not initialized, please run 'avb init'\n");
82 		return CMD_RET_USAGE;
83 	}
84 
85 	if (argc != 4)
86 		return CMD_RET_USAGE;
87 
88 	part = argv[1];
89 	offset = simple_strtoul(argv[2], NULL, 16);
90 	bytes = simple_strtoul(argv[3], NULL, 16);
91 
92 	buffer = malloc(bytes);
93 	if (!buffer) {
94 		printf("Failed to tlb_allocate buffer for data\n");
95 		return CMD_RET_FAILURE;
96 	}
97 	memset(buffer, 0, bytes);
98 
99 	if (avb_ops->read_from_partition(avb_ops, part, offset, bytes, buffer,
100 					 &bytes_read) == AVB_IO_RESULT_OK) {
101 		printf("Requested %zu, read %zu bytes\n", bytes, bytes_read);
102 		printf("Data: ");
103 		for (int i = 0; i < bytes_read; i++)
104 			printf("%02X", buffer[i]);
105 
106 		printf("\n");
107 
108 		free(buffer);
109 		return CMD_RET_SUCCESS;
110 	}
111 
112 	printf("Failed to read from partition\n");
113 
114 	free(buffer);
115 	return CMD_RET_FAILURE;
116 }
117 
do_avb_write_part(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])118 int do_avb_write_part(struct cmd_tbl *cmdtp, int flag, int argc,
119 		      char *const argv[])
120 {
121 	const char *part;
122 	s64 offset;
123 	size_t bytes;
124 	void *buffer;
125 
126 	if (!avb_ops) {
127 		printf("AVB 2.0 is not initialized, run 'avb init' first\n");
128 		return CMD_RET_FAILURE;
129 	}
130 
131 	if (argc != 5)
132 		return CMD_RET_USAGE;
133 
134 	part = argv[1];
135 	offset = simple_strtoul(argv[2], NULL, 16);
136 	bytes = simple_strtoul(argv[3], NULL, 16);
137 	buffer = (void *)simple_strtoul(argv[4], NULL, 16);
138 
139 	if (avb_ops->write_to_partition(avb_ops, part, offset, bytes, buffer) ==
140 	    AVB_IO_RESULT_OK) {
141 		printf("Wrote %zu bytes\n", bytes);
142 		return CMD_RET_SUCCESS;
143 	}
144 
145 	printf("Failed to write in partition\n");
146 
147 	return CMD_RET_FAILURE;
148 }
149 
do_avb_read_rb(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])150 int do_avb_read_rb(struct cmd_tbl *cmdtp, int flag, int argc,
151 		   char *const argv[])
152 {
153 	size_t index;
154 	u64 rb_idx;
155 
156 	if (!avb_ops) {
157 		printf("AVB 2.0 is not initialized, run 'avb init' first\n");
158 		return CMD_RET_FAILURE;
159 	}
160 
161 	if (argc != 2)
162 		return CMD_RET_USAGE;
163 
164 	index = (size_t)simple_strtoul(argv[1], NULL, 16);
165 
166 	if (avb_ops->read_rollback_index(avb_ops, index, &rb_idx) ==
167 	    AVB_IO_RESULT_OK) {
168 		printf("Rollback index: %llx\n", rb_idx);
169 		return CMD_RET_SUCCESS;
170 	}
171 
172 	printf("Failed to read rollback index\n");
173 
174 	return CMD_RET_FAILURE;
175 }
176 
do_avb_write_rb(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])177 int do_avb_write_rb(struct cmd_tbl *cmdtp, int flag, int argc,
178 		    char *const argv[])
179 {
180 	size_t index;
181 	u64 rb_idx;
182 
183 	if (!avb_ops) {
184 		printf("AVB 2.0 is not initialized, run 'avb init' first\n");
185 		return CMD_RET_FAILURE;
186 	}
187 
188 	if (argc != 3)
189 		return CMD_RET_USAGE;
190 
191 	index = (size_t)simple_strtoul(argv[1], NULL, 16);
192 	rb_idx = simple_strtoul(argv[2], NULL, 16);
193 
194 	if (avb_ops->write_rollback_index(avb_ops, index, rb_idx) ==
195 	    AVB_IO_RESULT_OK)
196 		return CMD_RET_SUCCESS;
197 
198 	printf("Failed to write rollback index\n");
199 
200 	return CMD_RET_FAILURE;
201 }
202 
do_avb_get_uuid(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])203 int do_avb_get_uuid(struct cmd_tbl *cmdtp, int flag,
204 		    int argc, char *const argv[])
205 {
206 	const char *part;
207 	char buffer[UUID_STR_LEN + 1];
208 
209 	if (!avb_ops) {
210 		printf("AVB 2.0 is not initialized, run 'avb init' first\n");
211 		return CMD_RET_FAILURE;
212 	}
213 
214 	if (argc != 2)
215 		return CMD_RET_USAGE;
216 
217 	part = argv[1];
218 
219 	if (avb_ops->get_unique_guid_for_partition(avb_ops, part, buffer,
220 						   UUID_STR_LEN + 1) ==
221 						   AVB_IO_RESULT_OK) {
222 		printf("'%s' UUID: %s\n", part, buffer);
223 		return CMD_RET_SUCCESS;
224 	}
225 
226 	printf("Failed to read UUID\n");
227 
228 	return CMD_RET_FAILURE;
229 }
230 
do_avb_verify_part(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])231 int do_avb_verify_part(struct cmd_tbl *cmdtp, int flag,
232 		       int argc, char *const argv[])
233 {
234 	const char * const requested_partitions[] = {"boot", NULL};
235 	AvbSlotVerifyResult slot_result;
236 	AvbSlotVerifyData *out_data;
237 	char *cmdline;
238 	char *extra_args;
239 	char *slot_suffix = "";
240 
241 	bool unlocked = false;
242 	int res = CMD_RET_FAILURE;
243 
244 	if (!avb_ops) {
245 		printf("AVB 2.0 is not initialized, run 'avb init' first\n");
246 		return CMD_RET_FAILURE;
247 	}
248 
249 	if (argc < 1 || argc > 2)
250 		return CMD_RET_USAGE;
251 
252 	if (argc == 2)
253 		slot_suffix = argv[1];
254 
255 	printf("## Android Verified Boot 2.0 version %s\n",
256 	       avb_version_string());
257 
258 	if (avb_ops->read_is_device_unlocked(avb_ops, &unlocked) !=
259 	    AVB_IO_RESULT_OK) {
260 		printf("Can't determine device lock state.\n");
261 		return CMD_RET_FAILURE;
262 	}
263 
264 	slot_result =
265 		avb_slot_verify(avb_ops,
266 				requested_partitions,
267 				slot_suffix,
268 				unlocked,
269 				AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
270 				&out_data);
271 
272 	switch (slot_result) {
273 	case AVB_SLOT_VERIFY_RESULT_OK:
274 		/* Until we don't have support of changing unlock states, we
275 		 * assume that we are by default in locked state.
276 		 * So in this case we can boot only when verification is
277 		 * successful; we also supply in cmdline GREEN boot state
278 		 */
279 		printf("Verification passed successfully\n");
280 
281 		/* export additional bootargs to AVB_BOOTARGS env var */
282 
283 		extra_args = avb_set_state(avb_ops, AVB_GREEN);
284 		if (extra_args)
285 			cmdline = append_cmd_line(out_data->cmdline,
286 						  extra_args);
287 		else
288 			cmdline = out_data->cmdline;
289 
290 		env_set(AVB_BOOTARGS, cmdline);
291 
292 		res = CMD_RET_SUCCESS;
293 		break;
294 	case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
295 		printf("Verification failed\n");
296 		break;
297 	case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
298 		printf("I/O error occurred during verification\n");
299 		break;
300 	case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
301 		printf("OOM error occurred during verification\n");
302 		break;
303 	case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
304 		printf("Corrupted dm-verity metadata detected\n");
305 		break;
306 	case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
307 		printf("Unsupported version avbtool was used\n");
308 		break;
309 	case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
310 		printf("Checking rollback index failed\n");
311 		break;
312 	case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
313 		printf("Public key was rejected\n");
314 		break;
315 	default:
316 		printf("Unknown error occurred\n");
317 	}
318 
319 	if (out_data)
320 		avb_slot_verify_data_free(out_data);
321 
322 	return res;
323 }
324 
do_avb_is_unlocked(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])325 int do_avb_is_unlocked(struct cmd_tbl *cmdtp, int flag,
326 		       int argc, char *const argv[])
327 {
328 	bool unlock;
329 
330 	if (!avb_ops) {
331 		printf("AVB not initialized, run 'avb init' first\n");
332 		return CMD_RET_FAILURE;
333 	}
334 
335 	if (argc != 1) {
336 		printf("--%s(-1)\n", __func__);
337 		return CMD_RET_USAGE;
338 	}
339 
340 	if (avb_ops->read_is_device_unlocked(avb_ops, &unlock) ==
341 	    AVB_IO_RESULT_OK) {
342 		printf("Unlocked = %d\n", unlock);
343 		return CMD_RET_SUCCESS;
344 	}
345 
346 	printf("Can't determine device lock state.\n");
347 
348 	return CMD_RET_FAILURE;
349 }
350 
do_avb_read_pvalue(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])351 int do_avb_read_pvalue(struct cmd_tbl *cmdtp, int flag, int argc,
352 		       char *const argv[])
353 {
354 	const char *name;
355 	size_t bytes;
356 	size_t bytes_read;
357 	void *buffer;
358 	char *endp;
359 
360 	if (!avb_ops) {
361 		printf("AVB 2.0 is not initialized, run 'avb init' first\n");
362 		return CMD_RET_FAILURE;
363 	}
364 
365 	if (argc != 3)
366 		return CMD_RET_USAGE;
367 
368 	name = argv[1];
369 	bytes = simple_strtoul(argv[2], &endp, 10);
370 	if (*endp && *endp != '\n')
371 		return CMD_RET_USAGE;
372 
373 	buffer = malloc(bytes);
374 	if (!buffer)
375 		return CMD_RET_FAILURE;
376 
377 	if (avb_ops->read_persistent_value(avb_ops, name, bytes, buffer,
378 					   &bytes_read) == AVB_IO_RESULT_OK) {
379 		printf("Read %zu bytes, value = %s\n", bytes_read,
380 		       (char *)buffer);
381 		free(buffer);
382 		return CMD_RET_SUCCESS;
383 	}
384 
385 	printf("Failed to read persistent value\n");
386 
387 	free(buffer);
388 
389 	return CMD_RET_FAILURE;
390 }
391 
do_avb_write_pvalue(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])392 int do_avb_write_pvalue(struct cmd_tbl *cmdtp, int flag, int argc,
393 			char *const argv[])
394 {
395 	const char *name;
396 	const char *value;
397 
398 	if (!avb_ops) {
399 		printf("AVB 2.0 is not initialized, run 'avb init' first\n");
400 		return CMD_RET_FAILURE;
401 	}
402 
403 	if (argc != 3)
404 		return CMD_RET_USAGE;
405 
406 	name = argv[1];
407 	value = argv[2];
408 
409 	if (avb_ops->write_persistent_value(avb_ops, name, strlen(value) + 1,
410 					    (const uint8_t *)value) ==
411 	    AVB_IO_RESULT_OK) {
412 		printf("Wrote %zu bytes\n", strlen(value) + 1);
413 		return CMD_RET_SUCCESS;
414 	}
415 
416 	printf("Failed to write persistent value\n");
417 
418 	return CMD_RET_FAILURE;
419 }
420 
421 static struct cmd_tbl cmd_avb[] = {
422 	U_BOOT_CMD_MKENT(init, 2, 0, do_avb_init, "", ""),
423 	U_BOOT_CMD_MKENT(read_rb, 2, 0, do_avb_read_rb, "", ""),
424 	U_BOOT_CMD_MKENT(write_rb, 3, 0, do_avb_write_rb, "", ""),
425 	U_BOOT_CMD_MKENT(is_unlocked, 1, 0, do_avb_is_unlocked, "", ""),
426 	U_BOOT_CMD_MKENT(get_uuid, 2, 0, do_avb_get_uuid, "", ""),
427 	U_BOOT_CMD_MKENT(read_part, 5, 0, do_avb_read_part, "", ""),
428 	U_BOOT_CMD_MKENT(read_part_hex, 4, 0, do_avb_read_part_hex, "", ""),
429 	U_BOOT_CMD_MKENT(write_part, 5, 0, do_avb_write_part, "", ""),
430 	U_BOOT_CMD_MKENT(verify, 2, 0, do_avb_verify_part, "", ""),
431 #ifdef CONFIG_OPTEE_TA_AVB
432 	U_BOOT_CMD_MKENT(read_pvalue, 3, 0, do_avb_read_pvalue, "", ""),
433 	U_BOOT_CMD_MKENT(write_pvalue, 3, 0, do_avb_write_pvalue, "", ""),
434 #endif
435 };
436 
do_avb(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])437 static int do_avb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
438 {
439 	struct cmd_tbl *cp;
440 
441 	cp = find_cmd_tbl(argv[1], cmd_avb, ARRAY_SIZE(cmd_avb));
442 
443 	argc--;
444 	argv++;
445 
446 	if (!cp || argc > cp->maxargs)
447 		return CMD_RET_USAGE;
448 
449 	if (flag == CMD_FLAG_REPEAT)
450 		return CMD_RET_FAILURE;
451 
452 	return cp->cmd(cmdtp, flag, argc, argv);
453 }
454 
455 U_BOOT_CMD(
456 	avb, 29, 0, do_avb,
457 	"Provides commands for testing Android Verified Boot 2.0 functionality",
458 	"init <dev> - initialize avb2 for <dev>\n"
459 	"avb read_rb <num> - read rollback index at location <num>\n"
460 	"avb write_rb <num> <rb> - write rollback index <rb> to <num>\n"
461 	"avb is_unlocked - returns unlock status of the device\n"
462 	"avb get_uuid <partname> - read and print uuid of partition <part>\n"
463 	"avb read_part <partname> <offset> <num> <addr> - read <num> bytes from\n"
464 	"    partition <partname> to buffer <addr>\n"
465 	"avb read_part_hex <partname> <offset> <num> - read <num> bytes from\n"
466 	"    partition <partname> and print to stdout\n"
467 	"avb write_part <partname> <offset> <num> <addr> - write <num> bytes to\n"
468 	"    <partname> by <offset> using data from <addr>\n"
469 #ifdef CONFIG_OPTEE_TA_AVB
470 	"avb read_pvalue <name> <bytes> - read a persistent value <name>\n"
471 	"avb write_pvalue <name> <value> - write a persistent value <name>\n"
472 #endif
473 	"avb verify [slot_suffix] - run verification process using hash data\n"
474 	"    from vbmeta structure\n"
475 	"    [slot_suffix] - _a, _b, etc (if vbmeta partition is slotted)\n"
476 	);
477