xref: /openbmc/u-boot/common/avb_verify.c (revision 09d84117)
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 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 		return NULL;
352 	}
353 
354 	if (mmc_init(part->mmc)) {
355 		printf("MMC initialization failed\n");
356 		return NULL;
357 	}
358 
359 	ret = mmc_switch_part(part->mmc, part_num);
360 	if (ret)
361 		return NULL;
362 
363 	mmc_blk = mmc_get_blk_desc(part->mmc);
364 	if (!mmc_blk) {
365 		printf("Error - failed to obtain block descriptor\n");
366 		return NULL;
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 		return NULL;
373 	}
374 
375 	part->dev_num = dev_num;
376 	part->mmc_blk = mmc_blk;
377 
378 	return part;
379 }
380 
381 static AvbIOResult mmc_byte_io(AvbOps *ops,
382 			       const char *partition,
383 			       s64 offset,
384 			       size_t num_bytes,
385 			       void *buffer,
386 			       size_t *out_num_read,
387 			       enum mmc_io_type io_type)
388 {
389 	ulong ret;
390 	struct mmc_part *part;
391 	u64 start_offset, start_sector, sectors, residue;
392 	u8 *tmp_buf;
393 	size_t io_cnt = 0;
394 
395 	if (!partition || !buffer || io_type > IO_WRITE)
396 		return AVB_IO_RESULT_ERROR_IO;
397 
398 	part = get_partition(ops, partition);
399 	if (!part)
400 		return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
401 
402 	start_offset = calc_offset(part, offset);
403 	while (num_bytes) {
404 		start_sector = start_offset / part->info.blksz;
405 		sectors = num_bytes / part->info.blksz;
406 		/* handle non block-aligned reads */
407 		if (start_offset % part->info.blksz ||
408 		    num_bytes < part->info.blksz) {
409 			tmp_buf = get_sector_buf();
410 			if (start_offset % part->info.blksz) {
411 				residue = part->info.blksz -
412 					(start_offset % part->info.blksz);
413 				if (residue > num_bytes)
414 					residue = num_bytes;
415 			} else {
416 				residue = num_bytes;
417 			}
418 
419 			if (io_type == IO_READ) {
420 				ret = mmc_read_and_flush(part,
421 							 part->info.start +
422 							 start_sector,
423 							 1, tmp_buf);
424 
425 				if (ret != 1) {
426 					printf("%s: read error (%ld, %lld)\n",
427 					       __func__, ret, start_sector);
428 					return AVB_IO_RESULT_ERROR_IO;
429 				}
430 				/*
431 				 * if this is not aligned at sector start,
432 				 * we have to adjust the tmp buffer
433 				 */
434 				tmp_buf += (start_offset % part->info.blksz);
435 				memcpy(buffer, (void *)tmp_buf, residue);
436 			} else {
437 				ret = mmc_read_and_flush(part,
438 							 part->info.start +
439 							 start_sector,
440 							 1, tmp_buf);
441 
442 				if (ret != 1) {
443 					printf("%s: read error (%ld, %lld)\n",
444 					       __func__, ret, start_sector);
445 					return AVB_IO_RESULT_ERROR_IO;
446 				}
447 				memcpy((void *)tmp_buf +
448 					start_offset % part->info.blksz,
449 					buffer, residue);
450 
451 				ret = mmc_write(part, part->info.start +
452 						start_sector, 1, tmp_buf);
453 				if (ret != 1) {
454 					printf("%s: write error (%ld, %lld)\n",
455 					       __func__, ret, start_sector);
456 					return AVB_IO_RESULT_ERROR_IO;
457 				}
458 			}
459 
460 			io_cnt += residue;
461 			buffer += residue;
462 			start_offset += residue;
463 			num_bytes -= residue;
464 			continue;
465 		}
466 
467 		if (sectors) {
468 			if (io_type == IO_READ) {
469 				ret = mmc_read_and_flush(part,
470 							 part->info.start +
471 							 start_sector,
472 							 sectors, buffer);
473 			} else {
474 				ret = mmc_write(part,
475 						part->info.start +
476 						start_sector,
477 						sectors, buffer);
478 			}
479 
480 			if (!ret) {
481 				printf("%s: sector read error\n", __func__);
482 				return AVB_IO_RESULT_ERROR_IO;
483 			}
484 
485 			io_cnt += ret * part->info.blksz;
486 			buffer += ret * part->info.blksz;
487 			start_offset += ret * part->info.blksz;
488 			num_bytes -= ret * part->info.blksz;
489 		}
490 	}
491 
492 	/* Set counter for read operation */
493 	if (io_type == IO_READ && out_num_read)
494 		*out_num_read = io_cnt;
495 
496 	return AVB_IO_RESULT_OK;
497 }
498 
499 /**
500  * ============================================================================
501  * AVB 2.0 operations
502  * ============================================================================
503  */
504 
505 /**
506  * read_from_partition() - reads @num_bytes from  @offset from partition
507  * identified by a string name
508  *
509  * @ops: contains AVB ops handlers
510  * @partition_name: partition name, NUL-terminated UTF-8 string
511  * @offset: offset from the beginning of partition
512  * @num_bytes: amount of bytes to read
513  * @buffer: destination buffer to store data
514  * @out_num_read:
515  *
516  * @return:
517  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
518  *      AVB_IO_RESULT_ERROR_IO, if i/o error occurred from the underlying i/o
519  *            subsystem
520  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if there is no partition with
521  *      the given name
522  */
523 static AvbIOResult read_from_partition(AvbOps *ops,
524 				       const char *partition_name,
525 				       s64 offset_from_partition,
526 				       size_t num_bytes,
527 				       void *buffer,
528 				       size_t *out_num_read)
529 {
530 	return mmc_byte_io(ops, partition_name, offset_from_partition,
531 			   num_bytes, buffer, out_num_read, IO_READ);
532 }
533 
534 /**
535  * write_to_partition() - writes N bytes to a partition identified by a string
536  * name
537  *
538  * @ops: AvbOps, contains AVB ops handlers
539  * @partition_name: partition name
540  * @offset_from_partition: offset from the beginning of partition
541  * @num_bytes: amount of bytes to write
542  * @buf: data to write
543  * @out_num_read:
544  *
545  * @return:
546  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
547  *      AVB_IO_RESULT_ERROR_IO, if input/output error occurred
548  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition, specified in
549  *            @partition_name was not found
550  */
551 static AvbIOResult write_to_partition(AvbOps *ops,
552 				      const char *partition_name,
553 				      s64 offset_from_partition,
554 				      size_t num_bytes,
555 				      const void *buffer)
556 {
557 	return mmc_byte_io(ops, partition_name, offset_from_partition,
558 			   num_bytes, (void *)buffer, NULL, IO_WRITE);
559 }
560 
561 /**
562  * validate_vmbeta_public_key() - checks if the given public key used to sign
563  * the vbmeta partition is trusted
564  *
565  * @ops: AvbOps, contains AVB ops handlers
566  * @public_key_data: public key for verifying vbmeta partition signature
567  * @public_key_length: length of public key
568  * @public_key_metadata:
569  * @public_key_metadata_length:
570  * @out_key_is_trusted:
571  *
572  * @return:
573  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
574  */
575 static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
576 					      const u8 *public_key_data,
577 					      size_t public_key_length,
578 					      const u8
579 					      *public_key_metadata,
580 					      size_t
581 					      public_key_metadata_length,
582 					      bool *out_key_is_trusted)
583 {
584 	if (!public_key_length || !public_key_data || !out_key_is_trusted)
585 		return AVB_IO_RESULT_ERROR_IO;
586 
587 	*out_key_is_trusted = false;
588 	if (public_key_length != sizeof(avb_root_pub))
589 		return AVB_IO_RESULT_ERROR_IO;
590 
591 	if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0)
592 		*out_key_is_trusted = true;
593 
594 	return AVB_IO_RESULT_OK;
595 }
596 
597 /**
598  * read_rollback_index() - gets the rollback index corresponding to the
599  * location of given by @out_rollback_index.
600  *
601  * @ops: contains AvbOps handlers
602  * @rollback_index_slot:
603  * @out_rollback_index: used to write a retrieved rollback index.
604  *
605  * @return
606  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
607  */
608 static AvbIOResult read_rollback_index(AvbOps *ops,
609 				       size_t rollback_index_slot,
610 				       u64 *out_rollback_index)
611 {
612 	/* For now we always return 0 as the stored rollback index. */
613 	printf("%s not supported yet\n", __func__);
614 
615 	if (out_rollback_index)
616 		*out_rollback_index = 0;
617 
618 	return AVB_IO_RESULT_OK;
619 }
620 
621 /**
622  * write_rollback_index() - sets the rollback index corresponding to the
623  * location of given by @out_rollback_index.
624  *
625  * @ops: contains AvbOps handlers
626  * @rollback_index_slot:
627  * @rollback_index: rollback index to write.
628  *
629  * @return
630  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
631  */
632 static AvbIOResult write_rollback_index(AvbOps *ops,
633 					size_t rollback_index_slot,
634 					u64 rollback_index)
635 {
636 	/* For now this is a no-op. */
637 	printf("%s not supported yet\n", __func__);
638 
639 	return AVB_IO_RESULT_OK;
640 }
641 
642 /**
643  * read_is_device_unlocked() - gets whether the device is unlocked
644  *
645  * @ops: contains AVB ops handlers
646  * @out_is_unlocked: device unlock state is stored here, true if unlocked,
647  *       false otherwise
648  *
649  * @return:
650  *       AVB_IO_RESULT_OK: state is retrieved successfully
651  *       AVB_IO_RESULT_ERROR_IO: an error occurred
652  */
653 static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
654 {
655 	/* For now we always return that the device is unlocked. */
656 
657 	printf("%s not supported yet\n", __func__);
658 
659 	*out_is_unlocked = true;
660 
661 	return AVB_IO_RESULT_OK;
662 }
663 
664 /**
665  * get_unique_guid_for_partition() - gets the GUID for a partition identified
666  * by a string name
667  *
668  * @ops: contains AVB ops handlers
669  * @partition: partition name (NUL-terminated UTF-8 string)
670  * @guid_buf: buf, used to copy in GUID string. Example of value:
671  *      527c1c6d-6361-4593-8842-3c78fcd39219
672  * @guid_buf_size: @guid_buf buffer size
673  *
674  * @return:
675  *      AVB_IO_RESULT_OK, on success (GUID found)
676  *      AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
677  *             provided
678  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
679  */
680 static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
681 						 const char *partition,
682 						 char *guid_buf,
683 						 size_t guid_buf_size)
684 {
685 	struct mmc_part *part;
686 	size_t uuid_size;
687 
688 	part = get_partition(ops, partition);
689 	if (!part)
690 		return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
691 
692 	uuid_size = sizeof(part->info.uuid);
693 	if (uuid_size > guid_buf_size)
694 		return AVB_IO_RESULT_ERROR_IO;
695 
696 	memcpy(guid_buf, part->info.uuid, uuid_size);
697 	guid_buf[uuid_size - 1] = 0;
698 
699 	return AVB_IO_RESULT_OK;
700 }
701 
702 /**
703  * get_size_of_partition() - gets the size of a partition identified
704  * by a string name
705  *
706  * @ops: contains AVB ops handlers
707  * @partition: partition name (NUL-terminated UTF-8 string)
708  * @out_size_num_bytes: returns the value of a partition size
709  *
710  * @return:
711  *      AVB_IO_RESULT_OK, on success (GUID found)
712  *      AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE, out_size_num_bytes is NULL
713  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
714  */
715 static AvbIOResult get_size_of_partition(AvbOps *ops,
716 					 const char *partition,
717 					 u64 *out_size_num_bytes)
718 {
719 	struct mmc_part *part;
720 
721 	if (!out_size_num_bytes)
722 		return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
723 
724 	part = get_partition(ops, partition);
725 	if (!part)
726 		return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
727 
728 	*out_size_num_bytes = part->info.blksz * part->info.size;
729 
730 	return AVB_IO_RESULT_OK;
731 }
732 
733 /**
734  * ============================================================================
735  * AVB2.0 AvbOps alloc/initialisation/free
736  * ============================================================================
737  */
738 AvbOps *avb_ops_alloc(int boot_device)
739 {
740 	struct AvbOpsData *ops_data;
741 
742 	ops_data = avb_calloc(sizeof(struct AvbOpsData));
743 	if (!ops_data)
744 		return NULL;
745 
746 	ops_data->ops.user_data = ops_data;
747 
748 	ops_data->ops.read_from_partition = read_from_partition;
749 	ops_data->ops.write_to_partition = write_to_partition;
750 	ops_data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key;
751 	ops_data->ops.read_rollback_index = read_rollback_index;
752 	ops_data->ops.write_rollback_index = write_rollback_index;
753 	ops_data->ops.read_is_device_unlocked = read_is_device_unlocked;
754 	ops_data->ops.get_unique_guid_for_partition =
755 		get_unique_guid_for_partition;
756 	ops_data->ops.get_size_of_partition = get_size_of_partition;
757 	ops_data->mmc_dev = boot_device;
758 
759 	return &ops_data->ops;
760 }
761 
762 void avb_ops_free(AvbOps *ops)
763 {
764 	struct AvbOpsData *ops_data;
765 
766 	if (ops)
767 		return;
768 
769 	ops_data = ops->user_data;
770 
771 	if (ops_data)
772 		avb_free(ops_data);
773 }
774