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, &current_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