dm: Add Hardware Spinlock class
[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 <fastboot.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) {
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_TARGET_DEAD:
651                 /*
652                  * The TA has paniced, close the session to reload the TA
653                  * for the next request.
654                  */
655                 tee_close_session(ops_data->tee, ops_data->session);
656                 ops_data->tee = NULL;
657                 return AVB_IO_RESULT_ERROR_IO;
658         default:
659                 return AVB_IO_RESULT_ERROR_IO;
660         }
661 }
662 #endif
663
664 /**
665  * read_rollback_index() - gets the rollback index corresponding to the
666  * location of given by @out_rollback_index.
667  *
668  * @ops: contains AvbOps handlers
669  * @rollback_index_slot:
670  * @out_rollback_index: used to write a retrieved rollback index.
671  *
672  * @return
673  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
674  */
675 static AvbIOResult read_rollback_index(AvbOps *ops,
676                                        size_t rollback_index_slot,
677                                        u64 *out_rollback_index)
678 {
679 #ifndef CONFIG_OPTEE_TA_AVB
680         /* For now we always return 0 as the stored rollback index. */
681         printf("%s not supported yet\n", __func__);
682
683         if (out_rollback_index)
684                 *out_rollback_index = 0;
685
686         return AVB_IO_RESULT_OK;
687 #else
688         AvbIOResult rc;
689         struct tee_param param[2];
690
691         if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
692                 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
693
694         memset(param, 0, sizeof(param));
695         param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
696         param[0].u.value.a = rollback_index_slot;
697         param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;
698
699         rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_ROLLBACK_INDEX,
700                          ARRAY_SIZE(param), param);
701         if (rc)
702                 return rc;
703
704         *out_rollback_index = (u64)param[1].u.value.a << 32 |
705                               (u32)param[1].u.value.b;
706         return AVB_IO_RESULT_OK;
707 #endif
708 }
709
710 /**
711  * write_rollback_index() - sets the rollback index corresponding to the
712  * location of given by @out_rollback_index.
713  *
714  * @ops: contains AvbOps handlers
715  * @rollback_index_slot:
716  * @rollback_index: rollback index to write.
717  *
718  * @return
719  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
720  */
721 static AvbIOResult write_rollback_index(AvbOps *ops,
722                                         size_t rollback_index_slot,
723                                         u64 rollback_index)
724 {
725 #ifndef CONFIG_OPTEE_TA_AVB
726         /* For now this is a no-op. */
727         printf("%s not supported yet\n", __func__);
728
729         return AVB_IO_RESULT_OK;
730 #else
731         struct tee_param param[2];
732
733         if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
734                 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
735
736         memset(param, 0, sizeof(param));
737         param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
738         param[0].u.value.a = rollback_index_slot;
739         param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
740         param[1].u.value.a = (u32)(rollback_index >> 32);
741         param[1].u.value.b = (u32)rollback_index;
742
743         return invoke_func(ops->user_data, TA_AVB_CMD_WRITE_ROLLBACK_INDEX,
744                            ARRAY_SIZE(param), param);
745 #endif
746 }
747
748 /**
749  * read_is_device_unlocked() - gets whether the device is unlocked
750  *
751  * @ops: contains AVB ops handlers
752  * @out_is_unlocked: device unlock state is stored here, true if unlocked,
753  *       false otherwise
754  *
755  * @return:
756  *       AVB_IO_RESULT_OK: state is retrieved successfully
757  *       AVB_IO_RESULT_ERROR_IO: an error occurred
758  */
759 static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
760 {
761 #ifndef CONFIG_OPTEE_TA_AVB
762         /* For now we always return that the device is unlocked. */
763
764         printf("%s not supported yet\n", __func__);
765
766         *out_is_unlocked = true;
767
768         return AVB_IO_RESULT_OK;
769 #else
770         AvbIOResult rc;
771         struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT };
772
773         rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_LOCK_STATE, 1, &param);
774         if (rc)
775                 return rc;
776         *out_is_unlocked = !param.u.value.a;
777         return AVB_IO_RESULT_OK;
778 #endif
779 }
780
781 /**
782  * get_unique_guid_for_partition() - gets the GUID for a partition identified
783  * by a string name
784  *
785  * @ops: contains AVB ops handlers
786  * @partition: partition name (NUL-terminated UTF-8 string)
787  * @guid_buf: buf, used to copy in GUID string. Example of value:
788  *      527c1c6d-6361-4593-8842-3c78fcd39219
789  * @guid_buf_size: @guid_buf buffer size
790  *
791  * @return:
792  *      AVB_IO_RESULT_OK, on success (GUID found)
793  *      AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
794  *             provided
795  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
796  */
797 static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
798                                                  const char *partition,
799                                                  char *guid_buf,
800                                                  size_t guid_buf_size)
801 {
802         struct mmc_part *part;
803         size_t uuid_size;
804
805         part = get_partition(ops, partition);
806         if (!part)
807                 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
808
809         uuid_size = sizeof(part->info.uuid);
810         if (uuid_size > guid_buf_size)
811                 return AVB_IO_RESULT_ERROR_IO;
812
813         memcpy(guid_buf, part->info.uuid, uuid_size);
814         guid_buf[uuid_size - 1] = 0;
815
816         return AVB_IO_RESULT_OK;
817 }
818
819 /**
820  * get_size_of_partition() - gets the size of a partition identified
821  * by a string name
822  *
823  * @ops: contains AVB ops handlers
824  * @partition: partition name (NUL-terminated UTF-8 string)
825  * @out_size_num_bytes: returns the value of a partition size
826  *
827  * @return:
828  *      AVB_IO_RESULT_OK, on success (GUID found)
829  *      AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE, out_size_num_bytes is NULL
830  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
831  */
832 static AvbIOResult get_size_of_partition(AvbOps *ops,
833                                          const char *partition,
834                                          u64 *out_size_num_bytes)
835 {
836         struct mmc_part *part;
837
838         if (!out_size_num_bytes)
839                 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
840
841         part = get_partition(ops, partition);
842         if (!part)
843                 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
844
845         *out_size_num_bytes = part->info.blksz * part->info.size;
846
847         return AVB_IO_RESULT_OK;
848 }
849
850 /**
851  * ============================================================================
852  * AVB2.0 AvbOps alloc/initialisation/free
853  * ============================================================================
854  */
855 AvbOps *avb_ops_alloc(int boot_device)
856 {
857         struct AvbOpsData *ops_data;
858
859         ops_data = avb_calloc(sizeof(struct AvbOpsData));
860         if (!ops_data)
861                 return NULL;
862
863         ops_data->ops.user_data = ops_data;
864
865         ops_data->ops.read_from_partition = read_from_partition;
866         ops_data->ops.write_to_partition = write_to_partition;
867         ops_data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key;
868         ops_data->ops.read_rollback_index = read_rollback_index;
869         ops_data->ops.write_rollback_index = write_rollback_index;
870         ops_data->ops.read_is_device_unlocked = read_is_device_unlocked;
871         ops_data->ops.get_unique_guid_for_partition =
872                 get_unique_guid_for_partition;
873         ops_data->ops.get_size_of_partition = get_size_of_partition;
874         ops_data->mmc_dev = boot_device;
875
876         return &ops_data->ops;
877 }
878
879 void avb_ops_free(AvbOps *ops)
880 {
881         struct AvbOpsData *ops_data;
882
883         if (!ops)
884                 return;
885
886         ops_data = ops->user_data;
887
888         if (ops_data) {
889 #ifdef CONFIG_OPTEE_TA_AVB
890                 if (ops_data->tee)
891                         tee_close_session(ops_data->tee, ops_data->session);
892 #endif
893                 avb_free(ops_data);
894         }
895 }