1 /*
2 * Copyright (C) 2020 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 "VolumeEncryption.h"
18
19 #include <string>
20
21 #include <android-base/logging.h>
22 #include <android-base/properties.h>
23
24 #include "KeyBuffer.h"
25 #include "KeyUtil.h"
26 #include "MetadataCrypt.h"
27 #include "cryptfs.h"
28
29 namespace android {
30 namespace vold {
31
32 enum class VolumeMethod { kFailed, kCrypt, kDefaultKey };
33
lookup_volume_method()34 static VolumeMethod lookup_volume_method() {
35 constexpr uint64_t pre_gki_level = 29;
36 auto first_api_level =
37 android::base::GetUintProperty<uint64_t>("ro.product.first_api_level", 0);
38 auto method = android::base::GetProperty("ro.crypto.volume.metadata.method", "default");
39 if (method == "default") {
40 return first_api_level > pre_gki_level ? VolumeMethod::kDefaultKey : VolumeMethod::kCrypt;
41 } else if (method == "dm-default-key") {
42 return VolumeMethod::kDefaultKey;
43 } else if (method == "dm-crypt") {
44 if (first_api_level > pre_gki_level) {
45 LOG(ERROR) << "volume encryption method dm-crypt cannot be used, "
46 "ro.product.first_api_level = "
47 << first_api_level;
48 return VolumeMethod::kFailed;
49 }
50 return VolumeMethod::kCrypt;
51 } else {
52 LOG(ERROR) << "Unknown volume encryption method: " << method;
53 return VolumeMethod::kFailed;
54 }
55 }
56
volume_method()57 static VolumeMethod volume_method() {
58 static VolumeMethod method = lookup_volume_method();
59 return method;
60 }
61
generate_volume_key(android::vold::KeyBuffer * key)62 bool generate_volume_key(android::vold::KeyBuffer* key) {
63 KeyGeneration gen;
64 switch (volume_method()) {
65 case VolumeMethod::kFailed:
66 LOG(ERROR) << "Volume encryption setup failed";
67 return false;
68 case VolumeMethod::kCrypt:
69 gen = cryptfs_get_keygen();
70 break;
71 case VolumeMethod::kDefaultKey:
72 if (!defaultkey_volume_keygen(&gen)) return false;
73 break;
74 }
75 if (!generateStorageKey(gen, key)) return false;
76 return true;
77 }
78
setup_ext_volume(const std::string & label,const std::string & blk_device,const android::vold::KeyBuffer & key,std::string * out_crypto_blkdev)79 bool setup_ext_volume(const std::string& label, const std::string& blk_device,
80 const android::vold::KeyBuffer& key, std::string* out_crypto_blkdev) {
81 switch (volume_method()) {
82 case VolumeMethod::kFailed:
83 LOG(ERROR) << "Volume encryption setup failed";
84 return false;
85 case VolumeMethod::kCrypt:
86 return cryptfs_setup_ext_volume(label.c_str(), blk_device.c_str(), key,
87 out_crypto_blkdev) == 0;
88 case VolumeMethod::kDefaultKey:
89 return defaultkey_setup_ext_volume(label, blk_device, key, out_crypto_blkdev);
90 }
91 }
92
93 } // namespace vold
94 } // namespace android
95