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