blob: 9cb8ca0c4d517a113e4b2c7581ac38e1be3dd2de [file] [log] [blame]
Paul Crowley1ef25582016-01-21 20:26:12 +00001/*
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 "KeyStorage.h"
18
19#include "Keymaster.h"
Paul Crowley63c18d32016-02-10 14:02:47 +000020#include "ScryptParameters.h"
Paul Crowley1ef25582016-01-21 20:26:12 +000021#include "Utils.h"
22
23#include <vector>
24
25#include <errno.h>
Paul Crowleydff8c722016-05-16 08:14:56 -070026#include <stdio.h>
Paul Crowley1ef25582016-01-21 20:26:12 +000027#include <sys/stat.h>
28#include <sys/types.h>
29#include <sys/wait.h>
30#include <unistd.h>
31
32#include <openssl/sha.h>
33
34#include <android-base/file.h>
35#include <android-base/logging.h>
36
Paul Crowley63c18d32016-02-10 14:02:47 +000037#include <cutils/properties.h>
38
Paul Crowley320e5e12016-03-04 14:07:05 -080039#include <hardware/hw_auth_token.h>
40
Janis Danisevskis8e537b82016-10-26 14:27:10 +010041#include <keystore/authorization_set.h>
42#include <keystore/keystore_hidl_support.h>
Paul Crowley1ef25582016-01-21 20:26:12 +000043
Paul Crowley63c18d32016-02-10 14:02:47 +000044extern "C" {
45
46#include "crypto_scrypt.h"
Paul Crowley63c18d32016-02-10 14:02:47 +000047}
48
Paul Crowley1ef25582016-01-21 20:26:12 +000049namespace android {
50namespace vold {
Janis Danisevskis8e537b82016-10-26 14:27:10 +010051using namespace keystore;
Paul Crowley1ef25582016-01-21 20:26:12 +000052
Paul Crowleydf528a72016-03-09 09:31:37 -080053const KeyAuthentication kEmptyAuthentication{"", ""};
Paul Crowley05720802016-02-08 15:55:41 +000054
Paul Crowley1ef25582016-01-21 20:26:12 +000055static constexpr size_t AES_KEY_BYTES = 32;
56static constexpr size_t GCM_NONCE_BYTES = 12;
57static constexpr size_t GCM_MAC_BYTES = 16;
Paul Crowleydf528a72016-03-09 09:31:37 -080058static constexpr size_t SALT_BYTES = 1 << 4;
59static constexpr size_t SECDISCARDABLE_BYTES = 1 << 14;
60static constexpr size_t STRETCHED_BYTES = 1 << 6;
Paul Crowley1ef25582016-01-21 20:26:12 +000061
Paul Crowleyb3de3372016-04-27 12:58:41 -070062static constexpr uint32_t AUTH_TIMEOUT = 30; // Seconds
63
Paul Crowley05720802016-02-08 15:55:41 +000064static const char* kCurrentVersion = "1";
Paul Crowley1ef25582016-01-21 20:26:12 +000065static const char* kRmPath = "/system/bin/rm";
66static const char* kSecdiscardPath = "/system/bin/secdiscard";
Paul Crowley63c18d32016-02-10 14:02:47 +000067static const char* kStretch_none = "none";
68static const char* kStretch_nopassword = "nopassword";
69static const std::string kStretchPrefix_scrypt = "scrypt ";
Paul Crowley1ef25582016-01-21 20:26:12 +000070static const char* kFn_encrypted_key = "encrypted_key";
Paul Crowley05720802016-02-08 15:55:41 +000071static const char* kFn_keymaster_key_blob = "keymaster_key_blob";
Paul Crowleydff8c722016-05-16 08:14:56 -070072static const char* kFn_keymaster_key_blob_upgraded = "keymaster_key_blob_upgraded";
Paul Crowley63c18d32016-02-10 14:02:47 +000073static const char* kFn_salt = "salt";
Paul Crowley1ef25582016-01-21 20:26:12 +000074static const char* kFn_secdiscardable = "secdiscardable";
Paul Crowley05720802016-02-08 15:55:41 +000075static const char* kFn_stretching = "stretching";
76static const char* kFn_version = "version";
Paul Crowley1ef25582016-01-21 20:26:12 +000077
Paul Crowley13ffd8e2016-01-27 14:30:22 +000078static bool checkSize(const std::string& kind, size_t actual, size_t expected) {
Paul Crowley1ef25582016-01-21 20:26:12 +000079 if (actual != expected) {
Paul Crowleydf528a72016-03-09 09:31:37 -080080 LOG(ERROR) << "Wrong number of bytes in " << kind << ", expected " << expected << " got "
81 << actual;
Paul Crowley1ef25582016-01-21 20:26:12 +000082 return false;
83 }
84 return true;
85}
86
Paul Crowleydf528a72016-03-09 09:31:37 -080087static std::string hashSecdiscardable(const std::string& secdiscardable) {
Paul Crowley1ef25582016-01-21 20:26:12 +000088 SHA512_CTX c;
89
90 SHA512_Init(&c);
91 // Personalise the hashing by introducing a fixed prefix.
92 // Hashing applications should use personalization except when there is a
93 // specific reason not to; see section 4.11 of https://www.schneier.com/skein1.3.pdf
Paul Crowley13ffd8e2016-01-27 14:30:22 +000094 std::string secdiscardableHashingPrefix = "Android secdiscardable SHA512";
95 secdiscardableHashingPrefix.resize(SHA512_CBLOCK);
96 SHA512_Update(&c, secdiscardableHashingPrefix.data(), secdiscardableHashingPrefix.size());
Paul Crowley1ef25582016-01-21 20:26:12 +000097 SHA512_Update(&c, secdiscardable.data(), secdiscardable.size());
98 std::string res(SHA512_DIGEST_LENGTH, '\0');
Paul Crowleydf528a72016-03-09 09:31:37 -080099 SHA512_Final(reinterpret_cast<uint8_t*>(&res[0]), &c);
Paul Crowley1ef25582016-01-21 20:26:12 +0000100 return res;
101}
102
Paul Crowleydf528a72016-03-09 09:31:37 -0800103static bool generateKeymasterKey(Keymaster& keymaster, const KeyAuthentication& auth,
104 const std::string& appId, std::string* key) {
Janis Danisevskis8e537b82016-10-26 14:27:10 +0100105 auto paramBuilder = AuthorizationSetBuilder()
Paul Crowleydf528a72016-03-09 09:31:37 -0800106 .AesEncryptionKey(AES_KEY_BYTES * 8)
Janis Danisevskis8e537b82016-10-26 14:27:10 +0100107 .Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
108 .Authorization(TAG_MIN_MAC_LENGTH, GCM_MAC_BYTES * 8)
109 .Authorization(TAG_PADDING, PaddingMode::NONE)
110 .Authorization(TAG_APPLICATION_ID, blob2hidlVec(appId));
Paul Crowley320e5e12016-03-04 14:07:05 -0800111 if (auth.token.empty()) {
112 LOG(DEBUG) << "Creating key that doesn't need auth token";
Janis Danisevskis8e537b82016-10-26 14:27:10 +0100113 paramBuilder.Authorization(TAG_NO_AUTH_REQUIRED);
Paul Crowley320e5e12016-03-04 14:07:05 -0800114 } else {
115 LOG(DEBUG) << "Auth token required for key";
116 if (auth.token.size() != sizeof(hw_auth_token_t)) {
117 LOG(ERROR) << "Auth token should be " << sizeof(hw_auth_token_t) << " bytes, was "
Paul Crowleydf528a72016-03-09 09:31:37 -0800118 << auth.token.size() << " bytes";
Paul Crowley320e5e12016-03-04 14:07:05 -0800119 return false;
120 }
Paul Crowleydf528a72016-03-09 09:31:37 -0800121 const hw_auth_token_t* at = reinterpret_cast<const hw_auth_token_t*>(auth.token.data());
Janis Danisevskis8e537b82016-10-26 14:27:10 +0100122 paramBuilder.Authorization(TAG_USER_SECURE_ID, at->user_id);
123 paramBuilder.Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::PASSWORD);
124 paramBuilder.Authorization(TAG_AUTH_TIMEOUT, AUTH_TIMEOUT);
Paul Crowley320e5e12016-03-04 14:07:05 -0800125 }
Janis Danisevskis8e537b82016-10-26 14:27:10 +0100126 return keymaster.generateKey(paramBuilder, key);
Paul Crowley320e5e12016-03-04 14:07:05 -0800127}
128
Janis Danisevskis8e537b82016-10-26 14:27:10 +0100129static AuthorizationSet beginParams(const KeyAuthentication& auth,
Paul Crowleydff8c722016-05-16 08:14:56 -0700130 const std::string& appId) {
Janis Danisevskis8e537b82016-10-26 14:27:10 +0100131 auto paramBuilder = AuthorizationSetBuilder()
132 .Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
133 .Authorization(TAG_MAC_LENGTH, GCM_MAC_BYTES * 8)
134 .Authorization(TAG_PADDING, PaddingMode::NONE)
135 .Authorization(TAG_APPLICATION_ID, blob2hidlVec(appId));
Paul Crowley320e5e12016-03-04 14:07:05 -0800136 if (!auth.token.empty()) {
137 LOG(DEBUG) << "Supplying auth token to Keymaster";
Janis Danisevskis8e537b82016-10-26 14:27:10 +0100138 paramBuilder.Authorization(TAG_AUTH_TOKEN, blob2hidlVec(auth.token));
Paul Crowley320e5e12016-03-04 14:07:05 -0800139 }
Janis Danisevskis8e537b82016-10-26 14:27:10 +0100140 return paramBuilder;
Paul Crowley1ef25582016-01-21 20:26:12 +0000141}
142
Paul Crowleydf528a72016-03-09 09:31:37 -0800143static bool readFileToString(const std::string& filename, std::string* result) {
Paul Crowleya051eb72016-03-08 16:08:32 -0800144 if (!android::base::ReadFileToString(filename, result)) {
Paul Crowleydf528a72016-03-09 09:31:37 -0800145 PLOG(ERROR) << "Failed to read from " << filename;
146 return false;
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000147 }
148 return true;
149}
150
Paul Crowleydf528a72016-03-09 09:31:37 -0800151static bool writeStringToFile(const std::string& payload, const std::string& filename) {
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000152 if (!android::base::WriteStringToFile(payload, filename)) {
Paul Crowleydf528a72016-03-09 09:31:37 -0800153 PLOG(ERROR) << "Failed to write to " << filename;
154 return false;
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000155 }
156 return true;
157}
158
Paul Crowleydff8c722016-05-16 08:14:56 -0700159static KeymasterOperation begin(Keymaster& keymaster, const std::string& dir,
Janis Danisevskis8e537b82016-10-26 14:27:10 +0100160 KeyPurpose purpose,
161 const AuthorizationSet &keyParams,
162 const AuthorizationSet &opParams,
163 AuthorizationSet* outParams) {
Paul Crowleydff8c722016-05-16 08:14:56 -0700164 auto kmKeyPath = dir + "/" + kFn_keymaster_key_blob;
165 std::string kmKey;
166 if (!readFileToString(kmKeyPath, &kmKey)) return KeymasterOperation();
Janis Danisevskis8e537b82016-10-26 14:27:10 +0100167 AuthorizationSet inParams(keyParams);
168 inParams.append(opParams.begin(), opParams.end());
Paul Crowleydff8c722016-05-16 08:14:56 -0700169 for (;;) {
170 auto opHandle = keymaster.begin(purpose, kmKey, inParams, outParams);
171 if (opHandle) {
172 return opHandle;
173 }
Janis Danisevskis8e537b82016-10-26 14:27:10 +0100174 if (opHandle.error() != ErrorCode::KEY_REQUIRES_UPGRADE) return opHandle;
Paul Crowleydff8c722016-05-16 08:14:56 -0700175 LOG(DEBUG) << "Upgrading key: " << dir;
176 std::string newKey;
177 if (!keymaster.upgradeKey(kmKey, keyParams, &newKey)) return KeymasterOperation();
178 auto newKeyPath = dir + "/" + kFn_keymaster_key_blob_upgraded;
179 if (!writeStringToFile(newKey, newKeyPath)) return KeymasterOperation();
180 if (rename(newKeyPath.c_str(), kmKeyPath.c_str()) != 0) {
181 PLOG(ERROR) << "Unable to move upgraded key to location: " << kmKeyPath;
182 return KeymasterOperation();
183 }
184 if (!keymaster.deleteKey(kmKey)) {
185 LOG(ERROR) << "Key deletion failed during upgrade, continuing anyway: " << dir;
186 }
187 kmKey = newKey;
188 LOG(INFO) << "Key upgraded: " << dir;
189 }
190}
191
192static bool encryptWithKeymasterKey(Keymaster& keymaster, const std::string& dir,
Janis Danisevskis8e537b82016-10-26 14:27:10 +0100193 const AuthorizationSet &keyParams,
Paul Crowleydff8c722016-05-16 08:14:56 -0700194 const std::string& message, std::string* ciphertext) {
Janis Danisevskis8e537b82016-10-26 14:27:10 +0100195 AuthorizationSet opParams;
196 AuthorizationSet outParams;
197 auto opHandle = begin(keymaster, dir, KeyPurpose::ENCRYPT, keyParams, opParams, &outParams);
Paul Crowleydff8c722016-05-16 08:14:56 -0700198 if (!opHandle) return false;
Janis Danisevskis8e537b82016-10-26 14:27:10 +0100199 auto nonceBlob = outParams.GetTagValue(TAG_NONCE);
200 if (!nonceBlob.isOk()) {
Paul Crowleydff8c722016-05-16 08:14:56 -0700201 LOG(ERROR) << "GCM encryption but no nonce generated";
202 return false;
203 }
204 // nonceBlob here is just a pointer into existing data, must not be freed
Janis Danisevskis8e537b82016-10-26 14:27:10 +0100205 std::string nonce(reinterpret_cast<const char*>(&nonceBlob.value()[0]), nonceBlob.value().size());
Paul Crowleydff8c722016-05-16 08:14:56 -0700206 if (!checkSize("nonce", nonce.size(), GCM_NONCE_BYTES)) return false;
207 std::string body;
208 if (!opHandle.updateCompletely(message, &body)) return false;
209
210 std::string mac;
211 if (!opHandle.finish(&mac)) return false;
212 if (!checkSize("mac", mac.size(), GCM_MAC_BYTES)) return false;
213 *ciphertext = nonce + body + mac;
214 return true;
215}
216
217static bool decryptWithKeymasterKey(Keymaster& keymaster, const std::string& dir,
Janis Danisevskis8e537b82016-10-26 14:27:10 +0100218 const AuthorizationSet &keyParams,
Paul Crowleydff8c722016-05-16 08:14:56 -0700219 const std::string& ciphertext, std::string* message) {
220 auto nonce = ciphertext.substr(0, GCM_NONCE_BYTES);
221 auto bodyAndMac = ciphertext.substr(GCM_NONCE_BYTES);
Janis Danisevskis8e537b82016-10-26 14:27:10 +0100222 auto opParams = AuthorizationSetBuilder()
223 .Authorization(TAG_NONCE, blob2hidlVec(nonce));
224 auto opHandle = begin(keymaster, dir, KeyPurpose::DECRYPT, keyParams, opParams, nullptr);
Paul Crowleydff8c722016-05-16 08:14:56 -0700225 if (!opHandle) return false;
226 if (!opHandle.updateCompletely(bodyAndMac, message)) return false;
227 if (!opHandle.finish(nullptr)) return false;
228 return true;
229}
230
Paul Crowley63c18d32016-02-10 14:02:47 +0000231static std::string getStretching() {
232 char paramstr[PROPERTY_VALUE_MAX];
233
234 property_get(SCRYPT_PROP, paramstr, SCRYPT_DEFAULTS);
235 return std::string() + kStretchPrefix_scrypt + paramstr;
236}
237
Paul Crowleydf528a72016-03-09 09:31:37 -0800238static bool stretchingNeedsSalt(const std::string& stretching) {
Paul Crowley63c18d32016-02-10 14:02:47 +0000239 return stretching != kStretch_nopassword && stretching != kStretch_none;
240}
241
Paul Crowleydf528a72016-03-09 09:31:37 -0800242static bool stretchSecret(const std::string& stretching, const std::string& secret,
243 const std::string& salt, std::string* stretched) {
Paul Crowley63c18d32016-02-10 14:02:47 +0000244 if (stretching == kStretch_nopassword) {
245 if (!secret.empty()) {
Paul Crowleyd9b92952016-03-04 13:45:00 -0800246 LOG(WARNING) << "Password present but stretching is nopassword";
Paul Crowley63c18d32016-02-10 14:02:47 +0000247 // Continue anyway
248 }
Paul Crowleya051eb72016-03-08 16:08:32 -0800249 stretched->clear();
Paul Crowley63c18d32016-02-10 14:02:47 +0000250 } else if (stretching == kStretch_none) {
Paul Crowleya051eb72016-03-08 16:08:32 -0800251 *stretched = secret;
Paul Crowleydf528a72016-03-09 09:31:37 -0800252 } else if (std::equal(kStretchPrefix_scrypt.begin(), kStretchPrefix_scrypt.end(),
253 stretching.begin())) {
Paul Crowley63c18d32016-02-10 14:02:47 +0000254 int Nf, rf, pf;
Paul Crowleydf528a72016-03-09 09:31:37 -0800255 if (!parse_scrypt_parameters(stretching.substr(kStretchPrefix_scrypt.size()).c_str(), &Nf,
256 &rf, &pf)) {
Paul Crowley63c18d32016-02-10 14:02:47 +0000257 LOG(ERROR) << "Unable to parse scrypt params in stretching: " << stretching;
258 return false;
259 }
Paul Crowleya051eb72016-03-08 16:08:32 -0800260 stretched->assign(STRETCHED_BYTES, '\0');
Paul Crowleydf528a72016-03-09 09:31:37 -0800261 if (crypto_scrypt(reinterpret_cast<const uint8_t*>(secret.data()), secret.size(),
262 reinterpret_cast<const uint8_t*>(salt.data()), salt.size(),
263 1 << Nf, 1 << rf, 1 << pf,
264 reinterpret_cast<uint8_t*>(&(*stretched)[0]), stretched->size()) != 0) {
Paul Crowley63c18d32016-02-10 14:02:47 +0000265 LOG(ERROR) << "scrypt failed with params: " << stretching;
266 return false;
267 }
268 } else {
269 LOG(ERROR) << "Unknown stretching type: " << stretching;
270 return false;
271 }
272 return true;
273}
274
Paul Crowleydf528a72016-03-09 09:31:37 -0800275static bool generateAppId(const KeyAuthentication& auth, const std::string& stretching,
276 const std::string& salt, const std::string& secdiscardable,
277 std::string* appId) {
Paul Crowley63c18d32016-02-10 14:02:47 +0000278 std::string stretched;
Paul Crowleya051eb72016-03-08 16:08:32 -0800279 if (!stretchSecret(stretching, auth.secret, salt, &stretched)) return false;
280 *appId = hashSecdiscardable(secdiscardable) + stretched;
Paul Crowley63c18d32016-02-10 14:02:47 +0000281 return true;
Paul Crowley05720802016-02-08 15:55:41 +0000282}
283
Paul Crowleydf528a72016-03-09 09:31:37 -0800284bool storeKey(const std::string& dir, const KeyAuthentication& auth, const std::string& key) {
Paul Crowley1ef25582016-01-21 20:26:12 +0000285 if (TEMP_FAILURE_RETRY(mkdir(dir.c_str(), 0700)) == -1) {
286 PLOG(ERROR) << "key mkdir " << dir;
287 return false;
288 }
Paul Crowleydf528a72016-03-09 09:31:37 -0800289 if (!writeStringToFile(kCurrentVersion, dir + "/" + kFn_version)) return false;
Paul Crowley1ef25582016-01-21 20:26:12 +0000290 std::string secdiscardable;
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000291 if (ReadRandomBytes(SECDISCARDABLE_BYTES, secdiscardable) != OK) {
Paul Crowley1ef25582016-01-21 20:26:12 +0000292 // TODO status_t plays badly with PLOG, fix it.
293 LOG(ERROR) << "Random read failed";
294 return false;
295 }
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000296 if (!writeStringToFile(secdiscardable, dir + "/" + kFn_secdiscardable)) return false;
Paul Crowley63c18d32016-02-10 14:02:47 +0000297 std::string stretching = auth.secret.empty() ? kStretch_nopassword : getStretching();
Paul Crowleydf528a72016-03-09 09:31:37 -0800298 if (!writeStringToFile(stretching, dir + "/" + kFn_stretching)) return false;
Paul Crowley63c18d32016-02-10 14:02:47 +0000299 std::string salt;
300 if (stretchingNeedsSalt(stretching)) {
301 if (ReadRandomBytes(SALT_BYTES, salt) != OK) {
302 LOG(ERROR) << "Random read failed";
303 return false;
304 }
Paul Crowleydf528a72016-03-09 09:31:37 -0800305 if (!writeStringToFile(salt, dir + "/" + kFn_salt)) return false;
Paul Crowley63c18d32016-02-10 14:02:47 +0000306 }
Paul Crowley320e5e12016-03-04 14:07:05 -0800307 std::string appId;
Paul Crowleya051eb72016-03-08 16:08:32 -0800308 if (!generateAppId(auth, stretching, salt, secdiscardable, &appId)) return false;
Paul Crowley1ef25582016-01-21 20:26:12 +0000309 Keymaster keymaster;
310 if (!keymaster) return false;
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000311 std::string kmKey;
Paul Crowleya051eb72016-03-08 16:08:32 -0800312 if (!generateKeymasterKey(keymaster, auth, appId, &kmKey)) return false;
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000313 if (!writeStringToFile(kmKey, dir + "/" + kFn_keymaster_key_blob)) return false;
Paul Crowleydff8c722016-05-16 08:14:56 -0700314 auto keyParams = beginParams(auth, appId);
Paul Crowley320e5e12016-03-04 14:07:05 -0800315 std::string encryptedKey;
Paul Crowleydff8c722016-05-16 08:14:56 -0700316 if (!encryptWithKeymasterKey(keymaster, dir, keyParams, key, &encryptedKey)) return false;
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000317 if (!writeStringToFile(encryptedKey, dir + "/" + kFn_encrypted_key)) return false;
Paul Crowley1ef25582016-01-21 20:26:12 +0000318 return true;
319}
320
Paul Crowleydf528a72016-03-09 09:31:37 -0800321bool retrieveKey(const std::string& dir, const KeyAuthentication& auth, std::string* key) {
Paul Crowley05720802016-02-08 15:55:41 +0000322 std::string version;
Paul Crowleya051eb72016-03-08 16:08:32 -0800323 if (!readFileToString(dir + "/" + kFn_version, &version)) return false;
Paul Crowley05720802016-02-08 15:55:41 +0000324 if (version != kCurrentVersion) {
325 LOG(ERROR) << "Version mismatch, expected " << kCurrentVersion << " got " << version;
326 return false;
327 }
Paul Crowley1ef25582016-01-21 20:26:12 +0000328 std::string secdiscardable;
Paul Crowleya051eb72016-03-08 16:08:32 -0800329 if (!readFileToString(dir + "/" + kFn_secdiscardable, &secdiscardable)) return false;
Paul Crowley63c18d32016-02-10 14:02:47 +0000330 std::string stretching;
Paul Crowleya051eb72016-03-08 16:08:32 -0800331 if (!readFileToString(dir + "/" + kFn_stretching, &stretching)) return false;
Paul Crowley63c18d32016-02-10 14:02:47 +0000332 std::string salt;
333 if (stretchingNeedsSalt(stretching)) {
Paul Crowleydf528a72016-03-09 09:31:37 -0800334 if (!readFileToString(dir + "/" + kFn_salt, &salt)) return false;
Paul Crowley63c18d32016-02-10 14:02:47 +0000335 }
Paul Crowley320e5e12016-03-04 14:07:05 -0800336 std::string appId;
Paul Crowleya051eb72016-03-08 16:08:32 -0800337 if (!generateAppId(auth, stretching, salt, secdiscardable, &appId)) return false;
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000338 std::string encryptedMessage;
Paul Crowleya051eb72016-03-08 16:08:32 -0800339 if (!readFileToString(dir + "/" + kFn_encrypted_key, &encryptedMessage)) return false;
Paul Crowley1ef25582016-01-21 20:26:12 +0000340 Keymaster keymaster;
341 if (!keymaster) return false;
Paul Crowleydff8c722016-05-16 08:14:56 -0700342 auto keyParams = beginParams(auth, appId);
343 return decryptWithKeymasterKey(keymaster, dir, keyParams, encryptedMessage, key);
Paul Crowley1ef25582016-01-21 20:26:12 +0000344}
345
Paul Crowleydf528a72016-03-09 09:31:37 -0800346static bool deleteKey(const std::string& dir) {
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000347 std::string kmKey;
Paul Crowleya051eb72016-03-08 16:08:32 -0800348 if (!readFileToString(dir + "/" + kFn_keymaster_key_blob, &kmKey)) return false;
Paul Crowley1ef25582016-01-21 20:26:12 +0000349 Keymaster keymaster;
350 if (!keymaster) return false;
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000351 if (!keymaster.deleteKey(kmKey)) return false;
Paul Crowley1ef25582016-01-21 20:26:12 +0000352 return true;
353}
354
Paul Crowleybeb33a62016-07-07 10:06:30 -0700355static bool runSecdiscard(const std::string& dir) {
Paul Crowleydf528a72016-03-09 09:31:37 -0800356 if (ForkExecvp(
Paul Crowleybeb33a62016-07-07 10:06:30 -0700357 std::vector<std::string>{kSecdiscardPath, "--",
358 dir + "/" + kFn_encrypted_key,
359 dir + "/" + kFn_keymaster_key_blob,
360 dir + "/" + kFn_secdiscardable,
361 }) != 0) {
Paul Crowley1ef25582016-01-21 20:26:12 +0000362 LOG(ERROR) << "secdiscard failed";
363 return false;
364 }
365 return true;
366}
367
Paul Crowleydf528a72016-03-09 09:31:37 -0800368static bool recursiveDeleteKey(const std::string& dir) {
369 if (ForkExecvp(std::vector<std::string>{kRmPath, "-rf", dir}) != 0) {
Paul Crowley1ef25582016-01-21 20:26:12 +0000370 LOG(ERROR) << "recursive delete failed";
371 return false;
372 }
373 return true;
374}
375
Paul Crowleydf528a72016-03-09 09:31:37 -0800376bool destroyKey(const std::string& dir) {
Paul Crowley1ef25582016-01-21 20:26:12 +0000377 bool success = true;
378 // Try each thing, even if previous things failed.
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000379 success &= deleteKey(dir);
Paul Crowleybeb33a62016-07-07 10:06:30 -0700380 success &= runSecdiscard(dir);
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000381 success &= recursiveDeleteKey(dir);
Paul Crowley1ef25582016-01-21 20:26:12 +0000382 return success;
383}
384
385} // namespace vold
386} // namespace android