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