Support Keymaster4
This CL changes vold from using a KM3 device directly to using the KM4
support wrapper from the KM4 support library, which supports both KM3
and KM4 devices (KM0, 1 and 2 devices are still supported as well,
because the default KM3 device is a wrapper that uses them).
In addition, I found myself getting confused about which "Keymaster"
types were locally-defined vold keymaster types and which were from
the KM4 HAL and support library, so I changd the approach to
referencing the latter, so all of them are qualified with the "km::"
namespace reference.
Test: Build & boot
Change-Id: I08ed5425641e7496f8597d5716cb3cd0cbd33a7f
diff --git a/Keymaster.cpp b/Keymaster.cpp
index c39280e..7d061bb 100644
--- a/Keymaster.cpp
+++ b/Keymaster.cpp
@@ -17,45 +17,48 @@
#include "Keymaster.h"
#include <android-base/logging.h>
-
-#include "authorization_set.h"
-#include "keymaster_tags.h"
-#include "keystore_hidl_support.h"
-
-using namespace ::keystore;
-using android::hardware::hidl_string;
+#include <keymasterV4_0/authorization_set.h>
+#include <keymasterV4_0/keymaster_utils.h>
namespace android {
namespace vold {
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+
KeymasterOperation::~KeymasterOperation() {
- if (mDevice.get()) mDevice->abort(mOpHandle);
+ if (mDevice) mDevice->abort(mOpHandle);
}
bool KeymasterOperation::updateCompletely(const char* input, size_t inputLen,
const std::function<void(const char*, size_t)> consumer) {
uint32_t inputConsumed = 0;
- ErrorCode km_error;
- auto hidlCB = [&](ErrorCode ret, uint32_t inputConsumedDelta,
- const hidl_vec<KeyParameter>& /*ignored*/, const hidl_vec<uint8_t>& _output) {
+ km::ErrorCode km_error;
+ auto hidlCB = [&](km::ErrorCode ret, uint32_t inputConsumedDelta,
+ const hidl_vec<km::KeyParameter>& /*ignored*/,
+ const hidl_vec<uint8_t>& _output) {
km_error = ret;
- if (km_error != ErrorCode::OK) return;
+ if (km_error != km::ErrorCode::OK) return;
inputConsumed += inputConsumedDelta;
consumer(reinterpret_cast<const char*>(&_output[0]), _output.size());
};
while (inputConsumed != inputLen) {
size_t toRead = static_cast<size_t>(inputLen - inputConsumed);
- auto inputBlob =
- blob2hidlVec(reinterpret_cast<const uint8_t*>(&input[inputConsumed]), toRead);
- auto error = mDevice->update(mOpHandle, hidl_vec<KeyParameter>(), inputBlob, hidlCB);
+ auto inputBlob = km::support::blob2hidlVec(
+ reinterpret_cast<const uint8_t*>(&input[inputConsumed]), toRead);
+ // TODO(swillden): Need to handle getting a VerificationToken from the TEE if mDevice is
+ // StrongBox, so we can provide it here. The VerificationToken will need to be
+ // requested/retrieved during Keymaster::begin().
+ auto error = mDevice->update(mOpHandle, hidl_vec<km::KeyParameter>(), inputBlob,
+ km::HardwareAuthToken(), km::VerificationToken(), hidlCB);
if (!error.isOk()) {
LOG(ERROR) << "update failed: " << error.description();
mDevice = nullptr;
return false;
}
- if (km_error != ErrorCode::OK) {
+ if (km_error != km::ErrorCode::OK) {
LOG(ERROR) << "update failed, code " << int32_t(km_error);
mDevice = nullptr;
return false;
@@ -70,21 +73,22 @@
}
bool KeymasterOperation::finish(std::string* output) {
- ErrorCode km_error;
- auto hidlCb = [&](ErrorCode ret, const hidl_vec<KeyParameter>& /*ignored*/,
+ km::ErrorCode km_error;
+ auto hidlCb = [&](km::ErrorCode ret, const hidl_vec<km::KeyParameter>& /*ignored*/,
const hidl_vec<uint8_t>& _output) {
km_error = ret;
- if (km_error != ErrorCode::OK) return;
+ if (km_error != km::ErrorCode::OK) return;
if (output) output->assign(reinterpret_cast<const char*>(&_output[0]), _output.size());
};
- auto error = mDevice->finish(mOpHandle, hidl_vec<KeyParameter>(), hidl_vec<uint8_t>(),
- hidl_vec<uint8_t>(), hidlCb);
+ auto error = mDevice->finish(mOpHandle, hidl_vec<km::KeyParameter>(), hidl_vec<uint8_t>(),
+ hidl_vec<uint8_t>(), km::HardwareAuthToken(),
+ km::VerificationToken(), hidlCb);
mDevice = nullptr;
if (!error.isOk()) {
LOG(ERROR) << "finish failed: " << error.description();
return false;
}
- if (km_error != ErrorCode::OK) {
+ if (km_error != km::ErrorCode::OK) {
LOG(ERROR) << "finish failed, code " << int32_t(km_error);
return false;
}
@@ -92,15 +96,21 @@
}
Keymaster::Keymaster() {
- mDevice = ::android::hardware::keymaster::V3_0::IKeymasterDevice::getService();
+ auto devices = KmDevice::enumerateAvailableDevices();
+ if (devices.empty()) return;
+ mDevice = std::move(devices[0]);
+ auto& version = mDevice->halVersion();
+ LOG(INFO) << "Using " << version.keymasterName << " from " << version.authorName
+ << " for encryption. Security level: " << toString(version.securityLevel)
+ << ", HAL: " << mDevice->descriptor() << "/" << mDevice->instanceName();
}
-bool Keymaster::generateKey(const AuthorizationSet& inParams, std::string* key) {
- ErrorCode km_error;
- auto hidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& keyBlob,
- const KeyCharacteristics& /*ignored*/) {
+bool Keymaster::generateKey(const km::AuthorizationSet& inParams, std::string* key) {
+ km::ErrorCode km_error;
+ auto hidlCb = [&](km::ErrorCode ret, const hidl_vec<uint8_t>& keyBlob,
+ const km::KeyCharacteristics& /*ignored*/) {
km_error = ret;
- if (km_error != ErrorCode::OK) return;
+ if (km_error != km::ErrorCode::OK) return;
if (key) key->assign(reinterpret_cast<const char*>(&keyBlob[0]), keyBlob.size());
};
@@ -109,7 +119,7 @@
LOG(ERROR) << "generate_key failed: " << error.description();
return false;
}
- if (km_error != ErrorCode::OK) {
+ if (km_error != km::ErrorCode::OK) {
LOG(ERROR) << "generate_key failed, code " << int32_t(km_error);
return false;
}
@@ -117,26 +127,26 @@
}
bool Keymaster::deleteKey(const std::string& key) {
- auto keyBlob = blob2hidlVec(key);
+ auto keyBlob = km::support::blob2hidlVec(key);
auto error = mDevice->deleteKey(keyBlob);
if (!error.isOk()) {
LOG(ERROR) << "delete_key failed: " << error.description();
return false;
}
- if (ErrorCode(error) != ErrorCode::OK) {
- LOG(ERROR) << "delete_key failed, code " << uint32_t(ErrorCode(error));
+ if (error != km::ErrorCode::OK) {
+ LOG(ERROR) << "delete_key failed, code " << int32_t(km::ErrorCode(error));
return false;
}
return true;
}
-bool Keymaster::upgradeKey(const std::string& oldKey, const AuthorizationSet& inParams,
+bool Keymaster::upgradeKey(const std::string& oldKey, const km::AuthorizationSet& inParams,
std::string* newKey) {
- auto oldKeyBlob = blob2hidlVec(oldKey);
- ErrorCode km_error;
- auto hidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& upgradedKeyBlob) {
+ auto oldKeyBlob = km::support::blob2hidlVec(oldKey);
+ km::ErrorCode km_error;
+ auto hidlCb = [&](km::ErrorCode ret, const hidl_vec<uint8_t>& upgradedKeyBlob) {
km_error = ret;
- if (km_error != ErrorCode::OK) return;
+ if (km_error != km::ErrorCode::OK) return;
if (newKey)
newKey->assign(reinterpret_cast<const char*>(&upgradedKeyBlob[0]),
upgradedKeyBlob.size());
@@ -146,44 +156,43 @@
LOG(ERROR) << "upgrade_key failed: " << error.description();
return false;
}
- if (km_error != ErrorCode::OK) {
+ if (km_error != km::ErrorCode::OK) {
LOG(ERROR) << "upgrade_key failed, code " << int32_t(km_error);
return false;
}
return true;
}
-KeymasterOperation Keymaster::begin(KeyPurpose purpose, const std::string& key,
- const AuthorizationSet& inParams, AuthorizationSet* outParams) {
- auto keyBlob = blob2hidlVec(key);
+KeymasterOperation Keymaster::begin(km::KeyPurpose purpose, const std::string& key,
+ const km::AuthorizationSet& inParams,
+ const km::HardwareAuthToken& authToken,
+ km::AuthorizationSet* outParams) {
+ auto keyBlob = km::support::blob2hidlVec(key);
uint64_t mOpHandle;
- ErrorCode km_error;
+ km::ErrorCode km_error;
- auto hidlCb = [&](ErrorCode ret, const hidl_vec<KeyParameter>& _outParams,
+ auto hidlCb = [&](km::ErrorCode ret, const hidl_vec<km::KeyParameter>& _outParams,
uint64_t operationHandle) {
km_error = ret;
- if (km_error != ErrorCode::OK) return;
+ if (km_error != km::ErrorCode::OK) return;
if (outParams) *outParams = _outParams;
mOpHandle = operationHandle;
};
- auto error = mDevice->begin(purpose, keyBlob, inParams.hidl_data(), hidlCb);
+ auto error = mDevice->begin(purpose, keyBlob, inParams.hidl_data(), authToken, hidlCb);
if (!error.isOk()) {
LOG(ERROR) << "begin failed: " << error.description();
- return KeymasterOperation(ErrorCode::UNKNOWN_ERROR);
+ return KeymasterOperation(km::ErrorCode::UNKNOWN_ERROR);
}
- if (km_error != ErrorCode::OK) {
+ if (km_error != km::ErrorCode::OK) {
LOG(ERROR) << "begin failed, code " << int32_t(km_error);
return KeymasterOperation(km_error);
}
- return KeymasterOperation(mDevice, mOpHandle);
+ return KeymasterOperation(mDevice.get(), mOpHandle);
}
+
bool Keymaster::isSecure() {
- bool _isSecure = false;
- auto rc =
- mDevice->getHardwareFeatures([&](bool isSecure, bool, bool, bool, bool, const hidl_string&,
- const hidl_string&) { _isSecure = isSecure; });
- return rc.isOk() && _isSecure;
+ return mDevice->halVersion().securityLevel != km::SecurityLevel::SOFTWARE;
}
} // namespace vold
@@ -216,17 +225,14 @@
return true;
}
-static AuthorizationSet keyParams(uint32_t rsa_key_size, uint64_t rsa_exponent, uint32_t ratelimit) {
- return AuthorizationSetBuilder()
- .Authorization(TAG_ALGORITHM, Algorithm::RSA)
- .Authorization(TAG_KEY_SIZE, rsa_key_size)
- .Authorization(TAG_RSA_PUBLIC_EXPONENT, rsa_exponent)
- .Authorization(TAG_PURPOSE, KeyPurpose::SIGN)
- .Authorization(TAG_PADDING, PaddingMode::NONE)
- .Authorization(TAG_DIGEST, Digest::NONE)
- .Authorization(TAG_BLOB_USAGE_REQUIREMENTS, KeyBlobUsageRequirements::STANDALONE)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .Authorization(TAG_MIN_SECONDS_BETWEEN_OPS, ratelimit);
+static km::AuthorizationSet keyParams(uint32_t rsa_key_size, uint64_t rsa_exponent,
+ uint32_t ratelimit) {
+ return km::AuthorizationSetBuilder()
+ .RsaSigningKey(rsa_key_size, rsa_exponent)
+ .NoDigestOrPadding()
+ .Authorization(km::TAG_BLOB_USAGE_REQUIREMENTS, km::KeyBlobUsageRequirements::STANDALONE)
+ .Authorization(km::TAG_NO_AUTH_REQUIRED)
+ .Authorization(km::TAG_MIN_SECONDS_BETWEEN_OPS, ratelimit);
}
int keymaster_create_key_for_cryptfs_scrypt(uint32_t rsa_key_size, uint64_t rsa_exponent,
@@ -279,31 +285,28 @@
return KeymasterSignResult::error;
}
- AuthorizationSet outParams;
+ km::AuthorizationSet outParams;
std::string key(reinterpret_cast<const char*>(key_blob), key_blob_size);
std::string input(reinterpret_cast<const char*>(object), object_size);
std::string output;
KeymasterOperation op;
- auto paramBuilder = AuthorizationSetBuilder()
- .Authorization(TAG_PADDING, PaddingMode::NONE)
- .Authorization(TAG_DIGEST, Digest::NONE);
-
+ auto paramBuilder = km::AuthorizationSetBuilder().NoDigestOrPadding();
while (true) {
- op = dev.begin(KeyPurpose::SIGN, key, paramBuilder, &outParams);
- if (op.errorCode() == ErrorCode::KEY_RATE_LIMIT_EXCEEDED) {
+ op = dev.begin(km::KeyPurpose::SIGN, key, paramBuilder, km::HardwareAuthToken(), &outParams);
+ if (op.errorCode() == km::ErrorCode::KEY_RATE_LIMIT_EXCEEDED) {
sleep(ratelimit);
continue;
} else
break;
}
- if (op.errorCode() == ErrorCode::KEY_REQUIRES_UPGRADE) {
+ if (op.errorCode() == km::ErrorCode::KEY_REQUIRES_UPGRADE) {
LOG(ERROR) << "Keymaster key requires upgrade";
return KeymasterSignResult::upgrade;
}
- if (op.errorCode() != ErrorCode::OK) {
+ if (op.errorCode() != km::ErrorCode::OK) {
LOG(ERROR) << "Error starting keymaster signature transaction: " << int32_t(op.errorCode());
return KeymasterSignResult::error;
}