1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2018, Linaro Limited
4 */
5
6#include <avb_verify.h>
7#include <blk.h>
8#include <cpu_func.h>
9#include <image.h>
10#include <malloc.h>
11#include <part.h>
12#include <tee.h>
13#include <tee/optee_ta_avb.h>
14
15static const unsigned char avb_root_pub[1032] = {
16	0x0, 0x0, 0x10, 0x0, 0x55, 0xd9, 0x4, 0xad, 0xd8, 0x4,
17	0xaf, 0xe3, 0xd3, 0x84, 0x6c, 0x7e, 0xd, 0x89, 0x3d, 0xc2,
18	0x8c, 0xd3, 0x12, 0x55, 0xe9, 0x62, 0xc9, 0xf1, 0xf, 0x5e,
19	0xcc, 0x16, 0x72, 0xab, 0x44, 0x7c, 0x2c, 0x65, 0x4a, 0x94,
20	0xb5, 0x16, 0x2b, 0x0, 0xbb, 0x6, 0xef, 0x13, 0x7, 0x53,
21	0x4c, 0xf9, 0x64, 0xb9, 0x28, 0x7a, 0x1b, 0x84, 0x98, 0x88,
22	0xd8, 0x67, 0xa4, 0x23, 0xf9, 0xa7, 0x4b, 0xdc, 0x4a, 0xf,
23	0xf7, 0x3a, 0x18, 0xae, 0x54, 0xa8, 0x15, 0xfe, 0xb0, 0xad,
24	0xac, 0x35, 0xda, 0x3b, 0xad, 0x27, 0xbc, 0xaf, 0xe8, 0xd3,
25	0x2f, 0x37, 0x34, 0xd6, 0x51, 0x2b, 0x6c, 0x5a, 0x27, 0xd7,
26	0x96, 0x6, 0xaf, 0x6b, 0xb8, 0x80, 0xca, 0xfa, 0x30, 0xb4,
27	0xb1, 0x85, 0xb3, 0x4d, 0xaa, 0xaa, 0xc3, 0x16, 0x34, 0x1a,
28	0xb8, 0xe7, 0xc7, 0xfa, 0xf9, 0x9, 0x77, 0xab, 0x97, 0x93,
29	0xeb, 0x44, 0xae, 0xcf, 0x20, 0xbc, 0xf0, 0x80, 0x11, 0xdb,
30	0x23, 0xc, 0x47, 0x71, 0xb9, 0x6d, 0xd6, 0x7b, 0x60, 0x47,
31	0x87, 0x16, 0x56, 0x93, 0xb7, 0xc2, 0x2a, 0x9a, 0xb0, 0x4c,
32	0x1, 0xc, 0x30, 0xd8, 0x93, 0x87, 0xf0, 0xed, 0x6e, 0x8b,
33	0xbe, 0x30, 0x5b, 0xf6, 0xa6, 0xaf, 0xdd, 0x80, 0x7c, 0x45,
34	0x5e, 0x8f, 0x91, 0x93, 0x5e, 0x44, 0xfe, 0xb8, 0x82, 0x7,
35	0xee, 0x79, 0xca, 0xbf, 0x31, 0x73, 0x62, 0x58, 0xe3, 0xcd,
36	0xc4, 0xbc, 0xc2, 0x11, 0x1d, 0xa1, 0x4a, 0xbf, 0xfe, 0x27,
37	0x7d, 0xa1, 0xf6, 0x35, 0xa3, 0x5e, 0xca, 0xdc, 0x57, 0x2f,
38	0x3e, 0xf0, 0xc9, 0x5d, 0x86, 0x6a, 0xf8, 0xaf, 0x66, 0xa7,
39	0xed, 0xcd, 0xb8, 0xed, 0xa1, 0x5f, 0xba, 0x9b, 0x85, 0x1a,
40	0xd5, 0x9, 0xae, 0x94, 0x4e, 0x3b, 0xcf, 0xcb, 0x5c, 0xc9,
41	0x79, 0x80, 0xf7, 0xcc, 0xa6, 0x4a, 0xa8, 0x6a, 0xd8, 0xd3,
42	0x31, 0x11, 0xf9, 0xf6, 0x2, 0x63, 0x2a, 0x1a, 0x2d, 0xd1,
43	0x1a, 0x66, 0x1b, 0x16, 0x41, 0xbd, 0xbd, 0xf7, 0x4d, 0xc0,
44	0x4a, 0xe5, 0x27, 0x49, 0x5f, 0x7f, 0x58, 0xe3, 0x27, 0x2d,
45	0xe5, 0xc9, 0x66, 0xe, 0x52, 0x38, 0x16, 0x38, 0xfb, 0x16,
46	0xeb, 0x53, 0x3f, 0xe6, 0xfd, 0xe9, 0xa2, 0x5e, 0x25, 0x59,
47	0xd8, 0x79, 0x45, 0xff, 0x3, 0x4c, 0x26, 0xa2, 0x0, 0x5a,
48	0x8e, 0xc2, 0x51, 0xa1, 0x15, 0xf9, 0x7b, 0xf4, 0x5c, 0x81,
49	0x9b, 0x18, 0x47, 0x35, 0xd8, 0x2d, 0x5, 0xe9, 0xad, 0xf,
50	0x35, 0x74, 0x15, 0xa3, 0x8e, 0x8b, 0xcc, 0x27, 0xda, 0x7c,
51	0x5d, 0xe4, 0xfa, 0x4, 0xd3, 0x5, 0xb, 0xba, 0x3a, 0xb2,
52	0x49, 0x45, 0x2f, 0x47, 0xc7, 0xd, 0x41, 0x3f, 0x97, 0x80,
53	0x4d, 0x3f, 0xc1, 0xb5, 0xbb, 0x70, 0x5f, 0xa7, 0x37, 0xaf,
54	0x48, 0x22, 0x12, 0x45, 0x2e, 0xf5, 0xf, 0x87, 0x92, 0xe2,
55	0x84, 0x1, 0xf9, 0x12, 0xf, 0x14, 0x15, 0x24, 0xce, 0x89,
56	0x99, 0xee, 0xb9, 0xc4, 0x17, 0x70, 0x70, 0x15, 0xea, 0xbe,
57	0xc6, 0x6c, 0x1f, 0x62, 0xb3, 0xf4, 0x2d, 0x16, 0x87, 0xfb,
58	0x56, 0x1e, 0x45, 0xab, 0xae, 0x32, 0xe4, 0x5e, 0x91, 0xed,
59	0x53, 0x66, 0x5e, 0xbd, 0xed, 0xad, 0xe6, 0x12, 0x39, 0xd,
60	0x83, 0xc9, 0xe8, 0x6b, 0x6c, 0x2d, 0xa5, 0xee, 0xc4, 0x5a,
61	0x66, 0xae, 0x8c, 0x97, 0xd7, 0xd, 0x6c, 0x49, 0xc7, 0xf5,
62	0xc4, 0x92, 0x31, 0x8b, 0x9, 0xee, 0x33, 0xda, 0xa9, 0x37,
63	0xb6, 0x49, 0x18, 0xf8, 0xe, 0x60, 0x45, 0xc8, 0x33, 0x91,
64	0xef, 0x20, 0x57, 0x10, 0xbe, 0x78, 0x2d, 0x83, 0x26, 0xd6,
65	0xca, 0x61, 0xf9, 0x2f, 0xe0, 0xbf, 0x5, 0x30, 0x52, 0x5a,
66	0x12, 0x1c, 0x0, 0xa7, 0x5d, 0xcc, 0x7c, 0x2e, 0xc5, 0x95,
67	0x8b, 0xa3, 0x3b, 0xf0, 0x43, 0x2e, 0x5e, 0xdd, 0x0, 0xdb,
68	0xd, 0xb3, 0x37, 0x99, 0xa9, 0xcd, 0x9c, 0xb7, 0x43, 0xf7,
69	0x35, 0x44, 0x21, 0xc2, 0x82, 0x71, 0xab, 0x8d, 0xaa, 0xb4,
70	0x41, 0x11, 0xec, 0x1e, 0x8d, 0xfc, 0x14, 0x82, 0x92, 0x4e,
71	0x83, 0x6a, 0xa, 0x6b, 0x35, 0x5e, 0x5d, 0xe9, 0x5c, 0xcc,
72	0x8c, 0xde, 0x39, 0xd1, 0x4a, 0x5b, 0x5f, 0x63, 0xa9, 0x64,
73	0xe0, 0xa, 0xcb, 0xb, 0xb8, 0x5a, 0x7c, 0xc3, 0xb, 0xe6,
74	0xbe, 0xfe, 0x8b, 0xf, 0x7d, 0x34, 0x8e, 0x2, 0x66, 0x74,
75	0x1, 0x6c, 0xca, 0x76, 0xac, 0x7c, 0x67, 0x8, 0x2f, 0x3f,
76	0x1a, 0xa6, 0x2c, 0x60, 0xb3, 0xff, 0xda, 0x8d, 0xb8, 0x12,
77	0xc, 0x0, 0x7f, 0xcc, 0x50, 0xa1, 0x5c, 0x64, 0xa1, 0xe2,
78	0x5f, 0x32, 0x65, 0xc9, 0x9c, 0xbe, 0xd6, 0xa, 0x13, 0x87,
79	0x3c, 0x2a, 0x45, 0x47, 0xc, 0xca, 0x42, 0x82, 0xfa, 0x89,
80	0x65, 0xe7, 0x89, 0xb4, 0x8f, 0xf7, 0x1e, 0xe6, 0x23, 0xa5,
81	0xd0, 0x59, 0x37, 0x79, 0x92, 0xd7, 0xce, 0x3d, 0xfd, 0xe3,
82	0xa1, 0xb, 0xcf, 0x6c, 0x85, 0xa0, 0x65, 0xf3, 0x5c, 0xc6,
83	0x4a, 0x63, 0x5f, 0x6e, 0x3a, 0x3a, 0x2a, 0x8b, 0x6a, 0xb6,
84	0x2f, 0xbb, 0xf8, 0xb2, 0x4b, 0x62, 0xbc, 0x1a, 0x91, 0x25,
85	0x66, 0xe3, 0x69, 0xca, 0x60, 0x49, 0xb, 0xf6, 0x8a, 0xbe,
86	0x3e, 0x76, 0x53, 0xc2, 0x7a, 0xa8, 0x4, 0x17, 0x75, 0xf1,
87	0xf3, 0x3, 0x62, 0x1b, 0x85, 0xb2, 0xb0, 0xef, 0x80, 0x15,
88	0xb6, 0xd4, 0x4e, 0xdf, 0x71, 0xac, 0xdb, 0x2a, 0x4, 0xd4,
89	0xb4, 0x21, 0xba, 0x65, 0x56, 0x57, 0xe8, 0xfa, 0x84, 0xa2,
90	0x7d, 0x13, 0xe, 0xaf, 0xd7, 0x9a, 0x58, 0x2a, 0xa3, 0x81,
91	0x84, 0x8d, 0x9, 0xa0, 0x6a, 0xc1, 0xbb, 0xd9, 0xf5, 0x86,
92	0xac, 0xbd, 0x75, 0x61, 0x9, 0xe6, 0x8c, 0x3d, 0x77, 0xb2,
93	0xed, 0x30, 0x20, 0xe4, 0x0, 0x1d, 0x97, 0xe8, 0xbf, 0xc7,
94	0x0, 0x1b, 0x21, 0xb1, 0x16, 0xe7, 0x41, 0x67, 0x2e, 0xec,
95	0x38, 0xbc, 0xe5, 0x1b, 0xb4, 0x6, 0x23, 0x31, 0x71, 0x1c,
96	0x49, 0xcd, 0x76, 0x4a, 0x76, 0x36, 0x8d, 0xa3, 0x89, 0x8b,
97	0x4a, 0x7a, 0xf4, 0x87, 0xc8, 0x15, 0xf, 0x37, 0x39, 0xf6,
98	0x6d, 0x80, 0x19, 0xef, 0x5c, 0xa8, 0x66, 0xce, 0x1b, 0x16,
99	0x79, 0x21, 0xdf, 0xd7, 0x31, 0x30, 0xc4, 0x21, 0xdd, 0x34,
100	0x5b, 0xd2, 0x1a, 0x2b, 0x3e, 0x5d, 0xf7, 0xea, 0xca, 0x5,
101	0x8e, 0xb7, 0xcb, 0x49, 0x2e, 0xa0, 0xe3, 0xf4, 0xa7, 0x48,
102	0x19, 0x10, 0x9c, 0x4, 0xa7, 0xf4, 0x28, 0x74, 0xc8, 0x6f,
103	0x63, 0x20, 0x2b, 0x46, 0x24, 0x26, 0x19, 0x1d, 0xd1, 0x2c,
104	0x31, 0x6d, 0x5a, 0x29, 0xa2, 0x6, 0xa6, 0xb2, 0x41, 0xcc,
105	0xa, 0x27, 0x96, 0x9, 0x96, 0xac, 0x47, 0x65, 0x78, 0x68,
106	0x51, 0x98, 0xd6, 0xd8, 0xa6, 0x2d, 0xa0, 0xcf, 0xec, 0xe2,
107	0x74, 0xf2, 0x82, 0xe3, 0x97, 0xd9, 0x7e, 0xd4, 0xf8, 0xb,
108	0x70, 0x43, 0x3d, 0xb1, 0x7b, 0x97, 0x80, 0xd6, 0xcb, 0xd7,
109	0x19, 0xbc, 0x63, 0xb, 0xfd, 0x4d, 0x88, 0xfe, 0x67, 0xac,
110	0xb8, 0xcc, 0x50, 0xb7, 0x68, 0xb3, 0x5b, 0xd6, 0x1e, 0x25,
111	0xfc, 0x5f, 0x3c, 0x8d, 0xb1, 0x33, 0x7c, 0xb3, 0x49, 0x1,
112	0x3f, 0x71, 0x55, 0xe, 0x51, 0xba, 0x61, 0x26, 0xfa, 0xea,
113	0xe5, 0xb5, 0xe8, 0xaa, 0xcf, 0xcd, 0x96, 0x9f, 0xd6, 0xc1,
114	0x5f, 0x53, 0x91, 0xad, 0x5, 0xde, 0x20, 0xe7, 0x51, 0xda,
115	0x5b, 0x95, 0x67, 0xed, 0xf4, 0xee, 0x42, 0x65, 0x70, 0x13,
116	0xb, 0x70, 0x14, 0x1c, 0xc9, 0xe0, 0x19, 0xca, 0x5f, 0xf5,
117	0x1d, 0x70, 0x4b, 0x6c, 0x6, 0x74, 0xec, 0xb5, 0x2e, 0x77,
118	0xe1, 0x74, 0xa1, 0xa3, 0x99, 0xa0, 0x85, 0x9e, 0xf1, 0xac,
119	0xd8, 0x7e,
120};
121
122const char *str_avb_io_error(AvbIOResult res)
123{
124	switch (res) {
125	case AVB_IO_RESULT_OK:
126		return "Requested operation was successful";
127	case AVB_IO_RESULT_ERROR_IO:
128		return "Underlying hardware encountered an I/O error";
129	case AVB_IO_RESULT_ERROR_OOM:
130		return "Unable to allocate memory";
131	case AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION:
132		return "Requested partition does not exist";
133	case AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION:
134		return "Bytes requested is outside the range of partition";
135	case AVB_IO_RESULT_ERROR_NO_SUCH_VALUE:
136		return "Named persistent value does not exist";
137	case AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE:
138		return "Named persistent value size is not supported";
139	case AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE:
140		return "Buffer is too small for the requested operation";
141	default:
142		return "Unknown AVB error";
143	}
144}
145
146const char *str_avb_slot_error(AvbSlotVerifyResult res)
147{
148	switch (res) {
149	case AVB_SLOT_VERIFY_RESULT_OK:
150		return "Verification passed successfully";
151	case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
152		return "Allocation of memory failed";
153	case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
154		return "I/O error occurred while trying to load data";
155	case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
156		return "Digest didn't match or signature checks failed";
157	case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
158		return "Rollback index is less than its stored value";
159	case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
160		return "Public keys are not accepted";
161	case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
162		return "Metadata is invalid or inconsistent";
163	case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
164		return "Metadata requires a newer version of libavb";
165	case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
166		return "Invalid arguments are used";
167	default:
168		return "Unknown AVB slot verification error";
169	}
170}
171/**
172 * ============================================================================
173 * Boot states support (GREEN, YELLOW, ORANGE, RED) and dm_verity
174 * ============================================================================
175 */
176char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state)
177{
178	struct AvbOpsData *data;
179	char *cmdline = NULL;
180
181	if (!ops)
182		return NULL;
183
184	data = (struct AvbOpsData *)ops->user_data;
185	if (!data)
186		return NULL;
187
188	data->boot_state = boot_state;
189	switch (boot_state) {
190	case AVB_GREEN:
191		cmdline = "androidboot.verifiedbootstate=green";
192		break;
193	case AVB_YELLOW:
194		cmdline = "androidboot.verifiedbootstate=yellow";
195		break;
196	case AVB_ORANGE:
197		cmdline = "androidboot.verifiedbootstate=orange";
198	case AVB_RED:
199		break;
200	}
201
202	return cmdline;
203}
204
205char *append_cmd_line(char *cmdline_orig, char *cmdline_new)
206{
207	char *cmd_line;
208
209	if (!cmdline_new)
210		return cmdline_orig;
211
212	if (cmdline_orig)
213		cmd_line = cmdline_orig;
214	else
215		cmd_line = " ";
216
217	cmd_line = avb_strdupv(cmd_line, " ", cmdline_new, NULL);
218
219	return cmd_line;
220}
221
222static int avb_find_dm_args(char **args, char *str)
223{
224	int i;
225
226	if (!str)
227		return -1;
228
229	for (i = 0; i < AVB_MAX_ARGS && args[i]; ++i) {
230		if (strstr(args[i], str))
231			return i;
232	}
233
234	return -1;
235}
236
237static char *avb_set_enforce_option(const char *cmdline, const char *option)
238{
239	char *cmdarg[AVB_MAX_ARGS];
240	char *newargs = NULL;
241	int i = 0;
242	int total_args;
243
244	memset(cmdarg, 0, sizeof(cmdarg));
245	cmdarg[i++] = strtok((char *)cmdline, " ");
246
247	do {
248		cmdarg[i] = strtok(NULL, " ");
249		if (!cmdarg[i])
250			break;
251
252		if (++i >= AVB_MAX_ARGS) {
253			printf("%s: Can't handle more then %d args\n",
254			       __func__, i);
255			return NULL;
256		}
257	} while (true);
258
259	total_args = i;
260	i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_LOGGING);
261	if (i >= 0) {
262		cmdarg[i] = (char *)option;
263	} else {
264		i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_RESTART);
265		if (i < 0) {
266			printf("%s: No verity options found\n", __func__);
267			return NULL;
268		}
269
270		cmdarg[i] = (char *)option;
271	}
272
273	for (i = 0; i <= total_args; i++)
274		newargs = append_cmd_line(newargs, cmdarg[i]);
275
276	return newargs;
277}
278
279char *avb_set_ignore_corruption(const char *cmdline)
280{
281	char *newargs = NULL;
282
283	newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_LOGGING);
284	if (newargs)
285		newargs = append_cmd_line(newargs,
286					  "androidboot.veritymode=eio");
287
288	return newargs;
289}
290
291char *avb_set_enforce_verity(const char *cmdline)
292{
293	char *newargs;
294
295	newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_RESTART);
296	if (newargs)
297		newargs = append_cmd_line(newargs,
298					  "androidboot.veritymode=enforcing");
299	return newargs;
300}
301
302/**
303 * ============================================================================
304 * IO(mmc) auxiliary functions
305 * ============================================================================
306 */
307static unsigned long mmc_read_and_flush(struct mmc_part *part,
308					lbaint_t start,
309					lbaint_t sectors,
310					void *buffer)
311{
312	unsigned long blks;
313	void *tmp_buf;
314	size_t buf_size;
315	bool unaligned = is_buf_unaligned(buffer);
316
317	if (start < part->info.start) {
318		printf("%s: partition start out of bounds\n", __func__);
319		return 0;
320	}
321	if ((start + sectors) > (part->info.start + part->info.size)) {
322		sectors = part->info.start + part->info.size - start;
323		printf("%s: read sector aligned to partition bounds (%ld)\n",
324		       __func__, sectors);
325	}
326
327	/*
328	 * Reading fails on unaligned buffers, so we have to
329	 * use aligned temporary buffer and then copy to destination
330	 */
331	if (unaligned) {
332		debug("%s: handling unaligned read buffer, addr = 0x%p\n",
333		      __func__, buffer);
334		tmp_buf = get_sector_buf();
335		buf_size = get_sector_buf_size();
336		if (sectors > buf_size / part->info.blksz)
337			sectors = buf_size / part->info.blksz;
338	} else {
339		tmp_buf = buffer;
340	}
341
342	blks = blk_dread(part->mmc_blk,
343			 start, sectors, tmp_buf);
344	/* flush cache after read */
345	flush_cache((ulong)tmp_buf, sectors * part->info.blksz);
346
347	if (unaligned)
348		memcpy(buffer, tmp_buf, sectors * part->info.blksz);
349
350	return blks;
351}
352
353static unsigned long mmc_write(struct mmc_part *part, lbaint_t start,
354			       lbaint_t sectors, void *buffer)
355{
356	void *tmp_buf;
357	size_t buf_size;
358	bool unaligned = is_buf_unaligned(buffer);
359
360	if (start < part->info.start) {
361		printf("%s: partition start out of bounds\n", __func__);
362		return 0;
363	}
364	if ((start + sectors) > (part->info.start + part->info.size)) {
365		sectors = part->info.start + part->info.size - start;
366		printf("%s: sector aligned to partition bounds (%ld)\n",
367		       __func__, sectors);
368	}
369	if (unaligned) {
370		tmp_buf = get_sector_buf();
371		buf_size = get_sector_buf_size();
372		debug("%s: handling unaligned read buffer, addr = 0x%p\n",
373		      __func__, buffer);
374		if (sectors > buf_size / part->info.blksz)
375			sectors = buf_size / part->info.blksz;
376
377		memcpy(tmp_buf, buffer, sectors * part->info.blksz);
378	} else {
379		tmp_buf = buffer;
380	}
381
382	return blk_dwrite(part->mmc_blk,
383			  start, sectors, tmp_buf);
384}
385
386static struct mmc_part *get_partition(AvbOps *ops, const char *partition)
387{
388	int ret;
389	u8 dev_num;
390	int part_num = 0;
391	struct mmc_part *part;
392	struct blk_desc *mmc_blk;
393
394	part = malloc(sizeof(struct mmc_part));
395	if (!part)
396		return NULL;
397
398	dev_num = get_boot_device(ops);
399	part->mmc = find_mmc_device(dev_num);
400	if (!part->mmc) {
401		printf("%s: no MMC device at slot %x\n", __func__, dev_num);
402		goto err;
403	}
404
405	ret = mmc_init(part->mmc);
406	if (ret) {
407		printf("%s: MMC initialization failed, err = %d\n",
408		       __func__, ret);
409		goto err;
410	}
411
412	if (IS_MMC(part->mmc)) {
413		ret = mmc_switch_part(part->mmc, part_num);
414		if (ret) {
415			printf("%s: MMC part switch failed, err = %d\n",
416			       __func__, ret);
417			goto err;
418		}
419	}
420
421	mmc_blk = mmc_get_blk_desc(part->mmc);
422	if (!mmc_blk) {
423		printf("%s: failed to obtain block descriptor\n", __func__);
424		goto err;
425	}
426
427	ret = part_get_info_by_name(mmc_blk, partition, &part->info);
428	if (ret < 0) {
429		printf("%s: can't find partition '%s'\n", __func__, partition);
430		goto err;
431	}
432
433	part->dev_num = dev_num;
434	part->mmc_blk = mmc_blk;
435
436	return part;
437err:
438	free(part);
439	return NULL;
440}
441
442static AvbIOResult mmc_byte_io(AvbOps *ops,
443			       const char *partition,
444			       s64 offset,
445			       size_t num_bytes,
446			       void *buffer,
447			       size_t *out_num_read,
448			       enum mmc_io_type io_type)
449{
450	ulong ret;
451	struct mmc_part *part;
452	u64 start_offset, start_sector, sectors, residue;
453	u8 *tmp_buf;
454	size_t io_cnt = 0;
455
456	if (!partition || !buffer || io_type > IO_WRITE)
457		return AVB_IO_RESULT_ERROR_IO;
458
459	part = get_partition(ops, partition);
460	if (!part)
461		return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
462
463	if (!part->info.blksz)
464		return AVB_IO_RESULT_ERROR_IO;
465
466	start_offset = calc_offset(part, offset);
467	while (num_bytes) {
468		start_sector = start_offset / part->info.blksz;
469		sectors = num_bytes / part->info.blksz;
470		/* handle non block-aligned reads */
471		if (start_offset % part->info.blksz ||
472		    num_bytes < part->info.blksz) {
473			tmp_buf = get_sector_buf();
474			if (start_offset % part->info.blksz) {
475				residue = part->info.blksz -
476					(start_offset % part->info.blksz);
477				if (residue > num_bytes)
478					residue = num_bytes;
479			} else {
480				residue = num_bytes;
481			}
482
483			if (io_type == IO_READ) {
484				ret = mmc_read_and_flush(part,
485							 part->info.start +
486							 start_sector,
487							 1, tmp_buf);
488
489				if (ret != 1) {
490					printf("%s: read error (%ld, %lld)\n",
491					       __func__, ret, start_sector);
492					return AVB_IO_RESULT_ERROR_IO;
493				}
494				/*
495				 * if this is not aligned at sector start,
496				 * we have to adjust the tmp buffer
497				 */
498				tmp_buf += (start_offset % part->info.blksz);
499				memcpy(buffer, (void *)tmp_buf, residue);
500			} else {
501				ret = mmc_read_and_flush(part,
502							 part->info.start +
503							 start_sector,
504							 1, tmp_buf);
505
506				if (ret != 1) {
507					printf("%s: read error (%ld, %lld)\n",
508					       __func__, ret, start_sector);
509					return AVB_IO_RESULT_ERROR_IO;
510				}
511				memcpy((void *)tmp_buf +
512					start_offset % part->info.blksz,
513					buffer, residue);
514
515				ret = mmc_write(part, part->info.start +
516						start_sector, 1, tmp_buf);
517				if (ret != 1) {
518					printf("%s: write error (%ld, %lld)\n",
519					       __func__, ret, start_sector);
520					return AVB_IO_RESULT_ERROR_IO;
521				}
522			}
523
524			io_cnt += residue;
525			buffer += residue;
526			start_offset += residue;
527			num_bytes -= residue;
528			continue;
529		}
530
531		if (sectors) {
532			if (io_type == IO_READ) {
533				ret = mmc_read_and_flush(part,
534							 part->info.start +
535							 start_sector,
536							 sectors, buffer);
537			} else {
538				ret = mmc_write(part,
539						part->info.start +
540						start_sector,
541						sectors, buffer);
542			}
543
544			if (!ret) {
545				printf("%s: sector read error\n", __func__);
546				return AVB_IO_RESULT_ERROR_IO;
547			}
548
549			io_cnt += ret * part->info.blksz;
550			buffer += ret * part->info.blksz;
551			start_offset += ret * part->info.blksz;
552			num_bytes -= ret * part->info.blksz;
553		}
554	}
555
556	/* Set counter for read operation */
557	if (io_type == IO_READ && out_num_read)
558		*out_num_read = io_cnt;
559
560	return AVB_IO_RESULT_OK;
561}
562
563/**
564 * ============================================================================
565 * AVB 2.0 operations
566 * ============================================================================
567 */
568
569/**
570 * read_from_partition() - reads @num_bytes from  @offset from partition
571 * identified by a string name
572 *
573 * @ops: contains AVB ops handlers
574 * @partition_name: partition name, NUL-terminated UTF-8 string
575 * @offset: offset from the beginning of partition
576 * @num_bytes: amount of bytes to read
577 * @buffer: destination buffer to store data
578 * @out_num_read:
579 *
580 * @return:
581 *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
582 *      AVB_IO_RESULT_ERROR_IO, if i/o error occurred from the underlying i/o
583 *            subsystem
584 *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if there is no partition with
585 *      the given name
586 */
587static AvbIOResult read_from_partition(AvbOps *ops,
588				       const char *partition_name,
589				       s64 offset_from_partition,
590				       size_t num_bytes,
591				       void *buffer,
592				       size_t *out_num_read)
593{
594	return mmc_byte_io(ops, partition_name, offset_from_partition,
595			   num_bytes, buffer, out_num_read, IO_READ);
596}
597
598/**
599 * write_to_partition() - writes N bytes to a partition identified by a string
600 * name
601 *
602 * @ops: AvbOps, contains AVB ops handlers
603 * @partition_name: partition name
604 * @offset_from_partition: offset from the beginning of partition
605 * @num_bytes: amount of bytes to write
606 * @buf: data to write
607 * @out_num_read:
608 *
609 * @return:
610 *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
611 *      AVB_IO_RESULT_ERROR_IO, if input/output error occurred
612 *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition, specified in
613 *            @partition_name was not found
614 */
615static AvbIOResult write_to_partition(AvbOps *ops,
616				      const char *partition_name,
617				      s64 offset_from_partition,
618				      size_t num_bytes,
619				      const void *buffer)
620{
621	return mmc_byte_io(ops, partition_name, offset_from_partition,
622			   num_bytes, (void *)buffer, NULL, IO_WRITE);
623}
624
625/**
626 * validate_vmbeta_public_key() - checks if the given public key used to sign
627 * the vbmeta partition is trusted
628 *
629 * @ops: AvbOps, contains AVB ops handlers
630 * @public_key_data: public key for verifying vbmeta partition signature
631 * @public_key_length: length of public key
632 * @public_key_metadata:
633 * @public_key_metadata_length:
634 * @out_key_is_trusted:
635 *
636 * @return:
637 *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
638 */
639static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
640					      const u8 *public_key_data,
641					      size_t public_key_length,
642					      const u8
643					      *public_key_metadata,
644					      size_t
645					      public_key_metadata_length,
646					      bool *out_key_is_trusted)
647{
648	if (!public_key_length || !public_key_data || !out_key_is_trusted)
649		return AVB_IO_RESULT_ERROR_IO;
650
651	*out_key_is_trusted = false;
652	if (public_key_length != sizeof(avb_root_pub))
653		return AVB_IO_RESULT_ERROR_IO;
654
655	if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0)
656		*out_key_is_trusted = true;
657
658	return AVB_IO_RESULT_OK;
659}
660
661#ifdef CONFIG_OPTEE_TA_AVB
662static int get_open_session(struct AvbOpsData *ops_data)
663{
664	struct udevice *tee = NULL;
665
666	while (!ops_data->tee) {
667		const struct tee_optee_ta_uuid uuid = TA_AVB_UUID;
668		struct tee_open_session_arg arg;
669		int rc;
670
671		tee = tee_find_device(tee, NULL, NULL, NULL);
672		if (!tee)
673			return -ENODEV;
674
675		memset(&arg, 0, sizeof(arg));
676		tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
677		rc = tee_open_session(tee, &arg, 0, NULL);
678		if (rc || arg.ret)
679			continue;
680
681		ops_data->tee = tee;
682		ops_data->session = arg.session;
683	}
684
685	return 0;
686}
687
688static AvbIOResult invoke_func(struct AvbOpsData *ops_data, u32 func,
689			       ulong num_param, struct tee_param *param)
690{
691	struct tee_invoke_arg arg;
692
693	if (get_open_session(ops_data))
694		return AVB_IO_RESULT_ERROR_IO;
695
696	memset(&arg, 0, sizeof(arg));
697	arg.func = func;
698	arg.session = ops_data->session;
699
700	if (tee_invoke_func(ops_data->tee, &arg, num_param, param))
701		return AVB_IO_RESULT_ERROR_IO;
702	switch (arg.ret) {
703	case TEE_SUCCESS:
704		return AVB_IO_RESULT_OK;
705	case TEE_ERROR_OUT_OF_MEMORY:
706		return AVB_IO_RESULT_ERROR_OOM;
707	case TEE_ERROR_STORAGE_NO_SPACE:
708		return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
709	case TEE_ERROR_ITEM_NOT_FOUND:
710		return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
711	case TEE_ERROR_TARGET_DEAD:
712		/*
713		 * The TA has paniced, close the session to reload the TA
714		 * for the next request.
715		 */
716		tee_close_session(ops_data->tee, ops_data->session);
717		ops_data->tee = NULL;
718		return AVB_IO_RESULT_ERROR_IO;
719	default:
720		return AVB_IO_RESULT_ERROR_IO;
721	}
722}
723#endif
724
725/**
726 * read_rollback_index() - gets the rollback index corresponding to the
727 * location of given by @out_rollback_index.
728 *
729 * @ops: contains AvbOps handlers
730 * @rollback_index_slot:
731 * @out_rollback_index: used to write a retrieved rollback index.
732 *
733 * @return
734 *       AVB_IO_RESULT_OK, if the roolback index was retrieved
735 */
736static AvbIOResult read_rollback_index(AvbOps *ops,
737				       size_t rollback_index_slot,
738				       u64 *out_rollback_index)
739{
740#ifndef CONFIG_OPTEE_TA_AVB
741	/* For now we always return 0 as the stored rollback index. */
742	debug("%s: rollback protection is not implemented\n", __func__);
743
744	if (out_rollback_index)
745		*out_rollback_index = 0;
746
747	return AVB_IO_RESULT_OK;
748#else
749	AvbIOResult rc;
750	struct tee_param param[2];
751
752	if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
753		return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
754
755	memset(param, 0, sizeof(param));
756	param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
757	param[0].u.value.a = rollback_index_slot;
758	param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;
759
760	rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_ROLLBACK_INDEX,
761			 ARRAY_SIZE(param), param);
762	if (rc)
763		return rc;
764
765	*out_rollback_index = (u64)param[1].u.value.a << 32 |
766			      (u32)param[1].u.value.b;
767	return AVB_IO_RESULT_OK;
768#endif
769}
770
771/**
772 * write_rollback_index() - sets the rollback index corresponding to the
773 * location of given by @out_rollback_index.
774 *
775 * @ops: contains AvbOps handlers
776 * @rollback_index_slot:
777 * @rollback_index: rollback index to write.
778 *
779 * @return
780 *       AVB_IO_RESULT_OK, if the roolback index was retrieved
781 */
782static AvbIOResult write_rollback_index(AvbOps *ops,
783					size_t rollback_index_slot,
784					u64 rollback_index)
785{
786#ifndef CONFIG_OPTEE_TA_AVB
787	/* For now this is a no-op. */
788	debug("%s: rollback protection is not implemented\n", __func__);
789
790	return AVB_IO_RESULT_OK;
791#else
792	struct tee_param param[2];
793
794	if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
795		return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
796
797	memset(param, 0, sizeof(param));
798	param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
799	param[0].u.value.a = rollback_index_slot;
800	param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
801	param[1].u.value.a = (u32)(rollback_index >> 32);
802	param[1].u.value.b = (u32)rollback_index;
803
804	return invoke_func(ops->user_data, TA_AVB_CMD_WRITE_ROLLBACK_INDEX,
805			   ARRAY_SIZE(param), param);
806#endif
807}
808
809/**
810 * read_is_device_unlocked() - gets whether the device is unlocked
811 *
812 * @ops: contains AVB ops handlers
813 * @out_is_unlocked: device unlock state is stored here, true if unlocked,
814 *       false otherwise
815 *
816 * @return:
817 *       AVB_IO_RESULT_OK: state is retrieved successfully
818 *       AVB_IO_RESULT_ERROR_IO: an error occurred
819 */
820static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
821{
822#ifndef CONFIG_OPTEE_TA_AVB
823	/* For now we always return that the device is unlocked. */
824	debug("%s: device locking is not implemented\n", __func__);
825
826	*out_is_unlocked = true;
827
828	return AVB_IO_RESULT_OK;
829#else
830	AvbIOResult rc;
831	struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT };
832
833	rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_LOCK_STATE, 1, &param);
834	if (rc)
835		return rc;
836	*out_is_unlocked = !param.u.value.a;
837	return AVB_IO_RESULT_OK;
838#endif
839}
840
841/**
842 * get_unique_guid_for_partition() - gets the GUID for a partition identified
843 * by a string name
844 *
845 * @ops: contains AVB ops handlers
846 * @partition: partition name (NUL-terminated UTF-8 string)
847 * @guid_buf: buf, used to copy in GUID string. Example of value:
848 *      527c1c6d-6361-4593-8842-3c78fcd39219
849 * @guid_buf_size: @guid_buf buffer size
850 *
851 * @return:
852 *      AVB_IO_RESULT_OK, on success (GUID found)
853 *      AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
854 *             provided
855 *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
856 */
857static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
858						 const char *partition,
859						 char *guid_buf,
860						 size_t guid_buf_size)
861{
862	struct mmc_part *part;
863	size_t uuid_size;
864
865	part = get_partition(ops, partition);
866	if (!part)
867		return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
868
869	uuid_size = sizeof(part->info.uuid);
870	if (uuid_size > guid_buf_size)
871		return AVB_IO_RESULT_ERROR_IO;
872
873	memcpy(guid_buf, part->info.uuid, uuid_size);
874	guid_buf[uuid_size - 1] = 0;
875
876	return AVB_IO_RESULT_OK;
877}
878
879/**
880 * get_size_of_partition() - gets the size of a partition identified
881 * by a string name
882 *
883 * @ops: contains AVB ops handlers
884 * @partition: partition name (NUL-terminated UTF-8 string)
885 * @out_size_num_bytes: returns the value of a partition size
886 *
887 * @return:
888 *      AVB_IO_RESULT_OK, on success (GUID found)
889 *      AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE, out_size_num_bytes is NULL
890 *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
891 */
892static AvbIOResult get_size_of_partition(AvbOps *ops,
893					 const char *partition,
894					 u64 *out_size_num_bytes)
895{
896	struct mmc_part *part;
897
898	if (!out_size_num_bytes)
899		return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
900
901	part = get_partition(ops, partition);
902	if (!part)
903		return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
904
905	*out_size_num_bytes = part->info.blksz * part->info.size;
906
907	return AVB_IO_RESULT_OK;
908}
909
910#ifdef CONFIG_OPTEE_TA_AVB
911static AvbIOResult read_persistent_value(AvbOps *ops,
912					 const char *name,
913					 size_t buffer_size,
914					 u8 *out_buffer,
915					 size_t *out_num_bytes_read)
916{
917	AvbIOResult rc;
918	struct tee_shm *shm_name;
919	struct tee_shm *shm_buf;
920	struct tee_param param[2];
921	struct udevice *tee;
922	size_t name_size = strlen(name) + 1;
923
924	if (get_open_session(ops->user_data))
925		return AVB_IO_RESULT_ERROR_IO;
926
927	tee = ((struct AvbOpsData *)ops->user_data)->tee;
928
929	rc = tee_shm_alloc(tee, name_size,
930			   TEE_SHM_ALLOC, &shm_name);
931	if (rc)
932		return AVB_IO_RESULT_ERROR_OOM;
933
934	rc = tee_shm_alloc(tee, buffer_size,
935			   TEE_SHM_ALLOC, &shm_buf);
936	if (rc) {
937		rc = AVB_IO_RESULT_ERROR_OOM;
938		goto free_name;
939	}
940
941	memcpy(shm_name->addr, name, name_size);
942
943	memset(param, 0, sizeof(param));
944	param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
945	param[0].u.memref.shm = shm_name;
946	param[0].u.memref.size = name_size;
947	param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
948	param[1].u.memref.shm = shm_buf;
949	param[1].u.memref.size = buffer_size;
950
951	rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_PERSIST_VALUE,
952			 2, param);
953	if (rc)
954		goto out;
955
956	if (param[1].u.memref.size > buffer_size) {
957		rc = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
958		goto out;
959	}
960
961	*out_num_bytes_read = param[1].u.memref.size;
962
963	memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read);
964
965out:
966	tee_shm_free(shm_buf);
967free_name:
968	tee_shm_free(shm_name);
969
970	return rc;
971}
972
973static AvbIOResult write_persistent_value(AvbOps *ops,
974					  const char *name,
975					  size_t value_size,
976					  const u8 *value)
977{
978	AvbIOResult rc;
979	struct tee_shm *shm_name;
980	struct tee_shm *shm_buf;
981	struct tee_param param[2];
982	struct udevice *tee;
983	size_t name_size = strlen(name) + 1;
984
985	if (get_open_session(ops->user_data))
986		return AVB_IO_RESULT_ERROR_IO;
987
988	tee = ((struct AvbOpsData *)ops->user_data)->tee;
989
990	if (!value_size)
991		return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
992
993	rc = tee_shm_alloc(tee, name_size,
994			   TEE_SHM_ALLOC, &shm_name);
995	if (rc)
996		return AVB_IO_RESULT_ERROR_OOM;
997
998	rc = tee_shm_alloc(tee, value_size,
999			   TEE_SHM_ALLOC, &shm_buf);
1000	if (rc) {
1001		rc = AVB_IO_RESULT_ERROR_OOM;
1002		goto free_name;
1003	}
1004
1005	memcpy(shm_name->addr, name, name_size);
1006	memcpy(shm_buf->addr, value, value_size);
1007
1008	memset(param, 0, sizeof(param));
1009	param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
1010	param[0].u.memref.shm = shm_name;
1011	param[0].u.memref.size = name_size;
1012	param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
1013	param[1].u.memref.shm = shm_buf;
1014	param[1].u.memref.size = value_size;
1015
1016	rc = invoke_func(ops->user_data, TA_AVB_CMD_WRITE_PERSIST_VALUE,
1017			 2, param);
1018	if (rc)
1019		goto out;
1020
1021out:
1022	tee_shm_free(shm_buf);
1023free_name:
1024	tee_shm_free(shm_name);
1025
1026	return rc;
1027}
1028#endif
1029
1030/**
1031 * ============================================================================
1032 * AVB2.0 AvbOps alloc/initialisation/free
1033 * ============================================================================
1034 */
1035AvbOps *avb_ops_alloc(int boot_device)
1036{
1037	struct AvbOpsData *ops_data;
1038
1039	ops_data = avb_calloc(sizeof(struct AvbOpsData));
1040	if (!ops_data)
1041		return NULL;
1042
1043	ops_data->ops.user_data = ops_data;
1044
1045	ops_data->ops.read_from_partition = read_from_partition;
1046	ops_data->ops.write_to_partition = write_to_partition;
1047	ops_data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key;
1048	ops_data->ops.read_rollback_index = read_rollback_index;
1049	ops_data->ops.write_rollback_index = write_rollback_index;
1050	ops_data->ops.read_is_device_unlocked = read_is_device_unlocked;
1051	ops_data->ops.get_unique_guid_for_partition =
1052		get_unique_guid_for_partition;
1053#ifdef CONFIG_OPTEE_TA_AVB
1054	ops_data->ops.write_persistent_value = write_persistent_value;
1055	ops_data->ops.read_persistent_value = read_persistent_value;
1056#endif
1057	ops_data->ops.get_size_of_partition = get_size_of_partition;
1058	ops_data->mmc_dev = boot_device;
1059
1060	return &ops_data->ops;
1061}
1062
1063void avb_ops_free(AvbOps *ops)
1064{
1065	struct AvbOpsData *ops_data;
1066
1067	if (!ops)
1068		return;
1069
1070	ops_data = ops->user_data;
1071
1072	if (ops_data) {
1073#ifdef CONFIG_OPTEE_TA_AVB
1074		if (ops_data->tee)
1075			tee_close_session(ops_data->tee, ops_data->session);
1076#endif
1077		avb_free(ops_data);
1078	}
1079}
1080