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_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:
656 * The TA has paniced, close the session to reload the TA
657 * for the next request.
659 tee_close_session(ops_data->tee, ops_data->session);
660 ops_data->tee = NULL;
661 return AVB_IO_RESULT_ERROR_IO;
663 return AVB_IO_RESULT_ERROR_IO;
669 * read_rollback_index() - gets the rollback index corresponding to the
670 * location of given by @out_rollback_index.
672 * @ops: contains AvbOps handlers
673 * @rollback_index_slot:
674 * @out_rollback_index: used to write a retrieved rollback index.
677 * AVB_IO_RESULT_OK, if the roolback index was retrieved
679 static AvbIOResult read_rollback_index(AvbOps *ops,
680 size_t rollback_index_slot,
681 u64 *out_rollback_index)
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__);
687 if (out_rollback_index)
688 *out_rollback_index = 0;
690 return AVB_IO_RESULT_OK;
693 struct tee_param param[2];
695 if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
696 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
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;
703 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_ROLLBACK_INDEX,
704 ARRAY_SIZE(param), param);
708 *out_rollback_index = (u64)param[1].u.value.a << 32 |
709 (u32)param[1].u.value.b;
710 return AVB_IO_RESULT_OK;
715 * write_rollback_index() - sets the rollback index corresponding to the
716 * location of given by @out_rollback_index.
718 * @ops: contains AvbOps handlers
719 * @rollback_index_slot:
720 * @rollback_index: rollback index to write.
723 * AVB_IO_RESULT_OK, if the roolback index was retrieved
725 static AvbIOResult write_rollback_index(AvbOps *ops,
726 size_t rollback_index_slot,
729 #ifndef CONFIG_OPTEE_TA_AVB
730 /* For now this is a no-op. */
731 printf("%s not supported yet\n", __func__);
733 return AVB_IO_RESULT_OK;
735 struct tee_param param[2];
737 if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
738 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
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;
747 return invoke_func(ops->user_data, TA_AVB_CMD_WRITE_ROLLBACK_INDEX,
748 ARRAY_SIZE(param), param);
753 * read_is_device_unlocked() - gets whether the device is unlocked
755 * @ops: contains AVB ops handlers
756 * @out_is_unlocked: device unlock state is stored here, true if unlocked,
760 * AVB_IO_RESULT_OK: state is retrieved successfully
761 * AVB_IO_RESULT_ERROR_IO: an error occurred
763 static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
765 #ifndef CONFIG_OPTEE_TA_AVB
766 /* For now we always return that the device is unlocked. */
768 printf("%s not supported yet\n", __func__);
770 *out_is_unlocked = true;
772 return AVB_IO_RESULT_OK;
775 struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT };
777 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_LOCK_STATE, 1, ¶m);
780 *out_is_unlocked = !param.u.value.a;
781 return AVB_IO_RESULT_OK;
786 * get_unique_guid_for_partition() - gets the GUID for a partition identified
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
796 * AVB_IO_RESULT_OK, on success (GUID found)
797 * AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
799 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
801 static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
802 const char *partition,
804 size_t guid_buf_size)
806 struct mmc_part *part;
809 part = get_partition(ops, partition);
811 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
813 uuid_size = sizeof(part->info.uuid);
814 if (uuid_size > guid_buf_size)
815 return AVB_IO_RESULT_ERROR_IO;
817 memcpy(guid_buf, part->info.uuid, uuid_size);
818 guid_buf[uuid_size - 1] = 0;
820 return AVB_IO_RESULT_OK;
824 * get_size_of_partition() - gets the size of a partition identified
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
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
836 static AvbIOResult get_size_of_partition(AvbOps *ops,
837 const char *partition,
838 u64 *out_size_num_bytes)
840 struct mmc_part *part;
842 if (!out_size_num_bytes)
843 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
845 part = get_partition(ops, partition);
847 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
849 *out_size_num_bytes = part->info.blksz * part->info.size;
851 return AVB_IO_RESULT_OK;
854 #ifdef CONFIG_OPTEE_TA_AVB
855 static AvbIOResult read_persistent_value(AvbOps *ops,
859 size_t *out_num_bytes_read)
862 struct tee_shm *shm_name;
863 struct tee_shm *shm_buf;
864 struct tee_param param[2];
866 size_t name_size = strlen(name) + 1;
868 if (get_open_session(ops->user_data))
869 return AVB_IO_RESULT_ERROR_IO;
871 tee = ((struct AvbOpsData *)ops->user_data)->tee;
873 rc = tee_shm_alloc(tee, name_size,
874 TEE_SHM_ALLOC, &shm_name);
876 return AVB_IO_RESULT_ERROR_OOM;
878 rc = tee_shm_alloc(tee, buffer_size,
879 TEE_SHM_ALLOC, &shm_buf);
881 rc = AVB_IO_RESULT_ERROR_OOM;
885 memcpy(shm_name->addr, name, name_size);
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;
895 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_PERSIST_VALUE,
900 if (param[1].u.memref.size > buffer_size) {
901 rc = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
905 *out_num_bytes_read = param[1].u.memref.size;
907 memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read);
910 tee_shm_free(shm_buf);
912 tee_shm_free(shm_name);
917 static AvbIOResult write_persistent_value(AvbOps *ops,
923 struct tee_shm *shm_name;
924 struct tee_shm *shm_buf;
925 struct tee_param param[2];
927 size_t name_size = strlen(name) + 1;
929 if (get_open_session(ops->user_data))
930 return AVB_IO_RESULT_ERROR_IO;
932 tee = ((struct AvbOpsData *)ops->user_data)->tee;
935 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
937 rc = tee_shm_alloc(tee, name_size,
938 TEE_SHM_ALLOC, &shm_name);
940 return AVB_IO_RESULT_ERROR_OOM;
942 rc = tee_shm_alloc(tee, value_size,
943 TEE_SHM_ALLOC, &shm_buf);
945 rc = AVB_IO_RESULT_ERROR_OOM;
949 memcpy(shm_name->addr, name, name_size);
950 memcpy(shm_buf->addr, value, value_size);
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;
960 rc = invoke_func(ops->user_data, TA_AVB_CMD_WRITE_PERSIST_VALUE,
966 tee_shm_free(shm_buf);
968 tee_shm_free(shm_name);
975 * ============================================================================
976 * AVB2.0 AvbOps alloc/initialisation/free
977 * ============================================================================
979 AvbOps *avb_ops_alloc(int boot_device)
981 struct AvbOpsData *ops_data;
983 ops_data = avb_calloc(sizeof(struct AvbOpsData));
987 ops_data->ops.user_data = ops_data;
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;
1001 ops_data->ops.get_size_of_partition = get_size_of_partition;
1002 ops_data->mmc_dev = boot_device;
1004 return &ops_data->ops;
1007 void avb_ops_free(AvbOps *ops)
1009 struct AvbOpsData *ops_data;
1014 ops_data = ops->user_data;
1017 #ifdef CONFIG_OPTEE_TA_AVB
1019 tee_close_session(ops_data->tee, ops_data->session);