diff options
| author | android-build-team Robot <android-build-team-robot@google.com> | 2017-12-28 08:20:50 +0000 |
|---|---|---|
| committer | android-build-team Robot <android-build-team-robot@google.com> | 2017-12-28 08:20:50 +0000 |
| commit | 7acd97fbede6d0dddbb1c26c40854019928cfa8f (patch) | |
| tree | e0e391613c93947c019e02b85bea7e89688777e4 | |
| parent | 18525f3df56d249d70e65fe4485846b39334d158 (diff) | |
| parent | cb9267dc53cb715c09ef276562dbe88b0d999a8d (diff) | |
Snap for 4519870 from cb9267dc53cb715c09ef276562dbe88b0d999a8d to pi-release
Change-Id: I4075fc39398fb25b6df161e944620a623a318914
36 files changed, 670 insertions, 926 deletions
diff --git a/keystore/Android.bp b/keystore/Android.bp index bfbc72f..de11ec6 100644 --- a/keystore/Android.bp +++ b/keystore/Android.bp @@ -23,6 +23,7 @@ cc_binary { ":IKeyAttestationApplicationIdProvider.aidl", "KeyStore.cpp", "Keymaster3.cpp", + "Keymaster4.cpp", "auth_token_table.cpp", "blob.cpp", "entropy.cpp", @@ -49,6 +50,7 @@ cc_binary { "libhidlbase", "libhidltransport", "libhwbinder", + "libkeymaster4support", "libkeymaster_messages", "libkeymaster_portable", "libkeystore_aidl", @@ -110,6 +112,7 @@ cc_binary { "libchrome", "libhidlbase", "libhwbinder", + "libkeymaster4support", "libkeystore_binder", ], @@ -135,6 +138,7 @@ cc_library_shared { "libhardware", "libhidlbase", "libhwbinder", + "libkeymaster4support", "liblog", "libprotobuf-cpp-lite", "libutils", @@ -144,6 +148,7 @@ cc_library_shared { "libbinder", "libhidlbase", "libhwbinder", + "libkeymaster4support", ], } // Library for keystore clients @@ -152,21 +157,20 @@ cc_library_shared { defaults: ["keystore_defaults"], srcs: [ - "authorization_set.cpp", "keyblob_utils.cpp", "keystore_client.proto", "keystore_client_impl.cpp", "keystore_get.cpp", - "keystore_tags_utils.cpp", ], shared_libs: [ - "android.hardware.keymaster@3.0", + "android.hardware.keymaster@4.0", "libbinder", "libhidlbase", "libhwbinder", - "liblog", + "libkeymaster4support", "libkeystore_aidl", "libkeystore_parcelables", + "liblog", "libprotobuf-cpp-lite", "libutils", ], @@ -181,7 +185,7 @@ cc_library_shared { }, export_include_dirs: ["include"], export_shared_lib_headers: [ - "android.hardware.keymaster@3.0", + "android.hardware.keymaster@4.0", "libbinder", "libhidlbase", "libhwbinder", @@ -217,19 +221,21 @@ cc_library_static { srcs: [ "auth_token_table.cpp", - "authorization_set.cpp", ], + cflags: [ "-O0", ], static_libs: ["libgtest_main"], shared_libs: [ "android.hardware.keymaster@4.0", "libhidlbase", "libhwbinder", + "libkeymaster4support", "libutils", ], export_shared_lib_headers: [ "android.hardware.keymaster@4.0", "libhidlbase", "libhwbinder", + "libkeymaster4support", ], export_include_dirs: ["include"], diff --git a/keystore/KeyStore.cpp b/keystore/KeyStore.cpp index fd5b26d..d9355b9 100644 --- a/keystore/KeyStore.cpp +++ b/keystore/KeyStore.cpp @@ -43,10 +43,26 @@ const android::String16 KeyStore::kEcKeyType("EC"); using android::String8; -KeyStore::KeyStore(Entropy* entropy, const sp<Keymaster>& device, const sp<Keymaster>& fallback, - bool allowNewFallback) - : mEntropy(entropy), mDevice(device), mFallbackDevice(fallback), - mAllowNewFallback(allowNewFallback) { +sp<Keymaster>& KeymasterDevices::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 at(static_cast<uint32_t>(secLevel)); +} + +sp<Keymaster> KeymasterDevices::operator[](SecurityLevel secLevel) const { + if (static_cast<uint32_t>(secLevel) > static_cast<uint32_t>(SecurityLevel::STRONGBOX)) { + LOG(ERROR) << "Invalid security level requested"; + return nullptr; + } + return (*const_cast<KeymasterDevices*>(this))[secLevel]; +} + +KeyStore::KeyStore(Entropy* entropy, const KeymasterDevices& kmDevices, + SecurityLevel minimalAllowedSecurityLevelForNewKeys) + : mEntropy(entropy), mKmDevices(kmDevices), + mAllowNewFallback(minimalAllowedSecurityLevelForNewKeys == SecurityLevel::SOFTWARE) { memset(&mMetaData, '\0', sizeof(mMetaData)); } @@ -359,7 +375,7 @@ ResponseCode KeyStore::del(const char* filename, const BlobType type, uid_t user return rc; } - auto& dev = getDevice(keyBlob); + auto dev = getDevice(keyBlob); if (keyBlob.getType() == ::TYPE_KEY_PAIR || keyBlob.getType() == ::TYPE_KEYMASTER_10) { auto ret = KS_HANDLE_HIDL_ERROR(dev->deleteKey(blob2hidlVec(keyBlob))); @@ -533,8 +549,18 @@ ResponseCode KeyStore::importKey(const uint8_t* key, size_t keyLen, const char* }; auto input = blob2hidlVec(key, keyLen); + SecurityLevel securityLevel = flagsToSecurityLevel(flags); + auto kmDevice = getDevice(securityLevel); + if (!kmDevice) { + // As of this writing the only caller is KeyStore::get in an attempt to import legacy + // software keys. It only ever requests TEE as target which must always be present. + // If we see this error, we probably have a new and unanticipated caller. + ALOGE("No implementation for security level %d. Cannot import key.", securityLevel); + return ResponseCode::SYSTEM_ERROR; + } + ErrorCode rc = KS_HANDLE_HIDL_ERROR( - mDevice->importKey(params.hidl_data(), KeyFormat::PKCS8, input, hidlCb)); + kmDevice->importKey(params.hidl_data(), KeyFormat::PKCS8, input, hidlCb)); if (rc != ErrorCode::OK) return ResponseCode::SYSTEM_ERROR; if (error != ErrorCode::OK) { ALOGE("Keymaster error %d importing key pair", error); @@ -544,25 +570,26 @@ ResponseCode KeyStore::importKey(const uint8_t* key, size_t keyLen, const char* Blob keyBlob(&blob[0], blob.size(), NULL, 0, TYPE_KEYMASTER_10); keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED); - keyBlob.setFallback(false); + keyBlob.setSecurityLevel(securityLevel); return put(filename, &keyBlob, userId); } bool KeyStore::isHardwareBacked(const android::String16& keyType) const { - if (mDevice == NULL) { + // if strongbox device is present TEE must also be present and of sufficiently high version + // to support all keys in hardware + if (getDevice(SecurityLevel::STRONGBOX)) return true; + if (!getDevice(SecurityLevel::TRUSTED_ENVIRONMENT)) { ALOGW("can't get keymaster device"); return false; } - auto version = mDevice->halVersion(); + auto version = getDevice(SecurityLevel::TRUSTED_ENVIRONMENT)->halVersion(); if (version.error != ErrorCode::OK) { ALOGE("Failed to get HAL version info"); return false; } - if (!version.isSecure) return false; - if (keyType == kRsaKeyType) return true; // All versions support RSA return keyType == kEcKeyType && version.supportsEc; } diff --git a/keystore/KeyStore.h b/keystore/KeyStore.h index 60cf56d..cfc5c31 100644 --- a/keystore/KeyStore.h +++ b/keystore/KeyStore.h @@ -21,39 +21,53 @@ #include <utils/Vector.h> +#include <keystore/keymaster_types.h> + #include "Keymaster.h" #include "blob.h" #include "grant_store.h" -#include "include/keystore/keymaster_tags.h" #include "user_state.h" namespace keystore { using ::android::sp; +class KeymasterDevices : public std::array<sp<Keymaster>, 3> { + public: + sp<Keymaster>& operator[](SecurityLevel secLevel); + sp<Keymaster> operator[](SecurityLevel secLevel) const; +}; + class KeyStore { public: - KeyStore(Entropy* entropy, const sp<Keymaster>& device, const sp<Keymaster>& fallback, - bool allowNewFallback); + KeyStore(Entropy* entropy, const KeymasterDevices& kmDevices, + SecurityLevel minimalAllowedSecurityLevelForNewKeys); ~KeyStore(); - sp<Keymaster>& getDevice() { return mDevice; } + sp<Keymaster> getDevice(SecurityLevel securityLevel) const { return mKmDevices[securityLevel]; } + + std::pair<sp<Keymaster>, SecurityLevel> getMostSecureDevice() const { + SecurityLevel level = SecurityLevel::STRONGBOX; + do { + if (mKmDevices[level].get()) { + return {mKmDevices[level], level}; + } + level = static_cast<SecurityLevel>(static_cast<uint32_t>(level) - 1); + } while (level != SecurityLevel::SOFTWARE); + return {nullptr, SecurityLevel::SOFTWARE}; + } - NullOr<sp<Keymaster>&> getFallbackDevice() { + sp<Keymaster> 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 mFallbackDevice; + return mKmDevices[SecurityLevel::SOFTWARE]; } else { - return {}; + return nullptr; } } - sp<Keymaster>& getDevice(const Blob& blob) { - // We return a device, based on the nature of the blob to provide backward - // compatibility with old key blobs generated using the fallback device. - return blob.isFallback() ? mFallbackDevice : mDevice; - } + sp<Keymaster> getDevice(const Blob& blob) { return mKmDevices[blob.getSecurityLevel()]; } ResponseCode initialize(); @@ -128,8 +142,7 @@ class KeyStore { static const android::String16 kEcKeyType; Entropy* mEntropy; - sp<Keymaster> mDevice; - sp<Keymaster> mFallbackDevice; + KeymasterDevices mKmDevices; bool mAllowNewFallback; android::Vector<UserState*> mMasterKeys; diff --git a/keystore/Keymaster.h b/keystore/Keymaster.h index 7fc2e99..4712eec 100644 --- a/keystore/Keymaster.h +++ b/keystore/Keymaster.h @@ -18,7 +18,6 @@ #ifndef SYSTEM_SECURITY_KEYSTORE_KEYMASTER__H_ #define SYSTEM_SECURITY_KEYSTORE_KEYMASTER__H_ -#include <keystore/keymaster_tags.h> #include <keystore/keymaster_types.h> namespace keystore { @@ -41,7 +40,7 @@ class Keymaster : public keymaster::IKeymasterDevice { struct VersionResult { ErrorCode error; uint8_t majorVersion; - bool isSecure; + SecurityLevel securityLevel; bool supportsEc; }; diff --git a/keystore/Keymaster3.cpp b/keystore/Keymaster3.cpp index c4ddc75..1a17226 100644 --- a/keystore/Keymaster3.cpp +++ b/keystore/Keymaster3.cpp @@ -98,7 +98,8 @@ void Keymaster3::getVersionIfNeeded() { [&](bool isSecure, bool supportsEllipticCurve, bool supportsSymmetricCryptography, bool supportsAttestation, bool supportsAllDigests, const hidl_string& keymasterName, const hidl_string& keymasterAuthorName) { - isSecure_ = isSecure; + securityLevel_ = + isSecure ? SecurityLevel::TRUSTED_ENVIRONMENT : SecurityLevel::SOFTWARE; supportsEllipticCurve_ = supportsEllipticCurve; supportsSymmetricCryptography_ = supportsSymmetricCryptography; supportsAttestation_ = supportsAttestation; @@ -109,7 +110,7 @@ void Keymaster3::getVersionIfNeeded() { CHECK(rc.isOk()) << "Got error " << rc.description() << " trying to get hardware features"; - if (!isSecure_) { + if (securityLevel_ == SecurityLevel::SOFTWARE) { majorVersion_ = 3; } else if (supportsAttestation_) { majorVersion_ = 3; // Could be 2, doesn't matter. @@ -122,13 +123,12 @@ void Keymaster3::getVersionIfNeeded() { Keymaster::VersionResult Keymaster3::halVersion() { getVersionIfNeeded(); - return {ErrorCode::OK, majorVersion_, isSecure_, supportsEllipticCurve_}; + return {ErrorCode::OK, majorVersion_, securityLevel_, supportsEllipticCurve_}; } Return<void> Keymaster3::getHardwareInfo(Keymaster3::getHardwareInfo_cb _hidl_cb) { getVersionIfNeeded(); - _hidl_cb(isSecure_ ? SecurityLevel::TRUSTED_ENVIRONMENT : SecurityLevel::SOFTWARE, - keymasterName_ + " (wrapped by keystore::Keymaster3)", authorName_); + _hidl_cb(securityLevel_, keymasterName_ + " (wrapped by keystore::Keymaster3)", authorName_); return Void(); } diff --git a/keystore/Keymaster3.h b/keystore/Keymaster3.h index 172ab23..6d74a12 100644 --- a/keystore/Keymaster3.h +++ b/keystore/Keymaster3.h @@ -36,7 +36,8 @@ using ::android::hardware::details::return_status; class Keymaster3 : public Keymaster { public: - Keymaster3(sp<IKeymaster3Device> km3_dev) : km3_dev_(km3_dev) {} + using WrappedIKeymasterDevice = IKeymaster3Device; + Keymaster3(sp<IKeymaster3Device> km3_dev) : km3_dev_(km3_dev), haveVersion_(false) {} VersionResult halVersion() override; @@ -105,9 +106,9 @@ class Keymaster3 : public Keymaster { sp<IKeymaster3Device> km3_dev_; - bool haveVersion_ = false; + bool haveVersion_; uint8_t majorVersion_; - bool isSecure_; + SecurityLevel securityLevel_; bool supportsEllipticCurve_; bool supportsSymmetricCryptography_; bool supportsAttestation_; diff --git a/keystore/Keymaster4.cpp b/keystore/Keymaster4.cpp new file mode 100644 index 0000000..3edfb53 --- /dev/null +++ b/keystore/Keymaster4.cpp @@ -0,0 +1,39 @@ +/* +** +** Copyright 2017, 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. +*/ +#include "Keymaster4.h" + +#include <android-base/logging.h> + +namespace keystore { + +void Keymaster4::getVersionIfNeeded() { + if (haveVersion_) return; + + auto rc = dev_->getHardwareInfo([&](SecurityLevel securityLevel, auto...) { + securityLevel_ = securityLevel; + haveVersion_ = true; + }); + + CHECK(rc.isOk()) << "Got error " << rc.description() << " trying to get hardware info"; +} + +Keymaster::VersionResult Keymaster4::halVersion() { + getVersionIfNeeded(); + return {ErrorCode::OK, halMajorVersion(), securityLevel_, true}; +} + +} // namespace keystore diff --git a/keystore/Keymaster4.h b/keystore/Keymaster4.h index 867f304..53ca08a 100644 --- a/keystore/Keymaster4.h +++ b/keystore/Keymaster4.h @@ -30,11 +30,12 @@ using IKeymaster4Device = ::android::hardware::keymaster::V4_0::IKeymasterDevice class Keymaster4 : public Keymaster { public: - Keymaster4(sp<IKeymasterDevice> km4_dev) : dev_(km4_dev) {} + using WrappedIKeymasterDevice = IKeymaster4Device; + Keymaster4(sp<IKeymasterDevice> km4_dev) : haveVersion_(false), dev_(km4_dev) {} uint8_t halMajorVersion() { return 4; } - VersionResult halVersion() override { return {ErrorCode::OK, halMajorVersion(), true, true}; } + VersionResult halVersion() override; Return<void> getHardwareInfo(getHardwareInfo_cb _hidl_cb) override { return dev_->getHardwareInfo(_hidl_cb); @@ -135,6 +136,10 @@ class Keymaster4 : public Keymaster { } private: + void getVersionIfNeeded(); + + bool haveVersion_; + SecurityLevel securityLevel_; sp<IKeymaster4Device> dev_; }; diff --git a/keystore/OperationResult.cpp b/keystore/OperationResult.cpp index 62c957e..53c8d62 100644 --- a/keystore/OperationResult.cpp +++ b/keystore/OperationResult.cpp @@ -17,11 +17,13 @@ #include "include/keystore/OperationResult.h" -#include <binder/Parcel.h> #include <utility> +#include <binder/Parcel.h> + +#include <keystore/keymaster_types.h> + #include "keystore_aidl_hidl_marshalling_utils.h" -#include <keystore/keymaster_tags.h> namespace android { namespace security { diff --git a/keystore/auth_token_table.h b/keystore/auth_token_table.h index 0a23c99..db60003 100644 --- a/keystore/auth_token_table.h +++ b/keystore/auth_token_table.h @@ -17,7 +17,6 @@ #include <memory> #include <vector> -#include <keystore/authorization_set.h> #include <keystore/keymaster_types.h> #ifndef KEYSTORE_AUTH_TOKEN_TABLE_H_ @@ -59,7 +58,7 @@ class AuthTokenTable { }; /** - * Add an authorization token to the table. The table takes ownership of the argument. + * Add an authorization token to the table. */ void AddAuthenticationToken(HardwareAuthToken&& auth_token); diff --git a/keystore/authorization_set.cpp b/keystore/authorization_set.cpp index e30b32d..537fe3d 100644 --- a/keystore/authorization_set.cpp +++ b/keystore/authorization_set.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include <keystore/authorization_set.h> +#include <keystore/keymaster_types.h> #include <assert.h> #include <stddef.h> diff --git a/keystore/blob.cpp b/keystore/blob.cpp index 625d057..aa1ae37 100644 --- a/keystore/blob.cpp +++ b/keystore/blob.cpp @@ -327,3 +327,12 @@ ResponseCode Blob::readBlob(const std::string& filename, const uint8_t* aes_key, return ResponseCode::NO_ERROR; } + +keystore::SecurityLevel Blob::getSecurityLevel() const { + return keystore::flagsToSecurityLevel(mBlob.flags); +} + +void Blob::setSecurityLevel(keystore::SecurityLevel secLevel) { + mBlob.flags &= ~(KEYSTORE_FLAG_FALLBACK | KEYSTORE_FLAG_STRONGBOX); + mBlob.flags |= keystore::securityLevelToFlags(secLevel); +} diff --git a/keystore/blob.h b/keystore/blob.h index 5335037..665e07a 100644 --- a/keystore/blob.h +++ b/keystore/blob.h @@ -22,6 +22,7 @@ #include <openssl/aes.h> #include <openssl/md5.h> +#include <keystore/keymaster_types.h> #include <keystore/keystore.h> constexpr size_t kValueSize = 32768; @@ -117,6 +118,9 @@ class Blob { BlobType getType() const { return BlobType(mBlob.type); } void setType(BlobType type) { mBlob.type = uint8_t(type); } + keystore::SecurityLevel getSecurityLevel() const; + void setSecurityLevel(keystore::SecurityLevel); + ResponseCode writeBlob(const std::string& filename, const uint8_t* aes_key, State state, Entropy* entropy); ResponseCode readBlob(const std::string& filename, const uint8_t* aes_key, State state); diff --git a/keystore/include/keystore/KeymasterArguments.h b/keystore/include/keystore/KeymasterArguments.h index 329579a..99074f8 100644 --- a/keystore/include/keystore/KeymasterArguments.h +++ b/keystore/include/keystore/KeymasterArguments.h @@ -17,7 +17,7 @@ #include <binder/Parcelable.h> -#include "keymaster_tags.h" +#include <keystore/keymaster_types.h> namespace android { namespace security { diff --git a/keystore/include/keystore/OperationResult.h b/keystore/include/keystore/OperationResult.h index 6dd5aef..2ceda9a 100644 --- a/keystore/include/keystore/OperationResult.h +++ b/keystore/include/keystore/OperationResult.h @@ -18,7 +18,7 @@ #include <binder/Parcel.h> #include <binder/Parcelable.h> -#include "keymaster_tags.h" +#include "keymaster_types.h" #include "keystore_return_types.h" namespace android { diff --git a/keystore/include/keystore/authorization_set.h b/keystore/include/keystore/authorization_set.h deleted file mode 100644 index 0e57a19..0000000 --- a/keystore/include/keystore/authorization_set.h +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright 2014 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 SYSTEM_SECURITY_KEYSTORE_AUTHORIZATION_SET_H_ -#define SYSTEM_SECURITY_KEYSTORE_AUTHORIZATION_SET_H_ - -#include "keymaster_tags.h" -#include <vector> - -namespace keystore { - -class AuthorizationSetBuilder; - -/** - * An ordered collection of KeyParameters. It provides memory ownership and some convenient - * functionality for sorting, deduplicating, joining, and subtracting sets of KeyParameters. - * For serialization, wrap the backing store of this structure in a hidl_vec<KeyParameter>. - */ -class AuthorizationSet { - public: - /** - * Construct an empty, dynamically-allocated, growable AuthorizationSet. - */ - AuthorizationSet() {}; - - // Copy constructor. - AuthorizationSet(const AuthorizationSet& other) : data_(other.data_) {} - - // Move constructor. - AuthorizationSet(AuthorizationSet&& other) : data_(std::move(other.data_)) {} - - // Constructor from hidl_vec<KeyParameter> - AuthorizationSet(const hidl_vec<KeyParameter>& other) { - *this = other; - } - - // Copy assignment. - AuthorizationSet& operator=(const AuthorizationSet& other) { - data_ = other.data_; - return *this; - } - - // Move assignment. - AuthorizationSet& operator=(AuthorizationSet&& other) { - data_ = std::move(other.data_); - return *this; - } - - AuthorizationSet& operator=(const hidl_vec<KeyParameter>& other) { - if (other.size() > 0) { - data_.resize(other.size()); - for (size_t i = 0; i < data_.size(); ++i) { - /* This makes a deep copy even of embedded blobs. - * See assignment operator/copy constructor of hidl_vec.*/ - data_[i] = other[i]; - } - } - return *this; - } - - /** - * Clear existing authorization set data - */ - void Clear(); - - ~AuthorizationSet() = default; - - /** - * Returns the size of the set. - */ - size_t size() const { return data_.size(); } - - /** - * Returns true if the set is empty. - */ - bool empty() const { return size() == 0; } - - /** - * Returns the data in the set, directly. Be careful with this. - */ - const KeyParameter* data() const { return data_.data(); } - - /** - * Sorts the set - */ - void Sort(); - - /** - * Sorts the set and removes duplicates (inadvertently duplicating tags is easy to do with the - * AuthorizationSetBuilder). - */ - void Deduplicate(); - - /** - * Adds all elements from \p set that are not already present in this AuthorizationSet. As a - * side-effect, if \p set is not null this AuthorizationSet will end up sorted. - */ - void Union(const AuthorizationSet& set); - - /** - * Removes all elements in \p set from this AuthorizationSet. - */ - void Subtract(const AuthorizationSet& set); - - /** - * Returns the offset of the next entry that matches \p tag, starting from the element after \p - * begin. If not found, returns -1. - */ - int find(Tag tag, int begin = -1) const; - - /** - * Removes the entry at the specified index. Returns true if successful, false if the index was - * out of bounds. - */ - bool erase(int index); - - /** - * Returns iterator (pointer) to beginning of elems array, to enable STL-style iteration - */ - std::vector<KeyParameter>::const_iterator begin() const { return data_.begin(); } - - /** - * Returns iterator (pointer) one past end of elems array, to enable STL-style iteration - */ - std::vector<KeyParameter>::const_iterator end() const { return data_.end(); } - - /** - * Returns the nth element of the set. - * Like for std::vector::operator[] there is no range check performed. Use of out of range - * indices is undefined. - */ - KeyParameter& operator[](int n); - - /** - * Returns the nth element of the set. - * Like for std::vector::operator[] there is no range check performed. Use of out of range - * indices is undefined. - */ - const KeyParameter& operator[](int n) const; - - /** - * Returns true if the set contains at least one instance of \p tag - */ - bool Contains(Tag tag) const { - return find(tag) != -1; - } - - template <TagType tag_type, Tag tag, typename ValueT> - bool Contains(TypedTag<tag_type, tag> ttag, const ValueT& value) const { - for (const auto& param: data_) { - auto entry = authorizationValue(ttag, param); - if (entry.isOk() && entry.value() == value) return true; - } - return false; - } - /** - * Returns the number of \p tag entries. - */ - size_t GetTagCount(Tag tag) const; - - template <typename T> - inline NullOr<const typename TypedTag2ValueType<T>::type&> GetTagValue(T tag) const { - auto entry = GetEntry(tag); - if (entry.isOk()) return authorizationValue(tag, entry.value()); - return {}; - } - - void push_back(const KeyParameter& param) { - data_.push_back(param); - } - void push_back(KeyParameter&& param) { - data_.push_back(std::move(param)); - } - - /** - * Append the tag and enumerated value to the set. - * "val" may be exactly one parameter unless a boolean parameter is added. - * In this case "val" is omitted. This condition is checked at compile time by Authorization() - */ - template <typename TypedTagT, typename... Value> - void push_back(TypedTagT tag, Value&&... val) { - push_back(Authorization(tag, std::forward<Value>(val)...)); - } - - template <typename Iterator> - void append(Iterator begin, Iterator end) { - while (begin != end) { - push_back(*begin); - ++begin; - } - } - - hidl_vec<KeyParameter> hidl_data() const { - hidl_vec<KeyParameter> result; - result.setToExternal(const_cast<KeyParameter*>(data()), size()); - return result; - } - - void Serialize(std::ostream* out) const; - void Deserialize(std::istream* in); - - private: - NullOr<const KeyParameter&> GetEntry(Tag tag) const; - - std::vector<KeyParameter> data_; -}; - -class AuthorizationSetBuilder: public AuthorizationSet { - public: - template <typename TagType, typename... ValueType> - AuthorizationSetBuilder& Authorization(TagType ttag, ValueType&&... value) { - push_back(ttag, std::forward<ValueType>(value)...); - return *this; - } - - template <Tag tag> - AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag, const uint8_t* data, - size_t data_length) { - hidl_vec<uint8_t> new_blob; - new_blob.setToExternal(const_cast<uint8_t*>(data), data_length); - push_back(ttag, std::move(new_blob)); - return *this; - } - - template <Tag tag> - AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag, const char* data, - size_t data_length) { - return Authorization(ttag, reinterpret_cast<const uint8_t*>(data), data_length); - } - - AuthorizationSetBuilder& RsaKey(uint32_t key_size, uint64_t public_exponent); - AuthorizationSetBuilder& EcdsaKey(uint32_t key_size); - AuthorizationSetBuilder& AesKey(uint32_t key_size); - AuthorizationSetBuilder& HmacKey(uint32_t key_size); - - AuthorizationSetBuilder& RsaSigningKey(uint32_t key_size, uint64_t public_exponent); - AuthorizationSetBuilder& RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent); - AuthorizationSetBuilder& EcdsaSigningKey(uint32_t key_size); - AuthorizationSetBuilder& AesEncryptionKey(uint32_t key_size); - - AuthorizationSetBuilder& SigningKey(); - AuthorizationSetBuilder& EncryptionKey(); - AuthorizationSetBuilder& NoDigestOrPadding(); - AuthorizationSetBuilder& EcbMode(); - - AuthorizationSetBuilder& Digest(Digest digest) { - return Authorization(TAG_DIGEST, digest); - } - - AuthorizationSetBuilder& Padding(PaddingMode padding) { - return Authorization(TAG_PADDING, padding); - } -}; - -inline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaKey(uint32_t key_size, - uint64_t public_exponent) { - Authorization(TAG_ALGORITHM, Algorithm::RSA); - Authorization(TAG_KEY_SIZE, key_size); - Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent); - return *this; -} - -inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(uint32_t key_size) { - Authorization(TAG_ALGORITHM, Algorithm::EC); - Authorization(TAG_KEY_SIZE, key_size); - return *this; -} - -inline AuthorizationSetBuilder& AuthorizationSetBuilder::AesKey(uint32_t key_size) { - Authorization(TAG_ALGORITHM, Algorithm::AES); - return Authorization(TAG_KEY_SIZE, key_size); -} - -inline AuthorizationSetBuilder& AuthorizationSetBuilder::HmacKey(uint32_t key_size) { - Authorization(TAG_ALGORITHM, Algorithm::HMAC); - Authorization(TAG_KEY_SIZE, key_size); - return SigningKey(); -} - -inline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaSigningKey(uint32_t key_size, - uint64_t public_exponent) { - RsaKey(key_size, public_exponent); - return SigningKey(); -} - -inline AuthorizationSetBuilder& -AuthorizationSetBuilder::RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent) { - RsaKey(key_size, public_exponent); - return EncryptionKey(); -} - -inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(uint32_t key_size) { - EcdsaKey(key_size); - return SigningKey(); -} - -inline AuthorizationSetBuilder& AuthorizationSetBuilder::AesEncryptionKey(uint32_t key_size) { - AesKey(key_size); - return EncryptionKey(); -} - -inline AuthorizationSetBuilder& AuthorizationSetBuilder::SigningKey() { - Authorization(TAG_PURPOSE, KeyPurpose::SIGN); - return Authorization(TAG_PURPOSE, KeyPurpose::VERIFY); -} - -inline AuthorizationSetBuilder& AuthorizationSetBuilder::EncryptionKey() { - Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT); - return Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT); -} - -inline AuthorizationSetBuilder& AuthorizationSetBuilder::NoDigestOrPadding() { - Authorization(TAG_DIGEST, Digest::NONE); - return Authorization(TAG_PADDING, PaddingMode::NONE); -} - -inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcbMode() { - return Authorization(TAG_BLOCK_MODE, BlockMode::ECB); -} - -} // namespace keystore - -#endif // SYSTEM_SECURITY_KEYSTORE_AUTHORIZATION_SET_H_ diff --git a/keystore/include/keystore/keymaster_tags.h b/keystore/include/keystore/keymaster_tags.h deleted file mode 100644 index 6d2048a..0000000 --- a/keystore/include/keystore/keymaster_tags.h +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright 2014 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 SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_ -#define SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_ - -/** - * This header contains various definitions that make working with keymaster tags safer and easier. - * - * It makes use of a fair amount of template metaprogramming. The metaprogramming serves the purpose - * of making it impossible to make certain classes of mistakes when operating on keymaster - * authorizations. For example, it's an error to create a KeyParameter with tag == Tag::PURPOSE - * and then to assign Algorithm::RSA to algorithm element of its union. But because the user - * must choose the union field, there could be a mismatch which the compiler has now way to - * diagnose. - * - * The machinery in this header solves these problems by describing which union field corresponds - * to which Tag. Central to this mechanism is the template TypedTag. It has zero size and binds a - * numeric Tag to a type that the compiler understands. By means of the macro DECLARE_TYPED_TAG, - * we declare types for each of the tags defined in hardware/interfaces/keymaster/2.0/types.hal. - * - * The macro DECLARE_TYPED_TAG(name) generates a typename TAG_name_t and a zero sized instance - * TAG_name. Once these typed tags have been declared we define metafunctions mapping the each tag - * to its value c++ type and the correct union element of KeyParameter. This is done by means of - * the macros MAKE_TAG_*VALUE_ACCESSOR, which generates TypedTag2ValueType, a metafunction mapping - * a typed tag to the corresponding c++ type, and access function, accessTagValue returning a - * reference to the correct element of KeyParameter. - * E.g.: - * given "KeyParameter param;" then "accessTagValue(TAG_PURPOSE, param)" - * yields a reference to param.f.purpose - * If used in an assignment the compiler can now check the compatibility of the assigned value. - * - * For convenience we also provide the constructor like function Authorization(). - * Authorization takes a typed tag and a value and checks at compile time whether the value given - * is suitable for the given tag. At runtime it creates a new KeyParameter initialized with the - * given tag and value and returns it by value. - * - * The second convenience function, authorizationValue, allows access to the KeyParameter value in - * a safe way. It takes a typed tag and a KeyParameter and returns a reference to the value wrapped - * by NullOr. NullOr has out-of-band information about whether it is save to access the wrapped - * reference. - * E.g.: - * auto param = Authorization(TAG_ALGORITM, Algorithm::RSA); - * auto value1 = authorizationValue(TAG_PURPOSE, param); - * auto value2 = authorizationValue(TAG_ALGORITM, param); - * value1.isOk() yields false, but value2.isOk() yields true, thus value2.value() is save to access. - */ - -#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h> -#include <type_traits> - -#include "keymaster_types.h" - -namespace keystore { - -// This namespace alias is temporary. This file will be removed in favor of the KM4 support -// library version. -namespace oldkeymaster = android::hardware::keymaster::V3_0; - -using keymaster::ErrorCode; -using keymaster::HardwareAuthToken; -using keymaster::HmacSharingParameters; -using keymaster::IKeymasterDevice; -using keymaster::KeyCharacteristics; -using keymaster::KeyOrigin; -using keymaster::KeyParameter; -using keymaster::KeyPurpose; -using keymaster::OperationHandle; -using keymaster::SecurityLevel; -using keymaster::Tag; -using keymaster::VerificationToken; -using oldkeymaster::Algorithm; -using oldkeymaster::BlockMode; -using oldkeymaster::Digest; -using oldkeymaster::EcCurve; -using oldkeymaster::HardwareAuthenticatorType; -using oldkeymaster::KeyBlobUsageRequirements; -using oldkeymaster::KeyDerivationFunction; -using oldkeymaster::KeyFormat; -using oldkeymaster::PaddingMode; -using oldkeymaster::TagType; - -using ::android::hardware::hidl_vec; -using ::android::hardware::Return; - -// The following create the numeric values that KM_TAG_PADDING and KM_TAG_DIGEST used to have. We -// need these old values to be able to support old keys that use them. -static const int32_t KM_TAG_DIGEST_OLD = static_cast<int32_t>(TagType::ENUM) | 5; -static const int32_t KM_TAG_PADDING_OLD = static_cast<int32_t>(TagType::ENUM) | 7; - -constexpr TagType typeFromTag(Tag tag) { - return static_cast<TagType>(static_cast<uint32_t>(tag) & static_cast<uint32_t>(0xf0000000)); -} - -/** - * TypedTag is a templatized version of Tag, which provides compile-time checking of - * keymaster tag types. Instances are convertible to Tag, so they can be used wherever - * Tag is expected, and because they encode the tag type it's possible to create - * function overloads that only operate on tags with a particular type. - */ -template <TagType tag_type, Tag tag> struct TypedTag { - inline TypedTag() { - // Ensure that it's impossible to create a TypedTag instance whose 'tag' doesn't have type - // 'tag_type'. Attempting to instantiate a tag with the wrong type will result in a compile - // error (no match for template specialization StaticAssert<false>), with no run-time cost. - static_assert(typeFromTag(tag) == tag_type, "mismatch between tag and tag_type"); - } - operator Tag() const { return tag; } -}; - -template <Tag tag> struct Tag2TypedTag { typedef TypedTag<typeFromTag(tag), tag> type; }; - -template <Tag tag> struct Tag2String; - -#define _TAGS_STRINGIFY(x) #x -#define TAGS_STRINGIFY(x) _TAGS_STRINGIFY(x) - -#define DECLARE_TYPED_TAG(name) \ - typedef typename Tag2TypedTag<Tag::name>::type TAG_##name##_t; \ - extern TAG_##name##_t TAG_##name; \ - template <> struct Tag2String<Tag::name> { \ - static const char* value() { return "Tag::" TAGS_STRINGIFY(name); } \ - } - -DECLARE_TYPED_TAG(INVALID); -DECLARE_TYPED_TAG(KEY_SIZE); -DECLARE_TYPED_TAG(MAC_LENGTH); -DECLARE_TYPED_TAG(CALLER_NONCE); -DECLARE_TYPED_TAG(MIN_MAC_LENGTH); -DECLARE_TYPED_TAG(RSA_PUBLIC_EXPONENT); -DECLARE_TYPED_TAG(INCLUDE_UNIQUE_ID); -DECLARE_TYPED_TAG(ACTIVE_DATETIME); -DECLARE_TYPED_TAG(ORIGINATION_EXPIRE_DATETIME); -DECLARE_TYPED_TAG(USAGE_EXPIRE_DATETIME); -DECLARE_TYPED_TAG(MIN_SECONDS_BETWEEN_OPS); -DECLARE_TYPED_TAG(MAX_USES_PER_BOOT); -DECLARE_TYPED_TAG(USER_SECURE_ID); -DECLARE_TYPED_TAG(NO_AUTH_REQUIRED); -DECLARE_TYPED_TAG(AUTH_TIMEOUT); -DECLARE_TYPED_TAG(ALLOW_WHILE_ON_BODY); -DECLARE_TYPED_TAG(APPLICATION_ID); -DECLARE_TYPED_TAG(APPLICATION_DATA); -DECLARE_TYPED_TAG(CREATION_DATETIME); -DECLARE_TYPED_TAG(ROLLBACK_RESISTANCE); -DECLARE_TYPED_TAG(ROOT_OF_TRUST); -DECLARE_TYPED_TAG(ASSOCIATED_DATA); -DECLARE_TYPED_TAG(NONCE); -DECLARE_TYPED_TAG(BOOTLOADER_ONLY); -DECLARE_TYPED_TAG(OS_VERSION); -DECLARE_TYPED_TAG(OS_PATCHLEVEL); -DECLARE_TYPED_TAG(UNIQUE_ID); -DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE); -DECLARE_TYPED_TAG(ATTESTATION_APPLICATION_ID); -DECLARE_TYPED_TAG(RESET_SINCE_ID_ROTATION); - -DECLARE_TYPED_TAG(PURPOSE); -DECLARE_TYPED_TAG(ALGORITHM); -DECLARE_TYPED_TAG(BLOCK_MODE); -DECLARE_TYPED_TAG(DIGEST); -DECLARE_TYPED_TAG(PADDING); -DECLARE_TYPED_TAG(BLOB_USAGE_REQUIREMENTS); -DECLARE_TYPED_TAG(ORIGIN); -DECLARE_TYPED_TAG(USER_AUTH_TYPE); -DECLARE_TYPED_TAG(EC_CURVE); - -template <typename... Elems> struct MetaList {}; - -using all_tags_t = MetaList< - TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t, TAG_MIN_MAC_LENGTH_t, - TAG_RSA_PUBLIC_EXPONENT_t, TAG_INCLUDE_UNIQUE_ID_t, TAG_ACTIVE_DATETIME_t, - TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t, TAG_MIN_SECONDS_BETWEEN_OPS_t, - TAG_MAX_USES_PER_BOOT_t, TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t, - TAG_ALLOW_WHILE_ON_BODY_t, TAG_APPLICATION_ID_t, TAG_APPLICATION_DATA_t, - TAG_CREATION_DATETIME_t, TAG_ROLLBACK_RESISTANCE_t, TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, - TAG_NONCE_t, TAG_BOOTLOADER_ONLY_t, TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t, - TAG_ATTESTATION_CHALLENGE_t, TAG_ATTESTATION_APPLICATION_ID_t, TAG_RESET_SINCE_ID_ROTATION_t, - TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t, TAG_DIGEST_t, TAG_PADDING_t, - TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t>; - -/* implementation in keystore_utils.cpp */ -extern const char* stringifyTag(Tag tag); - -template <typename TypedTagType> struct TypedTag2ValueType; - -#define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name) \ - template <Tag tag> struct TypedTag2ValueType<TypedTag<tag_type, tag>> { \ - typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type; \ - }; \ - template <Tag tag> \ - inline auto accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param) \ - ->const decltype(param.field_name)& { \ - return param.field_name; \ - } \ - template <Tag tag> \ - inline auto accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param) \ - ->decltype(param.field_name)& { \ - return param.field_name; \ - } - -MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG, f.longInteger) -MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG_REP, f.longInteger) -MAKE_TAG_VALUE_ACCESSOR(TagType::DATE, f.dateTime) -MAKE_TAG_VALUE_ACCESSOR(TagType::UINT, f.integer) -MAKE_TAG_VALUE_ACCESSOR(TagType::UINT_REP, f.integer) -MAKE_TAG_VALUE_ACCESSOR(TagType::BOOL, f.boolValue) -MAKE_TAG_VALUE_ACCESSOR(TagType::BYTES, blob) -MAKE_TAG_VALUE_ACCESSOR(TagType::BIGNUM, blob) - -#define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name) \ - template <> struct TypedTag2ValueType<decltype(typed_tag)> { \ - typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type; \ - }; \ - inline auto accessTagValue(decltype(typed_tag), const KeyParameter& param) \ - ->const decltype(param.field_name)& { \ - return param.field_name; \ - } \ - inline auto accessTagValue(decltype(typed_tag), KeyParameter& param) \ - ->decltype(param.field_name)& { \ - return param.field_name; \ - } - -MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, f.algorithm) -MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOB_USAGE_REQUIREMENTS, f.keyBlobUsageRequirements) -MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOCK_MODE, f.blockMode) -MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_DIGEST, f.digest) -MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_EC_CURVE, f.ecCurve) -MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ORIGIN, f.origin) -MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, f.paddingMode) -MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, f.purpose) -MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, f.hardwareAuthenticatorType) - -template <TagType tag_type, Tag tag, typename ValueT> -inline KeyParameter makeKeyParameter(TypedTag<tag_type, tag> ttag, ValueT&& value) { - KeyParameter param; - param.tag = tag; - param.f.longInteger = 0; - accessTagValue(ttag, param) = std::forward<ValueT>(value); - return param; -} - -// the boolean case -template <Tag tag> inline KeyParameter makeKeyParameter(TypedTag<TagType::BOOL, tag>) { - KeyParameter param; - param.tag = tag; - param.f.boolValue = true; - return param; -} - -template <typename... Pack> struct FirstOrNoneHelper; -template <typename First> struct FirstOrNoneHelper<First> { typedef First type; }; -template <> struct FirstOrNoneHelper<> { - struct type {}; -}; - -template <typename... Pack> using FirstOrNone = typename FirstOrNoneHelper<Pack...>::type; - -template <TagType tag_type, Tag tag, typename... Args> -inline KeyParameter Authorization(TypedTag<tag_type, tag> ttag, Args&&... args) { - static_assert(tag_type != TagType::BOOL || (sizeof...(args) == 0), - "TagType::BOOL Authorizations do not take parameters. Presence is truth."); - static_assert(tag_type == TagType::BOOL || (sizeof...(args) == 1), - "Authorization other then TagType::BOOL take exactly one parameter."); - static_assert( - tag_type == TagType::BOOL || - std::is_convertible<std::remove_cv_t<std::remove_reference_t<FirstOrNone<Args...>>>, - typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>::value, - "Invalid argument type for given tag."); - - return makeKeyParameter(ttag, std::forward<Args>(args)...); -} - -/** - * This class wraps a (mostly return) value and stores whether or not the wrapped value is valid out - * of band. Note that if the wrapped value is a reference it is unsafe to access the value if - * !isOk(). If the wrapped type is a pointer or value and !isOk(), it is still safe to access the - * wrapped value. In this case the pointer will be NULL though, and the value will be default - * constructed. - */ -template <typename ValueT> class NullOr { - template <typename T> struct reference_initializer { - static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); } - }; - template <typename T> struct pointer_initializer { - static T init() { return nullptr; } - }; - template <typename T> struct value_initializer { - static T init() { return T(); } - }; - template <typename T> - using initializer_t = - std::conditional_t<std::is_lvalue_reference<T>::value, reference_initializer<T>, - std::conditional_t<std::is_pointer<T>::value, pointer_initializer<T>, - value_initializer<T>>>; - - public: - NullOr() : value_(initializer_t<ValueT>::init()), null_(true) {} - NullOr(ValueT&& value) : value_(std::forward<ValueT>(value)), null_(false) {} - - bool isOk() const { return !null_; } - - const ValueT& value() const & { return value_; } - ValueT& value() & { return value_; } - ValueT&& value() && { return std::move(value_); } - - private: - ValueT value_; - bool null_; -}; - -template <typename T> std::remove_reference_t<T> NullOrOr(T&& v) { - if (v.isOk()) return v; - return {}; -} - -template <typename Head, typename... Tail> -std::remove_reference_t<Head> NullOrOr(Head&& head, Tail&&... tail) { - if (head.isOk()) return head; - return NullOrOr(std::forward<Tail>(tail)...); -} - -template <typename Default, typename Wrapped> -std::remove_reference_t<Wrapped> defaultOr(NullOr<Wrapped>&& optional, Default&& def) { - static_assert(std::is_convertible<std::remove_reference_t<Default>, - std::remove_reference_t<Wrapped>>::value, - "Type of default value must match the type wrapped by NullOr"); - if (optional.isOk()) return optional.value(); - return def; -} - -template <TagType tag_type, Tag tag> -inline NullOr<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type&> -authorizationValue(TypedTag<tag_type, tag> ttag, const KeyParameter& param) { - if (tag != param.tag) return {}; - return accessTagValue(ttag, param); -} - -} // namespace keystore - -#endif // SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_ diff --git a/keystore/include/keystore/keymaster_types.h b/keystore/include/keystore/keymaster_types.h index 272105f..d367136 100644 --- a/keystore/include/keystore/keymaster_types.h +++ b/keystore/include/keystore/keymaster_types.h @@ -12,22 +12,89 @@ // See the License for the specific language governing permissions and // limitations under the License. +#ifndef SECURITY_KEYSTORE_INCLUDE_KEYSTORE_KEYMASTER_TYPES_H_ +#define SECURITY_KEYSTORE_INCLUDE_KEYSTORE_KEYMASTER_TYPES_H_ + #include <android/hardware/keymaster/4.0/IKeymasterDevice.h> #include <android/hardware/keymaster/4.0/types.h> +#include <keymasterV4_0/authorization_set.h> +#include <keymasterV4_0/keymaster_tags.h> + /** * This header lifts the types from the current Keymaster version into the keystore namespace. */ namespace keystore { +// Changing this namespace alias will change the keymaster version. namespace keymaster = ::android::hardware::keymaster::V4_0; +using android::hardware::hidl_vec; +using android::hardware::Return; + using keymaster::IKeymasterDevice; using keymaster::SecurityLevel; +using keymaster::AuthorizationSet; +using keymaster::AuthorizationSetBuilder; + +using keymaster::Algorithm; +using keymaster::BlockMode; +using keymaster::Digest; +using keymaster::EcCurve; +using keymaster::ErrorCode; +using keymaster::HardwareAuthenticatorType; +using keymaster::HardwareAuthToken; +using keymaster::HmacSharingParameters; +using keymaster::KeyCharacteristics; +using keymaster::KeyFormat; +using keymaster::KeyParameter; +using keymaster::KeyPurpose; +using keymaster::OperationHandle; +using keymaster::PaddingMode; +using keymaster::SecurityLevel; +using keymaster::Tag; +using keymaster::TagType; +using keymaster::VerificationToken; + +using keymaster::TAG_ACTIVE_DATETIME; +using keymaster::TAG_ALGORITHM; +using keymaster::TAG_ALLOW_WHILE_ON_BODY; +using keymaster::TAG_APPLICATION_DATA; +using keymaster::TAG_APPLICATION_ID; +using keymaster::TAG_ATTESTATION_APPLICATION_ID; +using keymaster::TAG_AUTH_TIMEOUT; +using keymaster::TAG_BLOCK_MODE; +using keymaster::TAG_DIGEST; +using keymaster::TAG_EC_CURVE; +using keymaster::TAG_KEY_SIZE; +using keymaster::TAG_MAC_LENGTH; +using keymaster::TAG_MAX_USES_PER_BOOT; +using keymaster::TAG_MIN_MAC_LENGTH; +using keymaster::TAG_MIN_SECONDS_BETWEEN_OPS; +using keymaster::TAG_NO_AUTH_REQUIRED; +using keymaster::TAG_NONCE; +using keymaster::TAG_ORIGINATION_EXPIRE_DATETIME; +using keymaster::TAG_PADDING; +using keymaster::TAG_PURPOSE; +using keymaster::TAG_RESET_SINCE_ID_ROTATION; +using keymaster::TAG_RSA_PUBLIC_EXPONENT; +using keymaster::TAG_USAGE_EXPIRE_DATETIME; +using keymaster::TAG_USER_AUTH_TYPE; +using keymaster::TAG_USER_SECURE_ID; + +using keymaster::NullOr; + using Km3HardwareAuthToken = ::android::hardware::keymaster::V3_0::HardwareAuthToken; using Km3HardwareAuthenticatorType = ::android::hardware::keymaster::V3_0::HardwareAuthenticatorType; +// The following create the numeric values that KM_TAG_PADDING and KM_TAG_DIGEST used to have. We +// need these old values to be able to support old keys that use them. +constexpr int32_t KM_TAG_DIGEST_OLD = static_cast<int32_t>(TagType::ENUM) | 5; +constexpr int32_t KM_TAG_PADDING_OLD = static_cast<int32_t>(TagType::ENUM) | 7; + } // namespace keystore + +#endif // SYSTEM_SECURITY_KEYSTORE_KM4_AUTHORIZATION_SET_H_ diff --git a/keystore/include/keystore/keystore.h b/keystore/include/keystore/keystore.h index cb64498..07f645f 100644 --- a/keystore/include/keystore/keystore.h +++ b/keystore/include/keystore/keystore.h @@ -63,6 +63,7 @@ enum KeyStoreFlag : uint8_t { // encrypted, and it will be stored separately under an unique UID instead. This flag should // only be available to system uid. KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION = 1 << 3, + KEYSTORE_FLAG_STRONGBOX = 1 << 4, }; #endif diff --git a/keystore/include/keystore/keystore_client.h b/keystore/include/keystore/keystore_client.h index 928b2e6..d6a4807 100644 --- a/keystore/include/keystore/keystore_client.h +++ b/keystore/include/keystore/keystore_client.h @@ -21,7 +21,7 @@ #include <android-base/macros.h> -#include "authorization_set.h" +#include "keymaster_types.h" #include "keystore.h" #include "keystore_return_types.h" @@ -62,7 +62,7 @@ class KeystoreClient { // Note: implementations may generate more than one key but they will always // have |key_name| as a prefix. virtual bool encryptWithAuthentication(const std::string& key_name, const std::string& data, - std::string* encrypted_data) = 0; + int32_t flags, std::string* encrypted_data) = 0; // Decrypts and authenticates |encrypted_data| as output by // EncryptWithAuthentication using the key(s) identified by |key_name|. On @@ -85,8 +85,8 @@ class KeystoreClient { // Adds |entropy| to the random number generator. Returns KM_ERROR_OK on // success and a Keystore ResponseCode or keymaster_error_t on failure. - virtual KeyStoreNativeReturnCode - addRandomNumberGeneratorEntropy(const std::string& entropy) = 0; + virtual KeyStoreNativeReturnCode addRandomNumberGeneratorEntropy(const std::string& entropy, + int32_t flags) = 0; // Generates a key according to the given |key_parameters| and stores it with // the given |key_name|. The [hardware|software]_enforced_characteristics of @@ -95,7 +95,7 @@ class KeystoreClient { // failure. virtual KeyStoreNativeReturnCode generateKey(const std::string& key_name, const keystore::AuthorizationSet& key_parameters, - keystore::AuthorizationSet* hardware_enforced_characteristics, + int32_t flags, keystore::AuthorizationSet* hardware_enforced_characteristics, keystore::AuthorizationSet* software_enforced_characteristics) = 0; // Provides the [hardware|software]_enforced_characteristics of a key diff --git a/keystore/include/keystore/keystore_client_impl.h b/keystore/include/keystore/keystore_client_impl.h index a11e2fe..9edd082 100644 --- a/keystore/include/keystore/keystore_client_impl.h +++ b/keystore/include/keystore/keystore_client_impl.h @@ -35,7 +35,7 @@ class KeystoreClientImpl : public KeystoreClient { // KeystoreClient methods. bool encryptWithAuthentication(const std::string& key_name, const std::string& data, - std::string* encrypted_data) override; + int32_t flags, std::string* encrypted_data) override; bool decryptWithAuthentication(const std::string& key_name, const std::string& encrypted_data, std::string* data) override; bool oneShotOperation(KeyPurpose purpose, const std::string& key_name, @@ -43,10 +43,11 @@ class KeystoreClientImpl : public KeystoreClient { const std::string& input_data, const std::string& signature_to_verify, keystore::AuthorizationSet* output_parameters, std::string* output_data) override; - KeyStoreNativeReturnCode addRandomNumberGeneratorEntropy(const std::string& entropy) override; + KeyStoreNativeReturnCode addRandomNumberGeneratorEntropy(const std::string& entropy, + int32_t flags) override; KeyStoreNativeReturnCode generateKey(const std::string& key_name, const keystore::AuthorizationSet& key_parameters, - keystore::AuthorizationSet* hardware_enforced_characteristics, + int32_t flags, keystore::AuthorizationSet* hardware_enforced_characteristics, keystore::AuthorizationSet* software_enforced_characteristics) override; KeyStoreNativeReturnCode getKeyCharacteristics(const std::string& key_name, @@ -90,11 +91,11 @@ class KeystoreClientImpl : public KeystoreClient { // Creates an encryption key suitable for EncryptWithAuthentication or // verifies attributes if the key already exists. Returns true on success. - bool createOrVerifyEncryptionKey(const std::string& key_name); + bool createOrVerifyEncryptionKey(const std::string& key_name, int32_t flags); // Creates an authentication key suitable for EncryptWithAuthentication or // verifies attributes if the key already exists. Returns true on success. - bool createOrVerifyAuthenticationKey(const std::string& key_name); + bool createOrVerifyAuthenticationKey(const std::string& key_name, int32_t flags); // Verifies attributes of an encryption key suitable for // EncryptWithAuthentication. Returns true on success and populates |verified| diff --git a/keystore/include/keystore/keystore_hidl_support.h b/keystore/include/keystore/keystore_hidl_support.h index 944c3f6..7a3723e 100644 --- a/keystore/include/keystore/keystore_hidl_support.h +++ b/keystore/include/keystore/keystore_hidl_support.h @@ -27,7 +27,7 @@ #include <hardware/hw_auth_token.h> #include <hidl/Status.h> -#include <keystore/keymaster_tags.h> +#include <keystore/keymaster_types.h> namespace keystore { diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp index 137ab48..a61f7dc 100644 --- a/keystore/key_store_service.cpp +++ b/keystore/key_store_service.cpp @@ -785,10 +785,15 @@ Status KeyStoreService::clear_uid(int64_t targetUid64, int32_t* aidl_return) { return Status::ok(); } -Status KeyStoreService::addRngEntropy(const ::std::vector<uint8_t>& entropy, int32_t* aidl_return) { - const auto& device = mKeyStore->getDevice(); - *aidl_return = static_cast<int32_t>( - KeyStoreServiceReturnCode(KS_HANDLE_HIDL_ERROR(device->addRngEntropy(entropy)))); +Status KeyStoreService::addRngEntropy(const ::std::vector<uint8_t>& entropy, int32_t flags, + int32_t* aidl_return) { + auto device = mKeyStore->getDevice(flagsToSecurityLevel(flags)); + if (!device) { + *aidl_return = static_cast<int32_t>(ErrorCode::HARDWARE_TYPE_UNAVAILABLE); + } else { + *aidl_return = static_cast<int32_t>( + KeyStoreServiceReturnCode(KS_HANDLE_HIDL_ERROR(device->addRngEntropy(entropy)))); + } return Status::ok(); } @@ -821,15 +826,18 @@ KeyStoreService::generateKey(const String16& name, const KeymasterArguments& par } } - bool usingFallback = false; - auto& dev = mKeyStore->getDevice(); + SecurityLevel securityLevel = flagsToSecurityLevel(flags); + auto dev = mKeyStore->getDevice(securityLevel); + if (!dev) { + *aidl_return = static_cast<int32_t>(ErrorCode::HARDWARE_TYPE_UNAVAILABLE); + return Status::ok(); + } AuthorizationSet keyCharacteristics = params.getParameters(); // TODO: Seed from Linux RNG before this. - int32_t result; - addRngEntropy(entropy, &result); // binder error is not possible. - if (!KeyStoreServiceReturnCode(result).isOk()) { - *aidl_return = static_cast<int32_t>(result); + rc = KS_HANDLE_HIDL_ERROR(dev->addRngEntropy(entropy)); + if (!rc.isOk()) { + *aidl_return = static_cast<int32_t>(rc); return Status::ok(); } @@ -849,7 +857,7 @@ KeyStoreService::generateKey(const String16& name, const KeymasterArguments& par String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10)); Blob keyBlob(&hidlKeyBlob[0], hidlKeyBlob.size(), NULL, 0, ::TYPE_KEYMASTER_10); - keyBlob.setFallback(usingFallback); + keyBlob.setSecurityLevel(securityLevel); keyBlob.setCriticalToDeviceEncryption(flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION); if (isAuthenticationBound(params.getParameters()) && !keyBlob.isCriticalToDeviceEncryption()) { @@ -867,13 +875,13 @@ KeyStoreService::generateKey(const String16& name, const KeymasterArguments& par } if (!error.isOk()) { ALOGE("Failed to generate key -> falling back to software keymaster"); - usingFallback = true; + securityLevel = SecurityLevel::SOFTWARE; auto fallback = mKeyStore->getFallbackDevice(); - if (!fallback.isOk()) { + if (!fallback) { *aidl_return = static_cast<int32_t>(error); return Status::ok(); } - rc = KS_HANDLE_HIDL_ERROR(fallback.value()->generateKey(params.getParameters(), hidl_cb)); + rc = KS_HANDLE_HIDL_ERROR(fallback->generateKey(params.getParameters(), hidl_cb)); if (!rc.isOk()) { *aidl_return = static_cast<int32_t>(rc); return Status::ok(); @@ -897,7 +905,7 @@ KeyStoreService::generateKey(const String16& name, const KeymasterArguments& par auto kc_buf = kc_stream.str(); Blob charBlob(reinterpret_cast<const uint8_t*>(kc_buf.data()), kc_buf.size(), NULL, 0, ::TYPE_KEY_CHARACTERISTICS); - charBlob.setFallback(usingFallback); + charBlob.setSecurityLevel(securityLevel); charBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED); *aidl_return = @@ -956,7 +964,7 @@ Status KeyStoreService::getKeyCharacteristics( } auto hidlKeyBlob = blob2hidlVec(keyBlob); - auto& dev = mKeyStore->getDevice(keyBlob); + auto dev = mKeyStore->getDevice(keyBlob); KeyStoreServiceReturnCode error; @@ -1024,8 +1032,12 @@ KeyStoreService::importKey(const String16& name, const KeymasterArguments& param return Status::ok(); } - bool usingFallback = false; - auto& dev = mKeyStore->getDevice(); + SecurityLevel securityLevel = flagsToSecurityLevel(flags); + auto dev = mKeyStore->getDevice(securityLevel); + if (!dev) { + *aidl_return = static_cast<int32_t>(ErrorCode::HARDWARE_TYPE_UNAVAILABLE); + return Status::ok(); + } String8 name8(name); @@ -1045,7 +1057,7 @@ KeyStoreService::importKey(const String16& name, const KeymasterArguments& param String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10)); Blob ksBlob(&keyBlob[0], keyBlob.size(), NULL, 0, ::TYPE_KEYMASTER_10); - ksBlob.setFallback(usingFallback); + ksBlob.setSecurityLevel(securityLevel); ksBlob.setCriticalToDeviceEncryption(flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION); if (isAuthenticationBound(params.getParameters()) && !ksBlob.isCriticalToDeviceEncryption()) { @@ -1066,14 +1078,14 @@ KeyStoreService::importKey(const String16& name, const KeymasterArguments& param // now check error from callback if (!error.isOk()) { ALOGE("Failed to import key -> falling back to software keymaster"); - usingFallback = true; + securityLevel = SecurityLevel::SOFTWARE; auto fallback = mKeyStore->getFallbackDevice(); - if (!fallback.isOk()) { + if (!fallback) { *aidl_return = static_cast<int32_t>(error); return Status::ok(); } - rc = KS_HANDLE_HIDL_ERROR(fallback.value()->importKey(params.getParameters(), - KeyFormat(format), keyData, hidlCb)); + rc = KS_HANDLE_HIDL_ERROR( + fallback->importKey(params.getParameters(), KeyFormat(format), keyData, hidlCb)); // possible hidl error if (!rc.isOk()) { *aidl_return = static_cast<int32_t>(rc); @@ -1100,7 +1112,7 @@ KeyStoreService::importKey(const String16& name, const KeymasterArguments& param Blob charBlob(reinterpret_cast<const uint8_t*>(kcBuf.data()), kcBuf.size(), NULL, 0, ::TYPE_KEY_CHARACTERISTICS); - charBlob.setFallback(usingFallback); + charBlob.setSecurityLevel(securityLevel); charBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED); *aidl_return = @@ -1131,7 +1143,7 @@ Status KeyStoreService::exportKey(const String16& name, int32_t format, } auto key = blob2hidlVec(keyBlob); - auto& dev = mKeyStore->getDevice(keyBlob); + auto dev = mKeyStore->getDevice(keyBlob); auto hidlCb = [&](ErrorCode ret, const ::android::hardware::hidl_vec<uint8_t>& keyMaterial) { result->resultCode = ret; @@ -1204,7 +1216,7 @@ Status KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name, if (!result->resultCode.isOk()) return Status::ok(); auto key = blob2hidlVec(keyBlob); - auto& dev = mKeyStore->getDevice(keyBlob); + auto dev = mKeyStore->getDevice(keyBlob); AuthorizationSet opParams = params.getParameters(); KeyCharacteristics characteristics; result->resultCode = getOperationCharacteristics(key, &dev, opParams, &characteristics); @@ -1259,9 +1271,7 @@ Status KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name, // Add entropy to the device first. if (entropy.size()) { - int32_t resultCode; - addRngEntropy(entropy, &resultCode); // binder error is not possible - result->resultCode = KeyStoreServiceReturnCode(resultCode); + result->resultCode = KS_HANDLE_HIDL_ERROR(dev->addRngEntropy(entropy)); if (!result->resultCode.isOk()) { return Status::ok(); } @@ -1418,9 +1428,7 @@ Status KeyStoreService::finish(const sp<IBinder>& token, const KeymasterArgument if (!result->resultCode.isOk()) return Status::ok(); if (entropy.size()) { - int resultCode; - addRngEntropy(entropy, &resultCode); // binder error is not possible - result->resultCode = KeyStoreServiceReturnCode(resultCode); + result->resultCode = KS_HANDLE_HIDL_ERROR(op.device->addRngEntropy(entropy)); if (!result->resultCode.isOk()) { return Status::ok(); } @@ -1574,7 +1582,7 @@ Status KeyStoreService::attestKey(const String16& name, const KeymasterArguments }; auto hidlKey = blob2hidlVec(keyBlob); - auto& dev = mKeyStore->getDevice(keyBlob); + auto dev = mKeyStore->getDevice(keyBlob); rc = KS_HANDLE_HIDL_ERROR(dev->attestKey(hidlKey, mutableParams.hidl_data(), hidlCb)); if (!rc.isOk()) { *aidl_return = static_cast<int32_t>(rc); @@ -1624,7 +1632,15 @@ KeyStoreService::attestDeviceIds(const KeymasterArguments& params, } // Generate temporary key. - auto& dev = mKeyStore->getDevice(); + sp<Keymaster> dev; + SecurityLevel securityLevel; + std::tie(dev, securityLevel) = mKeyStore->getMostSecureDevice(); + + if (securityLevel == SecurityLevel::SOFTWARE) { + *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR); + return Status::ok(); + } + KeyStoreServiceReturnCode error; ::std::vector<uint8_t> hidlKey; @@ -1686,6 +1702,100 @@ Status KeyStoreService::onDeviceOffBody(int32_t* aidl_return) { return Status::ok(); } +#define AIDL_RETURN(rc) \ + (*_aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(rc)), Status::ok()) + +Status KeyStoreService::importWrappedKey( + const ::android::String16& wrappedKeyAlias, const ::std::vector<uint8_t>& wrappedKey, + const ::android::String16& wrappingKeyAlias, const ::std::vector<uint8_t>& maskingKey, + const KeymasterArguments& params, int64_t rootSid, int64_t fingerprintSid, + ::android::security::keymaster::KeyCharacteristics* outCharacteristics, int32_t* _aidl_return) { + + uid_t callingUid = IPCThreadState::self()->getCallingUid(); + + if (!checkBinderPermission(P_INSERT, callingUid)) { + return AIDL_RETURN(ResponseCode::PERMISSION_DENIED); + } + + Blob wrappingKeyBlob; + String8 wrappingKeyName8(wrappingKeyAlias); + KeyStoreServiceReturnCode rc = + mKeyStore->getKeyForName(&wrappingKeyBlob, wrappingKeyName8, callingUid, TYPE_KEYMASTER_10); + if (!rc.isOk()) { + return AIDL_RETURN(rc); + } + + SecurityLevel securityLevel = wrappingKeyBlob.getSecurityLevel(); + auto dev = mKeyStore->getDevice(securityLevel); + if (!dev) { + return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE); + } + + auto hidlWrappingKey = blob2hidlVec(wrappingKeyBlob); + String8 wrappedKeyAlias8(wrappedKeyAlias); + + KeyStoreServiceReturnCode error; + + auto hidlCb = [&](ErrorCode ret, const ::std::vector<uint8_t>& keyBlob, + const KeyCharacteristics& keyCharacteristics) { + error = ret; + if (!error.isOk()) { + return; + } + if (outCharacteristics) { + *outCharacteristics = + ::android::security::keymaster::KeyCharacteristics(keyCharacteristics); + } + + // Write the key: + String8 filename( + mKeyStore->getKeyNameForUidWithDir(wrappedKeyAlias8, callingUid, ::TYPE_KEYMASTER_10)); + + Blob ksBlob(&keyBlob[0], keyBlob.size(), NULL, 0, ::TYPE_KEYMASTER_10); + ksBlob.setSecurityLevel(securityLevel); + + if (containsTag(keyCharacteristics.hardwareEnforced, Tag::USER_SECURE_ID)) { + ksBlob.setSuperEncrypted(true); + } + + error = mKeyStore->put(filename.string(), &ksBlob, get_user_id(callingUid)); + }; + + // TODO b/70904859 sanitize params and forward to keymaster + // forward rootSid and fingerprintSid + (void)params; + (void)rootSid; + (void)fingerprintSid; + rc = KS_HANDLE_HIDL_ERROR( + dev->importWrappedKey(wrappedKey, hidlWrappingKey, maskingKey, hidlCb)); + // possible hidl error + if (!rc.isOk()) { + return AIDL_RETURN(rc); + } + // now check error from callback + if (!error.isOk()) { + return AIDL_RETURN(error); + } + + // Write the characteristics: + String8 cFilename(mKeyStore->getKeyNameForUidWithDir(wrappedKeyAlias8, callingUid, + ::TYPE_KEY_CHARACTERISTICS)); + + AuthorizationSet opParams = params.getParameters(); + std::stringstream kcStream; + opParams.Serialize(&kcStream); + if (kcStream.bad()) { + return AIDL_RETURN(ResponseCode::SYSTEM_ERROR); + } + auto kcBuf = kcStream.str(); + + Blob charBlob(reinterpret_cast<const uint8_t*>(kcBuf.data()), kcBuf.size(), NULL, 0, + ::TYPE_KEY_CHARACTERISTICS); + charBlob.setSecurityLevel(securityLevel); + + return AIDL_RETURN(mKeyStore->put(cFilename.string(), &charBlob, get_user_id(callingUid))); +} + /** * Prune the oldest pruneable operation. */ @@ -2048,7 +2158,7 @@ KeyStoreServiceReturnCode KeyStoreService::upgradeKeyBlob(const String16& name, ALOGI("upgradeKeyBlob %s %d", name8.string(), uid); auto hidlKey = blob2hidlVec(*blob); - auto& dev = mKeyStore->getDevice(*blob); + auto dev = mKeyStore->getDevice(*blob); KeyStoreServiceReturnCode error; auto hidlCb = [&](ErrorCode ret, const ::std::vector<uint8_t>& upgradedKeyBlob) { @@ -2070,7 +2180,7 @@ KeyStoreServiceReturnCode KeyStoreService::upgradeKeyBlob(const String16& name, Blob newBlob(&upgradedKeyBlob[0], upgradedKeyBlob.size(), nullptr /* info */, 0 /* infoLength */, ::TYPE_KEYMASTER_10); - newBlob.setFallback(blob->isFallback()); + newBlob.setSecurityLevel(blob->getSecurityLevel()); newBlob.setEncrypted(blob->isEncrypted()); newBlob.setSuperEncrypted(blob->isSuperEncrypted()); newBlob.setCriticalToDeviceEncryption(blob->isCriticalToDeviceEncryption()); diff --git a/keystore/key_store_service.h b/keystore/key_store_service.h index da3e60a..fec44ec 100644 --- a/keystore/key_store_service.h +++ b/keystore/key_store_service.h @@ -100,7 +100,7 @@ class KeyStoreService : public android::security::BnKeystoreService, ::android::binder::Status is_hardware_backed(const ::android::String16& string, int32_t* _aidl_return) override; ::android::binder::Status clear_uid(int64_t uid, int32_t* _aidl_return) override; - ::android::binder::Status addRngEntropy(const ::std::vector<uint8_t>& data, + ::android::binder::Status addRngEntropy(const ::std::vector<uint8_t>& data, int32_t flags, int32_t* _aidl_return) override; ::android::binder::Status generateKey(const ::android::String16& alias, @@ -160,6 +160,12 @@ class KeyStoreService : public android::security::BnKeystoreService, ::android::security::keymaster::KeymasterCertificateChain* chain, int32_t* _aidl_return) override; ::android::binder::Status onDeviceOffBody(int32_t* _aidl_return) override; + ::android::binder::Status importWrappedKey( + const ::android::String16& wrappedKeyAlias, const ::std::vector<uint8_t>& wrappedKey, + const ::android::String16& wrappingKeyAlias, const ::std::vector<uint8_t>& maskingKey, + const ::android::security::keymaster::KeymasterArguments& params, int64_t rootSid, + int64_t fingerprintSid, ::android::security::keymaster::KeyCharacteristics* characteristics, + int32_t* _aidl_return) override; private: static const int32_t UID_SELF = -1; diff --git a/keystore/keymaster_enforcement.h b/keystore/keymaster_enforcement.h index d751071..d7b27fc 100644 --- a/keystore/keymaster_enforcement.h +++ b/keystore/keymaster_enforcement.h @@ -19,7 +19,7 @@ #include <stdio.h> -#include <keystore/authorization_set.h> +#include <keystore/keymaster_types.h> namespace keystore { diff --git a/keystore/keystore_aidl_hidl_marshalling_utils.h b/keystore/keystore_aidl_hidl_marshalling_utils.h index 61f1ad1..13edbd2 100644 --- a/keystore/keystore_aidl_hidl_marshalling_utils.h +++ b/keystore/keystore_aidl_hidl_marshalling_utils.h @@ -18,10 +18,12 @@ #ifndef KEYSTORE_KEYSTORE_AIDL_HIDL_MARSHALLING_UTILS_H_ #define KEYSTORE_KEYSTORE_AIDL_HIDL_MARSHALLING_UTILS_H_ -#include <binder/Parcel.h> -#include <keystore/keymaster_tags.h> #include <utility> +#include <binder/Parcel.h> + +#include <keystore/keymaster_types.h> + namespace keystore { template <typename Fn, typename... Args> diff --git a/keystore/keystore_cli_v2.cpp b/keystore/keystore_cli_v2.cpp index 95fc491..6e995e0 100644 --- a/keystore/keystore_cli_v2.cpp +++ b/keystore/keystore_cli_v2.cpp @@ -17,16 +17,13 @@ #include <string> #include <vector> -#include "base/command_line.h" -#include "base/files/file_util.h" -#include "base/strings/string_util.h" -#include "keystore/authorization_set.h" -#include "keystore/keymaster_tags.h" -#include "keystore/keystore_client_impl.h" +#include <base/command_line.h> +#include <base/files/file_util.h> +#include <base/strings/string_util.h> +#include <keystore/keymaster_types.h> +#include <keystore/keystore_client_impl.h> using base::CommandLine; -using keystore::AuthorizationSet; -//using keymaster::AuthorizationSetBuilder; using keystore::KeystoreClient; namespace { @@ -42,8 +39,8 @@ void PrintUsageAndExit() { printf("Usage: keystore_client_v2 <command> [options]\n"); printf("Commands: brillo-platform-test [--prefix=<test_name_prefix>] [--test_for_0_3]\n" " list-brillo-tests\n" - " add-entropy --input=<entropy>\n" - " generate --name=<key_name>\n" + " add-entropy --input=<entropy> [--seclevel=software|strongbox|tee(default)]\n" + " generate --name=<key_name> [--seclevel=software|strongbox|tee(default)]\n" " get-chars --name=<key_name>\n" " export --name=<key_name>\n" " delete --name=<key_name>\n" @@ -51,18 +48,20 @@ void PrintUsageAndExit() { " exists --name=<key_name>\n" " list [--prefix=<key_name_prefix>]\n" " sign-verify --name=<key_name>\n" - " [en|de]crypt --name=<key_name> --in=<file> --out=<file>\n"); + " [en|de]crypt --name=<key_name> --in=<file> --out=<file>\n" + " [--seclevel=software|strongbox|tee(default)]\n"); exit(1); } std::unique_ptr<KeystoreClient> CreateKeystoreInstance() { return std::unique_ptr<KeystoreClient>( - static_cast<KeystoreClient*>(new keystore::KeystoreClientImpl)); + static_cast<KeystoreClient*>(new keystore::KeystoreClientImpl)); } void PrintTags(const AuthorizationSet& parameters) { for (auto iter = parameters.begin(); iter != parameters.end(); ++iter) { - printf(" %s\n", stringifyTag(iter->tag)); + auto tag_str = toString(iter->tag); + printf(" %s\n", tag_str.c_str()); } } @@ -78,8 +77,9 @@ bool TestKey(const std::string& name, bool required, const AuthorizationSet& par std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance(); AuthorizationSet hardware_enforced_characteristics; AuthorizationSet software_enforced_characteristics; - auto result = keystore->generateKey("tmp", parameters, &hardware_enforced_characteristics, - &software_enforced_characteristics); + auto result = + keystore->generateKey("tmp", parameters, 0 /*flags*/, &hardware_enforced_characteristics, + &software_enforced_characteristics); const char kBoldRedAbort[] = "\033[1;31mABORT\033[0m"; if (!result.isOk()) { LOG(ERROR) << "Failed to generate key: " << result; @@ -120,9 +120,7 @@ AuthorizationSet GetRSASignParameters(uint32_t key_size, bool sha256_only) { .Padding(PaddingMode::RSA_PSS) .Authorization(TAG_NO_AUTH_REQUIRED); if (!sha256_only) { - parameters.Digest(Digest::SHA_2_224) - .Digest(Digest::SHA_2_384) - .Digest(Digest::SHA_2_512); + parameters.Digest(Digest::SHA_2_224).Digest(Digest::SHA_2_384).Digest(Digest::SHA_2_512); } return parameters; } @@ -142,9 +140,7 @@ AuthorizationSet GetECDSAParameters(uint32_t key_size, bool sha256_only) { .Digest(Digest::SHA_2_256) .Authorization(TAG_NO_AUTH_REQUIRED); if (!sha256_only) { - parameters.Digest(Digest::SHA_2_224) - .Digest(Digest::SHA_2_384) - .Digest(Digest::SHA_2_512); + parameters.Digest(Digest::SHA_2_224).Digest(Digest::SHA_2_384).Digest(Digest::SHA_2_512); } return parameters; } @@ -205,7 +201,8 @@ int BrilloPlatformTest(const std::string& prefix, bool test_for_0_3) { const char kBoldYellowWarning[] = "\033[1;33mWARNING\033[0m"; if (test_for_0_3) { printf("%s: Testing for keymaster v0.3. " - "This does not meet Brillo requirements.\n", kBoldYellowWarning); + "This does not meet Brillo requirements.\n", + kBoldYellowWarning); } int test_count = 0; int fail_count = 0; @@ -259,14 +256,14 @@ void WriteFile(const std::string& filename, const std::string& content) { } } -int AddEntropy(const std::string& input) { +int AddEntropy(const std::string& input, int32_t flags) { std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance(); - int32_t result = keystore->addRandomNumberGeneratorEntropy(input); + int32_t result = keystore->addRandomNumberGeneratorEntropy(input, flags); printf("AddEntropy: %d\n", result); return result; } -int GenerateKey(const std::string& name) { +int GenerateKey(const std::string& name, int32_t flags) { std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance(); AuthorizationSetBuilder params; params.RsaSigningKey(2048, 65537) @@ -279,8 +276,8 @@ int GenerateKey(const std::string& name) { .Authorization(TAG_NO_AUTH_REQUIRED); AuthorizationSet hardware_enforced_characteristics; AuthorizationSet software_enforced_characteristics; - auto result = keystore->generateKey(name, params, &hardware_enforced_characteristics, - &software_enforced_characteristics); + auto result = keystore->generateKey(name, params, flags, &hardware_enforced_characteristics, + &software_enforced_characteristics); printf("GenerateKey: %d\n", int32_t(result)); if (result.isOk()) { PrintKeyCharacteristics(hardware_enforced_characteristics, @@ -294,7 +291,7 @@ int GetCharacteristics(const std::string& name) { AuthorizationSet hardware_enforced_characteristics; AuthorizationSet software_enforced_characteristics; auto result = keystore->getKeyCharacteristics(name, &hardware_enforced_characteristics, - &software_enforced_characteristics); + &software_enforced_characteristics); printf("GetCharacteristics: %d\n", int32_t(result)); if (result.isOk()) { PrintKeyCharacteristics(hardware_enforced_characteristics, @@ -352,8 +349,8 @@ int SignAndVerify(const std::string& name) { sign_params.Digest(Digest::SHA_2_256); AuthorizationSet output_params; uint64_t handle; - auto result = keystore->beginOperation(KeyPurpose::SIGN, name, sign_params, - &output_params, &handle); + auto result = + keystore->beginOperation(KeyPurpose::SIGN, name, sign_params, &output_params, &handle); if (!result.isOk()) { printf("Sign: BeginOperation failed: %d\n", int32_t(result)); return result; @@ -377,8 +374,8 @@ int SignAndVerify(const std::string& name) { // We have a signature, now verify it. std::string signature_to_verify = output_data; output_data.clear(); - result = keystore->beginOperation(KeyPurpose::VERIFY, name, sign_params, &output_params, - &handle); + result = + keystore->beginOperation(KeyPurpose::VERIFY, name, sign_params, &output_params, &handle); if (!result.isOk()) { printf("Verify: BeginOperation failed: %d\n", int32_t(result)); return result; @@ -404,11 +401,11 @@ int SignAndVerify(const std::string& name) { } int Encrypt(const std::string& key_name, const std::string& input_filename, - const std::string& output_filename) { + const std::string& output_filename, int32_t flags) { std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance(); std::string input = ReadFile(input_filename); std::string output; - if (!keystore->encryptWithAuthentication(key_name, input, &output)) { + if (!keystore->encryptWithAuthentication(key_name, input, flags, &output)) { printf("EncryptWithAuthentication failed.\n"); return 1; } @@ -429,6 +426,18 @@ int Decrypt(const std::string& key_name, const std::string& input_filename, return 0; } +uint32_t securityLevelOption2Flags(const CommandLine& cmd) { + if (cmd.HasSwitch("seclevel")) { + auto str = cmd.GetSwitchValueASCII("seclevel"); + if (str == "strongbox") { + return KEYSTORE_FLAG_STRONGBOX; + } else if (str == "software") { + return KEYSTORE_FLAG_FALLBACK; + } + } + return KEYSTORE_FLAG_NONE; +} + } // namespace int main(int argc, char** argv) { @@ -444,9 +453,11 @@ int main(int argc, char** argv) { } else if (args[0] == "list-brillo-tests") { return ListTestCases(); } else if (args[0] == "add-entropy") { - return AddEntropy(command_line->GetSwitchValueASCII("input")); + return AddEntropy(command_line->GetSwitchValueASCII("input"), + securityLevelOption2Flags(*command_line)); } else if (args[0] == "generate") { - return GenerateKey(command_line->GetSwitchValueASCII("name")); + return GenerateKey(command_line->GetSwitchValueASCII("name"), + securityLevelOption2Flags(*command_line)); } else if (args[0] == "get-chars") { return GetCharacteristics(command_line->GetSwitchValueASCII("name")); } else if (args[0] == "export") { @@ -462,9 +473,9 @@ int main(int argc, char** argv) { } else if (args[0] == "sign-verify") { return SignAndVerify(command_line->GetSwitchValueASCII("name")); } else if (args[0] == "encrypt") { - return Encrypt(command_line->GetSwitchValueASCII("name"), - command_line->GetSwitchValueASCII("in"), - command_line->GetSwitchValueASCII("out")); + return Encrypt( + command_line->GetSwitchValueASCII("name"), command_line->GetSwitchValueASCII("in"), + command_line->GetSwitchValueASCII("out"), securityLevelOption2Flags(*command_line)); } else if (args[0] == "decrypt") { return Decrypt(command_line->GetSwitchValueASCII("name"), command_line->GetSwitchValueASCII("in"), diff --git a/keystore/keystore_client_impl.cpp b/keystore/keystore_client_impl.cpp index d9a824b..6d998ad 100644 --- a/keystore/keystore_client_impl.cpp +++ b/keystore/keystore_client_impl.cpp @@ -28,10 +28,11 @@ #include <utils/String16.h> #include <utils/String8.h> -#include "keystore_client.pb.h" -#include <keystore/authorization_set.h> +#include <keystore/keymaster_types.h> #include <keystore/keystore_hidl_support.h> +#include "keystore_client.pb.h" + namespace { // Use the UID of the current process. @@ -60,18 +61,18 @@ KeystoreClientImpl::KeystoreClientImpl() { } bool KeystoreClientImpl::encryptWithAuthentication(const std::string& key_name, - const std::string& data, + const std::string& data, int32_t flags, std::string* encrypted_data) { // The encryption algorithm is AES-256-CBC with PKCS #7 padding and a random // IV. The authentication algorithm is HMAC-SHA256 and is computed over the // cipher-text (i.e. Encrypt-then-MAC approach). This was chosen over AES-GCM // because hardware support for GCM is not mandatory for all Brillo devices. std::string encryption_key_name = key_name + kEncryptSuffix; - if (!createOrVerifyEncryptionKey(encryption_key_name)) { + if (!createOrVerifyEncryptionKey(encryption_key_name, flags)) { return false; } std::string authentication_key_name = key_name + kAuthenticateSuffix; - if (!createOrVerifyAuthenticationKey(authentication_key_name)) { + if (!createOrVerifyAuthenticationKey(authentication_key_name, flags)) { return false; } AuthorizationSetBuilder encrypt_params; @@ -178,24 +179,23 @@ bool KeystoreClientImpl::oneShotOperation(KeyPurpose purpose, const std::string& } KeyStoreNativeReturnCode -KeystoreClientImpl::addRandomNumberGeneratorEntropy(const std::string& entropy) { +KeystoreClientImpl::addRandomNumberGeneratorEntropy(const std::string& entropy, int32_t flags) { int32_t result; - auto binder_result = keystore_->addRngEntropy(blob2hidlVec(entropy), &result); + auto binder_result = keystore_->addRngEntropy(blob2hidlVec(entropy), flags, &result); if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; return KeyStoreNativeReturnCode(result); } KeyStoreNativeReturnCode KeystoreClientImpl::generateKey(const std::string& key_name, const AuthorizationSet& key_parameters, - AuthorizationSet* hardware_enforced_characteristics, + int32_t flags, AuthorizationSet* hardware_enforced_characteristics, AuthorizationSet* software_enforced_characteristics) { String16 key_name16(key_name.data(), key_name.size()); ::android::security::keymaster::KeyCharacteristics characteristics; int32_t result; auto binder_result = keystore_->generateKey( key_name16, ::android::security::keymaster::KeymasterArguments(key_parameters.hidl_data()), - hidl_vec<uint8_t>() /* entropy */, kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics, - &result); + hidl_vec<uint8_t>() /* entropy */, kDefaultUID, flags, &characteristics, &result); if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; /* assignment (hidl_vec<KeyParameter> -> AuthorizationSet) makes a deep copy. @@ -387,7 +387,7 @@ uint64_t KeystoreClientImpl::getNextVirtualHandle() { return next_virtual_handle_++; } -bool KeystoreClientImpl::createOrVerifyEncryptionKey(const std::string& key_name) { +bool KeystoreClientImpl::createOrVerifyEncryptionKey(const std::string& key_name, int32_t flags) { bool key_exists = doesKeyExist(key_name); if (key_exists) { bool verified = false; @@ -411,8 +411,9 @@ bool KeystoreClientImpl::createOrVerifyEncryptionKey(const std::string& key_name .Authorization(TAG_NO_AUTH_REQUIRED); AuthorizationSet hardware_enforced_characteristics; AuthorizationSet software_enforced_characteristics; - auto result = generateKey(key_name, key_parameters, &hardware_enforced_characteristics, - &software_enforced_characteristics); + auto result = + generateKey(key_name, key_parameters, flags, &hardware_enforced_characteristics, + &software_enforced_characteristics); if (!result.isOk()) { ALOGE("Failed to generate encryption key: %d", int32_t(result)); return false; @@ -424,7 +425,8 @@ bool KeystoreClientImpl::createOrVerifyEncryptionKey(const std::string& key_name return true; } -bool KeystoreClientImpl::createOrVerifyAuthenticationKey(const std::string& key_name) { +bool KeystoreClientImpl::createOrVerifyAuthenticationKey(const std::string& key_name, + int32_t flags) { bool key_exists = doesKeyExist(key_name); if (key_exists) { bool verified = false; @@ -448,8 +450,9 @@ bool KeystoreClientImpl::createOrVerifyAuthenticationKey(const std::string& key_ .Authorization(TAG_NO_AUTH_REQUIRED); AuthorizationSet hardware_enforced_characteristics; AuthorizationSet software_enforced_characteristics; - auto result = generateKey(key_name, key_parameters, &hardware_enforced_characteristics, - &software_enforced_characteristics); + auto result = + generateKey(key_name, key_parameters, flags, &hardware_enforced_characteristics, + &software_enforced_characteristics); if (!result.isOk()) { ALOGE("Failed to generate authentication key: %d", int32_t(result)); return false; diff --git a/keystore/keystore_main.cpp b/keystore/keystore_main.cpp index f4ccf04..31b9704 100644 --- a/keystore/keystore_main.cpp +++ b/keystore/keystore_main.cpp @@ -14,22 +14,28 @@ * limitations under the License. */ +#define LOG_TAG "keystore" + #include <android-base/logging.h> +#include <android/hidl/manager/1.1/IServiceManager.h> +#include <android/security/IKeystoreService.h> #include <android/system/wifi/keystore/1.0/IKeystore.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> +#include <hidl/HidlTransportSupport.h> #include <utils/StrongPointer.h> #include <wifikeystorehal/keystore.h> +#include <keystore/keystore_hidl_support.h> +#include <keystore/keystore_return_types.h> + #include "KeyStore.h" #include "Keymaster3.h" +#include "Keymaster4.h" #include "entropy.h" -#include "include/keystore/keystore_hidl_support.h" -#include "include/keystore/keystore_return_types.h" #include "key_store_service.h" #include "legacy_keymaster_device_wrapper.h" #include "permissions.h" -#include <android/security/IKeystoreService.h> /* KeyStore is a secured storage for key-value pairs. In this implementation, * each file stores one key-value pair. Keys are encoded in file names, and @@ -41,12 +47,140 @@ using ::android::sp; using ::android::hardware::configureRpcThreadpool; using ::android::system::wifi::keystore::V1_0::IKeystore; using ::android::system::wifi::keystore::V1_0::implementation::Keystore; +using ::android::hidl::manager::V1_1::IServiceManager; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::keymaster::V4_0::SecurityLevel; +using ::android::hardware::keymaster::V4_0::HmacSharingParameters; +using ::android::hardware::keymaster::V4_0::ErrorCode; using keystore::Keymaster; +using keystore::Keymaster3; +using keystore::Keymaster4; + +using keystore::KeymasterDevices; + +template <typename Wrapper> +KeymasterDevices enumerateKeymasterDevices(IServiceManager* serviceManager) { + KeymasterDevices result; + serviceManager->listByInterface( + Wrapper::WrappedIKeymasterDevice::descriptor, [&](const hidl_vec<hidl_string>& names) { + auto try_get_device = [&](const auto& name, bool fail_silent) { + auto device = Wrapper::WrappedIKeymasterDevice::getService(name); + if (fail_silent && !device) return; + CHECK(device) << "Failed to get service for \"" + << Wrapper::WrappedIKeymasterDevice::descriptor + << "\" with interface name \"" << name << "\""; + + sp<Keymaster> kmDevice(new Wrapper(device)); + auto halVersion = kmDevice->halVersion(); + SecurityLevel securityLevel = halVersion.securityLevel; + LOG(INFO) << "found " << Wrapper::WrappedIKeymasterDevice::descriptor + << " with interface name " << name << " and seclevel " + << toString(securityLevel); + CHECK(static_cast<uint32_t>(securityLevel) < result.size()) + << "Security level of \"" << Wrapper::WrappedIKeymasterDevice::descriptor + << "\" with interface name \"" << name << "\" out of range"; + auto& deviceSlot = result[securityLevel]; + if (deviceSlot) { + if (!fail_silent) { + LOG(WARNING) << "Implementation of \"" + << Wrapper::WrappedIKeymasterDevice::descriptor + << "\" with interface name \"" << name + << "\" and security level: " << toString(securityLevel) + << " Masked by other implementation of Keymaster"; + } + } else { + deviceSlot = kmDevice; + } + }; + bool has_default = false; + for (auto& n : names) { + try_get_device(n, false); + if (n == "default") has_default = true; + } + // Make sure that we always check the default device. If we enumerate only what is + // known to hwservicemanager, we miss a possible passthrough HAL. + if (!has_default) { + try_get_device("default", true /* fail_silent */); + } + }); + return result; +} -/** - * TODO implement keystore daemon using binderized keymaster HAL. - */ +void performHmacKeyHandshake(std::initializer_list<const sp<Keymaster>> keymasters) { + hidl_vec<HmacSharingParameters> hmacSharingParams(keymasters.size()); + int index = 0; + for (const auto& km : keymasters) { + if (!km) continue; + ErrorCode ec = ErrorCode::OK; + auto rc = + km->getHmacSharingParameters([&](ErrorCode error, const HmacSharingParameters& params) { + ec = error; + if (error == ErrorCode::OK) hmacSharingParams[index] = params; + }); + CHECK(rc.isOk()) << "Communication error while calling getHmacSharingParameters on" + " Keymaster with index: " + << index; + CHECK(ec == ErrorCode::OK) << "Failed to get HmacSharingParameters from" + " Keymaster with index: " + << index; + ++index; + } + hmacSharingParams.resize(index); + hidl_vec<uint8_t> sharingCheck; + index = 0; + for (const auto& km : keymasters) { + if (!km) continue; + ErrorCode ec = ErrorCode::OK; + auto rc = km->computeSharedHmac( + hmacSharingParams, [&](ErrorCode error, const hidl_vec<uint8_t>& sharingCheck_) { + ec = error; + if (error != ErrorCode::OK) return; + if (index == 0) { + sharingCheck = sharingCheck_; + } else { + CHECK(sharingCheck == sharingCheck_) + << "Hmac Key computation failed (current index: " << index << ")"; + } + }); + CHECK(rc.isOk()) << "Communication error while calling computeSharedHmac on" + " Keymaster with index: " + << index; + CHECK(ec == ErrorCode::OK) << "Failed to compute shared hmac key from" + " Keymaster with index: " + << index; + ++index; + } +} + +KeymasterDevices initializeKeymasters() { + auto serviceManager = android::hidl::manager::V1_1::IServiceManager::getService(); + CHECK(serviceManager.get()) << "Failed to get ServiceManager"; + auto result = enumerateKeymasterDevices<Keymaster4>(serviceManager.get()); + CHECK(result[SecurityLevel::TRUSTED_ENVIRONMENT] || !result[SecurityLevel::STRONGBOX]) + << "We cannot have a Strongbox keymaster implementation without a TEE implementation"; + auto softKeymaster = result[SecurityLevel::SOFTWARE]; + if (result[SecurityLevel::TRUSTED_ENVIRONMENT]) { + performHmacKeyHandshake( + {result[SecurityLevel::TRUSTED_ENVIRONMENT], result[SecurityLevel::STRONGBOX]}); + } else { + result = enumerateKeymasterDevices<Keymaster3>(serviceManager.get()); + } + if (softKeymaster) result[SecurityLevel::SOFTWARE] = softKeymaster; + if (result[SecurityLevel::SOFTWARE] && !result[SecurityLevel::TRUSTED_ENVIRONMENT]) { + LOG(WARNING) << "No secure Keymaster implementation found, but device offers insecure" + " Keymaster HAL. Using as default."; + result[SecurityLevel::TRUSTED_ENVIRONMENT] = result[SecurityLevel::SOFTWARE]; + result[SecurityLevel::SOFTWARE] = nullptr; + } + if (!result[SecurityLevel::SOFTWARE]) { + auto fbdev = android::keystore::makeSoftwareKeymasterDevice(); + CHECK(fbdev.get()) << "Unable to create Software Keymaster Device"; + result[SecurityLevel::SOFTWARE] = new keystore::Keymaster3(fbdev); + } + return result; +} int main(int argc, char* argv[]) { using android::hardware::hidl_string; @@ -56,26 +190,25 @@ int main(int argc, char* argv[]) { Entropy entropy; CHECK(entropy.open()) << "Failed to open entropy source."; - auto hwdev = android::hardware::keymaster::V3_0::IKeymasterDevice::getService(); - CHECK(hwdev.get()) << "Failed to load @3.0::IKeymasterDevice"; - sp<Keymaster> dev = new keystore::Keymaster3(hwdev); + auto kmDevices = initializeKeymasters(); - auto fbdev = android::keystore::makeSoftwareKeymasterDevice(); - if (fbdev.get() == nullptr) return -1; - sp<Keymaster> fallback = new keystore::Keymaster3(fbdev); + CHECK(kmDevices[SecurityLevel::SOFTWARE]) << "Missing software Keymaster device"; + CHECK(kmDevices[SecurityLevel::TRUSTED_ENVIRONMENT]) + << "Error no viable keymaster device found"; CHECK(configure_selinux() != -1) << "Failed to configure SELinux."; - auto halVersion = dev->halVersion(); + auto halVersion = kmDevices[SecurityLevel::TRUSTED_ENVIRONMENT]->halVersion(); CHECK(halVersion.error == keystore::ErrorCode::OK) << "Error " << toString(halVersion.error) << " getting HAL version"; // If the hardware is keymaster 2.0 or higher we will not allow the fallback device for import // or generation of keys. The fallback device is only used for legacy keys present on the // device. - bool allowNewFallbackDevice = halVersion.majorVersion >= 2 && halVersion.isSecure; + SecurityLevel minimalAllowedSecurityLevelForNewKeys = + halVersion.majorVersion >= 2 ? SecurityLevel::TRUSTED_ENVIRONMENT : SecurityLevel::SOFTWARE; - keystore::KeyStore keyStore(&entropy, dev, fallback, allowNewFallbackDevice); + keystore::KeyStore keyStore(&entropy, kmDevices, minimalAllowedSecurityLevelForNewKeys); keyStore.initialize(); android::sp<android::IServiceManager> sm = android::defaultServiceManager(); android::sp<keystore::KeyStoreService> service = new keystore::KeyStoreService(&keyStore); diff --git a/keystore/keystore_tags_utils.cpp b/keystore/keystore_tags_utils.cpp deleted file mode 100644 index 278348a..0000000 --- a/keystore/keystore_tags_utils.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* -** -** Copyright 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. -*/ - -#include <keystore/keymaster_tags.h> - -namespace keystore { - -template<typename TagList> -struct TagStringifier; - -template<typename ... Tags> -struct TagStringifier<MetaList<Tags...>> { - template<TagType tag_type, Tag tag> - static TypedTag<tag_type, tag> chooseString(TypedTag<tag_type, tag> ttag, Tag runtime_tag, - const char** result) { - if (tag == runtime_tag) { - *result = Tag2String<tag>::value(); - } - return ttag; - } - static const char* stringify(Tag tag) { - const char* result = "unknown tag"; - [] (Tags&&...) {}(chooseString(Tags(), tag, &result)...); - return result; - } -}; - -const char* stringifyTag(Tag tag) { - return TagStringifier<all_tags_t>::stringify(tag); -} - -} diff --git a/keystore/keystore_utils.cpp b/keystore/keystore_utils.cpp index 54f61cc..3da3791 100644 --- a/keystore/keystore_utils.cpp +++ b/keystore/keystore_utils.cpp @@ -25,8 +25,11 @@ #include <cutils/log.h> #include <private/android_filesystem_config.h> -#include <keystore/authorization_set.h> +#include <keystore/keymaster_types.h> #include <keystore/keystore_client.h> + +#include "blob.h" + size_t readFully(int fd, uint8_t* data, size_t size) { size_t remaining = size; while (remaining > 0) { @@ -91,3 +94,37 @@ uid_t get_app_id(uid_t uid) { uid_t get_user_id(uid_t uid) { return uid / AID_USER; } + +namespace keystore { + +hidl_vec<uint8_t> blob2hidlVec(const Blob& blob) { + hidl_vec<uint8_t> result; + result.setToExternal(const_cast<uint8_t*>(blob.getValue()), blob.getLength()); + return result; +} + +SecurityLevel flagsToSecurityLevel(int32_t flags) { + switch (flags & (KEYSTORE_FLAG_FALLBACK | KEYSTORE_FLAG_STRONGBOX)) { + case KEYSTORE_FLAG_FALLBACK: + // treating Strongbox flag as "don't care" if Fallback is set + case (KEYSTORE_FLAG_FALLBACK | KEYSTORE_FLAG_STRONGBOX): + return SecurityLevel::SOFTWARE; + case KEYSTORE_FLAG_STRONGBOX: + return SecurityLevel::STRONGBOX; + default: + return SecurityLevel::TRUSTED_ENVIRONMENT; + } +} + +uint32_t securityLevelToFlags(SecurityLevel secLevel) { + switch (secLevel) { + case SecurityLevel::SOFTWARE: + return KEYSTORE_FLAG_FALLBACK; + case SecurityLevel::STRONGBOX: + return KEYSTORE_FLAG_STRONGBOX; + default: + return 0; + } +} + +} // namespace keystore diff --git a/keystore/keystore_utils.h b/keystore/keystore_utils.h index 24844b7..f1211de 100644 --- a/keystore/keystore_utils.h +++ b/keystore/keystore_utils.h @@ -17,8 +17,7 @@ #ifndef KEYSTORE_KEYSTORE_UTILS_H_ #define KEYSTORE_KEYSTORE_UTILS_H_ -#include <stdint.h> - +#include <cstdint> #include <vector> #include <openssl/evp.h> @@ -26,9 +25,7 @@ #include <memory> -#include <keystore/authorization_set.h> - -#include "blob.h" +#include <keystore/keymaster_types.h> size_t readFully(int fd, uint8_t* data, size_t size); size_t writeFully(int fd, uint8_t* data, size_t size); @@ -57,14 +54,15 @@ struct PKCS8_PRIV_KEY_INFO_Delete { }; typedef std::unique_ptr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO; +class Blob; + namespace keystore { -inline static hidl_vec<uint8_t> blob2hidlVec(const Blob& blob) { - hidl_vec<uint8_t> result; - result.setToExternal(const_cast<uint8_t*>(blob.getValue()), blob.getLength()); - return result; -} +hidl_vec<uint8_t> blob2hidlVec(const Blob& blob); + +SecurityLevel flagsToSecurityLevel(int32_t flags); +uint32_t securityLevelToFlags(SecurityLevel secLevel); -} // namespace keystore +} // namespace keystore #endif // KEYSTORE_KEYSTORE_UTILS_H_ diff --git a/keystore/operation.h b/keystore/operation.h index 6e97346..389f9f8 100644 --- a/keystore/operation.h +++ b/keystore/operation.h @@ -24,7 +24,7 @@ #include <binder/IBinder.h> #include <utils/StrongPointer.h> -#include <keystore/keymaster_tags.h> +#include <keystore/keymaster_types.h> #include "Keymaster.h" diff --git a/keystore/tests/Android.bp b/keystore/tests/Android.bp index 6d8f75d..0ddaa00 100644 --- a/keystore/tests/Android.bp +++ b/keystore/tests/Android.bp @@ -5,6 +5,7 @@ cc_test { "-Wall", "-Werror", "-Wextra", + "-O0", ], srcs: [ "auth_token_table_test.cpp", @@ -14,7 +15,10 @@ cc_test { name: "keystore_unit_tests", tags: ["test"], static_libs: [ + "libbase", "libgtest_main", + "libhidlbase", + "libkeymaster4support", "libkeystore_test", "liblog", ], diff --git a/keystore/tests/auth_token_formatting_test.cpp b/keystore/tests/auth_token_formatting_test.cpp index 511256f..2677718 100644 --- a/keystore/tests/auth_token_formatting_test.cpp +++ b/keystore/tests/auth_token_formatting_test.cpp @@ -16,18 +16,22 @@ #include <gtest/gtest.h> -#include <android/hardware/keymaster/3.0/types.h> #include <endian.h> -#include <hardware/hw_auth_token.h> #include <hidl/HidlSupport.h> #include <keymaster/logger.h> -#include "../auth_token_table.h" +#include <keystore/keymaster_types.h> #include <keystore/keystore_hidl_support.h> +#include "../auth_token_table.h" + using std::vector; namespace keystore { + +using android::hardware::hidl_array; +using android::hardware::hidl_vec; + namespace test { namespace { @@ -66,9 +70,6 @@ StdoutLogger logger; } // namespace -using android::hardware::hidl_array; -using android::hardware::hidl_vec; - constexpr const uint8_t test_token[69] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, diff --git a/keystore/tests/auth_token_table_test.cpp b/keystore/tests/auth_token_table_test.cpp index 1a5ef90..511a78d 100644 --- a/keystore/tests/auth_token_table_test.cpp +++ b/keystore/tests/auth_token_table_test.cpp @@ -62,8 +62,8 @@ TEST(AuthTokenTableTest, Create) { AuthTokenTable table; } -HardwareAuthToken make_token(uint64_t rsid, uint64_t ssid = 0, uint64_t challenge = 0, - uint64_t timestamp = 0) { +static HardwareAuthToken make_token(uint64_t rsid, uint64_t ssid = 0, uint64_t challenge = 0, + uint64_t timestamp = 0) { HardwareAuthToken token; token.userId = rsid; token.authenticatorId = ssid; |
