1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "avb_util.h"
18 
19 #include <unistd.h>
20 
21 #include <array>
22 #include <sstream>
23 
24 #include <android-base/file.h>
25 #include <android-base/strings.h>
26 #include <android-base/unique_fd.h>
27 
28 #include "util.h"
29 
30 using android::base::Basename;
31 using android::base::ReadFileToString;
32 using android::base::StartsWith;
33 using android::base::unique_fd;
34 
35 namespace android {
36 namespace fs_mgr {
37 
GetAvbPropertyDescriptor(const std::string & key,const std::vector<VBMetaData> & vbmeta_images)38 std::string GetAvbPropertyDescriptor(const std::string& key,
39                                      const std::vector<VBMetaData>& vbmeta_images) {
40     size_t value_size;
41     for (const auto& vbmeta : vbmeta_images) {
42         const char* value = avb_property_lookup(vbmeta.data(), vbmeta.size(), key.data(),
43                                                 key.size(), &value_size);
44         if (value != nullptr) {
45             return {value, value_size};
46         }
47     }
48     return "";
49 }
50 
51 // Constructs dm-verity arguments for sending DM_TABLE_LOAD ioctl to kernel.
52 // See the following link for more details:
53 // https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity
ConstructVerityTable(const FsAvbHashtreeDescriptor & hashtree_desc,const std::string & blk_device,android::dm::DmTable * table)54 bool ConstructVerityTable(const FsAvbHashtreeDescriptor& hashtree_desc,
55                           const std::string& blk_device, android::dm::DmTable* table) {
56     // Loads androidboot.veritymode from kernel cmdline.
57     std::string verity_mode;
58     if (!fs_mgr_get_boot_config("veritymode", &verity_mode)) {
59         verity_mode = "enforcing";  // Defaults to enforcing when it's absent.
60     }
61 
62     // Converts veritymode to the format used in kernel.
63     std::string dm_verity_mode;
64     if (verity_mode == "panicking") {
65         dm_verity_mode = "panic_on_corruption";
66     } else if (verity_mode == "enforcing") {
67         dm_verity_mode = "restart_on_corruption";
68     } else if (verity_mode == "logging") {
69         dm_verity_mode = "ignore_corruption";
70     } else if (verity_mode != "eio") {  // Default dm_verity_mode is eio.
71         LERROR << "Unknown androidboot.veritymode: " << verity_mode;
72         return false;
73     }
74 
75     std::ostringstream hash_algorithm;
76     hash_algorithm << hashtree_desc.hash_algorithm;
77 
78     android::dm::DmTargetVerity target(
79             0, hashtree_desc.image_size / 512, hashtree_desc.dm_verity_version, blk_device,
80             blk_device, hashtree_desc.data_block_size, hashtree_desc.hash_block_size,
81             hashtree_desc.image_size / hashtree_desc.data_block_size,
82             hashtree_desc.tree_offset / hashtree_desc.hash_block_size, hash_algorithm.str(),
83             hashtree_desc.root_digest, hashtree_desc.salt);
84     if (hashtree_desc.fec_size > 0) {
85         target.UseFec(blk_device, hashtree_desc.fec_num_roots,
86                       hashtree_desc.fec_offset / hashtree_desc.data_block_size,
87                       hashtree_desc.fec_offset / hashtree_desc.data_block_size);
88     }
89     if (!dm_verity_mode.empty()) {
90         target.SetVerityMode(dm_verity_mode);
91     }
92     // Always use ignore_zero_blocks.
93     target.IgnoreZeroBlocks();
94 
95     LINFO << "Built verity table: '" << target.GetParameterString() << "'";
96 
97     return table->AddTarget(std::make_unique<android::dm::DmTargetVerity>(target));
98 }
99 
HashtreeDmVeritySetup(FstabEntry * fstab_entry,const FsAvbHashtreeDescriptor & hashtree_desc,bool wait_for_verity_dev)100 bool HashtreeDmVeritySetup(FstabEntry* fstab_entry, const FsAvbHashtreeDescriptor& hashtree_desc,
101                            bool wait_for_verity_dev) {
102     android::dm::DmTable table;
103     if (!ConstructVerityTable(hashtree_desc, fstab_entry->blk_device, &table) || !table.valid()) {
104         LERROR << "Failed to construct verity table.";
105         return false;
106     }
107     table.set_readonly(true);
108 
109     std::chrono::milliseconds timeout = {};
110     if (wait_for_verity_dev) timeout = 1s;
111 
112     std::string dev_path;
113     const std::string mount_point(Basename(fstab_entry->mount_point));
114     const std::string device_name(GetVerityDeviceName(*fstab_entry));
115     android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance();
116     if (!dm.CreateDevice(device_name, table, &dev_path, timeout)) {
117         LERROR << "Couldn't create verity device!";
118         return false;
119     }
120 
121     // Marks the underlying block device as read-only.
122     SetBlockDeviceReadOnly(fstab_entry->blk_device);
123 
124     // Updates fstab_rec->blk_device to verity device name.
125     fstab_entry->blk_device = dev_path;
126     return true;
127 }
128 
GetHashDescriptor(const std::string & partition_name,const std::vector<VBMetaData> & vbmeta_images)129 std::unique_ptr<FsAvbHashDescriptor> GetHashDescriptor(
130         const std::string& partition_name, const std::vector<VBMetaData>& vbmeta_images) {
131     bool found = false;
132     const uint8_t* desc_partition_name;
133     auto hash_desc = std::make_unique<FsAvbHashDescriptor>();
134 
135     for (const auto& vbmeta : vbmeta_images) {
136         size_t num_descriptors;
137         std::unique_ptr<const AvbDescriptor*[], decltype(&avb_free)> descriptors(
138                 avb_descriptor_get_all(vbmeta.data(), vbmeta.size(), &num_descriptors), avb_free);
139 
140         if (!descriptors || num_descriptors < 1) {
141             continue;
142         }
143 
144         for (size_t n = 0; n < num_descriptors && !found; n++) {
145             AvbDescriptor desc;
146             if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) {
147                 LWARNING << "Descriptor[" << n << "] is invalid";
148                 continue;
149             }
150             if (desc.tag == AVB_DESCRIPTOR_TAG_HASH) {
151                 desc_partition_name = (const uint8_t*)descriptors[n] + sizeof(AvbHashDescriptor);
152                 if (!avb_hash_descriptor_validate_and_byteswap((AvbHashDescriptor*)descriptors[n],
153                                                                hash_desc.get())) {
154                     continue;
155                 }
156                 if (hash_desc->partition_name_len != partition_name.length()) {
157                     continue;
158                 }
159                 // Notes that desc_partition_name is not NUL-terminated.
160                 std::string hash_partition_name((const char*)desc_partition_name,
161                                                 hash_desc->partition_name_len);
162                 if (hash_partition_name == partition_name) {
163                     found = true;
164                 }
165             }
166         }
167 
168         if (found) break;
169     }
170 
171     if (!found) {
172         LERROR << "Hash descriptor not found: " << partition_name;
173         return nullptr;
174     }
175 
176     hash_desc->partition_name = partition_name;
177 
178     const uint8_t* desc_salt = desc_partition_name + hash_desc->partition_name_len;
179     hash_desc->salt = BytesToHex(desc_salt, hash_desc->salt_len);
180 
181     const uint8_t* desc_digest = desc_salt + hash_desc->salt_len;
182     hash_desc->digest = BytesToHex(desc_digest, hash_desc->digest_len);
183 
184     return hash_desc;
185 }
186 
GetHashtreeDescriptor(const std::string & partition_name,const std::vector<VBMetaData> & vbmeta_images)187 std::unique_ptr<FsAvbHashtreeDescriptor> GetHashtreeDescriptor(
188         const std::string& partition_name, const std::vector<VBMetaData>& vbmeta_images) {
189     bool found = false;
190     const uint8_t* desc_partition_name;
191     auto hashtree_desc = std::make_unique<FsAvbHashtreeDescriptor>();
192 
193     for (const auto& vbmeta : vbmeta_images) {
194         size_t num_descriptors;
195         std::unique_ptr<const AvbDescriptor* [], decltype(&avb_free)> descriptors(
196                 avb_descriptor_get_all(vbmeta.data(), vbmeta.size(), &num_descriptors), avb_free);
197 
198         if (!descriptors || num_descriptors < 1) {
199             continue;
200         }
201 
202         for (size_t n = 0; n < num_descriptors && !found; n++) {
203             AvbDescriptor desc;
204             if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) {
205                 LWARNING << "Descriptor[" << n << "] is invalid";
206                 continue;
207             }
208             if (desc.tag == AVB_DESCRIPTOR_TAG_HASHTREE) {
209                 desc_partition_name =
210                         (const uint8_t*)descriptors[n] + sizeof(AvbHashtreeDescriptor);
211                 if (!avb_hashtree_descriptor_validate_and_byteswap(
212                         (AvbHashtreeDescriptor*)descriptors[n], hashtree_desc.get())) {
213                     continue;
214                 }
215                 if (hashtree_desc->partition_name_len != partition_name.length()) {
216                     continue;
217                 }
218                 // Notes that desc_partition_name is not NUL-terminated.
219                 std::string hashtree_partition_name((const char*)desc_partition_name,
220                                                     hashtree_desc->partition_name_len);
221                 if (hashtree_partition_name == partition_name) {
222                     found = true;
223                 }
224             }
225         }
226 
227         if (found) break;
228     }
229 
230     if (!found) {
231         LERROR << "Hashtree descriptor not found: " << partition_name;
232         return nullptr;
233     }
234 
235     hashtree_desc->partition_name = partition_name;
236 
237     const uint8_t* desc_salt = desc_partition_name + hashtree_desc->partition_name_len;
238     hashtree_desc->salt = BytesToHex(desc_salt, hashtree_desc->salt_len);
239 
240     const uint8_t* desc_digest = desc_salt + hashtree_desc->salt_len;
241     hashtree_desc->root_digest = BytesToHex(desc_digest, hashtree_desc->root_digest_len);
242 
243     return hashtree_desc;
244 }
245 
LoadAvbHashtreeToEnableVerity(FstabEntry * fstab_entry,bool wait_for_verity_dev,const std::vector<VBMetaData> & vbmeta_images,const std::string & ab_suffix,const std::string & ab_other_suffix)246 bool LoadAvbHashtreeToEnableVerity(FstabEntry* fstab_entry, bool wait_for_verity_dev,
247                                    const std::vector<VBMetaData>& vbmeta_images,
248                                    const std::string& ab_suffix,
249                                    const std::string& ab_other_suffix) {
250     // Derives partition_name from blk_device to query the corresponding AVB HASHTREE descriptor
251     // to setup dm-verity. The partition_names in AVB descriptors are without A/B suffix.
252     std::string partition_name = DeriveAvbPartitionName(*fstab_entry, ab_suffix, ab_other_suffix);
253 
254     if (partition_name.empty()) {
255         LERROR << "partition name is empty, cannot lookup AVB descriptors";
256         return false;
257     }
258 
259     std::unique_ptr<FsAvbHashtreeDescriptor> hashtree_descriptor =
260             GetHashtreeDescriptor(partition_name, vbmeta_images);
261     if (!hashtree_descriptor) {
262         return false;
263     }
264 
265     // Converts HASHTREE descriptor to verity table to load into kernel.
266     // When success, the new device path will be returned, e.g., /dev/block/dm-2.
267     return HashtreeDmVeritySetup(fstab_entry, *hashtree_descriptor, wait_for_verity_dev);
268 }
269 
270 // Converts a AVB partition_name (without A/B suffix) to a device partition name.
271 // e.g.,       "system" => "system_a",
272 //       "system_other" => "system_b".
273 //
274 // If the device is non-A/B, converts it to a partition name without suffix.
275 // e.g.,       "system" => "system",
276 //       "system_other" => "system".
AvbPartitionToDevicePatition(const std::string & avb_partition_name,const std::string & ab_suffix,const std::string & ab_other_suffix)277 std::string AvbPartitionToDevicePatition(const std::string& avb_partition_name,
278                                          const std::string& ab_suffix,
279                                          const std::string& ab_other_suffix) {
280     bool is_other_slot = false;
281     std::string sanitized_partition_name(avb_partition_name);
282 
283     auto other_suffix = sanitized_partition_name.rfind("_other");
284     if (other_suffix != std::string::npos) {
285         sanitized_partition_name.erase(other_suffix);  // converts system_other => system
286         is_other_slot = true;
287     }
288 
289     auto append_suffix = is_other_slot ? ab_other_suffix : ab_suffix;
290     return sanitized_partition_name + append_suffix;
291 }
292 
293 // Converts fstab_entry.blk_device (with ab_suffix) to a AVB partition name.
294 // e.g., "/dev/block/by-name/system_a", slot_select       => "system",
295 //       "/dev/block/by-name/system_b", slot_select_other => "system_other".
296 //
297 // Or for a logical partition (with ab_suffix):
298 // e.g., "system_a", slot_select       => "system",
299 //       "system_b", slot_select_other => "system_other".
DeriveAvbPartitionName(const FstabEntry & fstab_entry,const std::string & ab_suffix,const std::string & ab_other_suffix)300 std::string DeriveAvbPartitionName(const FstabEntry& fstab_entry, const std::string& ab_suffix,
301                                    const std::string& ab_other_suffix) {
302     std::string partition_name;
303     if (fstab_entry.fs_mgr_flags.logical) {
304         partition_name = fstab_entry.logical_partition_name;
305     } else {
306         partition_name = Basename(fstab_entry.blk_device);
307     }
308 
309     if (fstab_entry.fs_mgr_flags.slot_select) {
310         auto found = partition_name.rfind(ab_suffix);
311         if (found != std::string::npos) {
312             partition_name.erase(found);  // converts system_a => system
313         }
314     } else if (fstab_entry.fs_mgr_flags.slot_select_other) {
315         auto found = partition_name.rfind(ab_other_suffix);
316         if (found != std::string::npos) {
317             partition_name.erase(found);  // converts system_b => system
318         }
319         partition_name += "_other";  // converts system => system_other
320     }
321 
322     return partition_name;
323 }
324 
GetTotalSize(int fd)325 off64_t GetTotalSize(int fd) {
326     off64_t saved_current = lseek64(fd, 0, SEEK_CUR);
327     if (saved_current == -1) {
328         PERROR << "Failed to get current position";
329         return -1;
330     }
331 
332     // lseek64() returns the resulting offset location from the beginning of the file.
333     off64_t total_size = lseek64(fd, 0, SEEK_END);
334     if (total_size == -1) {
335         PERROR << "Failed to lseek64 to end of the partition";
336         return -1;
337     }
338 
339     // Restores the original offset.
340     if (lseek64(fd, saved_current, SEEK_SET) == -1) {
341         PERROR << "Failed to lseek64 to the original offset: " << saved_current;
342     }
343 
344     return total_size;
345 }
346 
GetAvbFooter(int fd)347 std::unique_ptr<AvbFooter> GetAvbFooter(int fd) {
348     std::array<uint8_t, AVB_FOOTER_SIZE> footer_buf;
349     auto footer = std::make_unique<AvbFooter>();
350 
351     off64_t footer_offset = GetTotalSize(fd) - AVB_FOOTER_SIZE;
352 
353     ssize_t num_read =
354             TEMP_FAILURE_RETRY(pread64(fd, footer_buf.data(), AVB_FOOTER_SIZE, footer_offset));
355     if (num_read < 0 || num_read != AVB_FOOTER_SIZE) {
356         PERROR << "Failed to read AVB footer at offset: " << footer_offset;
357         return nullptr;
358     }
359 
360     if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf.data(), footer.get())) {
361         PERROR << "AVB footer verification failed at offset " << footer_offset;
362         return nullptr;
363     }
364 
365     return footer;
366 }
367 
ValidatePublicKeyBlob(const uint8_t * key,size_t length,const std::string & expected_key_blob)368 bool ValidatePublicKeyBlob(const uint8_t* key, size_t length,
369                            const std::string& expected_key_blob) {
370     if (expected_key_blob.empty()) {  // no expectation of the key, return true.
371         return true;
372     }
373     if (expected_key_blob.size() != length) {
374         return false;
375     }
376     if (0 == memcmp(key, expected_key_blob.data(), length)) {
377         return true;
378     }
379     return false;
380 }
381 
ValidatePublicKeyBlob(const std::string & key_blob_to_validate,const std::vector<std::string> & allowed_key_paths)382 bool ValidatePublicKeyBlob(const std::string& key_blob_to_validate,
383                            const std::vector<std::string>& allowed_key_paths) {
384     std::string allowed_key_blob;
385     if (key_blob_to_validate.empty()) {
386         LWARNING << "Failed to validate an empty key";
387         return false;
388     }
389     for (const auto& path : allowed_key_paths) {
390         if (ReadFileToString(path, &allowed_key_blob)) {
391             if (key_blob_to_validate == allowed_key_blob) return true;
392         }
393     }
394     return false;
395 }
396 
VerifyVBMetaSignature(const VBMetaData & vbmeta,const std::string & expected_public_key_blob,std::string * out_public_key_data)397 VBMetaVerifyResult VerifyVBMetaSignature(const VBMetaData& vbmeta,
398                                          const std::string& expected_public_key_blob,
399                                          std::string* out_public_key_data) {
400     const uint8_t* pk_data;
401     size_t pk_len;
402     ::AvbVBMetaVerifyResult vbmeta_ret;
403 
404     vbmeta_ret = avb_vbmeta_image_verify(vbmeta.data(), vbmeta.size(), &pk_data, &pk_len);
405 
406     if (out_public_key_data != nullptr) {
407         out_public_key_data->clear();
408         if (pk_len > 0) {
409             out_public_key_data->append(reinterpret_cast<const char*>(pk_data), pk_len);
410         }
411     }
412 
413     switch (vbmeta_ret) {
414         case AVB_VBMETA_VERIFY_RESULT_OK:
415             if (pk_data == nullptr || pk_len <= 0) {
416                 LERROR << vbmeta.partition()
417                        << ": Error verifying vbmeta image: failed to get public key";
418                 return VBMetaVerifyResult::kError;
419             }
420             if (!ValidatePublicKeyBlob(pk_data, pk_len, expected_public_key_blob)) {
421                 LERROR << vbmeta.partition() << ": Error verifying vbmeta image: public key used to"
422                        << " sign data does not match key in chain descriptor";
423                 return VBMetaVerifyResult::kErrorVerification;
424             }
425             return VBMetaVerifyResult::kSuccess;
426         case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
427         case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
428         case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
429             LERROR << vbmeta.partition() << ": Error verifying vbmeta image: "
430                    << avb_vbmeta_verify_result_to_string(vbmeta_ret);
431             return VBMetaVerifyResult::kErrorVerification;
432         case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
433             // No way to continue this case.
434             LERROR << vbmeta.partition() << ": Error verifying vbmeta image: invalid vbmeta header";
435             break;
436         case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
437             // No way to continue this case.
438             LERROR << vbmeta.partition()
439                    << ": Error verifying vbmeta image: unsupported AVB version";
440             break;
441         default:
442             LERROR << "Unknown vbmeta image verify return value: " << vbmeta_ret;
443             break;
444     }
445 
446     return VBMetaVerifyResult::kError;
447 }
448 
VerifyVBMetaData(int fd,const std::string & partition_name,const std::string & expected_public_key_blob,std::string * out_public_key_data,VBMetaVerifyResult * out_verify_result)449 std::unique_ptr<VBMetaData> VerifyVBMetaData(int fd, const std::string& partition_name,
450                                              const std::string& expected_public_key_blob,
451                                              std::string* out_public_key_data,
452                                              VBMetaVerifyResult* out_verify_result) {
453     uint64_t vbmeta_offset = 0;
454     uint64_t vbmeta_size = VBMetaData::kMaxVBMetaSize;
455     bool is_vbmeta_partition = StartsWith(partition_name, "vbmeta");
456 
457     if (out_verify_result) {
458         *out_verify_result = VBMetaVerifyResult::kError;
459     }
460 
461     if (!is_vbmeta_partition) {
462         std::unique_ptr<AvbFooter> footer = GetAvbFooter(fd);
463         if (!footer) {
464             return nullptr;
465         }
466         vbmeta_offset = footer->vbmeta_offset;
467         vbmeta_size = footer->vbmeta_size;
468     }
469 
470     if (vbmeta_size > VBMetaData::kMaxVBMetaSize) {
471         LERROR << "VbMeta size in footer exceeds kMaxVBMetaSize";
472         return nullptr;
473     }
474 
475     auto vbmeta = std::make_unique<VBMetaData>(vbmeta_size, partition_name);
476     ssize_t num_read = TEMP_FAILURE_RETRY(pread64(fd, vbmeta->data(), vbmeta_size, vbmeta_offset));
477     // Allows partial read for vbmeta partition, because its vbmeta_size is kMaxVBMetaSize.
478     if (num_read < 0 || (!is_vbmeta_partition && static_cast<uint64_t>(num_read) != vbmeta_size)) {
479         PERROR << partition_name << ": Failed to read vbmeta at offset " << vbmeta_offset
480                << " with size " << vbmeta_size;
481         return nullptr;
482     }
483 
484     auto verify_result =
485             VerifyVBMetaSignature(*vbmeta, expected_public_key_blob, out_public_key_data);
486 
487     if (out_verify_result != nullptr) {
488         *out_verify_result = verify_result;
489     }
490 
491     if (verify_result == VBMetaVerifyResult::kSuccess ||
492         verify_result == VBMetaVerifyResult::kErrorVerification) {
493         return vbmeta;
494     }
495 
496     return nullptr;
497 }
498 
RollbackDetected(const std::string & partition_name ATTRIBUTE_UNUSED,uint64_t rollback_index ATTRIBUTE_UNUSED)499 bool RollbackDetected(const std::string& partition_name ATTRIBUTE_UNUSED,
500                       uint64_t rollback_index ATTRIBUTE_UNUSED) {
501     // TODO(bowgotsai): Support rollback protection.
502     return false;
503 }
504 
GetChainPartitionInfo(const VBMetaData & vbmeta,bool * fatal_error)505 std::vector<ChainInfo> GetChainPartitionInfo(const VBMetaData& vbmeta, bool* fatal_error) {
506     CHECK(fatal_error != nullptr);
507     std::vector<ChainInfo> chain_partitions;
508 
509     size_t num_descriptors;
510     std::unique_ptr<const AvbDescriptor* [], decltype(&avb_free)> descriptors(
511             avb_descriptor_get_all(vbmeta.data(), vbmeta.size(), &num_descriptors), avb_free);
512 
513     if (!descriptors || num_descriptors < 1) {
514         return {};
515     }
516 
517     for (size_t i = 0; i < num_descriptors; i++) {
518         AvbDescriptor desc;
519         if (!avb_descriptor_validate_and_byteswap(descriptors[i], &desc)) {
520             LERROR << "Descriptor[" << i << "] is invalid in vbmeta: " << vbmeta.partition();
521             *fatal_error = true;
522             return {};
523         }
524         if (desc.tag == AVB_DESCRIPTOR_TAG_CHAIN_PARTITION) {
525             AvbChainPartitionDescriptor chain_desc;
526             if (!avb_chain_partition_descriptor_validate_and_byteswap(
527                         (AvbChainPartitionDescriptor*)descriptors[i], &chain_desc)) {
528                 LERROR << "Chain descriptor[" << i
529                        << "] is invalid in vbmeta: " << vbmeta.partition();
530                 *fatal_error = true;
531                 return {};
532             }
533             const char* chain_partition_name =
534                     ((const char*)descriptors[i]) + sizeof(AvbChainPartitionDescriptor);
535             const char* chain_public_key_blob =
536                     chain_partition_name + chain_desc.partition_name_len;
537             chain_partitions.emplace_back(
538                     std::string(chain_partition_name, chain_desc.partition_name_len),
539                     std::string(chain_public_key_blob, chain_desc.public_key_len));
540         }
541     }
542 
543     return chain_partitions;
544 }
545 
546 // Loads the vbmeta from a given path.
LoadAndVerifyVbmetaByPath(const std::string & image_path,const std::string & partition_name,const std::string & expected_public_key_blob,bool allow_verification_error,bool rollback_protection,bool is_chained_vbmeta,std::string * out_public_key_data,bool * out_verification_disabled,VBMetaVerifyResult * out_verify_result)547 std::unique_ptr<VBMetaData> LoadAndVerifyVbmetaByPath(
548         const std::string& image_path, const std::string& partition_name,
549         const std::string& expected_public_key_blob, bool allow_verification_error,
550         bool rollback_protection, bool is_chained_vbmeta, std::string* out_public_key_data,
551         bool* out_verification_disabled, VBMetaVerifyResult* out_verify_result) {
552     if (out_verify_result) {
553         *out_verify_result = VBMetaVerifyResult::kError;
554     }
555 
556     // Ensures the device path (might be a symlink created by init) is ready to access.
557     if (!WaitForFile(image_path, 1s)) {
558         PERROR << "No such path: " << image_path;
559         return nullptr;
560     }
561 
562     unique_fd fd(TEMP_FAILURE_RETRY(open(image_path.c_str(), O_RDONLY | O_CLOEXEC)));
563     if (fd < 0) {
564         PERROR << "Failed to open: " << image_path;
565         return nullptr;
566     }
567 
568     VBMetaVerifyResult verify_result;
569     std::unique_ptr<VBMetaData> vbmeta = VerifyVBMetaData(
570             fd, partition_name, expected_public_key_blob, out_public_key_data, &verify_result);
571     if (!vbmeta) {
572         LERROR << partition_name << ": Failed to load vbmeta, result: " << verify_result;
573         return nullptr;
574     }
575     vbmeta->set_vbmeta_path(image_path);
576 
577     if (!allow_verification_error && verify_result == VBMetaVerifyResult::kErrorVerification) {
578         LERROR << partition_name << ": allow verification error is not allowed";
579         return nullptr;
580     }
581 
582     std::unique_ptr<AvbVBMetaImageHeader> vbmeta_header =
583             vbmeta->GetVBMetaHeader(true /* update_vbmeta_size */);
584     if (!vbmeta_header) {
585         LERROR << partition_name << ": Failed to get vbmeta header";
586         return nullptr;
587     }
588 
589     if (rollback_protection && RollbackDetected(partition_name, vbmeta_header->rollback_index)) {
590         return nullptr;
591     }
592 
593     // vbmeta flags can only be set by the top-level vbmeta image.
594     if (is_chained_vbmeta && vbmeta_header->flags != 0) {
595         LERROR << partition_name << ": chained vbmeta image has non-zero flags";
596         return nullptr;
597     }
598 
599     // Checks if verification has been disabled by setting a bit in the image.
600     if (out_verification_disabled) {
601         if (vbmeta_header->flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
602             LWARNING << "VERIFICATION_DISABLED bit is set for partition: " << partition_name;
603             *out_verification_disabled = true;
604         } else {
605             *out_verification_disabled = false;
606         }
607     }
608 
609     if (out_verify_result) {
610         *out_verify_result = verify_result;
611     }
612 
613     return vbmeta;
614 }
615 
LoadAndVerifyVbmetaByPartition(const std::string & partition_name,const std::string & ab_suffix,const std::string & ab_other_suffix,const std::string & expected_public_key_blob,bool allow_verification_error,bool load_chained_vbmeta,bool rollback_protection,std::function<std::string (const std::string &)> device_path_constructor,bool is_chained_vbmeta,std::vector<VBMetaData> * out_vbmeta_images)616 VBMetaVerifyResult LoadAndVerifyVbmetaByPartition(
617     const std::string& partition_name, const std::string& ab_suffix,
618     const std::string& ab_other_suffix, const std::string& expected_public_key_blob,
619     bool allow_verification_error, bool load_chained_vbmeta, bool rollback_protection,
620     std::function<std::string(const std::string&)> device_path_constructor, bool is_chained_vbmeta,
621     std::vector<VBMetaData>* out_vbmeta_images) {
622     auto image_path = device_path_constructor(
623         AvbPartitionToDevicePatition(partition_name, ab_suffix, ab_other_suffix));
624 
625     bool verification_disabled = false;
626     VBMetaVerifyResult verify_result;
627     auto vbmeta = LoadAndVerifyVbmetaByPath(image_path, partition_name, expected_public_key_blob,
628                                             allow_verification_error, rollback_protection,
629                                             is_chained_vbmeta, nullptr /* out_public_key_data */,
630                                             &verification_disabled, &verify_result);
631 
632     if (!vbmeta) {
633         return VBMetaVerifyResult::kError;
634     }
635     if (out_vbmeta_images) {
636         out_vbmeta_images->emplace_back(std::move(*vbmeta));
637     }
638 
639     // Only loads chained vbmeta if AVB verification is NOT disabled.
640     if (!verification_disabled && load_chained_vbmeta) {
641         bool fatal_error = false;
642         auto chain_partitions = GetChainPartitionInfo(*out_vbmeta_images->rbegin(), &fatal_error);
643         if (fatal_error) {
644             return VBMetaVerifyResult::kError;
645         }
646         for (auto& chain : chain_partitions) {
647             auto sub_ret = LoadAndVerifyVbmetaByPartition(
648                 chain.partition_name, ab_suffix, ab_other_suffix, chain.public_key_blob,
649                 allow_verification_error, load_chained_vbmeta, rollback_protection,
650                 device_path_constructor, true, /* is_chained_vbmeta */
651                 out_vbmeta_images);
652             if (sub_ret != VBMetaVerifyResult::kSuccess) {
653                 verify_result = sub_ret;  // might be 'ERROR' or 'ERROR VERIFICATION'.
654                 if (verify_result == VBMetaVerifyResult::kError) {
655                     return verify_result;  // stop here if we got an 'ERROR'.
656                 }
657             }
658         }
659     }
660 
661     return verify_result;
662 }
663 
664 }  // namespace fs_mgr
665 }  // namespace android
666