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 "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->slots[0].priority = AVB_AB_MAX_PRIORITY;
68 data->slots[0].tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
69 data->slots[0].successful_boot = 0;
70 data->slots[1].priority = AVB_AB_MAX_PRIORITY - 1;
71 data->slots[1].tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
72 data->slots[1].successful_boot = 0;
73 }
74
75 /* The AvbABData struct is stored 2048 bytes into the 'misc' partition
76 * following the 'struct bootloader_message' field. The struct is
77 * compatible with the guidelines in bootable/recovery/bootloader.h -
78 * e.g. it is stored in the |slot_suffix| field, starts with a
79 * NUL-byte, and is 32 bytes long.
80 */
81 #define AB_METADATA_MISC_PARTITION_OFFSET 2048
82
avb_ab_data_read(AvbABOps * ab_ops,AvbABData * data)83 AvbIOResult avb_ab_data_read(AvbABOps* ab_ops, AvbABData* data) {
84 AvbOps* ops = ab_ops->ops;
85 AvbABData serialized;
86 AvbIOResult io_ret;
87 size_t num_bytes_read;
88
89 io_ret = ops->read_from_partition(ops,
90 "misc",
91 AB_METADATA_MISC_PARTITION_OFFSET,
92 sizeof(AvbABData),
93 &serialized,
94 &num_bytes_read);
95 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
96 return AVB_IO_RESULT_ERROR_OOM;
97 } else if (io_ret != AVB_IO_RESULT_OK ||
98 num_bytes_read != sizeof(AvbABData)) {
99 avb_error("Error reading A/B metadata.\n");
100 return AVB_IO_RESULT_ERROR_IO;
101 }
102
103 if (!avb_ab_data_verify_and_byteswap(&serialized, data)) {
104 avb_error(
105 "Error validating A/B metadata from disk. "
106 "Resetting and writing new A/B metadata to disk.\n");
107 avb_ab_data_init(data);
108 return avb_ab_data_write(ab_ops, data);
109 }
110
111 return AVB_IO_RESULT_OK;
112 }
113
avb_ab_data_write(AvbABOps * ab_ops,const AvbABData * data)114 AvbIOResult avb_ab_data_write(AvbABOps* ab_ops, const AvbABData* data) {
115 AvbOps* ops = ab_ops->ops;
116 AvbABData serialized;
117 AvbIOResult io_ret;
118
119 avb_ab_data_update_crc_and_byteswap(data, &serialized);
120 io_ret = ops->write_to_partition(ops,
121 "misc",
122 AB_METADATA_MISC_PARTITION_OFFSET,
123 sizeof(AvbABData),
124 &serialized);
125 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
126 return AVB_IO_RESULT_ERROR_OOM;
127 } else if (io_ret != AVB_IO_RESULT_OK) {
128 avb_error("Error writing A/B metadata.\n");
129 return AVB_IO_RESULT_ERROR_IO;
130 }
131 return AVB_IO_RESULT_OK;
132 }
133
slot_is_bootable(AvbABSlotData * slot)134 static bool slot_is_bootable(AvbABSlotData* slot) {
135 return slot->priority > 0 &&
136 (slot->successful_boot || (slot->tries_remaining > 0));
137 }
138
slot_set_unbootable(AvbABSlotData * slot)139 static void slot_set_unbootable(AvbABSlotData* slot) {
140 slot->priority = 0;
141 slot->tries_remaining = 0;
142 slot->successful_boot = 0;
143 }
144
145 /* Ensure all unbootable and/or illegal states are marked as the
146 * canonical 'unbootable' state, e.g. priority=0, tries_remaining=0,
147 * and successful_boot=0.
148 */
slot_normalize(AvbABSlotData * slot)149 static void slot_normalize(AvbABSlotData* slot) {
150 if (slot->priority > 0) {
151 if (slot->tries_remaining == 0 && !slot->successful_boot) {
152 /* We've exhausted all tries -> unbootable. */
153 slot_set_unbootable(slot);
154 }
155 if (slot->tries_remaining > 0 && slot->successful_boot) {
156 /* Illegal state - avb_ab_mark_slot_successful() will clear
157 * tries_remaining when setting successful_boot.
158 */
159 slot_set_unbootable(slot);
160 }
161 } else {
162 slot_set_unbootable(slot);
163 }
164 }
165
166 static const char* slot_suffixes[2] = {"_a", "_b"};
167
168 /* Helper function to load metadata - returns AVB_IO_RESULT_OK on
169 * success, error code otherwise.
170 */
load_metadata(AvbABOps * ab_ops,AvbABData * ab_data,AvbABData * ab_data_orig)171 static AvbIOResult load_metadata(AvbABOps* ab_ops,
172 AvbABData* ab_data,
173 AvbABData* ab_data_orig) {
174 AvbIOResult io_ret;
175
176 io_ret = ab_ops->read_ab_metadata(ab_ops, ab_data);
177 if (io_ret != AVB_IO_RESULT_OK) {
178 avb_error("I/O error while loading A/B metadata.\n");
179 return io_ret;
180 }
181 *ab_data_orig = *ab_data;
182
183 /* Ensure data is normalized, e.g. illegal states will be marked as
184 * unbootable and all unbootable states are represented with
185 * (priority=0, tries_remaining=0, successful_boot=0).
186 */
187 slot_normalize(&ab_data->slots[0]);
188 slot_normalize(&ab_data->slots[1]);
189 return AVB_IO_RESULT_OK;
190 }
191
192 /* Writes A/B metadata to disk only if it has changed - returns
193 * AVB_IO_RESULT_OK on success, error code otherwise.
194 */
save_metadata_if_changed(AvbABOps * ab_ops,AvbABData * ab_data,AvbABData * ab_data_orig)195 static AvbIOResult save_metadata_if_changed(AvbABOps* ab_ops,
196 AvbABData* ab_data,
197 AvbABData* ab_data_orig) {
198 if (avb_safe_memcmp(ab_data, ab_data_orig, sizeof(AvbABData)) != 0) {
199 avb_debug("Writing A/B metadata to disk.\n");
200 return ab_ops->write_ab_metadata(ab_ops, ab_data);
201 }
202 return AVB_IO_RESULT_OK;
203 }
204
avb_ab_flow(AvbABOps * ab_ops,const char * const * requested_partitions,AvbSlotVerifyFlags flags,AvbHashtreeErrorMode hashtree_error_mode,AvbSlotVerifyData ** out_data)205 AvbABFlowResult avb_ab_flow(AvbABOps* ab_ops,
206 const char* const* requested_partitions,
207 AvbSlotVerifyFlags flags,
208 AvbHashtreeErrorMode hashtree_error_mode,
209 AvbSlotVerifyData** out_data) {
210 AvbOps* ops = ab_ops->ops;
211 AvbSlotVerifyData* slot_data[2] = {NULL, NULL};
212 AvbSlotVerifyData* data = NULL;
213 AvbABFlowResult ret;
214 AvbABData ab_data, ab_data_orig;
215 size_t slot_index_to_boot, n;
216 AvbIOResult io_ret;
217 bool saw_and_allowed_verification_error = false;
218
219 io_ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
220 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
221 ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
222 goto out;
223 } else if (io_ret != AVB_IO_RESULT_OK) {
224 ret = AVB_AB_FLOW_RESULT_ERROR_IO;
225 goto out;
226 }
227
228 /* Validate all bootable slots. */
229 for (n = 0; n < 2; n++) {
230 if (slot_is_bootable(&ab_data.slots[n])) {
231 AvbSlotVerifyResult verify_result;
232 bool set_slot_unbootable = false;
233
234 verify_result = avb_slot_verify(ops,
235 requested_partitions,
236 slot_suffixes[n],
237 flags,
238 hashtree_error_mode,
239 &slot_data[n]);
240 switch (verify_result) {
241 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
242 ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
243 goto out;
244
245 case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
246 ret = AVB_AB_FLOW_RESULT_ERROR_IO;
247 goto out;
248
249 case AVB_SLOT_VERIFY_RESULT_OK:
250 break;
251
252 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
253 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
254 /* Even with AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
255 * these mean game over.
256 */
257 set_slot_unbootable = true;
258 break;
259
260 /* explicit fallthrough. */
261 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
262 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
263 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
264 if (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR) {
265 /* Do nothing since we allow this. */
266 avb_debugv("Allowing slot ",
267 slot_suffixes[n],
268 " which verified "
269 "with result ",
270 avb_slot_verify_result_to_string(verify_result),
271 " because "
272 "AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR "
273 "is set.\n",
274 NULL);
275 saw_and_allowed_verification_error = true;
276 } else {
277 set_slot_unbootable = true;
278 }
279 break;
280
281 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
282 ret = AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT;
283 goto out;
284 /* Do not add a 'default:' case here because of -Wswitch. */
285 }
286
287 if (set_slot_unbootable) {
288 avb_errorv("Error verifying slot ",
289 slot_suffixes[n],
290 " with result ",
291 avb_slot_verify_result_to_string(verify_result),
292 " - setting unbootable.\n",
293 NULL);
294 slot_set_unbootable(&ab_data.slots[n]);
295 }
296 }
297 }
298
299 if (slot_is_bootable(&ab_data.slots[0]) &&
300 slot_is_bootable(&ab_data.slots[1])) {
301 if (ab_data.slots[1].priority > ab_data.slots[0].priority) {
302 slot_index_to_boot = 1;
303 } else {
304 slot_index_to_boot = 0;
305 }
306 } else if (slot_is_bootable(&ab_data.slots[0])) {
307 slot_index_to_boot = 0;
308 } else if (slot_is_bootable(&ab_data.slots[1])) {
309 slot_index_to_boot = 1;
310 } else {
311 /* No bootable slots! */
312 avb_error("No bootable slots found.\n");
313 ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
314 goto out;
315 }
316
317 /* Update stored rollback index such that the stored rollback index
318 * is the largest value supporting all currently bootable slots. Do
319 * this for every rollback index location.
320 */
321 for (n = 0; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) {
322 uint64_t rollback_index_value = 0;
323
324 if (slot_data[0] != NULL && slot_data[1] != NULL) {
325 uint64_t a_rollback_index = slot_data[0]->rollback_indexes[n];
326 uint64_t b_rollback_index = slot_data[1]->rollback_indexes[n];
327 rollback_index_value =
328 (a_rollback_index < b_rollback_index ? a_rollback_index
329 : b_rollback_index);
330 } else if (slot_data[0] != NULL) {
331 rollback_index_value = slot_data[0]->rollback_indexes[n];
332 } else if (slot_data[1] != NULL) {
333 rollback_index_value = slot_data[1]->rollback_indexes[n];
334 }
335
336 if (rollback_index_value != 0) {
337 uint64_t current_rollback_index_value;
338 io_ret = ops->read_rollback_index(ops, n, ¤t_rollback_index_value);
339 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
340 ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
341 goto out;
342 } else if (io_ret != AVB_IO_RESULT_OK) {
343 avb_error("Error getting rollback index for slot.\n");
344 ret = AVB_AB_FLOW_RESULT_ERROR_IO;
345 goto out;
346 }
347 if (current_rollback_index_value != rollback_index_value) {
348 io_ret = ops->write_rollback_index(ops, n, rollback_index_value);
349 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
350 ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
351 goto out;
352 } else if (io_ret != AVB_IO_RESULT_OK) {
353 avb_error("Error setting stored rollback index.\n");
354 ret = AVB_AB_FLOW_RESULT_ERROR_IO;
355 goto out;
356 }
357 }
358 }
359 }
360
361 /* Finally, select this slot. */
362 avb_assert(slot_data[slot_index_to_boot] != NULL);
363 data = slot_data[slot_index_to_boot];
364 slot_data[slot_index_to_boot] = NULL;
365 if (saw_and_allowed_verification_error) {
366 avb_assert(flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
367 ret = AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR;
368 } else {
369 ret = AVB_AB_FLOW_RESULT_OK;
370 }
371
372 /* ... and decrement tries remaining, if applicable. */
373 if (!ab_data.slots[slot_index_to_boot].successful_boot &&
374 ab_data.slots[slot_index_to_boot].tries_remaining > 0) {
375 ab_data.slots[slot_index_to_boot].tries_remaining -= 1;
376 }
377
378 out:
379 io_ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
380 if (io_ret != AVB_IO_RESULT_OK) {
381 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
382 ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
383 } else {
384 ret = AVB_AB_FLOW_RESULT_ERROR_IO;
385 }
386 if (data != NULL) {
387 avb_slot_verify_data_free(data);
388 data = NULL;
389 }
390 }
391
392 for (n = 0; n < 2; n++) {
393 if (slot_data[n] != NULL) {
394 avb_slot_verify_data_free(slot_data[n]);
395 }
396 }
397
398 if (out_data != NULL) {
399 *out_data = data;
400 } else {
401 if (data != NULL) {
402 avb_slot_verify_data_free(data);
403 }
404 }
405
406 return ret;
407 }
408
avb_ab_mark_slot_active(AvbABOps * ab_ops,unsigned int slot_number)409 AvbIOResult avb_ab_mark_slot_active(AvbABOps* ab_ops,
410 unsigned int slot_number) {
411 AvbABData ab_data, ab_data_orig;
412 unsigned int other_slot_number;
413 AvbIOResult ret;
414
415 avb_assert(slot_number < 2);
416
417 ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
418 if (ret != AVB_IO_RESULT_OK) {
419 goto out;
420 }
421
422 /* Make requested slot top priority, unsuccessful, and with max tries. */
423 ab_data.slots[slot_number].priority = AVB_AB_MAX_PRIORITY;
424 ab_data.slots[slot_number].tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
425 ab_data.slots[slot_number].successful_boot = 0;
426
427 /* Ensure other slot doesn't have as high a priority. */
428 other_slot_number = 1 - slot_number;
429 if (ab_data.slots[other_slot_number].priority == AVB_AB_MAX_PRIORITY) {
430 ab_data.slots[other_slot_number].priority = AVB_AB_MAX_PRIORITY - 1;
431 }
432
433 ret = AVB_IO_RESULT_OK;
434
435 out:
436 if (ret == AVB_IO_RESULT_OK) {
437 ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
438 }
439 return ret;
440 }
441
avb_ab_mark_slot_unbootable(AvbABOps * ab_ops,unsigned int slot_number)442 AvbIOResult avb_ab_mark_slot_unbootable(AvbABOps* ab_ops,
443 unsigned int slot_number) {
444 AvbABData ab_data, ab_data_orig;
445 AvbIOResult ret;
446
447 avb_assert(slot_number < 2);
448
449 ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
450 if (ret != AVB_IO_RESULT_OK) {
451 goto out;
452 }
453
454 slot_set_unbootable(&ab_data.slots[slot_number]);
455
456 ret = AVB_IO_RESULT_OK;
457
458 out:
459 if (ret == AVB_IO_RESULT_OK) {
460 ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
461 }
462 return ret;
463 }
464
avb_ab_mark_slot_successful(AvbABOps * ab_ops,unsigned int slot_number)465 AvbIOResult avb_ab_mark_slot_successful(AvbABOps* ab_ops,
466 unsigned int slot_number) {
467 AvbABData ab_data, ab_data_orig;
468 AvbIOResult ret;
469
470 avb_assert(slot_number < 2);
471
472 ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
473 if (ret != AVB_IO_RESULT_OK) {
474 goto out;
475 }
476
477 if (!slot_is_bootable(&ab_data.slots[slot_number])) {
478 avb_error("Cannot mark unbootable slot as successful.\n");
479 ret = AVB_IO_RESULT_OK;
480 goto out;
481 }
482
483 ab_data.slots[slot_number].tries_remaining = 0;
484 ab_data.slots[slot_number].successful_boot = 1;
485
486 ret = AVB_IO_RESULT_OK;
487
488 out:
489 if (ret == AVB_IO_RESULT_OK) {
490 ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
491 }
492 return ret;
493 }
494
avb_ab_flow_result_to_string(AvbABFlowResult result)495 const char* avb_ab_flow_result_to_string(AvbABFlowResult result) {
496 const char* ret = NULL;
497
498 switch (result) {
499 case AVB_AB_FLOW_RESULT_OK:
500 ret = "OK";
501 break;
502
503 case AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR:
504 ret = "OK_WITH_VERIFICATION_ERROR";
505 break;
506
507 case AVB_AB_FLOW_RESULT_ERROR_OOM:
508 ret = "ERROR_OOM";
509 break;
510
511 case AVB_AB_FLOW_RESULT_ERROR_IO:
512 ret = "ERROR_IO";
513 break;
514
515 case AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS:
516 ret = "ERROR_NO_BOOTABLE_SLOTS";
517 break;
518
519 case AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT:
520 ret = "ERROR_INVALID_ARGUMENT";
521 break;
522 /* Do not add a 'default:' case here because of -Wswitch. */
523 }
524
525 if (ret == NULL) {
526 avb_error("Unknown AvbABFlowResult value.\n");
527 ret = "(unknown)";
528 }
529
530 return ret;
531 }
532