1 /*
2  * Copyright (C) 2016 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 "fs_avb/fs_avb.h"
18 
19 #include <fcntl.h>
20 #include <libgen.h>
21 #include <string.h>
22 #include <sys/ioctl.h>
23 #include <sys/types.h>
24 
25 #include <algorithm>
26 #include <sstream>
27 #include <string>
28 #include <vector>
29 
30 #include <android-base/file.h>
31 #include <android-base/parseint.h>
32 #include <android-base/stringprintf.h>
33 #include <android-base/strings.h>
34 #include <libavb/libavb.h>
35 #include <libdm/dm.h>
36 #include <libgsi/libgsi.h>
37 
38 #include "avb_ops.h"
39 #include "avb_util.h"
40 #include "fs_avb/fs_avb_util.h"
41 #include "sha.h"
42 #include "util.h"
43 
44 using android::base::Basename;
45 using android::base::ParseUint;
46 using android::base::ReadFileToString;
47 using android::base::Split;
48 using android::base::StringPrintf;
49 
50 namespace android {
51 namespace fs_mgr {
52 
53 template <typename Hasher>
VerifyVbmetaDigest(const std::vector<VBMetaData> & vbmeta_images,const uint8_t * expected_digest)54 std::pair<size_t, bool> VerifyVbmetaDigest(const std::vector<VBMetaData>& vbmeta_images,
55                                            const uint8_t* expected_digest) {
56     size_t total_size = 0;
57     Hasher hasher;
58     for (const auto& vbmeta : vbmeta_images) {
59         hasher.update(vbmeta.data(), vbmeta.size());
60         total_size += vbmeta.size();
61     }
62 
63     bool matched = (memcmp(hasher.finalize(), expected_digest, Hasher::DIGEST_SIZE) == 0);
64 
65     return std::make_pair(total_size, matched);
66 }
67 
68 template <typename Hasher>
CalculateVbmetaDigest(const std::vector<VBMetaData> & vbmeta_images)69 std::pair<std::string, size_t> CalculateVbmetaDigest(const std::vector<VBMetaData>& vbmeta_images) {
70     std::string digest;
71     size_t total_size = 0;
72 
73     Hasher hasher;
74     for (const auto& vbmeta : vbmeta_images) {
75         hasher.update(vbmeta.data(), vbmeta.size());
76         total_size += vbmeta.size();
77     }
78 
79     // Converts digest bytes to a hex string.
80     digest = BytesToHex(hasher.finalize(), Hasher::DIGEST_SIZE);
81     return std::make_pair(digest, total_size);
82 }
83 
84 // class AvbVerifier
85 // -----------------
86 // Reads the following values from kernel cmdline and provides the
87 // VerifyVbmetaImages() to verify AvbSlotVerifyData.
88 //   - androidboot.vbmeta.hash_alg
89 //   - androidboot.vbmeta.size
90 //   - androidboot.vbmeta.digest
91 class AvbVerifier {
92   public:
93     // The factory method to return a unique_ptr<AvbVerifier>
94     static std::unique_ptr<AvbVerifier> Create();
95     bool VerifyVbmetaImages(const std::vector<VBMetaData>& vbmeta_images);
96 
97   protected:
98     AvbVerifier() = default;
99 
100   private:
101     HashAlgorithm hash_alg_;
102     uint8_t digest_[SHA512_DIGEST_LENGTH];
103     size_t vbmeta_size_;
104 };
105 
Create()106 std::unique_ptr<AvbVerifier> AvbVerifier::Create() {
107     std::unique_ptr<AvbVerifier> avb_verifier(new AvbVerifier());
108     if (!avb_verifier) {
109         LERROR << "Failed to create unique_ptr<AvbVerifier>";
110         return nullptr;
111     }
112 
113     std::string value;
114     if (!fs_mgr_get_boot_config("vbmeta.size", &value) ||
115         !ParseUint(value.c_str(), &avb_verifier->vbmeta_size_)) {
116         LERROR << "Invalid hash size: " << value.c_str();
117         return nullptr;
118     }
119 
120     // Reads hash algorithm.
121     size_t expected_digest_size = 0;
122     std::string hash_alg;
123     fs_mgr_get_boot_config("vbmeta.hash_alg", &hash_alg);
124     if (hash_alg == "sha256") {
125         expected_digest_size = SHA256_DIGEST_LENGTH * 2;
126         avb_verifier->hash_alg_ = HashAlgorithm::kSHA256;
127     } else if (hash_alg == "sha512") {
128         expected_digest_size = SHA512_DIGEST_LENGTH * 2;
129         avb_verifier->hash_alg_ = HashAlgorithm::kSHA512;
130     } else {
131         LERROR << "Unknown hash algorithm: " << hash_alg.c_str();
132         return nullptr;
133     }
134 
135     // Reads digest.
136     std::string digest;
137     fs_mgr_get_boot_config("vbmeta.digest", &digest);
138     if (digest.size() != expected_digest_size) {
139         LERROR << "Unexpected digest size: " << digest.size()
140                << " (expected: " << expected_digest_size << ")";
141         return nullptr;
142     }
143 
144     if (!HexToBytes(avb_verifier->digest_, sizeof(avb_verifier->digest_), digest)) {
145         LERROR << "Hash digest contains non-hexidecimal character: " << digest.c_str();
146         return nullptr;
147     }
148 
149     return avb_verifier;
150 }
151 
VerifyVbmetaImages(const std::vector<VBMetaData> & vbmeta_images)152 bool AvbVerifier::VerifyVbmetaImages(const std::vector<VBMetaData>& vbmeta_images) {
153     if (vbmeta_images.empty()) {
154         LERROR << "No vbmeta images";
155         return false;
156     }
157 
158     size_t total_size = 0;
159     bool digest_matched = false;
160 
161     if (hash_alg_ == HashAlgorithm::kSHA256) {
162         std::tie(total_size, digest_matched) =
163                 VerifyVbmetaDigest<SHA256Hasher>(vbmeta_images, digest_);
164     } else if (hash_alg_ == HashAlgorithm::kSHA512) {
165         std::tie(total_size, digest_matched) =
166                 VerifyVbmetaDigest<SHA512Hasher>(vbmeta_images, digest_);
167     }
168 
169     if (total_size != vbmeta_size_) {
170         LERROR << "total vbmeta size mismatch: " << total_size << " (expected: " << vbmeta_size_
171                << ")";
172         return false;
173     }
174 
175     if (!digest_matched) {
176         LERROR << "vbmeta digest mismatch";
177         return false;
178     }
179 
180     return true;
181 }
182 
183 // class AvbHandle
184 // ---------------
LoadAndVerifyVbmeta(const std::string & partition_name,const std::string & ab_suffix,const std::string & ab_other_suffix,const std::string & expected_public_key_path,const HashAlgorithm & hash_algorithm,bool allow_verification_error,bool load_chained_vbmeta,bool rollback_protection,std::function<std::string (const std::string &)> custom_device_path)185 AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(
186         const std::string& partition_name, const std::string& ab_suffix,
187         const std::string& ab_other_suffix, const std::string& expected_public_key_path,
188         const HashAlgorithm& hash_algorithm, bool allow_verification_error,
189         bool load_chained_vbmeta, bool rollback_protection,
190         std::function<std::string(const std::string&)> custom_device_path) {
191     AvbUniquePtr avb_handle(new AvbHandle());
192     if (!avb_handle) {
193         LERROR << "Failed to allocate AvbHandle";
194         return nullptr;
195     }
196 
197     std::string expected_key_blob;
198     if (!expected_public_key_path.empty()) {
199         if (access(expected_public_key_path.c_str(), F_OK) != 0) {
200             LERROR << "Expected public key path doesn't exist: " << expected_public_key_path;
201             return nullptr;
202         } else if (!ReadFileToString(expected_public_key_path, &expected_key_blob)) {
203             LERROR << "Failed to load: " << expected_public_key_path;
204             return nullptr;
205         }
206     }
207 
208     auto android_by_name_symlink = [](const std::string& partition_name_with_ab) {
209         return "/dev/block/by-name/" + partition_name_with_ab;
210     };
211 
212     auto device_path = custom_device_path ? custom_device_path : android_by_name_symlink;
213 
214     auto verify_result = LoadAndVerifyVbmetaByPartition(
215         partition_name, ab_suffix, ab_other_suffix, expected_key_blob, allow_verification_error,
216         load_chained_vbmeta, rollback_protection, device_path, false,
217         /* is_chained_vbmeta */ &avb_handle->vbmeta_images_);
218     switch (verify_result) {
219         case VBMetaVerifyResult::kSuccess:
220             avb_handle->status_ = AvbHandleStatus::kSuccess;
221             break;
222         case VBMetaVerifyResult::kErrorVerification:
223             avb_handle->status_ = AvbHandleStatus::kVerificationError;
224             break;
225         default:
226             LERROR << "LoadAndVerifyVbmetaByPartition failed, result: " << verify_result;
227             return nullptr;
228     }
229 
230     // Validity check here because we have to use vbmeta_images_[0] below.
231     if (avb_handle->vbmeta_images_.size() < 1) {
232         LERROR << "LoadAndVerifyVbmetaByPartition failed, no vbmeta loaded";
233         return nullptr;
234     }
235 
236     // Sets the MAJOR.MINOR for init to set it into "ro.boot.avb_version".
237     avb_handle->avb_version_ = StringPrintf("%d.%d", AVB_VERSION_MAJOR, AVB_VERSION_MINOR);
238 
239     // Checks any disabled flag is set.
240     std::unique_ptr<AvbVBMetaImageHeader> vbmeta_header =
241             avb_handle->vbmeta_images_[0].GetVBMetaHeader();
242     bool verification_disabled = ((AvbVBMetaImageFlags)vbmeta_header->flags &
243                                   AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
244     bool hashtree_disabled =
245             ((AvbVBMetaImageFlags)vbmeta_header->flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
246     if (verification_disabled) {
247         avb_handle->status_ = AvbHandleStatus::kVerificationDisabled;
248     } else if (hashtree_disabled) {
249         avb_handle->status_ = AvbHandleStatus::kHashtreeDisabled;
250     }
251 
252     // Calculates the summary info for all vbmeta_images_;
253     std::string digest;
254     size_t total_size;
255     if (hash_algorithm == HashAlgorithm::kSHA256) {
256         std::tie(digest, total_size) =
257                 CalculateVbmetaDigest<SHA256Hasher>(avb_handle->vbmeta_images_);
258     } else if (hash_algorithm == HashAlgorithm::kSHA512) {
259         std::tie(digest, total_size) =
260                 CalculateVbmetaDigest<SHA512Hasher>(avb_handle->vbmeta_images_);
261     } else {
262         LERROR << "Invalid hash algorithm";
263         return nullptr;
264     }
265     avb_handle->vbmeta_info_ = VBMetaInfo(digest, hash_algorithm, total_size);
266 
267     LINFO << "Returning avb_handle with status: " << avb_handle->status_;
268     return avb_handle;
269 }
270 
IsAvbPermissive()271 static bool IsAvbPermissive() {
272     if (IsDeviceUnlocked()) {
273         // Manually putting a file under metadata partition can enforce AVB verification.
274         if (!access(DSU_METADATA_PREFIX "avb_enforce", F_OK)) {
275             LINFO << "Enforcing AVB verification when the device is unlocked";
276             return false;
277         }
278         return true;
279     }
280     return false;
281 }
282 
LoadAndVerifyVbmeta(const FstabEntry & fstab_entry,const std::vector<std::string> & preload_avb_key_blobs)283 AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry,
284                                             const std::vector<std::string>& preload_avb_key_blobs) {
285     // At least one of the following should be provided for public key matching.
286     if (preload_avb_key_blobs.empty() && fstab_entry.avb_keys.empty()) {
287         LERROR << "avb_keys=/path/to/key(s) is missing for " << fstab_entry.mount_point;
288         return nullptr;
289     }
290 
291     // Binds allow_verification_error and rollback_protection to device unlock state.
292     bool allow_verification_error = IsAvbPermissive();
293     bool rollback_protection = !allow_verification_error;
294 
295     std::string public_key_data;
296     bool verification_disabled = false;
297     VBMetaVerifyResult verify_result = VBMetaVerifyResult::kError;
298     std::unique_ptr<VBMetaData> vbmeta = LoadAndVerifyVbmetaByPath(
299             fstab_entry.blk_device, "" /* partition_name, no need for a standalone path */,
300             "" /* expected_public_key_blob, */, allow_verification_error, rollback_protection,
301             false /* not is_chained_vbmeta */, &public_key_data, &verification_disabled,
302             &verify_result);
303 
304     if (!vbmeta) {
305         LERROR << "Failed to load vbmeta: " << fstab_entry.blk_device;
306         return nullptr;
307     }
308 
309     AvbUniquePtr avb_handle(new AvbHandle());
310     if (!avb_handle) {
311         LERROR << "Failed to allocate AvbHandle";
312         return nullptr;
313     }
314     avb_handle->vbmeta_images_.emplace_back(std::move(*vbmeta));
315 
316     switch (verify_result) {
317         case VBMetaVerifyResult::kSuccess:
318             avb_handle->status_ = AvbHandleStatus::kSuccess;
319             break;
320         case VBMetaVerifyResult::kErrorVerification:
321             avb_handle->status_ = AvbHandleStatus::kVerificationError;
322             break;
323         default:
324             LERROR << "LoadAndVerifyVbmetaByPath failed, result: " << verify_result;
325             return nullptr;
326     }
327 
328     bool public_key_match = false;
329     // Performs key matching for preload_avb_key_blobs first, if it is present.
330     if (!public_key_data.empty() && !preload_avb_key_blobs.empty()) {
331         if (std::find(preload_avb_key_blobs.begin(), preload_avb_key_blobs.end(),
332                       public_key_data) != preload_avb_key_blobs.end()) {
333             public_key_match = true;
334         }
335     }
336     // Performs key matching for fstab_entry.avb_keys if necessary.
337     // Note that it is intentional to match both preload_avb_key_blobs and fstab_entry.avb_keys.
338     // Some keys might only be availble before init chroots into /system, e.g., /avb/key1
339     // in the first-stage ramdisk, while other keys might only be available after the chroot,
340     // e.g., /system/etc/avb/key2.
341     if (!public_key_data.empty() && !public_key_match) {
342         // fstab_entry.avb_keys might be either a directory containing multiple keys,
343         // or a string indicating multiple keys separated by ':'.
344         std::vector<std::string> allowed_avb_keys;
345         auto list_avb_keys_in_dir = ListFiles(fstab_entry.avb_keys);
346         if (list_avb_keys_in_dir.ok()) {
347             std::sort(list_avb_keys_in_dir->begin(), list_avb_keys_in_dir->end());
348             allowed_avb_keys = *list_avb_keys_in_dir;
349         } else {
350             allowed_avb_keys = Split(fstab_entry.avb_keys, ":");
351         }
352         if (ValidatePublicKeyBlob(public_key_data, allowed_avb_keys)) {
353             public_key_match = true;
354         }
355     }
356 
357     if (!public_key_match) {
358         avb_handle->status_ = AvbHandleStatus::kVerificationError;
359         LWARNING << "Found unknown public key used to sign " << fstab_entry.mount_point;
360         if (!allow_verification_error) {
361             LERROR << "Unknown public key is not allowed";
362             return nullptr;
363         }
364     }
365 
366     if (verification_disabled) {
367         LINFO << "AVB verification disabled on: " << fstab_entry.mount_point;
368         avb_handle->status_ = AvbHandleStatus::kVerificationDisabled;
369     }
370 
371     LINFO << "Returning avb_handle for '" << fstab_entry.mount_point
372           << "' with status: " << avb_handle->status_;
373     return avb_handle;
374 }
375 
LoadAndVerifyVbmeta()376 AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta() {
377     // Loads inline vbmeta images, starting from /vbmeta.
378     return LoadAndVerifyVbmeta("vbmeta", fs_mgr_get_slot_suffix(), fs_mgr_get_other_slot_suffix(),
379                                {} /* expected_public_key, already checked by bootloader */,
380                                HashAlgorithm::kSHA256,
381                                IsAvbPermissive(), /* allow_verification_error */
382                                true,              /* load_chained_vbmeta */
383                                false, /* rollback_protection, already checked by bootloader */
384                                nullptr /* custom_device_path */);
385 }
386 
387 // TODO(b/128807537): removes this function.
Open()388 AvbUniquePtr AvbHandle::Open() {
389     bool allow_verification_error = IsAvbPermissive();
390 
391     AvbUniquePtr avb_handle(new AvbHandle());
392     if (!avb_handle) {
393         LERROR << "Failed to allocate AvbHandle";
394         return nullptr;
395     }
396 
397     FsManagerAvbOps avb_ops;
398     AvbSlotVerifyFlags flags = allow_verification_error
399                                        ? AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
400                                        : AVB_SLOT_VERIFY_FLAGS_NONE;
401     AvbSlotVerifyResult verify_result =
402             avb_ops.AvbSlotVerify(fs_mgr_get_slot_suffix(), flags, &avb_handle->vbmeta_images_);
403 
404     // Only allow the following verify results:
405     //   - AVB_SLOT_VERIFY_RESULT_OK.
406     //   - AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION (UNLOCKED only).
407     //     Might occur in either the top-level vbmeta or a chained vbmeta.
408     //   - AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED (UNLOCKED only).
409     //     Could only occur in a chained vbmeta. Because we have *no-op* operations in
410     //     FsManagerAvbOps such that avb_ops->validate_vbmeta_public_key() used to validate
411     //     the public key of the top-level vbmeta always pass in userspace here.
412     //
413     // The following verify result won't happen, because the *no-op* operation
414     // avb_ops->read_rollback_index() always returns the minimum value zero. So rollbacked
415     // vbmeta images, which should be caught in the bootloader stage, won't be detected here.
416     //   - AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX
417     switch (verify_result) {
418         case AVB_SLOT_VERIFY_RESULT_OK:
419             avb_handle->status_ = AvbHandleStatus::kSuccess;
420             break;
421         case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
422         case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
423             if (!allow_verification_error) {
424                 LERROR << "ERROR_VERIFICATION / PUBLIC_KEY_REJECTED isn't allowed ";
425                 return nullptr;
426             }
427             avb_handle->status_ = AvbHandleStatus::kVerificationError;
428             break;
429         default:
430             LERROR << "avb_slot_verify failed, result: " << verify_result;
431             return nullptr;
432     }
433 
434     // Sets the MAJOR.MINOR for init to set it into "ro.boot.avb_version".
435     avb_handle->avb_version_ = StringPrintf("%d.%d", AVB_VERSION_MAJOR, AVB_VERSION_MINOR);
436 
437     // Verifies vbmeta structs against the digest passed from bootloader in kernel cmdline.
438     std::unique_ptr<AvbVerifier> avb_verifier = AvbVerifier::Create();
439     if (!avb_verifier || !avb_verifier->VerifyVbmetaImages(avb_handle->vbmeta_images_)) {
440         LERROR << "Failed to verify vbmeta digest";
441         if (!allow_verification_error) {
442             LERROR << "vbmeta digest error isn't allowed ";
443             return nullptr;
444         }
445     }
446 
447     // Checks whether FLAGS_VERIFICATION_DISABLED is set:
448     //   - Only the top-level vbmeta struct is read.
449     //   - vbmeta struct in other partitions are NOT processed, including AVB HASH descriptor(s)
450     //     and AVB HASHTREE descriptor(s).
451     AvbVBMetaImageHeader vbmeta_header;
452     avb_vbmeta_image_header_to_host_byte_order(
453             (AvbVBMetaImageHeader*)avb_handle->vbmeta_images_[0].data(), &vbmeta_header);
454     bool verification_disabled = ((AvbVBMetaImageFlags)vbmeta_header.flags &
455                                   AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
456 
457     // Checks whether FLAGS_HASHTREE_DISABLED is set.
458     //   - vbmeta struct in all partitions are still processed, just disable
459     //     dm-verity in the user space.
460     bool hashtree_disabled =
461             ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
462 
463     if (verification_disabled) {
464         avb_handle->status_ = AvbHandleStatus::kVerificationDisabled;
465     } else if (hashtree_disabled) {
466         avb_handle->status_ = AvbHandleStatus::kHashtreeDisabled;
467     }
468 
469     LINFO << "Returning avb_handle with status: " << avb_handle->status_;
470     return avb_handle;
471 }
472 
SetUpStandaloneAvbHashtree(FstabEntry * fstab_entry,bool wait_for_verity_dev)473 AvbHashtreeResult AvbHandle::SetUpStandaloneAvbHashtree(FstabEntry* fstab_entry,
474                                                         bool wait_for_verity_dev) {
475     auto avb_handle = LoadAndVerifyVbmeta(*fstab_entry);
476     if (!avb_handle) {
477         return AvbHashtreeResult::kFail;
478     }
479 
480     return avb_handle->SetUpAvbHashtree(fstab_entry, wait_for_verity_dev);
481 }
482 
SetUpAvbHashtree(FstabEntry * fstab_entry,bool wait_for_verity_dev)483 AvbHashtreeResult AvbHandle::SetUpAvbHashtree(FstabEntry* fstab_entry, bool wait_for_verity_dev) {
484     if (!fstab_entry || status_ == AvbHandleStatus::kUninitialized || vbmeta_images_.size() < 1) {
485         return AvbHashtreeResult::kFail;
486     }
487 
488     if (status_ == AvbHandleStatus::kHashtreeDisabled ||
489         status_ == AvbHandleStatus::kVerificationDisabled) {
490         LINFO << "AVB HASHTREE disabled on: " << fstab_entry->mount_point;
491         return AvbHashtreeResult::kDisabled;
492     }
493 
494     if (!LoadAvbHashtreeToEnableVerity(fstab_entry, wait_for_verity_dev, vbmeta_images_,
495                                        fs_mgr_get_slot_suffix(), fs_mgr_get_other_slot_suffix())) {
496         return AvbHashtreeResult::kFail;
497     }
498 
499     return AvbHashtreeResult::kSuccess;
500 }
501 
TearDownAvbHashtree(FstabEntry * fstab_entry,bool wait)502 bool AvbHandle::TearDownAvbHashtree(FstabEntry* fstab_entry, bool wait) {
503     if (!fstab_entry) {
504         return false;
505     }
506 
507     const std::string device_name(GetVerityDeviceName(*fstab_entry));
508 
509     // TODO: remove duplicated code with UnmapDevice()
510     android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance();
511     std::string path;
512     if (wait) {
513         dm.GetDmDevicePathByName(device_name, &path);
514     }
515     if (!dm.DeleteDevice(device_name)) {
516         return false;
517     }
518     if (!path.empty() && !WaitForFile(path, 1000ms, FileWaitMode::DoesNotExist)) {
519         return false;
520     }
521 
522     return true;
523 }
524 
GetSecurityPatchLevel(const FstabEntry & fstab_entry) const525 std::string AvbHandle::GetSecurityPatchLevel(const FstabEntry& fstab_entry) const {
526     if (vbmeta_images_.size() < 1) {
527         return "";
528     }
529     std::string avb_partition_name = DeriveAvbPartitionName(fstab_entry, fs_mgr_get_slot_suffix(),
530                                                             fs_mgr_get_other_slot_suffix());
531     auto avb_prop_name = "com.android.build." + avb_partition_name + ".security_patch";
532     return GetAvbPropertyDescriptor(avb_prop_name, vbmeta_images_);
533 }
534 
IsDeviceUnlocked()535 bool AvbHandle::IsDeviceUnlocked() {
536     return android::fs_mgr::IsDeviceUnlocked();
537 }
538 
539 }  // namespace fs_mgr
540 }  // namespace android
541