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 <cpu_func.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  */
avb_set_state(AvbOps * ops,enum avb_boot_state boot_state)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 
append_cmd_line(char * cmdline_orig,char * cmdline_new)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 
avb_find_dm_args(char ** args,char * str)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 
avb_set_enforce_option(const char * cmdline,const char * option)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 
avb_set_ignore_corruption(const char * cmdline)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 
avb_set_enforce_verity(const char * cmdline)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  */
mmc_read_and_flush(struct mmc_part * part,lbaint_t start,lbaint_t sectors,void * buffer)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 
mmc_write(struct mmc_part * part,lbaint_t start,lbaint_t sectors,void * buffer)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 
get_partition(AvbOps * ops,const char * partition)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 < 0) {
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 
mmc_byte_io(AvbOps * ops,const char * partition,s64 offset,size_t num_bytes,void * buffer,size_t * out_num_read,enum mmc_io_type io_type)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  */
read_from_partition(AvbOps * ops,const char * partition_name,s64 offset_from_partition,size_t num_bytes,void * buffer,size_t * out_num_read)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  */
write_to_partition(AvbOps * ops,const char * partition_name,s64 offset_from_partition,size_t num_bytes,const void * buffer)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  */
validate_vbmeta_public_key(AvbOps * ops,const u8 * public_key_data,size_t public_key_length,const u8 * public_key_metadata,size_t public_key_metadata_length,bool * out_key_is_trusted)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
get_open_session(struct AvbOpsData * ops_data)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 
invoke_func(struct AvbOpsData * ops_data,u32 func,ulong num_param,struct tee_param * param)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_STORAGE_NO_SPACE:
651 		return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
652 	case TEE_ERROR_ITEM_NOT_FOUND:
653 		return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
654 	case TEE_ERROR_TARGET_DEAD:
655 		/*
656 		 * The TA has paniced, close the session to reload the TA
657 		 * for the next request.
658 		 */
659 		tee_close_session(ops_data->tee, ops_data->session);
660 		ops_data->tee = NULL;
661 		return AVB_IO_RESULT_ERROR_IO;
662 	default:
663 		return AVB_IO_RESULT_ERROR_IO;
664 	}
665 }
666 #endif
667 
668 /**
669  * read_rollback_index() - gets the rollback index corresponding to the
670  * location of given by @out_rollback_index.
671  *
672  * @ops: contains AvbOps handlers
673  * @rollback_index_slot:
674  * @out_rollback_index: used to write a retrieved rollback index.
675  *
676  * @return
677  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
678  */
read_rollback_index(AvbOps * ops,size_t rollback_index_slot,u64 * out_rollback_index)679 static AvbIOResult read_rollback_index(AvbOps *ops,
680 				       size_t rollback_index_slot,
681 				       u64 *out_rollback_index)
682 {
683 #ifndef CONFIG_OPTEE_TA_AVB
684 	/* For now we always return 0 as the stored rollback index. */
685 	printf("%s not supported yet\n", __func__);
686 
687 	if (out_rollback_index)
688 		*out_rollback_index = 0;
689 
690 	return AVB_IO_RESULT_OK;
691 #else
692 	AvbIOResult rc;
693 	struct tee_param param[2];
694 
695 	if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
696 		return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
697 
698 	memset(param, 0, sizeof(param));
699 	param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
700 	param[0].u.value.a = rollback_index_slot;
701 	param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;
702 
703 	rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_ROLLBACK_INDEX,
704 			 ARRAY_SIZE(param), param);
705 	if (rc)
706 		return rc;
707 
708 	*out_rollback_index = (u64)param[1].u.value.a << 32 |
709 			      (u32)param[1].u.value.b;
710 	return AVB_IO_RESULT_OK;
711 #endif
712 }
713 
714 /**
715  * write_rollback_index() - sets the rollback index corresponding to the
716  * location of given by @out_rollback_index.
717  *
718  * @ops: contains AvbOps handlers
719  * @rollback_index_slot:
720  * @rollback_index: rollback index to write.
721  *
722  * @return
723  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
724  */
write_rollback_index(AvbOps * ops,size_t rollback_index_slot,u64 rollback_index)725 static AvbIOResult write_rollback_index(AvbOps *ops,
726 					size_t rollback_index_slot,
727 					u64 rollback_index)
728 {
729 #ifndef CONFIG_OPTEE_TA_AVB
730 	/* For now this is a no-op. */
731 	printf("%s not supported yet\n", __func__);
732 
733 	return AVB_IO_RESULT_OK;
734 #else
735 	struct tee_param param[2];
736 
737 	if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
738 		return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
739 
740 	memset(param, 0, sizeof(param));
741 	param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
742 	param[0].u.value.a = rollback_index_slot;
743 	param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
744 	param[1].u.value.a = (u32)(rollback_index >> 32);
745 	param[1].u.value.b = (u32)rollback_index;
746 
747 	return invoke_func(ops->user_data, TA_AVB_CMD_WRITE_ROLLBACK_INDEX,
748 			   ARRAY_SIZE(param), param);
749 #endif
750 }
751 
752 /**
753  * read_is_device_unlocked() - gets whether the device is unlocked
754  *
755  * @ops: contains AVB ops handlers
756  * @out_is_unlocked: device unlock state is stored here, true if unlocked,
757  *       false otherwise
758  *
759  * @return:
760  *       AVB_IO_RESULT_OK: state is retrieved successfully
761  *       AVB_IO_RESULT_ERROR_IO: an error occurred
762  */
read_is_device_unlocked(AvbOps * ops,bool * out_is_unlocked)763 static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
764 {
765 #ifndef CONFIG_OPTEE_TA_AVB
766 	/* For now we always return that the device is unlocked. */
767 
768 	printf("%s not supported yet\n", __func__);
769 
770 	*out_is_unlocked = true;
771 
772 	return AVB_IO_RESULT_OK;
773 #else
774 	AvbIOResult rc;
775 	struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT };
776 
777 	rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_LOCK_STATE, 1, &param);
778 	if (rc)
779 		return rc;
780 	*out_is_unlocked = !param.u.value.a;
781 	return AVB_IO_RESULT_OK;
782 #endif
783 }
784 
785 /**
786  * get_unique_guid_for_partition() - gets the GUID for a partition identified
787  * by a string name
788  *
789  * @ops: contains AVB ops handlers
790  * @partition: partition name (NUL-terminated UTF-8 string)
791  * @guid_buf: buf, used to copy in GUID string. Example of value:
792  *      527c1c6d-6361-4593-8842-3c78fcd39219
793  * @guid_buf_size: @guid_buf buffer size
794  *
795  * @return:
796  *      AVB_IO_RESULT_OK, on success (GUID found)
797  *      AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
798  *             provided
799  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
800  */
get_unique_guid_for_partition(AvbOps * ops,const char * partition,char * guid_buf,size_t guid_buf_size)801 static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
802 						 const char *partition,
803 						 char *guid_buf,
804 						 size_t guid_buf_size)
805 {
806 	struct mmc_part *part;
807 	size_t uuid_size;
808 
809 	part = get_partition(ops, partition);
810 	if (!part)
811 		return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
812 
813 	uuid_size = sizeof(part->info.uuid);
814 	if (uuid_size > guid_buf_size)
815 		return AVB_IO_RESULT_ERROR_IO;
816 
817 	memcpy(guid_buf, part->info.uuid, uuid_size);
818 	guid_buf[uuid_size - 1] = 0;
819 
820 	return AVB_IO_RESULT_OK;
821 }
822 
823 /**
824  * get_size_of_partition() - gets the size of a partition identified
825  * by a string name
826  *
827  * @ops: contains AVB ops handlers
828  * @partition: partition name (NUL-terminated UTF-8 string)
829  * @out_size_num_bytes: returns the value of a partition size
830  *
831  * @return:
832  *      AVB_IO_RESULT_OK, on success (GUID found)
833  *      AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE, out_size_num_bytes is NULL
834  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
835  */
get_size_of_partition(AvbOps * ops,const char * partition,u64 * out_size_num_bytes)836 static AvbIOResult get_size_of_partition(AvbOps *ops,
837 					 const char *partition,
838 					 u64 *out_size_num_bytes)
839 {
840 	struct mmc_part *part;
841 
842 	if (!out_size_num_bytes)
843 		return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
844 
845 	part = get_partition(ops, partition);
846 	if (!part)
847 		return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
848 
849 	*out_size_num_bytes = part->info.blksz * part->info.size;
850 
851 	return AVB_IO_RESULT_OK;
852 }
853 
854 #ifdef CONFIG_OPTEE_TA_AVB
read_persistent_value(AvbOps * ops,const char * name,size_t buffer_size,u8 * out_buffer,size_t * out_num_bytes_read)855 static AvbIOResult read_persistent_value(AvbOps *ops,
856 					 const char *name,
857 					 size_t buffer_size,
858 					 u8 *out_buffer,
859 					 size_t *out_num_bytes_read)
860 {
861 	AvbIOResult rc;
862 	struct tee_shm *shm_name;
863 	struct tee_shm *shm_buf;
864 	struct tee_param param[2];
865 	struct udevice *tee;
866 	size_t name_size = strlen(name) + 1;
867 
868 	if (get_open_session(ops->user_data))
869 		return AVB_IO_RESULT_ERROR_IO;
870 
871 	tee = ((struct AvbOpsData *)ops->user_data)->tee;
872 
873 	rc = tee_shm_alloc(tee, name_size,
874 			   TEE_SHM_ALLOC, &shm_name);
875 	if (rc)
876 		return AVB_IO_RESULT_ERROR_OOM;
877 
878 	rc = tee_shm_alloc(tee, buffer_size,
879 			   TEE_SHM_ALLOC, &shm_buf);
880 	if (rc) {
881 		rc = AVB_IO_RESULT_ERROR_OOM;
882 		goto free_name;
883 	}
884 
885 	memcpy(shm_name->addr, name, name_size);
886 
887 	memset(param, 0, sizeof(param));
888 	param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
889 	param[0].u.memref.shm = shm_name;
890 	param[0].u.memref.size = name_size;
891 	param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
892 	param[1].u.memref.shm = shm_buf;
893 	param[1].u.memref.size = buffer_size;
894 
895 	rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_PERSIST_VALUE,
896 			 2, param);
897 	if (rc)
898 		goto out;
899 
900 	if (param[1].u.memref.size > buffer_size) {
901 		rc = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
902 		goto out;
903 	}
904 
905 	*out_num_bytes_read = param[1].u.memref.size;
906 
907 	memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read);
908 
909 out:
910 	tee_shm_free(shm_buf);
911 free_name:
912 	tee_shm_free(shm_name);
913 
914 	return rc;
915 }
916 
write_persistent_value(AvbOps * ops,const char * name,size_t value_size,const u8 * value)917 static AvbIOResult write_persistent_value(AvbOps *ops,
918 					  const char *name,
919 					  size_t value_size,
920 					  const u8 *value)
921 {
922 	AvbIOResult rc;
923 	struct tee_shm *shm_name;
924 	struct tee_shm *shm_buf;
925 	struct tee_param param[2];
926 	struct udevice *tee;
927 	size_t name_size = strlen(name) + 1;
928 
929 	if (get_open_session(ops->user_data))
930 		return AVB_IO_RESULT_ERROR_IO;
931 
932 	tee = ((struct AvbOpsData *)ops->user_data)->tee;
933 
934 	if (!value_size)
935 		return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
936 
937 	rc = tee_shm_alloc(tee, name_size,
938 			   TEE_SHM_ALLOC, &shm_name);
939 	if (rc)
940 		return AVB_IO_RESULT_ERROR_OOM;
941 
942 	rc = tee_shm_alloc(tee, value_size,
943 			   TEE_SHM_ALLOC, &shm_buf);
944 	if (rc) {
945 		rc = AVB_IO_RESULT_ERROR_OOM;
946 		goto free_name;
947 	}
948 
949 	memcpy(shm_name->addr, name, name_size);
950 	memcpy(shm_buf->addr, value, value_size);
951 
952 	memset(param, 0, sizeof(param));
953 	param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
954 	param[0].u.memref.shm = shm_name;
955 	param[0].u.memref.size = name_size;
956 	param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
957 	param[1].u.memref.shm = shm_buf;
958 	param[1].u.memref.size = value_size;
959 
960 	rc = invoke_func(ops->user_data, TA_AVB_CMD_WRITE_PERSIST_VALUE,
961 			 2, param);
962 	if (rc)
963 		goto out;
964 
965 out:
966 	tee_shm_free(shm_buf);
967 free_name:
968 	tee_shm_free(shm_name);
969 
970 	return rc;
971 }
972 #endif
973 
974 /**
975  * ============================================================================
976  * AVB2.0 AvbOps alloc/initialisation/free
977  * ============================================================================
978  */
avb_ops_alloc(int boot_device)979 AvbOps *avb_ops_alloc(int boot_device)
980 {
981 	struct AvbOpsData *ops_data;
982 
983 	ops_data = avb_calloc(sizeof(struct AvbOpsData));
984 	if (!ops_data)
985 		return NULL;
986 
987 	ops_data->ops.user_data = ops_data;
988 
989 	ops_data->ops.read_from_partition = read_from_partition;
990 	ops_data->ops.write_to_partition = write_to_partition;
991 	ops_data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key;
992 	ops_data->ops.read_rollback_index = read_rollback_index;
993 	ops_data->ops.write_rollback_index = write_rollback_index;
994 	ops_data->ops.read_is_device_unlocked = read_is_device_unlocked;
995 	ops_data->ops.get_unique_guid_for_partition =
996 		get_unique_guid_for_partition;
997 #ifdef CONFIG_OPTEE_TA_AVB
998 	ops_data->ops.write_persistent_value = write_persistent_value;
999 	ops_data->ops.read_persistent_value = read_persistent_value;
1000 #endif
1001 	ops_data->ops.get_size_of_partition = get_size_of_partition;
1002 	ops_data->mmc_dev = boot_device;
1003 
1004 	return &ops_data->ops;
1005 }
1006 
avb_ops_free(AvbOps * ops)1007 void avb_ops_free(AvbOps *ops)
1008 {
1009 	struct AvbOpsData *ops_data;
1010 
1011 	if (!ops)
1012 		return;
1013 
1014 	ops_data = ops->user_data;
1015 
1016 	if (ops_data) {
1017 #ifdef CONFIG_OPTEE_TA_AVB
1018 		if (ops_data->tee)
1019 			tee_close_session(ops_data->tee, ops_data->session);
1020 #endif
1021 		avb_free(ops_data);
1022 	}
1023 }
1024