1 // SPDX-License-Identifier: GPL-2.0+
3 * (C) Copyright 2018, Linaro Limited
6 #include <avb_verify.h>
13 #include <tee/optee_ta_avb.h>
15 static const unsigned char avb_root_pub[1032] = {
16 0x0, 0x0, 0x10, 0x0, 0x55, 0xd9, 0x4, 0xad, 0xd8, 0x4,
17 0xaf, 0xe3, 0xd3, 0x84, 0x6c, 0x7e, 0xd, 0x89, 0x3d, 0xc2,
18 0x8c, 0xd3, 0x12, 0x55, 0xe9, 0x62, 0xc9, 0xf1, 0xf, 0x5e,
19 0xcc, 0x16, 0x72, 0xab, 0x44, 0x7c, 0x2c, 0x65, 0x4a, 0x94,
20 0xb5, 0x16, 0x2b, 0x0, 0xbb, 0x6, 0xef, 0x13, 0x7, 0x53,
21 0x4c, 0xf9, 0x64, 0xb9, 0x28, 0x7a, 0x1b, 0x84, 0x98, 0x88,
22 0xd8, 0x67, 0xa4, 0x23, 0xf9, 0xa7, 0x4b, 0xdc, 0x4a, 0xf,
23 0xf7, 0x3a, 0x18, 0xae, 0x54, 0xa8, 0x15, 0xfe, 0xb0, 0xad,
24 0xac, 0x35, 0xda, 0x3b, 0xad, 0x27, 0xbc, 0xaf, 0xe8, 0xd3,
25 0x2f, 0x37, 0x34, 0xd6, 0x51, 0x2b, 0x6c, 0x5a, 0x27, 0xd7,
26 0x96, 0x6, 0xaf, 0x6b, 0xb8, 0x80, 0xca, 0xfa, 0x30, 0xb4,
27 0xb1, 0x85, 0xb3, 0x4d, 0xaa, 0xaa, 0xc3, 0x16, 0x34, 0x1a,
28 0xb8, 0xe7, 0xc7, 0xfa, 0xf9, 0x9, 0x77, 0xab, 0x97, 0x93,
29 0xeb, 0x44, 0xae, 0xcf, 0x20, 0xbc, 0xf0, 0x80, 0x11, 0xdb,
30 0x23, 0xc, 0x47, 0x71, 0xb9, 0x6d, 0xd6, 0x7b, 0x60, 0x47,
31 0x87, 0x16, 0x56, 0x93, 0xb7, 0xc2, 0x2a, 0x9a, 0xb0, 0x4c,
32 0x1, 0xc, 0x30, 0xd8, 0x93, 0x87, 0xf0, 0xed, 0x6e, 0x8b,
33 0xbe, 0x30, 0x5b, 0xf6, 0xa6, 0xaf, 0xdd, 0x80, 0x7c, 0x45,
34 0x5e, 0x8f, 0x91, 0x93, 0x5e, 0x44, 0xfe, 0xb8, 0x82, 0x7,
35 0xee, 0x79, 0xca, 0xbf, 0x31, 0x73, 0x62, 0x58, 0xe3, 0xcd,
36 0xc4, 0xbc, 0xc2, 0x11, 0x1d, 0xa1, 0x4a, 0xbf, 0xfe, 0x27,
37 0x7d, 0xa1, 0xf6, 0x35, 0xa3, 0x5e, 0xca, 0xdc, 0x57, 0x2f,
38 0x3e, 0xf0, 0xc9, 0x5d, 0x86, 0x6a, 0xf8, 0xaf, 0x66, 0xa7,
39 0xed, 0xcd, 0xb8, 0xed, 0xa1, 0x5f, 0xba, 0x9b, 0x85, 0x1a,
40 0xd5, 0x9, 0xae, 0x94, 0x4e, 0x3b, 0xcf, 0xcb, 0x5c, 0xc9,
41 0x79, 0x80, 0xf7, 0xcc, 0xa6, 0x4a, 0xa8, 0x6a, 0xd8, 0xd3,
42 0x31, 0x11, 0xf9, 0xf6, 0x2, 0x63, 0x2a, 0x1a, 0x2d, 0xd1,
43 0x1a, 0x66, 0x1b, 0x16, 0x41, 0xbd, 0xbd, 0xf7, 0x4d, 0xc0,
44 0x4a, 0xe5, 0x27, 0x49, 0x5f, 0x7f, 0x58, 0xe3, 0x27, 0x2d,
45 0xe5, 0xc9, 0x66, 0xe, 0x52, 0x38, 0x16, 0x38, 0xfb, 0x16,
46 0xeb, 0x53, 0x3f, 0xe6, 0xfd, 0xe9, 0xa2, 0x5e, 0x25, 0x59,
47 0xd8, 0x79, 0x45, 0xff, 0x3, 0x4c, 0x26, 0xa2, 0x0, 0x5a,
48 0x8e, 0xc2, 0x51, 0xa1, 0x15, 0xf9, 0x7b, 0xf4, 0x5c, 0x81,
49 0x9b, 0x18, 0x47, 0x35, 0xd8, 0x2d, 0x5, 0xe9, 0xad, 0xf,
50 0x35, 0x74, 0x15, 0xa3, 0x8e, 0x8b, 0xcc, 0x27, 0xda, 0x7c,
51 0x5d, 0xe4, 0xfa, 0x4, 0xd3, 0x5, 0xb, 0xba, 0x3a, 0xb2,
52 0x49, 0x45, 0x2f, 0x47, 0xc7, 0xd, 0x41, 0x3f, 0x97, 0x80,
53 0x4d, 0x3f, 0xc1, 0xb5, 0xbb, 0x70, 0x5f, 0xa7, 0x37, 0xaf,
54 0x48, 0x22, 0x12, 0x45, 0x2e, 0xf5, 0xf, 0x87, 0x92, 0xe2,
55 0x84, 0x1, 0xf9, 0x12, 0xf, 0x14, 0x15, 0x24, 0xce, 0x89,
56 0x99, 0xee, 0xb9, 0xc4, 0x17, 0x70, 0x70, 0x15, 0xea, 0xbe,
57 0xc6, 0x6c, 0x1f, 0x62, 0xb3, 0xf4, 0x2d, 0x16, 0x87, 0xfb,
58 0x56, 0x1e, 0x45, 0xab, 0xae, 0x32, 0xe4, 0x5e, 0x91, 0xed,
59 0x53, 0x66, 0x5e, 0xbd, 0xed, 0xad, 0xe6, 0x12, 0x39, 0xd,
60 0x83, 0xc9, 0xe8, 0x6b, 0x6c, 0x2d, 0xa5, 0xee, 0xc4, 0x5a,
61 0x66, 0xae, 0x8c, 0x97, 0xd7, 0xd, 0x6c, 0x49, 0xc7, 0xf5,
62 0xc4, 0x92, 0x31, 0x8b, 0x9, 0xee, 0x33, 0xda, 0xa9, 0x37,
63 0xb6, 0x49, 0x18, 0xf8, 0xe, 0x60, 0x45, 0xc8, 0x33, 0x91,
64 0xef, 0x20, 0x57, 0x10, 0xbe, 0x78, 0x2d, 0x83, 0x26, 0xd6,
65 0xca, 0x61, 0xf9, 0x2f, 0xe0, 0xbf, 0x5, 0x30, 0x52, 0x5a,
66 0x12, 0x1c, 0x0, 0xa7, 0x5d, 0xcc, 0x7c, 0x2e, 0xc5, 0x95,
67 0x8b, 0xa3, 0x3b, 0xf0, 0x43, 0x2e, 0x5e, 0xdd, 0x0, 0xdb,
68 0xd, 0xb3, 0x37, 0x99, 0xa9, 0xcd, 0x9c, 0xb7, 0x43, 0xf7,
69 0x35, 0x44, 0x21, 0xc2, 0x82, 0x71, 0xab, 0x8d, 0xaa, 0xb4,
70 0x41, 0x11, 0xec, 0x1e, 0x8d, 0xfc, 0x14, 0x82, 0x92, 0x4e,
71 0x83, 0x6a, 0xa, 0x6b, 0x35, 0x5e, 0x5d, 0xe9, 0x5c, 0xcc,
72 0x8c, 0xde, 0x39, 0xd1, 0x4a, 0x5b, 0x5f, 0x63, 0xa9, 0x64,
73 0xe0, 0xa, 0xcb, 0xb, 0xb8, 0x5a, 0x7c, 0xc3, 0xb, 0xe6,
74 0xbe, 0xfe, 0x8b, 0xf, 0x7d, 0x34, 0x8e, 0x2, 0x66, 0x74,
75 0x1, 0x6c, 0xca, 0x76, 0xac, 0x7c, 0x67, 0x8, 0x2f, 0x3f,
76 0x1a, 0xa6, 0x2c, 0x60, 0xb3, 0xff, 0xda, 0x8d, 0xb8, 0x12,
77 0xc, 0x0, 0x7f, 0xcc, 0x50, 0xa1, 0x5c, 0x64, 0xa1, 0xe2,
78 0x5f, 0x32, 0x65, 0xc9, 0x9c, 0xbe, 0xd6, 0xa, 0x13, 0x87,
79 0x3c, 0x2a, 0x45, 0x47, 0xc, 0xca, 0x42, 0x82, 0xfa, 0x89,
80 0x65, 0xe7, 0x89, 0xb4, 0x8f, 0xf7, 0x1e, 0xe6, 0x23, 0xa5,
81 0xd0, 0x59, 0x37, 0x79, 0x92, 0xd7, 0xce, 0x3d, 0xfd, 0xe3,
82 0xa1, 0xb, 0xcf, 0x6c, 0x85, 0xa0, 0x65, 0xf3, 0x5c, 0xc6,
83 0x4a, 0x63, 0x5f, 0x6e, 0x3a, 0x3a, 0x2a, 0x8b, 0x6a, 0xb6,
84 0x2f, 0xbb, 0xf8, 0xb2, 0x4b, 0x62, 0xbc, 0x1a, 0x91, 0x25,
85 0x66, 0xe3, 0x69, 0xca, 0x60, 0x49, 0xb, 0xf6, 0x8a, 0xbe,
86 0x3e, 0x76, 0x53, 0xc2, 0x7a, 0xa8, 0x4, 0x17, 0x75, 0xf1,
87 0xf3, 0x3, 0x62, 0x1b, 0x85, 0xb2, 0xb0, 0xef, 0x80, 0x15,
88 0xb6, 0xd4, 0x4e, 0xdf, 0x71, 0xac, 0xdb, 0x2a, 0x4, 0xd4,
89 0xb4, 0x21, 0xba, 0x65, 0x56, 0x57, 0xe8, 0xfa, 0x84, 0xa2,
90 0x7d, 0x13, 0xe, 0xaf, 0xd7, 0x9a, 0x58, 0x2a, 0xa3, 0x81,
91 0x84, 0x8d, 0x9, 0xa0, 0x6a, 0xc1, 0xbb, 0xd9, 0xf5, 0x86,
92 0xac, 0xbd, 0x75, 0x61, 0x9, 0xe6, 0x8c, 0x3d, 0x77, 0xb2,
93 0xed, 0x30, 0x20, 0xe4, 0x0, 0x1d, 0x97, 0xe8, 0xbf, 0xc7,
94 0x0, 0x1b, 0x21, 0xb1, 0x16, 0xe7, 0x41, 0x67, 0x2e, 0xec,
95 0x38, 0xbc, 0xe5, 0x1b, 0xb4, 0x6, 0x23, 0x31, 0x71, 0x1c,
96 0x49, 0xcd, 0x76, 0x4a, 0x76, 0x36, 0x8d, 0xa3, 0x89, 0x8b,
97 0x4a, 0x7a, 0xf4, 0x87, 0xc8, 0x15, 0xf, 0x37, 0x39, 0xf6,
98 0x6d, 0x80, 0x19, 0xef, 0x5c, 0xa8, 0x66, 0xce, 0x1b, 0x16,
99 0x79, 0x21, 0xdf, 0xd7, 0x31, 0x30, 0xc4, 0x21, 0xdd, 0x34,
100 0x5b, 0xd2, 0x1a, 0x2b, 0x3e, 0x5d, 0xf7, 0xea, 0xca, 0x5,
101 0x8e, 0xb7, 0xcb, 0x49, 0x2e, 0xa0, 0xe3, 0xf4, 0xa7, 0x48,
102 0x19, 0x10, 0x9c, 0x4, 0xa7, 0xf4, 0x28, 0x74, 0xc8, 0x6f,
103 0x63, 0x20, 0x2b, 0x46, 0x24, 0x26, 0x19, 0x1d, 0xd1, 0x2c,
104 0x31, 0x6d, 0x5a, 0x29, 0xa2, 0x6, 0xa6, 0xb2, 0x41, 0xcc,
105 0xa, 0x27, 0x96, 0x9, 0x96, 0xac, 0x47, 0x65, 0x78, 0x68,
106 0x51, 0x98, 0xd6, 0xd8, 0xa6, 0x2d, 0xa0, 0xcf, 0xec, 0xe2,
107 0x74, 0xf2, 0x82, 0xe3, 0x97, 0xd9, 0x7e, 0xd4, 0xf8, 0xb,
108 0x70, 0x43, 0x3d, 0xb1, 0x7b, 0x97, 0x80, 0xd6, 0xcb, 0xd7,
109 0x19, 0xbc, 0x63, 0xb, 0xfd, 0x4d, 0x88, 0xfe, 0x67, 0xac,
110 0xb8, 0xcc, 0x50, 0xb7, 0x68, 0xb3, 0x5b, 0xd6, 0x1e, 0x25,
111 0xfc, 0x5f, 0x3c, 0x8d, 0xb1, 0x33, 0x7c, 0xb3, 0x49, 0x1,
112 0x3f, 0x71, 0x55, 0xe, 0x51, 0xba, 0x61, 0x26, 0xfa, 0xea,
113 0xe5, 0xb5, 0xe8, 0xaa, 0xcf, 0xcd, 0x96, 0x9f, 0xd6, 0xc1,
114 0x5f, 0x53, 0x91, 0xad, 0x5, 0xde, 0x20, 0xe7, 0x51, 0xda,
115 0x5b, 0x95, 0x67, 0xed, 0xf4, 0xee, 0x42, 0x65, 0x70, 0x13,
116 0xb, 0x70, 0x14, 0x1c, 0xc9, 0xe0, 0x19, 0xca, 0x5f, 0xf5,
117 0x1d, 0x70, 0x4b, 0x6c, 0x6, 0x74, 0xec, 0xb5, 0x2e, 0x77,
118 0xe1, 0x74, 0xa1, 0xa3, 0x99, 0xa0, 0x85, 0x9e, 0xf1, 0xac,
122 const char *str_avb_io_error(AvbIOResult res)
125 case AVB_IO_RESULT_OK:
126 return "Requested operation was successful";
127 case AVB_IO_RESULT_ERROR_IO:
128 return "Underlying hardware encountered an I/O error";
129 case AVB_IO_RESULT_ERROR_OOM:
130 return "Unable to allocate memory";
131 case AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION:
132 return "Requested partition does not exist";
133 case AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION:
134 return "Bytes requested is outside the range of partition";
135 case AVB_IO_RESULT_ERROR_NO_SUCH_VALUE:
136 return "Named persistent value does not exist";
137 case AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE:
138 return "Named persistent value size is not supported";
139 case AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE:
140 return "Buffer is too small for the requested operation";
142 return "Unknown AVB error";
146 const char *str_avb_slot_error(AvbSlotVerifyResult res)
149 case AVB_SLOT_VERIFY_RESULT_OK:
150 return "Verification passed successfully";
151 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
152 return "Allocation of memory failed";
153 case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
154 return "I/O error occurred while trying to load data";
155 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
156 return "Digest didn't match or signature checks failed";
157 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
158 return "Rollback index is less than its stored value";
159 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
160 return "Public keys are not accepted";
161 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
162 return "Metadata is invalid or inconsistent";
163 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
164 return "Metadata requires a newer version of libavb";
165 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
166 return "Invalid arguments are used";
168 return "Unknown AVB slot verification error";
172 * ============================================================================
173 * Boot states support (GREEN, YELLOW, ORANGE, RED) and dm_verity
174 * ============================================================================
176 char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state)
178 struct AvbOpsData *data;
179 char *cmdline = NULL;
184 data = (struct AvbOpsData *)ops->user_data;
188 data->boot_state = boot_state;
189 switch (boot_state) {
191 cmdline = "androidboot.verifiedbootstate=green";
194 cmdline = "androidboot.verifiedbootstate=yellow";
197 cmdline = "androidboot.verifiedbootstate=orange";
205 char *append_cmd_line(char *cmdline_orig, char *cmdline_new)
213 cmd_line = cmdline_orig;
217 cmd_line = avb_strdupv(cmd_line, " ", cmdline_new, NULL);
222 static int avb_find_dm_args(char **args, char *str)
229 for (i = 0; i < AVB_MAX_ARGS && args[i]; ++i) {
230 if (strstr(args[i], str))
237 static char *avb_set_enforce_option(const char *cmdline, const char *option)
239 char *cmdarg[AVB_MAX_ARGS];
240 char *newargs = NULL;
244 memset(cmdarg, 0, sizeof(cmdarg));
245 cmdarg[i++] = strtok((char *)cmdline, " ");
248 cmdarg[i] = strtok(NULL, " ");
252 if (++i >= AVB_MAX_ARGS) {
253 printf("%s: Can't handle more then %d args\n",
260 i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_LOGGING);
262 cmdarg[i] = (char *)option;
264 i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_RESTART);
266 printf("%s: No verity options found\n", __func__);
270 cmdarg[i] = (char *)option;
273 for (i = 0; i <= total_args; i++)
274 newargs = append_cmd_line(newargs, cmdarg[i]);
279 char *avb_set_ignore_corruption(const char *cmdline)
281 char *newargs = NULL;
283 newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_LOGGING);
285 newargs = append_cmd_line(newargs,
286 "androidboot.veritymode=eio");
291 char *avb_set_enforce_verity(const char *cmdline)
295 newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_RESTART);
297 newargs = append_cmd_line(newargs,
298 "androidboot.veritymode=enforcing");
303 * ============================================================================
304 * IO(mmc) auxiliary functions
305 * ============================================================================
307 static unsigned long mmc_read_and_flush(struct mmc_part *part,
315 bool unaligned = is_buf_unaligned(buffer);
317 if (start < part->info.start) {
318 printf("%s: partition start out of bounds\n", __func__);
321 if ((start + sectors) > (part->info.start + part->info.size)) {
322 sectors = part->info.start + part->info.size - start;
323 printf("%s: read sector aligned to partition bounds (%ld)\n",
328 * Reading fails on unaligned buffers, so we have to
329 * use aligned temporary buffer and then copy to destination
332 debug("%s: handling unaligned read buffer, addr = 0x%p\n",
334 tmp_buf = get_sector_buf();
335 buf_size = get_sector_buf_size();
336 if (sectors > buf_size / part->info.blksz)
337 sectors = buf_size / part->info.blksz;
342 blks = blk_dread(part->mmc_blk,
343 start, sectors, tmp_buf);
344 /* flush cache after read */
345 flush_cache((ulong)tmp_buf, sectors * part->info.blksz);
348 memcpy(buffer, tmp_buf, sectors * part->info.blksz);
353 static unsigned long mmc_write(struct mmc_part *part, lbaint_t start,
354 lbaint_t sectors, void *buffer)
358 bool unaligned = is_buf_unaligned(buffer);
360 if (start < part->info.start) {
361 printf("%s: partition start out of bounds\n", __func__);
364 if ((start + sectors) > (part->info.start + part->info.size)) {
365 sectors = part->info.start + part->info.size - start;
366 printf("%s: sector aligned to partition bounds (%ld)\n",
370 tmp_buf = get_sector_buf();
371 buf_size = get_sector_buf_size();
372 debug("%s: handling unaligned read buffer, addr = 0x%p\n",
374 if (sectors > buf_size / part->info.blksz)
375 sectors = buf_size / part->info.blksz;
377 memcpy(tmp_buf, buffer, sectors * part->info.blksz);
382 return blk_dwrite(part->mmc_blk,
383 start, sectors, tmp_buf);
386 static struct mmc_part *get_partition(AvbOps *ops, const char *partition)
391 struct mmc_part *part;
392 struct blk_desc *mmc_blk;
394 part = malloc(sizeof(struct mmc_part));
398 dev_num = get_boot_device(ops);
399 part->mmc = find_mmc_device(dev_num);
401 printf("%s: no MMC device at slot %x\n", __func__, dev_num);
405 ret = mmc_init(part->mmc);
407 printf("%s: MMC initialization failed, err = %d\n",
412 if (IS_MMC(part->mmc)) {
413 ret = mmc_switch_part(part->mmc, part_num);
415 printf("%s: MMC part switch failed, err = %d\n",
421 mmc_blk = mmc_get_blk_desc(part->mmc);
423 printf("%s: failed to obtain block descriptor\n", __func__);
427 ret = part_get_info_by_name(mmc_blk, partition, &part->info);
429 printf("%s: can't find partition '%s'\n", __func__, partition);
433 part->dev_num = dev_num;
434 part->mmc_blk = mmc_blk;
442 static AvbIOResult mmc_byte_io(AvbOps *ops,
443 const char *partition,
447 size_t *out_num_read,
448 enum mmc_io_type io_type)
451 struct mmc_part *part;
452 u64 start_offset, start_sector, sectors, residue;
456 if (!partition || !buffer || io_type > IO_WRITE)
457 return AVB_IO_RESULT_ERROR_IO;
459 part = get_partition(ops, partition);
461 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
463 if (!part->info.blksz)
464 return AVB_IO_RESULT_ERROR_IO;
466 start_offset = calc_offset(part, offset);
468 start_sector = start_offset / part->info.blksz;
469 sectors = num_bytes / part->info.blksz;
470 /* handle non block-aligned reads */
471 if (start_offset % part->info.blksz ||
472 num_bytes < part->info.blksz) {
473 tmp_buf = get_sector_buf();
474 if (start_offset % part->info.blksz) {
475 residue = part->info.blksz -
476 (start_offset % part->info.blksz);
477 if (residue > num_bytes)
483 if (io_type == IO_READ) {
484 ret = mmc_read_and_flush(part,
490 printf("%s: read error (%ld, %lld)\n",
491 __func__, ret, start_sector);
492 return AVB_IO_RESULT_ERROR_IO;
495 * if this is not aligned at sector start,
496 * we have to adjust the tmp buffer
498 tmp_buf += (start_offset % part->info.blksz);
499 memcpy(buffer, (void *)tmp_buf, residue);
501 ret = mmc_read_and_flush(part,
507 printf("%s: read error (%ld, %lld)\n",
508 __func__, ret, start_sector);
509 return AVB_IO_RESULT_ERROR_IO;
511 memcpy((void *)tmp_buf +
512 start_offset % part->info.blksz,
515 ret = mmc_write(part, part->info.start +
516 start_sector, 1, tmp_buf);
518 printf("%s: write error (%ld, %lld)\n",
519 __func__, ret, start_sector);
520 return AVB_IO_RESULT_ERROR_IO;
526 start_offset += residue;
527 num_bytes -= residue;
532 if (io_type == IO_READ) {
533 ret = mmc_read_and_flush(part,
538 ret = mmc_write(part,
545 printf("%s: sector read error\n", __func__);
546 return AVB_IO_RESULT_ERROR_IO;
549 io_cnt += ret * part->info.blksz;
550 buffer += ret * part->info.blksz;
551 start_offset += ret * part->info.blksz;
552 num_bytes -= ret * part->info.blksz;
556 /* Set counter for read operation */
557 if (io_type == IO_READ && out_num_read)
558 *out_num_read = io_cnt;
560 return AVB_IO_RESULT_OK;
564 * ============================================================================
566 * ============================================================================
570 * read_from_partition() - reads @num_bytes from @offset from partition
571 * identified by a string name
573 * @ops: contains AVB ops handlers
574 * @partition_name: partition name, NUL-terminated UTF-8 string
575 * @offset: offset from the beginning of partition
576 * @num_bytes: amount of bytes to read
577 * @buffer: destination buffer to store data
581 * AVB_IO_RESULT_OK, if partition was found and read operation succeed
582 * AVB_IO_RESULT_ERROR_IO, if i/o error occurred from the underlying i/o
584 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if there is no partition with
587 static AvbIOResult read_from_partition(AvbOps *ops,
588 const char *partition_name,
589 s64 offset_from_partition,
592 size_t *out_num_read)
594 return mmc_byte_io(ops, partition_name, offset_from_partition,
595 num_bytes, buffer, out_num_read, IO_READ);
599 * write_to_partition() - writes N bytes to a partition identified by a string
602 * @ops: AvbOps, contains AVB ops handlers
603 * @partition_name: partition name
604 * @offset_from_partition: offset from the beginning of partition
605 * @num_bytes: amount of bytes to write
606 * @buf: data to write
610 * AVB_IO_RESULT_OK, if partition was found and read operation succeed
611 * AVB_IO_RESULT_ERROR_IO, if input/output error occurred
612 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition, specified in
613 * @partition_name was not found
615 static AvbIOResult write_to_partition(AvbOps *ops,
616 const char *partition_name,
617 s64 offset_from_partition,
621 return mmc_byte_io(ops, partition_name, offset_from_partition,
622 num_bytes, (void *)buffer, NULL, IO_WRITE);
626 * validate_vmbeta_public_key() - checks if the given public key used to sign
627 * the vbmeta partition is trusted
629 * @ops: AvbOps, contains AVB ops handlers
630 * @public_key_data: public key for verifying vbmeta partition signature
631 * @public_key_length: length of public key
632 * @public_key_metadata:
633 * @public_key_metadata_length:
634 * @out_key_is_trusted:
637 * AVB_IO_RESULT_OK, if partition was found and read operation succeed
639 static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
640 const u8 *public_key_data,
641 size_t public_key_length,
643 *public_key_metadata,
645 public_key_metadata_length,
646 bool *out_key_is_trusted)
648 if (!public_key_length || !public_key_data || !out_key_is_trusted)
649 return AVB_IO_RESULT_ERROR_IO;
651 *out_key_is_trusted = false;
652 if (public_key_length != sizeof(avb_root_pub))
653 return AVB_IO_RESULT_ERROR_IO;
655 if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0)
656 *out_key_is_trusted = true;
658 return AVB_IO_RESULT_OK;
661 #ifdef CONFIG_OPTEE_TA_AVB
662 static int get_open_session(struct AvbOpsData *ops_data)
664 struct udevice *tee = NULL;
666 while (!ops_data->tee) {
667 const struct tee_optee_ta_uuid uuid = TA_AVB_UUID;
668 struct tee_open_session_arg arg;
671 tee = tee_find_device(tee, NULL, NULL, NULL);
675 memset(&arg, 0, sizeof(arg));
676 tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
677 rc = tee_open_session(tee, &arg, 0, NULL);
682 ops_data->session = arg.session;
688 static AvbIOResult invoke_func(struct AvbOpsData *ops_data, u32 func,
689 ulong num_param, struct tee_param *param)
691 struct tee_invoke_arg arg;
693 if (get_open_session(ops_data))
694 return AVB_IO_RESULT_ERROR_IO;
696 memset(&arg, 0, sizeof(arg));
698 arg.session = ops_data->session;
700 if (tee_invoke_func(ops_data->tee, &arg, num_param, param))
701 return AVB_IO_RESULT_ERROR_IO;
704 return AVB_IO_RESULT_OK;
705 case TEE_ERROR_OUT_OF_MEMORY:
706 return AVB_IO_RESULT_ERROR_OOM;
707 case TEE_ERROR_STORAGE_NO_SPACE:
708 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
709 case TEE_ERROR_ITEM_NOT_FOUND:
710 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
711 case TEE_ERROR_TARGET_DEAD:
713 * The TA has paniced, close the session to reload the TA
714 * for the next request.
716 tee_close_session(ops_data->tee, ops_data->session);
717 ops_data->tee = NULL;
718 return AVB_IO_RESULT_ERROR_IO;
720 return AVB_IO_RESULT_ERROR_IO;
726 * read_rollback_index() - gets the rollback index corresponding to the
727 * location of given by @out_rollback_index.
729 * @ops: contains AvbOps handlers
730 * @rollback_index_slot:
731 * @out_rollback_index: used to write a retrieved rollback index.
734 * AVB_IO_RESULT_OK, if the roolback index was retrieved
736 static AvbIOResult read_rollback_index(AvbOps *ops,
737 size_t rollback_index_slot,
738 u64 *out_rollback_index)
740 #ifndef CONFIG_OPTEE_TA_AVB
741 /* For now we always return 0 as the stored rollback index. */
742 debug("%s: rollback protection is not implemented\n", __func__);
744 if (out_rollback_index)
745 *out_rollback_index = 0;
747 return AVB_IO_RESULT_OK;
750 struct tee_param param[2];
752 if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
753 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
755 memset(param, 0, sizeof(param));
756 param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
757 param[0].u.value.a = rollback_index_slot;
758 param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;
760 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_ROLLBACK_INDEX,
761 ARRAY_SIZE(param), param);
765 *out_rollback_index = (u64)param[1].u.value.a << 32 |
766 (u32)param[1].u.value.b;
767 return AVB_IO_RESULT_OK;
772 * write_rollback_index() - sets the rollback index corresponding to the
773 * location of given by @out_rollback_index.
775 * @ops: contains AvbOps handlers
776 * @rollback_index_slot:
777 * @rollback_index: rollback index to write.
780 * AVB_IO_RESULT_OK, if the roolback index was retrieved
782 static AvbIOResult write_rollback_index(AvbOps *ops,
783 size_t rollback_index_slot,
786 #ifndef CONFIG_OPTEE_TA_AVB
787 /* For now this is a no-op. */
788 debug("%s: rollback protection is not implemented\n", __func__);
790 return AVB_IO_RESULT_OK;
792 struct tee_param param[2];
794 if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
795 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
797 memset(param, 0, sizeof(param));
798 param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
799 param[0].u.value.a = rollback_index_slot;
800 param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
801 param[1].u.value.a = (u32)(rollback_index >> 32);
802 param[1].u.value.b = (u32)rollback_index;
804 return invoke_func(ops->user_data, TA_AVB_CMD_WRITE_ROLLBACK_INDEX,
805 ARRAY_SIZE(param), param);
810 * read_is_device_unlocked() - gets whether the device is unlocked
812 * @ops: contains AVB ops handlers
813 * @out_is_unlocked: device unlock state is stored here, true if unlocked,
817 * AVB_IO_RESULT_OK: state is retrieved successfully
818 * AVB_IO_RESULT_ERROR_IO: an error occurred
820 static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
822 #ifndef CONFIG_OPTEE_TA_AVB
823 /* For now we always return that the device is unlocked. */
824 debug("%s: device locking is not implemented\n", __func__);
826 *out_is_unlocked = true;
828 return AVB_IO_RESULT_OK;
831 struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT };
833 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_LOCK_STATE, 1, ¶m);
836 *out_is_unlocked = !param.u.value.a;
837 return AVB_IO_RESULT_OK;
842 * get_unique_guid_for_partition() - gets the GUID for a partition identified
845 * @ops: contains AVB ops handlers
846 * @partition: partition name (NUL-terminated UTF-8 string)
847 * @guid_buf: buf, used to copy in GUID string. Example of value:
848 * 527c1c6d-6361-4593-8842-3c78fcd39219
849 * @guid_buf_size: @guid_buf buffer size
852 * AVB_IO_RESULT_OK, on success (GUID found)
853 * AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
855 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
857 static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
858 const char *partition,
860 size_t guid_buf_size)
862 struct mmc_part *part;
865 part = get_partition(ops, partition);
867 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
869 uuid_size = sizeof(part->info.uuid);
870 if (uuid_size > guid_buf_size)
871 return AVB_IO_RESULT_ERROR_IO;
873 memcpy(guid_buf, part->info.uuid, uuid_size);
874 guid_buf[uuid_size - 1] = 0;
876 return AVB_IO_RESULT_OK;
880 * get_size_of_partition() - gets the size of a partition identified
883 * @ops: contains AVB ops handlers
884 * @partition: partition name (NUL-terminated UTF-8 string)
885 * @out_size_num_bytes: returns the value of a partition size
888 * AVB_IO_RESULT_OK, on success (GUID found)
889 * AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE, out_size_num_bytes is NULL
890 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
892 static AvbIOResult get_size_of_partition(AvbOps *ops,
893 const char *partition,
894 u64 *out_size_num_bytes)
896 struct mmc_part *part;
898 if (!out_size_num_bytes)
899 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
901 part = get_partition(ops, partition);
903 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
905 *out_size_num_bytes = part->info.blksz * part->info.size;
907 return AVB_IO_RESULT_OK;
910 #ifdef CONFIG_OPTEE_TA_AVB
911 static AvbIOResult read_persistent_value(AvbOps *ops,
915 size_t *out_num_bytes_read)
918 struct tee_shm *shm_name;
919 struct tee_shm *shm_buf;
920 struct tee_param param[2];
922 size_t name_size = strlen(name) + 1;
924 if (get_open_session(ops->user_data))
925 return AVB_IO_RESULT_ERROR_IO;
927 tee = ((struct AvbOpsData *)ops->user_data)->tee;
929 rc = tee_shm_alloc(tee, name_size,
930 TEE_SHM_ALLOC, &shm_name);
932 return AVB_IO_RESULT_ERROR_OOM;
934 rc = tee_shm_alloc(tee, buffer_size,
935 TEE_SHM_ALLOC, &shm_buf);
937 rc = AVB_IO_RESULT_ERROR_OOM;
941 memcpy(shm_name->addr, name, name_size);
943 memset(param, 0, sizeof(param));
944 param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
945 param[0].u.memref.shm = shm_name;
946 param[0].u.memref.size = name_size;
947 param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
948 param[1].u.memref.shm = shm_buf;
949 param[1].u.memref.size = buffer_size;
951 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_PERSIST_VALUE,
956 if (param[1].u.memref.size > buffer_size) {
957 rc = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
961 *out_num_bytes_read = param[1].u.memref.size;
963 memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read);
966 tee_shm_free(shm_buf);
968 tee_shm_free(shm_name);
973 static AvbIOResult write_persistent_value(AvbOps *ops,
979 struct tee_shm *shm_name;
980 struct tee_shm *shm_buf;
981 struct tee_param param[2];
983 size_t name_size = strlen(name) + 1;
985 if (get_open_session(ops->user_data))
986 return AVB_IO_RESULT_ERROR_IO;
988 tee = ((struct AvbOpsData *)ops->user_data)->tee;
991 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
993 rc = tee_shm_alloc(tee, name_size,
994 TEE_SHM_ALLOC, &shm_name);
996 return AVB_IO_RESULT_ERROR_OOM;
998 rc = tee_shm_alloc(tee, value_size,
999 TEE_SHM_ALLOC, &shm_buf);
1001 rc = AVB_IO_RESULT_ERROR_OOM;
1005 memcpy(shm_name->addr, name, name_size);
1006 memcpy(shm_buf->addr, value, value_size);
1008 memset(param, 0, sizeof(param));
1009 param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
1010 param[0].u.memref.shm = shm_name;
1011 param[0].u.memref.size = name_size;
1012 param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
1013 param[1].u.memref.shm = shm_buf;
1014 param[1].u.memref.size = value_size;
1016 rc = invoke_func(ops->user_data, TA_AVB_CMD_WRITE_PERSIST_VALUE,
1022 tee_shm_free(shm_buf);
1024 tee_shm_free(shm_name);
1031 * ============================================================================
1032 * AVB2.0 AvbOps alloc/initialisation/free
1033 * ============================================================================
1035 AvbOps *avb_ops_alloc(int boot_device)
1037 struct AvbOpsData *ops_data;
1039 ops_data = avb_calloc(sizeof(struct AvbOpsData));
1043 ops_data->ops.user_data = ops_data;
1045 ops_data->ops.read_from_partition = read_from_partition;
1046 ops_data->ops.write_to_partition = write_to_partition;
1047 ops_data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key;
1048 ops_data->ops.read_rollback_index = read_rollback_index;
1049 ops_data->ops.write_rollback_index = write_rollback_index;
1050 ops_data->ops.read_is_device_unlocked = read_is_device_unlocked;
1051 ops_data->ops.get_unique_guid_for_partition =
1052 get_unique_guid_for_partition;
1053 #ifdef CONFIG_OPTEE_TA_AVB
1054 ops_data->ops.write_persistent_value = write_persistent_value;
1055 ops_data->ops.read_persistent_value = read_persistent_value;
1057 ops_data->ops.get_size_of_partition = get_size_of_partition;
1058 ops_data->mmc_dev = boot_device;
1060 return &ops_data->ops;
1063 void avb_ops_free(AvbOps *ops)
1065 struct AvbOpsData *ops_data;
1070 ops_data = ops->user_data;
1073 #ifdef CONFIG_OPTEE_TA_AVB
1075 tee_close_session(ops_data->tee, ops_data->session);