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