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