8b68026faa
Recent versions of Clang will flag this use of `count` in namespace `std` as ambiguous due to the existence of `std::count`. To remove this problem, we can switch to the commonly used `N` for array sizes. Bug: http://b/155835175 Test: m with aosp_blueline Change-Id: I983180b6e2e94dadb095f531e13ea415468ee104
200 lines
6.9 KiB
C++
200 lines
6.9 KiB
C++
/*
|
|
* Copyright (C) 2016 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef KEYSTORE_KEYSTORE_H_
|
|
#define KEYSTORE_KEYSTORE_H_
|
|
|
|
#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
|
|
#include <keymasterV4_1/Keymaster.h>
|
|
#include <utils/Vector.h>
|
|
|
|
#include <keystore/keymaster_types.h>
|
|
|
|
#include "auth_token_table.h"
|
|
#include "blob.h"
|
|
#include "confirmation_manager.h"
|
|
#include "grant_store.h"
|
|
#include "keymaster_worker.h"
|
|
#include "keystore_keymaster_enforcement.h"
|
|
#include "operation.h"
|
|
#include "user_state.h"
|
|
|
|
#include <array>
|
|
#include <optional>
|
|
#include <tuple>
|
|
|
|
namespace keystore {
|
|
|
|
using ::android::sp;
|
|
using keymaster::support::Keymaster;
|
|
|
|
template <typename T, size_t count> class Devices : public std::array<T, count> {
|
|
public:
|
|
T& operator[](SecurityLevel secLevel) {
|
|
static_assert(uint32_t(SecurityLevel::SOFTWARE) == 0 &&
|
|
uint32_t(SecurityLevel::TRUSTED_ENVIRONMENT) == 1 &&
|
|
uint32_t(SecurityLevel::STRONGBOX) == 2,
|
|
"Numeric values of security levels have changed");
|
|
return std::array<T, count>::at(static_cast<uint32_t>(secLevel));
|
|
}
|
|
T operator[](SecurityLevel secLevel) const {
|
|
if (static_cast<uint32_t>(secLevel) > static_cast<uint32_t>(SecurityLevel::STRONGBOX)) {
|
|
LOG(ERROR) << "Invalid security level requested";
|
|
return {};
|
|
}
|
|
return (*const_cast<Devices*>(this))[secLevel];
|
|
}
|
|
};
|
|
|
|
} // namespace keystore
|
|
|
|
namespace std {
|
|
template <typename T, size_t N> struct tuple_size<keystore::Devices<T, N>> {
|
|
public:
|
|
static constexpr size_t value = std::tuple_size<std::array<T, N>>::value;
|
|
};
|
|
} // namespace std
|
|
|
|
namespace keystore {
|
|
|
|
using KeymasterWorkers = Devices<std::shared_ptr<KeymasterWorker>, 3>;
|
|
using KeymasterDevices = Devices<sp<Keymaster>, 3>;
|
|
|
|
class KeyStore : public ::android::IBinder::DeathRecipient {
|
|
public:
|
|
KeyStore(const KeymasterDevices& kmDevices,
|
|
SecurityLevel minimalAllowedSecurityLevelForNewKeys);
|
|
~KeyStore();
|
|
|
|
std::shared_ptr<KeymasterWorker> getDevice(SecurityLevel securityLevel) const {
|
|
return mKmDevices[securityLevel];
|
|
}
|
|
|
|
std::shared_ptr<KeymasterWorker> getFallbackDevice() const {
|
|
// we only return the fallback device if the creation of new fallback key blobs is
|
|
// allowed. (also see getDevice below)
|
|
if (mAllowNewFallback) {
|
|
return mKmDevices[SecurityLevel::SOFTWARE];
|
|
} else {
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
std::shared_ptr<KeymasterWorker> getDevice(const Blob& blob) {
|
|
return mKmDevices[blob.getSecurityLevel()];
|
|
}
|
|
|
|
ResponseCode initialize();
|
|
|
|
State getState(uid_t userId) { return mUserStateDB.getUserState(userId)->getState(); }
|
|
|
|
ResponseCode initializeUser(const android::String8& pw, uid_t userId);
|
|
|
|
ResponseCode copyMasterKey(uid_t srcUser, uid_t dstUser);
|
|
ResponseCode writeMasterKey(const android::String8& pw, uid_t userId);
|
|
ResponseCode readMasterKey(const android::String8& pw, uid_t userId);
|
|
|
|
LockedKeyBlobEntry getLockedBlobEntryIfNotExists(const std::string& alias, uid_t uid);
|
|
std::optional<KeyBlobEntry> getBlobEntryIfExists(const std::string& alias, uid_t uid);
|
|
LockedKeyBlobEntry getLockedBlobEntryIfExists(const std::string& alias, uid_t uid);
|
|
/*
|
|
* Delete entries owned by userId. If keepUnencryptedEntries is true
|
|
* then only encrypted entries will be removed, otherwise all entries will
|
|
* be removed.
|
|
*/
|
|
void resetUser(uid_t userId, bool keepUnenryptedEntries);
|
|
bool isEmpty(uid_t userId) const;
|
|
|
|
void lock(uid_t userId);
|
|
|
|
std::tuple<ResponseCode, Blob, Blob> get(const LockedKeyBlobEntry& blobfile);
|
|
ResponseCode put(const LockedKeyBlobEntry& blobfile, Blob keyBlob, Blob characteristicsBlob);
|
|
ResponseCode del(const LockedKeyBlobEntry& blobfile);
|
|
|
|
std::string addGrant(const LockedKeyBlobEntry& blobfile, uid_t granteeUid);
|
|
bool removeGrant(const LockedKeyBlobEntry& blobfile, const uid_t granteeUid);
|
|
void removeAllGrantsToUid(const uid_t granteeUid);
|
|
|
|
ResponseCode importKey(const uint8_t* key, size_t keyLen, const LockedKeyBlobEntry& blobfile,
|
|
uid_t userId, int32_t flags);
|
|
|
|
bool isHardwareBacked(const android::String16& keyType) const;
|
|
|
|
std::tuple<ResponseCode, Blob, Blob, LockedKeyBlobEntry>
|
|
getKeyForName(const android::String8& keyName, const uid_t uid, const BlobType type);
|
|
|
|
void binderDied(const ::android::wp<IBinder>& who) override;
|
|
|
|
UserStateDB& getUserStateDB() { return mUserStateDB; }
|
|
AuthTokenTable& getAuthTokenTable() { return mAuthTokenTable; }
|
|
KeystoreKeymasterEnforcement& getEnforcementPolicy() { return mEnforcementPolicy; }
|
|
ConfirmationManager& getConfirmationManager() { return *mConfirmationManager; }
|
|
|
|
void addOperationDevice(sp<IBinder> token, std::shared_ptr<KeymasterWorker> dev) {
|
|
std::lock_guard<std::mutex> lock(operationDeviceMapMutex_);
|
|
operationDeviceMap_.emplace(std::move(token), std::move(dev));
|
|
}
|
|
std::shared_ptr<KeymasterWorker> getOperationDevice(const sp<IBinder>& token) {
|
|
std::lock_guard<std::mutex> lock(operationDeviceMapMutex_);
|
|
auto it = operationDeviceMap_.find(token);
|
|
if (it != operationDeviceMap_.end()) {
|
|
return it->second;
|
|
}
|
|
return {};
|
|
}
|
|
void removeOperationDevice(const sp<IBinder>& token) {
|
|
std::lock_guard<std::mutex> lock(operationDeviceMapMutex_);
|
|
operationDeviceMap_.erase(token);
|
|
}
|
|
|
|
private:
|
|
static const char* kOldMasterKey;
|
|
static const char* kMetaDataFile;
|
|
static const android::String16 kRsaKeyType;
|
|
static const android::String16 kEcKeyType;
|
|
|
|
KeymasterWorkers mKmDevices;
|
|
|
|
bool mAllowNewFallback;
|
|
|
|
UserStateDB mUserStateDB;
|
|
AuthTokenTable mAuthTokenTable;
|
|
KeystoreKeymasterEnforcement mEnforcementPolicy;
|
|
sp<ConfirmationManager> mConfirmationManager;
|
|
|
|
::keystore::GrantStore mGrants;
|
|
|
|
typedef struct { uint32_t version; } keystore_metadata_t;
|
|
|
|
keystore_metadata_t mMetaData;
|
|
|
|
/**
|
|
* Upgrade the key from the current version to whatever is newest.
|
|
*/
|
|
bool upgradeBlob(Blob* blob, const uint8_t oldVersion);
|
|
|
|
void readMetaData();
|
|
void writeMetaData();
|
|
|
|
bool upgradeKeystore();
|
|
|
|
std::mutex operationDeviceMapMutex_;
|
|
std::map<sp<IBinder>, std::shared_ptr<KeymasterWorker>> operationDeviceMap_;
|
|
};
|
|
|
|
} // namespace keystore
|
|
|
|
#endif // KEYSTORE_KEYSTORE_H_
|