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 "KeyUtil.h"
18
19 #include <linux/fs.h>
20 #include <iomanip>
21 #include <sstream>
22 #include <string>
23
24 #include <openssl/sha.h>
25
26 #include <android-base/file.h>
27 #include <android-base/logging.h>
28 #include <keyutils.h>
29
30 #include "KeyStorage.h"
31 #include "Utils.h"
32
33 namespace android {
34 namespace vold {
35
36 constexpr int FS_AES_256_XTS_KEY_SIZE = 64;
37
randomKey(KeyBuffer * key)38 bool randomKey(KeyBuffer* key) {
39 *key = KeyBuffer(FS_AES_256_XTS_KEY_SIZE);
40 if (ReadRandomBytes(key->size(), key->data()) != 0) {
41 // TODO status_t plays badly with PLOG, fix it.
42 LOG(ERROR) << "Random read failed";
43 return false;
44 }
45 return true;
46 }
47
48 // Get raw keyref - used to make keyname and to pass to ioctl
generateKeyRef(const uint8_t * key,int length)49 static std::string generateKeyRef(const uint8_t* key, int length) {
50 SHA512_CTX c;
51
52 SHA512_Init(&c);
53 SHA512_Update(&c, key, length);
54 unsigned char key_ref1[SHA512_DIGEST_LENGTH];
55 SHA512_Final(key_ref1, &c);
56
57 SHA512_Init(&c);
58 SHA512_Update(&c, key_ref1, SHA512_DIGEST_LENGTH);
59 unsigned char key_ref2[SHA512_DIGEST_LENGTH];
60 SHA512_Final(key_ref2, &c);
61
62 static_assert(FS_KEY_DESCRIPTOR_SIZE <= SHA512_DIGEST_LENGTH, "Hash too short for descriptor");
63 return std::string((char*)key_ref2, FS_KEY_DESCRIPTOR_SIZE);
64 }
65
fillKey(const KeyBuffer & key,fscrypt_key * fs_key)66 static bool fillKey(const KeyBuffer& key, fscrypt_key* fs_key) {
67 if (key.size() != FS_AES_256_XTS_KEY_SIZE) {
68 LOG(ERROR) << "Wrong size key " << key.size();
69 return false;
70 }
71 static_assert(FS_AES_256_XTS_KEY_SIZE <= sizeof(fs_key->raw), "Key too long!");
72 fs_key->mode = FS_ENCRYPTION_MODE_AES_256_XTS;
73 fs_key->size = key.size();
74 memset(fs_key->raw, 0, sizeof(fs_key->raw));
75 memcpy(fs_key->raw, key.data(), key.size());
76 return true;
77 }
78
79 static char const* const NAME_PREFIXES[] = {"ext4", "f2fs", "fscrypt", nullptr};
80
keyname(const std::string & prefix,const std::string & raw_ref)81 static std::string keyname(const std::string& prefix, const std::string& raw_ref) {
82 std::ostringstream o;
83 o << prefix << ":";
84 for (unsigned char i : raw_ref) {
85 o << std::hex << std::setw(2) << std::setfill('0') << (int)i;
86 }
87 return o.str();
88 }
89
90 // Get the keyring we store all keys in
fscryptKeyring(key_serial_t * device_keyring)91 static bool fscryptKeyring(key_serial_t* device_keyring) {
92 *device_keyring = keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0);
93 if (*device_keyring == -1) {
94 PLOG(ERROR) << "Unable to find device keyring";
95 return false;
96 }
97 return true;
98 }
99
100 // Install password into global keyring
101 // Return raw key reference for use in policy
installKey(const KeyBuffer & key,std::string * raw_ref)102 bool installKey(const KeyBuffer& key, std::string* raw_ref) {
103 // Place fscrypt_key into automatically zeroing buffer.
104 KeyBuffer fsKeyBuffer(sizeof(fscrypt_key));
105 fscrypt_key& fs_key = *reinterpret_cast<fscrypt_key*>(fsKeyBuffer.data());
106
107 if (!fillKey(key, &fs_key)) return false;
108 *raw_ref = generateKeyRef(fs_key.raw, fs_key.size);
109 key_serial_t device_keyring;
110 if (!fscryptKeyring(&device_keyring)) return false;
111 for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) {
112 auto ref = keyname(*name_prefix, *raw_ref);
113 key_serial_t key_id =
114 add_key("logon", ref.c_str(), (void*)&fs_key, sizeof(fs_key), device_keyring);
115 if (key_id == -1) {
116 PLOG(ERROR) << "Failed to insert key into keyring " << device_keyring;
117 return false;
118 }
119 LOG(DEBUG) << "Added key " << key_id << " (" << ref << ") to keyring " << device_keyring
120 << " in process " << getpid();
121 }
122 return true;
123 }
124
evictKey(const std::string & raw_ref)125 bool evictKey(const std::string& raw_ref) {
126 key_serial_t device_keyring;
127 if (!fscryptKeyring(&device_keyring)) return false;
128 bool success = true;
129 for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) {
130 auto ref = keyname(*name_prefix, raw_ref);
131 auto key_serial = keyctl_search(device_keyring, "logon", ref.c_str(), 0);
132
133 // Unlink the key from the keyring. Prefer unlinking to revoking or
134 // invalidating, since unlinking is actually no less secure currently, and
135 // it avoids bugs in certain kernel versions where the keyring key is
136 // referenced from places it shouldn't be.
137 if (keyctl_unlink(key_serial, device_keyring) != 0) {
138 PLOG(ERROR) << "Failed to unlink key with serial " << key_serial << " ref " << ref;
139 success = false;
140 } else {
141 LOG(DEBUG) << "Unlinked key with serial " << key_serial << " ref " << ref;
142 }
143 }
144 return success;
145 }
146
retrieveAndInstallKey(bool create_if_absent,const KeyAuthentication & key_authentication,const std::string & key_path,const std::string & tmp_path,std::string * key_ref)147 bool retrieveAndInstallKey(bool create_if_absent, const KeyAuthentication& key_authentication,
148 const std::string& key_path, const std::string& tmp_path,
149 std::string* key_ref) {
150 KeyBuffer key;
151 if (pathExists(key_path)) {
152 LOG(DEBUG) << "Key exists, using: " << key_path;
153 if (!retrieveKey(key_path, key_authentication, &key)) return false;
154 } else {
155 if (!create_if_absent) {
156 LOG(ERROR) << "No key found in " << key_path;
157 return false;
158 }
159 LOG(INFO) << "Creating new key in " << key_path;
160 if (!randomKey(&key)) return false;
161 if (!storeKeyAtomically(key_path, tmp_path, key_authentication, key)) return false;
162 }
163
164 if (!installKey(key, key_ref)) {
165 LOG(ERROR) << "Failed to install key in " << key_path;
166 return false;
167 }
168 return true;
169 }
170
retrieveKey(bool create_if_absent,const std::string & key_path,const std::string & tmp_path,KeyBuffer * key,bool keepOld)171 bool retrieveKey(bool create_if_absent, const std::string& key_path, const std::string& tmp_path,
172 KeyBuffer* key, bool keepOld) {
173 if (pathExists(key_path)) {
174 LOG(DEBUG) << "Key exists, using: " << key_path;
175 if (!retrieveKey(key_path, kEmptyAuthentication, key, keepOld)) return false;
176 } else {
177 if (!create_if_absent) {
178 LOG(ERROR) << "No key found in " << key_path;
179 return false;
180 }
181 LOG(INFO) << "Creating new key in " << key_path;
182 if (!randomKey(key)) return false;
183 if (!storeKeyAtomically(key_path, tmp_path, kEmptyAuthentication, *key)) return false;
184 }
185 return true;
186 }
187
188 } // namespace vold
189 } // namespace android
190