blob: e6a55a9ccc6df9beac6e78b66eaa15f22c903e4b [file] [log] [blame]
Paul Crowley886e5722020-02-07 12:51:56 -08001/*
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
29namespace android {
30namespace vold {
31
32enum class VolumeMethod { kFailed, kCrypt, kDefaultKey };
33
34static VolumeMethod lookup_volume_method() {
Paul Crowley886e5722020-02-07 12:51:56 -080035 auto first_api_level =
36 android::base::GetUintProperty<uint64_t>("ro.product.first_api_level", 0);
37 auto method = android::base::GetProperty("ro.crypto.volume.metadata.method", "default");
38 if (method == "default") {
Eric Biggers72d07132020-08-10 10:55:56 -070039 return first_api_level > __ANDROID_API_Q__ ? VolumeMethod::kDefaultKey
40 : VolumeMethod::kCrypt;
Paul Crowley886e5722020-02-07 12:51:56 -080041 } else if (method == "dm-default-key") {
42 return VolumeMethod::kDefaultKey;
43 } else if (method == "dm-crypt") {
Eric Biggers72d07132020-08-10 10:55:56 -070044 if (first_api_level > __ANDROID_API_Q__) {
Paul Crowley886e5722020-02-07 12:51:56 -080045 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
57static VolumeMethod volume_method() {
58 static VolumeMethod method = lookup_volume_method();
59 return method;
60}
61
62bool 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
79bool 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