1
2
3
4
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
16static 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
126
127
128char *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
157char *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
174static 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
189static 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
231char *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
243char *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
257
258
259static 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
281
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
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
305static 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
337static struct mmc_part *get_partition(AvbOps *ops, const char *partition)
338{
339 int ret;
340 u8 dev_num;
341 int part_num = 0;
342 struct mmc_part *part;
343 struct blk_desc *mmc_blk;
344
345 part = malloc(sizeof(struct mmc_part));
346 if (!part)
347 return NULL;
348
349 dev_num = get_boot_device(ops);
350 part->mmc = find_mmc_device(dev_num);
351 if (!part->mmc) {
352 printf("No MMC device at slot %x\n", dev_num);
353 goto err;
354 }
355
356 if (mmc_init(part->mmc)) {
357 printf("MMC initialization failed\n");
358 goto err;
359 }
360
361 ret = mmc_switch_part(part->mmc, part_num);
362 if (ret)
363 goto err;
364
365 mmc_blk = mmc_get_blk_desc(part->mmc);
366 if (!mmc_blk) {
367 printf("Error - failed to obtain block descriptor\n");
368 goto err;
369 }
370
371 ret = part_get_info_by_name(mmc_blk, partition, &part->info);
372 if (!ret) {
373 printf("Can't find partition '%s'\n", partition);
374 goto err;
375 }
376
377 part->dev_num = dev_num;
378 part->mmc_blk = mmc_blk;
379
380 return part;
381err:
382 free(part);
383 return NULL;
384}
385
386static 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
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
440
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
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
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531static 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
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559static 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
571
572
573
574
575
576
577
578
579
580
581
582
583static 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
606static 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
631static 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
657
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
670
671
672
673
674
675
676
677
678
679static 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
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
716
717
718
719
720
721
722
723
724
725static AvbIOResult write_rollback_index(AvbOps *ops,
726 size_t rollback_index_slot,
727 u64 rollback_index)
728{
729#ifndef CONFIG_OPTEE_TA_AVB
730
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
754
755
756
757
758
759
760
761
762
763static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
764{
765#ifndef CONFIG_OPTEE_TA_AVB
766
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, ¶m);
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
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801static 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
825
826
827
828
829
830
831
832
833
834
835
836static 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
855static 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
909out:
910 tee_shm_free(shm_buf);
911free_name:
912 tee_shm_free(shm_name);
913
914 return rc;
915}
916
917static 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
965out:
966 tee_shm_free(shm_buf);
967free_name:
968 tee_shm_free(shm_name);
969
970 return rc;
971}
972#endif
973
974
975
976
977
978
979AvbOps *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
1007void 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