diff options
| author | Janis Danisevskis <jdanis@google.com> | 2017-01-31 11:31:08 +0000 |
|---|---|---|
| committer | Janis Danisevskis <jdanis@google.com> | 2017-02-03 07:00:47 +0000 |
| commit | 6b7fa1bf178cd941aabe815d17da38d2e55d9867 (patch) | |
| tree | c668f7e423eb20f7321353fd00392e706c84d3a7 /Keymaster.cpp | |
| parent | bcbf326779eb7bbe54a38500ea0218e27d9495c6 (diff) | |
Port cryptfs to HILD keymaster HAL
Cryptfs uses keymaster for key derivation. Vold has a C++ abstraction
for Keymaster. However, cryptfs, being a pure C implementation, uses
its own abstraction of the keymaster HAL.
This patch expresses cryptfs' keymaster abstraction in terms of
vold's C++ Keymaster abstraction, consolidating the code base to a
single point where the actual keymaster HAL is beeing used.
Test: marlin device boots with FBE enabled
Change-Id: Ia51fed5508e06fd6c436cca193791e57e0ab99ea
Diffstat (limited to 'Keymaster.cpp')
| -rw-r--r-- | Keymaster.cpp | 123 |
1 files changed, 122 insertions, 1 deletions
diff --git a/Keymaster.cpp b/Keymaster.cpp index bb99cde..fd828b2 100644 --- a/Keymaster.cpp +++ b/Keymaster.cpp @@ -31,7 +31,8 @@ KeymasterOperation::~KeymasterOperation() { } bool KeymasterOperation::updateCompletely(const std::string& input, std::string* output) { - output->clear(); + if (output) + output->clear(); auto it = input.begin(); uint32_t inputConsumed; @@ -182,6 +183,126 @@ KeymasterOperation Keymaster::begin(KeyPurpose purpose, const std::string& key, } return KeymasterOperation(mDevice, mOpHandle); } +bool Keymaster::isSecure() { + bool _isSecure = false; + auto rc = mDevice->getHardwareFeatures( + [&] (bool isSecure, bool, bool, bool) { _isSecure = isSecure; }); + return rc.isOk() && _isSecure; +} } // namespace vold } // namespace android + +using namespace ::android::vold; + +int keymaster_compatibility_cryptfs_scrypt() { + return Keymaster().isSecure(); +} + +/* Create a new keymaster key and store it in this footer */ +int keymaster_create_key_for_cryptfs_scrypt(uint32_t rsa_key_size, + uint64_t rsa_exponent, + uint32_t ratelimit, + uint8_t* key_buffer, + uint32_t key_buffer_size, + uint32_t* key_out_size) +{ + Keymaster dev; + std::string key; + if (!dev) { + LOG(ERROR) << "Failed to initiate keymaster session"; + return -1; + } + if (!key_buffer || !key_out_size) { + LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":Invalid argument"; + return -1; + } + if (key_out_size) { + *key_out_size = 0; + } + + auto paramBuilder = 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); + + if (!dev.generateKey(paramBuilder, &key)) { + return -1; + } + + if (key_out_size) { + *key_out_size = key.size(); + } + + if (key_buffer_size < key.size()) { + return -1; + } + + std::copy(key.data(), key.data() + key.size(), key_buffer); + return 0; +} + +/* This signs the given object using the keymaster key. */ +int keymaster_sign_object_for_cryptfs_scrypt(const uint8_t* key_blob, + size_t key_blob_size, + uint32_t ratelimit, + const uint8_t* object, + const size_t object_size, + uint8_t** signature_buffer, + size_t* signature_buffer_size) +{ + Keymaster dev; + if (!dev) { + LOG(ERROR) << "Failed to initiate keymaster session"; + return -1; + } + if (!key_blob || !object || !signature_buffer || !signature_buffer_size) { + LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":Invalid argument"; + return -1; + } + + 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); + + while (true) { + op = dev.begin(KeyPurpose::SIGN, key, paramBuilder, &outParams); + if (op.error() == ErrorCode::KEY_RATE_LIMIT_EXCEEDED) { + sleep(ratelimit); + continue; + } else break; + } + + if (op.error() != ErrorCode::OK) { + LOG(ERROR) << "Error starting keymaster signature transaction: " << uint32_t(op.error()); + return -1; + } + + if (!op.updateCompletely(input, &output)) { + LOG(ERROR) << "Error sending data to keymaster signature transaction: " + << uint32_t(op.error()); + return -1; + } + + *signature_buffer = reinterpret_cast<uint8_t*>(malloc(output.size())); + if (*signature_buffer == nullptr) { + LOG(ERROR) << "Error allocation buffer for keymaster signature"; + return -1; + } + *signature_buffer_size = output.size(); + std::copy(output.data(), output.data() + output.size(), *signature_buffer); + return 0; +} |
