Merge tag 'dm-pull9apr20' of git://git.denx.de/u-boot-dm
[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 <fastboot.h>
11 #include <image.h>
12 #include <malloc.h>
13 #include <part.h>
14 #include <tee.h>
15 #include <tee/optee_ta_avb.h>
16
17 static const unsigned char avb_root_pub[1032] = {
18         0x0, 0x0, 0x10, 0x0, 0x55, 0xd9, 0x4, 0xad, 0xd8, 0x4,
19         0xaf, 0xe3, 0xd3, 0x84, 0x6c, 0x7e, 0xd, 0x89, 0x3d, 0xc2,
20         0x8c, 0xd3, 0x12, 0x55, 0xe9, 0x62, 0xc9, 0xf1, 0xf, 0x5e,
21         0xcc, 0x16, 0x72, 0xab, 0x44, 0x7c, 0x2c, 0x65, 0x4a, 0x94,
22         0xb5, 0x16, 0x2b, 0x0, 0xbb, 0x6, 0xef, 0x13, 0x7, 0x53,
23         0x4c, 0xf9, 0x64, 0xb9, 0x28, 0x7a, 0x1b, 0x84, 0x98, 0x88,
24         0xd8, 0x67, 0xa4, 0x23, 0xf9, 0xa7, 0x4b, 0xdc, 0x4a, 0xf,
25         0xf7, 0x3a, 0x18, 0xae, 0x54, 0xa8, 0x15, 0xfe, 0xb0, 0xad,
26         0xac, 0x35, 0xda, 0x3b, 0xad, 0x27, 0xbc, 0xaf, 0xe8, 0xd3,
27         0x2f, 0x37, 0x34, 0xd6, 0x51, 0x2b, 0x6c, 0x5a, 0x27, 0xd7,
28         0x96, 0x6, 0xaf, 0x6b, 0xb8, 0x80, 0xca, 0xfa, 0x30, 0xb4,
29         0xb1, 0x85, 0xb3, 0x4d, 0xaa, 0xaa, 0xc3, 0x16, 0x34, 0x1a,
30         0xb8, 0xe7, 0xc7, 0xfa, 0xf9, 0x9, 0x77, 0xab, 0x97, 0x93,
31         0xeb, 0x44, 0xae, 0xcf, 0x20, 0xbc, 0xf0, 0x80, 0x11, 0xdb,
32         0x23, 0xc, 0x47, 0x71, 0xb9, 0x6d, 0xd6, 0x7b, 0x60, 0x47,
33         0x87, 0x16, 0x56, 0x93, 0xb7, 0xc2, 0x2a, 0x9a, 0xb0, 0x4c,
34         0x1, 0xc, 0x30, 0xd8, 0x93, 0x87, 0xf0, 0xed, 0x6e, 0x8b,
35         0xbe, 0x30, 0x5b, 0xf6, 0xa6, 0xaf, 0xdd, 0x80, 0x7c, 0x45,
36         0x5e, 0x8f, 0x91, 0x93, 0x5e, 0x44, 0xfe, 0xb8, 0x82, 0x7,
37         0xee, 0x79, 0xca, 0xbf, 0x31, 0x73, 0x62, 0x58, 0xe3, 0xcd,
38         0xc4, 0xbc, 0xc2, 0x11, 0x1d, 0xa1, 0x4a, 0xbf, 0xfe, 0x27,
39         0x7d, 0xa1, 0xf6, 0x35, 0xa3, 0x5e, 0xca, 0xdc, 0x57, 0x2f,
40         0x3e, 0xf0, 0xc9, 0x5d, 0x86, 0x6a, 0xf8, 0xaf, 0x66, 0xa7,
41         0xed, 0xcd, 0xb8, 0xed, 0xa1, 0x5f, 0xba, 0x9b, 0x85, 0x1a,
42         0xd5, 0x9, 0xae, 0x94, 0x4e, 0x3b, 0xcf, 0xcb, 0x5c, 0xc9,
43         0x79, 0x80, 0xf7, 0xcc, 0xa6, 0x4a, 0xa8, 0x6a, 0xd8, 0xd3,
44         0x31, 0x11, 0xf9, 0xf6, 0x2, 0x63, 0x2a, 0x1a, 0x2d, 0xd1,
45         0x1a, 0x66, 0x1b, 0x16, 0x41, 0xbd, 0xbd, 0xf7, 0x4d, 0xc0,
46         0x4a, 0xe5, 0x27, 0x49, 0x5f, 0x7f, 0x58, 0xe3, 0x27, 0x2d,
47         0xe5, 0xc9, 0x66, 0xe, 0x52, 0x38, 0x16, 0x38, 0xfb, 0x16,
48         0xeb, 0x53, 0x3f, 0xe6, 0xfd, 0xe9, 0xa2, 0x5e, 0x25, 0x59,
49         0xd8, 0x79, 0x45, 0xff, 0x3, 0x4c, 0x26, 0xa2, 0x0, 0x5a,
50         0x8e, 0xc2, 0x51, 0xa1, 0x15, 0xf9, 0x7b, 0xf4, 0x5c, 0x81,
51         0x9b, 0x18, 0x47, 0x35, 0xd8, 0x2d, 0x5, 0xe9, 0xad, 0xf,
52         0x35, 0x74, 0x15, 0xa3, 0x8e, 0x8b, 0xcc, 0x27, 0xda, 0x7c,
53         0x5d, 0xe4, 0xfa, 0x4, 0xd3, 0x5, 0xb, 0xba, 0x3a, 0xb2,
54         0x49, 0x45, 0x2f, 0x47, 0xc7, 0xd, 0x41, 0x3f, 0x97, 0x80,
55         0x4d, 0x3f, 0xc1, 0xb5, 0xbb, 0x70, 0x5f, 0xa7, 0x37, 0xaf,
56         0x48, 0x22, 0x12, 0x45, 0x2e, 0xf5, 0xf, 0x87, 0x92, 0xe2,
57         0x84, 0x1, 0xf9, 0x12, 0xf, 0x14, 0x15, 0x24, 0xce, 0x89,
58         0x99, 0xee, 0xb9, 0xc4, 0x17, 0x70, 0x70, 0x15, 0xea, 0xbe,
59         0xc6, 0x6c, 0x1f, 0x62, 0xb3, 0xf4, 0x2d, 0x16, 0x87, 0xfb,
60         0x56, 0x1e, 0x45, 0xab, 0xae, 0x32, 0xe4, 0x5e, 0x91, 0xed,
61         0x53, 0x66, 0x5e, 0xbd, 0xed, 0xad, 0xe6, 0x12, 0x39, 0xd,
62         0x83, 0xc9, 0xe8, 0x6b, 0x6c, 0x2d, 0xa5, 0xee, 0xc4, 0x5a,
63         0x66, 0xae, 0x8c, 0x97, 0xd7, 0xd, 0x6c, 0x49, 0xc7, 0xf5,
64         0xc4, 0x92, 0x31, 0x8b, 0x9, 0xee, 0x33, 0xda, 0xa9, 0x37,
65         0xb6, 0x49, 0x18, 0xf8, 0xe, 0x60, 0x45, 0xc8, 0x33, 0x91,
66         0xef, 0x20, 0x57, 0x10, 0xbe, 0x78, 0x2d, 0x83, 0x26, 0xd6,
67         0xca, 0x61, 0xf9, 0x2f, 0xe0, 0xbf, 0x5, 0x30, 0x52, 0x5a,
68         0x12, 0x1c, 0x0, 0xa7, 0x5d, 0xcc, 0x7c, 0x2e, 0xc5, 0x95,
69         0x8b, 0xa3, 0x3b, 0xf0, 0x43, 0x2e, 0x5e, 0xdd, 0x0, 0xdb,
70         0xd, 0xb3, 0x37, 0x99, 0xa9, 0xcd, 0x9c, 0xb7, 0x43, 0xf7,
71         0x35, 0x44, 0x21, 0xc2, 0x82, 0x71, 0xab, 0x8d, 0xaa, 0xb4,
72         0x41, 0x11, 0xec, 0x1e, 0x8d, 0xfc, 0x14, 0x82, 0x92, 0x4e,
73         0x83, 0x6a, 0xa, 0x6b, 0x35, 0x5e, 0x5d, 0xe9, 0x5c, 0xcc,
74         0x8c, 0xde, 0x39, 0xd1, 0x4a, 0x5b, 0x5f, 0x63, 0xa9, 0x64,
75         0xe0, 0xa, 0xcb, 0xb, 0xb8, 0x5a, 0x7c, 0xc3, 0xb, 0xe6,
76         0xbe, 0xfe, 0x8b, 0xf, 0x7d, 0x34, 0x8e, 0x2, 0x66, 0x74,
77         0x1, 0x6c, 0xca, 0x76, 0xac, 0x7c, 0x67, 0x8, 0x2f, 0x3f,
78         0x1a, 0xa6, 0x2c, 0x60, 0xb3, 0xff, 0xda, 0x8d, 0xb8, 0x12,
79         0xc, 0x0, 0x7f, 0xcc, 0x50, 0xa1, 0x5c, 0x64, 0xa1, 0xe2,
80         0x5f, 0x32, 0x65, 0xc9, 0x9c, 0xbe, 0xd6, 0xa, 0x13, 0x87,
81         0x3c, 0x2a, 0x45, 0x47, 0xc, 0xca, 0x42, 0x82, 0xfa, 0x89,
82         0x65, 0xe7, 0x89, 0xb4, 0x8f, 0xf7, 0x1e, 0xe6, 0x23, 0xa5,
83         0xd0, 0x59, 0x37, 0x79, 0x92, 0xd7, 0xce, 0x3d, 0xfd, 0xe3,
84         0xa1, 0xb, 0xcf, 0x6c, 0x85, 0xa0, 0x65, 0xf3, 0x5c, 0xc6,
85         0x4a, 0x63, 0x5f, 0x6e, 0x3a, 0x3a, 0x2a, 0x8b, 0x6a, 0xb6,
86         0x2f, 0xbb, 0xf8, 0xb2, 0x4b, 0x62, 0xbc, 0x1a, 0x91, 0x25,
87         0x66, 0xe3, 0x69, 0xca, 0x60, 0x49, 0xb, 0xf6, 0x8a, 0xbe,
88         0x3e, 0x76, 0x53, 0xc2, 0x7a, 0xa8, 0x4, 0x17, 0x75, 0xf1,
89         0xf3, 0x3, 0x62, 0x1b, 0x85, 0xb2, 0xb0, 0xef, 0x80, 0x15,
90         0xb6, 0xd4, 0x4e, 0xdf, 0x71, 0xac, 0xdb, 0x2a, 0x4, 0xd4,
91         0xb4, 0x21, 0xba, 0x65, 0x56, 0x57, 0xe8, 0xfa, 0x84, 0xa2,
92         0x7d, 0x13, 0xe, 0xaf, 0xd7, 0x9a, 0x58, 0x2a, 0xa3, 0x81,
93         0x84, 0x8d, 0x9, 0xa0, 0x6a, 0xc1, 0xbb, 0xd9, 0xf5, 0x86,
94         0xac, 0xbd, 0x75, 0x61, 0x9, 0xe6, 0x8c, 0x3d, 0x77, 0xb2,
95         0xed, 0x30, 0x20, 0xe4, 0x0, 0x1d, 0x97, 0xe8, 0xbf, 0xc7,
96         0x0, 0x1b, 0x21, 0xb1, 0x16, 0xe7, 0x41, 0x67, 0x2e, 0xec,
97         0x38, 0xbc, 0xe5, 0x1b, 0xb4, 0x6, 0x23, 0x31, 0x71, 0x1c,
98         0x49, 0xcd, 0x76, 0x4a, 0x76, 0x36, 0x8d, 0xa3, 0x89, 0x8b,
99         0x4a, 0x7a, 0xf4, 0x87, 0xc8, 0x15, 0xf, 0x37, 0x39, 0xf6,
100         0x6d, 0x80, 0x19, 0xef, 0x5c, 0xa8, 0x66, 0xce, 0x1b, 0x16,
101         0x79, 0x21, 0xdf, 0xd7, 0x31, 0x30, 0xc4, 0x21, 0xdd, 0x34,
102         0x5b, 0xd2, 0x1a, 0x2b, 0x3e, 0x5d, 0xf7, 0xea, 0xca, 0x5,
103         0x8e, 0xb7, 0xcb, 0x49, 0x2e, 0xa0, 0xe3, 0xf4, 0xa7, 0x48,
104         0x19, 0x10, 0x9c, 0x4, 0xa7, 0xf4, 0x28, 0x74, 0xc8, 0x6f,
105         0x63, 0x20, 0x2b, 0x46, 0x24, 0x26, 0x19, 0x1d, 0xd1, 0x2c,
106         0x31, 0x6d, 0x5a, 0x29, 0xa2, 0x6, 0xa6, 0xb2, 0x41, 0xcc,
107         0xa, 0x27, 0x96, 0x9, 0x96, 0xac, 0x47, 0x65, 0x78, 0x68,
108         0x51, 0x98, 0xd6, 0xd8, 0xa6, 0x2d, 0xa0, 0xcf, 0xec, 0xe2,
109         0x74, 0xf2, 0x82, 0xe3, 0x97, 0xd9, 0x7e, 0xd4, 0xf8, 0xb,
110         0x70, 0x43, 0x3d, 0xb1, 0x7b, 0x97, 0x80, 0xd6, 0xcb, 0xd7,
111         0x19, 0xbc, 0x63, 0xb, 0xfd, 0x4d, 0x88, 0xfe, 0x67, 0xac,
112         0xb8, 0xcc, 0x50, 0xb7, 0x68, 0xb3, 0x5b, 0xd6, 0x1e, 0x25,
113         0xfc, 0x5f, 0x3c, 0x8d, 0xb1, 0x33, 0x7c, 0xb3, 0x49, 0x1,
114         0x3f, 0x71, 0x55, 0xe, 0x51, 0xba, 0x61, 0x26, 0xfa, 0xea,
115         0xe5, 0xb5, 0xe8, 0xaa, 0xcf, 0xcd, 0x96, 0x9f, 0xd6, 0xc1,
116         0x5f, 0x53, 0x91, 0xad, 0x5, 0xde, 0x20, 0xe7, 0x51, 0xda,
117         0x5b, 0x95, 0x67, 0xed, 0xf4, 0xee, 0x42, 0x65, 0x70, 0x13,
118         0xb, 0x70, 0x14, 0x1c, 0xc9, 0xe0, 0x19, 0xca, 0x5f, 0xf5,
119         0x1d, 0x70, 0x4b, 0x6c, 0x6, 0x74, 0xec, 0xb5, 0x2e, 0x77,
120         0xe1, 0x74, 0xa1, 0xa3, 0x99, 0xa0, 0x85, 0x9e, 0xf1, 0xac,
121         0xd8, 0x7e,
122 };
123
124 /**
125  * ============================================================================
126  * Boot states support (GREEN, YELLOW, ORANGE, RED) and dm_verity
127  * ============================================================================
128  */
129 char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state)
130 {
131         struct AvbOpsData *data;
132         char *cmdline = NULL;
133
134         if (!ops)
135                 return NULL;
136
137         data = (struct AvbOpsData *)ops->user_data;
138         if (!data)
139                 return NULL;
140
141         data->boot_state = boot_state;
142         switch (boot_state) {
143         case AVB_GREEN:
144                 cmdline = "androidboot.verifiedbootstate=green";
145                 break;
146         case AVB_YELLOW:
147                 cmdline = "androidboot.verifiedbootstate=yellow";
148                 break;
149         case AVB_ORANGE:
150                 cmdline = "androidboot.verifiedbootstate=orange";
151         case AVB_RED:
152                 break;
153         }
154
155         return cmdline;
156 }
157
158 char *append_cmd_line(char *cmdline_orig, char *cmdline_new)
159 {
160         char *cmd_line;
161
162         if (!cmdline_new)
163                 return cmdline_orig;
164
165         if (cmdline_orig)
166                 cmd_line = cmdline_orig;
167         else
168                 cmd_line = " ";
169
170         cmd_line = avb_strdupv(cmd_line, " ", cmdline_new, NULL);
171
172         return cmd_line;
173 }
174
175 static int avb_find_dm_args(char **args, char *str)
176 {
177         int i;
178
179         if (!str)
180                 return -1;
181
182         for (i = 0; i < AVB_MAX_ARGS && args[i]; ++i) {
183                 if (strstr(args[i], str))
184                         return i;
185         }
186
187         return -1;
188 }
189
190 static char *avb_set_enforce_option(const char *cmdline, const char *option)
191 {
192         char *cmdarg[AVB_MAX_ARGS];
193         char *newargs = NULL;
194         int i = 0;
195         int total_args;
196
197         memset(cmdarg, 0, sizeof(cmdarg));
198         cmdarg[i++] = strtok((char *)cmdline, " ");
199
200         do {
201                 cmdarg[i] = strtok(NULL, " ");
202                 if (!cmdarg[i])
203                         break;
204
205                 if (++i >= AVB_MAX_ARGS) {
206                         printf("%s: Can't handle more then %d args\n",
207                                __func__, i);
208                         return NULL;
209                 }
210         } while (true);
211
212         total_args = i;
213         i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_LOGGING);
214         if (i >= 0) {
215                 cmdarg[i] = (char *)option;
216         } else {
217                 i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_RESTART);
218                 if (i < 0) {
219                         printf("%s: No verity options found\n", __func__);
220                         return NULL;
221                 }
222
223                 cmdarg[i] = (char *)option;
224         }
225
226         for (i = 0; i <= total_args; i++)
227                 newargs = append_cmd_line(newargs, cmdarg[i]);
228
229         return newargs;
230 }
231
232 char *avb_set_ignore_corruption(const char *cmdline)
233 {
234         char *newargs = NULL;
235
236         newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_LOGGING);
237         if (newargs)
238                 newargs = append_cmd_line(newargs,
239                                           "androidboot.veritymode=eio");
240
241         return newargs;
242 }
243
244 char *avb_set_enforce_verity(const char *cmdline)
245 {
246         char *newargs;
247
248         newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_RESTART);
249         if (newargs)
250                 newargs = append_cmd_line(newargs,
251                                           "androidboot.veritymode=enforcing");
252         return newargs;
253 }
254
255 /**
256  * ============================================================================
257  * IO(mmc) auxiliary functions
258  * ============================================================================
259  */
260 static unsigned long mmc_read_and_flush(struct mmc_part *part,
261                                         lbaint_t start,
262                                         lbaint_t sectors,
263                                         void *buffer)
264 {
265         unsigned long blks;
266         void *tmp_buf;
267         size_t buf_size;
268         bool unaligned = is_buf_unaligned(buffer);
269
270         if (start < part->info.start) {
271                 printf("%s: partition start out of bounds\n", __func__);
272                 return 0;
273         }
274         if ((start + sectors) > (part->info.start + part->info.size)) {
275                 sectors = part->info.start + part->info.size - start;
276                 printf("%s: read sector aligned to partition bounds (%ld)\n",
277                        __func__, sectors);
278         }
279
280         /*
281          * Reading fails on unaligned buffers, so we have to
282          * use aligned temporary buffer and then copy to destination
283          */
284
285         if (unaligned) {
286                 printf("Handling unaligned read buffer..\n");
287                 tmp_buf = get_sector_buf();
288                 buf_size = get_sector_buf_size();
289                 if (sectors > buf_size / part->info.blksz)
290                         sectors = buf_size / part->info.blksz;
291         } else {
292                 tmp_buf = buffer;
293         }
294
295         blks = blk_dread(part->mmc_blk,
296                          start, sectors, tmp_buf);
297         /* flush cache after read */
298         flush_cache((ulong)tmp_buf, sectors * part->info.blksz);
299
300         if (unaligned)
301                 memcpy(buffer, tmp_buf, sectors * part->info.blksz);
302
303         return blks;
304 }
305
306 static unsigned long mmc_write(struct mmc_part *part, lbaint_t start,
307                                lbaint_t sectors, void *buffer)
308 {
309         void *tmp_buf;
310         size_t buf_size;
311         bool unaligned = is_buf_unaligned(buffer);
312
313         if (start < part->info.start) {
314                 printf("%s: partition start out of bounds\n", __func__);
315                 return 0;
316         }
317         if ((start + sectors) > (part->info.start + part->info.size)) {
318                 sectors = part->info.start + part->info.size - start;
319                 printf("%s: sector aligned to partition bounds (%ld)\n",
320                        __func__, sectors);
321         }
322         if (unaligned) {
323                 tmp_buf = get_sector_buf();
324                 buf_size = get_sector_buf_size();
325                 printf("Handling unaligned wrire buffer..\n");
326                 if (sectors > buf_size / part->info.blksz)
327                         sectors = buf_size / part->info.blksz;
328
329                 memcpy(tmp_buf, buffer, sectors * part->info.blksz);
330         } else {
331                 tmp_buf = buffer;
332         }
333
334         return blk_dwrite(part->mmc_blk,
335                           start, sectors, tmp_buf);
336 }
337
338 static struct mmc_part *get_partition(AvbOps *ops, const char *partition)
339 {
340         int ret;
341         u8 dev_num;
342         int part_num = 0;
343         struct mmc_part *part;
344         struct blk_desc *mmc_blk;
345
346         part = malloc(sizeof(struct mmc_part));
347         if (!part)
348                 return NULL;
349
350         dev_num = get_boot_device(ops);
351         part->mmc = find_mmc_device(dev_num);
352         if (!part->mmc) {
353                 printf("No MMC device at slot %x\n", dev_num);
354                 goto err;
355         }
356
357         if (mmc_init(part->mmc)) {
358                 printf("MMC initialization failed\n");
359                 goto err;
360         }
361
362         ret = mmc_switch_part(part->mmc, part_num);
363         if (ret)
364                 goto err;
365
366         mmc_blk = mmc_get_blk_desc(part->mmc);
367         if (!mmc_blk) {
368                 printf("Error - failed to obtain block descriptor\n");
369                 goto err;
370         }
371
372         ret = part_get_info_by_name(mmc_blk, partition, &part->info);
373         if (!ret) {
374                 printf("Can't find partition '%s'\n", partition);
375                 goto err;
376         }
377
378         part->dev_num = dev_num;
379         part->mmc_blk = mmc_blk;
380
381         return part;
382 err:
383         free(part);
384         return NULL;
385 }
386
387 static AvbIOResult mmc_byte_io(AvbOps *ops,
388                                const char *partition,
389                                s64 offset,
390                                size_t num_bytes,
391                                void *buffer,
392                                size_t *out_num_read,
393                                enum mmc_io_type io_type)
394 {
395         ulong ret;
396         struct mmc_part *part;
397         u64 start_offset, start_sector, sectors, residue;
398         u8 *tmp_buf;
399         size_t io_cnt = 0;
400
401         if (!partition || !buffer || io_type > IO_WRITE)
402                 return AVB_IO_RESULT_ERROR_IO;
403
404         part = get_partition(ops, partition);
405         if (!part)
406                 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
407
408         if (!part->info.blksz)
409                 return AVB_IO_RESULT_ERROR_IO;
410
411         start_offset = calc_offset(part, offset);
412         while (num_bytes) {
413                 start_sector = start_offset / part->info.blksz;
414                 sectors = num_bytes / part->info.blksz;
415                 /* handle non block-aligned reads */
416                 if (start_offset % part->info.blksz ||
417                     num_bytes < part->info.blksz) {
418                         tmp_buf = get_sector_buf();
419                         if (start_offset % part->info.blksz) {
420                                 residue = part->info.blksz -
421                                         (start_offset % part->info.blksz);
422                                 if (residue > num_bytes)
423                                         residue = num_bytes;
424                         } else {
425                                 residue = num_bytes;
426                         }
427
428                         if (io_type == IO_READ) {
429                                 ret = mmc_read_and_flush(part,
430                                                          part->info.start +
431                                                          start_sector,
432                                                          1, tmp_buf);
433
434                                 if (ret != 1) {
435                                         printf("%s: read error (%ld, %lld)\n",
436                                                __func__, ret, start_sector);
437                                         return AVB_IO_RESULT_ERROR_IO;
438                                 }
439                                 /*
440                                  * if this is not aligned at sector start,
441                                  * we have to adjust the tmp buffer
442                                  */
443                                 tmp_buf += (start_offset % part->info.blksz);
444                                 memcpy(buffer, (void *)tmp_buf, residue);
445                         } else {
446                                 ret = mmc_read_and_flush(part,
447                                                          part->info.start +
448                                                          start_sector,
449                                                          1, tmp_buf);
450
451                                 if (ret != 1) {
452                                         printf("%s: read error (%ld, %lld)\n",
453                                                __func__, ret, start_sector);
454                                         return AVB_IO_RESULT_ERROR_IO;
455                                 }
456                                 memcpy((void *)tmp_buf +
457                                         start_offset % part->info.blksz,
458                                         buffer, residue);
459
460                                 ret = mmc_write(part, part->info.start +
461                                                 start_sector, 1, tmp_buf);
462                                 if (ret != 1) {
463                                         printf("%s: write error (%ld, %lld)\n",
464                                                __func__, ret, start_sector);
465                                         return AVB_IO_RESULT_ERROR_IO;
466                                 }
467                         }
468
469                         io_cnt += residue;
470                         buffer += residue;
471                         start_offset += residue;
472                         num_bytes -= residue;
473                         continue;
474                 }
475
476                 if (sectors) {
477                         if (io_type == IO_READ) {
478                                 ret = mmc_read_and_flush(part,
479                                                          part->info.start +
480                                                          start_sector,
481                                                          sectors, buffer);
482                         } else {
483                                 ret = mmc_write(part,
484                                                 part->info.start +
485                                                 start_sector,
486                                                 sectors, buffer);
487                         }
488
489                         if (!ret) {
490                                 printf("%s: sector read error\n", __func__);
491                                 return AVB_IO_RESULT_ERROR_IO;
492                         }
493
494                         io_cnt += ret * part->info.blksz;
495                         buffer += ret * part->info.blksz;
496                         start_offset += ret * part->info.blksz;
497                         num_bytes -= ret * part->info.blksz;
498                 }
499         }
500
501         /* Set counter for read operation */
502         if (io_type == IO_READ && out_num_read)
503                 *out_num_read = io_cnt;
504
505         return AVB_IO_RESULT_OK;
506 }
507
508 /**
509  * ============================================================================
510  * AVB 2.0 operations
511  * ============================================================================
512  */
513
514 /**
515  * read_from_partition() - reads @num_bytes from  @offset from partition
516  * identified by a string name
517  *
518  * @ops: contains AVB ops handlers
519  * @partition_name: partition name, NUL-terminated UTF-8 string
520  * @offset: offset from the beginning of partition
521  * @num_bytes: amount of bytes to read
522  * @buffer: destination buffer to store data
523  * @out_num_read:
524  *
525  * @return:
526  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
527  *      AVB_IO_RESULT_ERROR_IO, if i/o error occurred from the underlying i/o
528  *            subsystem
529  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if there is no partition with
530  *      the given name
531  */
532 static AvbIOResult read_from_partition(AvbOps *ops,
533                                        const char *partition_name,
534                                        s64 offset_from_partition,
535                                        size_t num_bytes,
536                                        void *buffer,
537                                        size_t *out_num_read)
538 {
539         return mmc_byte_io(ops, partition_name, offset_from_partition,
540                            num_bytes, buffer, out_num_read, IO_READ);
541 }
542
543 /**
544  * write_to_partition() - writes N bytes to a partition identified by a string
545  * name
546  *
547  * @ops: AvbOps, contains AVB ops handlers
548  * @partition_name: partition name
549  * @offset_from_partition: offset from the beginning of partition
550  * @num_bytes: amount of bytes to write
551  * @buf: data to write
552  * @out_num_read:
553  *
554  * @return:
555  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
556  *      AVB_IO_RESULT_ERROR_IO, if input/output error occurred
557  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition, specified in
558  *            @partition_name was not found
559  */
560 static AvbIOResult write_to_partition(AvbOps *ops,
561                                       const char *partition_name,
562                                       s64 offset_from_partition,
563                                       size_t num_bytes,
564                                       const void *buffer)
565 {
566         return mmc_byte_io(ops, partition_name, offset_from_partition,
567                            num_bytes, (void *)buffer, NULL, IO_WRITE);
568 }
569
570 /**
571  * validate_vmbeta_public_key() - checks if the given public key used to sign
572  * the vbmeta partition is trusted
573  *
574  * @ops: AvbOps, contains AVB ops handlers
575  * @public_key_data: public key for verifying vbmeta partition signature
576  * @public_key_length: length of public key
577  * @public_key_metadata:
578  * @public_key_metadata_length:
579  * @out_key_is_trusted:
580  *
581  * @return:
582  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
583  */
584 static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
585                                               const u8 *public_key_data,
586                                               size_t public_key_length,
587                                               const u8
588                                               *public_key_metadata,
589                                               size_t
590                                               public_key_metadata_length,
591                                               bool *out_key_is_trusted)
592 {
593         if (!public_key_length || !public_key_data || !out_key_is_trusted)
594                 return AVB_IO_RESULT_ERROR_IO;
595
596         *out_key_is_trusted = false;
597         if (public_key_length != sizeof(avb_root_pub))
598                 return AVB_IO_RESULT_ERROR_IO;
599
600         if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0)
601                 *out_key_is_trusted = true;
602
603         return AVB_IO_RESULT_OK;
604 }
605
606 #ifdef CONFIG_OPTEE_TA_AVB
607 static int get_open_session(struct AvbOpsData *ops_data)
608 {
609         struct udevice *tee = NULL;
610
611         while (!ops_data->tee) {
612                 const struct tee_optee_ta_uuid uuid = TA_AVB_UUID;
613                 struct tee_open_session_arg arg;
614                 int rc;
615
616                 tee = tee_find_device(tee, NULL, NULL, NULL);
617                 if (!tee)
618                         return -ENODEV;
619
620                 memset(&arg, 0, sizeof(arg));
621                 tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
622                 rc = tee_open_session(tee, &arg, 0, NULL);
623                 if (!rc) {
624                         ops_data->tee = tee;
625                         ops_data->session = arg.session;
626                 }
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 }