blob: a4de168839ea03278628745f8a4a845e85f9218d [file] [log] [blame]
Igor Opaniuk3af30e42018-06-03 21:56:38 +03001/*
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
13const 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 */
125static 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
171static 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
203static 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
249static 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 */
391static 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 */
419static 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 */
443static 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 */
476static 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 */
500static 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 */
521static 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 */
548static 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 */
575AvbOps *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
599void 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}