Ext4Crypt.cpp revision 1ef255816c50e462acc23383a9ff747c5f55c4ff
1d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey/*
2d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * Copyright (C) 2015 The Android Open Source Project
3d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey *
4d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * you may not use this file except in compliance with the License.
6d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * You may obtain a copy of the License at
7d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey *
8d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey *
10d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
11d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * See the License for the specific language governing permissions and
14d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * limitations under the License.
15d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey */
16d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
17731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include "Ext4Crypt.h"
18731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
191ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley#include "KeyStorage.h"
20d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey#include "Utils.h"
21d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
22fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence#include <iomanip>
23731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include <map>
24fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence#include <string>
25fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence#include <sstream>
26731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
27731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include <errno.h>
2895376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley#include <dirent.h>
29731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include <sys/mount.h>
3095376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley#include <sys/types.h>
3195376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley#include <sys/stat.h>
3295376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley#include <fcntl.h>
33731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include <cutils/properties.h>
34fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence#include <openssl/sha.h>
357a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#include <selinux/android.h>
36731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
37480fcd2750c1d30f3397d1f3152519a11f60990bPaul Crowley#include <private/android_filesystem_config.h>
38480fcd2750c1d30f3397d1f3152519a11f60990bPaul Crowley
39731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include "unencrypted_properties.h"
40731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include "key_control.h"
41731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include "cryptfs.h"
4295376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley#include "ext4_crypt_init_extensions.h"
43731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
44731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#define LOG_TAG "Ext4Crypt"
45d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
467a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#define EMULATED_USES_SELINUX 0
477a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey
48d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey#include <cutils/fs.h>
49d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey#include <cutils/log.h>
50731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include <cutils/klog.h>
51d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
527e128fbe212c64492afa98bfd6d7fab6f1956831Elliott Hughes#include <android-base/file.h>
536bf0547ccce72233bd465178b919fa7f15e48b45Elliott Hughes#include <android-base/logging.h>
547e128fbe212c64492afa98bfd6d7fab6f1956831Elliott Hughes#include <android-base/stringprintf.h>
55731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
56d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkeyusing android::base::StringPrintf;
57d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
58fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkeystatic bool e4crypt_is_native() {
59fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey    char value[PROPERTY_VALUE_MAX];
60fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey    property_get("ro.crypto.type", value, "none");
61fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey    return !strcmp(value, "file");
62fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey}
63fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey
64fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkeystatic bool e4crypt_is_emulated() {
65fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey    return property_get_bool("persist.sys.emulate_fbe", false);
66fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey}
67c79fb89a10ea9bc3b0f1f9c7caa809a705989479Jeff Sharkey
68731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrencenamespace {
69731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    // Key length in bits
70731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    const int key_length = 128;
71fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    static_assert(key_length % 8 == 0,
72fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence                  "Key length must be multiple of 8 bits");
73731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
7486c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence    // How long do we store passwords for?
7586c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence    const int password_max_age_seconds = 60;
7686c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence
77285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    const std::string user_key_dir = std::string() + DATA_MNT_POINT + "/misc/vold/user_keys";
78285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley
79731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    // How is device encrypted
80731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    struct keys {
81731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        std::string master_key;
82731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        std::string password;
8386c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence        time_t expiry_time;
84731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    };
85731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    std::map<std::string, keys> s_key_store;
86395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova    // Maps the key paths of ephemeral keys to the keys
87395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova    std::map<std::string, std::string> s_ephemeral_user_keys;
88285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    // Map user serial numbers to key references
89285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    std::map<int, std::string> s_key_raw_refs;
90731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
91285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    // ext4enc:TODO get this const from somewhere good
92fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    const int EXT4_KEY_DESCRIPTOR_SIZE = 8;
93fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence
94731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    // ext4enc:TODO Include structure from somewhere sensible
95731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    // MUST be in sync with ext4_crypto.c in kernel
96fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    const int EXT4_MAX_KEY_SIZE = 64;
97fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    const int EXT4_ENCRYPTION_MODE_AES_256_XTS = 1;
98731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    struct ext4_encryption_key {
99fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence        uint32_t mode;
100fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence        char raw[EXT4_MAX_KEY_SIZE];
101fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence        uint32_t size;
102731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    };
103731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
104731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    namespace tag {
105731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        const char* magic = "magic";
106731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        const char* major_version = "major_version";
107731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        const char* minor_version = "minor_version";
108731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        const char* flags = "flags";
109731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        const char* crypt_type = "crypt_type";
110731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        const char* failed_decrypt_count = "failed_decrypt_count";
111731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        const char* crypto_type_name = "crypto_type_name";
112731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        const char* master_key = "master_key";
113731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        const char* salt = "salt";
114731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        const char* kdf_type = "kdf_type";
115731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        const char* N_factor = "N_factor";
116731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        const char* r_factor = "r_factor";
117731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        const char* p_factor = "p_factor";
118731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        const char* keymaster_blob = "keymaster_blob";
119731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        const char* scrypted_intermediate_key = "scrypted_intermediate_key";
120731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
121731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
122731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
12395376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowleystatic std::string e4crypt_install_key(const std::string &key);
124f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley
125731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrencestatic int put_crypt_ftr_and_key(const crypt_mnt_ftr& crypt_ftr,
126731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                                 UnencryptedProperties& props)
127731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{
128731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    SLOGI("Putting crypt footer");
129731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
130731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    bool success = props.Set<int>(tag::magic, crypt_ftr.magic)
131731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence      && props.Set<int>(tag::major_version, crypt_ftr.major_version)
132731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence      && props.Set<int>(tag::minor_version, crypt_ftr.minor_version)
133731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence      && props.Set<int>(tag::flags, crypt_ftr.flags)
134731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence      && props.Set<int>(tag::crypt_type, crypt_ftr.crypt_type)
135731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence      && props.Set<int>(tag::failed_decrypt_count,
136731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                        crypt_ftr.failed_decrypt_count)
137731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence      && props.Set<std::string>(tag::crypto_type_name,
138731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                                std::string(reinterpret_cast<const char*>(crypt_ftr.crypto_type_name)))
139731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence      && props.Set<std::string>(tag::master_key,
140731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                                std::string((const char*) crypt_ftr.master_key,
141731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                                            crypt_ftr.keysize))
142731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence      && props.Set<std::string>(tag::salt,
143731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                                std::string((const char*) crypt_ftr.salt,
144731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                                            SALT_LEN))
145731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence      && props.Set<int>(tag::kdf_type, crypt_ftr.kdf_type)
146731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence      && props.Set<int>(tag::N_factor, crypt_ftr.N_factor)
147731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence      && props.Set<int>(tag::r_factor, crypt_ftr.r_factor)
148731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence      && props.Set<int>(tag::p_factor, crypt_ftr.p_factor)
149731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence      && props.Set<std::string>(tag::keymaster_blob,
150731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                                std::string((const char*) crypt_ftr.keymaster_blob,
151731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                                            crypt_ftr.keymaster_blob_size))
152731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence      && props.Set<std::string>(tag::scrypted_intermediate_key,
153731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                                std::string((const char*) crypt_ftr.scrypted_intermediate_key,
154731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                                            SCRYPT_LEN));
155731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    return success ? 0 : -1;
156731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
157731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
158731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrencestatic int get_crypt_ftr_and_key(crypt_mnt_ftr& crypt_ftr,
159731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                                 const UnencryptedProperties& props)
160731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{
161731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    memset(&crypt_ftr, 0, sizeof(crypt_ftr));
162731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    crypt_ftr.magic = props.Get<int>(tag::magic);
163731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    crypt_ftr.major_version = props.Get<int>(tag::major_version);
164731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    crypt_ftr.minor_version = props.Get<int>(tag::minor_version);
1650d9cd9e9cf39e1cdb06565de6c4e11ff244b2a3aPaul Lawrence    crypt_ftr.ftr_size = sizeof(crypt_ftr);
166731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    crypt_ftr.flags = props.Get<int>(tag::flags);
167731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    crypt_ftr.crypt_type = props.Get<int>(tag::crypt_type);
168731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    crypt_ftr.failed_decrypt_count = props.Get<int>(tag::failed_decrypt_count);
169731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    std::string crypto_type_name = props.Get<std::string>(tag::crypto_type_name);
170731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    strlcpy(reinterpret_cast<char*>(crypt_ftr.crypto_type_name),
171731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence            crypto_type_name.c_str(),
172731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence            sizeof(crypt_ftr.crypto_type_name));
173731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    std::string master_key = props.Get<std::string>(tag::master_key);
174731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    crypt_ftr.keysize = master_key.size();
175731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (crypt_ftr.keysize > sizeof(crypt_ftr.master_key)) {
176731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        SLOGE("Master key size too long");
177731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return -1;
178731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
179731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    memcpy(crypt_ftr.master_key, &master_key[0], crypt_ftr.keysize);
180731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    std::string salt = props.Get<std::string>(tag::salt);
181731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (salt.size() != SALT_LEN) {
182731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        SLOGE("Salt wrong length");
183731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return -1;
184731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
185731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    memcpy(crypt_ftr.salt, &salt[0], SALT_LEN);
186731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    crypt_ftr.kdf_type = props.Get<int>(tag::kdf_type);
187731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    crypt_ftr.N_factor = props.Get<int>(tag::N_factor);
188731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    crypt_ftr.r_factor = props.Get<int>(tag::r_factor);
189731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    crypt_ftr.p_factor = props.Get<int>(tag::p_factor);
190731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    std::string keymaster_blob = props.Get<std::string>(tag::keymaster_blob);
191731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    crypt_ftr.keymaster_blob_size = keymaster_blob.size();
192731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (crypt_ftr.keymaster_blob_size > sizeof(crypt_ftr.keymaster_blob)) {
193731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        SLOGE("Keymaster blob too long");
194731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return -1;
195731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
196731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    memcpy(crypt_ftr.keymaster_blob, &keymaster_blob[0],
197731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence           crypt_ftr.keymaster_blob_size);
198731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    std::string scrypted_intermediate_key = props.Get<std::string>(tag::scrypted_intermediate_key);
199731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (scrypted_intermediate_key.size() != SCRYPT_LEN) {
200731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        SLOGE("scrypted intermediate key wrong length");
201731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return -1;
202731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
203731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    memcpy(crypt_ftr.scrypted_intermediate_key, &scrypted_intermediate_key[0],
204731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence           SCRYPT_LEN);
205731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
206731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    return 0;
207731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
208731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
209731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrencestatic UnencryptedProperties GetProps(const char* path)
210731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{
211731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    return UnencryptedProperties(path);
212731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
213731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
214731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrencestatic UnencryptedProperties GetAltProps(const char* path)
215731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{
216731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    return UnencryptedProperties((std::string() + path + "/tmp_mnt").c_str());
217731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
218731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
219731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrencestatic UnencryptedProperties GetPropsOrAltProps(const char* path)
220731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{
221731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    UnencryptedProperties props = GetProps(path);
222731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (props.OK()) {
223731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return props;
224731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
225731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    return GetAltProps(path);
226731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
227731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
228731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrenceint e4crypt_enable(const char* path)
229731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{
230731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    // Already enabled?
231731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (s_key_store.find(path) != s_key_store.end()) {
232731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return 0;
233731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
234731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
235731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    // Not an encryptable device?
236731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    UnencryptedProperties key_props = GetProps(path).GetChild(properties::key);
237731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (!key_props.OK()) {
238731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return 0;
239731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
240731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
241731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (key_props.Get<std::string>(tag::master_key).empty()) {
242731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        crypt_mnt_ftr ftr;
243731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        if (cryptfs_create_default_ftr(&ftr, key_length)) {
244731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence            SLOGE("Failed to create crypto footer");
245731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence            return -1;
246731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        }
247731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
2480d9cd9e9cf39e1cdb06565de6c4e11ff244b2a3aPaul Lawrence        // Scrub fields not used by ext4enc
2490d9cd9e9cf39e1cdb06565de6c4e11ff244b2a3aPaul Lawrence        ftr.persist_data_offset[0] = 0;
2500d9cd9e9cf39e1cdb06565de6c4e11ff244b2a3aPaul Lawrence        ftr.persist_data_offset[1] = 0;
2510d9cd9e9cf39e1cdb06565de6c4e11ff244b2a3aPaul Lawrence        ftr.persist_data_size = 0;
2520d9cd9e9cf39e1cdb06565de6c4e11ff244b2a3aPaul Lawrence
253731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        if (put_crypt_ftr_and_key(ftr, key_props)) {
254731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence            SLOGE("Failed to write crypto footer");
255731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence            return -1;
256731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        }
257731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
258731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        crypt_mnt_ftr ftr2;
259731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        if (get_crypt_ftr_and_key(ftr2, key_props)) {
260731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence            SLOGE("Failed to read crypto footer back");
261731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence            return -1;
262731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        }
263731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
264731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        if (memcmp(&ftr, &ftr2, sizeof(ftr)) != 0) {
265731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence            SLOGE("Crypto footer not correctly written");
2660d9cd9e9cf39e1cdb06565de6c4e11ff244b2a3aPaul Lawrence            return -1;
267731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        }
268731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
269731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
270731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (!UnencryptedProperties(path).Remove(properties::ref)) {
271731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        SLOGE("Failed to remove key ref");
272731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return -1;
273731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
274731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
275731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    return e4crypt_check_passwd(path, "");
276731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
277731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
278731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrenceint e4crypt_change_password(const char* path, int crypt_type,
279731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                            const char* password)
280731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{
281731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    SLOGI("e4crypt_change_password");
282a56d3134b03a3756a740aa909aa3d72643196842Paul Lawrence    auto key_props = GetProps(path).GetChild(properties::key);
283731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
284731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    crypt_mnt_ftr ftr;
285731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (get_crypt_ftr_and_key(ftr, key_props)) {
286731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        SLOGE("Failed to read crypto footer back");
287731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return -1;
288731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
289731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
290731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    auto mki = s_key_store.find(path);
291731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (mki == s_key_store.end()) {
292731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        SLOGE("No stored master key - can't change password");
293731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return -1;
294731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
295731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
29695376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley    const unsigned char* master_key_bytes
297731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        = reinterpret_cast<const unsigned char*>(&mki->second.master_key[0]);
298731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
29995376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley    if (cryptfs_set_password(&ftr, password, master_key_bytes)) {
300731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        SLOGE("Failed to set password");
301731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return -1;
302731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
303731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
304731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    ftr.crypt_type = crypt_type;
305731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
306731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (put_crypt_ftr_and_key(ftr, key_props)) {
307731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        SLOGE("Failed to write crypto footer");
308731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return -1;
309731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
310731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
311731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (!UnencryptedProperties(path).Set(properties::is_default,
312731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                            crypt_type == CRYPT_TYPE_DEFAULT)) {
313731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        SLOGE("Failed to update default flag");
314731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return -1;
315731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
316731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
317731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    return 0;
318731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
319731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
320731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrenceint e4crypt_crypto_complete(const char* path)
321731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{
322731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    SLOGI("ext4 crypto complete called on %s", path);
323a56d3134b03a3756a740aa909aa3d72643196842Paul Lawrence    auto key_props = GetPropsOrAltProps(path).GetChild(properties::key);
324731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (key_props.Get<std::string>(tag::master_key).empty()) {
325731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        SLOGI("No master key, so not ext4enc");
326731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return -1;
327731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
328731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
329731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    return 0;
330731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
331731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
3329336348200758d067fed164368636521b4e58621Paul Crowley// Get raw keyref - used to make keyname and to pass to ioctl
333fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrencestatic std::string generate_key_ref(const char* key, int length)
334fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence{
335fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    SHA512_CTX c;
336fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence
337fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    SHA512_Init(&c);
338fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    SHA512_Update(&c, key, length);
339285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    unsigned char key_ref1[SHA512_DIGEST_LENGTH];
340fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    SHA512_Final(key_ref1, &c);
341fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence
342fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    SHA512_Init(&c);
343285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    SHA512_Update(&c, key_ref1, SHA512_DIGEST_LENGTH);
344285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    unsigned char key_ref2[SHA512_DIGEST_LENGTH];
345fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    SHA512_Final(key_ref2, &c);
346fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence
347fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    return std::string((char*)key_ref2, EXT4_KEY_DESCRIPTOR_SIZE);
348fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence}
349fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence
350731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrenceint e4crypt_check_passwd(const char* path, const char* password)
351731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{
352731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    SLOGI("e4crypt_check_password");
353a56d3134b03a3756a740aa909aa3d72643196842Paul Lawrence    auto props = GetPropsOrAltProps(path);
354a56d3134b03a3756a740aa909aa3d72643196842Paul Lawrence    auto key_props = props.GetChild(properties::key);
355731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
356731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    crypt_mnt_ftr ftr;
357731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (get_crypt_ftr_and_key(ftr, key_props)) {
358731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        SLOGE("Failed to read crypto footer back");
359731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return -1;
360731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
361731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
36295376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley    unsigned char master_key_bytes[key_length / 8];
36395376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley    if (cryptfs_get_master_key (&ftr, password, master_key_bytes)){
364731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        SLOGI("Incorrect password");
365c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence        ftr.failed_decrypt_count++;
366c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence        if (put_crypt_ftr_and_key(ftr, key_props)) {
367c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence            SLOGW("Failed to update failed_decrypt_count");
368c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence        }
369c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence        return ftr.failed_decrypt_count;
370c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence    }
371c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence
372c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence    if (ftr.failed_decrypt_count) {
373c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence        ftr.failed_decrypt_count = 0;
374c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence        if (put_crypt_ftr_and_key(ftr, key_props)) {
375c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence            SLOGW("Failed to reset failed_decrypt_count");
376c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence        }
377731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
37895376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley    std::string master_key(reinterpret_cast<char*>(master_key_bytes),
37995376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley                           sizeof(master_key_bytes));
380731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
38186c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence    struct timespec now;
38286c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence    clock_gettime(CLOCK_BOOTTIME, &now);
38395376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley    s_key_store[path] = keys{master_key, password,
38486c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence                             now.tv_sec + password_max_age_seconds};
385f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley    auto raw_ref = e4crypt_install_key(master_key);
386f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley    if (raw_ref.empty()) {
387f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley        return -1;
388f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley    }
389731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
390f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley    // Save reference to key so we can set policy later
391f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley    if (!props.Set(properties::ref, raw_ref)) {
392f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley        SLOGE("Cannot save key reference");
393f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley        return -1;
394f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley    }
395f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley
396f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley    return 0;
397f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley}
398f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley
3999336348200758d067fed164368636521b4e58621Paul Crowleystatic ext4_encryption_key fill_key(const std::string &key)
400f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley{
401fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    // ext4enc:TODO Currently raw key is required to be of length
402fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    // sizeof(ext4_key.raw) == EXT4_MAX_KEY_SIZE, so zero pad to
403fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    // this length. Change when kernel bug is fixed.
404fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    ext4_encryption_key ext4_key = {EXT4_ENCRYPTION_MODE_AES_256_XTS,
405fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence                                    {0},
406fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence                                    sizeof(ext4_key.raw)};
407fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    memset(ext4_key.raw, 0, sizeof(ext4_key.raw));
408fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    static_assert(key_length / 8 <= sizeof(ext4_key.raw),
409fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence                  "Key too long!");
41095376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley    memcpy(ext4_key.raw, &key[0], key.size());
4119336348200758d067fed164368636521b4e58621Paul Crowley    return ext4_key;
4129336348200758d067fed164368636521b4e58621Paul Crowley}
413fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence
4149336348200758d067fed164368636521b4e58621Paul Crowleystatic std::string keyname(const std::string &raw_ref)
4159336348200758d067fed164368636521b4e58621Paul Crowley{
416fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    std::ostringstream o;
4179336348200758d067fed164368636521b4e58621Paul Crowley    o << "ext4:";
418fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    for (auto i = raw_ref.begin(); i != raw_ref.end(); ++i) {
419fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence        o << std::hex << std::setw(2) << std::setfill('0') << (int)*i;
420fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    }
4219336348200758d067fed164368636521b4e58621Paul Crowley    return o.str();
4229336348200758d067fed164368636521b4e58621Paul Crowley}
423731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
4249336348200758d067fed164368636521b4e58621Paul Crowley// Get the keyring we store all keys in
4259336348200758d067fed164368636521b4e58621Paul Crowleystatic key_serial_t e4crypt_keyring()
4269336348200758d067fed164368636521b4e58621Paul Crowley{
4279336348200758d067fed164368636521b4e58621Paul Crowley    return keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "e4crypt", 0);
4289336348200758d067fed164368636521b4e58621Paul Crowley}
429731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
4309336348200758d067fed164368636521b4e58621Paul Crowleystatic int e4crypt_install_key(const ext4_encryption_key &ext4_key, const std::string &ref)
4319336348200758d067fed164368636521b4e58621Paul Crowley{
4329336348200758d067fed164368636521b4e58621Paul Crowley    key_serial_t device_keyring = e4crypt_keyring();
433fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    key_serial_t key_id = add_key("logon", ref.c_str(),
434731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                                  (void*)&ext4_key, sizeof(ext4_key),
435731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                                  device_keyring);
436731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (key_id == -1) {
437285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        PLOG(ERROR) << "Failed to insert key into keyring " << device_keyring;
4389336348200758d067fed164368636521b4e58621Paul Crowley        return -1;
439731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
440285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    LOG(INFO) << "Added key " << key_id << " (" << ref << ") to keyring "
441285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        << device_keyring << " in process " << getpid();
4429336348200758d067fed164368636521b4e58621Paul Crowley    return 0;
4439336348200758d067fed164368636521b4e58621Paul Crowley}
444731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
4459336348200758d067fed164368636521b4e58621Paul Crowley// Install password into global keyring
4469336348200758d067fed164368636521b4e58621Paul Crowley// Return raw key reference for use in policy
4479336348200758d067fed164368636521b4e58621Paul Crowleystatic std::string e4crypt_install_key(const std::string &key)
4489336348200758d067fed164368636521b4e58621Paul Crowley{
4499336348200758d067fed164368636521b4e58621Paul Crowley    auto ext4_key = fill_key(key);
4509336348200758d067fed164368636521b4e58621Paul Crowley    auto raw_ref = generate_key_ref(ext4_key.raw, ext4_key.size);
4519336348200758d067fed164368636521b4e58621Paul Crowley    auto ref = keyname(raw_ref);
4529336348200758d067fed164368636521b4e58621Paul Crowley    if (e4crypt_install_key(ext4_key, ref) == -1) {
4539336348200758d067fed164368636521b4e58621Paul Crowley        return "";
4549336348200758d067fed164368636521b4e58621Paul Crowley    }
455f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley    return raw_ref;
456731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
457731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
458731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrenceint e4crypt_restart(const char* path)
459731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{
460731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    SLOGI("e4crypt_restart");
461731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
462731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    int rc = 0;
463731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
464731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    SLOGI("ext4 restart called on %s", path);
465731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    property_set("vold.decrypt", "trigger_reset_main");
466731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    SLOGI("Just asked init to shut down class main");
467731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    sleep(2);
468731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
469731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    std::string tmp_path = std::string() + path + "/tmp_mnt";
470731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
4712f32cda63bf5c86db880d36029a27c8597fb5e3cPaul Lawrence    rc = wait_and_unmount(tmp_path.c_str(), true);
472731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (rc) {
473731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        SLOGE("umount %s failed with rc %d, msg %s",
474731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence              tmp_path.c_str(), rc, strerror(errno));
475731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return rc;
476731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
477731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
4782f32cda63bf5c86db880d36029a27c8597fb5e3cPaul Lawrence    rc = wait_and_unmount(path, true);
479731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (rc) {
480731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        SLOGE("umount %s failed with rc %d, msg %s",
481731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence              path, rc, strerror(errno));
482731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return rc;
483731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
484731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
485731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    return 0;
486731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
487731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
48886c942a2537701a90b88768eab4648c0650dfad1Paul Lawrenceint e4crypt_get_password_type(const char* path)
48986c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence{
49086c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence    SLOGI("e4crypt_get_password_type");
49186c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence    return GetPropsOrAltProps(path).GetChild(properties::key)
49286c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence      .Get<int>(tag::crypt_type, CRYPT_TYPE_DEFAULT);
49386c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence}
49486c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence
495731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrenceconst char* e4crypt_get_password(const char* path)
496731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{
497731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    SLOGI("e4crypt_get_password");
498731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
499731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    auto i = s_key_store.find(path);
500731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (i == s_key_store.end()) {
501731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return 0;
502731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
50386c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence
50486c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence    struct timespec now;
50586c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence    clock_gettime(CLOCK_BOOTTIME, &now);
50686c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence    if (i->second.expiry_time < now.tv_sec) {
50786c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence        e4crypt_clear_password(path);
50886c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence        return 0;
50986c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence    }
51086c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence
51186c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence    return i->second.password.c_str();
512731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
513731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
51486c942a2537701a90b88768eab4648c0650dfad1Paul Lawrencevoid e4crypt_clear_password(const char* path)
515731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{
51686c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence    SLOGI("e4crypt_clear_password");
51786c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence
51886c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence    auto i = s_key_store.find(path);
51986c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence    if (i == s_key_store.end()) {
52086c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence        return;
52186c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence    }
52286c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence
52386c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence    memset(&i->second.password[0], 0, i->second.password.size());
52486c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence    i->second.password = std::string();
525731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
526368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence
527368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrenceint e4crypt_get_field(const char* path, const char* fieldname,
528368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence                      char* value, size_t len)
529368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence{
530368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence    auto v = GetPropsOrAltProps(path).GetChild(properties::props)
531368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence      .Get<std::string>(fieldname);
532368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence
533368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence    if (v == "") {
534368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence        return CRYPTO_GETFIELD_ERROR_NO_FIELD;
535368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence    }
536368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence
537368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence    if (v.length() >= len) {
538368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence        return CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL;
539368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence    }
540368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence
541368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence    strlcpy(value, v.c_str(), len);
542368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence    return 0;
543368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence}
544368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence
545368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrenceint e4crypt_set_field(const char* path, const char* fieldname,
546368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence                      const char* value)
547368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence{
548368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence    return GetPropsOrAltProps(path).GetChild(properties::props)
549368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence        .Set(fieldname, std::string(value)) ? 0 : -1;
550368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence}
55195376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley
552285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowleystatic std::string get_key_path(userid_t user_id) {
553285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    return StringPrintf("%s/%d", user_key_dir.c_str(), user_id);
554b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley}
555b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley
556395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtovastatic bool e4crypt_is_key_ephemeral(const std::string &key_path) {
557395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova    return s_ephemeral_user_keys.find(key_path) != s_ephemeral_user_keys.end();
558395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova}
559395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova
5601ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowleystatic bool read_user_key(userid_t user_id, std::string &key)
561b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley{
562285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    const auto key_path = get_key_path(user_id);
563395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova    const auto ephemeral_key_it = s_ephemeral_user_keys.find(key_path);
564395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova    if (ephemeral_key_it != s_ephemeral_user_keys.end()) {
5651ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley        key = ephemeral_key_it->second;
5661ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley        return true;
567395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova    }
5681ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    if (!android::vold::RetrieveKey(key_path, key)) return false;
5691ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    if (key.size() != key_length/8) {
5701ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley        LOG(ERROR) << "Wrong size key " << key.size() << " in " << key_path;
5711ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley        return false;
57295376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley    }
5731ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    return true;
574285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley}
575285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley
576285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowleystatic bool create_user_key(userid_t user_id, bool create_ephemeral) {
577285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    if (fs_prepare_dir(user_key_dir.c_str(), 0700, AID_ROOT, AID_ROOT)) {
578285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        PLOG(ERROR) << "Failed to prepare " << user_key_dir;
579285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        return false;
580285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    }
581285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    const auto key_path = get_key_path(user_id);
5821ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    std::string key;
5831ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    if (android::vold::ReadRandomBytes(key_length / 8, key) != 0) {
5841ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley        // TODO status_t plays badly with PLOG, fix it.
5851ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley        LOG(ERROR) << "Random read failed";
586285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        return false;
587285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    }
588395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova    if (create_ephemeral) {
589395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova        // If the key should be created as ephemeral, store it in memory only.
590395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova        s_ephemeral_user_keys[key_path] = key;
5911ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    } else if (!android::vold::StoreKey(key_path, key)) {
592285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        return false;
59395376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley    }
594285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    LOG(DEBUG) << "Created key " << key_path;
595285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    return true;
59695376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley}
59795376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley
598285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowleystatic int e4crypt_set_user_policy(userid_t user_id, int serial, std::string& path) {
599285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    LOG(DEBUG) << "e4crypt_set_user_policy for " << user_id << " serial " << serial;
600285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    if (s_key_raw_refs.count(serial) != 1) {
601285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        LOG(ERROR) << "Key unknown, can't e4crypt_set_user_policy for "
602285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley            << user_id << " serial " << serial;
60395376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley        return -1;
60495376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley    }
605285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    auto raw_ref = s_key_raw_refs[serial];
606285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    return do_policy_set(path.c_str(), raw_ref.data(), raw_ref.size());
60795376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley}
60895376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley
609285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowleyint e4crypt_vold_create_user_key(userid_t user_id, int serial, bool ephemeral) {
610285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    LOG(DEBUG) << "e4crypt_vold_create_user_key for " << user_id << " serial " << serial;
6111ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    std::string key;
6121ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    if (read_user_key(user_id, key)) {
613285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        LOG(ERROR) << "Already exists, can't e4crypt_vold_create_user_key for "
614285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley            << user_id << " serial " << serial;
615285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        // FIXME should we fail the command?
61695376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley        return 0;
61795376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley    }
618285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    if (!create_user_key(user_id, ephemeral)) {
61995376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley        return -1;
62095376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley    }
621285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    if (e4crypt_unlock_user_key(user_id, serial, nullptr) != 0) {
622d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        return -1;
623d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    }
624285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    // TODO: create second key for user_de data
625285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    return 0;
626d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey}
627d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
6281ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowleystatic bool evict_user_key(userid_t user_id) {
629285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    auto key_path = get_key_path(user_id);
6301ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    std::string key;
6311ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    if (!read_user_key(user_id, key)) return false;
6329336348200758d067fed164368636521b4e58621Paul Crowley    auto ext4_key = fill_key(key);
6339336348200758d067fed164368636521b4e58621Paul Crowley    auto ref = keyname(generate_key_ref(ext4_key.raw, ext4_key.size));
6349336348200758d067fed164368636521b4e58621Paul Crowley    auto key_serial = keyctl_search(e4crypt_keyring(), "logon", ref.c_str(), 0);
6351ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    if (keyctl_revoke(key_serial) != 0) {
636285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        PLOG(ERROR) << "Failed to revoke key with serial " << key_serial << " ref " << ref;
6371ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley        return false;
6389336348200758d067fed164368636521b4e58621Paul Crowley    }
6391ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    LOG(DEBUG) << "Revoked key with serial " << key_serial << " ref " << ref;
6401ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    return true;
6411ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley}
6421ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley
6431ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowleyint e4crypt_destroy_user_key(userid_t user_id) {
6441ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    LOG(DEBUG) << "e4crypt_destroy_user_key(" << user_id << ")";
6451ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    // TODO: destroy second key for user_de data
6461ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    bool evict_success = evict_user_key(user_id);
6471ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    auto key_path = get_key_path(user_id);
648395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova    if (e4crypt_is_key_ephemeral(key_path)) {
649395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova        s_ephemeral_user_keys.erase(key_path);
6501ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    } else {
6511ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley        if (!android::vold::DestroyKey(key_path)) {
6521ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley            return -1;
6531ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley        }
654b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley    }
6551ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    return evict_success ? 0 : -1;
656b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley}
657d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
6587a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkeystatic int emulated_lock(const std::string& path) {
6597a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    if (chmod(path.c_str(), 0000) != 0) {
6607a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey        PLOG(ERROR) << "Failed to chmod " << path;
6617a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey        return -1;
6627a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    }
6637a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#if EMULATED_USES_SELINUX
6647a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    if (setfilecon(path.c_str(), "u:object_r:storage_stub_file:s0") != 0) {
6657a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey        PLOG(WARNING) << "Failed to setfilecon " << path;
6667a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey        return -1;
6677a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    }
6687a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#endif
6697a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    return 0;
6707a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey}
6717a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey
6727a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkeystatic int emulated_unlock(const std::string& path, mode_t mode) {
6737a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    if (chmod(path.c_str(), mode) != 0) {
6747a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey        PLOG(ERROR) << "Failed to chmod " << path;
675a042cb5761f4bf954645b404ae5bb0a0d5b583fdPaul Crowley        // FIXME temporary workaround for b/26713622
676a042cb5761f4bf954645b404ae5bb0a0d5b583fdPaul Crowley        if (e4crypt_is_emulated()) return -1;
6777a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    }
6787a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#if EMULATED_USES_SELINUX
6797a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    if (selinux_android_restorecon(path.c_str(), SELINUX_ANDROID_RESTORECON_FORCE) != 0) {
6807a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey        PLOG(WARNING) << "Failed to restorecon " << path;
681a042cb5761f4bf954645b404ae5bb0a0d5b583fdPaul Crowley        // FIXME temporary workaround for b/26713622
682a042cb5761f4bf954645b404ae5bb0a0d5b583fdPaul Crowley        if (e4crypt_is_emulated()) return -1;
6837a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    }
6847a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#endif
6857a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    return 0;
6867a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey}
6877a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey
688285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowleyint e4crypt_unlock_user_key(userid_t user_id, int serial, const char* token) {
689285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    LOG(DEBUG) << "e4crypt_unlock_user_key " << user_id << " " << (token != nullptr);
690fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey    if (e4crypt_is_native()) {
6911ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley        std::string user_key;
6921ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley        if (!read_user_key(user_id, user_key)) {
693285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley            // FIXME special case for user 0
694285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley            if (user_id != 0) {
695285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley                LOG(ERROR) << "Couldn't read key for " << user_id;
696285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley                return -1;
697285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley            }
698285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley            // FIXME if the key exists and we just failed to read it, this destroys it.
699285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley            if (!create_user_key(user_id, false)) {
700285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley                return -1;
701285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley            }
7021ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley            if (!read_user_key(user_id, user_key)) {
703285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley                LOG(ERROR) << "Couldn't read just-created key for " << user_id;
704285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley                return -1;
705285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley            }
706d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        }
707d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        auto raw_ref = e4crypt_install_key(user_key);
708d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        if (raw_ref.empty()) {
709d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey            return -1;
710d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        }
711285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        s_key_raw_refs[serial] = raw_ref;
712285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        if (user_id == 0) {
713285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley            // FIXME special case for user 0
714285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley            // prepare their storage here
715285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley            e4crypt_prepare_user_storage(nullptr, 0, 0, false);
716285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        }
717285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        return 0;
718fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey    } else {
719fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey        // When in emulation mode, we just use chmod. However, we also
720fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey        // unlock directories when not in emulation mode, to bring devices
721fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey        // back into a known-good state.
7227a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey        if (emulated_unlock(android::vold::BuildDataSystemCePath(user_id), 0771) ||
7237a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey                emulated_unlock(android::vold::BuildDataMediaPath(nullptr, user_id), 0770) ||
7247a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey                emulated_unlock(android::vold::BuildDataUserPath(nullptr, user_id), 0771)) {
7257a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey            LOG(ERROR) << "Failed to unlock user " << user_id;
726fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey            return -1;
727fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey        }
728d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    }
729fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey
730d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    return 0;
731d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey}
732d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
733d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkeyint e4crypt_lock_user_key(userid_t user_id) {
734fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey    if (e4crypt_is_native()) {
735fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey        // TODO: remove from kernel keyring
736fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey    } else if (e4crypt_is_emulated()) {
737d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        // When in emulation mode, we just use chmod
7387a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey        if (emulated_lock(android::vold::BuildDataSystemCePath(user_id)) ||
7397a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey                emulated_lock(android::vold::BuildDataMediaPath(nullptr, user_id)) ||
7407a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey                emulated_lock(android::vold::BuildDataUserPath(nullptr, user_id))) {
741d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey            PLOG(ERROR) << "Failed to lock user " << user_id;
742d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey            return -1;
743d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        }
744d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    }
745fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey
746d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    return 0;
747d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey}
748d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
7499ad4369ce87cb445ea126a8a803e2b42c2c5ea2fLenka Trochtovaint e4crypt_prepare_user_storage(const char* volume_uuid,
7509ad4369ce87cb445ea126a8a803e2b42c2c5ea2fLenka Trochtova                                 userid_t user_id,
7519ad4369ce87cb445ea126a8a803e2b42c2c5ea2fLenka Trochtova                                 int serial,
7529ad4369ce87cb445ea126a8a803e2b42c2c5ea2fLenka Trochtova                                 bool ephemeral) {
753285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    if (volume_uuid) {
754285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        LOG(DEBUG) << "e4crypt_prepare_user_storage " << volume_uuid << " " << user_id;
755285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    } else {
756285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        LOG(DEBUG) << "e4crypt_prepare_user_storage, null volume " << user_id;
757285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    }
758d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    std::string system_ce_path(android::vold::BuildDataSystemCePath(user_id));
759d2d7bffd0c666bd3dc67364b36480e57a1913571Jeff Sharkey    std::string media_ce_path(android::vold::BuildDataMediaPath(volume_uuid, user_id));
760d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    std::string user_ce_path(android::vold::BuildDataUserPath(volume_uuid, user_id));
761d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    std::string user_de_path(android::vold::BuildDataUserDePath(volume_uuid, user_id));
762d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
763d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    if (fs_prepare_dir(system_ce_path.c_str(), 0700, AID_SYSTEM, AID_SYSTEM)) {
764d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        PLOG(ERROR) << "Failed to prepare " << system_ce_path;
765d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        return -1;
766d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    }
767d2d7bffd0c666bd3dc67364b36480e57a1913571Jeff Sharkey    if (fs_prepare_dir(media_ce_path.c_str(), 0770, AID_MEDIA_RW, AID_MEDIA_RW)) {
768d2d7bffd0c666bd3dc67364b36480e57a1913571Jeff Sharkey        PLOG(ERROR) << "Failed to prepare " << media_ce_path;
769d2d7bffd0c666bd3dc67364b36480e57a1913571Jeff Sharkey        return -1;
770d2d7bffd0c666bd3dc67364b36480e57a1913571Jeff Sharkey    }
771d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    if (fs_prepare_dir(user_ce_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM)) {
772d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        PLOG(ERROR) << "Failed to prepare " << user_ce_path;
773d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        return -1;
774d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    }
775d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    if (fs_prepare_dir(user_de_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM)) {
776d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        PLOG(ERROR) << "Failed to prepare " << user_de_path;
777d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        return -1;
778d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    }
779d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
780d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    if (e4crypt_crypto_complete(DATA_MNT_POINT) == 0) {
781285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        if (e4crypt_set_user_policy(user_id, serial, system_ce_path)
782285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley                || e4crypt_set_user_policy(user_id, serial, media_ce_path)
783285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley                || e4crypt_set_user_policy(user_id, serial, user_ce_path)) {
784d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey            return -1;
785d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        }
786d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    }
787d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
788d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    return 0;
789d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey}
790