Merge tag 'doc-2023-10-rc5-3' of https://source.denx.de/u-boot/custodians/u-boot-efi
[platform/kernel/u-boot.git] / common / avb_verify.c
1 /*
2  * (C) Copyright 2018, Linaro Limited
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6
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>
15
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 };
122
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)
129 {
130         struct AvbOpsData *data;
131         char *cmdline = NULL;
132
133         if (!ops)
134                 return NULL;
135
136         data = (struct AvbOpsData *)ops->user_data;
137         if (!data)
138                 return NULL;
139
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         }
153
154         return cmdline;
155 }
156
157 char *append_cmd_line(char *cmdline_orig, char *cmdline_new)
158 {
159         char *cmd_line;
160
161         if (!cmdline_new)
162                 return cmdline_orig;
163
164         if (cmdline_orig)
165                 cmd_line = cmdline_orig;
166         else
167                 cmd_line = " ";
168
169         cmd_line = avb_strdupv(cmd_line, " ", cmdline_new, NULL);
170
171         return cmd_line;
172 }
173
174 static int avb_find_dm_args(char **args, char *str)
175 {
176         int i;
177
178         if (!str)
179                 return -1;
180
181         for (i = 0; i < AVB_MAX_ARGS && args[i]; ++i) {
182                 if (strstr(args[i], str))
183                         return i;
184         }
185
186         return -1;
187 }
188
189 static char *avb_set_enforce_option(const char *cmdline, const char *option)
190 {
191         char *cmdarg[AVB_MAX_ARGS];
192         char *newargs = NULL;
193         int i = 0;
194         int total_args;
195
196         memset(cmdarg, 0, sizeof(cmdarg));
197         cmdarg[i++] = strtok((char *)cmdline, " ");
198
199         do {
200                 cmdarg[i] = strtok(NULL, " ");
201                 if (!cmdarg[i])
202                         break;
203
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);
210
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                 }
221
222                 cmdarg[i] = (char *)option;
223         }
224
225         for (i = 0; i <= total_args; i++)
226                 newargs = append_cmd_line(newargs, cmdarg[i]);
227
228         return newargs;
229 }
230
231 char *avb_set_ignore_corruption(const char *cmdline)
232 {
233         char *newargs = NULL;
234
235         newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_LOGGING);
236         if (newargs)
237                 newargs = append_cmd_line(newargs,
238                                           "androidboot.veritymode=eio");
239
240         return newargs;
241 }
242
243 char *avb_set_enforce_verity(const char *cmdline)
244 {
245         char *newargs;
246
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;
252 }
253
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)
263 {
264         unsigned long blks;
265         void *tmp_buf;
266         size_t buf_size;
267         bool unaligned = is_buf_unaligned(buffer);
268
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         }
278
279         /*
280          * Reading fails on unaligned buffers, so we have to
281          * use aligned temporary buffer and then copy to destination
282          */
283
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         }
293
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);
298
299         if (unaligned)
300                 memcpy(buffer, tmp_buf, sectors * part->info.blksz);
301
302         return blks;
303 }
304
305 static unsigned long mmc_write(struct mmc_part *part, lbaint_t start,
306                                lbaint_t sectors, void *buffer)
307 {
308         void *tmp_buf;
309         size_t buf_size;
310         bool unaligned = is_buf_unaligned(buffer);
311
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;
327
328                 memcpy(tmp_buf, buffer, sectors * part->info.blksz);
329         } else {
330                 tmp_buf = buffer;
331         }
332
333         return blk_dwrite(part->mmc_blk,
334                           start, sectors, tmp_buf);
335 }
336
337 static struct mmc_part *get_partition(AvbOps *ops, const char *partition)
338 {
339         int ret;
340         u8 dev_num;
341         int part_num = 0;
342         struct mmc_part *part;
343         struct blk_desc *mmc_blk;
344
345         part = malloc(sizeof(struct mmc_part));
346         if (!part)
347                 return NULL;
348
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         }
355
356         if (mmc_init(part->mmc)) {
357                 printf("MMC initialization failed\n");
358                 goto err;
359         }
360
361         ret = mmc_switch_part(part->mmc, part_num);
362         if (ret)
363                 goto err;
364
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         }
370
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         }
376
377         part->dev_num = dev_num;
378         part->mmc_blk = mmc_blk;
379
380         return part;
381 err:
382         free(part);
383         return NULL;
384 }
385
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)
393 {
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;
399
400         if (!partition || !buffer || io_type > IO_WRITE)
401                 return AVB_IO_RESULT_ERROR_IO;
402
403         part = get_partition(ops, partition);
404         if (!part)
405                 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
406
407         if (!part->info.blksz)
408                 return AVB_IO_RESULT_ERROR_IO;
409
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                         }
426
427                         if (io_type == IO_READ) {
428                                 ret = mmc_read_and_flush(part,
429                                                          part->info.start +
430                                                          start_sector,
431                                                          1, tmp_buf);
432
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);
449
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);
458
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                         }
467
468                         io_cnt += residue;
469                         buffer += residue;
470                         start_offset += residue;
471                         num_bytes -= residue;
472                         continue;
473                 }
474
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                         }
487
488                         if (!ret) {
489                                 printf("%s: sector read error\n", __func__);
490                                 return AVB_IO_RESULT_ERROR_IO;
491                         }
492
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         }
499
500         /* Set counter for read operation */
501         if (io_type == IO_READ && out_num_read)
502                 *out_num_read = io_cnt;
503
504         return AVB_IO_RESULT_OK;
505 }
506
507 /**
508  * ============================================================================
509  * AVB 2.0 operations
510  * ============================================================================
511  */
512
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)
537 {
538         return mmc_byte_io(ops, partition_name, offset_from_partition,
539                            num_bytes, buffer, out_num_read, IO_READ);
540 }
541
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)
564 {
565         return mmc_byte_io(ops, partition_name, offset_from_partition,
566                            num_bytes, (void *)buffer, NULL, IO_WRITE);
567 }
568
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)
591 {
592         if (!public_key_length || !public_key_data || !out_key_is_trusted)
593                 return AVB_IO_RESULT_ERROR_IO;
594
595         *out_key_is_trusted = false;
596         if (public_key_length != sizeof(avb_root_pub))
597                 return AVB_IO_RESULT_ERROR_IO;
598
599         if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0)
600                 *out_key_is_trusted = true;
601
602         return AVB_IO_RESULT_OK;
603 }
604
605 #ifdef CONFIG_OPTEE_TA_AVB
606 static int get_open_session(struct AvbOpsData *ops_data)
607 {
608         struct udevice *tee = NULL;
609
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;
614
615                 tee = tee_find_device(tee, NULL, NULL, NULL);
616                 if (!tee)
617                         return -ENODEV;
618
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 || arg.ret)
623                         continue;
624
625                 ops_data->tee = tee;
626                 ops_data->session = arg.session;
627         }
628
629         return 0;
630 }
631
632 static AvbIOResult invoke_func(struct AvbOpsData *ops_data, u32 func,
633                                ulong num_param, struct tee_param *param)
634 {
635         struct tee_invoke_arg arg;
636
637         if (get_open_session(ops_data))
638                 return AVB_IO_RESULT_ERROR_IO;
639
640         memset(&arg, 0, sizeof(arg));
641         arg.func = func;
642         arg.session = ops_data->session;
643
644         if (tee_invoke_func(ops_data->tee, &arg, num_param, param))
645                 return AVB_IO_RESULT_ERROR_IO;
646         switch (arg.ret) {
647         case TEE_SUCCESS:
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:
656                 /*
657                  * The TA has paniced, close the session to reload the TA
658                  * for the next request.
659                  */
660                 tee_close_session(ops_data->tee, ops_data->session);
661                 ops_data->tee = NULL;
662                 return AVB_IO_RESULT_ERROR_IO;
663         default:
664                 return AVB_IO_RESULT_ERROR_IO;
665         }
666 }
667 #endif
668
669 /**
670  * read_rollback_index() - gets the rollback index corresponding to the
671  * location of given by @out_rollback_index.
672  *
673  * @ops: contains AvbOps handlers
674  * @rollback_index_slot:
675  * @out_rollback_index: used to write a retrieved rollback index.
676  *
677  * @return
678  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
679  */
680 static AvbIOResult read_rollback_index(AvbOps *ops,
681                                        size_t rollback_index_slot,
682                                        u64 *out_rollback_index)
683 {
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__);
687
688         if (out_rollback_index)
689                 *out_rollback_index = 0;
690
691         return AVB_IO_RESULT_OK;
692 #else
693         AvbIOResult rc;
694         struct tee_param param[2];
695
696         if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
697                 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
698
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;
703
704         rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_ROLLBACK_INDEX,
705                          ARRAY_SIZE(param), param);
706         if (rc)
707                 return rc;
708
709         *out_rollback_index = (u64)param[1].u.value.a << 32 |
710                               (u32)param[1].u.value.b;
711         return AVB_IO_RESULT_OK;
712 #endif
713 }
714
715 /**
716  * write_rollback_index() - sets the rollback index corresponding to the
717  * location of given by @out_rollback_index.
718  *
719  * @ops: contains AvbOps handlers
720  * @rollback_index_slot:
721  * @rollback_index: rollback index to write.
722  *
723  * @return
724  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
725  */
726 static AvbIOResult write_rollback_index(AvbOps *ops,
727                                         size_t rollback_index_slot,
728                                         u64 rollback_index)
729 {
730 #ifndef CONFIG_OPTEE_TA_AVB
731         /* For now this is a no-op. */
732         printf("%s not supported yet\n", __func__);
733
734         return AVB_IO_RESULT_OK;
735 #else
736         struct tee_param param[2];
737
738         if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
739                 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
740
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;
747
748         return invoke_func(ops->user_data, TA_AVB_CMD_WRITE_ROLLBACK_INDEX,
749                            ARRAY_SIZE(param), param);
750 #endif
751 }
752
753 /**
754  * read_is_device_unlocked() - gets whether the device is unlocked
755  *
756  * @ops: contains AVB ops handlers
757  * @out_is_unlocked: device unlock state is stored here, true if unlocked,
758  *       false otherwise
759  *
760  * @return:
761  *       AVB_IO_RESULT_OK: state is retrieved successfully
762  *       AVB_IO_RESULT_ERROR_IO: an error occurred
763  */
764 static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
765 {
766 #ifndef CONFIG_OPTEE_TA_AVB
767         /* For now we always return that the device is unlocked. */
768
769         printf("%s not supported yet\n", __func__);
770
771         *out_is_unlocked = true;
772
773         return AVB_IO_RESULT_OK;
774 #else
775         AvbIOResult rc;
776         struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT };
777
778         rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_LOCK_STATE, 1, &param);
779         if (rc)
780                 return rc;
781         *out_is_unlocked = !param.u.value.a;
782         return AVB_IO_RESULT_OK;
783 #endif
784 }
785
786 /**
787  * get_unique_guid_for_partition() - gets the GUID for a partition identified
788  * by a string name
789  *
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
795  *
796  * @return:
797  *      AVB_IO_RESULT_OK, on success (GUID found)
798  *      AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
799  *             provided
800  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
801  */
802 static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
803                                                  const char *partition,
804                                                  char *guid_buf,
805                                                  size_t guid_buf_size)
806 {
807         struct mmc_part *part;
808         size_t uuid_size;
809
810         part = get_partition(ops, partition);
811         if (!part)
812                 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
813
814         uuid_size = sizeof(part->info.uuid);
815         if (uuid_size > guid_buf_size)
816                 return AVB_IO_RESULT_ERROR_IO;
817
818         memcpy(guid_buf, part->info.uuid, uuid_size);
819         guid_buf[uuid_size - 1] = 0;
820
821         return AVB_IO_RESULT_OK;
822 }
823
824 /**
825  * get_size_of_partition() - gets the size of a partition identified
826  * by a string name
827  *
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
831  *
832  * @return:
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
836  */
837 static AvbIOResult get_size_of_partition(AvbOps *ops,
838                                          const char *partition,
839                                          u64 *out_size_num_bytes)
840 {
841         struct mmc_part *part;
842
843         if (!out_size_num_bytes)
844                 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
845
846         part = get_partition(ops, partition);
847         if (!part)
848                 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
849
850         *out_size_num_bytes = part->info.blksz * part->info.size;
851
852         return AVB_IO_RESULT_OK;
853 }
854
855 #ifdef CONFIG_OPTEE_TA_AVB
856 static AvbIOResult read_persistent_value(AvbOps *ops,
857                                          const char *name,
858                                          size_t buffer_size,
859                                          u8 *out_buffer,
860                                          size_t *out_num_bytes_read)
861 {
862         AvbIOResult rc;
863         struct tee_shm *shm_name;
864         struct tee_shm *shm_buf;
865         struct tee_param param[2];
866         struct udevice *tee;
867         size_t name_size = strlen(name) + 1;
868
869         if (get_open_session(ops->user_data))
870                 return AVB_IO_RESULT_ERROR_IO;
871
872         tee = ((struct AvbOpsData *)ops->user_data)->tee;
873
874         rc = tee_shm_alloc(tee, name_size,
875                            TEE_SHM_ALLOC, &shm_name);
876         if (rc)
877                 return AVB_IO_RESULT_ERROR_OOM;
878
879         rc = tee_shm_alloc(tee, buffer_size,
880                            TEE_SHM_ALLOC, &shm_buf);
881         if (rc) {
882                 rc = AVB_IO_RESULT_ERROR_OOM;
883                 goto free_name;
884         }
885
886         memcpy(shm_name->addr, name, name_size);
887
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;
895
896         rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_PERSIST_VALUE,
897                          2, param);
898         if (rc)
899                 goto out;
900
901         if (param[1].u.memref.size > buffer_size) {
902                 rc = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
903                 goto out;
904         }
905
906         *out_num_bytes_read = param[1].u.memref.size;
907
908         memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read);
909
910 out:
911         tee_shm_free(shm_buf);
912 free_name:
913         tee_shm_free(shm_name);
914
915         return rc;
916 }
917
918 static AvbIOResult write_persistent_value(AvbOps *ops,
919                                           const char *name,
920                                           size_t value_size,
921                                           const u8 *value)
922 {
923         AvbIOResult rc;
924         struct tee_shm *shm_name;
925         struct tee_shm *shm_buf;
926         struct tee_param param[2];
927         struct udevice *tee;
928         size_t name_size = strlen(name) + 1;
929
930         if (get_open_session(ops->user_data))
931                 return AVB_IO_RESULT_ERROR_IO;
932
933         tee = ((struct AvbOpsData *)ops->user_data)->tee;
934
935         if (!value_size)
936                 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
937
938         rc = tee_shm_alloc(tee, name_size,
939                            TEE_SHM_ALLOC, &shm_name);
940         if (rc)
941                 return AVB_IO_RESULT_ERROR_OOM;
942
943         rc = tee_shm_alloc(tee, value_size,
944                            TEE_SHM_ALLOC, &shm_buf);
945         if (rc) {
946                 rc = AVB_IO_RESULT_ERROR_OOM;
947                 goto free_name;
948         }
949
950         memcpy(shm_name->addr, name, name_size);
951         memcpy(shm_buf->addr, value, value_size);
952
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;
960
961         rc = invoke_func(ops->user_data, TA_AVB_CMD_WRITE_PERSIST_VALUE,
962                          2, param);
963         if (rc)
964                 goto out;
965
966 out:
967         tee_shm_free(shm_buf);
968 free_name:
969         tee_shm_free(shm_name);
970
971         return rc;
972 }
973 #endif
974
975 /**
976  * ============================================================================
977  * AVB2.0 AvbOps alloc/initialisation/free
978  * ============================================================================
979  */
980 AvbOps *avb_ops_alloc(int boot_device)
981 {
982         struct AvbOpsData *ops_data;
983
984         ops_data = avb_calloc(sizeof(struct AvbOpsData));
985         if (!ops_data)
986                 return NULL;
987
988         ops_data->ops.user_data = ops_data;
989
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;
1001 #endif
1002         ops_data->ops.get_size_of_partition = get_size_of_partition;
1003         ops_data->mmc_dev = boot_device;
1004
1005         return &ops_data->ops;
1006 }
1007
1008 void avb_ops_free(AvbOps *ops)
1009 {
1010         struct AvbOpsData *ops_data;
1011
1012         if (!ops)
1013                 return;
1014
1015         ops_data = ops->user_data;
1016
1017         if (ops_data) {
1018 #ifdef CONFIG_OPTEE_TA_AVB
1019                 if (ops_data->tee)
1020                         tee_close_session(ops_data->tee, ops_data->session);
1021 #endif
1022                 avb_free(ops_data);
1023         }
1024 }