2 * (C) Copyright 2018, Linaro Limited
4 * SPDX-License-Identifier: GPL-2.0+
7 #include <avb_verify.h>
14 #include <tee/optee_ta_avb.h>
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,
124 * ============================================================================
125 * Boot states support (GREEN, YELLOW, ORANGE, RED) and dm_verity
126 * ============================================================================
128 char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state)
130 struct AvbOpsData *data;
131 char *cmdline = NULL;
136 data = (struct AvbOpsData *)ops->user_data;
140 data->boot_state = boot_state;
141 switch (boot_state) {
143 cmdline = "androidboot.verifiedbootstate=green";
146 cmdline = "androidboot.verifiedbootstate=yellow";
149 cmdline = "androidboot.verifiedbootstate=orange";
157 char *append_cmd_line(char *cmdline_orig, char *cmdline_new)
165 cmd_line = cmdline_orig;
169 cmd_line = avb_strdupv(cmd_line, " ", cmdline_new, NULL);
174 static int avb_find_dm_args(char **args, char *str)
181 for (i = 0; i < AVB_MAX_ARGS && args[i]; ++i) {
182 if (strstr(args[i], str))
189 static char *avb_set_enforce_option(const char *cmdline, const char *option)
191 char *cmdarg[AVB_MAX_ARGS];
192 char *newargs = NULL;
196 memset(cmdarg, 0, sizeof(cmdarg));
197 cmdarg[i++] = strtok((char *)cmdline, " ");
200 cmdarg[i] = strtok(NULL, " ");
204 if (++i >= AVB_MAX_ARGS) {
205 printf("%s: Can't handle more then %d args\n",
212 i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_LOGGING);
214 cmdarg[i] = (char *)option;
216 i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_RESTART);
218 printf("%s: No verity options found\n", __func__);
222 cmdarg[i] = (char *)option;
225 for (i = 0; i <= total_args; i++)
226 newargs = append_cmd_line(newargs, cmdarg[i]);
231 char *avb_set_ignore_corruption(const char *cmdline)
233 char *newargs = NULL;
235 newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_LOGGING);
237 newargs = append_cmd_line(newargs,
238 "androidboot.veritymode=eio");
243 char *avb_set_enforce_verity(const char *cmdline)
247 newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_RESTART);
249 newargs = append_cmd_line(newargs,
250 "androidboot.veritymode=enforcing");
255 * ============================================================================
256 * IO(mmc) auxiliary functions
257 * ============================================================================
259 static unsigned long mmc_read_and_flush(struct mmc_part *part,
267 bool unaligned = is_buf_unaligned(buffer);
269 if (start < part->info.start) {
270 printf("%s: partition start out of bounds\n", __func__);
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",
280 * Reading fails on unaligned buffers, so we have to
281 * use aligned temporary buffer and then copy to destination
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;
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);
300 memcpy(buffer, tmp_buf, sectors * part->info.blksz);
305 static unsigned long mmc_write(struct mmc_part *part, lbaint_t start,
306 lbaint_t sectors, void *buffer)
310 bool unaligned = is_buf_unaligned(buffer);
312 if (start < part->info.start) {
313 printf("%s: partition start out of bounds\n", __func__);
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",
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;
328 memcpy(tmp_buf, buffer, sectors * part->info.blksz);
333 return blk_dwrite(part->mmc_blk,
334 start, sectors, tmp_buf);
337 static struct mmc_part *get_partition(AvbOps *ops, const char *partition)
342 struct mmc_part *part;
343 struct blk_desc *mmc_blk;
345 part = malloc(sizeof(struct mmc_part));
349 dev_num = get_boot_device(ops);
350 part->mmc = find_mmc_device(dev_num);
352 printf("No MMC device at slot %x\n", dev_num);
356 if (mmc_init(part->mmc)) {
357 printf("MMC initialization failed\n");
361 ret = mmc_switch_part(part->mmc, part_num);
365 mmc_blk = mmc_get_blk_desc(part->mmc);
367 printf("Error - failed to obtain block descriptor\n");
371 ret = part_get_info_by_name(mmc_blk, partition, &part->info);
373 printf("Can't find partition '%s'\n", partition);
377 part->dev_num = dev_num;
378 part->mmc_blk = mmc_blk;
386 static AvbIOResult mmc_byte_io(AvbOps *ops,
387 const char *partition,
391 size_t *out_num_read,
392 enum mmc_io_type io_type)
395 struct mmc_part *part;
396 u64 start_offset, start_sector, sectors, residue;
400 if (!partition || !buffer || io_type > IO_WRITE)
401 return AVB_IO_RESULT_ERROR_IO;
403 part = get_partition(ops, partition);
405 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
407 if (!part->info.blksz)
408 return AVB_IO_RESULT_ERROR_IO;
410 start_offset = calc_offset(part, offset);
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)
427 if (io_type == IO_READ) {
428 ret = mmc_read_and_flush(part,
434 printf("%s: read error (%ld, %lld)\n",
435 __func__, ret, start_sector);
436 return AVB_IO_RESULT_ERROR_IO;
439 * if this is not aligned at sector start,
440 * we have to adjust the tmp buffer
442 tmp_buf += (start_offset % part->info.blksz);
443 memcpy(buffer, (void *)tmp_buf, residue);
445 ret = mmc_read_and_flush(part,
451 printf("%s: read error (%ld, %lld)\n",
452 __func__, ret, start_sector);
453 return AVB_IO_RESULT_ERROR_IO;
455 memcpy((void *)tmp_buf +
456 start_offset % part->info.blksz,
459 ret = mmc_write(part, part->info.start +
460 start_sector, 1, tmp_buf);
462 printf("%s: write error (%ld, %lld)\n",
463 __func__, ret, start_sector);
464 return AVB_IO_RESULT_ERROR_IO;
470 start_offset += residue;
471 num_bytes -= residue;
476 if (io_type == IO_READ) {
477 ret = mmc_read_and_flush(part,
482 ret = mmc_write(part,
489 printf("%s: sector read error\n", __func__);
490 return AVB_IO_RESULT_ERROR_IO;
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;
500 /* Set counter for read operation */
501 if (io_type == IO_READ && out_num_read)
502 *out_num_read = io_cnt;
504 return AVB_IO_RESULT_OK;
508 * ============================================================================
510 * ============================================================================
514 * read_from_partition() - reads @num_bytes from @offset from partition
515 * identified by a string name
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
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
528 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if there is no partition with
531 static AvbIOResult read_from_partition(AvbOps *ops,
532 const char *partition_name,
533 s64 offset_from_partition,
536 size_t *out_num_read)
538 return mmc_byte_io(ops, partition_name, offset_from_partition,
539 num_bytes, buffer, out_num_read, IO_READ);
543 * write_to_partition() - writes N bytes to a partition identified by a string
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
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
559 static AvbIOResult write_to_partition(AvbOps *ops,
560 const char *partition_name,
561 s64 offset_from_partition,
565 return mmc_byte_io(ops, partition_name, offset_from_partition,
566 num_bytes, (void *)buffer, NULL, IO_WRITE);
570 * validate_vmbeta_public_key() - checks if the given public key used to sign
571 * the vbmeta partition is trusted
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:
581 * AVB_IO_RESULT_OK, if partition was found and read operation succeed
583 static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
584 const u8 *public_key_data,
585 size_t public_key_length,
587 *public_key_metadata,
589 public_key_metadata_length,
590 bool *out_key_is_trusted)
592 if (!public_key_length || !public_key_data || !out_key_is_trusted)
593 return AVB_IO_RESULT_ERROR_IO;
595 *out_key_is_trusted = false;
596 if (public_key_length != sizeof(avb_root_pub))
597 return AVB_IO_RESULT_ERROR_IO;
599 if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0)
600 *out_key_is_trusted = true;
602 return AVB_IO_RESULT_OK;
605 #ifdef CONFIG_OPTEE_TA_AVB
606 static int get_open_session(struct AvbOpsData *ops_data)
608 struct udevice *tee = NULL;
610 while (!ops_data->tee) {
611 const struct tee_optee_ta_uuid uuid = TA_AVB_UUID;
612 struct tee_open_session_arg arg;
615 tee = tee_find_device(tee, NULL, NULL, NULL);
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);
624 ops_data->session = arg.session;
631 static AvbIOResult invoke_func(struct AvbOpsData *ops_data, u32 func,
632 ulong num_param, struct tee_param *param)
634 struct tee_invoke_arg arg;
636 if (get_open_session(ops_data))
637 return AVB_IO_RESULT_ERROR_IO;
639 memset(&arg, 0, sizeof(arg));
641 arg.session = ops_data->session;
643 if (tee_invoke_func(ops_data->tee, &arg, num_param, param))
644 return AVB_IO_RESULT_ERROR_IO;
647 return AVB_IO_RESULT_OK;
648 case TEE_ERROR_OUT_OF_MEMORY:
649 return AVB_IO_RESULT_ERROR_OOM;
650 case TEE_ERROR_TARGET_DEAD:
652 * The TA has paniced, close the session to reload the TA
653 * for the next request.
655 tee_close_session(ops_data->tee, ops_data->session);
656 ops_data->tee = NULL;
657 return AVB_IO_RESULT_ERROR_IO;
659 return AVB_IO_RESULT_ERROR_IO;
665 * read_rollback_index() - gets the rollback index corresponding to the
666 * location of given by @out_rollback_index.
668 * @ops: contains AvbOps handlers
669 * @rollback_index_slot:
670 * @out_rollback_index: used to write a retrieved rollback index.
673 * AVB_IO_RESULT_OK, if the roolback index was retrieved
675 static AvbIOResult read_rollback_index(AvbOps *ops,
676 size_t rollback_index_slot,
677 u64 *out_rollback_index)
679 #ifndef CONFIG_OPTEE_TA_AVB
680 /* For now we always return 0 as the stored rollback index. */
681 printf("%s not supported yet\n", __func__);
683 if (out_rollback_index)
684 *out_rollback_index = 0;
686 return AVB_IO_RESULT_OK;
689 struct tee_param param[2];
691 if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
692 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
694 memset(param, 0, sizeof(param));
695 param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
696 param[0].u.value.a = rollback_index_slot;
697 param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;
699 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_ROLLBACK_INDEX,
700 ARRAY_SIZE(param), param);
704 *out_rollback_index = (u64)param[1].u.value.a << 32 |
705 (u32)param[1].u.value.b;
706 return AVB_IO_RESULT_OK;
711 * write_rollback_index() - sets the rollback index corresponding to the
712 * location of given by @out_rollback_index.
714 * @ops: contains AvbOps handlers
715 * @rollback_index_slot:
716 * @rollback_index: rollback index to write.
719 * AVB_IO_RESULT_OK, if the roolback index was retrieved
721 static AvbIOResult write_rollback_index(AvbOps *ops,
722 size_t rollback_index_slot,
725 #ifndef CONFIG_OPTEE_TA_AVB
726 /* For now this is a no-op. */
727 printf("%s not supported yet\n", __func__);
729 return AVB_IO_RESULT_OK;
731 struct tee_param param[2];
733 if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
734 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
736 memset(param, 0, sizeof(param));
737 param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
738 param[0].u.value.a = rollback_index_slot;
739 param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
740 param[1].u.value.a = (u32)(rollback_index >> 32);
741 param[1].u.value.b = (u32)rollback_index;
743 return invoke_func(ops->user_data, TA_AVB_CMD_WRITE_ROLLBACK_INDEX,
744 ARRAY_SIZE(param), param);
749 * read_is_device_unlocked() - gets whether the device is unlocked
751 * @ops: contains AVB ops handlers
752 * @out_is_unlocked: device unlock state is stored here, true if unlocked,
756 * AVB_IO_RESULT_OK: state is retrieved successfully
757 * AVB_IO_RESULT_ERROR_IO: an error occurred
759 static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
761 #ifndef CONFIG_OPTEE_TA_AVB
762 /* For now we always return that the device is unlocked. */
764 printf("%s not supported yet\n", __func__);
766 *out_is_unlocked = true;
768 return AVB_IO_RESULT_OK;
771 struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT };
773 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_LOCK_STATE, 1, ¶m);
776 *out_is_unlocked = !param.u.value.a;
777 return AVB_IO_RESULT_OK;
782 * get_unique_guid_for_partition() - gets the GUID for a partition identified
785 * @ops: contains AVB ops handlers
786 * @partition: partition name (NUL-terminated UTF-8 string)
787 * @guid_buf: buf, used to copy in GUID string. Example of value:
788 * 527c1c6d-6361-4593-8842-3c78fcd39219
789 * @guid_buf_size: @guid_buf buffer size
792 * AVB_IO_RESULT_OK, on success (GUID found)
793 * AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
795 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
797 static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
798 const char *partition,
800 size_t guid_buf_size)
802 struct mmc_part *part;
805 part = get_partition(ops, partition);
807 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
809 uuid_size = sizeof(part->info.uuid);
810 if (uuid_size > guid_buf_size)
811 return AVB_IO_RESULT_ERROR_IO;
813 memcpy(guid_buf, part->info.uuid, uuid_size);
814 guid_buf[uuid_size - 1] = 0;
816 return AVB_IO_RESULT_OK;
820 * get_size_of_partition() - gets the size of a partition identified
823 * @ops: contains AVB ops handlers
824 * @partition: partition name (NUL-terminated UTF-8 string)
825 * @out_size_num_bytes: returns the value of a partition size
828 * AVB_IO_RESULT_OK, on success (GUID found)
829 * AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE, out_size_num_bytes is NULL
830 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
832 static AvbIOResult get_size_of_partition(AvbOps *ops,
833 const char *partition,
834 u64 *out_size_num_bytes)
836 struct mmc_part *part;
838 if (!out_size_num_bytes)
839 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
841 part = get_partition(ops, partition);
843 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
845 *out_size_num_bytes = part->info.blksz * part->info.size;
847 return AVB_IO_RESULT_OK;
851 * ============================================================================
852 * AVB2.0 AvbOps alloc/initialisation/free
853 * ============================================================================
855 AvbOps *avb_ops_alloc(int boot_device)
857 struct AvbOpsData *ops_data;
859 ops_data = avb_calloc(sizeof(struct AvbOpsData));
863 ops_data->ops.user_data = ops_data;
865 ops_data->ops.read_from_partition = read_from_partition;
866 ops_data->ops.write_to_partition = write_to_partition;
867 ops_data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key;
868 ops_data->ops.read_rollback_index = read_rollback_index;
869 ops_data->ops.write_rollback_index = write_rollback_index;
870 ops_data->ops.read_is_device_unlocked = read_is_device_unlocked;
871 ops_data->ops.get_unique_guid_for_partition =
872 get_unique_guid_for_partition;
873 ops_data->ops.get_size_of_partition = get_size_of_partition;
874 ops_data->mmc_dev = boot_device;
876 return &ops_data->ops;
879 void avb_ops_free(AvbOps *ops)
881 struct AvbOpsData *ops_data;
886 ops_data = ops->user_data;
889 #ifdef CONFIG_OPTEE_TA_AVB
891 tee_close_session(ops_data->tee, ops_data->session);