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, ¶ms); 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