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