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