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