xref: /openbmc/u-boot/cmd/avb.c (revision 6d89902d7a97bc988595fe471783715245096a9e)
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 <image.h>
11  #include <malloc.h>
12  #include <mmc.h>
13  
14  #define AVB_BOOTARGS	"avb_bootargs"
15  static struct AvbOps *avb_ops;
16  
17  static const char * const requested_partitions[] = {"boot",
18  					     "system",
19  					     "vendor",
20  					     NULL};
21  
do_avb_init(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])22  int do_avb_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
23  {
24  	unsigned long mmc_dev;
25  
26  	if (argc != 2)
27  		return CMD_RET_USAGE;
28  
29  	mmc_dev = simple_strtoul(argv[1], NULL, 16);
30  
31  	if (avb_ops)
32  		avb_ops_free(avb_ops);
33  
34  	avb_ops = avb_ops_alloc(mmc_dev);
35  	if (avb_ops)
36  		return CMD_RET_SUCCESS;
37  
38  	printf("Failed to initialize avb2\n");
39  
40  	return CMD_RET_FAILURE;
41  }
42  
do_avb_read_part(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])43  int do_avb_read_part(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
44  {
45  	const char *part;
46  	s64 offset;
47  	size_t bytes, bytes_read = 0;
48  	void *buffer;
49  
50  	if (!avb_ops) {
51  		printf("AVB 2.0 is not initialized, please run 'avb init'\n");
52  		return CMD_RET_USAGE;
53  	}
54  
55  	if (argc != 5)
56  		return CMD_RET_USAGE;
57  
58  	part = argv[1];
59  	offset = simple_strtoul(argv[2], NULL, 16);
60  	bytes = simple_strtoul(argv[3], NULL, 16);
61  	buffer = (void *)simple_strtoul(argv[4], NULL, 16);
62  
63  	if (avb_ops->read_from_partition(avb_ops, part, offset, bytes,
64  					 buffer, &bytes_read) ==
65  					 AVB_IO_RESULT_OK) {
66  		printf("Read %zu bytes\n", bytes_read);
67  		return CMD_RET_SUCCESS;
68  	}
69  
70  	printf("Failed to read from partition\n");
71  
72  	return CMD_RET_FAILURE;
73  }
74  
do_avb_read_part_hex(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])75  int do_avb_read_part_hex(cmd_tbl_t *cmdtp, int flag, int argc,
76  			 char *const argv[])
77  {
78  	const char *part;
79  	s64 offset;
80  	size_t bytes, bytes_read = 0;
81  	char *buffer;
82  
83  	if (!avb_ops) {
84  		printf("AVB 2.0 is not initialized, please run 'avb init'\n");
85  		return CMD_RET_USAGE;
86  	}
87  
88  	if (argc != 4)
89  		return CMD_RET_USAGE;
90  
91  	part = argv[1];
92  	offset = simple_strtoul(argv[2], NULL, 16);
93  	bytes = simple_strtoul(argv[3], NULL, 16);
94  
95  	buffer = malloc(bytes);
96  	if (!buffer) {
97  		printf("Failed to tlb_allocate buffer for data\n");
98  		return CMD_RET_FAILURE;
99  	}
100  	memset(buffer, 0, bytes);
101  
102  	if (avb_ops->read_from_partition(avb_ops, part, offset, bytes, buffer,
103  					 &bytes_read) == AVB_IO_RESULT_OK) {
104  		printf("Requested %zu, read %zu bytes\n", bytes, bytes_read);
105  		printf("Data: ");
106  		for (int i = 0; i < bytes_read; i++)
107  			printf("%02X", buffer[i]);
108  
109  		printf("\n");
110  
111  		free(buffer);
112  		return CMD_RET_SUCCESS;
113  	}
114  
115  	printf("Failed to read from partition\n");
116  
117  	free(buffer);
118  	return CMD_RET_FAILURE;
119  }
120  
do_avb_write_part(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])121  int do_avb_write_part(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
122  {
123  	const char *part;
124  	s64 offset;
125  	size_t bytes;
126  	void *buffer;
127  
128  	if (!avb_ops) {
129  		printf("AVB 2.0 is not initialized, run 'avb init' first\n");
130  		return CMD_RET_FAILURE;
131  	}
132  
133  	if (argc != 5)
134  		return CMD_RET_USAGE;
135  
136  	part = argv[1];
137  	offset = simple_strtoul(argv[2], NULL, 16);
138  	bytes = simple_strtoul(argv[3], NULL, 16);
139  	buffer = (void *)simple_strtoul(argv[4], NULL, 16);
140  
141  	if (avb_ops->write_to_partition(avb_ops, part, offset, bytes, buffer) ==
142  	    AVB_IO_RESULT_OK) {
143  		printf("Wrote %zu bytes\n", bytes);
144  		return CMD_RET_SUCCESS;
145  	}
146  
147  	printf("Failed to write in partition\n");
148  
149  	return CMD_RET_FAILURE;
150  }
151  
do_avb_read_rb(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])152  int do_avb_read_rb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
153  {
154  	size_t index;
155  	u64 rb_idx;
156  
157  	if (!avb_ops) {
158  		printf("AVB 2.0 is not initialized, run 'avb init' first\n");
159  		return CMD_RET_FAILURE;
160  	}
161  
162  	if (argc != 2)
163  		return CMD_RET_USAGE;
164  
165  	index = (size_t)simple_strtoul(argv[1], NULL, 16);
166  
167  	if (avb_ops->read_rollback_index(avb_ops, index, &rb_idx) ==
168  	    AVB_IO_RESULT_OK) {
169  		printf("Rollback index: %llx\n", rb_idx);
170  		return CMD_RET_SUCCESS;
171  	}
172  
173  	printf("Failed to read rollback index\n");
174  
175  	return CMD_RET_FAILURE;
176  }
177  
do_avb_write_rb(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])178  int do_avb_write_rb(cmd_tbl_t *cmdtp, int flag, int argc, 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(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])203  int do_avb_get_uuid(cmd_tbl_t *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(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])231  int do_avb_verify_part(cmd_tbl_t *cmdtp, int flag,
232  		       int argc, char *const argv[])
233  {
234  	AvbSlotVerifyResult slot_result;
235  	AvbSlotVerifyData *out_data;
236  	char *cmdline;
237  	char *extra_args;
238  
239  	bool unlocked = false;
240  	int res = CMD_RET_FAILURE;
241  
242  	if (!avb_ops) {
243  		printf("AVB 2.0 is not initialized, run 'avb init' first\n");
244  		return CMD_RET_FAILURE;
245  	}
246  
247  	if (argc != 1)
248  		return CMD_RET_USAGE;
249  
250  	printf("## Android Verified Boot 2.0 version %s\n",
251  	       avb_version_string());
252  
253  	if (avb_ops->read_is_device_unlocked(avb_ops, &unlocked) !=
254  	    AVB_IO_RESULT_OK) {
255  		printf("Can't determine device lock state.\n");
256  		return CMD_RET_FAILURE;
257  	}
258  
259  	slot_result =
260  		avb_slot_verify(avb_ops,
261  				requested_partitions,
262  				"",
263  				unlocked,
264  				AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
265  				&out_data);
266  
267  	switch (slot_result) {
268  	case AVB_SLOT_VERIFY_RESULT_OK:
269  		/* Until we don't have support of changing unlock states, we
270  		 * assume that we are by default in locked state.
271  		 * So in this case we can boot only when verification is
272  		 * successful; we also supply in cmdline GREEN boot state
273  		 */
274  		printf("Verification passed successfully\n");
275  
276  		/* export additional bootargs to AVB_BOOTARGS env var */
277  
278  		extra_args = avb_set_state(avb_ops, AVB_GREEN);
279  		if (extra_args)
280  			cmdline = append_cmd_line(out_data->cmdline,
281  						  extra_args);
282  		else
283  			cmdline = out_data->cmdline;
284  
285  		env_set(AVB_BOOTARGS, cmdline);
286  
287  		res = CMD_RET_SUCCESS;
288  		break;
289  	case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
290  		printf("Verification failed\n");
291  		break;
292  	case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
293  		printf("I/O error occurred during verification\n");
294  		break;
295  	case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
296  		printf("OOM error occurred during verification\n");
297  		break;
298  	case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
299  		printf("Corrupted dm-verity metadata detected\n");
300  		break;
301  	case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
302  		printf("Unsupported version avbtool was used\n");
303  		break;
304  	case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
305  		printf("Checking rollback index failed\n");
306  		break;
307  	case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
308  		printf("Public key was rejected\n");
309  		break;
310  	default:
311  		printf("Unknown error occurred\n");
312  	}
313  
314  	return res;
315  }
316  
do_avb_is_unlocked(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])317  int do_avb_is_unlocked(cmd_tbl_t *cmdtp, int flag,
318  		       int argc, char * const argv[])
319  {
320  	bool unlock;
321  
322  	if (!avb_ops) {
323  		printf("AVB not initialized, run 'avb init' first\n");
324  		return CMD_RET_FAILURE;
325  	}
326  
327  	if (argc != 1) {
328  		printf("--%s(-1)\n", __func__);
329  		return CMD_RET_USAGE;
330  	}
331  
332  	if (avb_ops->read_is_device_unlocked(avb_ops, &unlock) ==
333  	    AVB_IO_RESULT_OK) {
334  		printf("Unlocked = %d\n", unlock);
335  		return CMD_RET_SUCCESS;
336  	}
337  
338  	printf("Can't determine device lock state.\n");
339  
340  	return CMD_RET_FAILURE;
341  }
342  
343  static cmd_tbl_t cmd_avb[] = {
344  	U_BOOT_CMD_MKENT(init, 2, 0, do_avb_init, "", ""),
345  	U_BOOT_CMD_MKENT(read_rb, 2, 0, do_avb_read_rb, "", ""),
346  	U_BOOT_CMD_MKENT(write_rb, 3, 0, do_avb_write_rb, "", ""),
347  	U_BOOT_CMD_MKENT(is_unlocked, 1, 0, do_avb_is_unlocked, "", ""),
348  	U_BOOT_CMD_MKENT(get_uuid, 2, 0, do_avb_get_uuid, "", ""),
349  	U_BOOT_CMD_MKENT(read_part, 5, 0, do_avb_read_part, "", ""),
350  	U_BOOT_CMD_MKENT(read_part_hex, 4, 0, do_avb_read_part_hex, "", ""),
351  	U_BOOT_CMD_MKENT(write_part, 5, 0, do_avb_write_part, "", ""),
352  	U_BOOT_CMD_MKENT(verify, 1, 0, do_avb_verify_part, "", ""),
353  };
354  
do_avb(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])355  static int do_avb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
356  {
357  	cmd_tbl_t *cp;
358  
359  	cp = find_cmd_tbl(argv[1], cmd_avb, ARRAY_SIZE(cmd_avb));
360  
361  	argc--;
362  	argv++;
363  
364  	if (!cp || argc > cp->maxargs)
365  		return CMD_RET_USAGE;
366  
367  	if (flag == CMD_FLAG_REPEAT)
368  		return CMD_RET_FAILURE;
369  
370  	return cp->cmd(cmdtp, flag, argc, argv);
371  }
372  
373  U_BOOT_CMD(
374  	avb, 29, 0, do_avb,
375  	"Provides commands for testing Android Verified Boot 2.0 functionality",
376  	"init <dev> - initialize avb2 for <dev>\n"
377  	"avb read_rb <num> - read rollback index at location <num>\n"
378  	"avb write_rb <num> <rb> - write rollback index <rb> to <num>\n"
379  	"avb is_unlocked - returns unlock status of the device\n"
380  	"avb get_uuid <partname> - read and print uuid of partition <part>\n"
381  	"avb read_part <partname> <offset> <num> <addr> - read <num> bytes from\n"
382  	"    partition <partname> to buffer <addr>\n"
383  	"avb read_part_hex <partname> <offset> <num> - read <num> bytes from\n"
384  	"    partition <partname> and print to stdout\n"
385  	"avb write_part <partname> <offset> <num> <addr> - write <num> bytes to\n"
386  	"    <partname> by <offset> using data from <addr>\n"
387  	"avb verify - run verification process using hash data\n"
388  	"    from vbmeta structure\n"
389  	);
390