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