1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 #include <android_avb/avb_ab_flow.h>
26
avb_ab_data_verify_and_byteswap(const AvbABData * src,AvbABData * dest)27 bool avb_ab_data_verify_and_byteswap(const AvbABData* src, AvbABData* dest) {
28 /* Ensure magic is correct. */
29 if (avb_safe_memcmp(src->magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN) != 0) {
30 avb_error("Magic is incorrect.\n");
31 return false;
32 }
33
34 avb_memcpy(dest, src, sizeof(AvbABData));
35 dest->crc32 = avb_be32toh(dest->crc32);
36
37 /* Ensure we don't attempt to access any fields if the major version
38 * is not supported.
39 */
40 if (dest->version_major > AVB_AB_MAJOR_VERSION) {
41 avb_error("No support for given major version.\n");
42 return false;
43 }
44
45 /* Bail if CRC32 doesn't match. */
46 if (dest->crc32 !=
47 avb_crc32((const uint8_t*)dest, sizeof(AvbABData) - sizeof(uint32_t))) {
48 avb_error("CRC32 does not match.\n");
49 return false;
50 }
51
52 return true;
53 }
54
avb_ab_data_update_crc_and_byteswap(const AvbABData * src,AvbABData * dest)55 void avb_ab_data_update_crc_and_byteswap(const AvbABData* src,
56 AvbABData* dest) {
57 avb_memcpy(dest, src, sizeof(AvbABData));
58 dest->crc32 = avb_htobe32(
59 avb_crc32((const uint8_t*)dest, sizeof(AvbABData) - sizeof(uint32_t)));
60 }
61
avb_ab_data_init(AvbABData * data)62 void avb_ab_data_init(AvbABData* data) {
63 avb_memset(data, '\0', sizeof(AvbABData));
64 avb_memcpy(data->magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN);
65 data->version_major = AVB_AB_MAJOR_VERSION;
66 data->version_minor = AVB_AB_MINOR_VERSION;
67 data->last_boot = 0;
68 data->slots[0].priority = AVB_AB_MAX_PRIORITY;
69 data->slots[0].tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
70 data->slots[0].successful_boot = 0;
71 data->slots[1].priority = AVB_AB_MAX_PRIORITY - 1;
72 data->slots[1].tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
73 data->slots[1].successful_boot = 0;
74 }
75
76 /* The AvbABData struct is stored 2048 bytes into the 'misc' partition
77 * following the 'struct bootloader_message' field. The struct is
78 * compatible with the guidelines in bootable/recovery/bootloader.h -
79 * e.g. it is stored in the |slot_suffix| field, starts with a
80 * NUL-byte, and is 32 bytes long.
81 */
82 #define AB_METADATA_MISC_PARTITION_OFFSET 2048
83
avb_ab_data_read(AvbABOps * ab_ops,AvbABData * data)84 AvbIOResult avb_ab_data_read(AvbABOps* ab_ops, AvbABData* data) {
85 AvbOps* ops = ab_ops->ops;
86 AvbABData serialized;
87 AvbIOResult io_ret;
88 size_t num_bytes_read;
89
90 io_ret = ops->read_from_partition(ops,
91 "misc",
92 AB_METADATA_MISC_PARTITION_OFFSET,
93 sizeof(AvbABData),
94 &serialized,
95 &num_bytes_read);
96 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
97 return AVB_IO_RESULT_ERROR_OOM;
98 } else if (io_ret != AVB_IO_RESULT_OK ||
99 num_bytes_read != sizeof(AvbABData)) {
100 avb_error("Error reading A/B metadata.\n");
101 return AVB_IO_RESULT_ERROR_IO;
102 }
103
104 if (!avb_ab_data_verify_and_byteswap(&serialized, data)) {
105 avb_error(
106 "Error validating A/B metadata from disk. "
107 "Resetting and writing new A/B metadata to disk.\n");
108 avb_ab_data_init(data);
109 return avb_ab_data_write(ab_ops, data);
110 }
111
112 return AVB_IO_RESULT_OK;
113 }
114
avb_ab_data_write(AvbABOps * ab_ops,const AvbABData * data)115 AvbIOResult avb_ab_data_write(AvbABOps* ab_ops, const AvbABData* data) {
116 AvbOps* ops = ab_ops->ops;
117 AvbABData serialized;
118 AvbIOResult io_ret;
119
120 avb_ab_data_update_crc_and_byteswap(data, &serialized);
121 io_ret = ops->write_to_partition(ops,
122 "misc",
123 AB_METADATA_MISC_PARTITION_OFFSET,
124 sizeof(AvbABData),
125 &serialized);
126 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
127 return AVB_IO_RESULT_ERROR_OOM;
128 } else if (io_ret != AVB_IO_RESULT_OK) {
129 avb_error("Error writing A/B metadata.\n");
130 return AVB_IO_RESULT_ERROR_IO;
131 }
132 return AVB_IO_RESULT_OK;
133 }
134
slot_is_bootable(AvbABSlotData * slot)135 static bool slot_is_bootable(AvbABSlotData* slot) {
136 return slot->priority > 0 &&
137 (slot->successful_boot || (slot->tries_remaining > 0));
138 }
139
slot_set_unbootable(AvbABSlotData * slot)140 static void slot_set_unbootable(AvbABSlotData* slot) {
141 slot->priority = 0;
142 slot->tries_remaining = 0;
143 slot->successful_boot = 0;
144 }
145
146 /* Ensure all unbootable and/or illegal states are marked as the
147 * canonical 'unbootable' state, e.g. priority=0, tries_remaining=0,
148 * and successful_boot=0.
149 */
slot_normalize(AvbABSlotData * slot)150 static void slot_normalize(AvbABSlotData* slot) {
151 if (slot->priority > 0) {
152 if (slot->tries_remaining == 0 && !slot->successful_boot) {
153 /* We've exhausted all tries -> unbootable. */
154 slot_set_unbootable(slot);
155 }
156 if (slot->tries_remaining > 0 && slot->successful_boot) {
157 /* Illegal state - avb_ab_mark_slot_successful() will clear
158 * tries_remaining when setting successful_boot.
159 */
160 slot_set_unbootable(slot);
161 }
162 } else {
163 slot_set_unbootable(slot);
164 }
165 }
166
167 static const char* slot_suffixes[2] = {"_a", "_b"};
168
169 /* Helper function to load metadata - returns AVB_IO_RESULT_OK on
170 * success, error code otherwise.
171 */
load_metadata(AvbABOps * ab_ops,AvbABData * ab_data,AvbABData * ab_data_orig)172 AvbIOResult load_metadata(AvbABOps* ab_ops,
173 AvbABData* ab_data,
174 AvbABData* ab_data_orig) {
175 AvbIOResult io_ret;
176
177 io_ret = ab_ops->read_ab_metadata(ab_ops, ab_data);
178 if (io_ret != AVB_IO_RESULT_OK) {
179 avb_error("I/O error while loading A/B metadata.\n");
180 return io_ret;
181 }
182 *ab_data_orig = *ab_data;
183
184 /* Ensure data is normalized, e.g. illegal states will be marked as
185 * unbootable and all unbootable states are represented with
186 * (priority=0, tries_remaining=0, successful_boot=0).
187 */
188 slot_normalize(&ab_data->slots[0]);
189 slot_normalize(&ab_data->slots[1]);
190 return AVB_IO_RESULT_OK;
191 }
192
193 /* Writes A/B metadata to disk only if it has changed - returns
194 * AVB_IO_RESULT_OK on success, error code otherwise.
195 */
save_metadata_if_changed(AvbABOps * ab_ops,AvbABData * ab_data,AvbABData * ab_data_orig)196 AvbIOResult save_metadata_if_changed(AvbABOps* ab_ops,
197 AvbABData* ab_data,
198 AvbABData* ab_data_orig) {
199 if (avb_safe_memcmp(ab_data, ab_data_orig, sizeof(AvbABData)) != 0) {
200 avb_debug("Writing A/B metadata to disk.\n");
201 return ab_ops->write_ab_metadata(ab_ops, ab_data);
202 }
203 return AVB_IO_RESULT_OK;
204 }
205
avb_ab_flow(AvbABOps * ab_ops,const char * const * requested_partitions,AvbSlotVerifyFlags flags,AvbHashtreeErrorMode hashtree_error_mode,AvbSlotVerifyData ** out_data)206 AvbABFlowResult avb_ab_flow(AvbABOps* ab_ops,
207 const char* const* requested_partitions,
208 AvbSlotVerifyFlags flags,
209 AvbHashtreeErrorMode hashtree_error_mode,
210 AvbSlotVerifyData** out_data) {
211 AvbOps* ops = ab_ops->ops;
212 AvbSlotVerifyData* slot_data[2] = {NULL, NULL};
213 AvbSlotVerifyData* data = NULL;
214 AvbABFlowResult ret;
215 AvbABData ab_data, ab_data_orig;
216 size_t slot_index_to_boot, n;
217 AvbIOResult io_ret;
218 bool saw_and_allowed_verification_error = false;
219
220 io_ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
221 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
222 ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
223 goto out;
224 } else if (io_ret != AVB_IO_RESULT_OK) {
225 ret = AVB_AB_FLOW_RESULT_ERROR_IO;
226 goto out;
227 }
228
229 /* Validate all bootable slots. */
230 for (n = 0; n < 2; n++) {
231 if (slot_is_bootable(&ab_data.slots[n])) {
232 AvbSlotVerifyResult verify_result;
233 bool set_slot_unbootable = false;
234
235 verify_result = avb_slot_verify(ops,
236 requested_partitions,
237 slot_suffixes[n],
238 flags,
239 hashtree_error_mode,
240 &slot_data[n]);
241 switch (verify_result) {
242 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
243 ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
244 goto out;
245
246 case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
247 ret = AVB_AB_FLOW_RESULT_ERROR_IO;
248 goto out;
249
250 case AVB_SLOT_VERIFY_RESULT_OK:
251 break;
252
253 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
254 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
255 /* Even with AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
256 * these mean game over.
257 */
258 set_slot_unbootable = true;
259 break;
260
261 /* explicit fallthrough. */
262 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
263 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
264 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
265 if (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR) {
266 /* Do nothing since we allow this. */
267 avb_debugv("Allowing slot ",
268 slot_suffixes[n],
269 " which verified "
270 "with result ",
271 avb_slot_verify_result_to_string(verify_result),
272 " because "
273 "AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR "
274 "is set.\n",
275 NULL);
276 saw_and_allowed_verification_error = true;
277 } else {
278 set_slot_unbootable = true;
279 }
280 break;
281
282 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
283 ret = AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT;
284 goto out;
285 /* Do not add a 'default:' case here because of -Wswitch. */
286 }
287
288 if (set_slot_unbootable) {
289 avb_errorv("Error verifying slot ",
290 slot_suffixes[n],
291 " with result ",
292 avb_slot_verify_result_to_string(verify_result),
293 " - setting unbootable.\n",
294 NULL);
295 slot_set_unbootable(&ab_data.slots[n]);
296 }
297 }
298 }
299
300 if (slot_is_bootable(&ab_data.slots[0]) &&
301 slot_is_bootable(&ab_data.slots[1])) {
302 if (ab_data.slots[1].priority > ab_data.slots[0].priority) {
303 slot_index_to_boot = 1;
304 } else {
305 slot_index_to_boot = 0;
306 }
307 } else if (slot_is_bootable(&ab_data.slots[0])) {
308 slot_index_to_boot = 0;
309 } else if (slot_is_bootable(&ab_data.slots[1])) {
310 slot_index_to_boot = 1;
311 } else {
312 /* No bootable slots! */
313 avb_error("No bootable slots found.\n");
314 ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
315 goto out;
316 }
317
318 /* Update stored rollback index such that the stored rollback index
319 * is the largest value supporting all currently bootable slots. Do
320 * this for every rollback index location.
321 */
322 for (n = 0; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) {
323 uint64_t rollback_index_value = 0;
324
325 if (slot_data[0] != NULL && slot_data[1] != NULL) {
326 uint64_t a_rollback_index = slot_data[0]->rollback_indexes[n];
327 uint64_t b_rollback_index = slot_data[1]->rollback_indexes[n];
328 rollback_index_value =
329 (a_rollback_index < b_rollback_index ? a_rollback_index
330 : b_rollback_index);
331 } else if (slot_data[0] != NULL) {
332 rollback_index_value = slot_data[0]->rollback_indexes[n];
333 } else if (slot_data[1] != NULL) {
334 rollback_index_value = slot_data[1]->rollback_indexes[n];
335 }
336
337 if (rollback_index_value != 0) {
338 uint64_t current_rollback_index_value;
339 io_ret = ops->read_rollback_index(ops, n, ¤t_rollback_index_value);
340 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
341 ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
342 goto out;
343 } else if (io_ret != AVB_IO_RESULT_OK) {
344 avb_error("Error getting rollback index for slot.\n");
345 ret = AVB_AB_FLOW_RESULT_ERROR_IO;
346 goto out;
347 }
348 if (current_rollback_index_value != rollback_index_value) {
349 io_ret = ops->write_rollback_index(ops, n, rollback_index_value);
350 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
351 ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
352 goto out;
353 } else if (io_ret != AVB_IO_RESULT_OK) {
354 avb_error("Error setting stored rollback index.\n");
355 ret = AVB_AB_FLOW_RESULT_ERROR_IO;
356 goto out;
357 }
358 }
359 }
360 }
361
362 /* Finally, select this slot. */
363 avb_assert(slot_data[slot_index_to_boot] != NULL);
364 data = slot_data[slot_index_to_boot];
365 slot_data[slot_index_to_boot] = NULL;
366 if (saw_and_allowed_verification_error) {
367 avb_assert(flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
368 ret = AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR;
369 } else {
370 ret = AVB_AB_FLOW_RESULT_OK;
371 }
372
373 /* ... and decrement tries remaining, if applicable. */
374 if (!ab_data.slots[slot_index_to_boot].successful_boot &&
375 ab_data.slots[slot_index_to_boot].tries_remaining > 0) {
376 ab_data.slots[slot_index_to_boot].tries_remaining -= 1;
377 }
378
379 out:
380 io_ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
381 if (io_ret != AVB_IO_RESULT_OK) {
382 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
383 ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
384 } else {
385 ret = AVB_AB_FLOW_RESULT_ERROR_IO;
386 }
387 if (data != NULL) {
388 avb_slot_verify_data_free(data);
389 data = NULL;
390 }
391 }
392
393 for (n = 0; n < 2; n++) {
394 if (slot_data[n] != NULL) {
395 avb_slot_verify_data_free(slot_data[n]);
396 }
397 }
398
399 if (out_data != NULL) {
400 *out_data = data;
401 } else {
402 if (data != NULL) {
403 avb_slot_verify_data_free(data);
404 }
405 }
406
407 return ret;
408 }
409
avb_ab_mark_slot_active(AvbABOps * ab_ops,unsigned int slot_number)410 AvbIOResult avb_ab_mark_slot_active(AvbABOps* ab_ops,
411 unsigned int slot_number) {
412 AvbABData ab_data, ab_data_orig;
413 unsigned int other_slot_number;
414 AvbIOResult ret;
415
416 avb_assert(slot_number < 2);
417
418 ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
419 if (ret != AVB_IO_RESULT_OK) {
420 goto out;
421 }
422
423 /* Make requested slot top priority, unsuccessful, and with max tries. */
424 ab_data.slots[slot_number].priority = AVB_AB_MAX_PRIORITY;
425 ab_data.slots[slot_number].tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
426 ab_data.slots[slot_number].successful_boot = 0;
427
428 /* Ensure other slot doesn't have as high a priority. */
429 other_slot_number = 1 - slot_number;
430 if (ab_data.slots[other_slot_number].priority == AVB_AB_MAX_PRIORITY) {
431 ab_data.slots[other_slot_number].priority = AVB_AB_MAX_PRIORITY - 1;
432 }
433
434 ret = AVB_IO_RESULT_OK;
435
436 out:
437 if (ret == AVB_IO_RESULT_OK) {
438 ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
439 }
440 return ret;
441 }
442
avb_ab_mark_slot_unbootable(AvbABOps * ab_ops,unsigned int slot_number)443 AvbIOResult avb_ab_mark_slot_unbootable(AvbABOps* ab_ops,
444 unsigned int slot_number) {
445 AvbABData ab_data, ab_data_orig;
446 AvbIOResult ret;
447
448 avb_assert(slot_number < 2);
449
450 ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
451 if (ret != AVB_IO_RESULT_OK) {
452 goto out;
453 }
454
455 slot_set_unbootable(&ab_data.slots[slot_number]);
456
457 ret = AVB_IO_RESULT_OK;
458
459 out:
460 if (ret == AVB_IO_RESULT_OK) {
461 ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
462 }
463 return ret;
464 }
465
avb_ab_mark_slot_successful(AvbABOps * ab_ops,unsigned int slot_number)466 AvbIOResult avb_ab_mark_slot_successful(AvbABOps* ab_ops,
467 unsigned int slot_number) {
468 AvbABData ab_data, ab_data_orig;
469 AvbIOResult ret;
470
471 avb_assert(slot_number < 2);
472
473 ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
474 if (ret != AVB_IO_RESULT_OK) {
475 goto out;
476 }
477
478 if (!slot_is_bootable(&ab_data.slots[slot_number])) {
479 avb_error("Cannot mark unbootable slot as successful.\n");
480 ret = AVB_IO_RESULT_OK;
481 goto out;
482 }
483
484 ab_data.slots[slot_number].tries_remaining = 0;
485 ab_data.slots[slot_number].successful_boot = 1;
486
487 ret = AVB_IO_RESULT_OK;
488
489 out:
490 if (ret == AVB_IO_RESULT_OK) {
491 ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
492 }
493 return ret;
494 }
495
avb_ab_flow_result_to_string(AvbABFlowResult result)496 const char* avb_ab_flow_result_to_string(AvbABFlowResult result) {
497 const char* ret = NULL;
498
499 switch (result) {
500 case AVB_AB_FLOW_RESULT_OK:
501 ret = "OK";
502 break;
503
504 case AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR:
505 ret = "OK_WITH_VERIFICATION_ERROR";
506 break;
507
508 case AVB_AB_FLOW_RESULT_ERROR_OOM:
509 ret = "ERROR_OOM";
510 break;
511
512 case AVB_AB_FLOW_RESULT_ERROR_IO:
513 ret = "ERROR_IO";
514 break;
515
516 case AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS:
517 ret = "ERROR_NO_BOOTABLE_SLOTS";
518 break;
519
520 case AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT:
521 ret = "ERROR_INVALID_ARGUMENT";
522 break;
523 /* Do not add a 'default:' case here because of -Wswitch. */
524 }
525
526 if (ret == NULL) {
527 avb_error("Unknown AvbABFlowResult value.\n");
528 ret = "(unknown)";
529 }
530
531 return ret;
532 }
533