2 * (C) Copyright 2018, Linaro Limited
4 * SPDX-License-Identifier: GPL-2.0+
7 #include <avb_verify.h>
15 #include <tee/optee_ta_avb.h>
17 static const unsigned char avb_root_pub[1032] = {
18 0x0, 0x0, 0x10, 0x0, 0x55, 0xd9, 0x4, 0xad, 0xd8, 0x4,
19 0xaf, 0xe3, 0xd3, 0x84, 0x6c, 0x7e, 0xd, 0x89, 0x3d, 0xc2,
20 0x8c, 0xd3, 0x12, 0x55, 0xe9, 0x62, 0xc9, 0xf1, 0xf, 0x5e,
21 0xcc, 0x16, 0x72, 0xab, 0x44, 0x7c, 0x2c, 0x65, 0x4a, 0x94,
22 0xb5, 0x16, 0x2b, 0x0, 0xbb, 0x6, 0xef, 0x13, 0x7, 0x53,
23 0x4c, 0xf9, 0x64, 0xb9, 0x28, 0x7a, 0x1b, 0x84, 0x98, 0x88,
24 0xd8, 0x67, 0xa4, 0x23, 0xf9, 0xa7, 0x4b, 0xdc, 0x4a, 0xf,
25 0xf7, 0x3a, 0x18, 0xae, 0x54, 0xa8, 0x15, 0xfe, 0xb0, 0xad,
26 0xac, 0x35, 0xda, 0x3b, 0xad, 0x27, 0xbc, 0xaf, 0xe8, 0xd3,
27 0x2f, 0x37, 0x34, 0xd6, 0x51, 0x2b, 0x6c, 0x5a, 0x27, 0xd7,
28 0x96, 0x6, 0xaf, 0x6b, 0xb8, 0x80, 0xca, 0xfa, 0x30, 0xb4,
29 0xb1, 0x85, 0xb3, 0x4d, 0xaa, 0xaa, 0xc3, 0x16, 0x34, 0x1a,
30 0xb8, 0xe7, 0xc7, 0xfa, 0xf9, 0x9, 0x77, 0xab, 0x97, 0x93,
31 0xeb, 0x44, 0xae, 0xcf, 0x20, 0xbc, 0xf0, 0x80, 0x11, 0xdb,
32 0x23, 0xc, 0x47, 0x71, 0xb9, 0x6d, 0xd6, 0x7b, 0x60, 0x47,
33 0x87, 0x16, 0x56, 0x93, 0xb7, 0xc2, 0x2a, 0x9a, 0xb0, 0x4c,
34 0x1, 0xc, 0x30, 0xd8, 0x93, 0x87, 0xf0, 0xed, 0x6e, 0x8b,
35 0xbe, 0x30, 0x5b, 0xf6, 0xa6, 0xaf, 0xdd, 0x80, 0x7c, 0x45,
36 0x5e, 0x8f, 0x91, 0x93, 0x5e, 0x44, 0xfe, 0xb8, 0x82, 0x7,
37 0xee, 0x79, 0xca, 0xbf, 0x31, 0x73, 0x62, 0x58, 0xe3, 0xcd,
38 0xc4, 0xbc, 0xc2, 0x11, 0x1d, 0xa1, 0x4a, 0xbf, 0xfe, 0x27,
39 0x7d, 0xa1, 0xf6, 0x35, 0xa3, 0x5e, 0xca, 0xdc, 0x57, 0x2f,
40 0x3e, 0xf0, 0xc9, 0x5d, 0x86, 0x6a, 0xf8, 0xaf, 0x66, 0xa7,
41 0xed, 0xcd, 0xb8, 0xed, 0xa1, 0x5f, 0xba, 0x9b, 0x85, 0x1a,
42 0xd5, 0x9, 0xae, 0x94, 0x4e, 0x3b, 0xcf, 0xcb, 0x5c, 0xc9,
43 0x79, 0x80, 0xf7, 0xcc, 0xa6, 0x4a, 0xa8, 0x6a, 0xd8, 0xd3,
44 0x31, 0x11, 0xf9, 0xf6, 0x2, 0x63, 0x2a, 0x1a, 0x2d, 0xd1,
45 0x1a, 0x66, 0x1b, 0x16, 0x41, 0xbd, 0xbd, 0xf7, 0x4d, 0xc0,
46 0x4a, 0xe5, 0x27, 0x49, 0x5f, 0x7f, 0x58, 0xe3, 0x27, 0x2d,
47 0xe5, 0xc9, 0x66, 0xe, 0x52, 0x38, 0x16, 0x38, 0xfb, 0x16,
48 0xeb, 0x53, 0x3f, 0xe6, 0xfd, 0xe9, 0xa2, 0x5e, 0x25, 0x59,
49 0xd8, 0x79, 0x45, 0xff, 0x3, 0x4c, 0x26, 0xa2, 0x0, 0x5a,
50 0x8e, 0xc2, 0x51, 0xa1, 0x15, 0xf9, 0x7b, 0xf4, 0x5c, 0x81,
51 0x9b, 0x18, 0x47, 0x35, 0xd8, 0x2d, 0x5, 0xe9, 0xad, 0xf,
52 0x35, 0x74, 0x15, 0xa3, 0x8e, 0x8b, 0xcc, 0x27, 0xda, 0x7c,
53 0x5d, 0xe4, 0xfa, 0x4, 0xd3, 0x5, 0xb, 0xba, 0x3a, 0xb2,
54 0x49, 0x45, 0x2f, 0x47, 0xc7, 0xd, 0x41, 0x3f, 0x97, 0x80,
55 0x4d, 0x3f, 0xc1, 0xb5, 0xbb, 0x70, 0x5f, 0xa7, 0x37, 0xaf,
56 0x48, 0x22, 0x12, 0x45, 0x2e, 0xf5, 0xf, 0x87, 0x92, 0xe2,
57 0x84, 0x1, 0xf9, 0x12, 0xf, 0x14, 0x15, 0x24, 0xce, 0x89,
58 0x99, 0xee, 0xb9, 0xc4, 0x17, 0x70, 0x70, 0x15, 0xea, 0xbe,
59 0xc6, 0x6c, 0x1f, 0x62, 0xb3, 0xf4, 0x2d, 0x16, 0x87, 0xfb,
60 0x56, 0x1e, 0x45, 0xab, 0xae, 0x32, 0xe4, 0x5e, 0x91, 0xed,
61 0x53, 0x66, 0x5e, 0xbd, 0xed, 0xad, 0xe6, 0x12, 0x39, 0xd,
62 0x83, 0xc9, 0xe8, 0x6b, 0x6c, 0x2d, 0xa5, 0xee, 0xc4, 0x5a,
63 0x66, 0xae, 0x8c, 0x97, 0xd7, 0xd, 0x6c, 0x49, 0xc7, 0xf5,
64 0xc4, 0x92, 0x31, 0x8b, 0x9, 0xee, 0x33, 0xda, 0xa9, 0x37,
65 0xb6, 0x49, 0x18, 0xf8, 0xe, 0x60, 0x45, 0xc8, 0x33, 0x91,
66 0xef, 0x20, 0x57, 0x10, 0xbe, 0x78, 0x2d, 0x83, 0x26, 0xd6,
67 0xca, 0x61, 0xf9, 0x2f, 0xe0, 0xbf, 0x5, 0x30, 0x52, 0x5a,
68 0x12, 0x1c, 0x0, 0xa7, 0x5d, 0xcc, 0x7c, 0x2e, 0xc5, 0x95,
69 0x8b, 0xa3, 0x3b, 0xf0, 0x43, 0x2e, 0x5e, 0xdd, 0x0, 0xdb,
70 0xd, 0xb3, 0x37, 0x99, 0xa9, 0xcd, 0x9c, 0xb7, 0x43, 0xf7,
71 0x35, 0x44, 0x21, 0xc2, 0x82, 0x71, 0xab, 0x8d, 0xaa, 0xb4,
72 0x41, 0x11, 0xec, 0x1e, 0x8d, 0xfc, 0x14, 0x82, 0x92, 0x4e,
73 0x83, 0x6a, 0xa, 0x6b, 0x35, 0x5e, 0x5d, 0xe9, 0x5c, 0xcc,
74 0x8c, 0xde, 0x39, 0xd1, 0x4a, 0x5b, 0x5f, 0x63, 0xa9, 0x64,
75 0xe0, 0xa, 0xcb, 0xb, 0xb8, 0x5a, 0x7c, 0xc3, 0xb, 0xe6,
76 0xbe, 0xfe, 0x8b, 0xf, 0x7d, 0x34, 0x8e, 0x2, 0x66, 0x74,
77 0x1, 0x6c, 0xca, 0x76, 0xac, 0x7c, 0x67, 0x8, 0x2f, 0x3f,
78 0x1a, 0xa6, 0x2c, 0x60, 0xb3, 0xff, 0xda, 0x8d, 0xb8, 0x12,
79 0xc, 0x0, 0x7f, 0xcc, 0x50, 0xa1, 0x5c, 0x64, 0xa1, 0xe2,
80 0x5f, 0x32, 0x65, 0xc9, 0x9c, 0xbe, 0xd6, 0xa, 0x13, 0x87,
81 0x3c, 0x2a, 0x45, 0x47, 0xc, 0xca, 0x42, 0x82, 0xfa, 0x89,
82 0x65, 0xe7, 0x89, 0xb4, 0x8f, 0xf7, 0x1e, 0xe6, 0x23, 0xa5,
83 0xd0, 0x59, 0x37, 0x79, 0x92, 0xd7, 0xce, 0x3d, 0xfd, 0xe3,
84 0xa1, 0xb, 0xcf, 0x6c, 0x85, 0xa0, 0x65, 0xf3, 0x5c, 0xc6,
85 0x4a, 0x63, 0x5f, 0x6e, 0x3a, 0x3a, 0x2a, 0x8b, 0x6a, 0xb6,
86 0x2f, 0xbb, 0xf8, 0xb2, 0x4b, 0x62, 0xbc, 0x1a, 0x91, 0x25,
87 0x66, 0xe3, 0x69, 0xca, 0x60, 0x49, 0xb, 0xf6, 0x8a, 0xbe,
88 0x3e, 0x76, 0x53, 0xc2, 0x7a, 0xa8, 0x4, 0x17, 0x75, 0xf1,
89 0xf3, 0x3, 0x62, 0x1b, 0x85, 0xb2, 0xb0, 0xef, 0x80, 0x15,
90 0xb6, 0xd4, 0x4e, 0xdf, 0x71, 0xac, 0xdb, 0x2a, 0x4, 0xd4,
91 0xb4, 0x21, 0xba, 0x65, 0x56, 0x57, 0xe8, 0xfa, 0x84, 0xa2,
92 0x7d, 0x13, 0xe, 0xaf, 0xd7, 0x9a, 0x58, 0x2a, 0xa3, 0x81,
93 0x84, 0x8d, 0x9, 0xa0, 0x6a, 0xc1, 0xbb, 0xd9, 0xf5, 0x86,
94 0xac, 0xbd, 0x75, 0x61, 0x9, 0xe6, 0x8c, 0x3d, 0x77, 0xb2,
95 0xed, 0x30, 0x20, 0xe4, 0x0, 0x1d, 0x97, 0xe8, 0xbf, 0xc7,
96 0x0, 0x1b, 0x21, 0xb1, 0x16, 0xe7, 0x41, 0x67, 0x2e, 0xec,
97 0x38, 0xbc, 0xe5, 0x1b, 0xb4, 0x6, 0x23, 0x31, 0x71, 0x1c,
98 0x49, 0xcd, 0x76, 0x4a, 0x76, 0x36, 0x8d, 0xa3, 0x89, 0x8b,
99 0x4a, 0x7a, 0xf4, 0x87, 0xc8, 0x15, 0xf, 0x37, 0x39, 0xf6,
100 0x6d, 0x80, 0x19, 0xef, 0x5c, 0xa8, 0x66, 0xce, 0x1b, 0x16,
101 0x79, 0x21, 0xdf, 0xd7, 0x31, 0x30, 0xc4, 0x21, 0xdd, 0x34,
102 0x5b, 0xd2, 0x1a, 0x2b, 0x3e, 0x5d, 0xf7, 0xea, 0xca, 0x5,
103 0x8e, 0xb7, 0xcb, 0x49, 0x2e, 0xa0, 0xe3, 0xf4, 0xa7, 0x48,
104 0x19, 0x10, 0x9c, 0x4, 0xa7, 0xf4, 0x28, 0x74, 0xc8, 0x6f,
105 0x63, 0x20, 0x2b, 0x46, 0x24, 0x26, 0x19, 0x1d, 0xd1, 0x2c,
106 0x31, 0x6d, 0x5a, 0x29, 0xa2, 0x6, 0xa6, 0xb2, 0x41, 0xcc,
107 0xa, 0x27, 0x96, 0x9, 0x96, 0xac, 0x47, 0x65, 0x78, 0x68,
108 0x51, 0x98, 0xd6, 0xd8, 0xa6, 0x2d, 0xa0, 0xcf, 0xec, 0xe2,
109 0x74, 0xf2, 0x82, 0xe3, 0x97, 0xd9, 0x7e, 0xd4, 0xf8, 0xb,
110 0x70, 0x43, 0x3d, 0xb1, 0x7b, 0x97, 0x80, 0xd6, 0xcb, 0xd7,
111 0x19, 0xbc, 0x63, 0xb, 0xfd, 0x4d, 0x88, 0xfe, 0x67, 0xac,
112 0xb8, 0xcc, 0x50, 0xb7, 0x68, 0xb3, 0x5b, 0xd6, 0x1e, 0x25,
113 0xfc, 0x5f, 0x3c, 0x8d, 0xb1, 0x33, 0x7c, 0xb3, 0x49, 0x1,
114 0x3f, 0x71, 0x55, 0xe, 0x51, 0xba, 0x61, 0x26, 0xfa, 0xea,
115 0xe5, 0xb5, 0xe8, 0xaa, 0xcf, 0xcd, 0x96, 0x9f, 0xd6, 0xc1,
116 0x5f, 0x53, 0x91, 0xad, 0x5, 0xde, 0x20, 0xe7, 0x51, 0xda,
117 0x5b, 0x95, 0x67, 0xed, 0xf4, 0xee, 0x42, 0x65, 0x70, 0x13,
118 0xb, 0x70, 0x14, 0x1c, 0xc9, 0xe0, 0x19, 0xca, 0x5f, 0xf5,
119 0x1d, 0x70, 0x4b, 0x6c, 0x6, 0x74, 0xec, 0xb5, 0x2e, 0x77,
120 0xe1, 0x74, 0xa1, 0xa3, 0x99, 0xa0, 0x85, 0x9e, 0xf1, 0xac,
125 * ============================================================================
126 * Boot states support (GREEN, YELLOW, ORANGE, RED) and dm_verity
127 * ============================================================================
129 char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state)
131 struct AvbOpsData *data;
132 char *cmdline = NULL;
137 data = (struct AvbOpsData *)ops->user_data;
141 data->boot_state = boot_state;
142 switch (boot_state) {
144 cmdline = "androidboot.verifiedbootstate=green";
147 cmdline = "androidboot.verifiedbootstate=yellow";
150 cmdline = "androidboot.verifiedbootstate=orange";
158 char *append_cmd_line(char *cmdline_orig, char *cmdline_new)
166 cmd_line = cmdline_orig;
170 cmd_line = avb_strdupv(cmd_line, " ", cmdline_new, NULL);
175 static int avb_find_dm_args(char **args, char *str)
182 for (i = 0; i < AVB_MAX_ARGS && args[i]; ++i) {
183 if (strstr(args[i], str))
190 static char *avb_set_enforce_option(const char *cmdline, const char *option)
192 char *cmdarg[AVB_MAX_ARGS];
193 char *newargs = NULL;
197 memset(cmdarg, 0, sizeof(cmdarg));
198 cmdarg[i++] = strtok((char *)cmdline, " ");
201 cmdarg[i] = strtok(NULL, " ");
205 if (++i >= AVB_MAX_ARGS) {
206 printf("%s: Can't handle more then %d args\n",
213 i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_LOGGING);
215 cmdarg[i] = (char *)option;
217 i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_RESTART);
219 printf("%s: No verity options found\n", __func__);
223 cmdarg[i] = (char *)option;
226 for (i = 0; i <= total_args; i++)
227 newargs = append_cmd_line(newargs, cmdarg[i]);
232 char *avb_set_ignore_corruption(const char *cmdline)
234 char *newargs = NULL;
236 newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_LOGGING);
238 newargs = append_cmd_line(newargs,
239 "androidboot.veritymode=eio");
244 char *avb_set_enforce_verity(const char *cmdline)
248 newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_RESTART);
250 newargs = append_cmd_line(newargs,
251 "androidboot.veritymode=enforcing");
256 * ============================================================================
257 * IO(mmc) auxiliary functions
258 * ============================================================================
260 static unsigned long mmc_read_and_flush(struct mmc_part *part,
268 bool unaligned = is_buf_unaligned(buffer);
270 if (start < part->info.start) {
271 printf("%s: partition start out of bounds\n", __func__);
274 if ((start + sectors) > (part->info.start + part->info.size)) {
275 sectors = part->info.start + part->info.size - start;
276 printf("%s: read sector aligned to partition bounds (%ld)\n",
281 * Reading fails on unaligned buffers, so we have to
282 * use aligned temporary buffer and then copy to destination
286 printf("Handling unaligned read buffer..\n");
287 tmp_buf = get_sector_buf();
288 buf_size = get_sector_buf_size();
289 if (sectors > buf_size / part->info.blksz)
290 sectors = buf_size / part->info.blksz;
295 blks = blk_dread(part->mmc_blk,
296 start, sectors, tmp_buf);
297 /* flush cache after read */
298 flush_cache((ulong)tmp_buf, sectors * part->info.blksz);
301 memcpy(buffer, tmp_buf, sectors * part->info.blksz);
306 static unsigned long mmc_write(struct mmc_part *part, lbaint_t start,
307 lbaint_t sectors, void *buffer)
311 bool unaligned = is_buf_unaligned(buffer);
313 if (start < part->info.start) {
314 printf("%s: partition start out of bounds\n", __func__);
317 if ((start + sectors) > (part->info.start + part->info.size)) {
318 sectors = part->info.start + part->info.size - start;
319 printf("%s: sector aligned to partition bounds (%ld)\n",
323 tmp_buf = get_sector_buf();
324 buf_size = get_sector_buf_size();
325 printf("Handling unaligned wrire buffer..\n");
326 if (sectors > buf_size / part->info.blksz)
327 sectors = buf_size / part->info.blksz;
329 memcpy(tmp_buf, buffer, sectors * part->info.blksz);
334 return blk_dwrite(part->mmc_blk,
335 start, sectors, tmp_buf);
338 static struct mmc_part *get_partition(AvbOps *ops, const char *partition)
343 struct mmc_part *part;
344 struct blk_desc *mmc_blk;
346 part = malloc(sizeof(struct mmc_part));
350 dev_num = get_boot_device(ops);
351 part->mmc = find_mmc_device(dev_num);
353 printf("No MMC device at slot %x\n", dev_num);
357 if (mmc_init(part->mmc)) {
358 printf("MMC initialization failed\n");
362 ret = mmc_switch_part(part->mmc, part_num);
366 mmc_blk = mmc_get_blk_desc(part->mmc);
368 printf("Error - failed to obtain block descriptor\n");
372 ret = part_get_info_by_name(mmc_blk, partition, &part->info);
374 printf("Can't find partition '%s'\n", partition);
378 part->dev_num = dev_num;
379 part->mmc_blk = mmc_blk;
387 static AvbIOResult mmc_byte_io(AvbOps *ops,
388 const char *partition,
392 size_t *out_num_read,
393 enum mmc_io_type io_type)
396 struct mmc_part *part;
397 u64 start_offset, start_sector, sectors, residue;
401 if (!partition || !buffer || io_type > IO_WRITE)
402 return AVB_IO_RESULT_ERROR_IO;
404 part = get_partition(ops, partition);
406 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
408 if (!part->info.blksz)
409 return AVB_IO_RESULT_ERROR_IO;
411 start_offset = calc_offset(part, offset);
413 start_sector = start_offset / part->info.blksz;
414 sectors = num_bytes / part->info.blksz;
415 /* handle non block-aligned reads */
416 if (start_offset % part->info.blksz ||
417 num_bytes < part->info.blksz) {
418 tmp_buf = get_sector_buf();
419 if (start_offset % part->info.blksz) {
420 residue = part->info.blksz -
421 (start_offset % part->info.blksz);
422 if (residue > num_bytes)
428 if (io_type == IO_READ) {
429 ret = mmc_read_and_flush(part,
435 printf("%s: read error (%ld, %lld)\n",
436 __func__, ret, start_sector);
437 return AVB_IO_RESULT_ERROR_IO;
440 * if this is not aligned at sector start,
441 * we have to adjust the tmp buffer
443 tmp_buf += (start_offset % part->info.blksz);
444 memcpy(buffer, (void *)tmp_buf, residue);
446 ret = mmc_read_and_flush(part,
452 printf("%s: read error (%ld, %lld)\n",
453 __func__, ret, start_sector);
454 return AVB_IO_RESULT_ERROR_IO;
456 memcpy((void *)tmp_buf +
457 start_offset % part->info.blksz,
460 ret = mmc_write(part, part->info.start +
461 start_sector, 1, tmp_buf);
463 printf("%s: write error (%ld, %lld)\n",
464 __func__, ret, start_sector);
465 return AVB_IO_RESULT_ERROR_IO;
471 start_offset += residue;
472 num_bytes -= residue;
477 if (io_type == IO_READ) {
478 ret = mmc_read_and_flush(part,
483 ret = mmc_write(part,
490 printf("%s: sector read error\n", __func__);
491 return AVB_IO_RESULT_ERROR_IO;
494 io_cnt += ret * part->info.blksz;
495 buffer += ret * part->info.blksz;
496 start_offset += ret * part->info.blksz;
497 num_bytes -= ret * part->info.blksz;
501 /* Set counter for read operation */
502 if (io_type == IO_READ && out_num_read)
503 *out_num_read = io_cnt;
505 return AVB_IO_RESULT_OK;
509 * ============================================================================
511 * ============================================================================
515 * read_from_partition() - reads @num_bytes from @offset from partition
516 * identified by a string name
518 * @ops: contains AVB ops handlers
519 * @partition_name: partition name, NUL-terminated UTF-8 string
520 * @offset: offset from the beginning of partition
521 * @num_bytes: amount of bytes to read
522 * @buffer: destination buffer to store data
526 * AVB_IO_RESULT_OK, if partition was found and read operation succeed
527 * AVB_IO_RESULT_ERROR_IO, if i/o error occurred from the underlying i/o
529 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if there is no partition with
532 static AvbIOResult read_from_partition(AvbOps *ops,
533 const char *partition_name,
534 s64 offset_from_partition,
537 size_t *out_num_read)
539 return mmc_byte_io(ops, partition_name, offset_from_partition,
540 num_bytes, buffer, out_num_read, IO_READ);
544 * write_to_partition() - writes N bytes to a partition identified by a string
547 * @ops: AvbOps, contains AVB ops handlers
548 * @partition_name: partition name
549 * @offset_from_partition: offset from the beginning of partition
550 * @num_bytes: amount of bytes to write
551 * @buf: data to write
555 * AVB_IO_RESULT_OK, if partition was found and read operation succeed
556 * AVB_IO_RESULT_ERROR_IO, if input/output error occurred
557 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition, specified in
558 * @partition_name was not found
560 static AvbIOResult write_to_partition(AvbOps *ops,
561 const char *partition_name,
562 s64 offset_from_partition,
566 return mmc_byte_io(ops, partition_name, offset_from_partition,
567 num_bytes, (void *)buffer, NULL, IO_WRITE);
571 * validate_vmbeta_public_key() - checks if the given public key used to sign
572 * the vbmeta partition is trusted
574 * @ops: AvbOps, contains AVB ops handlers
575 * @public_key_data: public key for verifying vbmeta partition signature
576 * @public_key_length: length of public key
577 * @public_key_metadata:
578 * @public_key_metadata_length:
579 * @out_key_is_trusted:
582 * AVB_IO_RESULT_OK, if partition was found and read operation succeed
584 static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
585 const u8 *public_key_data,
586 size_t public_key_length,
588 *public_key_metadata,
590 public_key_metadata_length,
591 bool *out_key_is_trusted)
593 if (!public_key_length || !public_key_data || !out_key_is_trusted)
594 return AVB_IO_RESULT_ERROR_IO;
596 *out_key_is_trusted = false;
597 if (public_key_length != sizeof(avb_root_pub))
598 return AVB_IO_RESULT_ERROR_IO;
600 if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0)
601 *out_key_is_trusted = true;
603 return AVB_IO_RESULT_OK;
606 #ifdef CONFIG_OPTEE_TA_AVB
607 static int get_open_session(struct AvbOpsData *ops_data)
609 struct udevice *tee = NULL;
611 while (!ops_data->tee) {
612 const struct tee_optee_ta_uuid uuid = TA_AVB_UUID;
613 struct tee_open_session_arg arg;
616 tee = tee_find_device(tee, NULL, NULL, NULL);
620 memset(&arg, 0, sizeof(arg));
621 tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
622 rc = tee_open_session(tee, &arg, 0, NULL);
625 ops_data->session = arg.session;
632 static AvbIOResult invoke_func(struct AvbOpsData *ops_data, u32 func,
633 ulong num_param, struct tee_param *param)
635 struct tee_invoke_arg arg;
637 if (get_open_session(ops_data))
638 return AVB_IO_RESULT_ERROR_IO;
640 memset(&arg, 0, sizeof(arg));
642 arg.session = ops_data->session;
644 if (tee_invoke_func(ops_data->tee, &arg, num_param, param))
645 return AVB_IO_RESULT_ERROR_IO;
648 return AVB_IO_RESULT_OK;
649 case TEE_ERROR_OUT_OF_MEMORY:
650 return AVB_IO_RESULT_ERROR_OOM;
651 case TEE_ERROR_STORAGE_NO_SPACE:
652 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
653 case TEE_ERROR_ITEM_NOT_FOUND:
654 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
655 case TEE_ERROR_TARGET_DEAD:
657 * The TA has paniced, close the session to reload the TA
658 * for the next request.
660 tee_close_session(ops_data->tee, ops_data->session);
661 ops_data->tee = NULL;
662 return AVB_IO_RESULT_ERROR_IO;
664 return AVB_IO_RESULT_ERROR_IO;
670 * read_rollback_index() - gets the rollback index corresponding to the
671 * location of given by @out_rollback_index.
673 * @ops: contains AvbOps handlers
674 * @rollback_index_slot:
675 * @out_rollback_index: used to write a retrieved rollback index.
678 * AVB_IO_RESULT_OK, if the roolback index was retrieved
680 static AvbIOResult read_rollback_index(AvbOps *ops,
681 size_t rollback_index_slot,
682 u64 *out_rollback_index)
684 #ifndef CONFIG_OPTEE_TA_AVB
685 /* For now we always return 0 as the stored rollback index. */
686 printf("%s not supported yet\n", __func__);
688 if (out_rollback_index)
689 *out_rollback_index = 0;
691 return AVB_IO_RESULT_OK;
694 struct tee_param param[2];
696 if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
697 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
699 memset(param, 0, sizeof(param));
700 param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
701 param[0].u.value.a = rollback_index_slot;
702 param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;
704 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_ROLLBACK_INDEX,
705 ARRAY_SIZE(param), param);
709 *out_rollback_index = (u64)param[1].u.value.a << 32 |
710 (u32)param[1].u.value.b;
711 return AVB_IO_RESULT_OK;
716 * write_rollback_index() - sets the rollback index corresponding to the
717 * location of given by @out_rollback_index.
719 * @ops: contains AvbOps handlers
720 * @rollback_index_slot:
721 * @rollback_index: rollback index to write.
724 * AVB_IO_RESULT_OK, if the roolback index was retrieved
726 static AvbIOResult write_rollback_index(AvbOps *ops,
727 size_t rollback_index_slot,
730 #ifndef CONFIG_OPTEE_TA_AVB
731 /* For now this is a no-op. */
732 printf("%s not supported yet\n", __func__);
734 return AVB_IO_RESULT_OK;
736 struct tee_param param[2];
738 if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
739 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
741 memset(param, 0, sizeof(param));
742 param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
743 param[0].u.value.a = rollback_index_slot;
744 param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
745 param[1].u.value.a = (u32)(rollback_index >> 32);
746 param[1].u.value.b = (u32)rollback_index;
748 return invoke_func(ops->user_data, TA_AVB_CMD_WRITE_ROLLBACK_INDEX,
749 ARRAY_SIZE(param), param);
754 * read_is_device_unlocked() - gets whether the device is unlocked
756 * @ops: contains AVB ops handlers
757 * @out_is_unlocked: device unlock state is stored here, true if unlocked,
761 * AVB_IO_RESULT_OK: state is retrieved successfully
762 * AVB_IO_RESULT_ERROR_IO: an error occurred
764 static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
766 #ifndef CONFIG_OPTEE_TA_AVB
767 /* For now we always return that the device is unlocked. */
769 printf("%s not supported yet\n", __func__);
771 *out_is_unlocked = true;
773 return AVB_IO_RESULT_OK;
776 struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT };
778 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_LOCK_STATE, 1, ¶m);
781 *out_is_unlocked = !param.u.value.a;
782 return AVB_IO_RESULT_OK;
787 * get_unique_guid_for_partition() - gets the GUID for a partition identified
790 * @ops: contains AVB ops handlers
791 * @partition: partition name (NUL-terminated UTF-8 string)
792 * @guid_buf: buf, used to copy in GUID string. Example of value:
793 * 527c1c6d-6361-4593-8842-3c78fcd39219
794 * @guid_buf_size: @guid_buf buffer size
797 * AVB_IO_RESULT_OK, on success (GUID found)
798 * AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
800 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
802 static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
803 const char *partition,
805 size_t guid_buf_size)
807 struct mmc_part *part;
810 part = get_partition(ops, partition);
812 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
814 uuid_size = sizeof(part->info.uuid);
815 if (uuid_size > guid_buf_size)
816 return AVB_IO_RESULT_ERROR_IO;
818 memcpy(guid_buf, part->info.uuid, uuid_size);
819 guid_buf[uuid_size - 1] = 0;
821 return AVB_IO_RESULT_OK;
825 * get_size_of_partition() - gets the size of a partition identified
828 * @ops: contains AVB ops handlers
829 * @partition: partition name (NUL-terminated UTF-8 string)
830 * @out_size_num_bytes: returns the value of a partition size
833 * AVB_IO_RESULT_OK, on success (GUID found)
834 * AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE, out_size_num_bytes is NULL
835 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
837 static AvbIOResult get_size_of_partition(AvbOps *ops,
838 const char *partition,
839 u64 *out_size_num_bytes)
841 struct mmc_part *part;
843 if (!out_size_num_bytes)
844 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
846 part = get_partition(ops, partition);
848 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
850 *out_size_num_bytes = part->info.blksz * part->info.size;
852 return AVB_IO_RESULT_OK;
855 #ifdef CONFIG_OPTEE_TA_AVB
856 static AvbIOResult read_persistent_value(AvbOps *ops,
860 size_t *out_num_bytes_read)
863 struct tee_shm *shm_name;
864 struct tee_shm *shm_buf;
865 struct tee_param param[2];
867 size_t name_size = strlen(name) + 1;
869 if (get_open_session(ops->user_data))
870 return AVB_IO_RESULT_ERROR_IO;
872 tee = ((struct AvbOpsData *)ops->user_data)->tee;
874 rc = tee_shm_alloc(tee, name_size,
875 TEE_SHM_ALLOC, &shm_name);
877 return AVB_IO_RESULT_ERROR_OOM;
879 rc = tee_shm_alloc(tee, buffer_size,
880 TEE_SHM_ALLOC, &shm_buf);
882 rc = AVB_IO_RESULT_ERROR_OOM;
886 memcpy(shm_name->addr, name, name_size);
888 memset(param, 0, sizeof(param));
889 param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
890 param[0].u.memref.shm = shm_name;
891 param[0].u.memref.size = name_size;
892 param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
893 param[1].u.memref.shm = shm_buf;
894 param[1].u.memref.size = buffer_size;
896 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_PERSIST_VALUE,
901 if (param[1].u.memref.size > buffer_size) {
902 rc = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
906 *out_num_bytes_read = param[1].u.memref.size;
908 memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read);
911 tee_shm_free(shm_buf);
913 tee_shm_free(shm_name);
918 static AvbIOResult write_persistent_value(AvbOps *ops,
924 struct tee_shm *shm_name;
925 struct tee_shm *shm_buf;
926 struct tee_param param[2];
928 size_t name_size = strlen(name) + 1;
930 if (get_open_session(ops->user_data))
931 return AVB_IO_RESULT_ERROR_IO;
933 tee = ((struct AvbOpsData *)ops->user_data)->tee;
936 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
938 rc = tee_shm_alloc(tee, name_size,
939 TEE_SHM_ALLOC, &shm_name);
941 return AVB_IO_RESULT_ERROR_OOM;
943 rc = tee_shm_alloc(tee, value_size,
944 TEE_SHM_ALLOC, &shm_buf);
946 rc = AVB_IO_RESULT_ERROR_OOM;
950 memcpy(shm_name->addr, name, name_size);
951 memcpy(shm_buf->addr, value, value_size);
953 memset(param, 0, sizeof(param));
954 param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
955 param[0].u.memref.shm = shm_name;
956 param[0].u.memref.size = name_size;
957 param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
958 param[1].u.memref.shm = shm_buf;
959 param[1].u.memref.size = value_size;
961 rc = invoke_func(ops->user_data, TA_AVB_CMD_WRITE_PERSIST_VALUE,
967 tee_shm_free(shm_buf);
969 tee_shm_free(shm_name);
976 * ============================================================================
977 * AVB2.0 AvbOps alloc/initialisation/free
978 * ============================================================================
980 AvbOps *avb_ops_alloc(int boot_device)
982 struct AvbOpsData *ops_data;
984 ops_data = avb_calloc(sizeof(struct AvbOpsData));
988 ops_data->ops.user_data = ops_data;
990 ops_data->ops.read_from_partition = read_from_partition;
991 ops_data->ops.write_to_partition = write_to_partition;
992 ops_data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key;
993 ops_data->ops.read_rollback_index = read_rollback_index;
994 ops_data->ops.write_rollback_index = write_rollback_index;
995 ops_data->ops.read_is_device_unlocked = read_is_device_unlocked;
996 ops_data->ops.get_unique_guid_for_partition =
997 get_unique_guid_for_partition;
998 #ifdef CONFIG_OPTEE_TA_AVB
999 ops_data->ops.write_persistent_value = write_persistent_value;
1000 ops_data->ops.read_persistent_value = read_persistent_value;
1002 ops_data->ops.get_size_of_partition = get_size_of_partition;
1003 ops_data->mmc_dev = boot_device;
1005 return &ops_data->ops;
1008 void avb_ops_free(AvbOps *ops)
1010 struct AvbOpsData *ops_data;
1015 ops_data = ops->user_data;
1018 #ifdef CONFIG_OPTEE_TA_AVB
1020 tee_close_session(ops_data->tee, ops_data->session);