common: avb_verify: Fix memory leaks
[pandora-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         start_offset = calc_offset(part, offset);
406         while (num_bytes) {
407                 start_sector = start_offset / part->info.blksz;
408                 sectors = num_bytes / part->info.blksz;
409                 /* handle non block-aligned reads */
410                 if (start_offset % part->info.blksz ||
411                     num_bytes < part->info.blksz) {
412                         tmp_buf = get_sector_buf();
413                         if (start_offset % part->info.blksz) {
414                                 residue = part->info.blksz -
415                                         (start_offset % part->info.blksz);
416                                 if (residue > num_bytes)
417                                         residue = num_bytes;
418                         } else {
419                                 residue = num_bytes;
420                         }
421
422                         if (io_type == IO_READ) {
423                                 ret = mmc_read_and_flush(part,
424                                                          part->info.start +
425                                                          start_sector,
426                                                          1, tmp_buf);
427
428                                 if (ret != 1) {
429                                         printf("%s: read error (%ld, %lld)\n",
430                                                __func__, ret, start_sector);
431                                         return AVB_IO_RESULT_ERROR_IO;
432                                 }
433                                 /*
434                                  * if this is not aligned at sector start,
435                                  * we have to adjust the tmp buffer
436                                  */
437                                 tmp_buf += (start_offset % part->info.blksz);
438                                 memcpy(buffer, (void *)tmp_buf, residue);
439                         } else {
440                                 ret = mmc_read_and_flush(part,
441                                                          part->info.start +
442                                                          start_sector,
443                                                          1, tmp_buf);
444
445                                 if (ret != 1) {
446                                         printf("%s: read error (%ld, %lld)\n",
447                                                __func__, ret, start_sector);
448                                         return AVB_IO_RESULT_ERROR_IO;
449                                 }
450                                 memcpy((void *)tmp_buf +
451                                         start_offset % part->info.blksz,
452                                         buffer, residue);
453
454                                 ret = mmc_write(part, part->info.start +
455                                                 start_sector, 1, tmp_buf);
456                                 if (ret != 1) {
457                                         printf("%s: write error (%ld, %lld)\n",
458                                                __func__, ret, start_sector);
459                                         return AVB_IO_RESULT_ERROR_IO;
460                                 }
461                         }
462
463                         io_cnt += residue;
464                         buffer += residue;
465                         start_offset += residue;
466                         num_bytes -= residue;
467                         continue;
468                 }
469
470                 if (sectors) {
471                         if (io_type == IO_READ) {
472                                 ret = mmc_read_and_flush(part,
473                                                          part->info.start +
474                                                          start_sector,
475                                                          sectors, buffer);
476                         } else {
477                                 ret = mmc_write(part,
478                                                 part->info.start +
479                                                 start_sector,
480                                                 sectors, buffer);
481                         }
482
483                         if (!ret) {
484                                 printf("%s: sector read error\n", __func__);
485                                 return AVB_IO_RESULT_ERROR_IO;
486                         }
487
488                         io_cnt += ret * part->info.blksz;
489                         buffer += ret * part->info.blksz;
490                         start_offset += ret * part->info.blksz;
491                         num_bytes -= ret * part->info.blksz;
492                 }
493         }
494
495         /* Set counter for read operation */
496         if (io_type == IO_READ && out_num_read)
497                 *out_num_read = io_cnt;
498
499         return AVB_IO_RESULT_OK;
500 }
501
502 /**
503  * ============================================================================
504  * AVB 2.0 operations
505  * ============================================================================
506  */
507
508 /**
509  * read_from_partition() - reads @num_bytes from  @offset from partition
510  * identified by a string name
511  *
512  * @ops: contains AVB ops handlers
513  * @partition_name: partition name, NUL-terminated UTF-8 string
514  * @offset: offset from the beginning of partition
515  * @num_bytes: amount of bytes to read
516  * @buffer: destination buffer to store data
517  * @out_num_read:
518  *
519  * @return:
520  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
521  *      AVB_IO_RESULT_ERROR_IO, if i/o error occurred from the underlying i/o
522  *            subsystem
523  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if there is no partition with
524  *      the given name
525  */
526 static AvbIOResult read_from_partition(AvbOps *ops,
527                                        const char *partition_name,
528                                        s64 offset_from_partition,
529                                        size_t num_bytes,
530                                        void *buffer,
531                                        size_t *out_num_read)
532 {
533         return mmc_byte_io(ops, partition_name, offset_from_partition,
534                            num_bytes, buffer, out_num_read, IO_READ);
535 }
536
537 /**
538  * write_to_partition() - writes N bytes to a partition identified by a string
539  * name
540  *
541  * @ops: AvbOps, contains AVB ops handlers
542  * @partition_name: partition name
543  * @offset_from_partition: offset from the beginning of partition
544  * @num_bytes: amount of bytes to write
545  * @buf: data to write
546  * @out_num_read:
547  *
548  * @return:
549  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
550  *      AVB_IO_RESULT_ERROR_IO, if input/output error occurred
551  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition, specified in
552  *            @partition_name was not found
553  */
554 static AvbIOResult write_to_partition(AvbOps *ops,
555                                       const char *partition_name,
556                                       s64 offset_from_partition,
557                                       size_t num_bytes,
558                                       const void *buffer)
559 {
560         return mmc_byte_io(ops, partition_name, offset_from_partition,
561                            num_bytes, (void *)buffer, NULL, IO_WRITE);
562 }
563
564 /**
565  * validate_vmbeta_public_key() - checks if the given public key used to sign
566  * the vbmeta partition is trusted
567  *
568  * @ops: AvbOps, contains AVB ops handlers
569  * @public_key_data: public key for verifying vbmeta partition signature
570  * @public_key_length: length of public key
571  * @public_key_metadata:
572  * @public_key_metadata_length:
573  * @out_key_is_trusted:
574  *
575  * @return:
576  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
577  */
578 static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
579                                               const u8 *public_key_data,
580                                               size_t public_key_length,
581                                               const u8
582                                               *public_key_metadata,
583                                               size_t
584                                               public_key_metadata_length,
585                                               bool *out_key_is_trusted)
586 {
587         if (!public_key_length || !public_key_data || !out_key_is_trusted)
588                 return AVB_IO_RESULT_ERROR_IO;
589
590         *out_key_is_trusted = false;
591         if (public_key_length != sizeof(avb_root_pub))
592                 return AVB_IO_RESULT_ERROR_IO;
593
594         if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0)
595                 *out_key_is_trusted = true;
596
597         return AVB_IO_RESULT_OK;
598 }
599
600 /**
601  * read_rollback_index() - gets the rollback index corresponding to the
602  * location of given by @out_rollback_index.
603  *
604  * @ops: contains AvbOps handlers
605  * @rollback_index_slot:
606  * @out_rollback_index: used to write a retrieved rollback index.
607  *
608  * @return
609  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
610  */
611 static AvbIOResult read_rollback_index(AvbOps *ops,
612                                        size_t rollback_index_slot,
613                                        u64 *out_rollback_index)
614 {
615         /* For now we always return 0 as the stored rollback index. */
616         printf("%s not supported yet\n", __func__);
617
618         if (out_rollback_index)
619                 *out_rollback_index = 0;
620
621         return AVB_IO_RESULT_OK;
622 }
623
624 /**
625  * write_rollback_index() - sets the rollback index corresponding to the
626  * location of given by @out_rollback_index.
627  *
628  * @ops: contains AvbOps handlers
629  * @rollback_index_slot:
630  * @rollback_index: rollback index to write.
631  *
632  * @return
633  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
634  */
635 static AvbIOResult write_rollback_index(AvbOps *ops,
636                                         size_t rollback_index_slot,
637                                         u64 rollback_index)
638 {
639         /* For now this is a no-op. */
640         printf("%s not supported yet\n", __func__);
641
642         return AVB_IO_RESULT_OK;
643 }
644
645 /**
646  * read_is_device_unlocked() - gets whether the device is unlocked
647  *
648  * @ops: contains AVB ops handlers
649  * @out_is_unlocked: device unlock state is stored here, true if unlocked,
650  *       false otherwise
651  *
652  * @return:
653  *       AVB_IO_RESULT_OK: state is retrieved successfully
654  *       AVB_IO_RESULT_ERROR_IO: an error occurred
655  */
656 static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
657 {
658         /* For now we always return that the device is unlocked. */
659
660         printf("%s not supported yet\n", __func__);
661
662         *out_is_unlocked = true;
663
664         return AVB_IO_RESULT_OK;
665 }
666
667 /**
668  * get_unique_guid_for_partition() - gets the GUID for a partition identified
669  * by a string name
670  *
671  * @ops: contains AVB ops handlers
672  * @partition: partition name (NUL-terminated UTF-8 string)
673  * @guid_buf: buf, used to copy in GUID string. Example of value:
674  *      527c1c6d-6361-4593-8842-3c78fcd39219
675  * @guid_buf_size: @guid_buf buffer size
676  *
677  * @return:
678  *      AVB_IO_RESULT_OK, on success (GUID found)
679  *      AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
680  *             provided
681  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
682  */
683 static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
684                                                  const char *partition,
685                                                  char *guid_buf,
686                                                  size_t guid_buf_size)
687 {
688         struct mmc_part *part;
689         size_t uuid_size;
690
691         part = get_partition(ops, partition);
692         if (!part)
693                 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
694
695         uuid_size = sizeof(part->info.uuid);
696         if (uuid_size > guid_buf_size)
697                 return AVB_IO_RESULT_ERROR_IO;
698
699         memcpy(guid_buf, part->info.uuid, uuid_size);
700         guid_buf[uuid_size - 1] = 0;
701
702         return AVB_IO_RESULT_OK;
703 }
704
705 /**
706  * get_size_of_partition() - gets the size of a partition identified
707  * by a string name
708  *
709  * @ops: contains AVB ops handlers
710  * @partition: partition name (NUL-terminated UTF-8 string)
711  * @out_size_num_bytes: returns the value of a partition size
712  *
713  * @return:
714  *      AVB_IO_RESULT_OK, on success (GUID found)
715  *      AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE, out_size_num_bytes is NULL
716  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
717  */
718 static AvbIOResult get_size_of_partition(AvbOps *ops,
719                                          const char *partition,
720                                          u64 *out_size_num_bytes)
721 {
722         struct mmc_part *part;
723
724         if (!out_size_num_bytes)
725                 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
726
727         part = get_partition(ops, partition);
728         if (!part)
729                 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
730
731         *out_size_num_bytes = part->info.blksz * part->info.size;
732
733         return AVB_IO_RESULT_OK;
734 }
735
736 /**
737  * ============================================================================
738  * AVB2.0 AvbOps alloc/initialisation/free
739  * ============================================================================
740  */
741 AvbOps *avb_ops_alloc(int boot_device)
742 {
743         struct AvbOpsData *ops_data;
744
745         ops_data = avb_calloc(sizeof(struct AvbOpsData));
746         if (!ops_data)
747                 return NULL;
748
749         ops_data->ops.user_data = ops_data;
750
751         ops_data->ops.read_from_partition = read_from_partition;
752         ops_data->ops.write_to_partition = write_to_partition;
753         ops_data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key;
754         ops_data->ops.read_rollback_index = read_rollback_index;
755         ops_data->ops.write_rollback_index = write_rollback_index;
756         ops_data->ops.read_is_device_unlocked = read_is_device_unlocked;
757         ops_data->ops.get_unique_guid_for_partition =
758                 get_unique_guid_for_partition;
759         ops_data->ops.get_size_of_partition = get_size_of_partition;
760         ops_data->mmc_dev = boot_device;
761
762         return &ops_data->ops;
763 }
764
765 void avb_ops_free(AvbOps *ops)
766 {
767         struct AvbOpsData *ops_data;
768
769         if (ops)
770                 return;
771
772         ops_data = ops->user_data;
773
774         if (ops_data)
775                 avb_free(ops_data);
776 }