Merge "Allow Device IDs in Key attestation request"
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 @@
":IKeyAttestationApplicationIdProvider.aidl",
"KeyStore.cpp",
"Keymaster3.cpp",
+ "Keymaster4.cpp",
"auth_token_table.cpp",
"blob.cpp",
"entropy.cpp",
@@ -49,6 +50,7 @@
"libhidlbase",
"libhidltransport",
"libhwbinder",
+ "libkeymaster4support",
"libkeymaster_messages",
"libkeymaster_portable",
"libkeystore_aidl",
@@ -110,6 +112,7 @@
"libchrome",
"libhidlbase",
"libhwbinder",
+ "libkeymaster4support",
"libkeystore_binder",
],
@@ -135,6 +138,7 @@
"libhardware",
"libhidlbase",
"libhwbinder",
+ "libkeymaster4support",
"liblog",
"libprotobuf-cpp-lite",
"libutils",
@@ -144,6 +148,7 @@
"libbinder",
"libhidlbase",
"libhwbinder",
+ "libkeymaster4support",
],
}
// Library for keystore clients
@@ -152,21 +157,20 @@
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 @@
},
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 @@
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/KeyAttestationPackageInfo.cpp b/keystore/KeyAttestationPackageInfo.cpp
index 8092828..75fbb7a 100644
--- a/keystore/KeyAttestationPackageInfo.cpp
+++ b/keystore/KeyAttestationPackageInfo.cpp
@@ -25,17 +25,15 @@
KeyAttestationPackageInfo::KeyAttestationPackageInfo() = default;
-KeyAttestationPackageInfo::KeyAttestationPackageInfo(
- const String16& packageName, int32_t versionCode,
- SharedSignaturesVector signatures) :
- packageName_(new String16(packageName)), versionCode_(versionCode),
- signatures_(signatures) {
-}
+KeyAttestationPackageInfo::KeyAttestationPackageInfo(const String16& packageName,
+ int64_t versionCode,
+ SharedSignaturesVector signatures)
+ : packageName_(new String16(packageName)), versionCode_(versionCode), signatures_(signatures) {}
status_t KeyAttestationPackageInfo::writeToParcel(Parcel* parcel) const {
auto rc = parcel->writeString16(packageName_);
if (rc != NO_ERROR) return rc;
- rc = parcel->writeInt32(versionCode_);
+ rc = parcel->writeInt64(versionCode_);
if (rc != NO_ERROR) return rc;
return parcel->writeParcelableVector(signatures_);
}
@@ -43,7 +41,7 @@
status_t KeyAttestationPackageInfo::readFromParcel(const Parcel* parcel) {
auto rc = parcel->readString16(&packageName_);
if (rc != NO_ERROR) return rc;
- rc = parcel->readInt32(&versionCode_);
+ rc = parcel->readInt64(&versionCode_);
if (rc != NO_ERROR) return rc;
std::unique_ptr<SignaturesVector> temp_vector;
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 @@
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 @@
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 @@
};
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 @@
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]; }
- NullOr<sp<Keymaster>&> getFallbackDevice() {
+ 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};
+ }
+
+ 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 @@
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 @@
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 @@
[&](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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
};
/**
- * 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 @@
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 @@
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/KeyAttestationPackageInfo.h b/keystore/include/keystore/KeyAttestationPackageInfo.h
index efc33a6..92d4863 100644
--- a/keystore/include/keystore/KeyAttestationPackageInfo.h
+++ b/keystore/include/keystore/KeyAttestationPackageInfo.h
@@ -37,22 +37,22 @@
SignaturesVector;
typedef std::shared_ptr<SignaturesVector> SharedSignaturesVector;
- KeyAttestationPackageInfo(
- const String16& packageName, int32_t versionCode, SharedSignaturesVector signatures);
+ KeyAttestationPackageInfo(const String16& packageName, int64_t versionCode,
+ SharedSignaturesVector signatures);
KeyAttestationPackageInfo();
status_t writeToParcel(Parcel*) const override;
status_t readFromParcel(const Parcel* parcel) override;
const std::unique_ptr<String16>& package_name() const { return packageName_; }
- int32_t version_code() const { return versionCode_; }
+ int64_t version_code() const { return versionCode_; }
ConstSignatureIterator sigs_begin() const { return ConstSignatureIterator(signatures_); }
ConstSignatureIterator sigs_end() const { return ConstSignatureIterator(); }
private:
std::unique_ptr<String16> packageName_;
- int32_t versionCode_;
+ int64_t versionCode_;
SharedSignaturesVector signatures_;
};
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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
// 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 1db3f23..00d20bc 100644
--- a/keystore/key_store_service.cpp
+++ b/keystore/key_store_service.cpp
@@ -785,10 +785,15 @@
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 @@
}
}
- 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 @@
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 @@
}
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 @@
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 @@
}
auto hidlKeyBlob = blob2hidlVec(keyBlob);
- auto& dev = mKeyStore->getDevice(keyBlob);
+ auto dev = mKeyStore->getDevice(keyBlob);
KeyStoreServiceReturnCode error;
@@ -1024,8 +1032,12 @@
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 @@
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 @@
// 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 @@
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 @@
}
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 @@
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 @@
// 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 @@
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();
}
@@ -1575,7 +1583,7 @@
};
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);
@@ -1625,7 +1633,15 @@
}
// 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;
@@ -1687,6 +1703,100 @@
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.
*/
@@ -2049,7 +2159,7 @@
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) {
@@ -2071,7 +2181,7 @@
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 @@
::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 @@
::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_attestation_id.cpp b/keystore/keystore_attestation_id.cpp
index 7f9c38d..3d34ac5 100644
--- a/keystore/keystore_attestation_id.cpp
+++ b/keystore/keystore_attestation_id.cpp
@@ -37,6 +37,7 @@
#include <private/android_filesystem_config.h> /* for AID_SYSTEM */
#include <openssl/asn1t.h>
+#include <openssl/bn.h>
#include <openssl/sha.h>
#include <utils/String8.h>
@@ -148,10 +149,20 @@
return UNKNOWN_ERROR;
}
- if (!ASN1_INTEGER_set(attestation_package_info->version, pinfo.version_code())) {
+ BIGNUM* bn_version = BN_new();
+ if (bn_version == nullptr) {
+ return NO_MEMORY;
+ }
+ if (BN_set_u64(bn_version, static_cast<uint64_t>(pinfo.version_code())) != 1) {
+ BN_free(bn_version);
return UNKNOWN_ERROR;
}
- return NO_ERROR;
+ status_t retval = NO_ERROR;
+ if (BN_to_ASN1_INTEGER(bn_version, attestation_package_info->version) == nullptr) {
+ retval = UNKNOWN_ERROR;
+ }
+ BN_free(bn_version);
+ return retval;
}
StatusOr<std::vector<uint8_t>>
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 @@
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 @@
" 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 @@
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 @@
.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 @@
.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 @@
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 @@
}
}
-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 @@
.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 @@
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 @@
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 @@
// 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 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 @@
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 @@
} 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 @@
} 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 @@
}
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 @@
}
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 @@
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 @@
.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 @@
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 @@
.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..d5e20ba 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,138 @@
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;
-/**
- * TODO implement keystore daemon using binderized keymaster HAL.
- */
+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;
+}
+
+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());
+ 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 +188,25 @@
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_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 @@
};
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);
-} // namespace keystore
+SecurityLevel flagsToSecurityLevel(int32_t flags);
+uint32_t securityLevelToFlags(SecurityLevel secLevel);
+
+} // 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 @@
"-Wall",
"-Werror",
"-Wextra",
+ "-O0",
],
srcs: [
"auth_token_table_test.cpp",
@@ -14,7 +15,10 @@
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 @@
} // 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 @@
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;