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,bool allow_verification_error,AvbSlotVerifyData ** out_data)205 AvbABFlowResult avb_ab_flow(AvbABOps* ab_ops,
206 const char* const* requested_partitions,
207 bool allow_verification_error,
208 AvbSlotVerifyData** out_data) {
209 AvbOps* ops = ab_ops->ops;
210 AvbSlotVerifyData* slot_data[2] = {NULL, NULL};
211 AvbSlotVerifyData* data = NULL;
212 AvbABFlowResult ret;
213 AvbABData ab_data, ab_data_orig;
214 size_t slot_index_to_boot, n;
215 AvbIOResult io_ret;
216 bool saw_and_allowed_verification_error = false;
217
218 io_ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
219 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
220 ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
221 goto out;
222 } else if (io_ret != AVB_IO_RESULT_OK) {
223 ret = AVB_AB_FLOW_RESULT_ERROR_IO;
224 goto out;
225 }
226
227 /* Validate all bootable slots. */
228 for (n = 0; n < 2; n++) {
229 if (slot_is_bootable(&ab_data.slots[n])) {
230 AvbSlotVerifyResult verify_result;
231 bool set_slot_unbootable = false;
232
233 verify_result = avb_slot_verify(ops,
234 requested_partitions,
235 slot_suffixes[n],
236 allow_verification_error,
237 &slot_data[n]);
238 switch (verify_result) {
239 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
240 ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
241 goto out;
242
243 case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
244 ret = AVB_AB_FLOW_RESULT_ERROR_IO;
245 goto out;
246
247 case AVB_SLOT_VERIFY_RESULT_OK:
248 break;
249
250 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
251 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
252 /* Even with |allow_verification_error| these mean game over. */
253 set_slot_unbootable = true;
254 break;
255
256 /* explicit fallthrough. */
257 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
258 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
259 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
260 if (allow_verification_error) {
261 /* Do nothing since we allow this. */
262 avb_debugv("Allowing slot ",
263 slot_suffixes[n],
264 " which verified "
265 "with result ",
266 avb_slot_verify_result_to_string(verify_result),
267 " because |allow_verification_error| is true.\n",
268 NULL);
269 saw_and_allowed_verification_error = true;
270 } else {
271 set_slot_unbootable = true;
272 }
273 break;
274 }
275
276 if (set_slot_unbootable) {
277 avb_errorv("Error verifying slot ",
278 slot_suffixes[n],
279 " with result ",
280 avb_slot_verify_result_to_string(verify_result),
281 " - setting unbootable.\n",
282 NULL);
283 slot_set_unbootable(&ab_data.slots[n]);
284 }
285 }
286 }
287
288 if (slot_is_bootable(&ab_data.slots[0]) &&
289 slot_is_bootable(&ab_data.slots[1])) {
290 if (ab_data.slots[1].priority > ab_data.slots[0].priority) {
291 slot_index_to_boot = 1;
292 } else {
293 slot_index_to_boot = 0;
294 }
295 } else if (slot_is_bootable(&ab_data.slots[0])) {
296 slot_index_to_boot = 0;
297 } else if (slot_is_bootable(&ab_data.slots[1])) {
298 slot_index_to_boot = 1;
299 } else {
300 /* No bootable slots! */
301 avb_error("No bootable slots found.\n");
302 ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
303 goto out;
304 }
305
306 /* Update stored rollback index such that the stored rollback index
307 * is the largest value supporting all currently bootable slots. Do
308 * this for every rollback index location.
309 */
310 for (n = 0; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) {
311 uint64_t rollback_index_value = 0;
312
313 if (slot_data[0] != NULL && slot_data[1] != NULL) {
314 uint64_t a_rollback_index = slot_data[0]->rollback_indexes[n];
315 uint64_t b_rollback_index = slot_data[1]->rollback_indexes[n];
316 rollback_index_value =
317 (a_rollback_index < b_rollback_index ? a_rollback_index
318 : b_rollback_index);
319 } else if (slot_data[0] != NULL) {
320 rollback_index_value = slot_data[0]->rollback_indexes[n];
321 } else if (slot_data[1] != NULL) {
322 rollback_index_value = slot_data[1]->rollback_indexes[n];
323 }
324
325 if (rollback_index_value != 0) {
326 uint64_t current_rollback_index_value;
327 io_ret = ops->read_rollback_index(ops, n, ¤t_rollback_index_value);
328 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
329 ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
330 goto out;
331 } else if (io_ret != AVB_IO_RESULT_OK) {
332 avb_error("Error getting rollback index for slot.\n");
333 ret = AVB_AB_FLOW_RESULT_ERROR_IO;
334 goto out;
335 }
336 if (current_rollback_index_value != rollback_index_value) {
337 io_ret = ops->write_rollback_index(ops, n, rollback_index_value);
338 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
339 ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
340 goto out;
341 } else if (io_ret != AVB_IO_RESULT_OK) {
342 avb_error("Error setting stored rollback index.\n");
343 ret = AVB_AB_FLOW_RESULT_ERROR_IO;
344 goto out;
345 }
346 }
347 }
348 }
349
350 /* Finally, select this slot. */
351 avb_assert(slot_data[slot_index_to_boot] != NULL);
352 data = slot_data[slot_index_to_boot];
353 slot_data[slot_index_to_boot] = NULL;
354 if (saw_and_allowed_verification_error) {
355 avb_assert(allow_verification_error);
356 ret = AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR;
357 } else {
358 ret = AVB_AB_FLOW_RESULT_OK;
359 }
360
361 /* ... and decrement tries remaining, if applicable. */
362 if (!ab_data.slots[slot_index_to_boot].successful_boot &&
363 ab_data.slots[slot_index_to_boot].tries_remaining > 0) {
364 ab_data.slots[slot_index_to_boot].tries_remaining -= 1;
365 }
366
367 out:
368 io_ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
369 if (io_ret != AVB_IO_RESULT_OK) {
370 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
371 ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
372 } else {
373 ret = AVB_AB_FLOW_RESULT_ERROR_IO;
374 }
375 if (data != NULL) {
376 avb_slot_verify_data_free(data);
377 data = NULL;
378 }
379 }
380
381 for (n = 0; n < 2; n++) {
382 if (slot_data[n] != NULL) {
383 avb_slot_verify_data_free(slot_data[n]);
384 }
385 }
386
387 if (out_data != NULL) {
388 *out_data = data;
389 } else {
390 if (data != NULL) {
391 avb_slot_verify_data_free(data);
392 }
393 }
394
395 return ret;
396 }
397
avb_ab_mark_slot_active(AvbABOps * ab_ops,unsigned int slot_number)398 AvbIOResult avb_ab_mark_slot_active(AvbABOps* ab_ops,
399 unsigned int slot_number) {
400 AvbABData ab_data, ab_data_orig;
401 unsigned int other_slot_number;
402 AvbIOResult ret;
403
404 avb_assert(slot_number < 2);
405
406 ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
407 if (ret != AVB_IO_RESULT_OK) {
408 goto out;
409 }
410
411 /* Make requested slot top priority, unsuccessful, and with max tries. */
412 ab_data.slots[slot_number].priority = AVB_AB_MAX_PRIORITY;
413 ab_data.slots[slot_number].tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
414 ab_data.slots[slot_number].successful_boot = 0;
415
416 /* Ensure other slot doesn't have as high a priority. */
417 other_slot_number = 1 - slot_number;
418 if (ab_data.slots[other_slot_number].priority == AVB_AB_MAX_PRIORITY) {
419 ab_data.slots[other_slot_number].priority = AVB_AB_MAX_PRIORITY - 1;
420 }
421
422 ret = AVB_IO_RESULT_OK;
423
424 out:
425 if (ret == AVB_IO_RESULT_OK) {
426 ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
427 }
428 return ret;
429 }
430
avb_ab_mark_slot_unbootable(AvbABOps * ab_ops,unsigned int slot_number)431 AvbIOResult avb_ab_mark_slot_unbootable(AvbABOps* ab_ops,
432 unsigned int slot_number) {
433 AvbABData ab_data, ab_data_orig;
434 AvbIOResult ret;
435
436 avb_assert(slot_number < 2);
437
438 ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
439 if (ret != AVB_IO_RESULT_OK) {
440 goto out;
441 }
442
443 slot_set_unbootable(&ab_data.slots[slot_number]);
444
445 ret = AVB_IO_RESULT_OK;
446
447 out:
448 if (ret == AVB_IO_RESULT_OK) {
449 ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
450 }
451 return ret;
452 }
453
avb_ab_mark_slot_successful(AvbABOps * ab_ops,unsigned int slot_number)454 AvbIOResult avb_ab_mark_slot_successful(AvbABOps* ab_ops,
455 unsigned int slot_number) {
456 AvbABData ab_data, ab_data_orig;
457 AvbIOResult ret;
458
459 avb_assert(slot_number < 2);
460
461 ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
462 if (ret != AVB_IO_RESULT_OK) {
463 goto out;
464 }
465
466 if (!slot_is_bootable(&ab_data.slots[slot_number])) {
467 avb_error("Cannot mark unbootable slot as successful.\n");
468 ret = AVB_IO_RESULT_OK;
469 goto out;
470 }
471
472 ab_data.slots[slot_number].tries_remaining = 0;
473 ab_data.slots[slot_number].successful_boot = 1;
474
475 ret = AVB_IO_RESULT_OK;
476
477 out:
478 if (ret == AVB_IO_RESULT_OK) {
479 ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
480 }
481 return ret;
482 }
483
avb_ab_flow_result_to_string(AvbABFlowResult result)484 const char* avb_ab_flow_result_to_string(AvbABFlowResult result) {
485 const char* ret = NULL;
486
487 switch (result) {
488 case AVB_AB_FLOW_RESULT_OK:
489 ret = "OK";
490 break;
491
492 case AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR:
493 ret = "OK_WITH_VERIFICATION_ERROR";
494 break;
495
496 case AVB_AB_FLOW_RESULT_ERROR_OOM:
497 ret = "ERROR_OOM";
498 break;
499
500 case AVB_AB_FLOW_RESULT_ERROR_IO:
501 ret = "ERROR_IO";
502 break;
503
504 case AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS:
505 ret = "ERROR_NO_BOOTABLE_SLOTS";
506 break;
507 /* Do not add a 'default:' case here because of -Wswitch. */
508 }
509
510 if (ret == NULL) {
511 avb_error("Unknown AvbABFlowResult value.\n");
512 ret = "(unknown)";
513 }
514
515 return ret;
516 }
517