treewide: Drop bootm_headers_t typedef
[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) {
623                         ops_data->tee = tee;
624                         ops_data->session = arg.session;
625                 }
626         }
627
628         return 0;
629 }
630
631 static AvbIOResult invoke_func(struct AvbOpsData *ops_data, u32 func,
632                                ulong num_param, struct tee_param *param)
633 {
634         struct tee_invoke_arg arg;
635
636         if (get_open_session(ops_data))
637                 return AVB_IO_RESULT_ERROR_IO;
638
639         memset(&arg, 0, sizeof(arg));
640         arg.func = func;
641         arg.session = ops_data->session;
642
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         }
665 }
666 #endif
667
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)
682 {
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__);
686
687         if (out_rollback_index)
688                 *out_rollback_index = 0;
689
690         return AVB_IO_RESULT_OK;
691 #else
692         AvbIOResult rc;
693         struct tee_param param[2];
694
695         if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
696                 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
697
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;
702
703         rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_ROLLBACK_INDEX,
704                          ARRAY_SIZE(param), param);
705         if (rc)
706                 return rc;
707
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
712 }
713
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)
728 {
729 #ifndef CONFIG_OPTEE_TA_AVB
730         /* For now this is a no-op. */
731         printf("%s not supported yet\n", __func__);
732
733         return AVB_IO_RESULT_OK;
734 #else
735         struct tee_param param[2];
736
737         if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
738                 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
739
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;
746
747         return invoke_func(ops->user_data, TA_AVB_CMD_WRITE_ROLLBACK_INDEX,
748                            ARRAY_SIZE(param), param);
749 #endif
750 }
751
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)
764 {
765 #ifndef CONFIG_OPTEE_TA_AVB
766         /* For now we always return that the device is unlocked. */
767
768         printf("%s not supported yet\n", __func__);
769
770         *out_is_unlocked = true;
771
772         return AVB_IO_RESULT_OK;
773 #else
774         AvbIOResult rc;
775         struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT };
776
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
783 }
784
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)
805 {
806         struct mmc_part *part;
807         size_t uuid_size;
808
809         part = get_partition(ops, partition);
810         if (!part)
811                 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
812
813         uuid_size = sizeof(part->info.uuid);
814         if (uuid_size > guid_buf_size)
815                 return AVB_IO_RESULT_ERROR_IO;
816
817         memcpy(guid_buf, part->info.uuid, uuid_size);
818         guid_buf[uuid_size - 1] = 0;
819
820         return AVB_IO_RESULT_OK;
821 }
822
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)
839 {
840         struct mmc_part *part;
841
842         if (!out_size_num_bytes)
843                 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
844
845         part = get_partition(ops, partition);
846         if (!part)
847                 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
848
849         *out_size_num_bytes = part->info.blksz * part->info.size;
850
851         return AVB_IO_RESULT_OK;
852 }
853
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)
860 {
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;
867
868         if (get_open_session(ops->user_data))
869                 return AVB_IO_RESULT_ERROR_IO;
870
871         tee = ((struct AvbOpsData *)ops->user_data)->tee;
872
873         rc = tee_shm_alloc(tee, name_size,
874                            TEE_SHM_ALLOC, &shm_name);
875         if (rc)
876                 return AVB_IO_RESULT_ERROR_OOM;
877
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         }
884
885         memcpy(shm_name->addr, name, name_size);
886
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;
894
895         rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_PERSIST_VALUE,
896                          2, param);
897         if (rc)
898                 goto out;
899
900         if (param[1].u.memref.size > buffer_size) {
901                 rc = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
902                 goto out;
903         }
904
905         *out_num_bytes_read = param[1].u.memref.size;
906
907         memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read);
908
909 out:
910         tee_shm_free(shm_buf);
911 free_name:
912         tee_shm_free(shm_name);
913
914         return rc;
915 }
916
917 static AvbIOResult write_persistent_value(AvbOps *ops,
918                                           const char *name,
919                                           size_t value_size,
920                                           const u8 *value)
921 {
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;
928
929         if (get_open_session(ops->user_data))
930                 return AVB_IO_RESULT_ERROR_IO;
931
932         tee = ((struct AvbOpsData *)ops->user_data)->tee;
933
934         if (!value_size)
935                 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
936
937         rc = tee_shm_alloc(tee, name_size,
938                            TEE_SHM_ALLOC, &shm_name);
939         if (rc)
940                 return AVB_IO_RESULT_ERROR_OOM;
941
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         }
948
949         memcpy(shm_name->addr, name, name_size);
950         memcpy(shm_buf->addr, value, value_size);
951
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;
959
960         rc = invoke_func(ops->user_data, TA_AVB_CMD_WRITE_PERSIST_VALUE,
961                          2, param);
962         if (rc)
963                 goto out;
964
965 out:
966         tee_shm_free(shm_buf);
967 free_name:
968         tee_shm_free(shm_name);
969
970         return rc;
971 }
972 #endif
973
974 /**
975  * ============================================================================
976  * AVB2.0 AvbOps alloc/initialisation/free
977  * ============================================================================
978  */
979 AvbOps *avb_ops_alloc(int boot_device)
980 {
981         struct AvbOpsData *ops_data;
982
983         ops_data = avb_calloc(sizeof(struct AvbOpsData));
984         if (!ops_data)
985                 return NULL;
986
987         ops_data->ops.user_data = ops_data;
988
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;
1003
1004         return &ops_data->ops;
1005 }
1006
1007 void avb_ops_free(AvbOps *ops)
1008 {
1009         struct AvbOpsData *ops_data;
1010
1011         if (!ops)
1012                 return;
1013
1014         ops_data = ops->user_data;
1015
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         }
1023 }