1a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root/*
2c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden * Copyright (C) 2016 The Android Open Source Project
3a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root *
4a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * Licensed under the Apache License, Version 2.0 (the "License");
5a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * you may not use this file except in compliance with the License.
6a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * You may obtain a copy of the License at
7a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root *
8a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root *      http://www.apache.org/licenses/LICENSE-2.0
9a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root *
10a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * Unless required by applicable law or agreed to in writing, software
11a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * distributed under the License is distributed on an "AS IS" BASIS,
12a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * See the License for the specific language governing permissions and
14a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * limitations under the License.
15a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root */
16a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
17c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis#define LOG_TAG "keystore"
18c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis
19c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden#include "keystore.h"
2007438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root
21a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <dirent.h>
22a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <fcntl.h>
2370e3a86abd2c412d602a018967c01c177eb6cf4eKenny Root
24c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden#include <openssl/bio.h>
2517208e0de5a42722901d803118745cca25fd10c1Kenny Root
26c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden#include <utils/String16.h>
2770e3a86abd2c412d602a018967c01c177eb6cf4eKenny Root
2807438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root#include <keystore/IKeystoreService.h>
29822c3a99d930e9299e2fad2fb3e0ff91b119b95aKenny Root
30c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
31c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis
32c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden#include "keystore_utils.h"
33c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden#include "permissions.h"
34c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis#include <keystore/keystore_hidl_support.h>
35822c3a99d930e9299e2fad2fb3e0ff91b119b95aKenny Root
36c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenconst char* KeyStore::sOldMasterKey = ".masterkey";
37c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenconst char* KeyStore::sMetaDataFile = ".metadata";
38822c3a99d930e9299e2fad2fb3e0ff91b119b95aKenny Root
39c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenconst android::String16 KeyStore::sRSAKeyType("RSA");
4070e3a86abd2c412d602a018967c01c177eb6cf4eKenny Root
41c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskisusing namespace keystore;
42c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis
43e8ba1802a649ada4cea78af133ab4fb549eb57f5Janis DanisevskisKeyStore::KeyStore(Entropy* entropy, const km_device_t& device, const km_device_t& fallback,
44e8ba1802a649ada4cea78af133ab4fb549eb57f5Janis Danisevskis                   bool allowNewFallback)
45e8ba1802a649ada4cea78af133ab4fb549eb57f5Janis Danisevskis    : mEntropy(entropy), mDevice(device), mFallbackDevice(fallback),
46e8ba1802a649ada4cea78af133ab4fb549eb57f5Janis Danisevskis      mAllowNewFallback(allowNewFallback) {
47c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    memset(&mMetaData, '\0', sizeof(mMetaData));
48c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
4955268b5b037a8c3537602b1073ad624455d3672dShawn Willden
50c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenKeyStore::~KeyStore() {
51c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    for (android::Vector<grant_t*>::iterator it(mGrants.begin()); it != mGrants.end(); it++) {
52c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        delete *it;
5370e3a86abd2c412d602a018967c01c177eb6cf4eKenny Root    }
54c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    mGrants.clear();
5570e3a86abd2c412d602a018967c01c177eb6cf4eKenny Root
56c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    for (android::Vector<UserState*>::iterator it(mMasterKeys.begin()); it != mMasterKeys.end();
57c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden         it++) {
58c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        delete *it;
5955268b5b037a8c3537602b1073ad624455d3672dShawn Willden    }
60c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    mMasterKeys.clear();
61c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
6255268b5b037a8c3537602b1073ad624455d3672dShawn Willden
63c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode KeyStore::initialize() {
64c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    readMetaData();
65c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (upgradeKeystore()) {
66c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        writeMetaData();
6755268b5b037a8c3537602b1073ad624455d3672dShawn Willden    }
6855268b5b037a8c3537602b1073ad624455d3672dShawn Willden
69c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    return ResponseCode::NO_ERROR;
70c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
7155268b5b037a8c3537602b1073ad624455d3672dShawn Willden
72c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode KeyStore::initializeUser(const android::String8& pw, uid_t userId) {
73c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    UserState* userState = getUserState(userId);
74c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return userState->initialize(pw, mEntropy);
7555268b5b037a8c3537602b1073ad624455d3672dShawn Willden}
7655268b5b037a8c3537602b1073ad624455d3672dShawn Willden
77c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode KeyStore::copyMasterKey(uid_t srcUser, uid_t dstUser) {
78c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    UserState* userState = getUserState(dstUser);
79c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    UserState* initState = getUserState(srcUser);
80c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return userState->copyMasterKey(initState);
81c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
8255268b5b037a8c3537602b1073ad624455d3672dShawn Willden
83c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode KeyStore::writeMasterKey(const android::String8& pw, uid_t userId) {
84c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    UserState* userState = getUserState(userId);
85c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return userState->writeMasterKey(pw, mEntropy);
86c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
8755268b5b037a8c3537602b1073ad624455d3672dShawn Willden
88c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode KeyStore::readMasterKey(const android::String8& pw, uid_t userId) {
89c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    UserState* userState = getUserState(userId);
90c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return userState->readMasterKey(pw, mEntropy);
91c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
9270e3a86abd2c412d602a018967c01c177eb6cf4eKenny Root
93c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden/* Here is the encoding of keys. This is necessary in order to allow arbitrary
94c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden * characters in keys. Characters in [0-~] are not encoded. Others are encoded
95c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden * into two bytes. The first byte is one of [+-.] which represents the first
96c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden * two bits of the character. The second byte encodes the rest of the bits into
97c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden * [0-o]. Therefore in the worst case the length of a key gets doubled. Note
98c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden * that Base64 cannot be used here due to the need of prefix match on keys. */
9955268b5b037a8c3537602b1073ad624455d3672dShawn Willden
100c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenstatic size_t encode_key_length(const android::String8& keyName) {
101c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    const uint8_t* in = reinterpret_cast<const uint8_t*>(keyName.string());
102c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    size_t length = keyName.length();
103c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    for (int i = length; i > 0; --i, ++in) {
104c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (*in < '0' || *in > '~') {
105c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            ++length;
10655268b5b037a8c3537602b1073ad624455d3672dShawn Willden        }
107bd07a239085228c25898bc6cdece8b1b8758df83Chad Brubaker    }
108c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return length;
10955268b5b037a8c3537602b1073ad624455d3672dShawn Willden}
11055268b5b037a8c3537602b1073ad624455d3672dShawn Willden
111c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenstatic int encode_key(char* out, const android::String8& keyName) {
112c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    const uint8_t* in = reinterpret_cast<const uint8_t*>(keyName.string());
113c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    size_t length = keyName.length();
114c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    for (int i = length; i > 0; --i, ++in, ++out) {
115c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (*in < '0' || *in > '~') {
116c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            *out = '+' + (*in >> 6);
117c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            *++out = '0' + (*in & 0x3F);
118c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            ++length;
119c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        } else {
120c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            *out = *in;
121c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        }
12255268b5b037a8c3537602b1073ad624455d3672dShawn Willden    }
123c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    *out = '\0';
124c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return length;
12570e3a86abd2c412d602a018967c01c177eb6cf4eKenny Root}
12670e3a86abd2c412d602a018967c01c177eb6cf4eKenny Root
1270ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestroandroid::String8 KeyStore::getKeyName(const android::String8& keyName, const BlobType type) {
128cfd95aeb641d9adbfc8e8466dda952a5f7a3fe3fBin Chen    std::vector<char> encoded(encode_key_length(keyName) + 1);  // add 1 for null char
129cfd95aeb641d9adbfc8e8466dda952a5f7a3fe3fBin Chen    encode_key(encoded.data(), keyName);
1300ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro    if (type == TYPE_KEY_CHARACTERISTICS) {
1319c28dd5f2797510c3da719144247e867c58c6e18Tucker Sylvestro        return android::String8::format(".chr_%s", encoded.data());
1320ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro    } else {
1339c28dd5f2797510c3da719144247e867c58c6e18Tucker Sylvestro        return android::String8(encoded.data());
1340ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro    }
135fc18edcdfe2f7774e621030d51338f3216170b97Chad Brubaker}
136fc18edcdfe2f7774e621030d51338f3216170b97Chad Brubaker
1370ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestroandroid::String8 KeyStore::getKeyNameForUid(
1380ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro    const android::String8& keyName, uid_t uid, const BlobType type) {
139cfd95aeb641d9adbfc8e8466dda952a5f7a3fe3fBin Chen    std::vector<char> encoded(encode_key_length(keyName) + 1);  // add 1 for null char
140cfd95aeb641d9adbfc8e8466dda952a5f7a3fe3fBin Chen    encode_key(encoded.data(), keyName);
1410ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro    if (type == TYPE_KEY_CHARACTERISTICS) {
1429c28dd5f2797510c3da719144247e867c58c6e18Tucker Sylvestro        return android::String8::format(".%u_chr_%s", uid, encoded.data());
1430ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro    } else {
1449c28dd5f2797510c3da719144247e867c58c6e18Tucker Sylvestro        return android::String8::format("%u_%s", uid, encoded.data());
1450ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro    }
14670e3a86abd2c412d602a018967c01c177eb6cf4eKenny Root}
14770e3a86abd2c412d602a018967c01c177eb6cf4eKenny Root
1480ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestroandroid::String8 KeyStore::getKeyNameForUidWithDir(
1490ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro    const android::String8& keyName, uid_t uid, const BlobType type) {
150cfd95aeb641d9adbfc8e8466dda952a5f7a3fe3fBin Chen    std::vector<char> encoded(encode_key_length(keyName) + 1);  // add 1 for null char
151cfd95aeb641d9adbfc8e8466dda952a5f7a3fe3fBin Chen    encode_key(encoded.data(), keyName);
1520ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro
1530ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro    if (type == TYPE_KEY_CHARACTERISTICS) {
1540ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro        return android::String8::format("%s/.%u_chr_%s", getUserStateByUid(uid)->getUserDirName(),
1559c28dd5f2797510c3da719144247e867c58c6e18Tucker Sylvestro                                        uid, encoded.data());
1560ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro    } else {
1570ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro        return android::String8::format("%s/%u_%s", getUserStateByUid(uid)->getUserDirName(), uid,
1589c28dd5f2797510c3da719144247e867c58c6e18Tucker Sylvestro                                        encoded.data());
1590ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro    }
16055268b5b037a8c3537602b1073ad624455d3672dShawn Willden}
16155268b5b037a8c3537602b1073ad624455d3672dShawn Willden
162c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenvoid KeyStore::resetUser(uid_t userId, bool keepUnenryptedEntries) {
163c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    android::String8 prefix("");
164c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    android::Vector<android::String16> aliases;
165c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    UserState* userState = getUserState(userId);
166c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    if (list(prefix, &aliases, userId) != ResponseCode::NO_ERROR) {
167c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return;
168c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
169c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    for (uint32_t i = 0; i < aliases.size(); i++) {
170c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        android::String8 filename(aliases[i]);
171c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        filename = android::String8::format("%s/%s", userState->getUserDirName(),
1720ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro                                            getKeyName(filename, TYPE_ANY).string());
173c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        bool shouldDelete = true;
174c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (keepUnenryptedEntries) {
175c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            Blob blob;
176c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            ResponseCode rc = get(filename, &blob, ::TYPE_ANY, userId);
177c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
178d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden            switch (rc) {
179d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden            case ResponseCode::SYSTEM_ERROR:
180d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden            case ResponseCode::VALUE_CORRUPTED:
181d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden                // If we can't read blobs, delete them.
182d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden                shouldDelete = true;
183d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden                break;
184d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden
185d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden            case ResponseCode::NO_ERROR:
186d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden            case ResponseCode::LOCKED:
187d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden                // Delete encrypted blobs but keep unencrypted blobs and super-encrypted blobs.  We
188d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden                // need to keep super-encrypted blobs so we can report that the user is
189d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden                // unauthenticated if a caller tries to use them, rather than reporting that they
190d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden                // don't exist.
191d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden                shouldDelete = blob.isEncrypted();
192d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden                break;
193d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden
194d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden            default:
195d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden                ALOGE("Got unexpected return code %d from KeyStore::get()", rc);
196d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden                // This shouldn't happen.  To be on the safe side, delete it.
197d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden                shouldDelete = true;
198d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden                break;
199d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden            }
200c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        }
201c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (shouldDelete) {
202c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            del(filename, ::TYPE_ANY, userId);
2030ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro
2040ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro            // del() will fail silently if no cached characteristics are present for this alias.
2050ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro            android::String8 chr_filename(aliases[i]);
2060ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro            chr_filename = android::String8::format("%s/%s", userState->getUserDirName(),
2070ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro                                            getKeyName(chr_filename,
2080ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro                                                TYPE_KEY_CHARACTERISTICS).string());
2090ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro            del(chr_filename, ::TYPE_KEY_CHARACTERISTICS, userId);
210c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        }
211c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
212c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (!userState->deleteMasterKey()) {
213c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGE("Failed to delete user %d's master key", userId);
214c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
215c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (!keepUnenryptedEntries) {
216c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (!userState->reset()) {
217c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            ALOGE("Failed to remove user %d's directory", userId);
218c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        }
219eaabae9bf8ff0873b0ece2a835f71ee6c6b49437Riley Spahn    }
220eaabae9bf8ff0873b0ece2a835f71ee6c6b49437Riley Spahn}
221eaabae9bf8ff0873b0ece2a835f71ee6c6b49437Riley Spahn
222c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenbool KeyStore::isEmpty(uid_t userId) const {
223c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    const UserState* userState = getUserState(userId);
224c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (userState == NULL) {
225c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return true;
226e46b855e51233a33880e35eff9553550dc797754William Roberts    }
227e46b855e51233a33880e35eff9553550dc797754William Roberts
228c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    DIR* dir = opendir(userState->getUserDirName());
229c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (!dir) {
230eaabae9bf8ff0873b0ece2a835f71ee6c6b49437Riley Spahn        return true;
231eaabae9bf8ff0873b0ece2a835f71ee6c6b49437Riley Spahn    }
232eaabae9bf8ff0873b0ece2a835f71ee6c6b49437Riley Spahn
233c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    bool result = true;
234c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    struct dirent* file;
235c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    while ((file = readdir(dir)) != NULL) {
236c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // We only care about files.
237c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (file->d_type != DT_REG) {
238c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            continue;
239c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        }
240eaabae9bf8ff0873b0ece2a835f71ee6c6b49437Riley Spahn
241c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // Skip anything that starts with a "."
242c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (file->d_name[0] == '.') {
243c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            continue;
244c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        }
245eaabae9bf8ff0873b0ece2a835f71ee6c6b49437Riley Spahn
246c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        result = false;
247c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        break;
248eaabae9bf8ff0873b0ece2a835f71ee6c6b49437Riley Spahn    }
249c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    closedir(dir);
250c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return result;
251c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
25266dbf67dd65b4808a15ef64f0ffde1275bdd58a9Nick Kralevich
253c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenvoid KeyStore::lock(uid_t userId) {
254c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    UserState* userState = getUserState(userId);
255c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    userState->zeroizeMasterKeysInMemory();
256c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    userState->setState(STATE_LOCKED);
257eaabae9bf8ff0873b0ece2a835f71ee6c6b49437Riley Spahn}
258eaabae9bf8ff0873b0ece2a835f71ee6c6b49437Riley Spahn
259c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode KeyStore::get(const char* filename, Blob* keyBlob, const BlobType type, uid_t userId) {
260c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    UserState* userState = getUserState(userId);
261c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    ResponseCode rc =
262c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        keyBlob->readBlob(filename, userState->getDecryptionKey(), userState->getState());
263c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    if (rc != ResponseCode::NO_ERROR) {
264c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return rc;
265655b958eb2180c7c06889f83f606d23421bf038cKenny Root    }
266655b958eb2180c7c06889f83f606d23421bf038cKenny Root
267c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    const uint8_t version = keyBlob->getVersion();
268c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (version < CURRENT_BLOB_VERSION) {
269c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        /* If we upgrade the key, we need to write it to disk again. Then
270c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden         * it must be read it again since the blob is encrypted each time
271c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden         * it's written.
272c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden         */
273c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (upgradeBlob(filename, keyBlob, version, type, userId)) {
274c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis            if ((rc = this->put(filename, keyBlob, userId)) != ResponseCode::NO_ERROR ||
275c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                (rc = keyBlob->readBlob(filename, userState->getDecryptionKey(),
276c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis                                        userState->getState())) != ResponseCode::NO_ERROR) {
277c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                return rc;
278c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            }
27907438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root        }
28007438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root    }
28107438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root
282c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    /*
283c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis     * This will upgrade software-backed keys to hardware-backed keys.
284c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden     */
285c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    if (rc == ResponseCode::NO_ERROR && type == TYPE_KEY_PAIR && keyBlob->isFallback()) {
286c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ResponseCode imported =
287c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            importKey(keyBlob->getValue(), keyBlob->getLength(), filename, userId,
288c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                      keyBlob->isEncrypted() ? KEYSTORE_FLAG_ENCRYPTED : KEYSTORE_FLAG_NONE);
28907438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root
290d5a24e6745eb552c137cfdbb49e09e3db5701ad1Shawn Willden        // The HAL allowed the import, reget the key to have the "fresh" version.
291c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        if (imported == ResponseCode::NO_ERROR) {
292c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            rc = get(filename, keyBlob, TYPE_KEY_PAIR, userId);
29307438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root        }
29407438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root    }
29507438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root
296c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    // Keymaster 0.3 keys are valid keymaster 1.0 keys, so silently upgrade.
297c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (keyBlob->getType() == TYPE_KEY_PAIR) {
298c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        keyBlob->setType(TYPE_KEYMASTER_10);
299c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        rc = this->put(filename, keyBlob, userId);
3009489b7905acfb27a99dd505364a715f4cf2ab5e6Chad Brubaker    }
301c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
302c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (type != TYPE_ANY && keyBlob->getType() != type) {
303c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGW("key found but type doesn't match: %d vs %d", keyBlob->getType(), type);
304c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::KEY_NOT_FOUND;
305494689083467ec372a58f094f041c8f102f39393Kenny Root    }
306494689083467ec372a58f094f041c8f102f39393Kenny Root
307c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return rc;
308494689083467ec372a58f094f041c8f102f39393Kenny Root}
309494689083467ec372a58f094f041c8f102f39393Kenny Root
310c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode KeyStore::put(const char* filename, Blob* keyBlob, uid_t userId) {
311c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    UserState* userState = getUserState(userId);
312c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return keyBlob->writeBlob(filename, userState->getEncryptionKey(), userState->getState(),
313c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                              mEntropy);
314c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
315a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
316c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode KeyStore::del(const char* filename, const BlobType type, uid_t userId) {
317c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    Blob keyBlob;
318c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    ResponseCode rc = get(filename, &keyBlob, type, userId);
319c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    if (rc == ResponseCode::VALUE_CORRUPTED) {
320c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // The file is corrupt, the best we can do is rm it.
321c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return (unlink(filename) && errno != ENOENT) ?
322c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis                ResponseCode::SYSTEM_ERROR : ResponseCode::NO_ERROR;
323c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
324c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    if (rc != ResponseCode::NO_ERROR) {
325c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return rc;
326655b958eb2180c7c06889f83f606d23421bf038cKenny Root    }
327655b958eb2180c7c06889f83f606d23421bf038cKenny Root
32869c434aee7a02f66e9a7bcf8ce014f8c48066eb6Janis Danisevskis    auto& dev = getDevice(keyBlob);
32969c434aee7a02f66e9a7bcf8ce014f8c48066eb6Janis Danisevskis
330c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    if (keyBlob.getType() == ::TYPE_KEY_PAIR || keyBlob.getType() == ::TYPE_KEYMASTER_10) {
33169c434aee7a02f66e9a7bcf8ce014f8c48066eb6Janis Danisevskis        auto ret = KS_HANDLE_HIDL_ERROR(dev->deleteKey(blob2hidlVec(keyBlob)));
332c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis
333c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // A device doesn't have to implement delete_key.
334c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        if (ret != ErrorCode::OK && ret != ErrorCode::UNIMPLEMENTED)
335c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis            return ResponseCode::SYSTEM_ERROR;
336c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
337c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
338c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    return (unlink(filename) && errno != ENOENT) ?
339c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis            ResponseCode::SYSTEM_ERROR : ResponseCode::NO_ERROR;
34070e3a86abd2c412d602a018967c01c177eb6cf4eKenny Root}
34170e3a86abd2c412d602a018967c01c177eb6cf4eKenny Root
34207438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root/*
34307438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root * Converts from the "escaped" format on disk to actual name.
34407438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root * This will be smaller than the input string.
34507438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root *
34607438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root * Characters that should combine with the next at the end will be truncated.
34707438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root */
34807438c8d7256d3788dac323b4d0055f201e0bec9Kenny Rootstatic size_t decode_key_length(const char* in, size_t length) {
34907438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root    size_t outLength = 0;
35007438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root
35107438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root    for (const char* end = in + length; in < end; in++) {
35207438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root        /* This combines with the next character. */
35307438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root        if (*in < '0' || *in > '~') {
35407438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root            continue;
35507438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root        }
35607438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root
35707438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root        outLength++;
35807438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root    }
35907438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root    return outLength;
36007438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root}
36107438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root
36207438c8d7256d3788dac323b4d0055f201e0bec9Kenny Rootstatic void decode_key(char* out, const char* in, size_t length) {
36307438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root    for (const char* end = in + length; in < end; in++) {
36407438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root        if (*in < '0' || *in > '~') {
36507438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root            /* Truncate combining characters at the end. */
36607438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root            if (in + 1 >= end) {
36707438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root                break;
36807438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root            }
36907438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root
37007438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root            *out = (*in++ - '+') << 6;
37107438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root            *out++ |= (*in - '0') & 0x3F;
372a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        } else {
37307438c8d7256d3788dac323b4d0055f201e0bec9Kenny Root            *out++ = *in;
374a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
375a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
376a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    *out = '\0';
377a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
378a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
379c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode KeyStore::list(const android::String8& prefix,
380c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                            android::Vector<android::String16>* matches, uid_t userId) {
381c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
382c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    UserState* userState = getUserState(userId);
383c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    size_t n = prefix.length();
384c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
385c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    DIR* dir = opendir(userState->getUserDirName());
386c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (!dir) {
387c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGW("can't open directory for user: %s", strerror(errno));
388c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
389a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
390a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
391c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    struct dirent* file;
392c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    while ((file = readdir(dir)) != NULL) {
393c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // We only care about files.
394c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (file->d_type != DT_REG) {
395c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            continue;
396c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        }
397c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
398c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // Skip anything that starts with a "."
399c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (file->d_name[0] == '.') {
400c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            continue;
401c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        }
402c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
403c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (!strncmp(prefix.string(), file->d_name, n)) {
404c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            const char* p = &file->d_name[n];
405c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            size_t plen = strlen(p);
406c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
407c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            size_t extra = decode_key_length(p, plen);
408c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            char* match = (char*)malloc(extra + 1);
409c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            if (match != NULL) {
410c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                decode_key(match, p, plen);
411c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                matches->push(android::String16(match, extra));
412c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                free(match);
413c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            } else {
414c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                ALOGW("could not allocate match of size %zd", extra);
415c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            }
416a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
417a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
418c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    closedir(dir);
419c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    return ResponseCode::NO_ERROR;
420a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
421a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
422c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenvoid KeyStore::addGrant(const char* filename, uid_t granteeUid) {
423c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    const grant_t* existing = getGrant(filename, granteeUid);
424c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (existing == NULL) {
425c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        grant_t* grant = new grant_t;
426c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        grant->uid = granteeUid;
427c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        grant->filename = reinterpret_cast<const uint8_t*>(strdup(filename));
428c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        mGrants.add(grant);
429a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
430c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
431a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
432c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenbool KeyStore::removeGrant(const char* filename, uid_t granteeUid) {
433c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    for (android::Vector<grant_t*>::iterator it(mGrants.begin()); it != mGrants.end(); it++) {
434c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        grant_t* grant = *it;
435c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (grant->uid == granteeUid &&
436c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            !strcmp(reinterpret_cast<const char*>(grant->filename), filename)) {
437c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            mGrants.erase(it);
438c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            return true;
439a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
440a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
441c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return false;
442c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
443a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
444c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode KeyStore::importKey(const uint8_t* key, size_t keyLen, const char* filename,
445c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                                 uid_t userId, int32_t flags) {
446c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &key, keyLen));
447c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (!pkcs8.get()) {
448c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
449c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
450c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
451c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (!pkey.get()) {
452c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
453c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
454c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    int type = EVP_PKEY_type(pkey->type);
455c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    AuthorizationSet params;
456c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    add_legacy_key_authorizations(type, &params);
457c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    switch (type) {
458c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    case EVP_PKEY_RSA:
459c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        params.push_back(TAG_ALGORITHM, Algorithm::RSA);
460c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        break;
461c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    case EVP_PKEY_EC:
462c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        params.push_back(TAG_ALGORITHM, Algorithm::EC);
463c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        break;
464c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    default:
465c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGW("Unsupported key type %d", type);
466c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
467c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    }
468a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
469c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    AuthorizationSet opParams(params);
470c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    hidl_vec<uint8_t> blob;
471c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis
472c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    ErrorCode error;
473c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    auto hidlCb = [&] (ErrorCode ret, const hidl_vec<uint8_t>& keyBlob,
474c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis            const KeyCharacteristics& /* ignored */) {
475c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        error = ret;
476c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        if (error != ErrorCode::OK) return;
477c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        blob = keyBlob;
478c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    };
479c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    auto input = blob2hidlVec(key, keyLen);
480c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis
481c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    ErrorCode rc = KS_HANDLE_HIDL_ERROR(
482c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis            mDevice->importKey(params.hidl_data(), KeyFormat::PKCS8, input, hidlCb));
483c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    if (rc != ErrorCode::OK) return ResponseCode::SYSTEM_ERROR;
484c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    if (error != ErrorCode::OK) {
485c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        ALOGE("Keymaster error %d importing key pair", error);
486c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
487c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
488a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
489c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    Blob keyBlob(&blob[0], blob.size(), NULL, 0, TYPE_KEYMASTER_10);
490822c3a99d930e9299e2fad2fb3e0ff91b119b95aKenny Root
491c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
492c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    keyBlob.setFallback(false);
493f9119d6414f43ef669d64e9e53feb043eda49cf3Kenny Root
494c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return put(filename, &keyBlob, userId);
495c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
496a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
497c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskisbool KeyStore::isHardwareBacked(const android::String16& /*keyType*/) const {
498b8550a0929286bd8b91135c2beea1f61c01a441fShawn Willden    using ::android::hardware::hidl_string;
499c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (mDevice == NULL) {
500c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGW("can't get keymaster device");
501c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return false;
502a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
503e2b6caff1a8265d7c84e4532330c4968d49d9296Janis Danisevskis
504e2b6caff1a8265d7c84e4532330c4968d49d9296Janis Danisevskis    bool isSecure = false;
505b8550a0929286bd8b91135c2beea1f61c01a441fShawn Willden    auto hidlcb = [&] (bool _isSecure, bool, bool, bool, bool, const hidl_string&,
506b8550a0929286bd8b91135c2beea1f61c01a441fShawn Willden                       const hidl_string&) {
507e2b6caff1a8265d7c84e4532330c4968d49d9296Janis Danisevskis        isSecure = _isSecure;
508e2b6caff1a8265d7c84e4532330c4968d49d9296Janis Danisevskis    };
509e2b6caff1a8265d7c84e4532330c4968d49d9296Janis Danisevskis    auto rc = mDevice->getHardwareFeatures(hidlcb);
510e2b6caff1a8265d7c84e4532330c4968d49d9296Janis Danisevskis    if (!rc.isOk()) {
511e2b6caff1a8265d7c84e4532330c4968d49d9296Janis Danisevskis        ALOGE("Communication with keymaster HAL failed while retrieving hardware features (%s)",
512e2b6caff1a8265d7c84e4532330c4968d49d9296Janis Danisevskis                rc.description().c_str());
513e2b6caff1a8265d7c84e4532330c4968d49d9296Janis Danisevskis        return false;
514e2b6caff1a8265d7c84e4532330c4968d49d9296Janis Danisevskis    }
515e2b6caff1a8265d7c84e4532330c4968d49d9296Janis Danisevskis    return isSecure;
516c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
517a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
518c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode KeyStore::getKeyForName(Blob* keyBlob, const android::String8& keyName,
519c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                                     const uid_t uid, const BlobType type) {
5200ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro    android::String8 filepath8(getKeyNameForUidWithDir(keyName, uid, type));
521c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    uid_t userId = get_user_id(uid);
522a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
523c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    ResponseCode responseCode = get(filepath8.string(), keyBlob, type, userId);
524c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    if (responseCode == ResponseCode::NO_ERROR) {
525c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return responseCode;
526a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
527a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
528c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    // If this is one of the legacy UID->UID mappings, use it.
529c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    uid_t euid = get_keystore_euid(uid);
530c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (euid != uid) {
5310ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro        filepath8 = getKeyNameForUidWithDir(keyName, euid, type);
532c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        responseCode = get(filepath8.string(), keyBlob, type, userId);
533c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        if (responseCode == ResponseCode::NO_ERROR) {
534c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            return responseCode;
535c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        }
5365187818895c4c5f650a611c40531b1dff7764c18Kenny Root    }
5375187818895c4c5f650a611c40531b1dff7764c18Kenny Root
538c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    // They might be using a granted key.
5390ab28b78bd06a06a0ffa150cef5876d56212902aTucker Sylvestro    android::String8 filename8 = getKeyName(keyName, type);
540c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    char* end;
541c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    strtoul(filename8.string(), &end, 10);
542c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (end[0] != '_' || end[1] == 0) {
543c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::KEY_NOT_FOUND;
544a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
545c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    filepath8 = android::String8::format("%s/%s", getUserState(userId)->getUserDirName(),
546c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                                         filename8.string());
547c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (!hasGrant(filepath8.string(), uid)) {
548c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return responseCode;
549822c3a99d930e9299e2fad2fb3e0ff91b119b95aKenny Root    }
550822c3a99d930e9299e2fad2fb3e0ff91b119b95aKenny Root
551c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    // It is a granted key. Try to load it.
552c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return get(filepath8.string(), keyBlob, type, userId);
553c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
554f9119d6414f43ef669d64e9e53feb043eda49cf3Kenny Root
555c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenUserState* KeyStore::getUserState(uid_t userId) {
556c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    for (android::Vector<UserState*>::iterator it(mMasterKeys.begin()); it != mMasterKeys.end();
557c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden         it++) {
558c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        UserState* state = *it;
559c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (state->getUserId() == userId) {
560c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            return state;
561f9119d6414f43ef669d64e9e53feb043eda49cf3Kenny Root        }
562f9119d6414f43ef669d64e9e53feb043eda49cf3Kenny Root    }
563f9119d6414f43ef669d64e9e53feb043eda49cf3Kenny Root
564c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    UserState* userState = new UserState(userId);
565c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (!userState->initialize()) {
566c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        /* There's not much we can do if initialization fails. Trying to
567c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden         * unlock the keystore for that user will fail as well, so any
568c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden         * subsequent request for this user will just return SYSTEM_ERROR.
569c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden         */
570c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGE("User initialization failed for %u; subsuquent operations will fail", userId);
57117208e0de5a42722901d803118745cca25fd10c1Kenny Root    }
572c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    mMasterKeys.add(userState);
573c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return userState;
574c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
57517208e0de5a42722901d803118745cca25fd10c1Kenny Root
576c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenUserState* KeyStore::getUserStateByUid(uid_t uid) {
577c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    uid_t userId = get_user_id(uid);
578c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return getUserState(userId);
579c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
580c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
581c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenconst UserState* KeyStore::getUserState(uid_t userId) const {
582c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    for (android::Vector<UserState*>::const_iterator it(mMasterKeys.begin());
583c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden         it != mMasterKeys.end(); it++) {
584c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        UserState* state = *it;
585c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (state->getUserId() == userId) {
586c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            return state;
58717208e0de5a42722901d803118745cca25fd10c1Kenny Root        }
58817208e0de5a42722901d803118745cca25fd10c1Kenny Root    }
58917208e0de5a42722901d803118745cca25fd10c1Kenny Root
590c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return NULL;
591c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
592822c3a99d930e9299e2fad2fb3e0ff91b119b95aKenny Root
593c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenconst UserState* KeyStore::getUserStateByUid(uid_t uid) const {
594c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    uid_t userId = get_user_id(uid);
595c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return getUserState(userId);
596c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
597822c3a99d930e9299e2fad2fb3e0ff91b119b95aKenny Root
598c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenconst grant_t* KeyStore::getGrant(const char* filename, uid_t uid) const {
599c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    for (android::Vector<grant_t*>::const_iterator it(mGrants.begin()); it != mGrants.end(); it++) {
600c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        grant_t* grant = *it;
601c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (grant->uid == uid &&
602c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            !strcmp(reinterpret_cast<const char*>(grant->filename), filename)) {
603c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            return grant;
604c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        }
605822c3a99d930e9299e2fad2fb3e0ff91b119b95aKenny Root    }
606c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return NULL;
607c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
608822c3a99d930e9299e2fad2fb3e0ff91b119b95aKenny Root
609c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenbool KeyStore::upgradeBlob(const char* filename, Blob* blob, const uint8_t oldVersion,
610c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                           const BlobType type, uid_t uid) {
611c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    bool updated = false;
612c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    uint8_t version = oldVersion;
613f9119d6414f43ef669d64e9e53feb043eda49cf3Kenny Root
614c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    /* From V0 -> V1: All old types were unknown */
615c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (version == 0) {
616c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGV("upgrading to version 1 and setting type %d", type);
617a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
618c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        blob->setType(type);
619c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (type == TYPE_KEY_PAIR) {
620c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            importBlobAsKey(blob, filename, uid);
621f9119d6414f43ef669d64e9e53feb043eda49cf3Kenny Root        }
622c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        version = 1;
623c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        updated = true;
624c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
625a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
626c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    /* From V1 -> V2: All old keys were encrypted */
627c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (version == 1) {
628c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGV("upgrading to version 2");
629a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
630c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        blob->setEncrypted(true);
631c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        version = 2;
632c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        updated = true;
633a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
634a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
635c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    /*
636c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden     * If we've updated, set the key blob to the right version
637c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden     * and write it.
638c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden     */
639c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (updated) {
640c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGV("updated and writing file %s", filename);
641c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        blob->setVersion(version);
642c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
643f9119d6414f43ef669d64e9e53feb043eda49cf3Kenny Root
644c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return updated;
645c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
646a9a17eeca2f5d9d3101a7e0bb136360697b6e2f0Chad Brubaker
647c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenstruct BIO_Delete {
648c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    void operator()(BIO* p) const { BIO_free(p); }
649c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden};
650c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdentypedef UniquePtr<BIO, BIO_Delete> Unique_BIO;
651f9119d6414f43ef669d64e9e53feb043eda49cf3Kenny Root
652c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode KeyStore::importBlobAsKey(Blob* blob, const char* filename, uid_t uid) {
653c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    // We won't even write to the blob directly with this BIO, so const_cast is okay.
654c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    Unique_BIO b(BIO_new_mem_buf(const_cast<uint8_t*>(blob->getValue()), blob->getLength()));
655c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (b.get() == NULL) {
656c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGE("Problem instantiating BIO");
657c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
658c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
659a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
660c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    Unique_EVP_PKEY pkey(PEM_read_bio_PrivateKey(b.get(), NULL, NULL, NULL));
661c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (pkey.get() == NULL) {
662c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGE("Couldn't read old PEM file");
663c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
664a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
665a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
666c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    Unique_PKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(pkey.get()));
667c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    int len = i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), NULL);
668c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (len < 0) {
669c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGE("Couldn't measure PKCS#8 length");
670c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
671a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
672a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
673c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    UniquePtr<unsigned char[]> pkcs8key(new unsigned char[len]);
674c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    uint8_t* tmp = pkcs8key.get();
675c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), &tmp) != len) {
676c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGE("Couldn't convert to PKCS#8");
677c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
678a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
679a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
680c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    ResponseCode rc = importKey(pkcs8key.get(), len, filename, get_user_id(uid),
681c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                                blob->isEncrypted() ? KEYSTORE_FLAG_ENCRYPTED : KEYSTORE_FLAG_NONE);
682c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    if (rc != ResponseCode::NO_ERROR) {
683c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return rc;
68470e3a86abd2c412d602a018967c01c177eb6cf4eKenny Root    }
68570e3a86abd2c412d602a018967c01c177eb6cf4eKenny Root
686c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return get(filename, blob, TYPE_KEY_PAIR, uid);
687c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
68896d6d7868303ad87f1f408c40d3c44bcb39f561eChad Brubaker
689c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenvoid KeyStore::readMetaData() {
690c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    int in = TEMP_FAILURE_RETRY(open(sMetaDataFile, O_RDONLY));
691c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (in < 0) {
692c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return;
693a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
694c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    size_t fileLength = readFully(in, (uint8_t*)&mMetaData, sizeof(mMetaData));
695c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (fileLength != sizeof(mMetaData)) {
696c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGI("Metadata file is %zd bytes (%zd experted); upgrade?", fileLength, sizeof(mMetaData));
69779e0f6440aee69659bc01a0669a329dbaeaf471cChad Brubaker    }
698c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    close(in);
699c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
70079e0f6440aee69659bc01a0669a329dbaeaf471cChad Brubaker
701c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenvoid KeyStore::writeMetaData() {
702c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    const char* tmpFileName = ".metadata.tmp";
703c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    int out =
704c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        TEMP_FAILURE_RETRY(open(tmpFileName, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
705c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (out < 0) {
706c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGE("couldn't write metadata file: %s", strerror(errno));
707c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return;
708c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
709c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    size_t fileLength = writeFully(out, (uint8_t*)&mMetaData, sizeof(mMetaData));
710c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (fileLength != sizeof(mMetaData)) {
711c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGI("Could only write %zd bytes to metadata file (%zd expected)", fileLength,
712c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden              sizeof(mMetaData));
713c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
714c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    close(out);
715c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    rename(tmpFileName, sMetaDataFile);
716c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
71779e0f6440aee69659bc01a0669a329dbaeaf471cChad Brubaker
718c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenbool KeyStore::upgradeKeystore() {
719c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    bool upgraded = false;
7204e865753346fc6a075966972a7a98051818859dbRobin Lee
721c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (mMetaData.version == 0) {
722c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        UserState* userState = getUserStateByUid(0);
723a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
724c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // Initialize first so the directory is made.
725c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        userState->initialize();
726a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
727c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // Migrate the old .masterkey file to user 0.
728c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (access(sOldMasterKey, R_OK) == 0) {
729c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            if (rename(sOldMasterKey, userState->getMasterKeyFileName()) < 0) {
730c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                ALOGE("couldn't migrate old masterkey: %s", strerror(errno));
731c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                return false;
732a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            }
733a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
734a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
735c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // Initialize again in case we had a key.
736c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        userState->initialize();
737a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
738c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // Try to migrate existing keys.
739c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        DIR* dir = opendir(".");
740a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (!dir) {
741c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            // Give up now; maybe we can upgrade later.
742c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            ALOGE("couldn't open keystore's directory; something is wrong");
743655b958eb2180c7c06889f83f606d23421bf038cKenny Root            return false;
744655b958eb2180c7c06889f83f606d23421bf038cKenny Root        }
745655b958eb2180c7c06889f83f606d23421bf038cKenny Root
74631e27468b6d822adbd2aec9219a68c206aa6957cKenny Root        struct dirent* file;
747a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        while ((file = readdir(dir)) != NULL) {
748655b958eb2180c7c06889f83f606d23421bf038cKenny Root            // We only care about files.
749655b958eb2180c7c06889f83f606d23421bf038cKenny Root            if (file->d_type != DT_REG) {
750655b958eb2180c7c06889f83f606d23421bf038cKenny Root                continue;
751655b958eb2180c7c06889f83f606d23421bf038cKenny Root            }
752655b958eb2180c7c06889f83f606d23421bf038cKenny Root
753655b958eb2180c7c06889f83f606d23421bf038cKenny Root            // Skip anything that starts with a "."
754655b958eb2180c7c06889f83f606d23421bf038cKenny Root            if (file->d_name[0] == '.') {
755655b958eb2180c7c06889f83f606d23421bf038cKenny Root                continue;
756655b958eb2180c7c06889f83f606d23421bf038cKenny Root            }
757655b958eb2180c7c06889f83f606d23421bf038cKenny Root
758c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            // Find the current file's user.
759c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            char* end;
760c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            unsigned long thisUid = strtoul(file->d_name, &end, 10);
761c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            if (end[0] != '_' || end[1] == 0) {
7624b84fdc21457e16b08dc2738f4744c9ca7f7cc46Robin Lee                continue;
7634b84fdc21457e16b08dc2738f4744c9ca7f7cc46Robin Lee            }
764c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            UserState* otherUser = getUserStateByUid(thisUid);
765c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            if (otherUser->getUserId() != 0) {
766c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                unlinkat(dirfd(dir), file->d_name, 0);
767c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            }
7684b84fdc21457e16b08dc2738f4744c9ca7f7cc46Robin Lee
769c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            // Rename the file into user directory.
770c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            DIR* otherdir = opendir(otherUser->getUserDirName());
771c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            if (otherdir == NULL) {
772c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                ALOGW("couldn't open user directory for rename");
7734b84fdc21457e16b08dc2738f4744c9ca7f7cc46Robin Lee                continue;
7744b84fdc21457e16b08dc2738f4744c9ca7f7cc46Robin Lee            }
775c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            if (renameat(dirfd(dir), file->d_name, dirfd(otherdir), file->d_name) < 0) {
776c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                ALOGW("couldn't rename blob: %s: %s", file->d_name, strerror(errno));
7774b84fdc21457e16b08dc2738f4744c9ca7f7cc46Robin Lee            }
778c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            closedir(otherdir);
7794b84fdc21457e16b08dc2738f4744c9ca7f7cc46Robin Lee        }
7804b84fdc21457e16b08dc2738f4744c9ca7f7cc46Robin Lee        closedir(dir);
781a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
782c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        mMetaData.version = 1;
783c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        upgraded = true;
784a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
785a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
786c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return upgraded;
787a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
788