avb2.0: implement AVB ops
[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 <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  * IO(mmc) auxiliary functions
123  * ============================================================================
124  */
125 static unsigned long mmc_read_and_flush(struct mmc_part *part,
126                                         lbaint_t start,
127                                         lbaint_t sectors,
128                                         void *buffer)
129 {
130         unsigned long blks;
131         void *tmp_buf;
132         size_t buf_size;
133         bool unaligned = is_buf_unaligned(buffer);
134
135         if (start < part->info.start) {
136                 printf("%s: partition start out of bounds\n", __func__);
137                 return 0;
138         }
139         if ((start + sectors) > (part->info.start + part->info.size)) {
140                 sectors = part->info.start + part->info.size - start;
141                 printf("%s: read sector aligned to partition bounds (%ld)\n",
142                        __func__, sectors);
143         }
144
145         /*
146          * Reading fails on unaligned buffers, so we have to
147          * use aligned temporary buffer and then copy to destination
148          */
149
150         if (unaligned) {
151                 printf("Handling unaligned read buffer..\n");
152                 tmp_buf = get_sector_buf();
153                 buf_size = get_sector_buf_size();
154                 if (sectors > buf_size / part->info.blksz)
155                         sectors = buf_size / part->info.blksz;
156         } else {
157                 tmp_buf = buffer;
158         }
159
160         blks = part->mmc->block_dev.block_read(part->mmc_blk,
161                                 start, sectors, tmp_buf);
162         /* flush cache after read */
163         flush_cache((ulong)tmp_buf, sectors * part->info.blksz);
164
165         if (unaligned)
166                 memcpy(buffer, tmp_buf, sectors * part->info.blksz);
167
168         return blks;
169 }
170
171 static unsigned long mmc_write(struct mmc_part *part, lbaint_t start,
172                                lbaint_t sectors, void *buffer)
173 {
174         void *tmp_buf;
175         size_t buf_size;
176         bool unaligned = is_buf_unaligned(buffer);
177
178         if (start < part->info.start) {
179                 printf("%s: partition start out of bounds\n", __func__);
180                 return 0;
181         }
182         if ((start + sectors) > (part->info.start + part->info.size)) {
183                 sectors = part->info.start + part->info.size - start;
184                 printf("%s: sector aligned to partition bounds (%ld)\n",
185                        __func__, sectors);
186         }
187         if (unaligned) {
188                 tmp_buf = get_sector_buf();
189                 buf_size = get_sector_buf_size();
190                 printf("Handling unaligned wrire buffer..\n");
191                 if (sectors > buf_size / part->info.blksz)
192                         sectors = buf_size / part->info.blksz;
193
194                 memcpy(tmp_buf, buffer, sectors * part->info.blksz);
195         } else {
196                 tmp_buf = buffer;
197         }
198
199         return part->mmc->block_dev.block_write(part->mmc_blk,
200                                 start, sectors, tmp_buf);
201 }
202
203 static struct mmc_part *get_partition(AvbOps *ops, const char *partition)
204 {
205         int ret;
206         u8 dev_num;
207         int part_num = 0;
208         struct mmc_part *part;
209         struct blk_desc *mmc_blk;
210
211         part = malloc(sizeof(struct mmc_part));
212         if (!part)
213                 return NULL;
214
215         dev_num = get_boot_device(ops);
216         part->mmc = find_mmc_device(dev_num);
217         if (!part->mmc) {
218                 printf("No MMC device at slot %x\n", dev_num);
219                 return NULL;
220         }
221
222         if (mmc_init(part->mmc)) {
223                 printf("MMC initialization failed\n");
224                 return NULL;
225         }
226
227         ret = mmc_switch_part(part->mmc, part_num);
228         if (ret)
229                 return NULL;
230
231         mmc_blk = mmc_get_blk_desc(part->mmc);
232         if (!mmc_blk) {
233                 printf("Error - failed to obtain block descriptor\n");
234                 return NULL;
235         }
236
237         ret = part_get_info_by_name(mmc_blk, partition, &part->info);
238         if (!ret) {
239                 printf("Can't find partition '%s'\n", partition);
240                 return NULL;
241         }
242
243         part->dev_num = dev_num;
244         part->mmc_blk = mmc_blk;
245
246         return part;
247 }
248
249 static AvbIOResult mmc_byte_io(AvbOps *ops,
250                                const char *partition,
251                                s64 offset,
252                                size_t num_bytes,
253                                void *buffer,
254                                size_t *out_num_read,
255                                enum mmc_io_type io_type)
256 {
257         ulong ret;
258         struct mmc_part *part;
259         u64 start_offset, start_sector, sectors, residue;
260         u8 *tmp_buf;
261         size_t io_cnt = 0;
262
263         if (!partition || !buffer || io_type > IO_WRITE)
264                 return AVB_IO_RESULT_ERROR_IO;
265
266         part = get_partition(ops, partition);
267         if (!part)
268                 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
269
270         start_offset = calc_offset(part, offset);
271         while (num_bytes) {
272                 start_sector = start_offset / part->info.blksz;
273                 sectors = num_bytes / part->info.blksz;
274                 /* handle non block-aligned reads */
275                 if (start_offset % part->info.blksz ||
276                     num_bytes < part->info.blksz) {
277                         tmp_buf = get_sector_buf();
278                         if (start_offset % part->info.blksz) {
279                                 residue = part->info.blksz -
280                                         (start_offset % part->info.blksz);
281                                 if (residue > num_bytes)
282                                         residue = num_bytes;
283                         } else {
284                                 residue = num_bytes;
285                         }
286
287                         if (io_type == IO_READ) {
288                                 ret = mmc_read_and_flush(part,
289                                                          part->info.start +
290                                                          start_sector,
291                                                          1, tmp_buf);
292
293                                 if (ret != 1) {
294                                         printf("%s: read error (%ld, %lld)\n",
295                                                __func__, ret, start_sector);
296                                         return AVB_IO_RESULT_ERROR_IO;
297                                 }
298                                 /*
299                                  * if this is not aligned at sector start,
300                                  * we have to adjust the tmp buffer
301                                  */
302                                 tmp_buf += (start_offset % part->info.blksz);
303                                 memcpy(buffer, (void *)tmp_buf, residue);
304                         } else {
305                                 ret = mmc_read_and_flush(part,
306                                                          part->info.start +
307                                                          start_sector,
308                                                          1, tmp_buf);
309
310                                 if (ret != 1) {
311                                         printf("%s: read error (%ld, %lld)\n",
312                                                __func__, ret, start_sector);
313                                         return AVB_IO_RESULT_ERROR_IO;
314                                 }
315                                 memcpy((void *)tmp_buf +
316                                         start_offset % part->info.blksz,
317                                         buffer, residue);
318
319                                 ret = mmc_write(part, part->info.start +
320                                                 start_sector, 1, tmp_buf);
321                                 if (ret != 1) {
322                                         printf("%s: write error (%ld, %lld)\n",
323                                                __func__, ret, start_sector);
324                                         return AVB_IO_RESULT_ERROR_IO;
325                                 }
326                         }
327
328                         io_cnt += residue;
329                         buffer += residue;
330                         start_offset += residue;
331                         num_bytes -= residue;
332                         continue;
333                 }
334
335                 if (sectors) {
336                         if (io_type == IO_READ) {
337                                 ret = mmc_read_and_flush(part,
338                                                          part->info.start +
339                                                          start_sector,
340                                                          sectors, buffer);
341                         } else {
342                                 ret = mmc_write(part,
343                                                 part->info.start +
344                                                 start_sector,
345                                                 sectors, buffer);
346                         }
347
348                         if (!ret) {
349                                 printf("%s: sector read error\n", __func__);
350                                 return AVB_IO_RESULT_ERROR_IO;
351                         }
352
353                         io_cnt += ret * part->info.blksz;
354                         buffer += ret * part->info.blksz;
355                         start_offset += ret * part->info.blksz;
356                         num_bytes -= ret * part->info.blksz;
357                 }
358         }
359
360         /* Set counter for read operation */
361         if (io_type == IO_READ && out_num_read)
362                 *out_num_read = io_cnt;
363
364         return AVB_IO_RESULT_OK;
365 }
366
367 /**
368  * ============================================================================
369  * AVB 2.0 operations
370  * ============================================================================
371  */
372
373 /**
374  * read_from_partition() - reads @num_bytes from  @offset from partition
375  * identified by a string name
376  *
377  * @ops: contains AVB ops handlers
378  * @partition_name: partition name, NUL-terminated UTF-8 string
379  * @offset: offset from the beginning of partition
380  * @num_bytes: amount of bytes to read
381  * @buffer: destination buffer to store data
382  * @out_num_read:
383  *
384  * @return:
385  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
386  *      AVB_IO_RESULT_ERROR_IO, if i/o error occurred from the underlying i/o
387  *            subsystem
388  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if there is no partition with
389  *      the given name
390  */
391 static AvbIOResult read_from_partition(AvbOps *ops,
392                                        const char *partition_name,
393                                        s64 offset_from_partition,
394                                        size_t num_bytes,
395                                        void *buffer,
396                                        size_t *out_num_read)
397 {
398         return mmc_byte_io(ops, partition_name, offset_from_partition,
399                            num_bytes, buffer, out_num_read, IO_READ);
400 }
401
402 /**
403  * write_to_partition() - writes N bytes to a partition identified by a string
404  * name
405  *
406  * @ops: AvbOps, contains AVB ops handlers
407  * @partition_name: partition name
408  * @offset_from_partition: offset from the beginning of partition
409  * @num_bytes: amount of bytes to write
410  * @buf: data to write
411  * @out_num_read:
412  *
413  * @return:
414  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
415  *      AVB_IO_RESULT_ERROR_IO, if input/output error occurred
416  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition, specified in
417  *            @partition_name was not found
418  */
419 static AvbIOResult write_to_partition(AvbOps *ops,
420                                       const char *partition_name,
421                                       s64 offset_from_partition,
422                                       size_t num_bytes,
423                                       const void *buffer)
424 {
425         return mmc_byte_io(ops, partition_name, offset_from_partition,
426                            num_bytes, (void *)buffer, NULL, IO_WRITE);
427 }
428
429 /**
430  * validate_vmbeta_public_key() - checks if the given public key used to sign
431  * the vbmeta partition is trusted
432  *
433  * @ops: AvbOps, contains AVB ops handlers
434  * @public_key_data: public key for verifying vbmeta partition signature
435  * @public_key_length: length of public key
436  * @public_key_metadata:
437  * @public_key_metadata_length:
438  * @out_key_is_trusted:
439  *
440  * @return:
441  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
442  */
443 static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
444                                               const u8 *public_key_data,
445                                               size_t public_key_length,
446                                               const u8
447                                               *public_key_metadata,
448                                               size_t
449                                               public_key_metadata_length,
450                                               bool *out_key_is_trusted)
451 {
452         if (!public_key_length || !public_key_data || !out_key_is_trusted)
453                 return AVB_IO_RESULT_ERROR_IO;
454
455         *out_key_is_trusted = false;
456         if (public_key_length != sizeof(avb_root_pub))
457                 return AVB_IO_RESULT_ERROR_IO;
458
459         if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0)
460                 *out_key_is_trusted = true;
461
462         return AVB_IO_RESULT_OK;
463 }
464
465 /**
466  * read_rollback_index() - gets the rollback index corresponding to the
467  * location of given by @out_rollback_index.
468  *
469  * @ops: contains AvbOps handlers
470  * @rollback_index_slot:
471  * @out_rollback_index: used to write a retrieved rollback index.
472  *
473  * @return
474  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
475  */
476 static AvbIOResult read_rollback_index(AvbOps *ops,
477                                        size_t rollback_index_slot,
478                                        u64 *out_rollback_index)
479 {
480         /* For now we always return 0 as the stored rollback index. */
481         printf("TODO: implement %s.\n", __func__);
482
483         if (out_rollback_index)
484                 *out_rollback_index = 0;
485
486         return AVB_IO_RESULT_OK;
487 }
488
489 /**
490  * write_rollback_index() - sets the rollback index corresponding to the
491  * location of given by @out_rollback_index.
492  *
493  * @ops: contains AvbOps handlers
494  * @rollback_index_slot:
495  * @rollback_index: rollback index to write.
496  *
497  * @return
498  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
499  */
500 static AvbIOResult write_rollback_index(AvbOps *ops,
501                                         size_t rollback_index_slot,
502                                         u64 rollback_index)
503 {
504         /* For now this is a no-op. */
505         printf("TODO: implement %s.\n", __func__);
506
507         return AVB_IO_RESULT_OK;
508 }
509
510 /**
511  * read_is_device_unlocked() - gets whether the device is unlocked
512  *
513  * @ops: contains AVB ops handlers
514  * @out_is_unlocked: device unlock state is stored here, true if unlocked,
515  *       false otherwise
516  *
517  * @return:
518  *       AVB_IO_RESULT_OK: state is retrieved successfully
519  *       AVB_IO_RESULT_ERROR_IO: an error occurred
520  */
521 static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
522 {
523         /* For now we always return that the device is unlocked. */
524
525         printf("TODO: implement %s.\n", __func__);
526
527         *out_is_unlocked = true;
528
529         return AVB_IO_RESULT_OK;
530 }
531
532 /**
533  * get_unique_guid_for_partition() - gets the GUID for a partition identified
534  * by a string name
535  *
536  * @ops: contains AVB ops handlers
537  * @partition: partition name (NUL-terminated UTF-8 string)
538  * @guid_buf: buf, used to copy in GUID string. Example of value:
539  *      527c1c6d-6361-4593-8842-3c78fcd39219
540  * @guid_buf_size: @guid_buf buffer size
541  *
542  * @return:
543  *      AVB_IO_RESULT_OK, on success (GUID found)
544  *      AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
545  *             provided
546  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
547  */
548 static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
549                                                  const char *partition,
550                                                  char *guid_buf,
551                                                  size_t guid_buf_size)
552 {
553         struct mmc_part *part;
554         size_t uuid_size;
555
556         part = get_partition(ops, partition);
557         if (!part)
558                 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
559
560         uuid_size = sizeof(part->info.uuid);
561         if (uuid_size > guid_buf_size)
562                 return AVB_IO_RESULT_ERROR_IO;
563
564         memcpy(guid_buf, part->info.uuid, uuid_size);
565         guid_buf[uuid_size - 1] = 0;
566
567         return AVB_IO_RESULT_OK;
568 }
569
570 /**
571  * ============================================================================
572  * AVB2.0 AvbOps alloc/initialisation/free
573  * ============================================================================
574  */
575 AvbOps *avb_ops_alloc(int boot_device)
576 {
577         struct AvbOpsData *ops_data;
578
579         ops_data = avb_calloc(sizeof(struct AvbOpsData));
580         if (!ops_data)
581                 return NULL;
582
583         ops_data->ops.user_data = ops_data;
584
585         ops_data->ops.read_from_partition = read_from_partition;
586         ops_data->ops.write_to_partition = write_to_partition;
587         ops_data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key;
588         ops_data->ops.read_rollback_index = read_rollback_index;
589         ops_data->ops.write_rollback_index = write_rollback_index;
590         ops_data->ops.read_is_device_unlocked = read_is_device_unlocked;
591         ops_data->ops.get_unique_guid_for_partition =
592                 get_unique_guid_for_partition;
593
594         ops_data->mmc_dev = boot_device;
595
596         return &ops_data->ops;
597 }
598
599 void avb_ops_free(AvbOps *ops)
600 {
601         struct AvbOpsData *ops_data;
602
603         if (ops)
604                 return;
605
606         ops_data = ops->user_data;
607
608         if (ops_data)
609                 avb_free(ops_data);
610 }