]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ti-u-boot/ti-u-boot.git/blob - common/avb_verify.c
Prepare v2024.04
[ti-u-boot/ti-u-boot.git] / common / avb_verify.c
1 /*
2  * (C) Copyright 2018, Linaro Limited
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
7 #include <avb_verify.h>
8 #include <blk.h>
9 #include <cpu_func.h>
10 #include <image.h>
11 #include <malloc.h>
12 #include <part.h>
13 #include <tee.h>
14 #include <tee/optee_ta_avb.h>
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,
120         0xd8, 0x7e,
121 };
123 /**
124  * ============================================================================
125  * Boot states support (GREEN, YELLOW, ORANGE, RED) and dm_verity
126  * ============================================================================
127  */
128 char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state)
130         struct AvbOpsData *data;
131         char *cmdline = NULL;
133         if (!ops)
134                 return NULL;
136         data = (struct AvbOpsData *)ops->user_data;
137         if (!data)
138                 return NULL;
140         data->boot_state = boot_state;
141         switch (boot_state) {
142         case AVB_GREEN:
143                 cmdline = "androidboot.verifiedbootstate=green";
144                 break;
145         case AVB_YELLOW:
146                 cmdline = "androidboot.verifiedbootstate=yellow";
147                 break;
148         case AVB_ORANGE:
149                 cmdline = "androidboot.verifiedbootstate=orange";
150         case AVB_RED:
151                 break;
152         }
154         return cmdline;
157 char *append_cmd_line(char *cmdline_orig, char *cmdline_new)
159         char *cmd_line;
161         if (!cmdline_new)
162                 return cmdline_orig;
164         if (cmdline_orig)
165                 cmd_line = cmdline_orig;
166         else
167                 cmd_line = " ";
169         cmd_line = avb_strdupv(cmd_line, " ", cmdline_new, NULL);
171         return cmd_line;
174 static int avb_find_dm_args(char **args, char *str)
176         int i;
178         if (!str)
179                 return -1;
181         for (i = 0; i < AVB_MAX_ARGS && args[i]; ++i) {
182                 if (strstr(args[i], str))
183                         return i;
184         }
186         return -1;
189 static char *avb_set_enforce_option(const char *cmdline, const char *option)
191         char *cmdarg[AVB_MAX_ARGS];
192         char *newargs = NULL;
193         int i = 0;
194         int total_args;
196         memset(cmdarg, 0, sizeof(cmdarg));
197         cmdarg[i++] = strtok((char *)cmdline, " ");
199         do {
200                 cmdarg[i] = strtok(NULL, " ");
201                 if (!cmdarg[i])
202                         break;
204                 if (++i >= AVB_MAX_ARGS) {
205                         printf("%s: Can't handle more then %d args\n",
206                                __func__, i);
207                         return NULL;
208                 }
209         } while (true);
211         total_args = i;
212         i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_LOGGING);
213         if (i >= 0) {
214                 cmdarg[i] = (char *)option;
215         } else {
216                 i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_RESTART);
217                 if (i < 0) {
218                         printf("%s: No verity options found\n", __func__);
219                         return NULL;
220                 }
222                 cmdarg[i] = (char *)option;
223         }
225         for (i = 0; i <= total_args; i++)
226                 newargs = append_cmd_line(newargs, cmdarg[i]);
228         return newargs;
231 char *avb_set_ignore_corruption(const char *cmdline)
233         char *newargs = NULL;
235         newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_LOGGING);
236         if (newargs)
237                 newargs = append_cmd_line(newargs,
238                                           "androidboot.veritymode=eio");
240         return newargs;
243 char *avb_set_enforce_verity(const char *cmdline)
245         char *newargs;
247         newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_RESTART);
248         if (newargs)
249                 newargs = append_cmd_line(newargs,
250                                           "androidboot.veritymode=enforcing");
251         return newargs;
254 /**
255  * ============================================================================
256  * IO(mmc) auxiliary functions
257  * ============================================================================
258  */
259 static unsigned long mmc_read_and_flush(struct mmc_part *part,
260                                         lbaint_t start,
261                                         lbaint_t sectors,
262                                         void *buffer)
264         unsigned long blks;
265         void *tmp_buf;
266         size_t buf_size;
267         bool unaligned = is_buf_unaligned(buffer);
269         if (start < part->info.start) {
270                 printf("%s: partition start out of bounds\n", __func__);
271                 return 0;
272         }
273         if ((start + sectors) > (part->info.start + part->info.size)) {
274                 sectors = part->info.start + part->info.size - start;
275                 printf("%s: read sector aligned to partition bounds (%ld)\n",
276                        __func__, sectors);
277         }
279         /*
280          * Reading fails on unaligned buffers, so we have to
281          * use aligned temporary buffer and then copy to destination
282          */
284         if (unaligned) {
285                 printf("Handling unaligned read buffer..\n");
286                 tmp_buf = get_sector_buf();
287                 buf_size = get_sector_buf_size();
288                 if (sectors > buf_size / part->info.blksz)
289                         sectors = buf_size / part->info.blksz;
290         } else {
291                 tmp_buf = buffer;
292         }
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);
299         if (unaligned)
300                 memcpy(buffer, tmp_buf, sectors * part->info.blksz);
302         return blks;
305 static unsigned long mmc_write(struct mmc_part *part, lbaint_t start,
306                                lbaint_t sectors, void *buffer)
308         void *tmp_buf;
309         size_t buf_size;
310         bool unaligned = is_buf_unaligned(buffer);
312         if (start < part->info.start) {
313                 printf("%s: partition start out of bounds\n", __func__);
314                 return 0;
315         }
316         if ((start + sectors) > (part->info.start + part->info.size)) {
317                 sectors = part->info.start + part->info.size - start;
318                 printf("%s: sector aligned to partition bounds (%ld)\n",
319                        __func__, sectors);
320         }
321         if (unaligned) {
322                 tmp_buf = get_sector_buf();
323                 buf_size = get_sector_buf_size();
324                 printf("Handling unaligned wrire buffer..\n");
325                 if (sectors > buf_size / part->info.blksz)
326                         sectors = buf_size / part->info.blksz;
328                 memcpy(tmp_buf, buffer, sectors * part->info.blksz);
329         } else {
330                 tmp_buf = buffer;
331         }
333         return blk_dwrite(part->mmc_blk,
334                           start, sectors, tmp_buf);
337 static struct mmc_part *get_partition(AvbOps *ops, const char *partition)
339         int ret;
340         u8 dev_num;
341         int part_num = 0;
342         struct mmc_part *part;
343         struct blk_desc *mmc_blk;
345         part = malloc(sizeof(struct mmc_part));
346         if (!part)
347                 return NULL;
349         dev_num = get_boot_device(ops);
350         part->mmc = find_mmc_device(dev_num);
351         if (!part->mmc) {
352                 printf("No MMC device at slot %x\n", dev_num);
353                 goto err;
354         }
356         if (mmc_init(part->mmc)) {
357                 printf("MMC initialization failed\n");
358                 goto err;
359         }
361         ret = mmc_switch_part(part->mmc, part_num);
362         if (ret)
363                 goto err;
365         mmc_blk = mmc_get_blk_desc(part->mmc);
366         if (!mmc_blk) {
367                 printf("Error - failed to obtain block descriptor\n");
368                 goto err;
369         }
371         ret = part_get_info_by_name(mmc_blk, partition, &part->info);
372         if (ret < 0) {
373                 printf("Can't find partition '%s'\n", partition);
374                 goto err;
375         }
377         part->dev_num = dev_num;
378         part->mmc_blk = mmc_blk;
380         return part;
381 err:
382         free(part);
383         return NULL;
386 static AvbIOResult mmc_byte_io(AvbOps *ops,
387                                const char *partition,
388                                s64 offset,
389                                size_t num_bytes,
390                                void *buffer,
391                                size_t *out_num_read,
392                                enum mmc_io_type io_type)
394         ulong ret;
395         struct mmc_part *part;
396         u64 start_offset, start_sector, sectors, residue;
397         u8 *tmp_buf;
398         size_t io_cnt = 0;
400         if (!partition || !buffer || io_type > IO_WRITE)
401                 return AVB_IO_RESULT_ERROR_IO;
403         part = get_partition(ops, partition);
404         if (!part)
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);
411         while (num_bytes) {
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)
422                                         residue = num_bytes;
423                         } else {
424                                 residue = num_bytes;
425                         }
427                         if (io_type == IO_READ) {
428                                 ret = mmc_read_and_flush(part,
429                                                          part->info.start +
430                                                          start_sector,
431                                                          1, tmp_buf);
433                                 if (ret != 1) {
434                                         printf("%s: read error (%ld, %lld)\n",
435                                                __func__, ret, start_sector);
436                                         return AVB_IO_RESULT_ERROR_IO;
437                                 }
438                                 /*
439                                  * if this is not aligned at sector start,
440                                  * we have to adjust the tmp buffer
441                                  */
442                                 tmp_buf += (start_offset % part->info.blksz);
443                                 memcpy(buffer, (void *)tmp_buf, residue);
444                         } else {
445                                 ret = mmc_read_and_flush(part,
446                                                          part->info.start +
447                                                          start_sector,
448                                                          1, tmp_buf);
450                                 if (ret != 1) {
451                                         printf("%s: read error (%ld, %lld)\n",
452                                                __func__, ret, start_sector);
453                                         return AVB_IO_RESULT_ERROR_IO;
454                                 }
455                                 memcpy((void *)tmp_buf +
456                                         start_offset % part->info.blksz,
457                                         buffer, residue);
459                                 ret = mmc_write(part, part->info.start +
460                                                 start_sector, 1, tmp_buf);
461                                 if (ret != 1) {
462                                         printf("%s: write error (%ld, %lld)\n",
463                                                __func__, ret, start_sector);
464                                         return AVB_IO_RESULT_ERROR_IO;
465                                 }
466                         }
468                         io_cnt += residue;
469                         buffer += residue;
470                         start_offset += residue;
471                         num_bytes -= residue;
472                         continue;
473                 }
475                 if (sectors) {
476                         if (io_type == IO_READ) {
477                                 ret = mmc_read_and_flush(part,
478                                                          part->info.start +
479                                                          start_sector,
480                                                          sectors, buffer);
481                         } else {
482                                 ret = mmc_write(part,
483                                                 part->info.start +
484                                                 start_sector,
485                                                 sectors, buffer);
486                         }
488                         if (!ret) {
489                                 printf("%s: sector read error\n", __func__);
490                                 return AVB_IO_RESULT_ERROR_IO;
491                         }
493                         io_cnt += ret * part->info.blksz;
494                         buffer += ret * part->info.blksz;
495                         start_offset += ret * part->info.blksz;
496                         num_bytes -= ret * part->info.blksz;
497                 }
498         }
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;
507 /**
508  * ============================================================================
509  * AVB 2.0 operations
510  * ============================================================================
511  */
513 /**
514  * read_from_partition() - reads @num_bytes from  @offset from partition
515  * identified by a string name
516  *
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
522  * @out_num_read:
523  *
524  * @return:
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
527  *            subsystem
528  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if there is no partition with
529  *      the given name
530  */
531 static AvbIOResult read_from_partition(AvbOps *ops,
532                                        const char *partition_name,
533                                        s64 offset_from_partition,
534                                        size_t num_bytes,
535                                        void *buffer,
536                                        size_t *out_num_read)
538         return mmc_byte_io(ops, partition_name, offset_from_partition,
539                            num_bytes, buffer, out_num_read, IO_READ);
542 /**
543  * write_to_partition() - writes N bytes to a partition identified by a string
544  * name
545  *
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
551  * @out_num_read:
552  *
553  * @return:
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
558  */
559 static AvbIOResult write_to_partition(AvbOps *ops,
560                                       const char *partition_name,
561                                       s64 offset_from_partition,
562                                       size_t num_bytes,
563                                       const void *buffer)
565         return mmc_byte_io(ops, partition_name, offset_from_partition,
566                            num_bytes, (void *)buffer, NULL, IO_WRITE);
569 /**
570  * validate_vmbeta_public_key() - checks if the given public key used to sign
571  * the vbmeta partition is trusted
572  *
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:
579  *
580  * @return:
581  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
582  */
583 static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
584                                               const u8 *public_key_data,
585                                               size_t public_key_length,
586                                               const u8
587                                               *public_key_metadata,
588                                               size_t
589                                               public_key_metadata_length,
590                                               bool *out_key_is_trusted)
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;
613                 int rc;
615                 tee = tee_find_device(tee, NULL, NULL, NULL);
616                 if (!tee)
617                         return -ENODEV;
619                 memset(&arg, 0, sizeof(arg));
620                 tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
621                 rc = tee_open_session(tee, &arg, 0, NULL);
622                 if (!rc) {
623                         ops_data->tee = tee;
624                         ops_data->session = arg.session;
625                 }
626         }
628         return 0;
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));
640         arg.func = func;
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;
645         switch (arg.ret) {
646         case TEE_SUCCESS:
647                 return AVB_IO_RESULT_OK;
648         case TEE_ERROR_OUT_OF_MEMORY:
649                 return AVB_IO_RESULT_ERROR_OOM;
650         case TEE_ERROR_STORAGE_NO_SPACE:
651                 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
652         case TEE_ERROR_ITEM_NOT_FOUND:
653                 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
654         case TEE_ERROR_TARGET_DEAD:
655                 /*
656                  * The TA has paniced, close the session to reload the TA
657                  * for the next request.
658                  */
659                 tee_close_session(ops_data->tee, ops_data->session);
660                 ops_data->tee = NULL;
661                 return AVB_IO_RESULT_ERROR_IO;
662         default:
663                 return AVB_IO_RESULT_ERROR_IO;
664         }
666 #endif
668 /**
669  * read_rollback_index() - gets the rollback index corresponding to the
670  * location of given by @out_rollback_index.
671  *
672  * @ops: contains AvbOps handlers
673  * @rollback_index_slot:
674  * @out_rollback_index: used to write a retrieved rollback index.
675  *
676  * @return
677  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
678  */
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;
691 #else
692         AvbIOResult rc;
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);
705         if (rc)
706                 return rc;
708         *out_rollback_index = (u64)param[1].u.value.a << 32 |
709                               (u32)param[1].u.value.b;
710         return AVB_IO_RESULT_OK;
711 #endif
714 /**
715  * write_rollback_index() - sets the rollback index corresponding to the
716  * location of given by @out_rollback_index.
717  *
718  * @ops: contains AvbOps handlers
719  * @rollback_index_slot:
720  * @rollback_index: rollback index to write.
721  *
722  * @return
723  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
724  */
725 static AvbIOResult write_rollback_index(AvbOps *ops,
726                                         size_t rollback_index_slot,
727                                         u64 rollback_index)
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;
734 #else
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);
749 #endif
752 /**
753  * read_is_device_unlocked() - gets whether the device is unlocked
754  *
755  * @ops: contains AVB ops handlers
756  * @out_is_unlocked: device unlock state is stored here, true if unlocked,
757  *       false otherwise
758  *
759  * @return:
760  *       AVB_IO_RESULT_OK: state is retrieved successfully
761  *       AVB_IO_RESULT_ERROR_IO: an error occurred
762  */
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;
773 #else
774         AvbIOResult rc;
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, &param);
778         if (rc)
779                 return rc;
780         *out_is_unlocked = !param.u.value.a;
781         return AVB_IO_RESULT_OK;
782 #endif
785 /**
786  * get_unique_guid_for_partition() - gets the GUID for a partition identified
787  * by a string name
788  *
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
794  *
795  * @return:
796  *      AVB_IO_RESULT_OK, on success (GUID found)
797  *      AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
798  *             provided
799  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
800  */
801 static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
802                                                  const char *partition,
803                                                  char *guid_buf,
804                                                  size_t guid_buf_size)
806         struct mmc_part *part;
807         size_t uuid_size;
809         part = get_partition(ops, partition);
810         if (!part)
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;
823 /**
824  * get_size_of_partition() - gets the size of a partition identified
825  * by a string name
826  *
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
830  *
831  * @return:
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
835  */
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);
846         if (!part)
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,
856                                          const char *name,
857                                          size_t buffer_size,
858                                          u8 *out_buffer,
859                                          size_t *out_num_bytes_read)
861         AvbIOResult rc;
862         struct tee_shm *shm_name;
863         struct tee_shm *shm_buf;
864         struct tee_param param[2];
865         struct udevice *tee;
866         size_t name_size = strlen(name) + 1;
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);
875         if (rc)
876                 return AVB_IO_RESULT_ERROR_OOM;
878         rc = tee_shm_alloc(tee, buffer_size,
879                            TEE_SHM_ALLOC, &shm_buf);
880         if (rc) {
881                 rc = AVB_IO_RESULT_ERROR_OOM;
882                 goto free_name;
883         }
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,
896                          2, param);
897         if (rc)
898                 goto out;
900         if (param[1].u.memref.size > buffer_size) {
901                 rc = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
902                 goto out;
903         }
905         *out_num_bytes_read = param[1].u.memref.size;
907         memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read);
909 out:
910         tee_shm_free(shm_buf);
911 free_name:
912         tee_shm_free(shm_name);
914         return rc;
917 static AvbIOResult write_persistent_value(AvbOps *ops,
918                                           const char *name,
919                                           size_t value_size,
920                                           const u8 *value)
922         AvbIOResult rc;
923         struct tee_shm *shm_name;
924         struct tee_shm *shm_buf;
925         struct tee_param param[2];
926         struct udevice *tee;
927         size_t name_size = strlen(name) + 1;
929         if (get_open_session(ops->user_data))
930                 return AVB_IO_RESULT_ERROR_IO;
932         tee = ((struct AvbOpsData *)ops->user_data)->tee;
934         if (!value_size)
935                 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
937         rc = tee_shm_alloc(tee, name_size,
938                            TEE_SHM_ALLOC, &shm_name);
939         if (rc)
940                 return AVB_IO_RESULT_ERROR_OOM;
942         rc = tee_shm_alloc(tee, value_size,
943                            TEE_SHM_ALLOC, &shm_buf);
944         if (rc) {
945                 rc = AVB_IO_RESULT_ERROR_OOM;
946                 goto free_name;
947         }
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,
961                          2, param);
962         if (rc)
963                 goto out;
965 out:
966         tee_shm_free(shm_buf);
967 free_name:
968         tee_shm_free(shm_name);
970         return rc;
972 #endif
974 /**
975  * ============================================================================
976  * AVB2.0 AvbOps alloc/initialisation/free
977  * ============================================================================
978  */
979 AvbOps *avb_ops_alloc(int boot_device)
981         struct AvbOpsData *ops_data;
983         ops_data = avb_calloc(sizeof(struct AvbOpsData));
984         if (!ops_data)
985                 return NULL;
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;
1000 #endif
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;
1011         if (!ops)
1012                 return;
1014         ops_data = ops->user_data;
1016         if (ops_data) {
1017 #ifdef CONFIG_OPTEE_TA_AVB
1018                 if (ops_data->tee)
1019                         tee_close_session(ops_data->tee, ops_data->session);
1020 #endif
1021                 avb_free(ops_data);
1022         }