Merge https://gitlab.denx.de/u-boot/custodians/u-boot-samsung
[pandora-u-boot.git] / common / avb_verify.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2018, Linaro Limited
4  */
5
6 #include <avb_verify.h>
7 #include <blk.h>
8 #include <cpu_func.h>
9 #include <image.h>
10 #include <malloc.h>
11 #include <part.h>
12 #include <tee.h>
13 #include <tee/optee_ta_avb.h>
14
15 static const unsigned char avb_root_pub[1032] = {
16         0x0, 0x0, 0x10, 0x0, 0x55, 0xd9, 0x4, 0xad, 0xd8, 0x4,
17         0xaf, 0xe3, 0xd3, 0x84, 0x6c, 0x7e, 0xd, 0x89, 0x3d, 0xc2,
18         0x8c, 0xd3, 0x12, 0x55, 0xe9, 0x62, 0xc9, 0xf1, 0xf, 0x5e,
19         0xcc, 0x16, 0x72, 0xab, 0x44, 0x7c, 0x2c, 0x65, 0x4a, 0x94,
20         0xb5, 0x16, 0x2b, 0x0, 0xbb, 0x6, 0xef, 0x13, 0x7, 0x53,
21         0x4c, 0xf9, 0x64, 0xb9, 0x28, 0x7a, 0x1b, 0x84, 0x98, 0x88,
22         0xd8, 0x67, 0xa4, 0x23, 0xf9, 0xa7, 0x4b, 0xdc, 0x4a, 0xf,
23         0xf7, 0x3a, 0x18, 0xae, 0x54, 0xa8, 0x15, 0xfe, 0xb0, 0xad,
24         0xac, 0x35, 0xda, 0x3b, 0xad, 0x27, 0xbc, 0xaf, 0xe8, 0xd3,
25         0x2f, 0x37, 0x34, 0xd6, 0x51, 0x2b, 0x6c, 0x5a, 0x27, 0xd7,
26         0x96, 0x6, 0xaf, 0x6b, 0xb8, 0x80, 0xca, 0xfa, 0x30, 0xb4,
27         0xb1, 0x85, 0xb3, 0x4d, 0xaa, 0xaa, 0xc3, 0x16, 0x34, 0x1a,
28         0xb8, 0xe7, 0xc7, 0xfa, 0xf9, 0x9, 0x77, 0xab, 0x97, 0x93,
29         0xeb, 0x44, 0xae, 0xcf, 0x20, 0xbc, 0xf0, 0x80, 0x11, 0xdb,
30         0x23, 0xc, 0x47, 0x71, 0xb9, 0x6d, 0xd6, 0x7b, 0x60, 0x47,
31         0x87, 0x16, 0x56, 0x93, 0xb7, 0xc2, 0x2a, 0x9a, 0xb0, 0x4c,
32         0x1, 0xc, 0x30, 0xd8, 0x93, 0x87, 0xf0, 0xed, 0x6e, 0x8b,
33         0xbe, 0x30, 0x5b, 0xf6, 0xa6, 0xaf, 0xdd, 0x80, 0x7c, 0x45,
34         0x5e, 0x8f, 0x91, 0x93, 0x5e, 0x44, 0xfe, 0xb8, 0x82, 0x7,
35         0xee, 0x79, 0xca, 0xbf, 0x31, 0x73, 0x62, 0x58, 0xe3, 0xcd,
36         0xc4, 0xbc, 0xc2, 0x11, 0x1d, 0xa1, 0x4a, 0xbf, 0xfe, 0x27,
37         0x7d, 0xa1, 0xf6, 0x35, 0xa3, 0x5e, 0xca, 0xdc, 0x57, 0x2f,
38         0x3e, 0xf0, 0xc9, 0x5d, 0x86, 0x6a, 0xf8, 0xaf, 0x66, 0xa7,
39         0xed, 0xcd, 0xb8, 0xed, 0xa1, 0x5f, 0xba, 0x9b, 0x85, 0x1a,
40         0xd5, 0x9, 0xae, 0x94, 0x4e, 0x3b, 0xcf, 0xcb, 0x5c, 0xc9,
41         0x79, 0x80, 0xf7, 0xcc, 0xa6, 0x4a, 0xa8, 0x6a, 0xd8, 0xd3,
42         0x31, 0x11, 0xf9, 0xf6, 0x2, 0x63, 0x2a, 0x1a, 0x2d, 0xd1,
43         0x1a, 0x66, 0x1b, 0x16, 0x41, 0xbd, 0xbd, 0xf7, 0x4d, 0xc0,
44         0x4a, 0xe5, 0x27, 0x49, 0x5f, 0x7f, 0x58, 0xe3, 0x27, 0x2d,
45         0xe5, 0xc9, 0x66, 0xe, 0x52, 0x38, 0x16, 0x38, 0xfb, 0x16,
46         0xeb, 0x53, 0x3f, 0xe6, 0xfd, 0xe9, 0xa2, 0x5e, 0x25, 0x59,
47         0xd8, 0x79, 0x45, 0xff, 0x3, 0x4c, 0x26, 0xa2, 0x0, 0x5a,
48         0x8e, 0xc2, 0x51, 0xa1, 0x15, 0xf9, 0x7b, 0xf4, 0x5c, 0x81,
49         0x9b, 0x18, 0x47, 0x35, 0xd8, 0x2d, 0x5, 0xe9, 0xad, 0xf,
50         0x35, 0x74, 0x15, 0xa3, 0x8e, 0x8b, 0xcc, 0x27, 0xda, 0x7c,
51         0x5d, 0xe4, 0xfa, 0x4, 0xd3, 0x5, 0xb, 0xba, 0x3a, 0xb2,
52         0x49, 0x45, 0x2f, 0x47, 0xc7, 0xd, 0x41, 0x3f, 0x97, 0x80,
53         0x4d, 0x3f, 0xc1, 0xb5, 0xbb, 0x70, 0x5f, 0xa7, 0x37, 0xaf,
54         0x48, 0x22, 0x12, 0x45, 0x2e, 0xf5, 0xf, 0x87, 0x92, 0xe2,
55         0x84, 0x1, 0xf9, 0x12, 0xf, 0x14, 0x15, 0x24, 0xce, 0x89,
56         0x99, 0xee, 0xb9, 0xc4, 0x17, 0x70, 0x70, 0x15, 0xea, 0xbe,
57         0xc6, 0x6c, 0x1f, 0x62, 0xb3, 0xf4, 0x2d, 0x16, 0x87, 0xfb,
58         0x56, 0x1e, 0x45, 0xab, 0xae, 0x32, 0xe4, 0x5e, 0x91, 0xed,
59         0x53, 0x66, 0x5e, 0xbd, 0xed, 0xad, 0xe6, 0x12, 0x39, 0xd,
60         0x83, 0xc9, 0xe8, 0x6b, 0x6c, 0x2d, 0xa5, 0xee, 0xc4, 0x5a,
61         0x66, 0xae, 0x8c, 0x97, 0xd7, 0xd, 0x6c, 0x49, 0xc7, 0xf5,
62         0xc4, 0x92, 0x31, 0x8b, 0x9, 0xee, 0x33, 0xda, 0xa9, 0x37,
63         0xb6, 0x49, 0x18, 0xf8, 0xe, 0x60, 0x45, 0xc8, 0x33, 0x91,
64         0xef, 0x20, 0x57, 0x10, 0xbe, 0x78, 0x2d, 0x83, 0x26, 0xd6,
65         0xca, 0x61, 0xf9, 0x2f, 0xe0, 0xbf, 0x5, 0x30, 0x52, 0x5a,
66         0x12, 0x1c, 0x0, 0xa7, 0x5d, 0xcc, 0x7c, 0x2e, 0xc5, 0x95,
67         0x8b, 0xa3, 0x3b, 0xf0, 0x43, 0x2e, 0x5e, 0xdd, 0x0, 0xdb,
68         0xd, 0xb3, 0x37, 0x99, 0xa9, 0xcd, 0x9c, 0xb7, 0x43, 0xf7,
69         0x35, 0x44, 0x21, 0xc2, 0x82, 0x71, 0xab, 0x8d, 0xaa, 0xb4,
70         0x41, 0x11, 0xec, 0x1e, 0x8d, 0xfc, 0x14, 0x82, 0x92, 0x4e,
71         0x83, 0x6a, 0xa, 0x6b, 0x35, 0x5e, 0x5d, 0xe9, 0x5c, 0xcc,
72         0x8c, 0xde, 0x39, 0xd1, 0x4a, 0x5b, 0x5f, 0x63, 0xa9, 0x64,
73         0xe0, 0xa, 0xcb, 0xb, 0xb8, 0x5a, 0x7c, 0xc3, 0xb, 0xe6,
74         0xbe, 0xfe, 0x8b, 0xf, 0x7d, 0x34, 0x8e, 0x2, 0x66, 0x74,
75         0x1, 0x6c, 0xca, 0x76, 0xac, 0x7c, 0x67, 0x8, 0x2f, 0x3f,
76         0x1a, 0xa6, 0x2c, 0x60, 0xb3, 0xff, 0xda, 0x8d, 0xb8, 0x12,
77         0xc, 0x0, 0x7f, 0xcc, 0x50, 0xa1, 0x5c, 0x64, 0xa1, 0xe2,
78         0x5f, 0x32, 0x65, 0xc9, 0x9c, 0xbe, 0xd6, 0xa, 0x13, 0x87,
79         0x3c, 0x2a, 0x45, 0x47, 0xc, 0xca, 0x42, 0x82, 0xfa, 0x89,
80         0x65, 0xe7, 0x89, 0xb4, 0x8f, 0xf7, 0x1e, 0xe6, 0x23, 0xa5,
81         0xd0, 0x59, 0x37, 0x79, 0x92, 0xd7, 0xce, 0x3d, 0xfd, 0xe3,
82         0xa1, 0xb, 0xcf, 0x6c, 0x85, 0xa0, 0x65, 0xf3, 0x5c, 0xc6,
83         0x4a, 0x63, 0x5f, 0x6e, 0x3a, 0x3a, 0x2a, 0x8b, 0x6a, 0xb6,
84         0x2f, 0xbb, 0xf8, 0xb2, 0x4b, 0x62, 0xbc, 0x1a, 0x91, 0x25,
85         0x66, 0xe3, 0x69, 0xca, 0x60, 0x49, 0xb, 0xf6, 0x8a, 0xbe,
86         0x3e, 0x76, 0x53, 0xc2, 0x7a, 0xa8, 0x4, 0x17, 0x75, 0xf1,
87         0xf3, 0x3, 0x62, 0x1b, 0x85, 0xb2, 0xb0, 0xef, 0x80, 0x15,
88         0xb6, 0xd4, 0x4e, 0xdf, 0x71, 0xac, 0xdb, 0x2a, 0x4, 0xd4,
89         0xb4, 0x21, 0xba, 0x65, 0x56, 0x57, 0xe8, 0xfa, 0x84, 0xa2,
90         0x7d, 0x13, 0xe, 0xaf, 0xd7, 0x9a, 0x58, 0x2a, 0xa3, 0x81,
91         0x84, 0x8d, 0x9, 0xa0, 0x6a, 0xc1, 0xbb, 0xd9, 0xf5, 0x86,
92         0xac, 0xbd, 0x75, 0x61, 0x9, 0xe6, 0x8c, 0x3d, 0x77, 0xb2,
93         0xed, 0x30, 0x20, 0xe4, 0x0, 0x1d, 0x97, 0xe8, 0xbf, 0xc7,
94         0x0, 0x1b, 0x21, 0xb1, 0x16, 0xe7, 0x41, 0x67, 0x2e, 0xec,
95         0x38, 0xbc, 0xe5, 0x1b, 0xb4, 0x6, 0x23, 0x31, 0x71, 0x1c,
96         0x49, 0xcd, 0x76, 0x4a, 0x76, 0x36, 0x8d, 0xa3, 0x89, 0x8b,
97         0x4a, 0x7a, 0xf4, 0x87, 0xc8, 0x15, 0xf, 0x37, 0x39, 0xf6,
98         0x6d, 0x80, 0x19, 0xef, 0x5c, 0xa8, 0x66, 0xce, 0x1b, 0x16,
99         0x79, 0x21, 0xdf, 0xd7, 0x31, 0x30, 0xc4, 0x21, 0xdd, 0x34,
100         0x5b, 0xd2, 0x1a, 0x2b, 0x3e, 0x5d, 0xf7, 0xea, 0xca, 0x5,
101         0x8e, 0xb7, 0xcb, 0x49, 0x2e, 0xa0, 0xe3, 0xf4, 0xa7, 0x48,
102         0x19, 0x10, 0x9c, 0x4, 0xa7, 0xf4, 0x28, 0x74, 0xc8, 0x6f,
103         0x63, 0x20, 0x2b, 0x46, 0x24, 0x26, 0x19, 0x1d, 0xd1, 0x2c,
104         0x31, 0x6d, 0x5a, 0x29, 0xa2, 0x6, 0xa6, 0xb2, 0x41, 0xcc,
105         0xa, 0x27, 0x96, 0x9, 0x96, 0xac, 0x47, 0x65, 0x78, 0x68,
106         0x51, 0x98, 0xd6, 0xd8, 0xa6, 0x2d, 0xa0, 0xcf, 0xec, 0xe2,
107         0x74, 0xf2, 0x82, 0xe3, 0x97, 0xd9, 0x7e, 0xd4, 0xf8, 0xb,
108         0x70, 0x43, 0x3d, 0xb1, 0x7b, 0x97, 0x80, 0xd6, 0xcb, 0xd7,
109         0x19, 0xbc, 0x63, 0xb, 0xfd, 0x4d, 0x88, 0xfe, 0x67, 0xac,
110         0xb8, 0xcc, 0x50, 0xb7, 0x68, 0xb3, 0x5b, 0xd6, 0x1e, 0x25,
111         0xfc, 0x5f, 0x3c, 0x8d, 0xb1, 0x33, 0x7c, 0xb3, 0x49, 0x1,
112         0x3f, 0x71, 0x55, 0xe, 0x51, 0xba, 0x61, 0x26, 0xfa, 0xea,
113         0xe5, 0xb5, 0xe8, 0xaa, 0xcf, 0xcd, 0x96, 0x9f, 0xd6, 0xc1,
114         0x5f, 0x53, 0x91, 0xad, 0x5, 0xde, 0x20, 0xe7, 0x51, 0xda,
115         0x5b, 0x95, 0x67, 0xed, 0xf4, 0xee, 0x42, 0x65, 0x70, 0x13,
116         0xb, 0x70, 0x14, 0x1c, 0xc9, 0xe0, 0x19, 0xca, 0x5f, 0xf5,
117         0x1d, 0x70, 0x4b, 0x6c, 0x6, 0x74, 0xec, 0xb5, 0x2e, 0x77,
118         0xe1, 0x74, 0xa1, 0xa3, 0x99, 0xa0, 0x85, 0x9e, 0xf1, 0xac,
119         0xd8, 0x7e,
120 };
121
122 const char *str_avb_io_error(AvbIOResult res)
123 {
124         switch (res) {
125         case AVB_IO_RESULT_OK:
126                 return "Requested operation was successful";
127         case AVB_IO_RESULT_ERROR_IO:
128                 return "Underlying hardware encountered an I/O error";
129         case AVB_IO_RESULT_ERROR_OOM:
130                 return "Unable to allocate memory";
131         case AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION:
132                 return "Requested partition does not exist";
133         case AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION:
134                 return "Bytes requested is outside the range of partition";
135         case AVB_IO_RESULT_ERROR_NO_SUCH_VALUE:
136                 return "Named persistent value does not exist";
137         case AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE:
138                 return "Named persistent value size is not supported";
139         case AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE:
140                 return "Buffer is too small for the requested operation";
141         default:
142                 return "Unknown AVB error";
143         }
144 }
145
146 const char *str_avb_slot_error(AvbSlotVerifyResult res)
147 {
148         switch (res) {
149         case AVB_SLOT_VERIFY_RESULT_OK:
150                 return "Verification passed successfully";
151         case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
152                 return "Allocation of memory failed";
153         case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
154                 return "I/O error occurred while trying to load data";
155         case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
156                 return "Digest didn't match or signature checks failed";
157         case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
158                 return "Rollback index is less than its stored value";
159         case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
160                 return "Public keys are not accepted";
161         case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
162                 return "Metadata is invalid or inconsistent";
163         case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
164                 return "Metadata requires a newer version of libavb";
165         case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
166                 return "Invalid arguments are used";
167         default:
168                 return "Unknown AVB slot verification error";
169         }
170 }
171 /**
172  * ============================================================================
173  * Boot states support (GREEN, YELLOW, ORANGE, RED) and dm_verity
174  * ============================================================================
175  */
176 char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state)
177 {
178         struct AvbOpsData *data;
179         char *cmdline = NULL;
180
181         if (!ops)
182                 return NULL;
183
184         data = (struct AvbOpsData *)ops->user_data;
185         if (!data)
186                 return NULL;
187
188         data->boot_state = boot_state;
189         switch (boot_state) {
190         case AVB_GREEN:
191                 cmdline = "androidboot.verifiedbootstate=green";
192                 break;
193         case AVB_YELLOW:
194                 cmdline = "androidboot.verifiedbootstate=yellow";
195                 break;
196         case AVB_ORANGE:
197                 cmdline = "androidboot.verifiedbootstate=orange";
198         case AVB_RED:
199                 break;
200         }
201
202         return cmdline;
203 }
204
205 char *append_cmd_line(char *cmdline_orig, char *cmdline_new)
206 {
207         char *cmd_line;
208
209         if (!cmdline_new)
210                 return cmdline_orig;
211
212         if (cmdline_orig)
213                 cmd_line = cmdline_orig;
214         else
215                 cmd_line = " ";
216
217         cmd_line = avb_strdupv(cmd_line, " ", cmdline_new, NULL);
218
219         return cmd_line;
220 }
221
222 static int avb_find_dm_args(char **args, char *str)
223 {
224         int i;
225
226         if (!str)
227                 return -1;
228
229         for (i = 0; i < AVB_MAX_ARGS && args[i]; ++i) {
230                 if (strstr(args[i], str))
231                         return i;
232         }
233
234         return -1;
235 }
236
237 static char *avb_set_enforce_option(const char *cmdline, const char *option)
238 {
239         char *cmdarg[AVB_MAX_ARGS];
240         char *newargs = NULL;
241         int i = 0;
242         int total_args;
243
244         memset(cmdarg, 0, sizeof(cmdarg));
245         cmdarg[i++] = strtok((char *)cmdline, " ");
246
247         do {
248                 cmdarg[i] = strtok(NULL, " ");
249                 if (!cmdarg[i])
250                         break;
251
252                 if (++i >= AVB_MAX_ARGS) {
253                         printf("%s: Can't handle more then %d args\n",
254                                __func__, i);
255                         return NULL;
256                 }
257         } while (true);
258
259         total_args = i;
260         i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_LOGGING);
261         if (i >= 0) {
262                 cmdarg[i] = (char *)option;
263         } else {
264                 i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_RESTART);
265                 if (i < 0) {
266                         printf("%s: No verity options found\n", __func__);
267                         return NULL;
268                 }
269
270                 cmdarg[i] = (char *)option;
271         }
272
273         for (i = 0; i <= total_args; i++)
274                 newargs = append_cmd_line(newargs, cmdarg[i]);
275
276         return newargs;
277 }
278
279 char *avb_set_ignore_corruption(const char *cmdline)
280 {
281         char *newargs = NULL;
282
283         newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_LOGGING);
284         if (newargs)
285                 newargs = append_cmd_line(newargs,
286                                           "androidboot.veritymode=eio");
287
288         return newargs;
289 }
290
291 char *avb_set_enforce_verity(const char *cmdline)
292 {
293         char *newargs;
294
295         newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_RESTART);
296         if (newargs)
297                 newargs = append_cmd_line(newargs,
298                                           "androidboot.veritymode=enforcing");
299         return newargs;
300 }
301
302 /**
303  * ============================================================================
304  * IO(mmc) auxiliary functions
305  * ============================================================================
306  */
307 static unsigned long mmc_read_and_flush(struct mmc_part *part,
308                                         lbaint_t start,
309                                         lbaint_t sectors,
310                                         void *buffer)
311 {
312         unsigned long blks;
313         void *tmp_buf;
314         size_t buf_size;
315         bool unaligned = is_buf_unaligned(buffer);
316
317         if (start < part->info.start) {
318                 printf("%s: partition start out of bounds\n", __func__);
319                 return 0;
320         }
321         if ((start + sectors) > (part->info.start + part->info.size)) {
322                 sectors = part->info.start + part->info.size - start;
323                 printf("%s: read sector aligned to partition bounds (%ld)\n",
324                        __func__, sectors);
325         }
326
327         /*
328          * Reading fails on unaligned buffers, so we have to
329          * use aligned temporary buffer and then copy to destination
330          */
331         if (unaligned) {
332                 debug("%s: handling unaligned read buffer, addr = 0x%p\n",
333                       __func__, buffer);
334                 tmp_buf = get_sector_buf();
335                 buf_size = get_sector_buf_size();
336                 if (sectors > buf_size / part->info.blksz)
337                         sectors = buf_size / part->info.blksz;
338         } else {
339                 tmp_buf = buffer;
340         }
341
342         blks = blk_dread(part->mmc_blk,
343                          start, sectors, tmp_buf);
344         /* flush cache after read */
345         flush_cache((ulong)tmp_buf, sectors * part->info.blksz);
346
347         if (unaligned)
348                 memcpy(buffer, tmp_buf, sectors * part->info.blksz);
349
350         return blks;
351 }
352
353 static unsigned long mmc_write(struct mmc_part *part, lbaint_t start,
354                                lbaint_t sectors, void *buffer)
355 {
356         void *tmp_buf;
357         size_t buf_size;
358         bool unaligned = is_buf_unaligned(buffer);
359
360         if (start < part->info.start) {
361                 printf("%s: partition start out of bounds\n", __func__);
362                 return 0;
363         }
364         if ((start + sectors) > (part->info.start + part->info.size)) {
365                 sectors = part->info.start + part->info.size - start;
366                 printf("%s: sector aligned to partition bounds (%ld)\n",
367                        __func__, sectors);
368         }
369         if (unaligned) {
370                 tmp_buf = get_sector_buf();
371                 buf_size = get_sector_buf_size();
372                 debug("%s: handling unaligned read buffer, addr = 0x%p\n",
373                       __func__, buffer);
374                 if (sectors > buf_size / part->info.blksz)
375                         sectors = buf_size / part->info.blksz;
376
377                 memcpy(tmp_buf, buffer, sectors * part->info.blksz);
378         } else {
379                 tmp_buf = buffer;
380         }
381
382         return blk_dwrite(part->mmc_blk,
383                           start, sectors, tmp_buf);
384 }
385
386 static struct mmc_part *get_partition(AvbOps *ops, const char *partition)
387 {
388         int ret;
389         u8 dev_num;
390         int part_num = 0;
391         struct mmc_part *part;
392         struct blk_desc *mmc_blk;
393
394         part = malloc(sizeof(struct mmc_part));
395         if (!part)
396                 return NULL;
397
398         dev_num = get_boot_device(ops);
399         part->mmc = find_mmc_device(dev_num);
400         if (!part->mmc) {
401                 printf("%s: no MMC device at slot %x\n", __func__, dev_num);
402                 goto err;
403         }
404
405         ret = mmc_init(part->mmc);
406         if (ret) {
407                 printf("%s: MMC initialization failed, err = %d\n",
408                        __func__, ret);
409                 goto err;
410         }
411
412         if (IS_MMC(part->mmc)) {
413                 ret = mmc_switch_part(part->mmc, part_num);
414                 if (ret) {
415                         printf("%s: MMC part switch failed, err = %d\n",
416                                __func__, ret);
417                         goto err;
418                 }
419         }
420
421         mmc_blk = mmc_get_blk_desc(part->mmc);
422         if (!mmc_blk) {
423                 printf("%s: failed to obtain block descriptor\n", __func__);
424                 goto err;
425         }
426
427         ret = part_get_info_by_name(mmc_blk, partition, &part->info);
428         if (ret < 0) {
429                 printf("%s: can't find partition '%s'\n", __func__, partition);
430                 goto err;
431         }
432
433         part->dev_num = dev_num;
434         part->mmc_blk = mmc_blk;
435
436         return part;
437 err:
438         free(part);
439         return NULL;
440 }
441
442 static AvbIOResult mmc_byte_io(AvbOps *ops,
443                                const char *partition,
444                                s64 offset,
445                                size_t num_bytes,
446                                void *buffer,
447                                size_t *out_num_read,
448                                enum mmc_io_type io_type)
449 {
450         ulong ret;
451         struct mmc_part *part;
452         u64 start_offset, start_sector, sectors, residue;
453         u8 *tmp_buf;
454         size_t io_cnt = 0;
455
456         if (!partition || !buffer || io_type > IO_WRITE)
457                 return AVB_IO_RESULT_ERROR_IO;
458
459         part = get_partition(ops, partition);
460         if (!part)
461                 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
462
463         if (!part->info.blksz)
464                 return AVB_IO_RESULT_ERROR_IO;
465
466         start_offset = calc_offset(part, offset);
467         while (num_bytes) {
468                 start_sector = start_offset / part->info.blksz;
469                 sectors = num_bytes / part->info.blksz;
470                 /* handle non block-aligned reads */
471                 if (start_offset % part->info.blksz ||
472                     num_bytes < part->info.blksz) {
473                         tmp_buf = get_sector_buf();
474                         if (start_offset % part->info.blksz) {
475                                 residue = part->info.blksz -
476                                         (start_offset % part->info.blksz);
477                                 if (residue > num_bytes)
478                                         residue = num_bytes;
479                         } else {
480                                 residue = num_bytes;
481                         }
482
483                         if (io_type == IO_READ) {
484                                 ret = mmc_read_and_flush(part,
485                                                          part->info.start +
486                                                          start_sector,
487                                                          1, tmp_buf);
488
489                                 if (ret != 1) {
490                                         printf("%s: read error (%ld, %lld)\n",
491                                                __func__, ret, start_sector);
492                                         return AVB_IO_RESULT_ERROR_IO;
493                                 }
494                                 /*
495                                  * if this is not aligned at sector start,
496                                  * we have to adjust the tmp buffer
497                                  */
498                                 tmp_buf += (start_offset % part->info.blksz);
499                                 memcpy(buffer, (void *)tmp_buf, residue);
500                         } else {
501                                 ret = mmc_read_and_flush(part,
502                                                          part->info.start +
503                                                          start_sector,
504                                                          1, tmp_buf);
505
506                                 if (ret != 1) {
507                                         printf("%s: read error (%ld, %lld)\n",
508                                                __func__, ret, start_sector);
509                                         return AVB_IO_RESULT_ERROR_IO;
510                                 }
511                                 memcpy((void *)tmp_buf +
512                                         start_offset % part->info.blksz,
513                                         buffer, residue);
514
515                                 ret = mmc_write(part, part->info.start +
516                                                 start_sector, 1, tmp_buf);
517                                 if (ret != 1) {
518                                         printf("%s: write error (%ld, %lld)\n",
519                                                __func__, ret, start_sector);
520                                         return AVB_IO_RESULT_ERROR_IO;
521                                 }
522                         }
523
524                         io_cnt += residue;
525                         buffer += residue;
526                         start_offset += residue;
527                         num_bytes -= residue;
528                         continue;
529                 }
530
531                 if (sectors) {
532                         if (io_type == IO_READ) {
533                                 ret = mmc_read_and_flush(part,
534                                                          part->info.start +
535                                                          start_sector,
536                                                          sectors, buffer);
537                         } else {
538                                 ret = mmc_write(part,
539                                                 part->info.start +
540                                                 start_sector,
541                                                 sectors, buffer);
542                         }
543
544                         if (!ret) {
545                                 printf("%s: sector read error\n", __func__);
546                                 return AVB_IO_RESULT_ERROR_IO;
547                         }
548
549                         io_cnt += ret * part->info.blksz;
550                         buffer += ret * part->info.blksz;
551                         start_offset += ret * part->info.blksz;
552                         num_bytes -= ret * part->info.blksz;
553                 }
554         }
555
556         /* Set counter for read operation */
557         if (io_type == IO_READ && out_num_read)
558                 *out_num_read = io_cnt;
559
560         return AVB_IO_RESULT_OK;
561 }
562
563 /**
564  * ============================================================================
565  * AVB 2.0 operations
566  * ============================================================================
567  */
568
569 /**
570  * read_from_partition() - reads @num_bytes from  @offset from partition
571  * identified by a string name
572  *
573  * @ops: contains AVB ops handlers
574  * @partition_name: partition name, NUL-terminated UTF-8 string
575  * @offset: offset from the beginning of partition
576  * @num_bytes: amount of bytes to read
577  * @buffer: destination buffer to store data
578  * @out_num_read:
579  *
580  * @return:
581  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
582  *      AVB_IO_RESULT_ERROR_IO, if i/o error occurred from the underlying i/o
583  *            subsystem
584  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if there is no partition with
585  *      the given name
586  */
587 static AvbIOResult read_from_partition(AvbOps *ops,
588                                        const char *partition_name,
589                                        s64 offset_from_partition,
590                                        size_t num_bytes,
591                                        void *buffer,
592                                        size_t *out_num_read)
593 {
594         return mmc_byte_io(ops, partition_name, offset_from_partition,
595                            num_bytes, buffer, out_num_read, IO_READ);
596 }
597
598 /**
599  * write_to_partition() - writes N bytes to a partition identified by a string
600  * name
601  *
602  * @ops: AvbOps, contains AVB ops handlers
603  * @partition_name: partition name
604  * @offset_from_partition: offset from the beginning of partition
605  * @num_bytes: amount of bytes to write
606  * @buf: data to write
607  * @out_num_read:
608  *
609  * @return:
610  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
611  *      AVB_IO_RESULT_ERROR_IO, if input/output error occurred
612  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition, specified in
613  *            @partition_name was not found
614  */
615 static AvbIOResult write_to_partition(AvbOps *ops,
616                                       const char *partition_name,
617                                       s64 offset_from_partition,
618                                       size_t num_bytes,
619                                       const void *buffer)
620 {
621         return mmc_byte_io(ops, partition_name, offset_from_partition,
622                            num_bytes, (void *)buffer, NULL, IO_WRITE);
623 }
624
625 /**
626  * validate_vmbeta_public_key() - checks if the given public key used to sign
627  * the vbmeta partition is trusted
628  *
629  * @ops: AvbOps, contains AVB ops handlers
630  * @public_key_data: public key for verifying vbmeta partition signature
631  * @public_key_length: length of public key
632  * @public_key_metadata:
633  * @public_key_metadata_length:
634  * @out_key_is_trusted:
635  *
636  * @return:
637  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
638  */
639 static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
640                                               const u8 *public_key_data,
641                                               size_t public_key_length,
642                                               const u8
643                                               *public_key_metadata,
644                                               size_t
645                                               public_key_metadata_length,
646                                               bool *out_key_is_trusted)
647 {
648         if (!public_key_length || !public_key_data || !out_key_is_trusted)
649                 return AVB_IO_RESULT_ERROR_IO;
650
651         *out_key_is_trusted = false;
652         if (public_key_length != sizeof(avb_root_pub))
653                 return AVB_IO_RESULT_ERROR_IO;
654
655         if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0)
656                 *out_key_is_trusted = true;
657
658         return AVB_IO_RESULT_OK;
659 }
660
661 #ifdef CONFIG_OPTEE_TA_AVB
662 static int get_open_session(struct AvbOpsData *ops_data)
663 {
664         struct udevice *tee = NULL;
665
666         while (!ops_data->tee) {
667                 const struct tee_optee_ta_uuid uuid = TA_AVB_UUID;
668                 struct tee_open_session_arg arg;
669                 int rc;
670
671                 tee = tee_find_device(tee, NULL, NULL, NULL);
672                 if (!tee)
673                         return -ENODEV;
674
675                 memset(&arg, 0, sizeof(arg));
676                 tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
677                 rc = tee_open_session(tee, &arg, 0, NULL);
678                 if (rc || arg.ret)
679                         continue;
680
681                 ops_data->tee = tee;
682                 ops_data->session = arg.session;
683         }
684
685         return 0;
686 }
687
688 static AvbIOResult invoke_func(struct AvbOpsData *ops_data, u32 func,
689                                ulong num_param, struct tee_param *param)
690 {
691         struct tee_invoke_arg arg;
692
693         if (get_open_session(ops_data))
694                 return AVB_IO_RESULT_ERROR_IO;
695
696         memset(&arg, 0, sizeof(arg));
697         arg.func = func;
698         arg.session = ops_data->session;
699
700         if (tee_invoke_func(ops_data->tee, &arg, num_param, param))
701                 return AVB_IO_RESULT_ERROR_IO;
702         switch (arg.ret) {
703         case TEE_SUCCESS:
704                 return AVB_IO_RESULT_OK;
705         case TEE_ERROR_OUT_OF_MEMORY:
706                 return AVB_IO_RESULT_ERROR_OOM;
707         case TEE_ERROR_STORAGE_NO_SPACE:
708                 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
709         case TEE_ERROR_ITEM_NOT_FOUND:
710                 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
711         case TEE_ERROR_TARGET_DEAD:
712                 /*
713                  * The TA has paniced, close the session to reload the TA
714                  * for the next request.
715                  */
716                 tee_close_session(ops_data->tee, ops_data->session);
717                 ops_data->tee = NULL;
718                 return AVB_IO_RESULT_ERROR_IO;
719         default:
720                 return AVB_IO_RESULT_ERROR_IO;
721         }
722 }
723 #endif
724
725 /**
726  * read_rollback_index() - gets the rollback index corresponding to the
727  * location of given by @out_rollback_index.
728  *
729  * @ops: contains AvbOps handlers
730  * @rollback_index_slot:
731  * @out_rollback_index: used to write a retrieved rollback index.
732  *
733  * @return
734  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
735  */
736 static AvbIOResult read_rollback_index(AvbOps *ops,
737                                        size_t rollback_index_slot,
738                                        u64 *out_rollback_index)
739 {
740 #ifndef CONFIG_OPTEE_TA_AVB
741         /* For now we always return 0 as the stored rollback index. */
742         debug("%s: rollback protection is not implemented\n", __func__);
743
744         if (out_rollback_index)
745                 *out_rollback_index = 0;
746
747         return AVB_IO_RESULT_OK;
748 #else
749         AvbIOResult rc;
750         struct tee_param param[2];
751
752         if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
753                 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
754
755         memset(param, 0, sizeof(param));
756         param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
757         param[0].u.value.a = rollback_index_slot;
758         param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;
759
760         rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_ROLLBACK_INDEX,
761                          ARRAY_SIZE(param), param);
762         if (rc)
763                 return rc;
764
765         *out_rollback_index = (u64)param[1].u.value.a << 32 |
766                               (u32)param[1].u.value.b;
767         return AVB_IO_RESULT_OK;
768 #endif
769 }
770
771 /**
772  * write_rollback_index() - sets the rollback index corresponding to the
773  * location of given by @out_rollback_index.
774  *
775  * @ops: contains AvbOps handlers
776  * @rollback_index_slot:
777  * @rollback_index: rollback index to write.
778  *
779  * @return
780  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
781  */
782 static AvbIOResult write_rollback_index(AvbOps *ops,
783                                         size_t rollback_index_slot,
784                                         u64 rollback_index)
785 {
786 #ifndef CONFIG_OPTEE_TA_AVB
787         /* For now this is a no-op. */
788         debug("%s: rollback protection is not implemented\n", __func__);
789
790         return AVB_IO_RESULT_OK;
791 #else
792         struct tee_param param[2];
793
794         if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
795                 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
796
797         memset(param, 0, sizeof(param));
798         param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
799         param[0].u.value.a = rollback_index_slot;
800         param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
801         param[1].u.value.a = (u32)(rollback_index >> 32);
802         param[1].u.value.b = (u32)rollback_index;
803
804         return invoke_func(ops->user_data, TA_AVB_CMD_WRITE_ROLLBACK_INDEX,
805                            ARRAY_SIZE(param), param);
806 #endif
807 }
808
809 /**
810  * read_is_device_unlocked() - gets whether the device is unlocked
811  *
812  * @ops: contains AVB ops handlers
813  * @out_is_unlocked: device unlock state is stored here, true if unlocked,
814  *       false otherwise
815  *
816  * @return:
817  *       AVB_IO_RESULT_OK: state is retrieved successfully
818  *       AVB_IO_RESULT_ERROR_IO: an error occurred
819  */
820 static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
821 {
822 #ifndef CONFIG_OPTEE_TA_AVB
823         /* For now we always return that the device is unlocked. */
824         debug("%s: device locking is not implemented\n", __func__);
825
826         *out_is_unlocked = true;
827
828         return AVB_IO_RESULT_OK;
829 #else
830         AvbIOResult rc;
831         struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT };
832
833         rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_LOCK_STATE, 1, &param);
834         if (rc)
835                 return rc;
836         *out_is_unlocked = !param.u.value.a;
837         return AVB_IO_RESULT_OK;
838 #endif
839 }
840
841 /**
842  * get_unique_guid_for_partition() - gets the GUID for a partition identified
843  * by a string name
844  *
845  * @ops: contains AVB ops handlers
846  * @partition: partition name (NUL-terminated UTF-8 string)
847  * @guid_buf: buf, used to copy in GUID string. Example of value:
848  *      527c1c6d-6361-4593-8842-3c78fcd39219
849  * @guid_buf_size: @guid_buf buffer size
850  *
851  * @return:
852  *      AVB_IO_RESULT_OK, on success (GUID found)
853  *      AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
854  *             provided
855  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
856  */
857 static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
858                                                  const char *partition,
859                                                  char *guid_buf,
860                                                  size_t guid_buf_size)
861 {
862         struct mmc_part *part;
863         size_t uuid_size;
864
865         part = get_partition(ops, partition);
866         if (!part)
867                 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
868
869         uuid_size = sizeof(part->info.uuid);
870         if (uuid_size > guid_buf_size)
871                 return AVB_IO_RESULT_ERROR_IO;
872
873         memcpy(guid_buf, part->info.uuid, uuid_size);
874         guid_buf[uuid_size - 1] = 0;
875
876         return AVB_IO_RESULT_OK;
877 }
878
879 /**
880  * get_size_of_partition() - gets the size of a partition identified
881  * by a string name
882  *
883  * @ops: contains AVB ops handlers
884  * @partition: partition name (NUL-terminated UTF-8 string)
885  * @out_size_num_bytes: returns the value of a partition size
886  *
887  * @return:
888  *      AVB_IO_RESULT_OK, on success (GUID found)
889  *      AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE, out_size_num_bytes is NULL
890  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
891  */
892 static AvbIOResult get_size_of_partition(AvbOps *ops,
893                                          const char *partition,
894                                          u64 *out_size_num_bytes)
895 {
896         struct mmc_part *part;
897
898         if (!out_size_num_bytes)
899                 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
900
901         part = get_partition(ops, partition);
902         if (!part)
903                 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
904
905         *out_size_num_bytes = part->info.blksz * part->info.size;
906
907         return AVB_IO_RESULT_OK;
908 }
909
910 #ifdef CONFIG_OPTEE_TA_AVB
911 static AvbIOResult read_persistent_value(AvbOps *ops,
912                                          const char *name,
913                                          size_t buffer_size,
914                                          u8 *out_buffer,
915                                          size_t *out_num_bytes_read)
916 {
917         AvbIOResult rc;
918         struct tee_shm *shm_name;
919         struct tee_shm *shm_buf;
920         struct tee_param param[2];
921         struct udevice *tee;
922         size_t name_size = strlen(name) + 1;
923
924         if (get_open_session(ops->user_data))
925                 return AVB_IO_RESULT_ERROR_IO;
926
927         tee = ((struct AvbOpsData *)ops->user_data)->tee;
928
929         rc = tee_shm_alloc(tee, name_size,
930                            TEE_SHM_ALLOC, &shm_name);
931         if (rc)
932                 return AVB_IO_RESULT_ERROR_OOM;
933
934         rc = tee_shm_alloc(tee, buffer_size,
935                            TEE_SHM_ALLOC, &shm_buf);
936         if (rc) {
937                 rc = AVB_IO_RESULT_ERROR_OOM;
938                 goto free_name;
939         }
940
941         memcpy(shm_name->addr, name, name_size);
942
943         memset(param, 0, sizeof(param));
944         param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
945         param[0].u.memref.shm = shm_name;
946         param[0].u.memref.size = name_size;
947         param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
948         param[1].u.memref.shm = shm_buf;
949         param[1].u.memref.size = buffer_size;
950
951         rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_PERSIST_VALUE,
952                          2, param);
953         if (rc)
954                 goto out;
955
956         if (param[1].u.memref.size > buffer_size) {
957                 rc = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
958                 goto out;
959         }
960
961         *out_num_bytes_read = param[1].u.memref.size;
962
963         memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read);
964
965 out:
966         tee_shm_free(shm_buf);
967 free_name:
968         tee_shm_free(shm_name);
969
970         return rc;
971 }
972
973 static AvbIOResult write_persistent_value(AvbOps *ops,
974                                           const char *name,
975                                           size_t value_size,
976                                           const u8 *value)
977 {
978         AvbIOResult rc;
979         struct tee_shm *shm_name;
980         struct tee_shm *shm_buf;
981         struct tee_param param[2];
982         struct udevice *tee;
983         size_t name_size = strlen(name) + 1;
984
985         if (get_open_session(ops->user_data))
986                 return AVB_IO_RESULT_ERROR_IO;
987
988         tee = ((struct AvbOpsData *)ops->user_data)->tee;
989
990         if (!value_size)
991                 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
992
993         rc = tee_shm_alloc(tee, name_size,
994                            TEE_SHM_ALLOC, &shm_name);
995         if (rc)
996                 return AVB_IO_RESULT_ERROR_OOM;
997
998         rc = tee_shm_alloc(tee, value_size,
999                            TEE_SHM_ALLOC, &shm_buf);
1000         if (rc) {
1001                 rc = AVB_IO_RESULT_ERROR_OOM;
1002                 goto free_name;
1003         }
1004
1005         memcpy(shm_name->addr, name, name_size);
1006         memcpy(shm_buf->addr, value, value_size);
1007
1008         memset(param, 0, sizeof(param));
1009         param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
1010         param[0].u.memref.shm = shm_name;
1011         param[0].u.memref.size = name_size;
1012         param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
1013         param[1].u.memref.shm = shm_buf;
1014         param[1].u.memref.size = value_size;
1015
1016         rc = invoke_func(ops->user_data, TA_AVB_CMD_WRITE_PERSIST_VALUE,
1017                          2, param);
1018         if (rc)
1019                 goto out;
1020
1021 out:
1022         tee_shm_free(shm_buf);
1023 free_name:
1024         tee_shm_free(shm_name);
1025
1026         return rc;
1027 }
1028 #endif
1029
1030 /**
1031  * ============================================================================
1032  * AVB2.0 AvbOps alloc/initialisation/free
1033  * ============================================================================
1034  */
1035 AvbOps *avb_ops_alloc(int boot_device)
1036 {
1037         struct AvbOpsData *ops_data;
1038
1039         ops_data = avb_calloc(sizeof(struct AvbOpsData));
1040         if (!ops_data)
1041                 return NULL;
1042
1043         ops_data->ops.user_data = ops_data;
1044
1045         ops_data->ops.read_from_partition = read_from_partition;
1046         ops_data->ops.write_to_partition = write_to_partition;
1047         ops_data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key;
1048         ops_data->ops.read_rollback_index = read_rollback_index;
1049         ops_data->ops.write_rollback_index = write_rollback_index;
1050         ops_data->ops.read_is_device_unlocked = read_is_device_unlocked;
1051         ops_data->ops.get_unique_guid_for_partition =
1052                 get_unique_guid_for_partition;
1053 #ifdef CONFIG_OPTEE_TA_AVB
1054         ops_data->ops.write_persistent_value = write_persistent_value;
1055         ops_data->ops.read_persistent_value = read_persistent_value;
1056 #endif
1057         ops_data->ops.get_size_of_partition = get_size_of_partition;
1058         ops_data->mmc_dev = boot_device;
1059
1060         return &ops_data->ops;
1061 }
1062
1063 void avb_ops_free(AvbOps *ops)
1064 {
1065         struct AvbOpsData *ops_data;
1066
1067         if (!ops)
1068                 return;
1069
1070         ops_data = ops->user_data;
1071
1072         if (ops_data) {
1073 #ifdef CONFIG_OPTEE_TA_AVB
1074                 if (ops_data->tee)
1075                         tee_close_session(ops_data->tee, ops_data->session);
1076 #endif
1077                 avb_free(ops_data);
1078         }
1079 }