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_debug("Allowing slot ",
267 slot_suffixes[n],
268 " which verified with result ",
269 avb_slot_verify_result_to_string(verify_result),
270 " because AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR "
271 "is set.\n");
272 saw_and_allowed_verification_error = true;
273 } else {
274 set_slot_unbootable = true;
275 }
276 break;
277
278 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
279 ret = AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT;
280 goto out;
281 /* Do not add a 'default:' case here because of -Wswitch. */
282 }
283
284 if (set_slot_unbootable) {
285 avb_error("Error verifying slot ",
286 slot_suffixes[n],
287 " with result ",
288 avb_slot_verify_result_to_string(verify_result),
289 " - setting unbootable.\n");
290 slot_set_unbootable(&ab_data.slots[n]);
291 }
292 }
293 }
294
295 if (slot_is_bootable(&ab_data.slots[0]) &&
296 slot_is_bootable(&ab_data.slots[1])) {
297 if (ab_data.slots[1].priority > ab_data.slots[0].priority) {
298 slot_index_to_boot = 1;
299 } else {
300 slot_index_to_boot = 0;
301 }
302 } else if (slot_is_bootable(&ab_data.slots[0])) {
303 slot_index_to_boot = 0;
304 } else if (slot_is_bootable(&ab_data.slots[1])) {
305 slot_index_to_boot = 1;
306 } else {
307 /* No bootable slots! */
308 avb_error("No bootable slots found.\n");
309 ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
310 goto out;
311 }
312
313 /* Update stored rollback index such that the stored rollback index
314 * is the largest value supporting all currently bootable slots. Do
315 * this for every rollback index location.
316 */
317 for (n = 0; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) {
318 uint64_t rollback_index_value = 0;
319
320 if (slot_data[0] != NULL && slot_data[1] != NULL) {
321 uint64_t a_rollback_index = slot_data[0]->rollback_indexes[n];
322 uint64_t b_rollback_index = slot_data[1]->rollback_indexes[n];
323 rollback_index_value =
324 (a_rollback_index < b_rollback_index ? a_rollback_index
325 : b_rollback_index);
326 } else if (slot_data[0] != NULL) {
327 rollback_index_value = slot_data[0]->rollback_indexes[n];
328 } else if (slot_data[1] != NULL) {
329 rollback_index_value = slot_data[1]->rollback_indexes[n];
330 }
331
332 if (rollback_index_value != 0) {
333 uint64_t current_rollback_index_value;
334 io_ret = ops->read_rollback_index(ops, n, ¤t_rollback_index_value);
335 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
336 ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
337 goto out;
338 } else if (io_ret != AVB_IO_RESULT_OK) {
339 avb_error("Error getting rollback index for slot.\n");
340 ret = AVB_AB_FLOW_RESULT_ERROR_IO;
341 goto out;
342 }
343 if (current_rollback_index_value != rollback_index_value) {
344 io_ret = ops->write_rollback_index(ops, n, rollback_index_value);
345 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
346 ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
347 goto out;
348 } else if (io_ret != AVB_IO_RESULT_OK) {
349 avb_error("Error setting stored rollback index.\n");
350 ret = AVB_AB_FLOW_RESULT_ERROR_IO;
351 goto out;
352 }
353 }
354 }
355 }
356
357 /* Finally, select this slot. */
358 avb_assert(slot_data[slot_index_to_boot] != NULL);
359 data = slot_data[slot_index_to_boot];
360 slot_data[slot_index_to_boot] = NULL;
361 if (saw_and_allowed_verification_error) {
362 avb_assert(flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
363 ret = AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR;
364 } else {
365 ret = AVB_AB_FLOW_RESULT_OK;
366 }
367
368 /* ... and decrement tries remaining, if applicable. */
369 if (!ab_data.slots[slot_index_to_boot].successful_boot &&
370 ab_data.slots[slot_index_to_boot].tries_remaining > 0) {
371 ab_data.slots[slot_index_to_boot].tries_remaining -= 1;
372 }
373
374 out:
375 io_ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
376 if (io_ret != AVB_IO_RESULT_OK) {
377 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
378 ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
379 } else {
380 ret = AVB_AB_FLOW_RESULT_ERROR_IO;
381 }
382 if (data != NULL) {
383 avb_slot_verify_data_free(data);
384 data = NULL;
385 }
386 }
387
388 for (n = 0; n < 2; n++) {
389 if (slot_data[n] != NULL) {
390 avb_slot_verify_data_free(slot_data[n]);
391 }
392 }
393
394 if (out_data != NULL) {
395 *out_data = data;
396 } else {
397 if (data != NULL) {
398 avb_slot_verify_data_free(data);
399 }
400 }
401
402 return ret;
403 }
404
avb_ab_mark_slot_active(AvbABOps * ab_ops,unsigned int slot_number)405 AvbIOResult avb_ab_mark_slot_active(AvbABOps* ab_ops,
406 unsigned int slot_number) {
407 AvbABData ab_data, ab_data_orig;
408 unsigned int other_slot_number;
409 AvbIOResult ret;
410
411 avb_assert(slot_number < 2);
412
413 ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
414 if (ret != AVB_IO_RESULT_OK) {
415 goto out;
416 }
417
418 /* Make requested slot top priority, unsuccessful, and with max tries. */
419 ab_data.slots[slot_number].priority = AVB_AB_MAX_PRIORITY;
420 ab_data.slots[slot_number].tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
421 ab_data.slots[slot_number].successful_boot = 0;
422
423 /* Ensure other slot doesn't have as high a priority. */
424 other_slot_number = 1 - slot_number;
425 if (ab_data.slots[other_slot_number].priority == AVB_AB_MAX_PRIORITY) {
426 ab_data.slots[other_slot_number].priority = AVB_AB_MAX_PRIORITY - 1;
427 }
428
429 ret = AVB_IO_RESULT_OK;
430
431 out:
432 if (ret == AVB_IO_RESULT_OK) {
433 ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
434 }
435 return ret;
436 }
437
avb_ab_mark_slot_unbootable(AvbABOps * ab_ops,unsigned int slot_number)438 AvbIOResult avb_ab_mark_slot_unbootable(AvbABOps* ab_ops,
439 unsigned int slot_number) {
440 AvbABData ab_data, ab_data_orig;
441 AvbIOResult ret;
442
443 avb_assert(slot_number < 2);
444
445 ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
446 if (ret != AVB_IO_RESULT_OK) {
447 goto out;
448 }
449
450 slot_set_unbootable(&ab_data.slots[slot_number]);
451
452 ret = AVB_IO_RESULT_OK;
453
454 out:
455 if (ret == AVB_IO_RESULT_OK) {
456 ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
457 }
458 return ret;
459 }
460
avb_ab_mark_slot_successful(AvbABOps * ab_ops,unsigned int slot_number)461 AvbIOResult avb_ab_mark_slot_successful(AvbABOps* ab_ops,
462 unsigned int slot_number) {
463 AvbABData ab_data, ab_data_orig;
464 AvbIOResult ret;
465
466 avb_assert(slot_number < 2);
467
468 ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
469 if (ret != AVB_IO_RESULT_OK) {
470 goto out;
471 }
472
473 if (!slot_is_bootable(&ab_data.slots[slot_number])) {
474 avb_error("Cannot mark unbootable slot as successful.\n");
475 ret = AVB_IO_RESULT_OK;
476 goto out;
477 }
478
479 ab_data.slots[slot_number].tries_remaining = 0;
480 ab_data.slots[slot_number].successful_boot = 1;
481
482 ret = AVB_IO_RESULT_OK;
483
484 out:
485 if (ret == AVB_IO_RESULT_OK) {
486 ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
487 }
488 return ret;
489 }
490
avb_ab_flow_result_to_string(AvbABFlowResult result)491 const char* avb_ab_flow_result_to_string(AvbABFlowResult result) {
492 const char* ret = NULL;
493
494 switch (result) {
495 case AVB_AB_FLOW_RESULT_OK:
496 ret = "OK";
497 break;
498
499 case AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR:
500 ret = "OK_WITH_VERIFICATION_ERROR";
501 break;
502
503 case AVB_AB_FLOW_RESULT_ERROR_OOM:
504 ret = "ERROR_OOM";
505 break;
506
507 case AVB_AB_FLOW_RESULT_ERROR_IO:
508 ret = "ERROR_IO";
509 break;
510
511 case AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS:
512 ret = "ERROR_NO_BOOTABLE_SLOTS";
513 break;
514
515 case AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT:
516 ret = "ERROR_INVALID_ARGUMENT";
517 break;
518 /* Do not add a 'default:' case here because of -Wswitch. */
519 }
520
521 if (ret == NULL) {
522 avb_error("Unknown AvbABFlowResult value.\n");
523 ret = "(unknown)";
524 }
525
526 return ret;
527 }
528