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 */
avb_set_state(AvbOps * ops,enum avb_boot_state boot_state)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
append_cmd_line(char * cmdline_orig,char * cmdline_new)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
avb_find_dm_args(char ** args,char * str)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
avb_set_enforce_option(const char * cmdline,const char * option)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
avb_set_ignore_corruption(const char * cmdline)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
avb_set_enforce_verity(const char * cmdline)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 */
mmc_read_and_flush(struct mmc_part * part,lbaint_t start,lbaint_t sectors,void * buffer)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
mmc_write(struct mmc_part * part,lbaint_t start,lbaint_t sectors,void * buffer)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
get_partition(AvbOps * ops,const char * partition)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
mmc_byte_io(AvbOps * ops,const char * partition,s64 offset,size_t num_bytes,void * buffer,size_t * out_num_read,enum mmc_io_type io_type)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 */
read_from_partition(AvbOps * ops,const char * partition_name,s64 offset_from_partition,size_t num_bytes,void * buffer,size_t * out_num_read)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 */
write_to_partition(AvbOps * ops,const char * partition_name,s64 offset_from_partition,size_t num_bytes,const void * buffer)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 */
validate_vbmeta_public_key(AvbOps * ops,const u8 * public_key_data,size_t public_key_length,const u8 * public_key_metadata,size_t public_key_metadata_length,bool * out_key_is_trusted)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 */
read_rollback_index(AvbOps * ops,size_t rollback_index_slot,u64 * out_rollback_index)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 */
write_rollback_index(AvbOps * ops,size_t rollback_index_slot,u64 rollback_index)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 */
read_is_device_unlocked(AvbOps * ops,bool * out_is_unlocked)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 */
get_unique_guid_for_partition(AvbOps * ops,const char * partition,char * guid_buf,size_t guid_buf_size)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 */
avb_ops_alloc(int boot_device)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
avb_ops_free(AvbOps * ops)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 }
742