summaryrefslogtreecommitdiff
authorXindong Xu <xindong.xu@amlogic.com>2020-04-27 01:42:41 (GMT)
committer Xindong Xu <xindong.xu@amlogic.com>2020-04-27 01:42:41 (GMT)
commit5f98c979d780115f85f8c815e57a620b73471bfc (patch)
treef5a1bed37f9244a934625bdae5c7d8246b0d7aab
parentee9f363f98df4f99de4efcec553f97ae654e474c (diff)
downloadkeymaster-q-amlogic.zip
keymaster-q-amlogic.tar.gz
keymaster-q-amlogic.tar.bz2
keymaster: sync to ref q
2e847b99eabc67bc7ba1fccb77d7aa3399eb7d75 Change-Id: I37fbba12c99ce802dd1f636d1b69922ab037875e
Diffstat
-rwxr-xr-x4.0/AmlogicKeymaster4Device.cpp571
-rwxr-xr-x4.0/android.hardware.keymaster@4.0-service.amlogic.rc4
-rwxr-xr-x4.0/service.cpp43
-rwxr-xr-x[-rw-r--r--]8efb1e1c-37e5-4326-a5d68c33726c7d57.ta11646
-rwxr-xr-xAmlogicKeymaster.cpp352
-rwxr-xr-x[-rw-r--r--]Android.mk125
-rw-r--r--aml_keymaster_device.cpp1021
-rw-r--r--aml_keymaster_device.h194
-rw-r--r--aml_keymaster_ipc.cpp128
-rw-r--r--aml_keymaster_ipc.h33
-rwxr-xr-xinclude/amlogic_keymaster/AmlogicKeymaster.h86
-rwxr-xr-xinclude/amlogic_keymaster/AmlogicKeymaster4Device.h105
-rwxr-xr-xinclude/amlogic_keymaster/amlogic_keymaster_messages.h222
-rwxr-xr-xinclude/amlogic_keymaster/ipc/amlogic_keymaster_ipc.h52
-rwxr-xr-x[-rw-r--r--]include/amlogic_keymaster/ipc/keymaster_ipc.h (renamed from keymaster_ipc.h)17
-rwxr-xr-xipc/amlogic_keymaster_ipc.cpp325
-rw-r--r--module.cpp61
-rw-r--r--unit_test/android_keymaster_messages_test.cpp732
-rw-r--r--unit_test/android_keymaster_test.cpp3976
-rw-r--r--unit_test/android_keymaster_test_utils.cpp902
-rw-r--r--unit_test/android_keymaster_test_utils.h470
-rw-r--r--unit_test/android_keymaster_utils.h306
-rw-r--r--unit_test/attestation_record.cpp690
-rw-r--r--unit_test/attestation_record.h62
-rw-r--r--unit_test/attestation_record_test.cpp145
-rw-r--r--unit_test/authorization_set_test.cpp745
-rw-r--r--unit_test/ecies_kem_test.cpp73
-rw-r--r--unit_test/gtest_main.cpp34
-rw-r--r--unit_test/hkdf_test.cpp78
-rw-r--r--unit_test/hmac_test.cpp84
-rw-r--r--unit_test/kdf1_test.cpp60
-rw-r--r--unit_test/kdf2_test.cpp86
-rw-r--r--unit_test/kdf_test.cpp46
-rw-r--r--unit_test/key_blob_test.cpp362
-rw-r--r--unit_test/keymaster0_engine.h103
-rw-r--r--unit_test/keymaster1_engine.h123
-rw-r--r--unit_test/keymaster_configuration_test.cpp68
-rw-r--r--unit_test/keymaster_enforcement_test.cpp872
-rw-r--r--unit_test/keymaster_tags.cpp173
-rw-r--r--unit_test/nist_curve_key_exchange_test.cpp219
-rw-r--r--unit_test/openssl_utils.h100
-rw-r--r--unit_test/sw_rsa_attest_root.key.pem15
42 files changed, 6493 insertions, 19016 deletions
diff --git a/4.0/AmlogicKeymaster4Device.cpp b/4.0/AmlogicKeymaster4Device.cpp
new file mode 100755
index 0000000..2cf5fb2
--- a/dev/null
+++ b/4.0/AmlogicKeymaster4Device.cpp
@@ -0,0 +1,571 @@
+/*
+ **
+ ** Copyright 2018, 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.
+ */
+
+#define LOG_TAG "android.hardware.keymaster@4.0-impl.amlogic"
+
+#include <authorization_set.h>
+#include <log/log.h>
+#include <keymaster/android_keymaster_messages.h>
+#include <amlogic_keymaster/AmlogicKeymaster4Device.h>
+#include <amlogic_keymaster/ipc/amlogic_keymaster_ipc.h>
+
+using ::keymaster::AbortOperationRequest;
+using ::keymaster::AbortOperationResponse;
+using ::keymaster::AddEntropyRequest;
+using ::keymaster::AddEntropyResponse;
+using ::keymaster::AttestKeyRequest;
+using ::keymaster::AttestKeyResponse;
+using ::keymaster::AuthorizationSet;
+using ::keymaster::BeginOperationRequest;
+using ::keymaster::BeginOperationResponse;
+using ::keymaster::ExportKeyRequest;
+using ::keymaster::ExportKeyResponse;
+using ::keymaster::FinishOperationRequest;
+using ::keymaster::FinishOperationResponse;
+using ::keymaster::GenerateKeyRequest;
+using ::keymaster::GenerateKeyResponse;
+using ::keymaster::GetKeyCharacteristicsRequest;
+using ::keymaster::GetKeyCharacteristicsResponse;
+using ::keymaster::ImportKeyRequest;
+using ::keymaster::ImportKeyResponse;
+using ::keymaster::UpdateOperationRequest;
+using ::keymaster::UpdateOperationResponse;
+using ::keymaster::ng::Tag;
+
+namespace keymaster {
+namespace V4_0 {
+namespace {
+
+inline keymaster_tag_t legacy_enum_conversion(const Tag value) {
+ return keymaster_tag_t(value);
+}
+inline Tag legacy_enum_conversion(const keymaster_tag_t value) {
+ return Tag(value);
+}
+inline keymaster_purpose_t legacy_enum_conversion(const KeyPurpose value) {
+ return keymaster_purpose_t(value);
+}
+inline keymaster_key_format_t legacy_enum_conversion(const KeyFormat value) {
+ return keymaster_key_format_t(value);
+}
+
+inline SecurityLevel legacy_enum_conversion(const keymaster_security_level_t value) {
+ return static_cast<SecurityLevel>(value);
+}
+
+inline hw_authenticator_type_t legacy_enum_conversion(const HardwareAuthenticatorType value) {
+ return static_cast<hw_authenticator_type_t>(value);
+}
+
+inline ErrorCode legacy_enum_conversion(const keymaster_error_t value) {
+ return ErrorCode(value);
+}
+
+inline keymaster_tag_type_t typeFromTag(const keymaster_tag_t tag) {
+ return keymaster_tag_get_type(tag);
+}
+
+class KmParamSet : public keymaster_key_param_set_t {
+ public:
+ KmParamSet(const hidl_vec<KeyParameter>& keyParams) {
+ params = new keymaster_key_param_t[keyParams.size()];
+ length = keyParams.size();
+ for (size_t i = 0; i < keyParams.size(); ++i) {
+ auto tag = legacy_enum_conversion(keyParams[i].tag);
+ switch (typeFromTag(tag)) {
+ case KM_ENUM:
+ case KM_ENUM_REP:
+ params[i] = keymaster_param_enum(tag, keyParams[i].f.integer);
+ break;
+ case KM_UINT:
+ case KM_UINT_REP:
+ params[i] = keymaster_param_int(tag, keyParams[i].f.integer);
+ break;
+ case KM_ULONG:
+ case KM_ULONG_REP:
+ params[i] = keymaster_param_long(tag, keyParams[i].f.longInteger);
+ break;
+ case KM_DATE:
+ params[i] = keymaster_param_date(tag, keyParams[i].f.dateTime);
+ break;
+ case KM_BOOL:
+ if (keyParams[i].f.boolValue)
+ params[i] = keymaster_param_bool(tag);
+ else
+ params[i].tag = KM_TAG_INVALID;
+ break;
+ case KM_BIGNUM:
+ case KM_BYTES:
+ params[i] = keymaster_param_blob(tag, &keyParams[i].blob[0],
+ keyParams[i].blob.size());
+ break;
+ case KM_INVALID:
+ default:
+ params[i].tag = KM_TAG_INVALID;
+ /* just skip */
+ break;
+ }
+ }
+ }
+ KmParamSet(KmParamSet&& other) noexcept
+ : keymaster_key_param_set_t{other.params, other.length} {
+ other.length = 0;
+ other.params = nullptr;
+ }
+ KmParamSet(const KmParamSet&) = delete;
+ ~KmParamSet() { delete[] params; }
+};
+
+inline hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_key_blob_t& blob) {
+ hidl_vec<uint8_t> result;
+ result.setToExternal(const_cast<unsigned char*>(blob.key_material), blob.key_material_size);
+ return result;
+}
+
+inline hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_blob_t& blob) {
+ hidl_vec<uint8_t> result;
+ result.setToExternal(const_cast<unsigned char*>(blob.data), blob.data_length);
+ return result;
+}
+
+inline hidl_vec<uint8_t> kmBuffer2hidlVec(const ::keymaster::Buffer& buf) {
+ hidl_vec<uint8_t> result;
+ result.setToExternal(const_cast<unsigned char*>(buf.peek_read()), buf.available_read());
+ return result;
+}
+
+inline static hidl_vec<hidl_vec<uint8_t>> kmCertChain2Hidl(
+ const keymaster_cert_chain_t& cert_chain) {
+ hidl_vec<hidl_vec<uint8_t>> result;
+ if (!cert_chain.entry_count || !cert_chain.entries) return result;
+
+ result.resize(cert_chain.entry_count);
+ for (size_t i = 0; i < cert_chain.entry_count; ++i) {
+ result[i] = kmBlob2hidlVec(cert_chain.entries[i]);
+ }
+
+ return result;
+}
+
+static inline hidl_vec<KeyParameter> kmParamSet2Hidl(const keymaster_key_param_set_t& set) {
+ hidl_vec<KeyParameter> result;
+ if (set.length == 0 || set.params == nullptr) return result;
+
+ result.resize(set.length);
+ keymaster_key_param_t* params = set.params;
+ for (size_t i = 0; i < set.length; ++i) {
+ auto tag = params[i].tag;
+ result[i].tag = legacy_enum_conversion(tag);
+ switch (typeFromTag(tag)) {
+ case KM_ENUM:
+ case KM_ENUM_REP:
+ result[i].f.integer = params[i].enumerated;
+ break;
+ case KM_UINT:
+ case KM_UINT_REP:
+ result[i].f.integer = params[i].integer;
+ break;
+ case KM_ULONG:
+ case KM_ULONG_REP:
+ result[i].f.longInteger = params[i].long_integer;
+ break;
+ case KM_DATE:
+ result[i].f.dateTime = params[i].date_time;
+ break;
+ case KM_BOOL:
+ result[i].f.boolValue = params[i].boolean;
+ break;
+ case KM_BIGNUM:
+ case KM_BYTES:
+ result[i].blob.setToExternal(const_cast<unsigned char*>(params[i].blob.data),
+ params[i].blob.data_length);
+ break;
+ case KM_INVALID:
+ default:
+ params[i].tag = KM_TAG_INVALID;
+ /* just skip */
+ break;
+ }
+ }
+ return result;
+}
+
+void addClientAndAppData(const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
+ ::keymaster::AuthorizationSet* params) {
+ params->Clear();
+ if (clientId.size()) {
+ params->push_back(::keymaster::TAG_APPLICATION_ID, clientId.data(), clientId.size());
+ }
+ if (appData.size()) {
+ params->push_back(::keymaster::TAG_APPLICATION_DATA, appData.data(), appData.size());
+ }
+}
+
+} // anonymous namespace
+
+AmlogicKeymaster4Device::AmlogicKeymaster4Device(AmlogicKeymaster* impl) : impl_(impl) {}
+
+AmlogicKeymaster4Device::~AmlogicKeymaster4Device() {}
+
+Return<void> AmlogicKeymaster4Device::getHardwareInfo(getHardwareInfo_cb _hidl_cb) {
+ _hidl_cb(SecurityLevel::TRUSTED_ENVIRONMENT, "AmlogicKeymaster", "Google");
+ return Void();
+}
+
+Return<void> AmlogicKeymaster4Device::getHmacSharingParameters(
+ getHmacSharingParameters_cb _hidl_cb) {
+ const GetHmacSharingParametersResponse response = impl_->GetHmacSharingParameters();
+ // response.params is not the same as the HIDL structure, we need to convert it
+ V4_0::HmacSharingParameters params;
+ params.seed.setToExternal(const_cast<uint8_t*>(response.params.seed.data),
+ response.params.seed.data_length);
+ static_assert(sizeof(response.params.nonce) == params.nonce.size(), "Nonce sizes don't match");
+ memcpy(params.nonce.data(), response.params.nonce, params.nonce.size());
+ _hidl_cb(legacy_enum_conversion(response.error), params);
+ return Void();
+}
+
+Return<void> AmlogicKeymaster4Device::computeSharedHmac(
+ const hidl_vec<HmacSharingParameters>& params, computeSharedHmac_cb _hidl_cb) {
+ ComputeSharedHmacRequest request;
+ request.params_array.params_array = new keymaster::HmacSharingParameters[params.size()];
+ request.params_array.num_params = params.size();
+ for (size_t i = 0; i < params.size(); ++i) {
+ request.params_array.params_array[i].seed = {params[i].seed.data(), params[i].seed.size()};
+ static_assert(sizeof(request.params_array.params_array[i].nonce) ==
+ decltype(params[i].nonce)::size(),
+ "Nonce sizes don't match");
+ memcpy(request.params_array.params_array[i].nonce, params[i].nonce.data(),
+ params[i].nonce.size());
+ }
+
+ auto response = impl_->ComputeSharedHmac(request);
+ hidl_vec<uint8_t> sharing_check;
+ if (response.error == KM_ERROR_OK) {
+ sharing_check = kmBlob2hidlVec(response.sharing_check);
+ }
+
+ _hidl_cb(legacy_enum_conversion(response.error), sharing_check);
+ return Void();
+}
+
+Return<void> AmlogicKeymaster4Device::verifyAuthorization(
+ uint64_t challenge, const hidl_vec<KeyParameter>& parametersToVerify,
+ const HardwareAuthToken& authToken, verifyAuthorization_cb _hidl_cb) {
+ VerifyAuthorizationRequest request;
+ request.challenge = challenge;
+ request.parameters_to_verify.Reinitialize(KmParamSet(parametersToVerify));
+ request.auth_token.challenge = authToken.challenge;
+ request.auth_token.user_id = authToken.userId;
+ request.auth_token.authenticator_id = authToken.authenticatorId;
+ request.auth_token.authenticator_type = legacy_enum_conversion(authToken.authenticatorType);
+ request.auth_token.timestamp = authToken.timestamp;
+ KeymasterBlob mac(authToken.mac.data(), authToken.mac.size());
+ request.auth_token.mac = mac;
+
+ auto response = impl_->VerifyAuthorization(request);
+
+ ::android::hardware::keymaster::V4_0::VerificationToken token;
+ token.challenge = response.token.challenge;
+ token.timestamp = response.token.timestamp;
+ token.parametersVerified = kmParamSet2Hidl(response.token.parameters_verified);
+ token.securityLevel = legacy_enum_conversion(response.token.security_level);
+ token.mac = kmBlob2hidlVec(response.token.mac);
+
+ _hidl_cb(legacy_enum_conversion(response.error), token);
+
+ return Void();
+}
+
+Return<ErrorCode> AmlogicKeymaster4Device::addRngEntropy(const hidl_vec<uint8_t>& data) {
+ if (data.size() == 0) return ErrorCode::OK;
+ AddEntropyRequest request;
+ request.random_data.Reinitialize(data.data(), data.size());
+
+ AddEntropyResponse response;
+ impl_->AddRngEntropy(request, &response);
+
+ return legacy_enum_conversion(response.error);
+}
+
+Return<void> AmlogicKeymaster4Device::generateKey(const hidl_vec<KeyParameter>& keyParams,
+ generateKey_cb _hidl_cb) {
+ GenerateKeyRequest request;
+ request.key_description.Reinitialize(KmParamSet(keyParams));
+
+ GenerateKeyResponse response;
+ impl_->GenerateKey(request, &response);
+
+ KeyCharacteristics resultCharacteristics;
+ hidl_vec<uint8_t> resultKeyBlob;
+ if (response.error == KM_ERROR_OK) {
+ resultKeyBlob = kmBlob2hidlVec(response.key_blob);
+ resultCharacteristics.hardwareEnforced = kmParamSet2Hidl(response.enforced);
+ resultCharacteristics.softwareEnforced = kmParamSet2Hidl(response.unenforced);
+ }
+ _hidl_cb(legacy_enum_conversion(response.error), resultKeyBlob, resultCharacteristics);
+ return Void();
+}
+
+Return<void> AmlogicKeymaster4Device::getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
+ const hidl_vec<uint8_t>& clientId,
+ const hidl_vec<uint8_t>& appData,
+ getKeyCharacteristics_cb _hidl_cb) {
+ GetKeyCharacteristicsRequest request;
+ request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+ addClientAndAppData(clientId, appData, &request.additional_params);
+
+ GetKeyCharacteristicsResponse response;
+ impl_->GetKeyCharacteristics(request, &response);
+
+ KeyCharacteristics resultCharacteristics;
+ if (response.error == KM_ERROR_OK) {
+ resultCharacteristics.hardwareEnforced = kmParamSet2Hidl(response.enforced);
+ resultCharacteristics.softwareEnforced = kmParamSet2Hidl(response.unenforced);
+ }
+ _hidl_cb(legacy_enum_conversion(response.error), resultCharacteristics);
+ return Void();
+}
+
+Return<void> AmlogicKeymaster4Device::importKey(const hidl_vec<KeyParameter>& params,
+ KeyFormat keyFormat,
+ const hidl_vec<uint8_t>& keyData,
+ importKey_cb _hidl_cb) {
+ ImportKeyRequest request;
+ request.key_description.Reinitialize(KmParamSet(params));
+ request.key_format = legacy_enum_conversion(keyFormat);
+ request.SetKeyMaterial(keyData.data(), keyData.size());
+
+ ImportKeyResponse response;
+ impl_->ImportKey(request, &response);
+
+ KeyCharacteristics resultCharacteristics;
+ hidl_vec<uint8_t> resultKeyBlob;
+ if (response.error == KM_ERROR_OK) {
+ resultKeyBlob = kmBlob2hidlVec(response.key_blob);
+ resultCharacteristics.hardwareEnforced = kmParamSet2Hidl(response.enforced);
+ resultCharacteristics.softwareEnforced = kmParamSet2Hidl(response.unenforced);
+ }
+ _hidl_cb(legacy_enum_conversion(response.error), resultKeyBlob, resultCharacteristics);
+ return Void();
+}
+
+Return<void> AmlogicKeymaster4Device::importWrappedKey(
+ const hidl_vec<uint8_t>& wrappedKeyData, const hidl_vec<uint8_t>& wrappingKeyBlob,
+ const hidl_vec<uint8_t>& maskingKey, const hidl_vec<KeyParameter>& unwrappingParams,
+ uint64_t passwordSid, uint64_t biometricSid, importWrappedKey_cb _hidl_cb) {
+ ImportWrappedKeyRequest request;
+ request.SetWrappedMaterial(wrappedKeyData.data(), wrappedKeyData.size());
+ request.SetWrappingMaterial(wrappingKeyBlob.data(), wrappingKeyBlob.size());
+ request.SetMaskingKeyMaterial(maskingKey.data(), maskingKey.size());
+ request.additional_params.Reinitialize(KmParamSet(unwrappingParams));
+ request.password_sid = passwordSid;
+ request.biometric_sid = biometricSid;
+
+ ImportWrappedKeyResponse response;
+ impl_->ImportWrappedKey(request, &response);
+
+ KeyCharacteristics resultCharacteristics;
+ hidl_vec<uint8_t> resultKeyBlob;
+ if (response.error == KM_ERROR_OK) {
+ resultKeyBlob = kmBlob2hidlVec(response.key_blob);
+ resultCharacteristics.hardwareEnforced = kmParamSet2Hidl(response.enforced);
+ resultCharacteristics.softwareEnforced = kmParamSet2Hidl(response.unenforced);
+ }
+ _hidl_cb(legacy_enum_conversion(response.error), resultKeyBlob, resultCharacteristics);
+ return Void();
+}
+
+Return<void> AmlogicKeymaster4Device::exportKey(KeyFormat exportFormat,
+ const hidl_vec<uint8_t>& keyBlob,
+ const hidl_vec<uint8_t>& clientId,
+ const hidl_vec<uint8_t>& appData,
+ exportKey_cb _hidl_cb) {
+ ExportKeyRequest request;
+ request.key_format = legacy_enum_conversion(exportFormat);
+ request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+ addClientAndAppData(clientId, appData, &request.additional_params);
+
+ ExportKeyResponse response;
+ impl_->ExportKey(request, &response);
+
+ hidl_vec<uint8_t> resultKeyBlob;
+ if (response.error == KM_ERROR_OK) {
+ resultKeyBlob.setToExternal(response.key_data, response.key_data_length);
+ }
+ _hidl_cb(legacy_enum_conversion(response.error), resultKeyBlob);
+ return Void();
+}
+
+Return<void> AmlogicKeymaster4Device::attestKey(const hidl_vec<uint8_t>& keyToAttest,
+ const hidl_vec<KeyParameter>& attestParams,
+ attestKey_cb _hidl_cb) {
+ AttestKeyRequest request;
+ request.SetKeyMaterial(keyToAttest.data(), keyToAttest.size());
+ request.attest_params.Reinitialize(KmParamSet(attestParams));
+
+ AttestKeyResponse response;
+ impl_->AttestKey(request, &response);
+
+ hidl_vec<hidl_vec<uint8_t>> resultCertChain;
+ if (response.error == KM_ERROR_OK) {
+ resultCertChain = kmCertChain2Hidl(response.certificate_chain);
+ }
+ _hidl_cb(legacy_enum_conversion(response.error), resultCertChain);
+ return Void();
+}
+
+Return<void> AmlogicKeymaster4Device::upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+ const hidl_vec<KeyParameter>& upgradeParams,
+ upgradeKey_cb _hidl_cb) {
+ UpgradeKeyRequest request;
+ request.SetKeyMaterial(keyBlobToUpgrade.data(), keyBlobToUpgrade.size());
+ request.upgrade_params.Reinitialize(KmParamSet(upgradeParams));
+
+ UpgradeKeyResponse response;
+ impl_->UpgradeKey(request, &response);
+
+ if (response.error == KM_ERROR_OK) {
+ _hidl_cb(ErrorCode::OK, kmBlob2hidlVec(response.upgraded_key));
+ } else {
+ _hidl_cb(legacy_enum_conversion(response.error), hidl_vec<uint8_t>());
+ }
+ return Void();
+}
+
+Return<ErrorCode> AmlogicKeymaster4Device::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
+ DeleteKeyRequest request;
+ request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+
+ DeleteKeyResponse response;
+ impl_->DeleteKey(request, &response);
+
+ return legacy_enum_conversion(response.error);
+}
+
+Return<ErrorCode> AmlogicKeymaster4Device::deleteAllKeys() {
+ DeleteAllKeysRequest request;
+ DeleteAllKeysResponse response;
+ impl_->DeleteAllKeys(request, &response);
+
+ return legacy_enum_conversion(response.error);
+}
+
+Return<ErrorCode> AmlogicKeymaster4Device::destroyAttestationIds() {
+ return ErrorCode::UNIMPLEMENTED;
+}
+
+Return<void> AmlogicKeymaster4Device::begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+ const hidl_vec<KeyParameter>& inParams,
+ const HardwareAuthToken& authToken, begin_cb _hidl_cb) {
+ (void)authToken;
+ BeginOperationRequest request;
+ request.purpose = legacy_enum_conversion(purpose);
+ request.SetKeyMaterial(key.data(), key.size());
+ request.additional_params.Reinitialize(KmParamSet(inParams));
+
+ BeginOperationResponse response;
+ impl_->BeginOperation(request, &response);
+
+ hidl_vec<KeyParameter> resultParams;
+ if (response.error == KM_ERROR_OK) {
+ resultParams = kmParamSet2Hidl(response.output_params);
+ }
+
+ _hidl_cb(legacy_enum_conversion(response.error), resultParams, response.op_handle);
+ return Void();
+}
+
+Return<void> AmlogicKeymaster4Device::update(uint64_t operationHandle,
+ const hidl_vec<KeyParameter>& inParams,
+ const hidl_vec<uint8_t>& input,
+ const HardwareAuthToken& authToken,
+ const VerificationToken& verificationToken,
+ update_cb _hidl_cb) {
+ (void)authToken;
+ (void)verificationToken;
+ UpdateOperationRequest request;
+ UpdateOperationResponse response;
+ hidl_vec<KeyParameter> resultParams;
+ hidl_vec<uint8_t> resultBlob;
+ uint32_t resultConsumed = 0;
+
+ request.op_handle = operationHandle;
+ request.additional_params.Reinitialize(KmParamSet(inParams));
+
+ size_t inp_size = input.size();
+ size_t ser_size = request.SerializedSize();
+
+ if (ser_size > AMLOGIC_KEYMASTER_SEND_BUF_SIZE) {
+ response.error = KM_ERROR_INVALID_INPUT_LENGTH;
+ } else {
+ if (ser_size + inp_size > AMLOGIC_KEYMASTER_SEND_BUF_SIZE) {
+ inp_size = AMLOGIC_KEYMASTER_SEND_BUF_SIZE - ser_size;
+ }
+ request.input.Reinitialize(input.data(), inp_size);
+
+ impl_->UpdateOperation(request, &response);
+
+ if (response.error == KM_ERROR_OK) {
+ resultConsumed = response.input_consumed;
+ resultParams = kmParamSet2Hidl(response.output_params);
+ resultBlob = kmBuffer2hidlVec(response.output);
+ }
+ }
+ _hidl_cb(legacy_enum_conversion(response.error), resultConsumed, resultParams, resultBlob);
+ return Void();
+}
+
+Return<void> AmlogicKeymaster4Device::finish(uint64_t operationHandle,
+ const hidl_vec<KeyParameter>& inParams,
+ const hidl_vec<uint8_t>& input,
+ const hidl_vec<uint8_t>& signature,
+ const HardwareAuthToken& authToken,
+ const VerificationToken& verificationToken,
+ finish_cb _hidl_cb) {
+ (void)authToken;
+ (void)verificationToken;
+ FinishOperationRequest request;
+ request.op_handle = operationHandle;
+ request.input.Reinitialize(input.data(), input.size());
+ request.signature.Reinitialize(signature.data(), signature.size());
+ request.additional_params.Reinitialize(KmParamSet(inParams));
+
+ FinishOperationResponse response;
+ impl_->FinishOperation(request, &response);
+
+ hidl_vec<KeyParameter> resultParams;
+ hidl_vec<uint8_t> resultBlob;
+ if (response.error == KM_ERROR_OK) {
+ resultParams = kmParamSet2Hidl(response.output_params);
+ resultBlob = kmBuffer2hidlVec(response.output);
+ }
+ _hidl_cb(legacy_enum_conversion(response.error), resultParams, resultBlob);
+ return Void();
+}
+
+Return<ErrorCode> AmlogicKeymaster4Device::abort(uint64_t operationHandle) {
+ AbortOperationRequest request;
+ request.op_handle = operationHandle;
+
+ AbortOperationResponse response;
+ impl_->AbortOperation(request, &response);
+
+ return legacy_enum_conversion(response.error);
+}
+} // namespace V4_0
+} // namespace keymaster
diff --git a/4.0/android.hardware.keymaster@4.0-service.amlogic.rc b/4.0/android.hardware.keymaster@4.0-service.amlogic.rc
new file mode 100755
index 0000000..53b1651
--- a/dev/null
+++ b/4.0/android.hardware.keymaster@4.0-service.amlogic.rc
@@ -0,0 +1,4 @@
+service vendor.keymaster-4-0 /vendor/bin/hw/android.hardware.keymaster@4.0-service.amlogic
+ class early_hal
+ user system
+ group system drmrpc
diff --git a/4.0/service.cpp b/4.0/service.cpp
new file mode 100755
index 0000000..6a7105a
--- a/dev/null
+++ b/4.0/service.cpp
@@ -0,0 +1,43 @@
+/*
+**
+** Copyright 2018, 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 <android-base/logging.h>
+#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+#include <hidl/HidlTransportSupport.h>
+#include <amlogic_keymaster/AmlogicKeymaster.h>
+#include <amlogic_keymaster/AmlogicKeymaster4Device.h>
+
+int main() {
+ ::android::hardware::configureRpcThreadpool(1, true);
+ auto trustyKeymaster = new keymaster::AmlogicKeymaster();
+ int err = trustyKeymaster->Initialize();
+ if (err != 0) {
+ LOG(FATAL) << "Could not initialize AmlogicKeymaster (" << err << ")";
+ return -1;
+ }
+
+ auto keymaster = new ::keymaster::V4_0::AmlogicKeymaster4Device(trustyKeymaster);
+
+ auto status = keymaster->registerAsService();
+ if (status != android::OK) {
+ LOG(FATAL) << "Could not register service for Keymaster 4.0 (" << status << ")";
+ return -1;
+ }
+
+ android::hardware::joinRpcThreadpool();
+ return -1; // Should never get here.
+}
diff --git a/8efb1e1c-37e5-4326-a5d68c33726c7d57.ta b/8efb1e1c-37e5-4326-a5d68c33726c7d57.ta
index 4f50e04..97a792b 100644..100755
--- a/8efb1e1c-37e5-4326-a5d68c33726c7d57.ta
+++ b/8efb1e1c-37e5-4326-a5d68c33726c7d57.ta
@@ -1,2867 +1,2758 @@
-HSTO
-
-
-
-
-ve tv@`DAFaDAFataEv!etA
-tv@`DAFaDAFataEvAet!
-tEvet!
-PV!FPaNXAB\!HPdJTdAFFfaH@LT!NJF^!BZFaDABb!Fa@DAB!@H\B!@TNRfZFaB!@DAF`D@@RVFaZ\HB!LJTB\NADA
-RB~a
-|!
-vNLNaJAFaDAH\A@ zHrA@\AH t
-xxAp! pFPNXNaJAFaDAH
-^TPZ\a RXaPV=@FJ@B(LLHNHhB!DDANFaHԁJޡ
-z@ B,
-~@DA@B!B(Jԡ
-tEvetavA@`DAFaDAFatEv!e t
-tEvaetvA@`DAFaDAFatE vet!
-tEvaet v@`DAFaDAFatEvAet!
-p
-  
-   
-
-  
- 
-
-  
- Bit-sliced AES for NEON, CRYPTOGAMS by <appro@openssl.org>
-ve tv@`DAFaDAFataEv!etA
-tv@`DAFaDAFataEvAet!
-tEvet!
-\Pa T
-P V^aZXaZ^ARaZ!NXaBTAJV!DXdLPdAFFfaH@FP!NJNR!J\FaDABb!Fa@DAB!@DVB!HPBZn\FaB!@DAF`D@@RVFaZ\HB!LLPJVNADA ZJ~a | vNLNaJAFaDAH
-ppaNXBTNaJAFaDAHT@zAHr@THtANLNADARB~a|!vxxp!pAP\! P^
-TVAZaZ V=_@ B,
-~@DA@B!B(J֡
-tEvetAva@`DAFaDAFa tEv!et
-tEvAetva@`DAFaDAFa tEvet!
-tEvAe tv@`DAFaDAFatEvaet!
-p
-|  J  j 2
-*݀ *lFUF
-
-
-
-P
-Q
-~ Q
-
-**` *r! *#` Jt *` j v ` xa j* ` z `|A JP
--*
->рP
-Ң 
- ЁB!ZrH@*DA Z'
-th@J ЁFaZ' *
-'
-z$ | F~hFP``B
- Rp
-B! ZrH@* ЁDAZ'
-
-z$ | FhF``B
-
-z FhF_``B
-
-p
-N
-`
-0
-
-RFF -/
-
-#Fb Ш   &
-hF
-RFF w-/
-
-#F#
-" 
- ЁB!ZrH@*DA Z'
-th@J ЁFaZ' *
-'
-z$ | F~hF``B
- Rp
-B! ZrH@* ЁDAZ'
-
-z$ | FhF
-
-z FhF``B
-
-r
-P
-`
-2
-
-FRFF -/
-
-#F*Fb ;В Zp( B!'
-hF
-RFF -/
-
-FF
-hF
-RF i-/
-
-#F#
- 
- 
- N \
- N 
- NKN \(@ NlN|?m
- #
-n B hl88 P`P"RbR!
-  
-zl | B~l @+IB!+BDA Fa &(h
-N  
-N \ 
-N  
-NK N \{NlN|?2
- A
-B
-«@
-z  | B~  x M
-HB b
-zl | ~l @ BB! DA FaN N B8Н
-  $
-/ 6$=&i''NͲuu t,,X.4-6nnZZ[RRM;;vaַγ}{))R>q//^SShѹ
+HSTO
+
+
+
+
+Kl k kh k
+W@ y@Olz@ |O2S, S(@ $4AS$@qS!L@qS!L@@1S!L@!1BS!rS" L@T@ a@Olb@ |O2S, S(p '7AS'pqS!O@qS!O@@1S!O@!1BS!rS" O@W@y@Olz@ |O2S, S(@ $4AS$@qS!L@qS!L@@1S!L@!1BS!rS" a@Q@L@OlJ@ |O2S, S(p '7DS'ptS$@g@tS$@|@@7S'p|@'7BS'prS" |@T@g@ O7ObrS" J@S(J@!1LS! |J@S,J@qS!J@@1S!J@!1GS!wJ@S'J@
+f@ObO6rS" Q@S% Q@"2JS"
+zQ@S* Q@rS" Q@@2S" Q@"2FS" vS&0Q@K@OOSU1AJ@$"c@31J@ABK@1J@`C`
+P7Of O2{DvS&`S+`&6JS&`
+zS*OhxS(@S((BS(rS" r@U@OfO5vS&`w@S(`w@&6NS&`~~@S.p~@wS'p~@@7S'p~@'7ES'puS%P~@
+V@ u@Onr@~O2S.S(p'7ES'puS%Po@uS%Po@@5S%Po@%5BS%PrS" o@ W@ }@Onz@~O2S.S(`&6ES&`uS%Pn@uS%Pn@@5S%Pn@%5BS%PrS" n@V@u@Onr@~O2S.S(p'7ES'puS%Po@uS%Po@@5S%Po@%5BS%PrS" o@W@z@On}@~O5S.S(`&6BS&`rS" V@rS" V@@2S" V@"2ES" uS%Pr@j@V@OnU@~O5S.S(p'7FS'pvS&`w@vS&`~@@7S'p~@'7ES'puS%P~@u@o@O7OfvS&`r@S(`V@"2S" V@BrS" V@rS" V@@2S" V@"2GS" wV@S' V@w@O7ObrS" j@S(Pj@%5S%Pj@EuS%Pj@uS%Pj@@5S%Pj@%5GS%Pwj@S'Pj@ T@O4OdtS$@t@S'`t@&6LS&` |t@S,`t@vS&`t@@6S&`t@&6ES&`uS%Pt@l@ a@OeO1uS%Pj@S&Pj@%5IS%P yj@S)Pj@uS%Pj@@5S%Pj@%5AS%PqS!0j@S@+
+Kl k khh k
+W@ y@Onz@~O2S.S(@$4AS$@qS!L@qS!L@@1S!L@!1BS!rS" L@T@ a@Onb@~O2S.S(p'7AS'pqS!O@qS!O@@1S!O@!1BS!rS" O@W@y@Onz@~O2S.S(@$4AS$@qS!L@qS!L@@1S!L@!1BS!rS" a@Q@L@OnJ@~O2S.S(p'7DS'ptS$@g@tS$@|@@7S'p|@'7BS'prS" |@T@g@O7ObrS" J@S(J@!1NS!~J@S.J@qS!J@@1S!J@!1GS!wJ@S'J@
+f@ObO6rS" Q@S% Q@"2JS"
+zQ@S* Q@rS" Q@@2S" Q@"2FS" vS&0Q@K@OO`C`
+7Of O2{DvS&`S+`&6JS&`
+zS*OhxS(@S((BS(rS" r@ U@OfO5vS&`S(`&6LS&` |S,Ol |S, @ S,,E uS,S%P n@
+V@ u@Onr@~O2S. S( .ES.uS%P  uS%P @5S%P %5BS%PrS"    On~ S.O2S(`&6ES&`uS%Pn@uS%Pn@@5S%Pn@%5BS%PrS" n@V@u@Onr@~O2S. S( .ES.uS%P  uS%P @5S%P %5BS%PrS"    On ~O5S.S(`&6BS&`rS" V@rS" V@@2S" V@"2ES" uS%Pr@j@V@OnU@~O5S. S( .FS.vS&`  vS&` @ S, , ES,uS%P u@ OfO<vS&`r@S(`V@"2S" V@BrS" V@ObrS" V@@2S" V@"2LS" |V@S, V@ ObO<rS" j@S(Pj@%5S%Pj@EuS%Pj@OeuS%Pj@@5S%Pj@%5LS%P |j@S,Pj@W@T@O4t S$@t@S,`t@&6GS&`wt@S'`t@vS&`t@@6S&`t@&6ES&`uS%Pt@l@ a@OeO1uS%Pj@S&Pj@%5IS%P yj@S)Pj@uS%Pj@@5S%Pj@%5AS%PqS!0j@S@rE
+O
+iiE
+iE
+A
+c6OuC4vdQO|C0 F`
+Kh hiiQiihhQhh"g 4#% 4O
+CC FC
+BFC
+C
+
+%
+CH
+$CF
+)FN"FCC FC)C9FC(CFFFCI&C C
+!FC*F
+CDCF
+CF*]AFF
+CF"CN,F C)&F4(C C @'I AC  &L C $G
+F%FECp CC 
+FhtxlCCF C C(C C8C@B  CR*_A C F C "I C H CF CF C F&C FC$CFFFC@ B +zO
+F
+FF
+C
+C
+
+*C"FxF
+C
+F|p C C CFC?CC0C CRCF
+C CI^A
+CFC FI " C H  CNC I 'FC  L 
+)O1g,F
+8FC1F
+CeCF
+C ^A"C I 
+C $L%
+
+`FC
+N C "F C 
+xI  FC pH0F C L F
+F )FB
+FB%B"
+CFB
+B
+
+B $L YB  GF"44444 4lB 
+4444FB
+ BBBF  BA[xBUA B[WA
+pB F B I 
+BF )B
+B
+B
+
+BhFF
+,B %I AB  $L B  G"4444`4 44
+444444BF
+
+Bv BaB BB L [B WA hB L  pB
+
+FB F(K F8B
+pB@ BFB
+:FI 0F
+I%I F
+phL  F %gFL I $` CC C"
+L  }L ,L L  FC
+
+CC
+
+C F"K 8C
+@g1F:F
+C
+C LC&F
+ C
+NC^AC NNtFDC4FC
+C6_AC K
+c c
+c7O|C0 `
+ FF FF F
+ a]aa--OFhhLhPh
-II
- l$$H\\]ŸnӽשּׁCbbĨ917Ӌyy2CȋY77nmmڌdձNN੩IllVV%ϯeeʎzz鮮Gպoxxo%%Jr..\$8WǴsQƗ#|ݡtt!>KKܽa ppB>>|ĵqffHHaa_55jWWйiX':'8볘+3"iip٩3-"< I·UUx((PzߥY  ڿe1BBhhAA)w--Z˰{TTֻm:,c|w{ko0g+׫vʂ}YGԢr&6?4q1#'u ,nZR;ֳ)/S
-I$\Ӭby7mNlVezx%.tKp>fHa5WiَU(ߌ BhA-T
-
-'@G(P)`)
-]
-
-vOeGP(p Ee EEVKE %
-vOO eGP(p Ee EEVKE %
-vOO eGP(p Ee EEVKE %
-|B|
-!\hT[:.6$g
- WҖO aiKwZ
-*C"< Nj򹨶-ȩWLuݙ`&r\;fD4~[v)C#hc1cB@" Ƅ}$J=2m)K/0R wl+pH"dGČ?,}V3"NI8ʌ6 Ԙρ(z&ڤ?:, xP_jbF~Tؐ^9.Â]|i-o%;ȧ}nc{; x&Yn쨚Oen~ϼ!ٛ6oJ |)11#?*0f57NtʂАا3JAP/MvMCTMўjL,QeF^]5st.A ZgRے3VGmaךz 7Y<'5a<GzYҜ?sUy7sS[_o=߆Dx>h,4$8_@r %⼋I<(A q9޳ ؐVda{p2t\lHBWR j068@|9/4CDT{2#=L BN.f($v[Im%rdhԤ\]elpHP^FWث
-XE,?k:AOgst"57unGq)ʼnobV>Ky xZݨ31Y'_`QJ -zɜ;M*<Sa+~w&icU! }-_jFF
-j
-ap x
-bx  AGB(p F
-c x@
-
-0
-N
-<
-`jIYF,
-B
-GL`,
-"*
-
-"* #
-
-"
-
-"J 0C*"
-"0SCC*"
-"CPAJ/
-"J 0C*"@CC
-"0SBCC*"@CC
-"BCPAJ/
- cPErPEBggg' p`_
-
-B'p@`P `p0
-f
- 
-n"*c
-`(@**g,.^
-`(*,@.^
-g`Vbb##bCC*g``##`CC^ 0 R^`1bb##bCC^!F
-g`PR
-AD*g T$ V!& JAAf*0
-
-g`Vb##bCC*g`##`CCb##bCCh##hCC
-R
-!B&  *A
-& 
-$cPE
-g`V""##"CC*g 󀃰 #󂣰 J \, CC j \!,"󈃰"󊣰 j`p"C#\Al(󈃰(󊣰^A(##^a*󈃰*󊣰aF9*##!:,󈃰,󊣰#8Ͽ,##% R...#XA
-g JZa` jaF*g jA* .
-
-g`V""##*g  ##""## J ((##j **##^A,,##^a..#
-j
-O
- DN
-O
-SkO
- DN
-*}mJ#BjÊ㪭¥ "B,\b.^ǂ bd!fAha: jJ
-Ȭ¬"} mBbÂ㢭­"B,\b.^ǂ bd!fAha: jJ<
-oFF=
-
-?F
-"B< bǂ> J׬&"B}bmJâѬ=ȭ
-"Bb>悰ǢpJ&"Bb}‚mJǬѬ=
-"B
-Bb}¢m٬JǬ="
-Bb Ƣr( tHJBf*b}جm٬J"=B
-bł@墭tH@"vhJbfJլ}جmJ"B=b
-Ţ`­vh`"Bx麗Jfjլ}m"JBb=Ă
-x煮"Bbz﨨Jf튬}"mBJbmĢ!­"z﫨Bb<*J 
-
-"f
-Bjb6¢¬j"BbƢ­G*Bf*bj6᢬¬"jBbł墭­"GJbfJj6¬"BjbŢ­"BGjfjj׬6"BbjĂ䢭­"BbGfj׬6"BbĢmǭ! 
-"BbG TAGVaGBG &ffBf B B=
- B BF
-Ȱf=
-fBf>
-=Ȱ?
-p=qr(=s8!tH=(uXAvh=Hwxax=hyz={&¸=ч?
+i O{Si`
+ D1F&F FD 2F)aDD
+ja0D
+a h-OFh
+K
+kK "E
+ ziE
-w 
-g
-OD
-NWDQ
-f
-ND
-NVDQ
-e
-MD
-NUDQ
-d
-LD
-NTDQ
-c
-KD
-NSDF љQ
-g
-OD
-NWD<4
- 
-OyfyN
-ND
-VD<4
- 
-OyeyN
-MD
-UD<4
- 
-OydyN
-LD
-TD<4
- 
-OycyN
-KD
-SD
- 
-OygyN
-ODWD<4
- 
-OyfyN
-NDVD<4
- 
-OyeyN
-MDUD<4
- 
-OydyN
-LDTD<4
- 
-OycyN
-KDSDF o<4
- 
-OygyN
- ODWD<4
- 
-OyfyN
- NDVD<4
- 
-OyeyN
- MDUD<4
- 
-OydyN
- LDTD<4
- 
-OycyN
- KDSDF [<
-  
-dlHL*LJ
-OD flgn
- O_D@%
-NDHԁ Hf
- L@ O^D$
-MDh xe
- Oz]D#
-zLD @d@
- O\DD('
-KD `c
- O[DB!&
-ODHց Hg
- LO_D%
-NDh( x$f
- Oz^D$
-zMD B! eB!
- O]DFH#
-LD b$d
- O\DDA'
-KDH (Hc
- LO[D&
-ODhH ,xDg
- Oz_D%
-zND DA0fDA
- O^D`h$
-MD d4e
- O]DFa#
-LDH 8Hd
- LO\D'
-KDhh <xdc
- Oz[D&
-zOD Fa
- O_D%
-ND
- Of^D$
-HЁMD x
- Ox]D#
-LD d
- O\D'
-KD c
- O[D
-ODr! gT!O_D`l
-NDHҁ x fOL^D
-x%MD eO]D
-LD  dO\DB
-KD$tA cVAO[Dbl
-ODHԁ( x@gOL_D
-xEND, fO^D
-MD0 eO]DD
-LD4va dpaO\Ddl
-KDHց8 x`cOL[D
-xeOD< gO_D
-ND
-MD@ e@O]Dfl
-LDH x
-xKD  cO[D
-OD gO_D`
-NDB! fB!O^D`쨇
-MDH x eOL]D
-x%LD dO\D
-KD  cO[DOD
-$DAg DAWD  bO_DHND
-x@(fL VDxE  O^DMD
-,e UD  O]DLD
-0d TD  O\DKD
-4Fac FaSD  dO[DHOD
-x`8gL WDxe  O_DND
-<f VD  O^DMD
-
-
-x
- g WD  O_DND
-f VD  O^DMD
-r!e T!UD  `lO]DHҁLD
-x dL TDx%  O\DKD
-c SD  O[DOD
- g WD  O_DBND
-$tAf VAVD  blO^DHԁMD
-x@(eL UDxE  O]DLD
-,d TD  O\DKD
-0c SD  O[DD
-OD4va gpaO_Ddl
-NDHց8 x`fOL^D
-xeMD< eO]D
-LD
-KDL@ @9!  ! BcO[D
-
-ND  fO^D
-MD eO]D 
-LD`l L
-dO\D
-KD cO[D
-OD gO_D
-ND  fO^D@
-MDbl($ L*eO]D
-LD( dO\D
-KD, cO[D
-OD0 gO_D`
-NDdlH4 LJfO^D
-MD8 eO]D
-LD< dO\D
-KD cO[D
-(
-(pG
-'8!.m,M 8STs
-e
-jv.,r迢KfpK£Ql$օ5pjl7LwH'4 9JNOʜ[o.htocxxȄnjlPxq
- D
- DQ+ 4P _D wD@^;D 
-D  DQ+;P  VD
-
-vD@^ˑD D DQ+ :P MD  uD@^;DD DQ+
-9P  DD
- tD@^DgD DQ+ 8P D {D@^;D D DQ+7P  D zfD@^D
-eD DQ+ 6P DyD@^;D  D  DQ+5P  D xdD@^˓D
- D
- DQ+ 4P _D wD@^;D 
-D  DQ+;P  VD
-
-vD@^ˑD
- D DQ+ :P MD  uD@^;D D DQ+
-9P  DD
- tD@^D gD DQ+ 8P D {D@^;D  D DQ+7P  D zfD@^D
-eD DQ+ 6P DyD@^;D  D  D5P  D OdDOqL@L
-D^˓D
- D
- D 4P _D ODOqC@C
-DwD@
-D^;D 
-D  D
-
-ODOqL@L
-D^ˑD D D :P MD  ODOqC@C
-D^;DD D
-9P  DD
- ODOqL@L
-D^DgD D 8P D ODOqC@C
-D^;D D D7P  D OfDOqL@L
-D^D
-eD D 6P DODOqC@C
-D^;D  D  D 5P  D OdDOqL@L
-D^˓D
- D
- D
- 4P _D ODOqC@C
-D^;D 
-D  D ;P  VD
-
-ODOqL@L
-,DvbD@
-D^ˑD
- D D :P MD  ODOqC@C
-D^;D D D
-
-9P  DD
- ODOqL@L
-D^D gD D 8P D ODOqC@C
-D^;D  D D 7P  D OfDOqL@L
-D^D
-eD D
-D^;D  D  D+5P  D  dDhZhDhDifDDiDiDHDDaE~v
-! *! J! jn
-n*nJnj
-dHA*fhAJAj@
-xF$dDLp@
- b  p 4PDpE p`_D B!Dpe wDB!C  
-;P bDI  VD
-
- DIvD )L   :PDI MD n
-DuID!)C `
-9PD  DDA
-
- DDt@$DLp@ "b( p 8PDpE p`D B!Dpe{D B!C 7P"b(DI  D DIzfD")(
-L  6PDI Dn
-D yID #)8C ` 5PD  DA
- FD
-xB$dDLp@
-$bH  p 4PDpE  p`_D B!Dpe wDB!C  
-;P$bHD
-I  VD
-
- DIvD$)HL   :PDI  MD n
-DuID%)XC `
-9PD  DDA
-
- @DtD$DLp@ &bh p 8PDpE  p`D B!Dpe{D B!C 7P&bhDI  D DIzfD&)h
-L  6PDI Dn
-D yID ')xC ` 5PD
-
-! *! J! jiFD
-xdDn
-L
-
-;PD  VD
-
- DvDL   :PD MD DuDC 
-9PD  DD
- A
-DtDn
-L   8PD` D D{D C 7PD  D DzfD
-L  6PD DD yD C 5PD  D A
-D
-xdDn
-L
-@  4PD`  _D D wDC 
-;PD
-  VD
-
- DvDL   :PD  MD DuDC 
-9PD  DD
- A
-DtDn
-L ` 8PD`  D D{D C 7PD  D DzfD
-L  6PD DD yD C 5PD  D A
-hdDhhDieDDiDiDBKDB[DBkDB{
-GoQcpn
-g))/F
-'&&\8!.*Zm,M߳ 8ScTs
-ew<
-jvG.;5,rdL迢0BKfpK0TQlReU$* qW5ѻ2pjҸSAQl7LwH'Hᵼ4cZų 9ˊAJNscwOʜ[o.h]t`/CocxrxȄ9dnj(c#齂lPyƲ+SrxqƜa&>'!Ǹ}xnO}orgȢ}c
- ?G5 q}#w($@{2
-<L gCB>˾L*~e)Y:o_XGJDlr
- KhQK$O9O:I8J<IJ9:X)W*YZ (D
-, 0D 4 
-$ 
-
-
- D
-  D HNOyOz
-yzEiFj  D
- E  
- F
-E  F F?c.OYPOZTst#$
-c dJcOIOJL9K:\y[z
-xi| D
-Ġ D  D
-O9O:I8J<IJ9:X)W*YZ (D
-, 0D 4 
-$ 
-
-
- D
-  D HNOyOz
-yzEiFj  D
- E  
- F
-E  F F!.
+
+
+FԼ
+FFM(FF H L F"F9FXF *F9F0F*F9F@F*BFAF8F:FAF@FBF 1F@FuAFPFZFYF XFZFYFXFZFYF8F}:FQFPF*F!F(FsM0FLn1Fv*FFRFYFHF"F!F F[!F FcJFAFHF5"F!F FM"FIFHFC-O}FF x 0FF1FFXF9
+ $G
+O?7D.@f@>D|6H(|HH |HhfOD<D7@W@<D |$L,
+|LL |Ll[OGD:D'@o@:D|rbI)|II|IiQOgD/D@u@=D|5UN.|NN|NnGOOD7D.@f@>DDO6wD'D4@T@<D@O$DD*@r@:D<ObD
+/D5@e@=D7OU
+.DU@5DNuUD>Do@7DN7GND4D~@4DNt$Db@2DN2rD .DU@5DNuUVD7Dn@7DN7GD
+<D
+TDfOTODd  =DMDbOuEDe >D ND^O&GDf:DBDYObDb <DUODDT3+DdU@DuEDec@>DDKO&Dfk@:DDGKbsDbDtDCKT;DdW@D=D?OuEgDe >D D;O,:NDlk@:D
+7K gDg DDTDd z@5DV.JvFhDhbDf  DBhD`2D.Dh"`B`,D`)
+B""<
+
+
+BB!<BbJC3D <@D
+jG'<GG<Gg;|
+@O
+
+g@O
+B2D,/DgN.,NN,Nn
+ 
+D,DnOL,,LL ,Ll B2D ,D hL,
+,LL ,Ll    OB2~@RDbDbOL
+"@O_@r@_@Os C3DbDb{@ {@{@Os@k@O
+
+p@
+OpDBDD lO r@r@j@OrDCDD
+j s@ c@
+OsO D GD D
+ iO
+w@w@G@OvO
+ D D8hw@w@W@Ov
+ O D D_D  g3FO Ov D DD3F k
+  Ov  O DDD
+j3F   Ov O DDD  i
+3FO
+
+3F nO    OvDgD D hOw@_@w@OvzODDܱ l
+w@w@OvODDWD g
+ O E@
+
+OvDF f@DT@Dt^@ k^@ Oz ~@O]@DDPvD]@DOsf DD(DO \@e\@ Ox t@OX@DDDX@ d
+
+gDODZ@`2OZ@Z@Osb@OD D b_@;F{@
+O
+
+ CS3D uDe_@_@_@OsD dDF 
+dDOsE OC CS3D pDd
+ Os :DDb7@OC:D@ {@ {@OOs 
+
+C@C@OsD
+@
+
+
+DC@C@ OsH
+Op+N fD`B>@O&C D
+ E@ OpC
+
+
+ B@
+  S@OsJCCV3D0D
+k@k@Os {@OJEV@EV5,D #DcO l@l@MOte(D Df
+
+ k
+OG@g@Op{O:DyOD
+j B@ O B@ Or
+;DmOD
+ iO
+C@
+ C@C@ Os>DaOD hO F@  F@F@
+Ov=DWOD nOE@E@ U@OuD D8 lG@ |@\@OtFODDWD
+g
+xO @1h[h
+h hi[i ii?<B"><BB=<BbO"pb
+c@#@
+,@
+c@DD<<; C
+cO*
+ D
+#8@C@Or0D
+D8<7 C
+c@D
+1 D4<3 C
+
+P c@DD/<0 @ .<@@-<@`O#
+ W
+$
+Du@Op6DV@}@.DD$\D#lO'E%"lEE!lEeyf-+EU5/" 
+ 7Dl@O|5'D
+tiBB Bb4D!
+ODb[1$} Uހܛt
+O,
+rlDhDDdDOr< \
+OH^@,ODS@<yDD$CDDN@LO.sn[hD%DuD& @ MDOs4TC@@
+
+S@Oy2Dk@R =@k@$D3 
+S@Ox2 R c@$D $ $U@S@| OFOBS@LP@<wB#D"3DD@@< O.rniD DsD @*B@DOr0
+rD @U
+RD
+DFP`
+yB
+{ OCB
+}
+B"}BB} BbCE FFB2 V@C3BP"k@V@:EW%F-Jk@;F,J@-
+@[B."
+
+
+E7M~rAF ~NC#~CC~Cc E%EE Ee ( CNEF E5C3u@O^FP&.NR.u@FH
+F
+
+
+
+F
+-@ EO8!PON 0HH%`N>O^C#"PNZ.CC#PCc$P OCE%&`C3EE'`EeO6FF(OU^@{KE[% yM@N 6 H
+#
+' e@uL C
+FX& (N@F-L#
+E D   (
+
- D  F
+
+D 
+
+DE@
+C $A
+$.
+
+@
+H*I%
+
+
+'&@F
+&
+
+ iPN 
+K L h0mC#jPCCkPCclPE %nE EoOCC3E eO<LL,O5% OSENOECZ#E5 vKO^N[."FrLB&*N,
+L# +  
+EO~CNECUEOBl(L ')U@@F(  '  F)   NzAGq@p0=OC#r@CCs@uPCct@D$vPDDwPDd "&EEO<LL D4 C3e@O\LR, &DR$e@LC* +G(L$ &
+
+G=BF c@AK
+O,Ee Ll FEf  0&&OIIF9 FE6O&HUxONU~&OIi0 !LEF**O<+LL EN+ OHF6* +H5O^*+NV.FU& RlR|\K H
+5F*%F+.* + J u(2E O|)32LO~(N)O~(NO|)L OFh( HOFi)I  ()  
+
+ N v30E12E 
+OU
+N~OU L|-
+Eh6
+Ff O
+NFn"F 
+' OIF IE9OL'LE<O'HUxO NU~'OIi F  01O81HHO>0NN E<0 F6 1O\0LV,OX1 HV(RxlFRt\L u L 0
+N $ 1' *5F0.@+F1 N 6O~FNO~NFOEhHOEiI( 
+
+ N  E
+L OU N~OU  L|-
+Eh6
+Ff O NFn#F 
+F OIIE9OLLE<OHUxO NU~OIi O>F 
+O<OENHLLONE5OVN> OUF[&EZ% RVdG1d
+
+E*L % +%
+0~@ dL-E?GGEODlLODn N(F )F  (F )  FG C  F] Eu\Dt
+C
+@`k@ `@ EDe$k@D
+  1}@[
+C
+@`k@ `@ EDe%k@D
+D
+GD7 DE4
+
+Gg}@@ * +FF *+*DD C3 @0s@`@+DU$+D@FU&0^@R01E
+C
+@`k@ `@EDe&k@D
- D 
- $(, bH
-$ (D , 048< 0F
+R0 *J
+ +E
-4 8D < } ~
-ISJ}兩{視|FHQ{טּPEQq~!ͷuXca IRJ}露{視|EHA{טּWDAp~!tHc` IQJ}{視|DH1{טּVC1wx~!s8cg IPJ}{視|CH!{טּUB!vh~!r(cfIWJ}{視|BH{טּTAuX~!qceIVJ}{視|AH{טּS@tH~O  ހޠpޅBޥNN0nJN0lN0ncdIUJ}笠{視|@Hq{טּRGqs8~wxccITJ}隸{視|GHa{טּQFar(~ЀРvhЅDХNN2n(LN2l(N2n(cbISJ}兩{視|FHQ{טּPEQq~uXcaIRJ}露{視|EHA{טּWDAp~ҀҠtH҅FҥNN4nHNN4lHN4nHc`IQJ}{視|DH1{טּVC1wx~s8cgIPJ}{視|CH!{טּUB!vh~ԀԠr(ԅHԥNN6nh@N6lhN6nhcfIWJ}{視|BH{טּTAuX~qceIVJ}{視|AH{טּS@tH~ր֠pօJ֥NN8nBN8lN8ncdIUJ}笠{視|@Hq{טּRGqs8~wxccITJ}隸{視|GHa{טּQFar(~؀ؠvh؅LإNN:nDN:lN:ncbISJ}兩{視|FHQ{טּPEQq~uXcaIRJ}露{視|EHA{טּWDAp~ڀڠtHڅNڥNN<nFN<lN<nc`IQJ}{視|DH1{טּVC1wx~s8cgIPJ}{視|CH!{טּUB!vh~܀ܠr(܅@ܥNN>nHN>lN>ncfIWJ}{視|BH{טּTAuX~qceIVJ}{視|AH{טּS@tH~Lppr(tHvh  s~xpGSHA512 block transform for ARMv4/NEON, CRYPTOGAMS by <appro@openssl.org>
-
- 0S͂aQna
-be`
-b\A
-@HPa!@!BN.D(TA@r!t!&NA#1 t@H&ADt
-
-"n/J
-V!BaFa
-0 Bx¨th:@zhvvh8Hth<B|jH4h:Bth>@~hvh<jh6@vpp jH4h>z(rк2l8ń0
- P
--
- P
-0 `-
-"-*"G"-
--*G!` 2& Q@$!
-$t'%G&!Fg'RA@ D!B @EAD PFaF `Gt
-B&-&-D -D NH*N*-JH"-
-"-JFH"-
-F"G".`@P/
-"-*$-J%!-j$-%RaTš$V%X%YgPihP .
-$-*$G$@-j$
-B './L HHHHHH
--/JB)./􃬢򂨣򁨦򀨧*./
-B􈌢򂈪򇈣򁈫򆈦򀈬  -/Jb򥈧򤈭򤨨 -/)./bH'./b&./b&./#./",((((((̢ȣȧȦȨ 
--/*bHH򆨢򥨣((Ȣȣ%./*b,/jb􇨣Ȣ!./j"ȣ -/*b*./Jb&./b(fpfzȮH>؅F~(rrH0j:H<؅f|jH4H>ftpp(rN<HttN(2 `@fr jH4@0
-"-*$B -*"-J$D("PG"g$FH$-
--*G `@P`-
-"-*$BH B -*"-j$F"F("g"$J&Jh&-J-
---*g
-$-*$G$N-j$
-B './L HHHHHH
--/JB)./􃬢򂨣򁨦򀨧*./
-B􈌢򂈪򇈣򁈫򆈦򀈬  -/Jb򥈧򤈭򤨨 -/)./bH'./b&./b&./#./",((((((̢ȣȧȦȨ 
--/*bHH򆨢򥨣((Ȣȣ%./*b,/jb􇨣Ȣ!./j"ȣ -/*b*./Jb&./b(fpfzȮH>؅F~(rrH0j:H<؅f|jH4H>ftpp(rN<HttN(2.`@fr jH4@0
-"-*$-J%!-j$-%RaTš$V%X%YgPihP .
-"-*$B -*"-J$D("^G"g$FH$-
--*G0 @-
-$-*$G$N-j$
-B './L HHHHHH
--/JB)./􃬢򂨣򁨦򀨧*./
-B􈌢򂈪򇈣򁈫򆈦򀈬  -/Jb򥈧򤈭򤨨 -/)./bH'./b&./b&./#./",((((((̢ȣȧȦȨ 
--/*bHH򆨢򥨣((Ȣȣ%./*b,/jb􇨣Ȣ!./j"ȣ -/*b*./Jb&./b(fpfzȮH>؅F~(rrH0j:H<؅f|jH4H>ftpp(rN<HttN(2 @fr jH4@0
-!-*!G!-
--*G
-P
-P.N
-
-&-*&G&-
--*G
-n~S
-P)fJDbdLbb&`)( 
-ȫ0Ȭ򨈠򅈡 򣈭0򆨤򅨥򄨪и򁨫0΀򣨬ȠȡȮ
-ȯ0ȭ򇈤򆈥򅈪 򄈫0򁈬򀨠 `G⇨f􄨭"
-pg&h`h@kh о
- RaphpF0`aFFh<N6p`R (rsLh6p؁XwXuy)H44`8s`F`R &:a
-P)fJDbdLbb&`)( 
-ȫ0Ȭ򨈠򅈡 򣈭0򆨤򅨥򄨪и򁨫0΀򣨬ȠȡȮ
-ȯ0ȭ򇈤򆈥򅈪 򄈫0򁈬򀨠 E⇨b􄨭"
-pg"h h@kh о
- RaphpF0`aFFh<N6p`R (rsLh6p؁XwXuy)H44 8s B`R &:a
- @-
-"-*"G"-
--*G
-"-*"G"-
--*G
-K˼ "B 0 -Bü @<CD P MDż `\EF p mFǼ |GH Hɼ IJ  JA-#39FFYSlsy੆
-* 0@P`p
-`-*`G`
- /*0/J`/jp//@/jAP/A/A/A@
-! *!p /J"` /j"
-" *! ' `86XDD(`|G0 /J"|' /*"Qg /
-"
-b8 A@
-NHx 0C
-0
-@ *@G@
-
-
-ol@j@O4wS'p~@S'p~@'7BS'pr~@S"pvS&p@6S&`z@r@&6DS&`tS$@r@b@ooT@@o<7oe@{Db@wO2S'p~@S'p~@'7ES'puS%P~@n@uS%Pn@@5S%Pn@%5BS%PrS" n@ oV@Jou@r@O2wS'p|@S'p|@'7ES'pu|@S%ptS$p@4S$@}@e@$4BS$@rS" e@nU@nl@j@O2wS'p~@S'p~@'7DS'ptS$@~@f@tS$@f@@4S$@f@$4BS$@rS" f@ nV@Jnt@r@O2wS'p}@S'p}@'7DS'ptS$@}@e@tS$@e@@4S$@e@$4BS$@rS" e@mU@ml@j@O2wS'p~@S'p~@'7DS'ptS$@~@f@tS$@f@@4S$@f@$4BS$@rS" f@ mV@Jmt@r@O2wS'p}@S'p}@'7DS'ptS$@}@e@tS$@e@@4S$@e@$4BS$@rS" e@lU@ll@j@O2wS'p~@S'p~@'7DS'ptS$@~@f@tS$@f@@4S$@f@$4BS$@rS" f@ lV@Jlt@r@O2wS'p}@S'p}@'7DS'ptS$@}@e@tS$@e@@4S$@e@$4BS$@rS" e@kU@kl@j@O2wS'p~@S'p~@'7DS'ptS$@~@f@tS$@f@@4S$@f@$4BS$@rS" f@ kV@Jkt@r@O2wS'p}@S'p}@'7DS'ptS$@}@e@tS$@e@@4S$@e@$4BS$@rS" e@jU@jl@j@O2wS'p~@S'p~@'7DS'ptS$@~@f@tS$@f@@4S$@f@$4BS$@rS" f@ jV@Jjt@r@O2wS'p}@S'p}@'7DS'ptS$@}@e@tS$@e@@4S$@e@$4BS$@rS" e@iU@il@j@O2wS'p~@S'p~@'7DS'ptS$@~@f@tS$@f@@4S$@f@$4BS$@rS" f@ iV@Jit@r@O2wS'p}@S'p}@'7DS'ptS$@}@e@tS$@e@@4S$@e@$4BS$@rS" e@hU@hl@j@O4wS'p~@S'p~@'7BS'pr~@S"pvS&p@6S&`z@r@&6DS&`tS$@r@b@ hIhT@Q@O1OvS&`n@S%p%5Dt~@S%pS$@~@f@tS$@f@@4S$@f@$4AS$@qS!0f@^@OVU4D"T@"33Z@AK@A2Q@`C`𽺭
-ol@j@O4wS'p~@S'p~@'7BS'pr~@S"pvS&p@6S&`z@r@&6DS&`tS$@r@b@ooT@@o6oe@{Db@wO2S'p~@S'p~@'7ES'puS%P~@n@uS%Pn@@5S%Pn@%5BS%PrS" n@ oV@Jou@r@O2wS'p|@S'p|@'7ES'pu|@S%ptS$p@4S$@}@e@$4BS$@rS" e@nU@nl@j@O2wS'p~@S'p~@'7DS'ptS$@~@f@tS$@f@@4S$@f@$4BS$@rS" f@ nV@Jnt@r@O2wS'p}@S'p}@'7DS'ptS$@}@e@tS$@e@@4S$@e@$4BS$@rS" e@mU@ml@j@O2wS'p~@S'p~@'7DS'ptS$@~@f@tS$@f@@4S$@f@$4BS$@rS" f@ mV@Jmt@r@O2wS'p}@S'p}@'7DS'ptS$@}@e@tS$@e@@4S$@e@$4BS$@rS" e@lU@ll@j@O2wS'p~@S'p~@'7DS'ptS$@~@f@tS$@f@@4S$@f@$4BS$@rS" f@ lV@Jlt@r@O2wS'p}@S'p}@'7DS'ptS$@}@e@tS$@e@@4S$@e@$4BS$@rS" e@kU@kl@j@O2wS'p~@S'p~@'7DS'ptS$@~@f@tS$@f@@4S$@f@$4BS$@rS" f@ kV@Jkt@r@O2wS'p}@S'p}@'7DS'ptS$@}@e@tS$@e@@4S$@e@$4BS$@rS" e@jU@jl@j@O2wS'p~@S'p~@'7DS'ptS$@~@f@tS$@f@@4S$@f@$4BS$@rS" f@ jV@Jjt@r@O2wS'p}@S'p}@'7DS'ptS$@}@e@tS$@e@@4S$@e@$4BS$@rS" e@iU@il@j@O2wS'p~@S'p~@'7DS'ptS$@~@f@tS$@f@@4S$@f@$4BS$@rS" f@ iV@Jit@r@O2wS'p}@S'p}@'7DS'ptS$@}@e@tS$@e@@4S$@e@$4BS$@rS" e@hU@hl@j@O4wS'p~@S'p~@'7BS'pr~@S"pvS&p@6S&`z@r@&6DS&`tS$@r@b@ hIhT@Q@O1Ov`S&`u@S&`u@&6DS&`tu@S$`uS%`@5S%Pt@l@%5AS%PqS!l@OC`ܟ
-
-
-a4pG
-apGF"C"F>pG@h>@h>8OqhF(4p>xBн8@>8{O -O 
-wO
-
-
-Cv/
-
-E#"C+CE k`#B`*``
-
-P
- 
-OG|OwO
-w'
-E&C/CEt@}@d
-
-(
-O((Կ  pG pG pG pG@cBܰoܰڰڰ(ܚ(Կ  pG pG pG pG pG pG pG-CFFF"F!FJF F!FG^3F\\A@3t
- hB H@=IKxDyD{DcT_TqA`d0Cy@
-HOr
+ ( k@)
+(C
+1J]Eu\Dt
+C
+@`k@ `@EDe'k@D
+ D
+$D-EEu@D^|@F_u@G(|@^@)@( ) E2C
+3J  ]Eu\ Dt
+C
+@`k@ `@EDek@D
+F3@C
+)C (F)!!]Eu\!Dt
+C
+@`k@ `@EDek@ D
+D
+E DA
+"@ "]Eu\"Dt
+C
+@`k@ `@EDek@
+D
+C OtOsDCl@OKe{@OJgEGl@{@(*}@
+F)  F(;F)@*]D0CA1s@#]#Eu\#Dt
+C
+@`k@ `@EDek@  D
+) %@  (
+)] @*2{A3C*G+$]Eu\$$Dt
+C
+@`k@ `@EDek@! D
+gCG #N #
+|@( %@4)C 5(I)%]Eu\%Dt
+C
+@`k@ `@EDek@ D
+K L &&]Eu\&Dt
+C
+@`k@ `@EDek@#D
+
+3t@
+C
+@`k@ `@EDek@$D
+|@
+Eh6
+Ff ONFn F ''%F OIIE9OL%LE<O%HUxO NU~%OIi' * 'F  EN FL E5F6O^O\NW.LT,' FR\ FR\N4 5N *F+  * O|0FLO|O~1L N
+jpG"F 
+#F0(F `(``
+)
+6KO Y@0K@A
+ײ"9OO OOOO O
+O OO
+ O T(D&D&D;D'DvS@/S@"
+;"Df^@0*D^@+D?^@#D2^@+D;_@0{@_@ #D2_@ F+DF #D6C@
++D"D A+D? C K@ AD&CY@
+ i A !EQ 1OkQiA!
+
+iJ
+&
+*
+
+
+~_G@ix@R h@Uh@%OeFE%Ͳ AE %
+A@y@qO@
+M@ 
+ A@hH@ H@H@DD&D@F C9_@9aA#D9!
+"DC!r
+iպpG
+ipG-OF
+Q ` `u@gs@|@$C2?-
+* OBrD tj@-
+0S@bD4
+K {D<r F0X"
+KOrIH{D$3yDxDY`
+K-{D0K{D0
+JzD JzD JzD @" " pGV
+JzD JzD JzD " " pG
+JzD JzD JzD " " pG
+JzD! JzD!JzD !@"!p"!pG
+JzD$! JzD(!JzD,!@"0!p"4!pG
+JzDd! JzDh!JzDl!@"p!\"t!pG$U
+JzD! JzD!JzD!@"!\"!pG
+K{D2 K{D2K{D2K{D2 R
+K{D2 K{D2K{D2K{D2 0R
+K{D2 K{D
+K{D 3 K{D(3K{D03K{D43 Q
+K{DH3 K{DP3K{DX3K{D\3 (Q
+K{Dp3 K{Dx3K{D3K{D3 P
+KzD{D<b$&"(&,&
+XFE 
+El@X@l@
+F
+ #
+  AFXFr@  "  B  b> "r)F(F\@F"YFfE;
+ "9F(F?
+
+
+F #DiB
+K {D;:4F
+
+@K#@<A
+
+ 1I ]Osf"
+u Fo9FF PFLF hE
+J D
+e"D
+FE
+#hO0h8F F
+Kk"
I
-KxDyD{D7e
-JzDfpGđ
-JzD JzD JzD " " pG
-JzD JzD JzD " " pG
-JzD JzD JzD @" p" pG
-JzD JzD JzD @" p"
-JzD0! JzD4!JzD8!@"<!\"@!pG
-JzDP! JzDT!JzDX!@"\!\"`!pG
-K"{D2K{D2K{D2K{D2
-K"{D2K{D2K{D2K{D
-KzD{Dt%"x%|%
-ZCҲ8PF J@  "  B  c"0 FZFFQF"F<Ѹk<FS۲1F"=e
-i @G
-KA"{D
-Os
-
-FFR{<xFC F
-(F
-hh
-`
-;QlXB p:
-_#
-I{DxDyDSgSy|N
-KA"{D8
-Kh
-E
-6AF0F*FW?I00 h:E0
-D`E h.Fh
-F3FR =0FC F
-#h:!S"=)@C" Fg!FF Fp@ p8FFHh1 F!F*F8@} 8
-h
-h
-h`b
-Њh,`h<`13g
-Y X@2CI P3cE 
- gF`  hdFhENhE,F Wh
- E,
- E (3O:O
- hMh4
- (6O:O
- Thh4
- O:O
- hi (3
- E (3O:O
-Lh [4
- O
-(6Wh
- (6KihO:O
-Li v4
- O
-(3i
- ENhWiO:O
- hi (3
- E (3O:O
-Lh [4
- O
-(6h
- EKihO:O
- iWh (6
- (6ihO:O
-i v4
- O
-(3Wi
- EhiO:O
- Nhi (3
- E (3O:O
-h [4
- O
-(6h
- (6ihO:O
-i v4
- O
-(3i
- E (3O:O
-Li [4
- (6O:O
- ii4
- (3O
- gF`  hdFhENhE,F Wh
- E,
- E (3O:O
- hMh4
- (6O:O
- hh4
- (3O
-O  RBF RF  F
-FAF3F#
-/JF F
-BF IFSF F
-
-5
-
-*ʹƹ
-/+
-
-
-OCZ[F Op
-
-zFQF*F FYF"F[DF #
-+FP;YF
-+FA 
-0F
-0F
-ZF, QF
-
- (6#
- (6#
- (7#
- (7#i
- (7#
- (7#i
- (7#
- (7#
-+)F2FSF
-9F
-Fah*C C
-
-kK
- 
-
-  
-I  @FIFd)
- FQF
-
-3c`B!F8F%$
-*KhBE$8F8F'F
-Os
-H#
-Yp>,
-G p _P
-ù
-ڍ#
-
-C% ch`
-
-
- 0F h S@`
-
-:
- {
-
-Z 
-
-(F)F
- F!Fk(F)Ffȱ7+F%FF#F,FFkh
-89H"9I9KxDyD{D`(Ff`F84H"4I5KxDyD{D( B0H"0I1KxDyD{D F1F
-
-HF )F:F#F
-@S
- FJ
-3#O
-D#
-#(F!F*FX
-2F'QhKB?7B
-n
-kh+hh
-:^Chch";#hhC##hhO3jh
-*hh(FB)F"F;FvB"(#F ,FFo8F0F
-#
+H{D CyDxD[T[f d
+FFBh@ h# hH@BܰT#3C0F F!F(F
+
+K {D: F
+Kh#
+5X?2FIF(FGR2F F
+
+o@F-
+O
+"F)F0F
+*F!F0F[
+ KOr I H{DnCyDxD0F
+F]FFFbp
+h
+FFF
++
+~KOr}I~H{DCyDxD+
+yK@YyIyH{DCyDxD,Z O,ܣ
+
+OHFD
+  KD
+z 
+DPZMIF(F8F 
+#F
+9FHF#FF*FIF@F#F
+*FIF(F
+*F
+
+;DF#FF d
+W#`
+ܕK@IH{DCyDxD
+ܐKOrIH{DCyDxD3+
+ٌK@IH{DCyDxD-OE ܫ*
++
+
+D s
+ 9YFQF8Fc @F ^"F
+8F
+
+
+
+
+
+O
+L(

-W(8F9FEP8F9FBF
-0FQF
+L i h(

-1( F!FP F!FBF
-(FQF
- F!F:Fq
-ܸY ܸԿ%%%%
-z
-xF
-F'
-AF 9(8
-
-FF
-DB
-
-
-F FF
+

-E(FA
-2FF#F(F
-
-FK 3#O
-FB۹
-
-O
-(F:F3F
-h@F1F
-
- F(F`
+GaMi h(

-E 6O XF1FX
-
-FL O O
-FEOl 2
-
-
-O
- F3-GFFFFFBNE(FFF
-K#
-(F
-j+F:FG
- 8
-j
-
-0@i f
-@#
-Z
-F FF# `
-#h FIF2FiCFG
-
-bp pp#q
-bq qq|-GF
-
-C
- ey B
-)qjp pp
-
-jq
- q
-q5
-6
-9q{p pp
-{q q q
- p!qcp
-pcq qqyUF^Fay?Bh"yG'
- CyGgAxpx1xB
-CxBa2yqyL,FL y6Ll
-jq: ?qq5
-    * ,;*
-,;\;2,;2 ,;2
-,;lO#
-cq; ?qqF(0
-#qap pp
-bq qq-OFhFFPhBӮh
-
- CbyC
-+qip pp
-iq qq5
-5 
-3qqp pp
-qq qq
-"p#qap pp
-bq qqy
-
-kq; ?qq5
-    * ,;*
-,;\;2,;2 ,;2
-,;lO#
-cq; ?qq0h
-Ka"
-H
-I{DxDysyDLL hG F 
-CLL#h FhG |
-0^IFRF"B1F
-
- 
-
-Ch`pGpFFFQZ
-
-H!F*FxD
-8FL
-kFFF3k
--
-QF1
-QF%
-9F
-RFG
-,l9F . @F!F
-+FG
-
- FaF2F
-+FG
-+FG
-G
-QFG
-HFn#F
-
-
- F FO
-
-8F 
-(@0F)F#F G
- ,
-
-F
-% F, Fs0FD
-
-WF
-
-&l
-
+O
+O
+L(

-
-: !#h F
-1#h ,
- F1FRF+FG(#h 
-F3FGб#h F
-F3FG(PF
-
-[h ˹@%
-(F2 (F2(F2F
-! `%
-O
-
-O
-O
-O
-O
- O
-E8O(C+
-38hD
-O
+LMiLh(

-OH h
-ЙBAEЬ#
+O

-
-K
+Li h(

-(ZF^0;:  EѮB @e
-O P)0+ W)0 h
-W 0
-2
+

+Gai h(
+
+O
+O
+LbF(
+
+Gih(
+
+
+
+bG
+idi(
+
+
+O
+ N(
+
+cGidi(
+
+g
+O
+ N(
+
+aGhdh(
+
+g
+
+ 4@#
+ [O2C KO0
+ F[ FF8
+ 8`a`hFCF
+F4
+ FQF
+F1FF
+EC;^#0#F$ *F_:F
+L H-CF0F FFJD"F
+0FO
+A9R!0O
+h+RD
+3D
+
+ 
+B1 F%s !FF P
+: 
+:
+3
+t
+FF
+
+#F>#F:h1(h7E0FI(FE`Km"IH{D SyDxDO
+)h
+V#P3RB@
+F8!F F
+-XF
+`#
+#`#
+
+
+F
+J
+#h
+
+QFh: QF
+#`Os
+f`"h
+Ose"
+
+: FE(F(#FO1FF(FM4 *F)F0FOD
+I H{DQSyDxD-p
+KO:r I
+H{DQSyDxDWW3F"F(Fp@
+
+
+; E0FFJ)
+
-Q 0;:E*F#Fs
-F.
-0
-F^#0
-:
- F0FV
-2, 2); Q$
-V@2p$1(TD?0`G(6pOtT5H3ZD9?=Fh&@G '^@:4`Or2CD>C7pO LL
-,<Fg@n@8`OssL;F l@f@dD>`Oue6F &
-
-?`@1Jf
-
-
-
-TD
-OtT
-
-
-RDOr2DD  SD
-K
-
-SDOssDB  UD
-K
-
-C UDtOeD TD
-K
-
-E TDXOTD RD
-K
-
-RD8OBDD  SD
-K
-
-SDOssDB  UD
-K
-
- UDOeDC  TD
-K
-
-E TDԢOTD RD
-K
-
-RDOBDD  SD
-K
-
-SDOssDB  UD
-K
-
-$UDpOeDC  TD
-K
+
+FI 4BݥBڻ
+F
+%K@"%I%H{DgSyDxD3FBF9F$:Oi (
+
+O
+MEOi (8F YT
+F;B0F&J
+FJ
+3Bܻ
+4
+(FKFZ,?
+O
+F;F*FIFHFFH
+@OJB
+T
+ (F #D0 F
+gK@?BgIgH{DwSyDxD <IF@FF
+$cBFAF(F
+~#k"
+
+Cp9F8F/
+
+QF F+
+2hh1FB0F;F"FmBx#F 4FFF
+
+
+O
+`!
-E TDPOTD RD
-K
+O
+pF@
+
+K{D1F F
+
+
+
+qBҫBЂ#s"
+c P#F:FG
+8
+WDD
+j+F8aF0FG
+8F7D2F
+Os
+si#h
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+DB%ppGXY
+bp pp#q
+bq qq0-CFhFFUhB]
+FF+
+G'xGGxGgZyI)yyII
+ *OOo
+D<
+𚗕Cyx7, B"BBBa,M@B
+L,* ,*,"
+," ,", 9, 9C#, 9C, 9 9BB 9B"\@
+CU@"/8P+
+<q{p+ p+p#
+{q# q#q+
+5p4qsp+ -p#
+psq# $qq
+L,* -,"
+\F," $,L\F# 8
+8
+8
+#qap pp
+bq qq}-OFhFFUhB؇h]
+{3i 
+
+O 
+G'xGGxGgZyI)yyIIIiy]@\@CDF
++OOo
+L<+ <+<#
+<# <#< 9, 9C#, 9C, 9 9BB 9B"\@
+CU@T8P+
+<q{p+ p+p#
+{q# q#q+
+5p4qsp+ -p#
+psq# $qq
+L<+ -<#
+\]F<# $<LTF# 8
+8
+8
+Ka"
+I H{DcyDxDTT hG F 
+0X@RFIF F"YF FEE
+
+8
+
+
+
+
+
+
+
+
+
+Ch`pGpFFFQZ
+
+8F F
+
+
+
+
+YF:FQF FF7F2F)F F IDD F@ #hik RFAF FGCF *FAF FG[&ZF9F FG;F2F9F FG:FAF F
+RFQF FG*FEFSF FGD6c [FBFAF FG2F>FCF FG2F)FLI|DLpyD;@
+
+
+
+ZFYFSF F[F {YF FGZF FGCFBF x FAFCFBFAF FCFBFQF FSF FFKF*FIF F F FGKF FFBF F+F*F)F F*F)F FGZF FFG+F*F)F F+F FF } YF xGIF FnGJFAF FG]F FGKFRF)F F*F)F F zG*F)F[F F*F)FCF F+F*F)F FmQF FGSF8QF FG[FRFQF F\[FRFQF FV[FRFQF FPRF FG+F FFU+F FFO F: FFGKF FF? FF9CFBFAF F$CFBFAF FCFBFAF F*F F!SF FFGCF^B-OMFF Mh yQs xiiF F YF
+ FG1F[F F2F1F FG2F1FKF F;F2F1F F;FZFAF FG
+DBF AF FGKF F G
+9F F9F F3F :F/ FG1FKF FG FD3
+3FȮ
+1FG2FٮCF1F F3F2F1F F{1F F C+RF Fk;F:F1F F {xc2F1F FG3F:FAF g F YyG3Fb 9F FGJF1F FGCF2F1F FS;F2F1F FM;F2F1F FG:F3F9F F@KF:F9F FGCF tHAF FGCF:F9F F.CF:F9F F(1F F/
+9F F
+$@F>  SDBF(F4 ,
+_8 |
+
+)F F"F)F F&!F@F!F F!F FBF!F Fr!FHFx!F F!F F!F F!F FJF!F FY!FPF_!F Fz>RF!F F {&G!FXFM!F Fh>ZF!F FH7!F0F= #!F FV;!FP0*F!F F!#!F FD; 2FFP"FF2:ZFFF
+YFXFYFXF
+JFYFXFYFXFYFXFBFYFXF @YFXFYFXF*FYFXF"FYF@FAF(F'J)F(FzD3b0FP*F1F1F F !TPOc"
+iiB ,h hB0
+iiB ,h hB0
+?R [ B @3C"
+K{D-)h F
+K
+);FQF F# F>FH#A"
+K{D%[E
+
+
+
+$
+i#d"
+ 
+p0-O}FF
+#SFeJ
+zD8Cd2l
+_FAFHF
+FF.0Fy6(Ft> Fp1F)FD
+
+
+
+@
+
+ 3DHFKFIj
+ @7D+
+8F FRFIF F =z R
+\[(F
+
+@9F F
+DIF@F
+ %D4@ %DLOu5D $D DD d
+D,@|@DLO{{D $D DD d 'D  t@'DLOwgD $D DD d H (&D <@l@H H&DLOvVI)LH hII LIi %D4@ D%D LOu5 N.
+LNN LNn,@|@wDDO{t
+,L
+LL
+l
- RD0OBDD  SD
-K
+
+
+eDVD
+OvV
+
+
+UDG
+Ou5
+
+J
+\DWDOttF
+
+
+
+J
+ WD
+OgVDE
+
+
+J
+ VD 
+OVUDD
-SDOssDB  UD
-K
+
+DJ
+ UD
+OETDG
+
+
+J
+ TD
+OttWDF
+
+
+J
+ WD
+OgVDE
+
+
+J
+ VD
+OVUDD
-(UDOeDC  TD
-K
+
+DJ
+ UD
+OETDG
+
+
+J
+ TD
+OttWDF
+
+
+J
+ WD
+OgVDE
+
+
+J
+ VD
+OVUDD
-E TD̡OTD RD
-K
+
+DJ
+ UD
+OETDG
+
+
+J
+ TD
+OttWDF
+
+
+J
+ WD
+OgVDE
+
+
+J
+ VD 
+OVUDD
-
-
-LD`TDOtTDJDBDDOrB D CD0KD$OssD  EDMDOU D DDLD OtTD BD bDOrBDcDCD Oss (D eDMDOUD dD LDOtTDg@bD OOrBWDOCDOss_D}OEDOUgD<ODDOtTf@h`FhrBhB`h`` >? 
+
+DJ
+
+ \DOtt
+WD
+
+WD
+OWVD
+
+MDVD OvV
+TD  
+MDOuE
+ TDOtt OD
Q  R S0ciT0
-U  V "W0Y
+U  V "W0
+
jp ppch+q
jq qqh+r
jr rrh+s
-js ssp
-|4?G ':C|BgJ}RD&@^@?}"G '>C}FgN@o@^D~~sc?G '>C~FgNfD@g@u5U?G '!>CFgN $/@4W@ `"p4?G '%>C#pFgN
-FD'@_@&p$`"(-?G ')>C'pFg~N ND@o@*p(`sc,?G ,@L+g@F lpNVDu,`.p5U?G'>C/pFg$FO> /@4W@12p0`405?9G('@H3_@FhVN^D=6`4p"6F &  7C7` GfJOGD8pKD:scO II
-)
-
-
-I;
-G i>O}>pUD<5U?G '  G
-
-?p @1JgȠDTDĠ\D 4D RD ZD "D  SD [D cD  UD x]D0UD  TD `\DDD  %xjVp $ν|*ƇGF0FؘiD\"kqCy!Ib%@@QZ^&ǶRD ̤ZD22D  SD [DcD UD   ]DUDTD   \DDD  RD lZD,22D  SD P[DcD UD  @ ]DUD  TD \D(DD  RD ZD22D SD   [DcD  UD أ]D$UD  TD \DDD
-ZD
-  ZD+22k[D
-(DK:z[D
- ]]DK0
-uU[D  K\D4D
- KD KZD r"[D  DDK:z[D
- ]]DK$
-uU[D  K\D4D
- cD J[D s# DDJ:z<ZD
- U]DJ
-uUZD  \DJ 4DZD
-  DK{+ DD}J :zBD
-R xK
-rRU@vKd4D
-e@DDqK{+ke@SD[$lM cUDc
-
-RDhMRMDb  ,LDcMtDMDd  DD^M+ EDkCDYM cUDc BDdDR SMb DDeDtDD(d LM D+EDIMk  cD} cEMc0 MDR,@Mb _@utDD<Md<OV@DUD+9Mkf@eD cc R< b ^@.NtDdU@^Dvh[`Ehheh&`F``48?4q"am 8D꾤K`Kp~('09|eVD")*C#9Y[e ]O~o,CN~S*5:ӆ]/SD!7Ç ZEogL*mpF F?+ 8K"8H9I{DxDyDGG/!vZ8*
+js ssp:
Q  R S0ciT0
-U  V "W01
+U  V "W0
jp ppch+q
jq qqh+r
jr rrh+s
-js ssp
-EFH'FѡSFEF
- F/F<O
-+BوH}"IKxDyD{D,٤ BٴBbFF;CFFcC BF PFYFG
+js ssp

- *(PFYFBFG
+ ++ AF8FDDoU"
+
+ AF FGz
+YFHFG
+F
+
+
+A@FF   ,;CcFF +O
+(DRXFXA@
+

- +%8FIF"
-:XFBFGO
-  % FBFG
-
-
-+]>S@+U4;SF
-+C
-F@(F)FBFG*] 0S@+U4 0  O
-+C
-FA(F)FBFG 0*]Z@  +U4O
-L
-h'
-
-
-0"C
-
-
-
-0#AJ
-\E 
-1F$
-
-
-g@ FBaAgO6n@O@
-g #
-IO0
-#@{O6
-#P@Y@ #
-P@Y@#P@Y@# P@Y@
-
- #
-
- *.##
- 02##g 4## <gg
- 6## 8## 
-:# K
->{D;`K{D3`!
-L2F
-l, @C
-
- 8hv F1F
-FK@
- @
-
-@
-
-O
-
-O
-
-,&F
- OFmE@F4G" | 
-
-ђF
-3A@?CEh
-
- @
-3KEh
-
-HSxh1l!*@
-#b@k@#n @F1FJF/
-F0F@,4"F"p@-GFFFFlDhC@C
-jB
-@C
-n!FRF
-
- "RP@lS
-+!F;F:!F;Fi}"
-1]4x=J@+BF F*
-
-"1"x
-|D
-p
-q
-
- PF!F"1 -GF
-w
-0!aM F
-2F3FE a1_0!M
-#
-K  
-
-K1F h{D
-F
-ٌ#
-
-
-
-E@w
-HF
-PFIF:F#FF(HFIF;F
-)s@k
-$ XF1FC
-#
-#
-
-
- F
-
-@v!Fy
-
+
+t'-OFFFF0)
+
+
++OoO
+ 3EDD*F
+
+
+ 
+
+~D
+ cK"IH{DysyDxDOOhCF F
+"
+
+CmFhvF
+pi
+F!FF\
+F!FF
+#[O2#Bu [BaCS@#% Z@ 
+p FFF1-F
+
+r& @ 37
+QEHEـh1t1C`@
+@ 
+
+
+3
++O6O DDo Uͱ FGND@
+QEHE׀h1t1C`@
+@ 
+
+
+3
++O6O DDo Uű FGND@
+``@DVE:h1ZF FG@
+O F`@BHIF
+
+G`ݱh1 FG@`
+p!FSvO
+#8F#B@K@#
+#B@K@#m
+BF)F8F1T@ 
+r[2n1Fm(F
+"
+s
+?
+?EE@dC}"
+
+ 02
+#
+?EEOc}"
+""} 
+
+
+*: DDow
+~D
+ }KB"IH{DsyDxDMM#
+
+ RF
+15"FHF310GE0/:FYF
+0!0FU
+M}Ddv0F6h70FhG16
+
+
+
+Foo@H
+
+
+FH
+F
+|"9FxO -|2[+*F9Fx>3i
+B
+2{D3#@;o7K{D7K{D#9FF FJ(
+ F /CE(F
+8FF
+ ;

-E&(F
-)-CFFFO#
- B
-T#
-Kq"{DY2FO >`b
-)-OFFFب#
- B
-٭#
-
- XF!RFV x
-.
-#
-
-f@ C+at@#v>#
-K"{DHFy*F `
-JC60F,3F@Os
-'
-) '
+E@wn"
+
+Osk"
+O
+8F0@_l"
+$F.
+
+K{D
+@7l"
+@1FD# :FCC
+PF F
+ F+
+0
+
+FF|O0-OFFFFF))Os
+)-CFFF O#~"
+f#t"
+)-GFFF ب#~"
+6
+Cp6 F2EѨ
+.#~"
+
+ Ch@!t,#
+RE@Mr"
+)FZ
+O 5/J@p/\3J@:p
+
+
h` h` i `
Ci`pG i `
-i` j`F@h FFF
-XB6C0B @
-2Fz "Fu =`
-FBO!s
-hZ@#
-!<I"yDg
-O
-*
-h:w#
-҂#
-
-hB@
-s
-O s
-?j '
- @_FFFFF F
-i '
- @-GFFFF lhB @#
-
-N& F*FP@73
- "+F FXOOs
- "
-FFF @3
-H!F2FxD
-I{DxD/cyDA/AA\
+i` j`F@hFFF
+
+K{D `
+ @PFY@F h T8FQHFNFI$FD)A3Fbi!iPF^O1s"
+
+3@#o"
+j
+FPFFn
+
+BOs
+3 
+PF
+Os}"
+FFCh h@#"
+(F
+ѥK@12IH{DyDxDJhSK@32IH{DyDxD=0F0FF0F
+3 >
+rK@]2qIrH{DyDxD
+ OFȹ@#F
+4
+r
+ "
+K ,F{D(
+
+
+H!F:FxD
+
+c(F+@9C~"
+ObIH'cyDxDIIo 9F8F
+H{D)cyDxDII\
ciV [0X  Y 
-Z "
+Z "
pchq*q jq
qhr*r jr
rhs*s js
s#it*t jt
-tpx
-K
+tp²
#jb g0d  e 
-f "f8F1F@",n+ +Y U6Qp.O!pp Y U6Qp .O!pp
-T&06p*p jp
-p5n0F
-#
-#
-!F"0F4HHF1F"++ب#3D
-QFODHF
-
-
+f "f@")F8FKn+ ++?0Fn0"T%05
+
+B 3<$
+B(F֮
+#
+#
+S $&
+
0  
-   l0l 
+   0# 
0 1F 
-   "000+@+1<0T?bhqp(p hp
-p*q jq
-q5B p<@T?bhqp(p hp
-p*q jq
-q5B
-@%
-D!)z,D!)v=D!)rND!)n_D!)jpD!)f F
-
-
-
-
-HLxD2^hF F0
-JDF@(FIFFt
-
-D
-
-
-, F
- 
-sa3B4ah
-"(FKBE]F(K9K
-H
-3yD>> Fp
-M
-K}D FX3@;<
-M3
-K}D FX3@;<
-Mq
-K}D FX3@;$
-K}D FX3#`8
-JF{DX3@,;a
-@FDE!F(FD AFF8FD
-K FYEhF(FD(FD
-@FDE!F(FDAFF8FD
-K FYEF(FD(FD
-@FDEE!F(FDAFF8FD
-K FYDF(FD(FD
-
-@FDE!F(FDAFF8FD
-K FYDF(FD(FD
-@FDE!F(FDAFF8FD
-K FYD@F(FD(FD
-JF{DX3@4;
-JF{DX3@ ;u
-JF{DX3@$;A
-JF{DX3@$;)
-K JF{DX3`@kD{
-K JF{DX3`@kDC
-K JF{DX3`hD)
-
-H
-
-
-
-
-E7O
-
-HF AF:F#FCu-GFFFFC0F F+h(F
-FFK}D FX`3#`pv
-MFFw K}D F
-(5(/((*@B@B @BHxDpGHxDpG HxDpG HxDpG HxDpG HxDpG HxDpG HxDpG
-HxDpG
-HxDpG7
-I
-)F
-H+ F0! "H>(F!F "
-"hE
-o( `CF0`
-K{D ` `
-i
-HxDoc
-KB X<
-H
-L K"|D!{D F
-e
-б(Bh[iGF)F0F 4B
-(Fk Bn;h6k BhAF<2F
-KFhh{D3
-KFhh{D3
-0F7(F
-B8FBxhF4(BRF
-`#aA'8FBB(F0F-OFFF
-BhkGF@FBF@FBF FPFAFB8YF#`F
-BhkGF@FB8F@FB9F FPFAFBH$
-B
-8FBhkG
-
-+h x"sZxbsx3s+`
- FH F8E
-)OFFD"h;P5
-K&a
-KF{Ds`hAs
-KF{D s`hAS
-Hu"IKxDyD{D9b9to
-I{DxD3yD9:9Lo
-"F@F1FF+h ,`
-"i h`#a
-i`Kaaa bKbpGKhiH{DXhh"EG
-M
-,hKBP;B򞀂KB
-;B;B
-аO<O
-аO5 0F9F?40F9F?Y-2hx+"غB  +r3h33`0F9F ?0F9F?h
-B܋BBD `
-H)FxD F!%@a?(F|
- H
- ;Dh
-
-FO
-1F:Fs
-B
-F<H!FxDPFL? G
-O6+M
-!FRF
-BFKED%JBVF
+   "0h-00+@+#
+    
+
+B p<H5T/3ah ,    
+    
+
+B FAhF\`K"IH{Dn3yDxDHH
+F0OsA"
+)F`hZh
+F1F!F(F F!+(F6pplFF FF F
+F1Fe!F(F F!+(F6p-OFhFFFdU#e"
+
+0F
+h +F O
+FB=)FFhOsF
+J!F(F`(F~@T Fw$
+@d"
+O B!F8F
+F++ F "0Fб F"1FFPO sF
+O BQF8FW
+"((F
+2
+HFz
+p1F F'
+(FA=F(DB F#h"
+!(Fx(F
+8F
+#
+8FF
+K{Dbh!hSbh!hS+hbhD+`
+JQF@FF
+"QF@F-
+O BQF@F
+
+"QF8F
+O BQF8F
+;JQF8F
+
+
+e
+8F+
+lFHFyFHF y3F
+Fh
+ TF
+MhxDh
+
+ p xD
+!`oxD
+$*X
+AF pxD
+!`oxD
+FoxD
+AF
+  O
+xD
+
+xD
+  xD 0 !PFt7IFzhXBD3
+  xD
+D AFO p
+xD
+D 
+  xD
+D zAFO 
+xD
+D HAF
+ p O
+D HAF 
+O
+
+D D8 pxD
+;h@FH++ha;{Dh  `MF0FM1h
+D Z"h@F
+D @ AF p 
+xD
+
+{;hHFH++ha:{Dh g `M F0FMc1hq
+!`oxD
+D S
+AF p 
+xD
+d;hH+@:{Dha8:HF{Dh  `MF0FM1hq
+!`oxD
+D AF p 
+xD
+J;hHFH++ha9{Dh `MHF0FM1hqt !`oxD
+D L AF p xD
+5;hHFH++ha8{Dh C `MF0FM?1hq!`oxD
+D /AF p xD
+;hHFH++haL8{Dh `MF0FL1hq0!`oxD
+D AF p
+xD
+:hH*+ha7PF{Dh s `MF0FLo1hѹh!`oxD
+D SoPF "hHF
+D E AF
+  O
+;hH++ha6HF{Dh
+ `MF0FL1hx!`oxD
+D
+DAF@xDD
+;h(FH+
+ `MMF0FL1h9!`o(F
+D
+AF p 
+xD
+;hH+5{Dha5HF{Dh
+P `MF0FLL1h!`od5X3LoPF
+D
+8<AFO
+O
+m;hH+
+ `MF0FL1hi!`o(F
+D
+tAFO
+ p xD
+
+;hH+K{DhaKHF{Dh
+g `M F0FLc1hH!`oxD
+D
+No
+
+D
+:HAF pxD
+d;h@FH++haK{Dh
+ `LF0FL1h
+xD
+ `LPF0FL1hH!`oxD
+D
+oHF
+D
+HAFO 
+xD8 0KtX3Ip=
+= `LF0FL91htH!`oxD
+D
+'
+ p xD8 !PF
+ `LF0FL
+D
+HAF p xDO8 KyhHFXAD3K{DhL
+ `LQF0FL1hquH!`oxD
+D
+4oPF
+D
+dHAF pxDb0 6aK!@FX3_K{Dh
+Q `LF0FLM1hQOH!`oxD
+D
+A޸GHAF pxD0 DK!@FX3BK{Dh
+
+D
+oPF
+D
+
+J IzDRXFB`
+K JF{DX3`hL<
+JzDB JzDzrJzD~r
+K JF{DX3@8; $
+JF{D0X2@,JX3@<L F
+K JF{DX3@<; 
+IiBؕ
+IiBؕ
+IiBؕ
+IiBؕ
+IiBؕ
+
+ip`` "AF
+Ѳh
+iaii
+$H! xD,0
+
+# (RFAF
+# FPFK F po%
+p
+UK(FUO X%wD3#aRKXb3#bQKXFK ")F`b,
+DB
+(
+C
+
+
+
+HF 3B
+B Fo(
+BF9F0FCf
+CFF,0
+hS!F,0
+0`# 0 #FH2@o%0FJ F#F H2
+0F
+ 0 8F
+XFJ8FK0FH
+J(F
+p F
+mPF98F (@FF
+JF)F F
+$Jo%
+o
+
+ Fo1gHxD
+
+i F
+W1F(FG
+ "#IF
+4O
+ "#IF
+oFw
+2F)FD +
+H !LxD
+
+?o0+`&`f`F+FF:F@F+h
+ )F8Ft)hFQ
+
+-o;`
+o0;`
+9F(FF@h
+8!+/ BFiBF(FT7
+
+
+#h >`YF F ;FG
+
+h|I"0F
+F0@o
+"uI8F
+xsI"0F
+F@qHo
+ xD
+kI"
+F@jHo
+ xD
+gK
+V
+mh[iGF
+ZhB@K[F B-ٜ
+J2L
+J|JyJJJp
+("
+J!Or 
+1F(F
+)FV
+|
+@FJ3MJX("IF(FNr(F(F
+})F8F
+?
+2MK{DJ
+$#h ! FiGF
+
+
+)FHF
+`h@"!ihD
+
+ihhh  F
+0FS50F
+F
+FF9F0F
+H*FxD
+M K}DX3@<;IK
+I#F
+JF{DXh3`
+HxD
+(@
+` JFAFDM<#1F(F
+FK{D[k
+1(FMyI o%
+01(FMIbo%L
+KBF0FX
+F!h
+HxD
+{DO3:FpH!Fo(xD
+ 
+R2 S3O S3
+R2 O
+o
+}D_4
+@!(F
+K7 F
+JF{D FXFH
+XFX2/JX2F D3$D"C&DL2F!FPFLRF
+H)FBF0F@"HQFxD
+K`pG
+K`pG
+K`pG
+K`pGpF: {F o0`pmF "
+)F0FLh FSFJF)FF@FHro0ocj{
+`pGHxDpG((HxD0pGFpGd
+`pGHxD0pG((HxD0pGFpG
+/I" FyDL3
+I" FyDLI" FyDLhI"yD     
+B"F)D0FK F(
+K@1
+H{DxDK&0{D
+H{D
+
+K L!{D|D
+FF{Dhb
+?7ңv6 @T$ @4CG? @<D44"DGhO 
+DBC#Ck`BK`a`xiB'ѹh
+DB
+
+(
+PEЄEhB?B
+0!B:0yE0iEaapi
+)
+C@
+DY@
+D@@
+DDL3T#0ZhF"Ri
+
+
+?:ҡw? @V6 @>CNONvD66"FO
+- 5%%
+. 6&&
+) FYD<
+:E G"0ƹX"0
++ 3#C2DQ+
+* 2""D3F#D@8FFr
+?=Ңt$ @Q @!CG? @9D11&AGhO 
+* 2""
+* 2"")FB)FF@P) F8#YB Fo?B ?
+*  2%"8F)D)
+D
+hiB
+K{DhSRBD@FpG
+pGDBҙE_h/'
+/PDQDSDJFIFKFMFOFFHFh
+)4%o  D2# Os-7 Ӥtlw
+f
+FyAyC!0fz +zD${DDE{DdY@ 0++$]
+0   " 0 ]F
+0 iF 
+   "0]FݿFA[ y + "$Jx xC#xCCx!F]KCbݿ$i K{Da
+yB"@+
+FO
+|CCJ|!F]KCb߿{{C# |CCL| yCc)O3F"
+~CCJ~Cc FF
+`lF
+FF FE0 F FEFFKh{DBnF-*F1F Fp"1F F
+K{D`
+*
+CFE
+`{{0iB"|[|BB!FBbHrh1i}}C
+|CCJ|Cc2i
+}CCJ}CcB;h UK{D`FIF(FB
+DE h
+xZT\4F
+(3K
+%#x
++Ko&{D
+*\ FHOaF FH#x/ +ЮFDFFO
+CIF"p;DF@?b+&
+"D
+0yDDABI
+0" DyDH#L0H

- F?fE FO O
-KEh{D3`-(F@(F?h-(F@(F? F8
-1F?70F?>9F?~0F?F
-# 40LN9FBFB
-гB JBAF F08F?:EHF9F3F
-#AF
-#:o7? 3V#(F
-#0F3F0'HoxDN
-#FػHoxD4o 1o6.?
-JF{D X?F``?^`hF@?V
-JF{D X?F``?`hF@?
-0F>ZHAFo xD+
-H"IKxDyD{D77 F?  F? F?
-U
- hh"F1FhjGFo(>= o
-o+h(F1F[jGF
-KF{D83E0;(F=d
-
-
-@FXFB
-RF(FlGF @ @
-@ F
-@\@~P @V @
-@ @@}@i@Do
-+􃮄 F.F @ @
-@ X
-@F
-KX=FHA 8F.DP
- F@(F=@@F@9FF"F F*F0F@0F@
-GF
-L
-N M|D K~D}D0FX*FK0*FXp@Ѿ
-8F;h1F
-_+B#`o4
-#`PFO
-+@FB F>HF:0+ + +uF.F*F&0+ + +aFFF0+ + +MFF,F
-FF >7Fk8` + (FAF"F;F[
- F `
-FF
-FF
-0F+`
-
-L
-N M|D K~D}D0FX*F+K0*FXp@#
-@ 3@/@ +O3p'
-<5>
-FP
-GF
-<M >So(>e> #o F > >F
-MFF K}DT
-
-L
-N M|D K~D}D0FX*F3K0*FXp@+
-
-DFO
-o
-FFFo f (FfB. o8f
-o #`<FzO2C -HFFO
-K
-;L=#
-FP
-GF
-;d=>[>oHo(xD F
-MFFi K}D@
-O0 `pmFk}sCҠmFkrFH1FxD#o O0+`p p pn&
-"F)FFȹ9F0F:F="F
-L0F:9
-F(F!FF9k+ E
-*F 9F=F8F:
-*F. 9F=<F8F:`
-ܰ_@_аOѠhH"IKxDyD{D22}
-
-:Bgo|bDB@𕁍
-o~rDB
-
-#  F#<
- < 
- F<< 
-<8aH1Fo xD D O
-EHFl<"F
-F0FF(F8F;G
-@ @@ O3p
-
-$$$$$
-+hB FR
- 8hqFFP#
-F
- (`"`g"u"
-OJ
-@
-
-K"%F{D 9F
-F
-0FPK#
-#C`F Fh+ ܀hG 3`
-+
- FH#
-#c`0Fp
-Fh!h FH#
-Od ~D ) \Z,+,-,
-1a``D`
-O< OajD
- D1 )M
-K"%F{D 9F
-K"%F{D 9F
-
-p$h<SSB T:\ 
-#FD  ;\ 
- 
-Fh!hFPOs
-Xp p h3 `pG hp pZp
- p h3 `pG-NF FFFA A
-A /NE;="VE"x=cx4C#^E cx="xCcxCx4C# F)F:
-G
- z#
-A$A$A$
-
- F
-E9F(F2F
-<
-
-
- hB`h>
-h2<
-0F!Flp+` g"
-hhhpGhhpGibpGK{D`pG
-N~D0hH"F; 0h;F(Fp1N!
-|D#h'#%HxD; `#K{Dh<#
--ܑ)\Z*+*-*
-D\0> *wRx0 /q&3B0j\!pBf W!pB`ܸO/ 
-O< OajD\0> /&اx0 v\#p0>B W#pB(+
- 32+ FSXBXA
-E F
-Fo
-KA"{D`@F %`Fh1F*F;Yh
-h|FHF#
-hFF
-F@@VC
-F F
-O5
+vFd alQ/HYxD`
+g
+IyDxH
+
+(FyDDRDIF(FD\;",*TIF`DF0
+%)0lP'
+0FYF%+O
+
+0
+
+ `
+0Z`rlOR
+
+j
+ B
+
+OA"0ADA<
+0DHP1")')  XFGF
+L0
+%
+
+D $C#g9FjE,
+ F@3(h3x[hh5
+0Dk@hBkB6 lY
+h8kBkB 6sh
+h #k3j`k`hZՠh h F@#R#3
+S|68FGF8FEkhJ
+fS* ]PbS"
+6
+F b)%zD.
+
+`cc;c
+C!(D ,
+J
+
+ J ,@FC
+ F (FpF8 I(FyDC(D 5FI"(FyDG5|I0yDC zJzD x>+
+  FsiJzDZhI"(FyDGF
+]+9FpCK0DCx>+[!(FGEsr)F F
+@h
+(K
+HFPF 3hBF
+)F@FG`(FB4h# (FeAF(FG4@F,
+YQF@F; AF(F`0FBp0FB-pOFFF±
+
+
+,
+ 
+h(F B<ZFIF+F
+3    <  (
+!F@F3F
+x `+aPFBa
+)OF FD!hs
+K,a
+DFpFF
+h1FR4 4[hAp-OFFFQFHFAx8FFH
+ F
+ 0h$0pGpFFhF)FbhA )F #p@pF0 FF@ 1F(F #p@pF
+#)F
+D
+I
+KEh{D3`-(F
+ F-OF0FFF@ @F4EkX$#
+ 6b42F0;FQFHFO
+
+R
+3 FA%h[E#1F#O3#@F
+ FAoF
+ KEZF  ,F.
+o
+BF)F8F@q(@KE IH@xD
+[E
+CE3hJF)F8F@
+XiDB'
+F)FF0`G0pGD
+
+baLjaDbJb0
+iih`KiCaiaia jbKjCb
+6
+?3F:F!F
+HxD0C F
+
+i&hDBzhRF1F F
+F
+DB'ٚB H@V"xD
+I>FP
+H.F!hxD0o
+;`
+I@F&FHxD
+IF
+H1hxD
+ #
+
+B H"xD
+h
+ґBF"FC++h #D+`8
+ KY0F?F F>"h
+K"{D=
+RFHFhG
+hG > #0`
+
+^hh#"ich1DD
+p#ih3B#akhBH"xD
+p(
+`; +o:
+
+
+c
+.`o(
+DB:BڢrB
+
+$!hu
+ I0F,0عo>d0h?
+O
+O
+ *
+
+8FYiF
+ <AIBF8FDK0F<IY03+hiRF[F
+F
+ EJ
+"0 
+
+
+FC
+ 3H :F> F
+8`Xh0`h
+FC
+KF
+ :
+FS
+& 0 F
+ F@n
+I@F
+p"FIPF
+BH
+3`5IF 2IF
+)F0F
+H*F !xD
+F
+JFSF!F0F
+"xD
+ 1FK
+X0
+302  1 00 F
+Z7 FZh
+M{D3`}D
+FFI'ع"FI0FRXHxD
+
+(F(FF@(FCI}H(F
+
+
+
+@ Q@M@ IO3pE
+
+JF{DXFC+`
+FFIXFO3B=HF@I2h0FiG(.o4*`#`F6IPF
+@#bcb? F@@<,dDdp
+06KPF*{D\3#`
+) ))(џ*Jod:*K{D3 F8p*Jo%e:*K{DB: i:*K{DBh HxDo(o%o
+@ @@
+O3p
+F
+M{D3`}D
+3
+FFhIFhh
+9
+0:H SF0Fm
+
+
+
+#ɍ
+cgKXKg2PgPPPX3#`p
+
+F
+H"xD
+2i+ؽ@
+H!FxD0o
+H"xD
+O0 `
+hh#*i
+ F8F F"F9F(FF
+RkoHM+
+BZF@F:F
+thSF1iJF
+ F8F F"F9F(FcF
+koHM+
+BZF@FF
+thSF1iJF
+p+h(FjG
+0FIF0FF"h FihjG$C0 
+jGF#h FjG
+X
+܋#"
+ED
+
+h
+'f
+DK EOI
+0F`K#,F
+#0C`F Fh+ ܀h `("
++
+ F`#F
+,F
+#`h0F; ` Fy
+FFhhFX#F
+ D $0
+_ +<0 ,
+:B0^&pBX&pB
+#0; +?b8OabZCx0;޲ .?X`0 /?Q
+'c0;;+?J<&"4
+zD   3
+D-% F`(F
+@F
+FFOs۽@JBcC Osc`PCh+
+FFhh=F`@F
+JF0F
+
+ ObBї#
+
+9Dh
+A$X
+A$XVJA$XSJA$XPJA$XNJFOX $X F
+@FF#A"
+F8FP!O(F
+I "yD@FO4
+
+ګ#
+B
+٥ ۲+
+&"$"  h hhhpG
+@FrF%  F #
+ IyD@F:Fh@FIyD+hB Fy
+,`O
+ h
+<0;ڲ *,0 . #B0X.`BZ.`B@6.),.02
+!1;a``B``++?O6 dEox0;ڲ *:y0 O
+#0; +?|@OabZC{y0;߲ /?r P0 /?k
+'S0;;+?d<%"
+zD   3
+Fj
+
+hhC`
+hFXF#F
+o
+hFF 7
+F-
+
+FP@MC"
+@3"
+
+'J= 7
+7
+ F@ C"
++@33"
+K=h
-37
-
-i
-
-
-F %@F@@#
-+bѹ
-F ' 8F8@3
-
-* @3
-
-B
-hO
-0FYF*F$a
-FF@Os
-6@D@
- 
-  7
+"
+6hSE1F F YF #
+
+
+
+CE3h
+

-hB۝60s F@Os
-!F0F!F
+   T

-9*7 @
-F /"
-
-F &,F@@&#
-+FFP@1#
-
-&0
-c@FF@9#
-0F)F8
-KF."FKFF
-?'O
+ F1F
+@F8X@F8!i PF
+
+ '
+C Н'@lOsx"
+0F,F(@F#
+ 
+ٱ+@N#"
+h`
+
+
+#?(O
+yO O

-
-x
-y
-
-
-!F
-O3
-
-9K
-ZF
-H <
-H H<(F 9"E(F9OKF "8F O
-{D9b#h X,X 
-9X<
-
-   (F9E  `*8FZHFWAF (F9
-
-FO
-F
-
-@i@Ϳ
-+ 
- *K{DT3rԊ
-
-9*hch+`&ch3`
-hB131Bai@
-FA3
-:/ɲ]!C%=0
-CY2&(>"!2%
-bp "2` 
-"pcp  0`#p
-2`pF!
-#+T
-H"IKxDyD{D,,0`p 
-F FFF
-E
-F2F08#h&`_FRF08(F0"!DO
-"+
-
-O
-+ ڲ*[ K@40"h2*q"`@FZFZ#50#`D+4VE
-
-8F @*DDUE5
-[K @#<
-Kr"{Do
-Kr"{D_o
-Kr"{D1o
-`pGh
-C`h [j[Os
-!Fc
-F
-NB4F F~D(F1F(4
-:FB
-HxD{K H{DhxD,ֿbO4`p F
-J8#ti0F F-AFF F
-*ТBF8F)F
-)+)).) :r)/
-): ):s)-Ђ)
-8
-K`h`(h h-AFFi խ#
-F
- {D\[\pCppG 
-" 00
+(F7Z(@ր(F7T #XC F
+8F6
+6H <
+H H<(F 7B(F>F7\KF "8FO
+(F7|B8 F
+F{#
++Q#0DG
+i"h]KG FF]K-O FFFH x h**i
+h CE
+h-AF Fh
+B0F7,
+Bi
++%$$$$ $$$
+@3B
+ NlK{DT3l
+
+|
+i:ShhhDpG
+hBSh
+DBLݢ20r*L}i  <OkO @o @Ti SUsD5 D DIcCH3 iDH4hDDK<$]
+ 4`
+:X@
+jp"2` 
+*pkp  0`+p
+FFFF
+.K".I.H{DyDxD+8+J0
+E
+4*FF D7T3hD5`4FRF D7H0"8F1Dt;
+_D
+"
+/-
+*F07+$t5`
+p,#
+2`p(F,
+"C*T
+ 3DB
+ B
+F(F1F
+T F0("
+o
+o
+o
+FFFο8F FF7A!FF(F8@ph id#
+po
+`pGh
+
+![
+F
+bpGFj
+
+"6vTE0h
+A
+ZE ,K@+I,H{D3yDxD+6+H1h@FQD
+
+ҼB(<F!F0h
+3xBB +ػ`
+?
+HxDeK H{DhxD,ֿbO4`Z F
+-
+)4 ) s)(Ђ)ja`h
+kO4 FP5ho
+% F0m
+F
+ {D\[\pCppGC;
+",
+ 
-|# 0
-#"!0
-",rC
-)' )CD)܉)Ќ);)Г)6 i h
-٘FC.H@.I.KxDyD{DFFh%iB*H@)I*KxDyD{Dh`iB(B5F%9F*F7h"iB`HOrIKxDyD{Dv/D@F8F
-8F0F
-#
- F"FF
-x
-OO
- 7J %F )
-I
-t#
- H" I KxDyD{D**" s`q
- gDz pz`p4 :;9
-!701ɲ
-!7s?Fи
- F1.+x-+
-p
-a#
-Ӊ#
-KE"{D
-ӵ#
-
-7|"h#`
-H
-OHt"OIPKxDyD{D**
-0FU& .F
-
-Ӣ EC UCBB
-OC
-;B#ss
-HQ"
-I KxDyD{D)){hu hr
-kh2{B`l`+h"Zs
-O&O&O&9
-I KxDyD{D3))
-FRѻ
-1(ٜ0
-
-JH*"JIJKxDyD{D))fxx-E%&x5CxEefyy-E%&y5CyEefzz-E%&zz5CEdXМx]x$D$x,CxDd]yy$D$y,CyDd]zz$D$z,CzDd]{{$D${,C{Dd]| |$D$|,C|Dd]}
-}$D$},C}Dd]~ ~$D$~,C~Dd ]$D$,CDc 
-k
-KHP"KIKKxDyD{D)<)N
-AF"<
-
-#Et
-FF9F"(FF50F "50 
-J#
-<r " Fyx
--BbO#*F!F
--BbO#*F!F= "QF2Fo? F
-#
-#
-5pG-OFFFFhF"
-3
-
-0F"
-0
-k+ @>#
-ZF"%IFBF
-
- OAs
- 
-@ 3
- A
-T+ @#
-v#
-#
-
-0
-
-O
-+ SD[DOS:ZDJ
-
- JD(
-
-
-O"BHѼ ?''1DD?1ED?1CD?1BDDDCC`C`-GO h~'Dh $ OTO
-H$)?
-
-6O
-J2
-# OU 6I5 "6Ѽ !?''1?1?1?1EBCC`C`-O FFF
-xqx3x?G! C
-ix+xB")yCxBbyW@C# Cy5CcIFX@'p;
- qcp; p;p
-cq qq4
+@|#"9F 0
+"1F0
+)% ) ) ܉)Ќ) hpch
+U F+FJF
+
+x
+'
+G%F4
+
+ܫhB< K" I!H{DyDxD0,O
+K"
+I H{DyDxD**j` 2
+F
+F
+!(F66010Fɲ
+O
+p
+K
+5#hD#`
+8 F
+KKq"KIKH{DyDxD)n)@B(D
+
+HF
+'
+Н0 _ + O
+)hh hT$
++h"Zs
+KOr I
+H{D3yDxD))h{hDhD
+
+()F h"8@88F F()F h"8@8Ch+hhQ`
+F FYFPF yF
+`0 @"
+F
+hD``(F4
+p("
+4!F"4
+
+&
+OueDw@DO7WDD@DO4T O3cDDO2b O3Cw@DOwgD@DOtdE@O5UDDD O1AO3cDD O7W
+O6VD O2bD
+Ovf
+#DD
+O0cO2BD 
+Otd OvfDY@FO1QDD O2cD A@OqaD}@DO5E+DFS@O3SD}@7DO5e*D O5ES@Osc(DD@DO4TD O5e(DD@
+OtdO5E*DQ@O1QDO5e*DQ@ Oqa
+O6V7DO2bD
+OvfT28:ذ53=;ܠ94<1 R# Q#
+DA# 3+
+3@+HpO@Obpp
+RKO"RIRH{DyDxD((.NKP"NIOH{DyDxD#'F8F ( (F
+ UFIF(F
+K"IH{DyDxD''9F
+ "F3 a#FAF
+F(Y#A"
+FU2
+*CcO!1F F?
+FT2
+*CcO!1F F "= F*FIF F$?*F
++ #
+3pG-GoFFFFF"8F0
+c0B8FQFG
+Q0-GF F 
+ "
+FO
+F
+FFF F_& FJFYF F "
+ @F"AF F
+Xh@3
++ OAse"
+ @ 
+x-AFFFFs+ w#u"
+MF
+hOs
+Ah(F
+K{D9F(F
+ @h@Uz
+
+04@+ХB6O
+
+-CF FFF+ Os
+"  VDD~ED2DO8HE2D$2DTDO6F6)
+TD4DOT93DI( 3DCDO&FC!Ѿ!?1`O O 5D?1`2D?1`4D?1`3D7EBDC`C`-CFhOO Dh7~o $ OTH$) OFB2(7lOF3" 7lOUF5#7l!Ѿ!?1`O O ?1`?1`?1`7mECBB`B`-OFF
+Fxx=x<yE
+]@\@
+CD*
+

-
-3
-,$ 
- qcp; p;p
-cq qq;
-7p0qsp; ?p
-psq
-+xiyO KK+*yK xKkyC#IFCy5Cc
-Fbq: ?qq4F
-
-
-dS@
- 
-<,<,< ,<
-,<<O#
-sq; ?qq-O FFFFhF Oz(O2
- H" I KxDyD{D'q'D4`p(Fp
-Z#
-PF  l`
-AF:F(F
-AF:F(F
-AF:F(F
-AF:F(F
-(0$($F`0Y6!"F4)F \
-ڣ#
-k_
-
- HDZF4 h0F RF4 ( F
-
-
-
-
-9
- Hs" I KxDyD{D''D4`p(Fp
-=#
-PF3@- &HR"&I'KxDyD{D3' '-
-AF:F(F
-AF:F(F
-AF:F(F
-AF:F(F
-AF:F(F
-AF:F(F
-AF:F(F
-AF:F(F
-AF:F(F
-AF:F(F
-F
- F<P;0 (<
-0
-0FBEHOrEIEKxDyD{D
-BF
-F F
-B
-` D$
-z
-
-F FP
-F
-F7BTH"TIUKxDyD{D
-
-Q
-8D F
-
+D<*
+2x6
+ L ,* ,* ,"
+ ," ," ,>,>C#,>C,>>BB>B"\@
+CYFU@!
+@0+ 0+0#
+0# 0#0+
+=p<q{p+ -p#
+p{q# $qq
+qy6
+ L ) - !
+ \EF ! $  LF" ;p"
+;pL;*;p* ;p*
+;p\4FMF-OFFFFF  
+?
+Ks"
+I
+H{DyDxD%2Fl Fpv
+PF@.$KR"$I$H{D3yDxD.2F9F
+ F
+)F F
+)F F
+)F F
+)F F
+)F F
+)F F
+)F F
+)F F
+)F F
+)F F
+
+
+ڊ#u"
+op+p
+0F
+1
+RF0F
+
phpy qÈKqCh
qChqz rCKrh
rhr{ sÉKsh
shs| tCKti
-titpG
-pX3 +p@y pÈKpCh
-pChpx qCKqh
-qP;q1BpG^z-OF FF1B.F\F4FO{
-1F(F|=6k@`
-EFH"FIGKxDyD{DB
-DH"DIEKxDyD{D&&@)AH"AIAKxDyD{DrE&
-B<(, 0FO|AF
-B(3
-  I 2B F@
-3. >fC
-\, "J 3Y ~BF
-CJT5BFj
-F F
-F{D
-JzDx2Cx20
- rhQU5"x0ԚB"xBzH|xD BbxB44rhQU5"x0՚B{x; 
-#
- @I
-phAU5Q]
-O4xDFXOs
-;@F!F2F@#,F
-('FO
-@  !F F2
-* ;
- Y\x3@ F!3x4ёBB Zx9 
-3JFxzD2  
-
-|?
-}T`hRhN FK
-
-K"%F{D
-(F!F2FF F!(F|
- F2G%F,F 2
-
- 
-gc#rOR`E
-g g
-E
-#E
-j-O
-iiiiOii h)|I
-aO)*O)JO)i$|Dab!~AI c"|BO#~CO9OXHOlOl8Ol\LG O
-O, GsGsss.Ft.-tEDtuEuDuLuLIvAAvvvBwBwww
-
-
-
- 
-
-@+#
-
- 
-, #'#####$##%#&##(#'###)##*##
-##
-## (-'#$%&-.(')*+, .g/#g-(g'g$gg%gg&gE
-#EEtOT`E
-J 
-OakI 
-# e"2@;@aaO3aO|B
-
-  #
-c *b#c jb1hF-OHhh i
-%hC
-X
-
- 
-
-  Xgg
-g!gg
-g
-g!ggX ggg
-g ggg!gg
-g g
-O|BK O3@@
-#i@O~@CO1#@# @c E#rOR`K
-B EE#ErOR`C
-
-BE@O~F O|B@# e
-
-  #
-c  #c $ #0FhF Fz
-iFv
-Fr
-!FF$
-hFiFiFc
-F
-ZFV<
-F $
-JFF<
-F$:F6<F $F*F&<
-F1$
-F<
-Fc$
-F<F1$FF<
-F$
-F
-F<(F
-jF)0
-
-X
-\0 h0ppl`dpp`h`t0p`lp(d`h0
-#C
-# #gC ##C##C##C##C#I #G
-gK #A
-#O|J O;g
-@ 
- a
-
-# I 
- 
-#gO~@@
- iO9 #4&c #`g
- g gBO~H #
- gg # a
- gO~J O;#
- c  "q(!F F!*Fh!*FFm(F("Fh#!Fc3-CFF((F9F2Fx F(F9F2FPI8F!FBFN(F)F(HHFPxAPhF
-F' F9F*F,(F9F*F8FiFJFHFiFJF
-k FFOPjMJ z
-(
-k FF OPkOajK4
-k FF"OPkMK
-k OiCLH (#
-
-,g#"@+@ahA$# i
-iFzD#2FhFiF
-2FF&
-s
-F Fj F!F
-jF F!F!F\(X(FT(!FF(FFF(F(=(F9>(F &(-(F)>(F&2(2F>(2F &(F (F >(F1&((F>(Fc&2(2F>(2F1&(F(F>(F4NrF~D(F F"Fb F!F]jF F!FX(!F(
-FOjF2(@2xAF " @jF2('2iAF " 1 F!FH+!FYx0 F!Fx
-x''
-jF58F@6(
-P7jF8FiF
-8F9FJF- F?%(
-P
-q cP
-:iFYPFP-piF5RFhF1F
-hPiFC c
-0P
-piF5- F
-(
- #B K Bb 
-EhDt 
- g BAb 
-
-" Br 
-EIO0
- g
-
-DAt 
- #t
- 
-g
-[ FAf
-
- E"
- $
-$E'
-*
- (E,
-,Br 
-E1
- Br 
-E7
- 9
- <@Ap # 3
-G #g*3G.g g w
-K 
-g
-$#C g$#&# wNC&#sgY(#C*# # 3G#g.g3A #( 3GcB*g
-g
-2DA g$ wA$I3E]&#C&#  E$E#C# (# C
-#sB
-2*g6DgJG(g g wA3Y$#C#  g6G"E$# # C
-#cB
-2E$DEE (E$<H 
-E
-2$DEE E$H 
-#C# #C
-# 
-
-
-2 g6D G g g6H 
-A
-YPA!#c#OPRA
-EORTC
-#c
-#OPRA
-E$ E
-EmB
-
-aE$EE  E$HE$E
-EUB
-Ui
-E$E 
-EE $EEM#EE #E"E 3E#"EE3A #  C
- #sB
-2$DE E
-E $E
-EcM3Eg]6G Eg #
-
- EQ$E E E$AH 
-EY$EE #E
-E#E
-#
-
-gG # 3 
-#
- 
-DK
- #J
-K OPRE
-Ecg ##ORPC
-EMDE%6gI
-A!K
-#A
-#EEc
-#A
-C#K 4Fa=F"G
-EG D
-U  
-K
-
-E$HEE
-I£Q#C#r {B"]
-k B"_ OBVG'A"F+F
-EcF#B KFB"_OBVG'OTREi B"k
-OCWAVKG'B FFE
-k B"_OBVG'EF F cF#b kFB"E_OBVAG'KB OC[B"i K+OBZEF F
-c OeYOTX #"#OIWH(G'OHVC FFFi g"ORXOcYFH(OIQOHPG A!{r
-k B"]TE%0F9F@NI
-g%N
- wC#KB 2
-g
-hDG g
-g
- w
-&FK /F
-@  <#aDC#kb OC[B"K+OBZI OiS
-
-g B"gYgPA!FFGr
-k {B"YPA!
-K 2F;F
-gcTF#OkSOZR]FYB"A!OBPOVRG$eB"{EOBXEOCYAKI)B FFB"
-k OCYOBXI)EF F c F
-#kb F_B"
-G'OBVOZRK i "gB"OkSTOCUG{E%r 
-k ]B"E%OBTA2F;Fgc #KB ]B"E%OBTOVRG
-q CB3C{q q CCCq#[O2{
-2rsr{ C3Cr3 r3 ;s3 C3CLSsOsO3,CLCCsO tO#StOC47FC3PCtOZOZ:t00Su3
-u3 NFCCOYHC@uv
-Sv CA3Cv v CCMFCw#[O2OY#bww1-O_} FF !P-FF@1#@1_1?C@_1X "+"F)F&``(`6-- "  " "F)FLpp
-
- Brgp
-BArgp
-`Brw 
-cOPOHAhL
- E2#MCD
- EI4E52E4#C2##2EE2E@
- #4EE4E#4EE4E  #4EEL@
- #4EE4E#4EE4E  #4EE4E#4EE4EM<<CDt7
-" #6EE6E#6EE6E  #6EE6E#6EE6E#6EE<EH
-! #6EE#6E"#6EE6E  #6EE6E#6EE6E#6EE6E#6EE6EN>>[ m Cd9
-* #8EE!8E #8EE8E #" #8EE8E#8EE8E#8EE8E#8EE8E#8EEO>EFFCt89
-$ #8EE+8E*#8EE!8E #8EE8E#" #8EE8E#
-8E # DE 8EGBEb .
-
-# D#DC
- (
-# D#DC
- 3YD#A)E(
-# D#DA D#A.E
-  3YD#A)E (
-# D#DA D#A.E  3YD#A)E(
-# D##DA" D#A.E  3YD#A)E(
-# D!#DA  D#A.E  3YD#A)
-E(
-EE
-E&
-E
-
-E)(
-#&A'
-# D%#DA$ D#A.
-E  3YD#(A)
-# D'#DA& D#A."E ) 3
-Y# D(#DA D#A E.
- D 3Y##DA:E g 3 D:#C
-K e0# *EORPDC
-C#K e6#6(E8EC
-k 8#g.ORPC
-k #g0C
-k
-#C
-E@FIFe#"EC
-g
-k I
-#MLgC
-a#
-.
-3G#g
-3A HI0g
-3G#.g
-gGKgN#
-6##gNCO##
-
-cD
-K # 3
-K
-K #  SD.
-K ı # 3
-K #,cDI (#
-3I (#
-3I (
-3I (
-(CDI (,
-#  
- 3(I # cDI 
-#
-3
-K # 3I 
-
-K
-J
-Ei #C
-O@RK C#a
-#ORPC
-
-e #"EC
-OPRA
-i #ORXC
-
-(,
-
-I
-
- 4 
-I
-<
-I
-I   T
-K H&E
-=DK Oܢ E UI
-E
-
- E 
-EM
-K
- DEE  EE E E4
-H 
-E
-pt
-2K EF
-K D#
-C 2#FE
-7KK U2O
-EK 
-U
-
-DK 
-
-OPRA
-#i C
-k
-A
-E%K aOPRA
-A
-YPA!#c#OPRI
-I 
-HK
-k EB"OCYI)EOBXkb FF
-k B"OCYI)OBXA"F+FEc #KB OCYB"I)OBXEF F c #kb OCYB"I)OBXA"F+FEc  #KB OCYB"I)OBXEF Fc #kb OCYB"I)OBXA"F+F
-Ec #KB OCYB"I)OBXEF Fc 
-#kb OCYB"I)OBXA"F+FEc #KB OCYB"I)OBXEF Fc #kb YB"A!OBPI "FOXW+FcG'#OiSz@FIFcC#aIEUE ` 
-H 
-
-G'OBVK OkSOZRi B"YPA!RFI [Fc#OXROiSFFB"OF]OBTE%OPRA6gB"K gOCUI TOiSE%OXRgFYB"F
-k EA!OBPGBFKFFcF#{r OC[B"K+OBZEb k
-i
-B"OCY F
-OBXI)OZRK )FEB"OkS
-OCWEkG'b OCY
-k B"gI)OBXA"F+Fc #B KB"]OBTGE%{r
-$0  CF3-C%0 &0 CC-C'0#[O2s
-( )0s C3-C*0; +0; ,0; C3-CG-0 .0
-CBC-C/0d00
-10 -C3`pC5p20OZOZ:304`FO#60OCC CC@7080
-90  CA3C:0 ;0 CCC<0_iO8OX#OXH= >0? _}-AF?0x=FFF
-p  pp 8 8"pp c`* F$>W
-c]Z
-Fp)Fzz)FF(FF*p<ODDDghbe `*x `iF "
- hF F
-h`pGpFFFh`h` p h `
-i` Bh`F
-h`
-!KH8F!!D8F!?豍QF(h"3FHF!
-ѣi0F
-Os
-O0 hF)F
-"
-K{DchG/8F1F*
-
-KA"{D
+titpG 8$1P/3,B,h
+,h,BpG8H10y3,ˆ,Bh
+,Bh ,x ,B ,h
+
+,h ,BpG5B2,FO
+``  U@7E U@ ,u$
+B
+DK"DIDH{DyDxD%%B@K"@IAH{DyDxD@)>K">I?H{DyDxDsB6u
+FhF
+ YB!OqC  L 0_(@5 CsC 02
+  K@IH{D3yDxD%*%<(Ff#@#B-@.9#'OK0F{D
+
+E/KOrIH{D3yDxD #'OK@ {D
+ @
+
+X@,p
+
+3BfQF F
+ X\ CZT3BnB
+ F,+h F %`Z
+FDxo[
+FDxo[
+E)F@FA
+K@1{Dx3  Bx3 00
+BpG^
+n+
+b+
+t+ #ahKU5 #
+##
+ !3F(FzDI*F yD&T`hh F
+@\!F F0LC
+)B6
+F
+
+)(F/
+
+K" {D(FpF2F(FF F 
+
+:(x0
+1 F F038%
+ )Bh*:\ ) )pG3:`B`B`8FF F0bhBJ)F h0@ 8
+D
+"9F(F8
+FF F0)F Fg
+JlF)F FzD0I FyD
+I(FyDPD F0Fu
+9F0Fw(F8 F
+@!(FFZ(F y 0D @  OSJF)F8F z09FPF  "FEF@"!F`
+(F )F(F *FIF(F T)F֭(FF *F(F!F O)FHF"(FS0ӻ (F (F "QF(F "(F IF "(F @"`(F
+#>` 0JzD (F (F "(F "QF@&2O
+h`pGpFFFh`h` p h `
+i` Bh`F
+!0F
+K{DAF0FpF(F(F
+D]KShG3+
+
+(F#
+K{D0F=
+FFF F, FcF8
+ {Dh F0"
Ci`pG Dh `
-h` h`pF
-*v
-8O
-
-w,4"\2ҲTR
-
-
-
- K
-
-
-
-{8Fxu|F
-
-
-тBS
-
-
-
-
-
-
-
-
-
-
-
-
-F
-x3
-"
-"FF "FAF
-,|ii"F
-OG"FADki "FYxiiO"FADo`ki"FYf(h 6.@
-"D8#
- "6
-
-
-"P#
-"
-KF{D
-ڕ#
-0F.8F 8FTO4 F
-FF$Fh#
-
-тBS
-
-GF8@ʿ
-h ?Ӕ
-FOpFp!FOr(J F)FzD
-
--H"-I-KxDyD{D@N1eRKaX!&HxD````
-F F p F
-K(F{Dhb`
- F8j
-F*W%
- FF
-@F  
-0
- Z0
-
-
-FP#
-#
-FOq F F 
-Ft! F F 
-F!Կ F F" JhDhBh3k#GO0o
-׺
-"V
-G F
-F F!x4
-г +рh]鿀h]轀h]Os
-#
-#
-i- Os
-i@- Os
-i- Os
-i - Os
+h` h`pF
+`U*F9F$/*F9F,/$  Bx3۲9
+
+3
+
+DB
+ {D"FF
+ FDFOPF
+RF0
+ K
+ 
+  FS @F+ а@#d"
+~@F{PFxF
+
+FF]O07FFF(`0
+тDBS
+XDB
+ K{D F
+ {D F
+
+ {DL F
+
+ {D F
+
+ O F
+
+x32F F,p Fx
+;JQF@FH#
+K{DF|
+FF(F(FFx#d"
+
+
+тDBS
+XDB
+h ?ӌ
+x"Fv"h9h0h*hZF((FOa
+ HF$3Y2K
+0Ph
+ #`
+F! F F 
+Ft! F F3 
+FOqԿ F F JhDhBhKk;]KGO0]KpGo
+p 0F  0#t#
+"9F F
+K {D Fx:F1F FG
+FFF #f"
+г +рh]h]Vh]@W"
j
-^kFOs
-Ѐ+Os
-K}"{D i @
-KF{D+h(F!hiGF h%` |
-"
-"yD1
-"
-"yD1o
-0F
-#
-hS#
-~#
-3Fr#` 
-"
-"yD1%
-"
-"yD1n
-1#
-K"{D F
-@ (`1F1Fp@9 p
-"
-"yD1]
-"
-"yD1
-KA"{D F
-KA"{D F &9F@"@`%(F0F`
-@_
-HF
-@?
-F
-BF;BABc[A B
-+@
-
-!
-@u#
-"7
- "yD1
-"
- "yD1V
-
-0F
-h#h#+-GFO
-0FH#
-0
-`hF9F0F"
+\k\Os}"
+@+Ѐ+Os~"
+"9F0F
+м#o"
+h[#
+
+K {D(F0F
+F
+Fh 3p
+"1F8F3
+"!F0F
+KA"{D Fp
+KA"{D9(F$@"9F@@*0F` F
+ҷ#d"
+ `
+F
+FCF
+F
+BA BABl
+i``!@.i+Ost"
+]
+"1F(Fg
+"1F F
+jB #HxD
+0F
+@F$K,FFF.F{D!K{DRF IHF
++-GO
+04F
+0qF#F
-ўH_"IKxDyD{D( @"@9$ O
-
-~d^$J
-7p`
- S 
-Ay<qi QIDE71qc
-
-Ҫ#
-F H
-E O
-  T'HFAF:F$T
-"F+F#D 2C
-
- 4
- 
-[
-K
-K
-K
-F(F
-H7"IKxDyD{DI[p
-F FN02F
-
-H"IKxDyD{D3E
-chS%
-F
-
-F
-FF
-4DE
-JzD#hhB
-#FpGO0pG pG
-#̻FpGF
-#h`h/a`h` F F h@ciA
-#fFpG
-hI0FyD FFpF 8FF(0F*FFhF!ihhFF
-LF
-I|D`X
- I
-LF
-I|D`X
- I
-
-LF
-I|D`X
- I
-LF
-I|D`X
- I
-LF
-I|D`X
- I
-LF
-I|D`X
- I
-i!FPl#
-
-d#h
-(
-(
-(
-JF
-B=nYF0F F#
+џK_"IH{DyDxD
+ P
+@"PF@9)#O
+
+DJ# 3+
+4
+OJKFX
+0
+3.F
+K 
+@3"
+@C"
+(F
+K7"IH{DyDxDhz 
+K"IH{DyDxDN`!F
+F
+F
+(F8F
+F
+F
+h#SCJzDX(L
+h!K{D3Yh(
+Ose"
+(hhh'a`h`رF
+hJI:FyD0FF Fs FFH(F:FFh!ilF F FF(
+FF/HxD^F
+M &}DTghBѧhB#h` 3+
+
+
+
+
+
+L M|DdY  
+L M|DdY  
+L
+M|DdY  
+L M|DdY  
+L
+M|DdY  
+L M|DdY  
+ѹ&hFl#F
+
+(FyK&FWO
+
+
+F@F1FF
+(
cb #b
-" 
-
-chh cj3(F!F!e!F(F! 4
-&
-HFPOs
-!0
-)8F))L|DL|DL|DL|DI(FObyD!F(FOb I(FObyD8@
-#
-+sI "yD"F@Os
-,
-FA)7:a)W: Os
-O
-! `9FBFKF>C
-HF!F"e
-# "Cp
-
-*&
-0F
- ?F8@#
-O
-(FF8@#
-Sp
-YF F "
-!
-D
-RD
-#Cp
-`rh
-`jh
-```f0Fc(F` 8F0F(F
-
-
-`
-O3
-F
-F
-O3
-F
-O3
-O3
-F
-1FBF;F
-"
- "yDF0%KC"
-
- F FBѿ
-
-I "yD 1
-
-Hm"IKxDyD{D.(F!F= F "
-(F) (F_Bъ
-}
-FIyD
-FIyD
-0"
-"
-0"z
-  "
- Fy
-
-F8@
-g@Fa
-Д#
-0@PE<DEҎ#
-ӕ#
-HFAF s\
- 0  Eё  hHF
-  HFQFZF
-BF7gCDgff>O
-
-@FIF U : E8F)F H "FH"IKxDyD{Dk!:\pD T
-;BRBo
- 4 @j#
-#
-
-@q
-"
-sF
-q`
-!
-
-RW
-
-0"
- 
-
-"5
- 0" @Os
-
-"FPOs
-"
-
-(
-"
-FP@i
-
- FA=F(B F#
-
-!
-+2
-
-
-QF( B #
-KD"{Dz F
-O
-HFLFPOs
- HFFHF9FF
- FB
-% 
- i*|J
-h)|I
-
-
-
-
-
-~FpG pGF@hhv8 (F
-IxDyD|F ` F,F& 
-Kh"{D F
-FFFhx#
- FFX#
-FFrFh#
-@FM
-"G
- p
-
-O
-Cx4B"!xbx4B" + F
-wh8FFFYF FJFGO8NI F"yDG
-(F!Fh3hi
-I F"yDGf
-"F.
- O
-Y
-IF(FSЃh0FBBFG
-#F
-
-(FF1F&0F G D\D
-FKh+IyD0Y
-V#
-}#
-F#
-"E$#xB
-P+U+
-@#
-(FF8@3
-`D
-rI *FyD{ F
-
-mJmI{DzDyD`
- 
-`0ѫ`,a
-@
-"F#xB
- F7F Ft(а(Ѡh)F0@h)F0@ƾh)F0@P#
-`
-RH"RISKxDyD{D FF8#
-I F$yDIyD
-FhDIF;F2F FyD8F@I2F FyD+h Fh
-K"%F{D 1F
- O
-#
-"yDD
-K"%F{D 1F
-I(FyDv  F
-+ +PP<2O*0FiFW
-O CD~3 +~ؓy /TzOCy DzsO
+7 3
+/
+6I0FyD'Fh
+(
+(
+!0F3p
+I FyD&?@
+)8F))L|DIOb(FyDd!FOb(F^
+I(FOb8@yDUL|DL|DL|DB
+"E
++[I "(FyD&FX@m"
+,u
+FFPFFHF& NIF " FyD (Y:FIF FBRGI" FyD}(J0F&F
+!(F
+RF!FHF
+
+#Cp
+PF&NF0"8D&.F
+ F
+"Zp
+(F
+ }F(@#
+ O ch
+"Zp
+
+] +0D
+#{p
+;hRFHFDI
+`jh
+`bh
+`b`<(F9 F6 Y
+
+FHF F0F
+DF Fcx
+F 
+ 
+ 
+
+ 
+
+F 
+ 
+[F
+o#
+
+0
+O B9F F:
+F(F(F$[
+!F(F$
+!F(F$
+
+y
+F
+Kj"IH{DyDxD9F0F$
+0F$
+0F$Eђ
+FIyD
+FIyD
+K{Dbh!h$/bh!h$)+hbhD+`絡
+FF!FJ((#
+"QF0F
+F0FFF
+
+iE* $
+B))F@F$tq!F E{ B19D
+
+8FIF$J0 07K"IH{DyDxD\ bDDT
+;
+GciFGF0F#"8F
+")F F
+F
+ (F
+ (FDF
+8FDKF
+IJ9F F
+"QF8F
+
+"QFXF
+J)F F
+O B9F FQ
+" (8F
+8F)F
+
+K"
+I H{D*3yDxD h0
+FF(F(FFxx#d"
+K{D FF
+FF(F(FqFx#d"
+F FF
+DDE;QF0F \\0 "G
+")FG
+ 0(.JF !(FzDc")FG
+#p" G
+
+۲EB(F"x4B"R"x4 1F F
+ɲ
+ 0 DF
+(F%F6г
+.9F
+0FJO
+#F
+
+FFHxDp
+FFHxDFO4
+hh
+(F*:FQF(F
+F
+
+0F!Ed- 4 IF8Fw*
+h
+2F
+"!M
+Os"
+
-A
-zDzzO A Dy({/,%9,#Q{/) 9)$/OD DuБ{.)&B/ ټ9
-d!
- '
-
-+6
-O
- O
- O
-FFhըI "yD
-"yD
-#
-]iI FZFyDt
-F&F
-
-BEI FyDLCICKyD{Dkh
-h
-+h?
-Fh
-=<,E <$=$
-h[hh:F F
-hhh#h++ `hQh@(`hQh@)ͰFF)0220F*FԱ##`F )F0F9F@#h53#`0FhBO0MFh+@h+@h F@8F Fp
-6HF hB0(F
-
-@hGh8F F9FFp(h08F K FLFX$6(hB0 F
-FF
-  
-C!C
-  !
- 
-3#
-K"{D
-hhhpGpFm  pchc#h۹)F`h0`B5
-5
-Ѫ#
-#a cas (N~D3hsHxDF0`8#
-T
-0F!FCh
-`#ih f!Fff
- j@0sFo
-`f!F&f
--
-"
-6
-=  --1F " 6 =2xZ*-*+*0",FpZp3F-prxZpбx.)6=x609 )<3FB3F
-hFYC
-
-;hi`&
-
-j@Ā*j
-2BU
- ` ``P h 
- coF
- hnعaF#l FGF
-
-
-F f#g cg#
-#
-YFPFF0  PFEPFEHFO
+F{70F!FO1 hJDzD
+`1ѣ`%a
+"!F#x4DB
+@A3"
+:!F(F
+
+PK"PIQH{DyDxD`hFH#
+p
+ 'cI" FyDF
+" FyD1
+'
+
+&4S` h;` `p
+ЖI FyDT
++ + P2O*IF0F
+y
+$Ky0:21: *
+0y0 003Mz0 \z0^[ {0 -UM{0=_ NظUMЌ{.,Jo   
+ E0
+ Z.DX" 1N~Dx0 Od 0>Ozy xxO
+ 0> 
+3 3-
+#
++7
+JCI
+0vI!" FyD
+ #WI " FyDG
+" FyD;
+#:#
+9FRF@F!PE #x"IF@F(@#
+K
++h? <
+kRjj*jj8@88Fh FSChCh{
+hhhhÿ
+hhQiXi
+hhhh0
+
+)F0iKFRFAF50iBd#h8F;`ch{` LF F@hpG-G̀FFoDF h 0 hKF2F!@h( h0;F2F! F8(Fx
++(h0q
+@hGh8F9F Fx(h0^8F K FX0F6(hB0J
+""ZE!
+C
+
+C "
+""
+DND$ݙ#
+
+ 3
+
+K{D+э#h"
+Ch`pGChh
+FF@0A("F)F Fp@oFCK2F)F F{Dhp@G2F)Fh p
++a ka$N~D3hHxDUF0``#
+M&}D5P4,LI|DyD hh
+hhh`
+
+h#ih
+ f!Fff
+F
+FsF++
+#ef#f!Fi

-S P  O
- QF(hF
-c
+B&"!F"f
+E ѹ
+hCn B7
+h 
+
+

-EѺ
-b
-n
-@s
-A F(FB@
-F
-F
-% f!Fi
-.i2"
-
-
-!F(F h4;`DE8F-CFFFF
-
-h|`0F)Fx` -AFFFFh$]F
-Ch``ch
-[h`p FFF F %O5[*FF
-FIF{DXX!F@ܾH
-FIF{DXX!F@H
-FIF{DXX!F@~H
-FIF{DXX!F@^H
-FIF{DXX!F@>H
-FIF{DXX!F@H
-FIF{DXX!F@^G
-FIF{DXX!F@\G
-FIF{DXX!F@\G
-FIF{DXX!F@nG
-FIF{DXX!F@~G
-FIF{DXX!F@^G
-FIF{DXX!F@ҸG
-FIF{DXX!F@F
-FIF{DXX!F@F
-FIF{DXX!F@.>F
-FIF{DXX!F@E
-FIF{DXX!F@濮E
-FIF{DXX!F@fE
-FIF{DXX!F@ֿE
-FIF{DXX!F@zD
-FIF{DXX!F@VD
-FIF{DXX!F@jFD
-FIF{DXX!F@FC
-FIF{DXX!F@꾶C
-FIF{DXX!F@ƾnC
-FIF{DXX!F@rB
-FIF{DXX!F@$*B
-B
-FIF{DXX!F@8A
-FIF{DXX!F@
-FIF{DXX!F@RA
-A
-FIF{DXX!F@@
-FIF{DXX!F@]
-FIF{DXX!F@8R@
-HEZ(Ќ(#iC
-F8Z #iC#a+t(a@F
-
-O2F(hQFFhBF
+
+/Ff)F jF
+`
+.FBe)F mO
+ 0 3coFYF F h 
+
+
+#g cg F#kfGF
+hhhhFP@sr"
+
+K{D4
+FF
+H|*F!FxD"
+hhhh͹FH j5 F@0FFFF
+
+FF
+FF!
+
+
+0
+
+L
+
+FB!,a0Fh5@FF
+K{D8FA]2F)F F(Fc"
+K
+FFFRC
+FFFҼ2C
+FFFXC
+FFFB
+FFFUB
+FFFB
+FFFB
+FFF@rB
+FFFRB
+FFFR2B
+FFFظB
+FFF
+FFFA
+FFFv.A
+FFFfA
+FFF@
+FFF̺J@
+FFF*@
+@
+FFFκ?
+FFF?
+FFFJF?
+FFF$>
+FFF6>
+FFFb>
+FFF>
+FFF=
+FFF<<
+FFF޸n<
+FFF"<
+FFF͸
+FFF;
+FFF2;
+FFF
+FFF迂:
+FFF
+:
+hhhhs
+FXZ+a  d
+
+(3#hXikB玹#h
+
+B ܻh=`<<
+ 
+I
+
+
+
+
+
+
+0FA=F(DB p#}"
+F hFF
+,`sFFhF`#,F
+KA" {D, Fp!F1F(FF(F
+KA" {D Fp!F1F(FeF(FJ
+KA" {D Fp!FJ1F(FF(F
+K"
+I H{D3yDxD(F%fh
+hhQhXh̿7F M}D
+3KHFO Z0FHF]
+KhXFKhXF F0@
+O
+`TO
+g`@ 'h
+:h
+
+
+K{DA
+2F0!8F1F8FF*F
+h*
+xkx*xx
+FF ]Os"
+FAPFr
+FF F{-OHO FFD1F

-(hEL8F
-(FA=F(B p#
-p
-)F F1FF F(F|
-)F F1FnF F`(F|
-)FJ F1F,F F(F|
-
-
-FXi a%d
-khh`hh!FnhE`hHAF
-F F
-Ի Ah
+HFEHF6@FB1F@FF@h
+)FJFoF
+
+K:h{D F,F
+
+!h
+
+3HFB6KHFZ0F:
+:K{D
+I2F[F FyD2Fh F5
+
+
+O
+YF0FuP!(F
+
+K*h{D
+
+hB +  
+K {DN
+K)F{Dh!F Y#
+FFF-+O2
+h-CF F:*
+/ 
+/?
+Ch1 h
+40#F
+K {D
+FFDFMF@FWB 
+I " FyDmih F 8
+hh$D K*F I{DyD FpK*FI{DyDF]
+FKjjFpGF"jCՋj
+Fj[Ճ Kj"
+Fc pG pGFxh ՛
+FH jFHj@
+K&
+M I{Dh}DyDP4 ,K
+
+ O3a
+HEPEѣjCsjCbjCjCjC jC@jCAFkChFkh
+B !FhhhF
+!Fhh9FF
+K {D Ff(F
+ $7NO
+0$~D
+
+baUSp#i3+0 /3CA.7:Ca.W:p hhBkp ..<` `7FF*F@F
+C$F3"" A9)٢0 ) *"KD$.*7$-*D
+IyD/2Fa(FBIyD%2F!FF 
+xx ()+
+K|DF(FXFhK8FXFa0F𽐱
+c-"9F0F - +
+FF;S:+,+ќ0
+O3
+*Kj  j[iKi ih
+## #O
+K{ #[A ##Cg
+G
+44
+4###C\
+K EOIyOE
+I  mA
+I OeDI E
+E$mA E
+
+OEu J B
+ OYkE
+
+UEb
+J  EE
+ OE
+ODtJ
+ OkJIKvAmODOd DO[jJE EE!F OE AqdIAG
+OVgGEEE&EEuEEmAEFONB# ###C   FvORA[F[ AOTgIME[B # ### C
+GwOCGC OiJDF ggG ggOVI IJzOVI 7FRJ
+vAJ
+I
+
+NYFJ"|BGb
+#|CZc`#|Ca#~CCa #|Ea#~D,~CaCbP"0:gk:{'{Gk
+K@B
+I
+H{DyDxDm2
+*
+*
+,
+, j$i[iKi ihhKh h
+Sj j i ihhSh h# ### #C### #D   E 8F EEE"EEE EEEE E EE EE EE E#E E
+
+A$mA
+EF E
+O E
+@ I 
+DOhH
+FEOE DtIvA!DORjzJ
+
+B
+&EEFEFE6OEDtAvDIAGOShSHC#
+
+EECEuF[A OYdCSD
+C#
+
+ gggBEuG@
+ gg% O\fGF[gw #|C!OeG
+ScE`(|F`b
+*#
+F8F F&9F(F)F(F!F*F(F!*F9F8F9F F"F)F(F)F F!F F>*F!F(F &)F F!F F>*F!F FO!F0F1F0F"F1F FO !F Fu!F Fq*F!F(FO1)F Fc!F F_*F!F FOc!F0FQ1F0FM1F"F F1&!F F@!F F<>!F*F(F$)F(F0)F(F,<:F)FHF)[-O
+,
+,Kj ih
+ h g
+*
+,
+,Kj ih
+*
+*$ iiNii "K [[` KB`JFaa U``!b
+*ѽ
+*
+KhhhOicii(|HSb#~C[n i"|B^l jIjgWf'~GGae&|FaUd%~Eaa$|DbOQi!~AAb!
+ c(|H
+K@2 I
+H{D?3yDxD2
+*ѽ
+
+F!FF*F!FPF
+2F9F Fx f(QF@F`Px0FXPHFFBF!F8FBF!FPFIF F2F!FP
+F
+( HFYF F
+P(F*F)F0F(1F(FZFQF@FP
+{AF0FJF!F@FrJF!FPFwAF F"F1F8FnQF F"F)Fx
+* h
+iNi|IKh  |Bi2~Hh~Fxi|Nh6~|E~Lj  5|~DKj4r|G7v~J

- F
-
-9)F8FFF
-h*
-!F0F+*FF8F4>F0FB@(F hF F+a *X
-ѩx*xkx
-IyDIyDa FihZ
-FFUOs
-QFF F8FHOs
+u)|C(~Ht.|N,~Lw"|B&~Fz%|E$~DOq'|G!|I!~K) DKD!|A#|IcD#~HScD#|N c
+D#~LSc^D#|Bc D#~FSc\D&#|EcDSg#~D*~CT[D'|AcO
+#~C
+W*0
+  3 ;K@":I;H{DH3yDxDJ

-HFeEHF )FJF{F F6@
-6
-- I F"yDP4%'F48xW
-1F`BF
-DJ#F
-
-
-DP#
-q๱#
-1ع@
-"
-PFOs
-hOs
-
-
-
- ~8`
-#I0FyD90
-x
-hB,+* #
-#h
-I F
-hhhpGh
-hhhpGChpGsFN~D3hsHxDPF0`8T#
-KA"{D(F F
-M}D(h
-FFF-
- HFYF"}@ *  $K"
-5 )F8l!F058lB
-
-
-
-
-I F "yD Fihq 8
- F*FSF
-hhhpGhhpGjFAj
-j
-ѣ#
-M
-I{Dh}DyD (4L,K
-܂(܁(6(Є(1(܉(Ћ()PEXE$jCjCjCjCjCjC 
-jC@jCjCsb8F *EoK8FY W
-#
-K {Dv(F F2
-
-TZp#i3#a F@hh h F@}-EFhFF0 
-0$~D
-7NO
-
- $
-
-MchCsc`!F F0
-*F FOs
-FHOs
-
-F F,Fl F00FFo
-
-
-
+
+O'
+ ss2
+Bt2 tj
+BTT
+ v
+ DvvBQBw
+ www 
+-O}F "88F;x!F.F F#;pC@w$.Ɣ
+)ш[OjOkJ(|HP@Q@P@Q @
+
+P @Q   @P@QFFg"p|@&~FFObA
+ a"~@ `a"|@a"~@a+|@ b T! *gk
+)t(F~.Q"FL8F 2F F:F0F
+8FJ9FHF  ,OzD2"F9FPFbQFXF"FIFPF6NQF8FvRF9F8F9F0FmRF1F0FZF1F0F1F(F_)F F[!F FW"F1F F"F)F(F)F(FI*F!F(F)F F@!F F<*F!F(FO )F F.!F F**F!F F x!F@F#AF@F;"FAF Ft!F F
+ #!F F;*F!F(Fb)F F1#!F F;*F!F FP!F@c#AF@F;AF"F FO1<!F F!F F*F!F(F,)F(F)F(F2F)F0F:F1F0FZF1F0F1FHFRFIFHF FZFIF Fjx FZFIFl Fa0J1F0FzD2@1F F
+F1F1"F1F(
+
+F!F
+BF!FPFJF1F FS (QF8FMx x(FFPF P@Fx <BFAFHF:F!F0F:F!FPFIF F*F!FP
+
+F!F
+zBF!FPF~ (1F FJFQF8Fx x(FPF P@Fx BFAFHFR:F!F0FW:F!FPFHIF F*F!FP
+RF
+O  XF y
+AF `4 {Ox AFF}OZ FV !F0FZ1F8F!F
+5:FAF Fj!F0FE1F
+0
+
+w(FO
+VP
+ 
+
+ 
+  
+
+
+vKtK#fB D3Q3C4gKjH&bJbJ#U3DC]KF
+F
+g  LFUF
+
+FE
+ 0F
+
+&OT[C
+OT[OTZC
+
+c OT^C
+ Fa9OTUC
+Af 0Fv$c OUXC
+Jh{AYBDF O K # # ,
+
+N B
+gD
+G08FIgw(1GFLgw0GOE
+FU
+R  
+CKw#
+
+;DC OWSH
+IB &R e* ORZC
+OQWOGWB
+b OPTB
+b OQ[OQZB
+ b  B
+
+M4###D
+D K OhTC#OPSDC#i 
+AOnQ O\SC#OWTA OiUD$wFPOVQE
+
+OjS`A!C T OkXD$& 0vF+OTZHJ*Oh\p
+OZQL A!,OlU-CK hFC#1B
+ HLpFE
+;H
+sA^ F&[4Cc nC#ORWF OkS(G'UFOWXCH(mSFOX^E"N.[ -
+
+ Oi[C# OYSK
+OfZC#)*JPp
+spJN@ECApp# q
+@CHq<q<IL IO0
+Cst"ZtG!JCOtO"OX8FNutv"ZvE
++Cvv3Cw#[O2Jw[
+w[ w;?
+    T p q O FJAj pT -~ / p} 5kIO0
+F0
+#F F4
+# #F F5
+# # #F F6
+F # O# # #FF
+# # # ##FF
+# # # ##FF
+# # # ##5KA6#
+# # # ##KA#
+# # # ##7KA8
+#
+C
+ #
+>4 
+
+,!b
+"$%B
+0%b $&'OP\B
+OUQB
+bDOVRN
+C
+
+8c C
+ >C
+
+E MgE=D EOEU2aLEfE5DN E E&0
+~LE
+!FE
+
+E D,E 4FFJEFFOU0$BLE#FE UE
+P5DNE
+\EUIEMF.FEUE FIEU
+ E
+8
+MDB
+FH
+C
+
+ FMAO
+D !DLA
+
+@ i OPRC
+B Rc"OQXC
+c   OTQC
+OQ[C
+ F
+c$OQPC
+C
+
+G4FgwL
+NG@gGD
+
+GDG~Lg
+g'DDGmKHg
+  C#
+4
+C TH
+
+RJ
+3DCN#3CDCKF#3QC
+
+EL
+NOV^ON^`OP^E
+OQROQ[G
+g
+  OQ\OQPG
+g OQ^G
+@
+
+g
+
+LMDE
+
+OZPB @ OiRFBb hB"QOQW@ OkYG' OWZI J*OiX
+OZQHA!OhP
+
+B
+
+OhYC#I
+FOXSObYC#I
+x @#
+!0 E ACD#0#"@EML$0C%P>&0DJN'#[O2( =JK#)0CCC*0+03,0
+O\<IG602
+>0[ ?0 Y}
+!F(FuPF)F4RF F1F
+!F(FfPF)F%RF F1F |!F(FWPF)FRF F1F (*m!F(FHPF)FRF F1F *^!F(F9)FPFRF F1FQ!F(F,)F h0N$<XQbN00{4N8Fc "8FF@ NUK{Dc(FT0
+zOj
+
+*2F2FF*YF
+()F0FRFXF4ڪF
+P 2z ЪPFFrZF1F(FwZF1FhQF0F1Fi1FPFZ
+
+F+رKBKBK
+H
+K"
+HOq{DxD
+
+
-O
+O
K"
-H!{DxD
+H!{DxD
K"
-H!{DxD
-FpGK{D`pG
-J
+H!{DxD
+ FpGK{D`pG
K"
-H@{DxD
-KB K" H@{DxD
+HOq{DxD
+KB K" HOq{DxD
+ F>0P
+ F
K"
-HOq{DxD
+H@g{DxD
+z4
+J
+J
+#hJB
K"
-H\!{DxD
+H!{DxD
+ F0
+ F
+f 0
+(L F
+E
+^;`
+F F-) AM^FK@5H*F{DxD
+HOq
+K"xD0{D
+r00
+J+` F0
+$ K
+(FFx K" HOq{DxD
+ 0
+ K
+(FtFx K" HOq{DxD
+ 0
+xi(K
+di K
+P"F0FIF"F@F1FF KBK"HOq{DxD
+1 F$F
+
+ `
+
+ `
+~&K
+iK
+T0F)FF KB3BK"HOq{DxD
+7 Fp
K"
-H@_{DxD
-
-KB
+HOq{DxD
+ 0
+ FF
+ fp  %(Z F3`p3 F
+]L
+  .!
+
+  48<F +`") Ap=F&I. F
+(h1FG
+' A]RF(F(FF KB
K"
-H@
-!{DxD
+H@!{DxD
+i F0
+F'
+& 0F)F"FxFKBKB3BK"H@!{DxD
+LL F
+
K"
-H@S!{DxD
+HOEq{DxD
+\&
K"
-HOq{DxD
-
-FFk˱gk1FjB4B(/F:F kak8c
-BDckk<[B D 
-1[BD1F
-KB
-lKB
-أSB
-=FFO" #:F
-k)F*F
-
-
-}| K" H@{DxD
-lĕ
-bib
-MKB(F
-i%K"HOq{DxD(
-ch
-FFxK"H@!{DxD(
-iC
-KKBM(F 
-BC #iCE> j)`j&i9F j##afFP`j1F`FKB&iC#a KB3B3BK"HO4q{DxD(
-KBMM(F
-*h#hBGK
-xch+i(F"!jFbj/i0 acikajb00BjkckB0K
-EjjDZ~'K"'H@!{DxDH
-1jjk
-Pkc~K"HO?q{DxD
-kkFK"H@1{DxD
-'
-%kb9F2FF K@#1 H*F{DxD
-
-tKB F0
-Och+(K
-;i[#jK
-%j F3&kbAF:F>FxKOXqH2F{DxD(
-
-00
-A{DxD
-L F
-9L F0
-sB;BsBѨkik 
-E
-KB F
-}ch+K
-hiZ#jK
-Qj F_# Fb9F2F@i
-ch+.K
-i
-j+K
-k1F*FFK"H@A{DxD
-¸
-
-tKB F0
-Tb LK"H@)Q{DxD
-1KBL F
-
-zD
- kjk(F
-,J(FX#F
-H
-;BKB3BK"H@a{DxD
-H
-;BKB3BK"HOa{DxD
- 9`{`l{ala
-H
-;BK"H@Oq{DxD
-LH"@aq{DxD
-2H"Oa{DxD
-(H"@jq{DxD
-
-p
+H@!1{DxD
+~&
+Y F
+ F 
+
+F +h!F8F2F
+FFk˱gk1FjB4B(/F:F
+kak8c
+E
+BDckk<[B D 
+j1Fk*FCFO
+1[BD1F
+`k ]c
+KB
+أSB
+@"/@̀
+"
+"SF
+k)F*F
+
+bib
+FFxK"HOq{DxD(
+BC #iCE> j`j
+sB;BsBѨkik 
+
+
+
+bFF
+H
+XF%
+;BKB3BK"H@a{DxD
+
+H
+;BKB3BK"H@a{DxD
+
+
+ 9`{`l{ala
+H
+;BK"H@vq{DxD
+LH"Oa{DxD
+2H"@q{DxD
+(H"@q{DxD
+
K"
-H@q{DxD
+HOa{DxD
K"
-H@q{DxD
-
-` HxDA`hF
-` JzDh;`3@˾h
-
-
+HOa{DxD
+`HxDA`hF
+` J KzDXh[iR+н@h
p
-H xD
-s
-pK(F
+H xD
+
K"
-H!{DxD
-
-ٸ e
-F{D
-HxD
-
- F
-x
-]
- F
-J
--
- F
-
-
-F¿pF FF!F
-c
-H LxD K" HA!{D
-[h
+H!{DxD
+F{D
+F¿pF FF!F
+H LxD K" HA!{D
+[h
+
l2
-d@VH@E2UIVKxDyD{D P,
-BIKxDyD{D`O
-B lH@kIlKxDyD{DB3fx&.gHOrfIgKxDyD{DS,8S<AhB`H@`I`KxDyD{DC`D<D,1FD,9WK{Dh
-"*I*KxDyD{DN3A F)FF
-V5p
-تBؑBبB3B
+d@VH@E2UIVKxDyD{D P,
+BIKxDyD{D`O
+B lH@kIlKxDyD{DB3hz&.gHOrfIgKxDyD{DS,8S<AhB`H@`I`KxDyD{DC`D<D,1FD,9WK{Dh
+V5p
+تBؑBبB3B
; 
ܸ#fи*fи @X.jи0и-@_U
3h6C{j

-`H`"
+`H`"

AEq0
"
@@ -2876,113 +2767,120 @@ BIKxDyD{D`O
8
 1YE{ #
-;:
-q1JzD
+;:
+qP/JzD
ȿ$,($+U
-+,
-Jh01
++,
+Jh01
F
-  B FAF h
-8A0F_z1F O  #F {O O
+  B FAF h
+
+8A0F_z1F O  #F {O O
-!=F
- 7OE
-
-!F? !F; !F7
-ch"
+!gF
+ ;7OE
+
+!Fi !Fe !Fa
+!FF F
+ch"
FKFFF;F
-:/FF
+:/FF
74
50_(
(
-( (а HBHApG pGA
-@6KD FF
-{h[B{`O6 JzDx0F
-B
-   0\>HFQ2F1)
-1
-
-
-h
->8F
-?
-  5 @˄
- @7
-Y@
-J#<#D@:M@
-
-v1F F
-!rp1t!
-s/
-qbFbXFO^pʺ
-$mAvAA(
-18#*   
-Fi&YF F 
-?
-_
-eF  @(
-y
-#B@K@~
-K@B@
-#
-
-v\E
-
-E `@i@
-t\
-04#
-x
-E|l
-
-F@O@
-#F@O@g{@r@
-gF@O@gp
-g
-gg x
-@
-p@y@
-g 
-
- 
- 
- 
- #`@i@
-
-JF8FEEY#T@]@
-
- *F48FB,%,,cArb
-#(gr@{@&g(#t@}@&En^
+( (а HBHApG pGA
+@6KD FF
+{h[B{`O6 JzDx0F
+B
+   0\>HFQ2F1)
+1
+н# FF F]K
+#F #`F F
+O
+EB
+JO K.F+,txF FX F
+
+'z-OFFFW
+@FR
+ )FG
+,#
+a%@$
+DBO3`pGhF@hihB$h޼ChihhihDpG8F h+ihBF(FȄ
+hhBRpC
+#U8r@ U4 U@A@XU<TY@ mK@U(J@U$K@!mH@ U0<X@U,<Y@ #mU  m
+ XZh
+V@UU@5p@ !  @Z@K@J@K@J@K@
+N@p@# -*# H= #
+V@ X
+
+V2+[A@AIA(e[A@AIA(e ǒ[A@AIA(v4B
+FSF0F
+Q@
+ B@< V,V,Z@> V@62XJhx@
+ 'VH _@ @
-* * :PBPApG*XBXApG
-))
-.+/+:+=+?+$%\  B
-hB+++@hIhպ@hKhpG@hIh[O0pG
-+
-
-ih
-G FF@-G FF iF
-xh
-h Fh
-!C4( (#hC#hC#`
-F@0#
-E4GFWF0 Fh
-F FA1FRF1F
-AF:F(F3F
-#jb#B  F7 
- #Aqjb
-gai
-C
-
-
-
-B:R
-BhR# BF@Ͽ3B
-FF(#hXh#h]`( 88
-FF(#hh#h`( 888FhiB
-FF(#hi#ha( 888Fh
+S@Vh,Vx<Vt<Vd,Z@VX<Y@VT<A@Z@VD<Z@K@!S@674Y@Z@E: 5;X@ E8Y@Z@ E
+? 9>X@E   <
+H@=Y@EE,B@Z@CH@A{@E# E@5;T D 9"7 ˄
+
+{@0Y@ 0Z@K@S@@!5"  l#Z@ O@
+C@ #N !K@z@Z` `` C@K@
+Z@Z@
+P@S@"HD O@V@ vP ˉ
+F !r0Fy` R#hB@K@V
+#L@=A@A:*+(Z@;)K@8#L@9A@AT"3-O˰FXF
+UXW 
+
+F0F!F
+?
+@ s 6BHl Up 3 J@W@P@U8p J@6S@K@S@U
+ U Z@<x@Y@ : lS@U Z@U @ X@ > 2XJhC@
+ >?@ 
+DD"#$%"˄
+#O$"#P@%S@"j$"J@ajO@"'!r9F BF8F !4 S@!J@ 2JCD"H@i@9F,
+FY@ !!r)F$P# Q@Z@R4X@!c@W 
+O
+#h@H@Q@Z@*:;<]@+-Y@,QZ@=C@#h@H@Q@Z@L
+SDFWF\\3+
+
+:PBPApG*XBXApG
+)(F!F )FF
+hB+++@hKhpGIh@hԼIh@hO0pG
+%O
+O
+O5 F d0 #` F 8 F "` F( hr
+$
+
+!(hC+ 
+0
+
+  .E0D50
+
+#|C@pD#cckD`c$
+!j0
+#i4 #i#ai # #!i
+3D",
+3 3dA
+FH "
+8PFN$0(b,#|C"|Ga0 !|Fa4 !|Eb"|D|LDSi#|Ch`(|H l |@Oq>IB
+@C)|C@
+L
+P
+F0 3,G
+T
+X
+
+" 
+BA ="
+A="
+FF(#hXh#h]`( 8
+FF(#hhk#h`( 88 FFhiB
+FjF(#hiT#ha( 88
+Ch`pGChh@hpG8 FFpChBF#F`he`( 8
+:F
-( ( (а XBXApG pGa+A8(
+( ( (а XBXApG pGa+A8(
ڰG
Z6:h
8X'O (F OI  
@@ -2991,15 +2889,15 @@ h `:`9F"F3F""?GE
6:h
 JZEZF
 BEBF
-3FE !FXF
-
-
-Fx1Bxp*(xxp:
+3FE !FXF
+
+
+Fx1Bxp*(xxp:
JO O;K?
-&PF1O3S`d
-(F!FjF
-
+&PF1O3S`d
+
+
D ;
O
   GYh
@@ -3013,62 +2911,75 @@ JO O;K?


: ?
-E ;
+E ;
O
-DEмB
+DEмB
*Fch
-
-FHhFhR<R `R,FhS` i` HiGp
-R#F
-O 
+
+FHhFhR<R `R,FhS` i` HiGp
+R#F
+O 
T!8
B
T!
-   Bت
+   Bت
gE5  T%
-F
+F
Y%:F5vPFshB
Y'
&v
OD
- *F6MFW
-@BF
+ *F6MFW
+@BF
FFF!F9FBF#FD1F
FFF!F9FBF#F1F
-FFF!F9FBF#F;1F
-9@9h::j ;Ð;<<==>$>M?f?~@ӆ@A|ABUB2 2 2$2$3$3$4$4$5$.5$;6$I6$W7$e7$n8${8$9$R 2(j2(" 3(}3(^ 4(4(
-90%90::0N:0b;0s;0<0<0=0ˁ=0>0>0?0?0&@02@0GA0WA0nB0{B0C0C0D0ӂD0E0E0F0-F0JG0cG0qH0H0I0I0J0σJ0K0K0 L0L0)M0?M0MN0cN0uO0O0P0P0Q0΄Q0R0R0S0'S0?T0XT0qU0U0V0V0W0҅W0X0X0Y0Y0,Z0;Z0[[0j[0\0\0]0ӆ]0^0
-3@3@+4@I4@Y5@k5@x6@6@7@7@8@ș8@9@ؙ9@:@ :@;@-;@d
-W@ X@FX@u Y@Y@ Z@ƠZ@ [@[@!\@A\@N!]@e]@!^@^@!_@ѡ_@!`@`@E"a@}a@"b@b@"c@ˢc@"d@d@)#e@@e@X#f@f@#g@Σg@#h@h@H$i@vi@$j@j@?&k@bk@x&l@l@")m@Jm@x)n@ũn@)o@o@/*p@Lp@
-B
-
-BJ% Bå B' B B& B B'B'B^B'B;'B(!B'&B(+B+B(,BD,B#(-B-Bj(.B.B+2D:2DF3DT3Dg4Dx4D5D5D6D6D7Dч7D8D8D
-HP2IP2IPH2JPXJPx2KPKP2LPܲLP2MP MP&3NPBNPT3OPkOPz3PPPP3QP:2X2hj2h} 3h
-3h4h4h2l42l3l
-2t2tE 3t~ 2x2x 3x3x 4xÉ4x 5x5x
-6x/6x?
-7x`7xs
-8x8x
-9x9x
-:xԊ:x
-;x;x <x<x5 =xJ=x
->xR>x2|
-j
-{*
- p'd'_0 lb^xGf
-kG|
-ෑJ .<Eɋyǐ:%;$%`7
-
-#ae
-NQ
-YG=6D^:հ5mp?LPiBl)+18{k Ψ`%cfc}Ҵ#ZoAsu0RhEf;S<iliQ҄(f mrae!2Hz8u=Jo=?Wk?Jnr{[t꾜zm@I*upNtu>MfO<lwGQcT;0*u)L|m8U[#(6A&>ʜz+`Edo\ MKZ&irb>^SOsvt:MևllDr>sN=ZuY,GA馗&js[ee[0bY26RJ!^ kZ̰ҋ_;>qf(?' Z#a -D\NxzWenqDCPgHZF HzEi׊ 돲mvX St-SnQ<}ukjR0EQ6 F?>7Ϙ^ZSw `@\⥭*k~#[ (-@L5
-&by M]1~ӡAa]Ta|IDt/z/]>)M7n(l X2o6W]v1Cyב1b<Ґ,V7{@X"y:1
-}ztFr=ܽh q2i;xWnnE7J QOg<#hdjE2!Y|PVi{X;MFmE4͉nJ{@'+fY{935/.hS\Rw't#>.. %%99=ng^fc(Nt]wv^b<W+6.9>um:15y5& kZ$m1K FJ+C7Ys<vx˦ y_( [QBoP=!^%]7G0pN CG*b]3bV$fCh;i|կ>!1 j^|EՌW_/OR|X_Q!/[j4mXKs]ė*lFBWP5<mlΰɢwk 70,^_Z0Nbe+V>MϺb_r(W=W}q1옐T G\r$d |s;UX0/bfU!%dqKvYŪgÆ%NK?D.j]SP3٨-}*?
-Ҽ3bSwCf'C_U*Lzy Xzte d0\UVE;><jRr[9 #JL] #j==}?#GqlWC3{bF}i8'o8ŮfsL!:6VudǫZ&BRCm 1$$o!ۃi;kT/\wa ;>OZ)1?6ⷜҼ/=rhR%LJ`~BdrF[Yq\cX֜
-+0C:ͳ4yJQ"; tgN)܀b4h!*H 
+FFF!F9FBF#F;1F
+'8!.m,M 8STs
+e
+jv.,r迢KfpK£Ql$օ5pjl7LwH'4 9JNOʜ[o.htocxxȄnjlPxq"(ט/Be#D7q/;Mۉ۵8H[V9YO?m^BؾopE[N1$} Uo{t]r;ހ5%ܛ&itJi%O8GՌƝew̡ $u+Yo,-ntJAܩ\SڈvfRQ>2-m1?!'Y= %
+GoQcpn
+g))/F
+'&&\8!.*Zm,M߳ 8ScTs
+ew<
+jvG.;5,rdL迢0BKfpK0TQlReU$* qW5ѻ2pjҸSAQl7LwH'Hᵼ4cZų 9ˊAJNscwOʜ[o.h]t`/CocxrxȄ9dnj(c#齂lPyƲ+SrxqƜa&>'!Ǹ}xnO}orgȢ}c
+ ?G5 q}#w($@{2
+<L gCB>˾L*~e)Y:o_XGJDl
+/ 6$=&i''NͲuu t,,X.4-6nnZZ[RRM;;vaַγ}{))R>q//^SShѹ
+
+II
+ l$$H\\]ŸnӽשּׁCbbĨ917Ӌyy2CȋY77nmmڌdձNN੩IllVV%ϯeeʎzz鮮Gպoxxo%%Jr..\$8WǴsQƗ#|ݡtt!>KKܽa ppB>>|ĵqffHHaa_55jWWйiX':'8볘+3"iip٩3-"< I·UUx((PzߥY  ڿe1BBhhAA)w--Z˰{TTֻm:,ccƥ||ww{{ kkֽooޱőT00`PggΩ++V}׵bMvvʏEɉ@}}YYGG AԳg_Eꜜ#Srr[u=&&Lj66lZ??~ÃO44h\Q4qqثs11bS*? ǕR##FeÝ^0(7
+/ $6=&''Niuu ,,Xt4.6-nnܲZZ[RR;;vMַa}))R{>//^qSSѹh
+
+II
+$$Hl\\Ÿ]ӽnCbbĦ917yy2ȋC77nYmmڷձdNNҩIllشVV%eeʯzz􎮮Goxx%%Jo..\r8$WsƗQ#ݡ|tt>!KKݽa܋ pp>>|Bqff̪HHaa£55j_WWiІX:''8+"3iiһ٩p3-<" ·IUU((PxߥzY e1BBhhиAAÙ)--Zw{TTm,:cƥc||ww{{ kֽkoޱoőT0`P0gΩg+V}+׵b׫MvvʏEʂɉ@}}YYGG AԳgԢ_Eꯜ#Srr[u·=&Lj&6lZ6?~A?̃O4h\4Q4qqثs1bS1*? ǕR#Fe#Ý^0(7
+/ $6=&'Ni'Ͳuu  ,Xt,4.6-nܲnZZ[RR;vM;ַaֳ}γ)R{)>/^q/SSѹh
+
+II
+$Hl$\\Ÿ]ӽnӬCbĦb917yy2ȋC7nY7mڷmձdNNIlشlVV%eʯezzGoպxx%Jo%.\r.8$WsǴƗQ#ݡ|tt>!KKaܽ pp>|B>qĵf̪fHHa£a5j_5WWiйX:''8+"3iһi٩pَ3-<" ·IUU(Px(ߥzߌY  eڿ1BBhиhAA)-Zw-{˰TTmֻ,:ƥcc||ww{{ ֽkkޱooT`P00ΩggV}++bM櫫vvE@}}YYGG A쭭g_E꯯#Srr[u·=Lj&&lZ66~A??Oh\44Q4qqsbS11*? RFe##^0(7
+/ $6=&Ni''Ͳuu Xt,,4.6-ܲnnZZ[RRvM;;a}γR{))>^q//SSh
+
+II
+Hl$$\\]½nCשּׁĦbb917yy2CnY77ڷmmd՜NNI੩شllVV%ʯeezzG鮮oպxxJo%%\r..8$WsǴQ#|tt>!KKaܽ pp|B>>qĵ̪ffHH£aaj_55WWiйX:''8+"3һiip3-<" IΪUUPx((zY  eڿ1BBиhhAA)Zw--{˰TTmֻ,:PQSeA~ä^':k;EXKU0 mvv̈%LO*ŀD5&bIZg%E]u/LFk_zmYR-!tX)iIDɎjuxyk>Xq'Of ɴ:}Jc1`3QESbwdk+XhHpElޔ{R#sKrW*Uf(µ/{ņ7(0#j\+ϊyiNeվb4ъĝS.4U2u9 `@q^Qn!>=ݖ>FMT]qoP`$C@wgB谈8[yG
+|B|
+!\hT[:.6$g
+ WҖO aiKwZ
+*C"< Nj򹨶-ȩWLuݙ`&r\;fD4~[v)C#hc1cB@" Ƅ}$J=2m)K/0R wl+pH"dGČ?,}V3"NI8ʌ6 Ԙρ(z&ڤ?:, xP_jbF~Tؐ^9.Â]|i-o%;ȧ}nc{; x&Yn쨚Oen~ϼ!ٛ6oJ |)11#?*0f57NtʂАا3JAP/MvMCTMўjL,QeF^]5st.A ZgRے3VGmaךz 7Y<'5a<GzYҜ?sUy7sS[_o=߆Dx>h,4$8_@r %⼋I<(A q9޳ ؐVda{p2t\lHBWQP~SeAä:^';kEXK U0mvv%LO*&D5bIZ%gE]u/LFk_zmYR-X!tI)iDujxyk>X'qOf }:cJ1`3QbESwdk+pXhHElR{#srKWf*U(/µ{ӥ70(#j\+ϧyNieվb4Ċ4S.U2ኤu 9@`^qQn>!=ݮ>MF摵Tq]o`P$֗齉C@gwٰB8[yȡG
+||B
+dh!\T[$:.6 g
+WҖOa ZiKw
+*<C" Nj-ȩWLuݙ`&\rD;f[4~v)C#hc1Bc@" ƅ}$J=2m)K/0 Rw+lpHG"dČ?V,}"3NI8ʘ6 Ԧρ(z&?,:P xj_TbF~.^9ß]i|o-ϳ%;}nc{; x&nYOen~!ϼٛJ6o )|1*1#?05ft7NʂА3اJAP/vMCMTMLj,FQe^]5st.A ZgR3VmG֚a7z Y<'5az<GYU?sys7S_[o=xDʁ>h8,4$_@r %(I<A 9q޳ ؜dV{ap2Ht\lBWQPeA~S^':k;EXK0 Umvv̈L%O*D5&bZI%gE]u/LFk_眒zmYRڃ-!tXiI)ɎDujyx>Xkq'Oᾶ f:}Jc13Q`SbEwdk+hHpXElޔ{Rs#KrWUf*(µ/{ņ7ӥ(0#j\ϊ+yiNe;b4ĊS.4U2u 9`@q^nQ!>ݖ=>ݮMFT]qoP`$֗C@̞gwB谽[8y
+|GB|
+d\h!T[.6$:g
+ WґO aKwZi
+*"<C  Nj򭨶-WuLݙ`&r\;fD~[4)Cv#hc1ʅcB"@Ƅ $J}=2)m/K0R w+lpHdG"?,}Vؐ3"NI8ʌ Ԙ6z(&?:,xP _jF~Tb¸ؐ9.^Â]i|-o%ϳ;}cn;{x& YnOne~ϼ!6oJ |)ֲ1#?*10f5Nt7ʂАا3JAP/MvCMMTߵўjL,QeF^5]tsA .gZےRV3Gmaך 7zY<'a5Gz<ҜYsU?y7sS_[o=Dxʁh>4$8,@_r% I<( A9q ؜Vd{a2p\lHtWBQPA~Seä':^;kEXK0 Uvm̈v%LO*5&DbIZ%gE]/uLFk_mzRY-tX!I)iɎDujxyXk>'qᾶO f}:cJ1Q`3SbEdwk+HpXhEޔl{Rs#KrWUf*(/ņ{7ӥ(0#j\ϊ+yiNeվ4bĊ.4SU2u 9`@q^nQ!>ݖ=>ݮMFTq]oP`$֗@Cgw谽B8[y|G
+B|
+d\h![T6$:.
+ gWҖOa wZiK
+*"<C  Ƕ-ȩWuL`&r\fD;[4~Cv)#hc1cB@"Ƅ J}$=2)mK/0 Rw+lpHG"dČ?}V,3"IN8ʌԘ6 ρz(޷&?:,xP _j~TbFؐ9.^Â]i|o-%ϳ;}nc;{& xYnOen~!ٛoJ6 )|1?*1#05fNt7ʐЧ3JAP/MvCMTMўjL,eFQ^]5st .AgZےR3VmGךa7z Y<'a5Gz<ҜYU?sys7S_[=oDxۯʁh>$8,4_@r %<(I A9q ޳؜Vd{a2plHt\BWaes_nohw_encrypt
+XE,?k:AOgst"57unGq)ʼnobV>Ky xZݨ31Y'_`QJ -zɜ;M*<Sa+~w&icU! }
-!/wP“[klMJȮTQwą6h3ێ^(ZD"2kr.:+^$l6'W `'_
+!/wP“[klMJȮTQwą6h3ێ^(ZD"2kr.:+^$l6'W `'_


@@ -3084,10 +2995,24 @@ NQ

 
-
+
6J&,o])(|1
`~zC|_cM7-X Hzj)s*H=
- A2VPD׿غ' 9C#U k2JV"42\!7c#L"CuZGdDՁ
+ A2VPD׿غ' 9C#U k2JV"42\!7c#L"CuZGdDՁ
+VWS\J%!݈҅]%q
+sz1F:Ȼ/[qn5mVJ$
+B>?i _к;;sr gPD
+}8w
+b;a)cA
+e 
+S9
+A$MD
+vb7GeO %en6ӂ!‚D߂5l]V/~/
+QQv1 ԇ_
+ypCkㅝl-"l\u@VegoC
+!+"D
++xYQ@Z8Gaё*#Ք
+FE{3`SNB. h'=6xJ{C^t9ۃoâ:J3L;`oJu}Yd3rsa_generate_key_impl

!
1
@@ -3121,8 +3046,58 @@ u
-    # ) - ? G Q W ] e o {   % / 1 A [ _ a m s w      ! + - = ? O U i y !'/5;KWY]kqu}  %)1CGMOSY[gk!%+9=?Qisy{ '-9EGY_cio #)+17AGS_qsy} '-7CEIOW]gim{!/3;EMYkoqu %)+7=ACI_egk} %39=EOUimou #'3A]cw{57;CIMUgqw}13EIQ[y!#-/5?MQik{}#%/17;AGOUYeks '+-3=EKOUs !#59?AKS]ciqu{} %+/=IMOmq 9IKQgu{   ' ) - 3 G M Q _ c e i w } !!5!A!I!O!Y![!_!s!}!!!!!!!!!!!!!!!!!" """!"%"+"1"9"K"O"c"g"s"u"""""""""""""""# # #'#)#/#3#5#E#Q#S#Y#c#k################$ $$$)$=$A$C$M$_$g$k$y$}$$$$$$$$$$$$$$$$$$%%%%'%1%=%C%K%O%s%%%%%%%%%%%%%%%%& &&&'&)&5&;&?&K&S&Y&e&i&o&{&&&&&&&&&&&&&&&''5'7'M'S'U'_'k'm's'w''''''''''''''(( ((((!(1(=(?(I(Q([(](a(g(u((((((((((((()))!)#)?)G)])e)i)o)u))))))))))))))))***%*/*O*U*_*e*k*m*s***************+'+1+3+=+?+K+O+U+i+m+o+{++++++++++++++ ,,,#,/,5,9,A,W,Y,i,w,,,,,,,,,,,,,,,,---;-C-I-M-a-e-q-----------... ...%.-.3.7.9.?.W.[.o.y................/ / //'/)/A/E/K/M/Q/W/o/u/}///////////////0 0#0)070;0U0Y0[0g0q0y0}000000000000000001 11!1'1-191C1E1K1]1a1g1m1s11111111111111 2222)252Y2]2c2k2o2u2w2{22222222222222223%3+3/353A3G3[3_3g3k3s3y33333333333334444474E4U4W4c4i4m44444444444444 555-535;5A5Q5e5o5q5w5{5}555555555555555666#6165676;6M6O6S6Y6a6k6m6666666666667777?7E7I7O7]7a7u7777777777778 8!83858A8G8K8S8W8_8e8o8q8}8888888888888899#9%9)9/9=9A9M9[9k9y9}999999999999999999::::':+:1:K:Q:[:c:g:m:y::::::::::::;;;!;#;-;9;E;S;Y;_;q;{;;;;;;;;;;;;;;;;;;< <<<<)<5<C<O<S<[<e<k<q<<<<<<<<<<<<<= ====!=-=3=7=?=C=o=s=u=y={=============> >>>>#>)>/>3>A>W>c>e>w>>>>>>>>>>>>>>>> ? ?7?;?=?A?Y?_?e?g?y?}????????????@!@%@+@1@?@C@E@]@a@g@m@@@@@@@@@@@@@ A AAA!A3A5A;A?AYAeAkAwA{AAAAAAAAAAABBBB#B)B/BCBSBUB[BaBsB}BBBBBBBBBBBBBBCCC%C'C3C7C9COCWCiCCCCCCCCCCCCCCCCC D DD#D)D;D?DEDKDQDSDYDeDoDDDDDDDDDDDDDDEEE+E1EAEIESEUEaEwE}EEEEEEEE
-FE{3`SNB. h'=6xJ{C^t9ۃoâ:J3L;`oJu}Yd3md5_sha1_init
+    # ) - ? G Q W ] e o {   % / 1 A [ _ a m s w      ! + - = ? O U i y !'/5;KWY]kqu}  %)1CGMOSY[gk!%+9=?Qisy{ '-9EGY_cio #)+17AGS_qsy} '-7CEIOW]gim{!/3;EMYkoqu %)+7=ACI_egk} %39=EOUimou #'3A]cw{57;CIMUgqw}13EIQ[y!#-/5?MQik{}#%/17;AGOUYeks '+-3=EKOUs !#59?AKS]ciqu{} %+/=IMOmq 9IKQgu{   ' ) - 3 G M Q _ c e i w } !!5!A!I!O!Y![!_!s!}!!!!!!!!!!!!!!!!!" """!"%"+"1"9"K"O"c"g"s"u"""""""""""""""# # #'#)#/#3#5#E#Q#S#Y#c#k################$ $$$)$=$A$C$M$_$g$k$y$}$$$$$$$$$$$$$$$$$$%%%%'%1%=%C%K%O%s%%%%%%%%%%%%%%%%& &&&'&)&5&;&?&K&S&Y&e&i&o&{&&&&&&&&&&&&&&&''5'7'M'S'U'_'k'm's'w''''''''''''''(( ((((!(1(=(?(I(Q([(](a(g(u((((((((((((()))!)#)?)G)])e)i)o)u))))))))))))))))***%*/*O*U*_*e*k*m*s***************+'+1+3+=+?+K+O+U+i+m+o+{++++++++++++++ ,,,#,/,5,9,A,W,Y,i,w,,,,,,,,,,,,,,,,---;-C-I-M-a-e-q-----------... ...%.-.3.7.9.?.W.[.o.y................/ / //'/)/A/E/K/M/Q/W/o/u/}///////////////0 0#0)070;0U0Y0[0g0q0y0}000000000000000001 11!1'1-191C1E1K1]1a1g1m1s11111111111111 2222)252Y2]2c2k2o2u2w2{22222222222222223%3+3/353A3G3[3_3g3k3s3y33333333333334444474E4U4W4c4i4m44444444444444 555-535;5A5Q5e5o5q5w5{5}555555555555555666#6165676;6M6O6S6Y6a6k6m6666666666667777?7E7I7O7]7a7u7777777777778 8!83858A8G8K8S8W8_8e8o8q8}8888888888888899#9%9)9/9=9A9M9[9k9y9}999999999999999999::::':+:1:K:Q:[:c:g:m:y::::::::::::;;;!;#;-;9;E;S;Y;_;q;{;;;;;;;;;;;;;;;;;;< <<<<)<5<C<O<S<[<e<k<q<<<<<<<<<<<<<= ====!=-=3=7=?=C=o=s=u=y={=============> >>>>#>)>/>3>A>W>c>e>w>>>>>>>>>>>>>>>> ? ?7?;?=?A?Y?_?e?g?y?}????????????@!@%@+@1@?@C@E@]@a@g@m@@@@@@@@@@@@@ A AAA!A3A5A;A?AYAeAkAwA{AAAAAAAAAAABBBB#B)B/BCBSBUB[BaBsB}BBBBBBBBBBBBBBCCC%C'C3C7C9COCWCiCCCCCCCCCCCCCCCCC D DD#D)D;D?DEDKDQDSDYDeDoDDDDDDDDDDDDDDEEE+E1EAEIESEUEaEwE}EEEEEEEE
+j
+ p'd'_0 lb^xGf
+kG|
+ෑJ .<Eɋyǐ:%\cX֜
+#`e
+NQ
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+IJ 22$ 363
+9X9::l ;ې;<<==*><>e?~?@Ն@AABmB2 2 2$2$3$3$4$4$)5$F5$S6$a6$o7$}7$8$8$9$T 2(l2($ 3(3(` 4(4(
+0?,"?,L0@,Б@,]0A,pA,B,B,"C,C,/D,/D,
+90%90::0N:0b;0s;0<0<0=0ˁ=0>0>0?0?0&@02@0GA0WA0nB0{B0C0C0D0ӂD0E0E0F0-F0JG0\G0jH0{H0I0I0J0ȃJ0K0K0L0L0M01M0?N0UN0gO0yO0P0P0Q0ЄQ0R0R0S0)S0AT0ZT0sU0U0V0V0W0ԅW0X0X0Y0Y0.Z0=Z0][0l[0\0\0]0Ն]0^0^0_0"_0`0e 24y24 3434 4444 54
+B
+B& BT B) Bj B( B B(Bq)BB9)B(B)!BT)&B*+B>+Bx*,B,B)-B]-B#*.BI.B-2D<2DH3DV3Di4Dz4D5D5D6D6D7DӇ7D8D8D9D9D#:D2Hϒ2H3H3H#2L32LF3Lf3L
+2t2tG 3t 2x2x 3x3x 4xʼn4x 5x5x
+6x16xA
+7xb7xu
+8x8x
+9x9x
+:x֊:x
+;x;x <x <x7 =xL=x
+>xT>x2|
+YG=6D^:հ5mp?LPiBl)+18{k Ψ`%cfc}Ҵ#ZoAsu0RhEf;S<iliQ҄(f mrae!2Hz8u=Jo=?Wk?Jnr{[t꾜zm@I*upNtu>MfO<lwGQcT;0*u)L|m8U[#(6A&>ʜz+`Edo\ MKZ&irb>^SOsvt:MևllDr>sN=ZuY,GA馗&js[ee[0bY26RJ!^ kZ̰ҋ_;>qf(?' Z#a -D\NxzWenqDCPgHZF HzEi׊ 돲mvX St-SnQ<}ukjR0EQ6 F?>7Ϙ^ZSw `@\⥭*k~#[ (-@L5
+&by M]1~ӡAa]Ta|IDt/z/]>)M7n(l X2o6W]v1Cyב1b<Ґ,V7{@X"y:1
+}ztFr=ܽh q2i;xWnnE7J QOg<#hdjE2!Y|PVi{X;MFmE4͉nJ{@'+fY{935/.hS\Rw't#>.. %%99=ng^fc(Nt]wv^b<W+6.9>um:15y5& kZ$m1K FJ+C7Ys<vx˦ y_( [QBoP=!^%]7G0pN CG*b]3bV$fCh;i|կ>!1 j^|EՌW_/OR|X_Q!/[j4mXKs]ė*lFBWP5<mlΰɢwk 70,^_Z0Nbe+V>MϺb_r(W=W}q1옐T G\r$d |s;UX0/bfU!%dqKvYŪgÆ%NK?D.j]SP3٨-}*?
+Ҽ3bSwCf'C_U*Lzy Xzte d0\UVE;><jRr[9 #JL] #j==}?#GqlWC3{bF}i8'o8ŮfsL!:6VudǫZ&BRCm 1$$o!ۃi;kT/\wa ;>OZ)1?6ⷜҼ/=rhR%LJ`~BdrF[Yq\cX֜
++0C:ͳ4yJQ"; tgN)܀b4h!*H 



@@ -3172,7 +3147,8 @@ g+ g+ U
*H  `He`He(
******b*c**
*H *H>+$+$+$+$+$+$+$+$+$ +$
-+$ +$ +$ +$*H  +H?
++$ +$ +$ +$*H  +H?
+
 SiJJ)
A @ @ 4!R
"A  !@h@2l
@@ -3191,36 +3167,67 @@ g+ g+ U


-o/Dyeڜ
-
-
-
-
-
-
-
-
-
-
-
-
+o/Dyeڜ
+*H=DB
+California10U Mountain View10U
+ Google, Inc.10U Android0 160104124053Z 351230124053Z0v1 0 UUS10U
+California10U
+ Google, Inc.10U Android1)0'U Android Software Attestation Key00  *H 
+California10U Mountain View10U
+ Google, Inc.10U Android0 160104123108Z 351230123108Z0c1 0 UUS10U
+California10U Mountain View10U
+ Google, Inc.10U Android00  *H 
+*H=DB
+*H=01 0 UUS10U
+California10U Mountain View10U
+ Google, Inc.10U Android1301U *Android Keystore Software Attestation Root0 160111004609Z 260108004609Z01 0 UUS10U
+California10U
+ Google, Inc.10U Android1;09U 2Android Keystore Software Attestation Intermediate0Y0*H=*H=B
+*H=H
+*H=01 0 UUS10U
+California10U Mountain View10U
+ Google, Inc.10U Android1301U *Android Keystore Software Attestation Root0 160111004350Z 360106004350Z01 0 UUS10U
+California10U Mountain View10U
+ Google, Inc.10U Android1301U *Android Keystore Software Attestation Root0Y0*H=*H=B
+*H=G
+
+
+
+
+
-
-
-
- haead_ssl3_tag_len
+
+
+
+
+
+ ='"
+ %
+ >
+ )
+ />
+ =/>
+ =
+
+
+
+
+
+
+
+ haead_tls_tag_len
-
-
-
+
+
+
*H 
-*H  external/openssl/src/crypto/pkcs8/pkcs8_x509.c
+*H  *H  *H  external/openssl/src/crypto/pkcs8/pkcs8_x509.c
@@ -3249,13 +3256,13 @@ o/Dyeڜ
%*s
-
+
-
+
%*s
%*s
@@ -3264,3728 +3271,1554 @@ o/Dyeڜ
-
-
-
-%*sZone: %s, User:
-
+
+
+
+%*sZone: %s, User:
+TA : 938406c
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-*H=DB
+#
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
California10U Mountain View10U
Google, Inc.10U Android0 160104124053Z 351230124053Z0v1 0 UUS10U
California10U
@@ -7005,293 +4838,182 @@ California10U Mountain View10U
Google, Inc.10U Android1301U *Android Keystore Software Attestation Root0 160111004350Z 360106004350Z01 0 UUS10U
California10U Mountain View10U
Google, Inc.10U Android1301U *Android Keystore Software Attestation Root0Y0*H=*H=B
-*H=G
-
-
-
-d
-h
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+*H=G
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]
+]
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+m
+
+
+p
+p
+
+z
+z
+
+
+
+
+
+
+
+
+
+
+
+
+
+<ATTESTATION_ID>
+ <SERIAL>123456789</SERIAL>
+ <BRAND>amlogic</BRAND>
+ <DEVICE>amlogic</DEVICE>
+ <PRODUCT>amlogic</PRODUCT>
+ <MANUFACTURER>amlogic</MANUFACTURER>
+ <MODEL>franklin</MODEL>
+</ATTESTATION_ID>OCB3 (OpenSSL)
A 
- *D
-
-
-
-
-
-
-
-
-
-
-
-
-
+*D
+
+
+
+
+
+
+
+
+
diff --git a/AmlogicKeymaster.cpp b/AmlogicKeymaster.cpp
new file mode 100755
index 0000000..e5a8132
--- a/dev/null
+++ b/AmlogicKeymaster.cpp
@@ -0,0 +1,352 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#define LOG_TAG "AmlogicKeymaster"
+
+#include <log/log.h>
+#include <keymaster/android_keymaster_messages.h>
+#include <keymaster/keymaster_configuration.h>
+#include <amlogic_keymaster/AmlogicKeymaster.h>
+#include <amlogic_keymaster/ipc/amlogic_keymaster_ipc.h>
+
+#if AMLOGIC_MODIFY
+#include <amlogic_keymaster/amlogic_keymaster_messages.h>
+
+#include <android-base/properties.h>
+#include <sys/system_properties.h>
+#endif
+
+namespace keymaster {
+
+int AmlogicKeymaster::Initialize() {
+ int err;
+
+#if AMLOGIC_MODIFY
+ KM_context.fd = 0;
+ KM_session.ctx = NULL;
+ KM_session.session_id = 0;
+
+ err = aml_keymaster_connect(&KM_context, &KM_session);
+#else
+ err = trusty_keymaster_connect();
+#endif
+ if (err) {
+ ALOGE("Failed to connect to amlogic keymaster %d", err);
+ return err;
+ }
+#if AMLOGIC_MODIFY
+ // Set boot parameters before configure
+ SetBootParamsRequest setBootParamReq;
+ SetBootParamsResponse setBootParamRsp;
+ SetBootParams(setBootParamReq, &setBootParamRsp);
+ if (setBootParamRsp.error != KM_ERROR_OK) {
+ ALOGE("Failed to set boot params to keymaster %d", setBootParamRsp.error);
+ //return -1;
+ }
+#endif
+ ConfigureRequest req;
+ req.os_version = GetOsVersion();
+ req.os_patchlevel = GetOsPatchlevel();
+
+ ConfigureResponse rsp;
+ Configure(req, &rsp);
+
+ if (rsp.error != KM_ERROR_OK) {
+ ALOGE("Failed to configure keymaster %d", rsp.error);
+ return -1;
+ }
+
+ return 0;
+}
+
+AmlogicKeymaster::AmlogicKeymaster() {}
+
+AmlogicKeymaster::~AmlogicKeymaster() {
+#if AMLOGIC_MODIFY
+ if (KM_session.ctx != NULL)
+ aml_keymaster_disconnect(&KM_context, &KM_session);
+#else
+ trusty_keymaster_disconnect();
+#endif
+}
+#if AMLOGIC_MODIFY
+/* Move this method into class */
+void AmlogicKeymaster::ForwardCommand(enum keymaster_command command, const Serializable& req,
+ KeymasterResponse* rsp) {
+ keymaster_error_t err;
+ err = aml_keymaster_send(&KM_session, command, req, rsp);
+ if (err != KM_ERROR_OK) {
+ ALOGE("Failed to send cmd %d err: %d", command, err);
+ rsp->error = err;
+ }
+}
+#else
+static void ForwardCommand(enum keymaster_command command, const Serializable& req,
+ KeymasterResponse* rsp) {
+ keymaster_error_t err;
+ err = trusty_keymaster_send(command, req, rsp);
+ if (err != KM_ERROR_OK) {
+ ALOGE("Failed to send cmd %d err: %d", command, err);
+ rsp->error = err;
+ }
+}
+#endif
+
+void AmlogicKeymaster::GetVersion(const GetVersionRequest& request, GetVersionResponse* response) {
+ ForwardCommand(KM_GET_VERSION, request, response);
+}
+
+void AmlogicKeymaster::SupportedAlgorithms(const SupportedAlgorithmsRequest& request,
+ SupportedAlgorithmsResponse* response) {
+ ForwardCommand(KM_GET_SUPPORTED_ALGORITHMS, request, response);
+}
+
+void AmlogicKeymaster::SupportedBlockModes(const SupportedBlockModesRequest& request,
+ SupportedBlockModesResponse* response) {
+ ForwardCommand(KM_GET_SUPPORTED_BLOCK_MODES, request, response);
+}
+
+void AmlogicKeymaster::SupportedPaddingModes(const SupportedPaddingModesRequest& request,
+ SupportedPaddingModesResponse* response) {
+ ForwardCommand(KM_GET_SUPPORTED_PADDING_MODES, request, response);
+}
+
+void AmlogicKeymaster::SupportedDigests(const SupportedDigestsRequest& request,
+ SupportedDigestsResponse* response) {
+ ForwardCommand(KM_GET_SUPPORTED_DIGESTS, request, response);
+}
+
+void AmlogicKeymaster::SupportedImportFormats(const SupportedImportFormatsRequest& request,
+ SupportedImportFormatsResponse* response) {
+ ForwardCommand(KM_GET_SUPPORTED_IMPORT_FORMATS, request, response);
+}
+
+void AmlogicKeymaster::SupportedExportFormats(const SupportedExportFormatsRequest& request,
+ SupportedExportFormatsResponse* response) {
+ ForwardCommand(KM_GET_SUPPORTED_EXPORT_FORMATS, request, response);
+}
+
+void AmlogicKeymaster::AddRngEntropy(const AddEntropyRequest& request,
+ AddEntropyResponse* response) {
+ ForwardCommand(KM_ADD_RNG_ENTROPY, request, response);
+}
+
+void AmlogicKeymaster::Configure(const ConfigureRequest& request, ConfigureResponse* response) {
+ ForwardCommand(KM_CONFIGURE, request, response);
+}
+
+void AmlogicKeymaster::GenerateKey(const GenerateKeyRequest& request,
+ GenerateKeyResponse* response) {
+ GenerateKeyRequest datedRequest(request.message_version);
+ datedRequest.key_description = request.key_description;
+
+ if (!request.key_description.Contains(TAG_CREATION_DATETIME)) {
+ datedRequest.key_description.push_back(TAG_CREATION_DATETIME, java_time(time(NULL)));
+ }
+
+ ForwardCommand(KM_GENERATE_KEY, datedRequest, response);
+}
+
+void AmlogicKeymaster::GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
+ GetKeyCharacteristicsResponse* response) {
+ ForwardCommand(KM_GET_KEY_CHARACTERISTICS, request, response);
+}
+
+void AmlogicKeymaster::ImportKey(const ImportKeyRequest& request, ImportKeyResponse* response) {
+ ForwardCommand(KM_IMPORT_KEY, request, response);
+}
+
+void AmlogicKeymaster::ImportWrappedKey(const ImportWrappedKeyRequest& request,
+ ImportWrappedKeyResponse* response) {
+ ForwardCommand(KM_IMPORT_WRAPPED_KEY, request, response);
+}
+
+void AmlogicKeymaster::ExportKey(const ExportKeyRequest& request, ExportKeyResponse* response) {
+ ForwardCommand(KM_EXPORT_KEY, request, response);
+}
+
+void AmlogicKeymaster::AttestKey(const AttestKeyRequest& request, AttestKeyResponse* response) {
+ ForwardCommand(KM_ATTEST_KEY, request, response);
+}
+
+void AmlogicKeymaster::UpgradeKey(const UpgradeKeyRequest& request, UpgradeKeyResponse* response) {
+ ForwardCommand(KM_UPGRADE_KEY, request, response);
+}
+
+void AmlogicKeymaster::DeleteKey(const DeleteKeyRequest& request, DeleteKeyResponse* response) {
+ ForwardCommand(KM_DELETE_KEY, request, response);
+}
+
+void AmlogicKeymaster::DeleteAllKeys(const DeleteAllKeysRequest& request,
+ DeleteAllKeysResponse* response) {
+ ForwardCommand(KM_DELETE_ALL_KEYS, request, response);
+}
+
+void AmlogicKeymaster::BeginOperation(const BeginOperationRequest& request,
+ BeginOperationResponse* response) {
+ ForwardCommand(KM_BEGIN_OPERATION, request, response);
+}
+
+void AmlogicKeymaster::UpdateOperation(const UpdateOperationRequest& request,
+ UpdateOperationResponse* response) {
+ ForwardCommand(KM_UPDATE_OPERATION, request, response);
+}
+
+void AmlogicKeymaster::FinishOperation(const FinishOperationRequest& request,
+ FinishOperationResponse* response) {
+ ForwardCommand(KM_FINISH_OPERATION, request, response);
+}
+
+void AmlogicKeymaster::AbortOperation(const AbortOperationRequest& request,
+ AbortOperationResponse* response) {
+ ForwardCommand(KM_ABORT_OPERATION, request, response);
+}
+
+GetHmacSharingParametersResponse AmlogicKeymaster::GetHmacSharingParameters() {
+ // Dummy empty buffer to allow ForwardCommand to have something to serialize
+ Buffer request;
+ GetHmacSharingParametersResponse response;
+ ForwardCommand(KM_GET_HMAC_SHARING_PARAMETERS, request, &response);
+ return response;
+}
+
+ComputeSharedHmacResponse AmlogicKeymaster::ComputeSharedHmac(
+ const ComputeSharedHmacRequest& request) {
+ ComputeSharedHmacResponse response;
+ ForwardCommand(KM_COMPUTE_SHARED_HMAC, request, &response);
+ return response;
+}
+
+VerifyAuthorizationResponse AmlogicKeymaster::VerifyAuthorization(
+ const VerifyAuthorizationRequest& request) {
+ VerifyAuthorizationResponse response;
+ ForwardCommand(KM_VERIFY_AUTHORIZATION, request, &response);
+ return response;
+}
+#if AMLOGIC_MODIFY
+void AmlogicKeymaster::SetBootParams(SetBootParamsRequest& req, SetBootParamsResponse *rsp) {
+#if 0
+ std::string prop_val;
+ // SHA256
+ uint8_t bootkey_hash[32];
+ uint8_t vbmeta_digest[32];
+
+ const uint8_t empty_hash_bin[32] = {0x0};
+ std::string empty_hash_hex_str(64, '0');
+
+ req.os_version = GetOsVersion();
+ req.os_patchlevel = GetOsPatchlevel();
+
+ // device_locked
+ prop_val = android::base::GetProperty("ro.boot.vbmeta.device_state", "unlocked");
+ req.device_locked = !prop_val.compare("locked")? 1: 0;
+
+ // verified_boot_state
+ prop_val = android::base::GetProperty("ro.boot.verifiedbootstate", "red");
+ req.verified_boot_state = KM_VERIFIED_BOOT_FAILED;
+ if (!prop_val.compare("green"))
+ req.verified_boot_state = KM_VERIFIED_BOOT_VERIFIED;
+ else if (!prop_val.compare("yellow"))
+ req.verified_boot_state = KM_VERIFIED_BOOT_SELF_SIGNED;
+ else if (!prop_val.compare("orange"))
+ req.verified_boot_state = KM_VERIFIED_BOOT_UNVERIFIED;
+ else if (!prop_val.compare("red"))
+ req.verified_boot_state = KM_VERIFIED_BOOT_FAILED;
+
+ // verified_boot_key
+ prop_val = android::base::GetProperty("ro.boot.vbmeta.bootkey_hash", empty_hash_hex_str);
+ //ALOGE("bootkey_hash = %s", prop_val.c_str());
+ //bootkey_hash = hex2bin(prop_val);
+ if (HexToBytes(bootkey_hash, sizeof(bootkey_hash), prop_val))
+ req.verified_boot_key.Reinitialize(bootkey_hash, sizeof(bootkey_hash));
+ else
+ req.verified_boot_key.Reinitialize(empty_hash_bin, sizeof(empty_hash_bin));
+
+ // verified_boot_hash
+ prop_val = android::base::GetProperty("ro.boot.vbmeta.digest", empty_hash_hex_str);
+ //ALOGE("vbmeta.digest = %s", prop_val.c_str());
+
+ //vbmeta_digest = hex2bin(prop_val);
+ if (HexToBytes(vbmeta_digest, sizeof(vbmeta_digest), prop_val))
+ req.verified_boot_hash.Reinitialize(vbmeta_digest, sizeof(vbmeta_digest));
+ else
+ req.verified_boot_hash.Reinitialize(empty_hash_bin, sizeof(empty_hash_bin));
+#endif
+ ALOGE("send empty boot params");
+
+ req.os_version = GetOsVersion();
+ req.os_patchlevel = GetOsPatchlevel();
+
+ ForwardCommand(KM_SET_BOOT_PARAMS, req, rsp);
+}
+#if 0
+bool AmlogicKeymaster::NibbleValue(const char& c, uint8_t* value) {
+ //CHECK(value != nullptr);
+ switch (c) {
+ case '0' ... '9':
+ *value = c - '0';
+ break;
+ case 'a' ... 'f':
+ *value = c - 'a' + 10;
+ break;
+ case 'A' ... 'F':
+ *value = c - 'A' + 10;
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool AmlogicKeymaster::HexToBytes(uint8_t* bytes, size_t bytes_len, const std::string& hex) {
+ //CHECK(bytes != nullptr);
+
+ if (hex.size() % 2 != 0) {
+ return false;
+ }
+ if (hex.size() / 2 > bytes_len) {
+ return false;
+ }
+ for (size_t i = 0, j = 0, n = hex.size(); i < n; i += 2, ++j) {
+ uint8_t high;
+ if (!NibbleValue(hex[i], &high)) {
+ return false;
+ }
+ uint8_t low;
+ if (!NibbleValue(hex[i + 1], &low)) {
+ return false;
+ }
+ bytes[j] = (high << 4) | low;
+ }
+ return true;
+}
+std::string AmlogicKeymaster::hex2bin(std::string const& s) {
+ //assert(s.length() % 2 == 0);
+ std::string sOut;
+ sOut.reserve(s.length()/2);
+
+ std::string extract;
+ for (std::string::const_iterator pos = s.begin(); pos<s.end(); pos += 2)
+ {
+ extract.assign(pos, pos+2);
+ sOut.push_back(std::stoi(extract, nullptr, 16));
+ }
+ return sOut;
+}
+#endif
+#endif
+} // namespace keymaster
diff --git a/Android.mk b/Android.mk
index 4395a85..4afea80 100644..100755
--- a/Android.mk
+++ b/Android.mk
@@ -16,48 +16,6 @@ LOCAL_PATH := $(call my-dir)
KEYMASTER_TA_BINARY := 8efb1e1c-37e5-4326-a5d68c33726c7d57
-include $(CLEAR_VARS)
-LOCAL_MODULE := keystore.amlogic
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SRC_FILES := module.cpp \
- aml_keymaster_ipc.cpp \
- aml_keymaster_device.cpp \
-
-LOCAL_C_INCLUDES := \
- system/security/keystore \
- $(LOCAL_PATH)/include \
- system/keymaster/ \
- system/keymaster/include \
- external/boringssl/include \
- $(BOARD_AML_VENDOR_PATH)/tdk/ca_export_arm/include \
-
-LOCAL_CFLAGS = -fvisibility=hidden -Wall -Werror
-LOCAL_CFLAGS += -DANDROID_BUILD
-ifeq ($(USE_SOFT_KEYSTORE), false)
-LOCAL_CFLAGS += -DUSE_HW_KEYMASTER
-endif
-LOCAL_SHARED_LIBRARIES := libcrypto \
- liblog \
- libkeystore_binder \
- libkeymaster_messages \
- libteec
-
-LOCAL_MODULE_TAGS := optional
-
-ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 26 && echo OK),OK)
-LOCAL_PROPRIETARY_MODULE := true
-endif
-
-ifeq ($(shell test $(PLATFORM_SDK_VERSION) -le 26 && echo OK),OK)
-LOCAL_SHARED_LIBRARIES += libkeymaster1
-endif
-
-LOCAL_CFLAGS += -DANDROID_PLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION)
-
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_REQUIRED_MODULES := $(KEYMASTER_TA_BINARY)
-include $(BUILD_SHARED_LIBRARY)
-
#####################################################
# TA Library
#####################################################
@@ -67,62 +25,51 @@ LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := $(KEYMASTER_TA_BINARY)
LOCAL_MODULE_SUFFIX := .ta
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/lib/teetz
+KEYMASTER_UNSIGNED_TA := $(LOCAL_PATH)/$(LOCAL_MODULE)$(LOCAL_MODULE_SUFFIX)
ifeq ($(TARGET_ENABLE_TA_SIGN), true)
-$(info $(shell mkdir $(ANDROID_BUILD_TOP)/$(LOCAL_PATH)/signed))
-$(info $(shell $(ANDROID_BUILD_TOP)/$(BOARD_AML_VENDOR_PATH)/tdk/ta_export/scripts/sign_ta_auto.py \
- --in=$(ANDROID_BUILD_TOP)/$(LOCAL_PATH)/$(LOCAL_MODULE)$(LOCAL_MODULE_SUFFIX) \
- --out=$(ANDROID_BUILD_TOP)/$(LOCAL_PATH)/signed/$(LOCAL_MODULE)$(LOCAL_MODULE_SUFFIX)))
-LOCAL_SRC_FILES := signed/$(LOCAL_MODULE)$(LOCAL_MODULE_SUFFIX)
+include $(BUILD_SYSTEM)/base_rules.mk
+$(LOCAL_BUILT_MODULE):
+ @mkdir -p $(dir $@)
+ $(BOARD_AML_VENDOR_PATH)/tdk/ta_export/scripts/sign_ta_auto.py \
+ --in=$(KEYMASTER_UNSIGNED_TA) \
+ --out=$@ \
+ --keydir=$(BOARD_AML_TDK_KEY_PATH)
else
-LOCAL_SRC_FILES := $(LOCAL_MODULE)$(LOCAL_MODULE_SUFFIX)
-endif
+LOCAL_PREBUILT_MODULE_FILE := $(KEYMASTER_UNSIGNED_TA)
include $(BUILD_PREBUILT)
+endif
-
-# Unit tests for libkeymaster
include $(CLEAR_VARS)
-LOCAL_MODULE := amlkeymaster_tests
-LOCAL_SRC_FILES := \
- unit_test/android_keymaster_test.cpp \
- unit_test/android_keymaster_test_utils.cpp \
- unit_test/attestation_record.cpp
-# unit_test/attestation_record_test.cpp \
- unit_test/authorization_set_test.cpp \
-# unit_test/android_keymaster_messages_test.cpp \
- unit_test/hkdf_test.cpp \
- unit_test/hmac_test.cpp \
- unit_test/kdf1_test.cpp \
- unit_test/kdf2_test.cpp \
- unit_test/kdf_test.cpp \
- unit_test/key_blob_test.cpp \
- unit_test/keymaster_enforcement_test.cpp
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := 4.0/service.cpp \
+ 4.0/AmlogicKeymaster4Device.cpp \
+ ipc/amlogic_keymaster_ipc.cpp \
+ AmlogicKeymaster.cpp
+LOCAL_CFLAGS += -DAMLOGIC_MODIFY=1
LOCAL_C_INCLUDES := \
- external/boringssl/include \
- system/keymaster/include \
- system/keymaster \
- system/security/softkeymaster/include
+ $(LOCAL_PATH)/include \
+ $(BOARD_AML_VENDOR_PATH)/tdk/ca_export_arm/include
-LOCAL_CFLAGS = -Wall -Werror -Wunused -DKEYMASTER_NAME_TAGS
-LOCAL_CLANG_CFLAGS += -Wno-error=unused-const-variable -Wno-error=unused-private-field
-# TODO(krasin): reenable coverage flags, when the new Clang toolchain is released.
-# Currently, if enabled, these flags will cause an internal error in Clang.
-LOCAL_CLANG_CFLAGS += -fno-sanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp
-LOCAL_MODULE_TAGS := tests
LOCAL_SHARED_LIBRARIES := \
- libsoftkeymasterdevice \
- libkeymaster_messages \
- libcrypto \
- libsoftkeymaster \
- libkeymaster_portable \
- libhardware
-
-LOCAL_CFLAGS += -DANDROID_PLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION)
+ liblog \
+ libcutils \
+ libdl \
+ libbase \
+ libutils \
+ libhardware \
+ libhidlbase \
+ libhidltransport \
+ libteec \
+ libkeymaster_messages \
+ libkeymaster4 \
+ android.hardware.keymaster@4.0
-ifeq ($(shell test $(PLATFORM_SDK_VERSION) -le 26 && echo OK),OK)
-LOCAL_SHARED_LIBRARIES += libkeymaster1
+ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 26 && echo OK),OK)
+LOCAL_PROPRIETARY_MODULE := true
endif
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-include $(BUILD_NATIVE_TEST)
-
+LOCAL_REQUIRED_MODULES := $(KEYMASTER_TA_BINARY)
+LOCAL_MODULE := android.hardware.keymaster@4.0-service.amlogic
+LOCAL_INIT_RC := 4.0/android.hardware.keymaster@4.0-service.amlogic.rc
+include $(BUILD_EXECUTABLE)
diff --git a/aml_keymaster_device.cpp b/aml_keymaster_device.cpp
deleted file mode 100644
index 7a8c785..0000000
--- a/aml_keymaster_device.cpp
+++ b/dev/null
@@ -1,1021 +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.
- */
-
-#define LOG_TAG "AmlKeymaster"
-
-#include <assert.h>
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-#include <openssl/sha.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <fstream>
-#include <iostream>
-#include <inttypes.h>
-
-#include <algorithm>
-#include <type_traits>
-
-#include <hardware/keymaster2.h>
-#include <keymaster/authorization_set.h>
-#include <log/log.h>
-#include <utils/String8.h>
-
-#include "keymaster_ipc.h"
-#include "aml_keymaster_device.h"
-#include "aml_keymaster_ipc.h"
-
-#ifndef KEYMASTER_TEMP_FAILURE_RETRY
-#define KEYMASTER_TEMP_FAILURE_RETRY(exp, retry) \
- ({ \
- __typeof__(exp) _rc; \
- int count = 0; \
- do { \
- _rc = (exp); \
- count ++; \
- } while (_rc != TEEC_SUCCESS && count < retry); \
- _rc; \
- })
-#endif
-
-const uint32_t RECV_BUF_SIZE = 66 * 1024;
-const uint32_t SEND_BUF_SIZE = (66 * 1024 - sizeof(struct keymaster_message) - 16 /* tipc header */);
-
-const size_t kMaximumAttestationChallengeLength = 128;
-const size_t kMaximumFinishInputLength = 64 * 1024;
-
-namespace keymaster {
-
-static keymaster_error_t translate_error(TEEC_Result err) {
- switch (err) {
- case TEEC_SUCCESS:
- return KM_ERROR_OK;
- case TEEC_ERROR_ACCESS_DENIED:
- return KM_ERROR_SECURE_HW_ACCESS_DENIED;
-
- case TEEC_ERROR_CANCEL:
- return KM_ERROR_OPERATION_CANCELLED;
-
- case TEEC_ERROR_NOT_IMPLEMENTED:
- return KM_ERROR_UNIMPLEMENTED;
-
- case TEEC_ERROR_OUT_OF_MEMORY:
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- case TEEC_ERROR_BUSY:
- return KM_ERROR_SECURE_HW_BUSY;
-
- case TEEC_ERROR_COMMUNICATION:
- return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
-
- case TEEC_ERROR_SHORT_BUFFER:
- return KM_ERROR_INVALID_INPUT_LENGTH;
-
- default:
- return KM_ERROR_UNKNOWN_ERROR;
- }
-}
-
-AmlKeymasterDevice::AmlKeymasterDevice(const hw_module_t* module) {
- static_assert(std::is_standard_layout<AmlKeymasterDevice>::value,
- "AmlKeymasterDevice must be standard layout");
- static_assert(offsetof(AmlKeymasterDevice, device_) == 0,
- "device_ must be the first member of AmlKeymasterDevice");
- static_assert(offsetof(AmlKeymasterDevice, device_.common) == 0,
- "common must be the first member of keymaster2_device");
-
- ALOGI("Creating device");
- ALOGD("Device address: %p", this);
-
- device_ = {};
-
- device_.common.tag = HARDWARE_DEVICE_TAG;
- device_.common.version = 1;
- device_.common.module = const_cast<hw_module_t*>(module);
- device_.common.close = close_device;
-
- device_.flags = KEYMASTER_SUPPORTS_EC;
-
- device_.configure = configure;
- device_.add_rng_entropy = add_rng_entropy;
- device_.generate_key = generate_key;
- device_.get_key_characteristics = get_key_characteristics;
- device_.import_key = import_key;
- device_.export_key = export_key;
- device_.attest_key = attest_key;
- device_.upgrade_key = upgrade_key;
- device_.delete_key = delete_key;
- device_.delete_all_keys = nullptr;
- device_.begin = begin;
- device_.update = update;
- device_.finish = finish;
- device_.abort = abort;
-
- KM_context.fd = 0;
- KM_session.ctx = NULL;
- KM_session.session_id = 0;
-
-
- TEEC_Result rc = KEYMASTER_TEMP_FAILURE_RETRY(aml_keymaster_connect(&KM_context, &KM_session), 100);
- error_ = translate_error(rc);
- if (rc != TEEC_SUCCESS) {
- ALOGE("failed to connect to keymaster (0x%x)", rc);
- error_ = KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
- return;
- }
-
- GetVersionRequest version_request;
- GetVersionResponse version_response;
- error_ = Send(KM_GET_VERSION, version_request, &version_response);
- if (error_ == KM_ERROR_INVALID_ARGUMENT || error_ == KM_ERROR_UNIMPLEMENTED) {
- ALOGE("\"Bad parameters\" error on GetVersion call. Version 0 is not supported.");
- error_ = KM_ERROR_VERSION_MISMATCH;
- return;
- }
- message_version_ = MessageVersion(version_response.major_ver, version_response.minor_ver,
- version_response.subminor_ver);
- if (message_version_ < 0) {
- // Can't translate version? Keymaster implementation must be newer.
- ALOGE("Keymaster version %d.%d.%d not supported.", version_response.major_ver,
- version_response.minor_ver, version_response.subminor_ver);
- error_ = KM_ERROR_VERSION_MISMATCH;
- }
-}
-
-AmlKeymasterDevice::~AmlKeymasterDevice() {
- if (KM_session.ctx != NULL)
- aml_keymaster_disconnect(&KM_context, &KM_session);
-}
-
-namespace {
-
-// Allocates a new buffer with malloc and copies the contents of |buffer| to it. Caller takes
-// ownership of the returned buffer.
-uint8_t* DuplicateBuffer(const uint8_t* buffer, size_t size) {
- uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(size));
- if (tmp) {
- memcpy(tmp, buffer, size);
- }
- return tmp;
-}
-
-template <typename RequestType>
-void AddClientAndAppData(const keymaster_blob_t* client_id, const keymaster_blob_t* app_data,
- RequestType* request) {
- request->additional_params.Clear();
- if (client_id) {
- request->additional_params.push_back(TAG_APPLICATION_ID, *client_id);
- }
- if (app_data) {
- request->additional_params.push_back(TAG_APPLICATION_DATA, *app_data);
- }
-}
-
-} // unnamed namespace
-
-struct tag_table_entry {
- const char *name;
- keymaster_tag_t tag;
-};
-
-static struct tag_table_entry tag_table[] =
-{
- {"KM_TAG_PURPOSE", KM_TAG_PURPOSE},
- {"KM_TAG_ALGORITHM", KM_TAG_ALGORITHM},
- {"KM_TAG_KEY_SIZE", KM_TAG_KEY_SIZE},
- {"KM_TAG_BLOCK_MODE", KM_TAG_BLOCK_MODE},
- {"KM_TAG_DIGEST", KM_TAG_DIGEST},
- {"KM_TAG_PADDING", KM_TAG_PADDING},
- {"KM_TAG_CALLER_NONCE", KM_TAG_CALLER_NONCE},
- {"KM_TAG_MIN_MAC_LENGTH", KM_TAG_MIN_MAC_LENGTH},
- {"KM_TAG_RSA_PUBLIC_EXPONENT", KM_TAG_RSA_PUBLIC_EXPONENT},
- {"KM_TAG_BLOB_USAGE_REQUIREMENTS", KM_TAG_BLOB_USAGE_REQUIREMENTS},
- {"KM_TAG_BOOTLOADER_ONLY", KM_TAG_BOOTLOADER_ONLY},
- {"KM_TAG_ACTIVE_DATETIME", KM_TAG_ACTIVE_DATETIME},
- {"KM_TAG_ORIGINATION_EXPIRE_DATETIME", KM_TAG_ORIGINATION_EXPIRE_DATETIME},
- {"KM_TAG_USAGE_EXPIRE_DATETIME",KM_TAG_USAGE_EXPIRE_DATETIME},
- {"KM_TAG_MIN_SECONDS_BETWEEN_OPS",KM_TAG_MIN_SECONDS_BETWEEN_OPS},
- {"KM_TAG_MAX_USES_PER_BOOT",KM_TAG_MAX_USES_PER_BOOT},
- {"KM_TAG_ALL_USERS", KM_TAG_ALL_USERS},
- {"KM_TAG_USER_ID", KM_TAG_USER_ID},
- {"KM_TAG_USER_SECURE_ID",KM_TAG_USER_SECURE_ID},
- {"KM_TAG_NO_AUTH_REQUIRED",KM_TAG_NO_AUTH_REQUIRED},
- {"KM_TAG_USER_AUTH_TYPE ", KM_TAG_USER_AUTH_TYPE},
- {"KM_TAG_AUTH_TIMEOUT ",KM_TAG_AUTH_TIMEOUT },
- {"KM_TAG_ALL_APPLICATIONS ", KM_TAG_ALL_APPLICATIONS },
- {"KM_TAG_APPLICATION_ID", KM_TAG_APPLICATION_ID},
- {"KM_TAG_APPLICATION_DATA ",KM_TAG_APPLICATION_DATA },
- {"KM_TAG_CREATION_DATETIME ",KM_TAG_CREATION_DATETIME },
- {"KM_TAG_ORIGIN ", KM_TAG_ORIGIN },
- {"KM_TAG_ROLLBACK_RESISTANT ", KM_TAG_ROLLBACK_RESISTANT },
- {"KM_TAG_ROOT_OF_TRUST", KM_TAG_ROOT_OF_TRUST},
- {"KM_TAG_ASSOCIATED_DATA ",KM_TAG_ASSOCIATED_DATA},
- {"KM_TAG_NONCE", KM_TAG_NONCE},
- {"KM_TAG_AUTH_TOKEN",KM_TAG_AUTH_TOKEN},
- {"KM_TAG_MAC_LENGTH", KM_TAG_MAC_LENGTH},
-};
-
-const size_t tag_table_size = sizeof(tag_table)/sizeof(struct tag_table_entry);
-
-void AmlKeymasterDevice::dump_tag_item_value(const char *name, const keymaster_key_param_t* item)
-{
- keymaster_tag_type_t type = KM_INVALID;
-
- if (item) {
- type = keymaster_tag_get_type(item->tag);
- switch (type) {
- case KM_ULONG:
- case KM_ULONG_REP:
- ALOGI("%s: %" PRIx64 "\n", name, item->long_integer);
- //printf("%s: %" PRIx64 "\n", name, item->long_integer);
- break;
- case KM_DATE:
- ALOGI("%s: %" PRIx64 "\n", name, item->date_time);
- //printf("%s: %" PRIx64 "\n", name, item->date_time);
- break;
- case KM_BYTES:
- case KM_BIGNUM:
- ALOGI("%s: blob data: %p, len: 0x%zx\n", name, item->blob.data, item->blob.data_length);
- //printf("%s: blob data: %p, len: 0x%zx\n", name, item->blob.data, item->blob.data_length);
- break;
- case KM_ENUM:
- case KM_ENUM_REP:
- ALOGI("%s: 0x%x\n", name, item->enumerated);
- //printf("%s: 0x%x\n", name, item->enumerated);
- break;
- case KM_BOOL:
- ALOGI("%s: 0x%x\n", name, item->boolean);
- //printf("%s: 0x%x\n", name, item->boolean);
- break;
- case KM_UINT:
- case KM_UINT_REP:
- ALOGI("%s: 0x%x\n", name, item->integer);
- //printf("%s: 0x%x\n", name, item->integer);
- break;
- default:
- ALOGI("%s: invalid type: %d\n", name, type);
- //printf("%s: invalid type: %d\n", name, type);
- break;
- }
- }
-}
-
-void AmlKeymasterDevice::dump_tags(const char *name, const keymaster_key_param_set_t *params)
-{
- size_t i = 0, j =0;
- keymaster_key_param_t* item = params->params;
-
- ALOGI("==== start dump %s, length (%zu)\n", name, params->length);
- //printf("==== start dump %s, length (%zu)\n", name, params->length);
- for (i = 0; i < params->length; i++) {
- for (j = 0; j < tag_table_size; j++) {
- if (tag_table[j].tag == item[i].tag) {
- dump_tag_item_value(tag_table[j].name, &item[i]);
- break;
- }
- }
- }
- ALOGI("==== end dump %s\n", name);
- //printf("==== end dump %s\n", name);
-}
-
-keymaster_error_t AmlKeymasterDevice::configure(const keymaster_key_param_set_t* params) {
- ALOGD("Device received configure\n");
-
- if (error_ != KM_ERROR_OK) {
- return error_;
- }
- if (!params) {
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
- }
-
- AuthorizationSet params_copy(*params);
- ConfigureRequest request;
- if (!params_copy.GetTagValue(TAG_OS_VERSION, &request.os_version) ||
- !params_copy.GetTagValue(TAG_OS_PATCHLEVEL, &request.os_patchlevel)) {
- ALOGD("Configuration parameters must contain OS version and patch level");
- return KM_ERROR_INVALID_ARGUMENT;
- }
-
- ConfigureResponse response;
- keymaster_error_t err = Send(KM_CONFIGURE, request, &response);
- if (err != KM_ERROR_OK) {
- return err;
- }
-
- return KM_ERROR_OK;
-}
-
-keymaster_error_t AmlKeymasterDevice::add_rng_entropy(const uint8_t* data, size_t data_length) {
- ALOGD("Device received add_rng_entropy");
-
- if (error_ != KM_ERROR_OK) {
- return error_;
- }
-
- AddEntropyRequest request;
- request.random_data.Reinitialize(data, data_length);
- AddEntropyResponse response;
- return Send(KM_ADD_RNG_ENTROPY, request, &response);
-}
-
-keymaster_error_t AmlKeymasterDevice::simple_bin2ascii(uint8_t *data, size_t data_length, char *out) {
- for (size_t i = 0; i < data_length; i++) {
- if (((data[i] & 0xf0) >> 4) < 0xa)
- out[i * 2] = ((data[i] & 0xf0) >> 4) + 48;
- else
- out[i * 2] = ((data[i] & 0xf0) >> 4) + 87;
- if ((data[i] & 0xf) < 0xa)
- out[i * 2 + 1] = (data[i] & 0xf) + 48;
- else
- out[i * 2 + 1] = (data[i] & 0xf) + 87;
- }
-
- return KM_ERROR_OK;
-}
-
-keymaster_error_t AmlKeymasterDevice::store_encrypted_key(keymaster_key_blob_t* key_blob) {
- SHA256_CTX sha256_ctx;
- UniquePtr<uint8_t[]> hash_buf(new (std::nothrow) uint8_t[SHA256_DIGEST_LENGTH + 1]);
- UniquePtr<char[]> name_buf(new (std::nothrow) char [SHA256_DIGEST_LENGTH * 2 + 1]);
- std::ofstream out;
- char name[256];
-
- // Hash key data to create filename.
- Eraser sha256_ctx_eraser(sha256_ctx);
- memset(name_buf.get(), 0, SHA256_DIGEST_LENGTH * 2 + 1);
- SHA256_Init(&sha256_ctx);
- SHA256_Update(&sha256_ctx, key_blob->key_material, key_blob->key_material_size);
- SHA256_Final(hash_buf.get(), &sha256_ctx);
-
- simple_bin2ascii(hash_buf.get(), SHA256_DIGEST_LENGTH, name_buf.get());
- name_buf[SHA256_DIGEST_LENGTH * 2] = '\0';
- sprintf(name, "/data/tee/%s", name_buf.get());
- out.open(name, std::ofstream::out | std::ofstream::binary);
- if (out.is_open()) {
- out.write((const char *)key_blob->key_material, key_blob->key_material_size);
- out.close();
- } else {
- ALOGE("error opening key files\n");
- }
-
- return KM_ERROR_OK;
-}
-
-keymaster_error_t AmlKeymasterDevice::delete_encrypted_key(const keymaster_key_blob_t* key_blob) {
- SHA256_CTX sha256_ctx;
- UniquePtr<uint8_t[]> hash_buf(new (std::nothrow) uint8_t[SHA256_DIGEST_LENGTH + 1]);
- UniquePtr<char[]> name_buf(new (std::nothrow) char [SHA256_DIGEST_LENGTH * 2 + 1]);
- std::ofstream out;
- char name[256];
- int result = -1;
-
- // Hash key data to get filename.
- Eraser sha256_ctx_eraser(sha256_ctx);
- memset(name_buf.get(), 0, SHA256_DIGEST_LENGTH * 2 + 1);
- SHA256_Init(&sha256_ctx);
- SHA256_Update(&sha256_ctx, key_blob->key_material, key_blob->key_material_size);
- SHA256_Final(hash_buf.get(), &sha256_ctx);
-
- simple_bin2ascii(hash_buf.get(), SHA256_DIGEST_LENGTH, name_buf.get());
- name_buf[SHA256_DIGEST_LENGTH * 2] = '\0';
- sprintf(name, "/data/tee/%s", name_buf.get());
- out.open(name, std::ofstream::out | std::ofstream::binary);
- result = unlink(name);
-
- if (!result) {
- return KM_ERROR_OK;
- } else {
- ALOGE("cannot locate %s\n", name);
- return KM_ERROR_INVALID_OPERATION_HANDLE;
- }
-}
-
-keymaster_error_t AmlKeymasterDevice::generate_key(
- const keymaster_key_param_set_t* params, keymaster_key_blob_t* key_blob,
- keymaster_key_characteristics_t* characteristics) {
- ALOGD("Device received generate_key");
-
- if (error_ != KM_ERROR_OK) {
- return error_;
- }
- if (!params) {
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
- }
- if (!key_blob) {
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
- }
-
- GenerateKeyRequest request(message_version_);
- request.key_description.Reinitialize(*params);
- request.key_description.push_back(TAG_CREATION_DATETIME, java_time(time(NULL)));
-
- GenerateKeyResponse response(message_version_);
- keymaster_error_t err = Send(KM_GENERATE_KEY, request, &response);
- if (err != KM_ERROR_OK) {
- return err;
- }
-
- key_blob->key_material_size = response.key_blob.key_material_size;
- key_blob->key_material =
- DuplicateBuffer(response.key_blob.key_material, response.key_blob.key_material_size);
- if (!key_blob->key_material) {
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- }
-
- if (characteristics) {
- response.enforced.CopyToParamSet(&characteristics->hw_enforced);
- response.unenforced.CopyToParamSet(&characteristics->sw_enforced);
- }
-
- return KM_ERROR_OK;
-}
-
-keymaster_error_t AmlKeymasterDevice::get_key_characteristics(
- const keymaster_key_blob_t* key_blob, const keymaster_blob_t* client_id,
- const keymaster_blob_t* app_data, keymaster_key_characteristics_t* characteristics) {
- ALOGD("Device received get_key_characteristics");
-
- if (error_ != KM_ERROR_OK) {
- return error_;
- }
- if (!key_blob || !key_blob->key_material) {
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
- }
- if (!characteristics) {
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
- }
-
- GetKeyCharacteristicsRequest request;
- request.SetKeyMaterial(*key_blob);
- AddClientAndAppData(client_id, app_data, &request);
-
- GetKeyCharacteristicsResponse response;
- keymaster_error_t err = Send(KM_GET_KEY_CHARACTERISTICS, request, &response);
- if (err != KM_ERROR_OK) {
- return err;
- }
-
- response.enforced.CopyToParamSet(&characteristics->hw_enforced);
- response.unenforced.CopyToParamSet(&characteristics->sw_enforced);
-
- return KM_ERROR_OK;
-}
-
-keymaster_error_t AmlKeymasterDevice::import_key(
- const keymaster_key_param_set_t* params, keymaster_key_format_t key_format,
- const keymaster_blob_t* key_data, keymaster_key_blob_t* key_blob,
- keymaster_key_characteristics_t* characteristics) {
- ALOGD("Device received import_key");
-
- if (error_ != KM_ERROR_OK) {
- return error_;
- }
- if (!params || !key_data) {
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
- }
- if (!key_blob) {
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
- }
-
- ImportKeyRequest request(message_version_);
- request.key_description.Reinitialize(*params);
- request.key_description.push_back(TAG_CREATION_DATETIME, java_time(time(NULL)));
-
- dump_tags("import", &request.key_description);
- request.key_format = key_format;
- request.SetKeyMaterial(key_data->data, key_data->data_length);
-
- ImportKeyResponse response(message_version_);
- keymaster_error_t err = Send(KM_IMPORT_KEY, request, &response);
- if (err != KM_ERROR_OK) {
- return err;
- }
-
- key_blob->key_material_size = response.key_blob.key_material_size;
- key_blob->key_material =
- DuplicateBuffer(response.key_blob.key_material, response.key_blob.key_material_size);
- if (!key_blob->key_material) {
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- }
-
- dump_tags("hw", &response.enforced);
- dump_tags("sw", &response.unenforced);
- if (characteristics) {
- response.enforced.CopyToParamSet(&characteristics->hw_enforced);
- response.unenforced.CopyToParamSet(&characteristics->sw_enforced);
- }
-
- return KM_ERROR_OK;
-}
-
-keymaster_error_t AmlKeymasterDevice::export_key(keymaster_key_format_t export_format,
- const keymaster_key_blob_t* key_to_export,
- const keymaster_blob_t* client_id,
- const keymaster_blob_t* app_data,
- keymaster_blob_t* export_data) {
- ALOGD("Device received export_key");
-
- if (error_ != KM_ERROR_OK) {
- return error_;
- }
- if (!key_to_export || !key_to_export->key_material) {
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
- }
- if (!export_data) {
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
- }
-
- export_data->data = nullptr;
- export_data->data_length = 0;
-
- ExportKeyRequest request(message_version_);
- request.key_format = export_format;
- request.SetKeyMaterial(*key_to_export);
- AddClientAndAppData(client_id, app_data, &request);
-
- ExportKeyResponse response(message_version_);
- keymaster_error_t err = Send(KM_EXPORT_KEY, request, &response);
- if (err != KM_ERROR_OK) {
- return err;
- }
-
- export_data->data_length = response.key_data_length;
- export_data->data = DuplicateBuffer(response.key_data, response.key_data_length);
- if (!export_data->data) {
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- }
-
- return KM_ERROR_OK;
-}
-
-keymaster_error_t AmlKeymasterDevice::attest_key(const keymaster_key_blob_t* key_to_attest,
- const keymaster_key_param_set_t* attest_params,
- keymaster_cert_chain_t* cert_chain) {
- ALOGD("Device received attest_key");
-
- if (error_ != KM_ERROR_OK) {
- return error_;
- }
- if (!key_to_attest || !attest_params) {
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
- }
- if (!cert_chain) {
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
- }
-
- cert_chain->entry_count = 0;
- cert_chain->entries = nullptr;
-
- AttestKeyRequest request;
- request.SetKeyMaterial(*key_to_attest);
- request.attest_params.Reinitialize(*attest_params);
-
- keymaster_blob_t attestation_challenge = {};
- request.attest_params.GetTagValue(TAG_ATTESTATION_CHALLENGE, &attestation_challenge);
- if (attestation_challenge.data_length > kMaximumAttestationChallengeLength) {
- ALOGE("%zu-byte attestation challenge; only %zu bytes allowed",
- attestation_challenge.data_length, kMaximumAttestationChallengeLength);
- return KM_ERROR_INVALID_INPUT_LENGTH;
- }
-
- AttestKeyResponse response;
- keymaster_error_t err = Send(KM_ATTEST_KEY, request, &response);
- if (err != KM_ERROR_OK) {
- return err;
- }
-
- // Allocate and clear storage for cert_chain.
- keymaster_cert_chain_t& rsp_chain = response.certificate_chain;
- cert_chain->entries = reinterpret_cast<keymaster_blob_t*>(
- malloc(rsp_chain.entry_count * sizeof(*cert_chain->entries)));
- if (!cert_chain->entries) {
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- }
- cert_chain->entry_count = rsp_chain.entry_count;
- for (keymaster_blob_t& entry : array_range(cert_chain->entries, cert_chain->entry_count)) {
- entry = {};
- }
-
- // Copy cert_chain contents
- size_t i = 0;
- for (keymaster_blob_t& entry : array_range(rsp_chain.entries, rsp_chain.entry_count)) {
- cert_chain->entries[i].data = DuplicateBuffer(entry.data, entry.data_length);
- if (!cert_chain->entries[i].data) {
- keymaster_free_cert_chain(cert_chain);
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- }
- cert_chain->entries[i].data_length = entry.data_length;
- ++i;
- }
-
- return KM_ERROR_OK;
-}
-
-keymaster_error_t AmlKeymasterDevice::upgrade_key(const keymaster_key_blob_t* key_to_upgrade,
- const keymaster_key_param_set_t* upgrade_params,
- keymaster_key_blob_t* upgraded_key) {
- ALOGD("Device received upgrade_key");
-
- if (error_ != KM_ERROR_OK) {
- return error_;
- }
- if (!key_to_upgrade || !upgrade_params) {
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
- }
- if (!upgraded_key) {
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
- }
-
- UpgradeKeyRequest request;
- request.SetKeyMaterial(*key_to_upgrade);
- request.upgrade_params.Reinitialize(*upgrade_params);
-
- UpgradeKeyResponse response;
- keymaster_error_t err = Send(KM_UPGRADE_KEY, request, &response);
- if (err != KM_ERROR_OK) {
- return err;
- }
-
- upgraded_key->key_material_size = response.upgraded_key.key_material_size;
- upgraded_key->key_material = DuplicateBuffer(response.upgraded_key.key_material,
- response.upgraded_key.key_material_size);
- if (!upgraded_key->key_material) {
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- }
-
- return KM_ERROR_OK;
-}
-
-keymaster_error_t AmlKeymasterDevice::delete_key(const keymaster_key_blob_t* key) {
- (void)key;
- return KM_ERROR_OK;
-}
-
-keymaster_error_t AmlKeymasterDevice::begin(keymaster_purpose_t purpose,
- const keymaster_key_blob_t* key,
- const keymaster_key_param_set_t* in_params,
- keymaster_key_param_set_t* out_params,
- keymaster_operation_handle_t* operation_handle) {
- ALOGD("Device received begin");
-
- if (error_ != KM_ERROR_OK) {
- return error_;
- }
- if (!key || !key->key_material) {
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
- }
- if (!operation_handle) {
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
- }
-
- if (out_params) {
- *out_params = {};
- }
-
- BeginOperationRequest request;
- request.purpose = purpose;
- request.SetKeyMaterial(*key);
- request.additional_params.Reinitialize(*in_params);
-
- BeginOperationResponse response;
- keymaster_error_t err = Send(KM_BEGIN_OPERATION, request, &response);
- if (err != KM_ERROR_OK) {
- return err;
- }
-
- if (response.output_params.size() > 0) {
- if (out_params) {
- response.output_params.CopyToParamSet(out_params);
- } else {
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
- }
- }
- *operation_handle = response.op_handle;
-
- return KM_ERROR_OK;
-}
-
-keymaster_error_t AmlKeymasterDevice::update(keymaster_operation_handle_t operation_handle,
- const keymaster_key_param_set_t* in_params,
- const keymaster_blob_t* input,
- size_t* input_consumed,
- keymaster_key_param_set_t* out_params,
- keymaster_blob_t* output) {
- ALOGD("Device received update");
-
- if (error_ != KM_ERROR_OK) {
- return error_;
- }
- if (!input) {
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
- }
- if (!input_consumed) {
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
- }
-
- if (out_params) {
- *out_params = {};
- }
- if (output) {
- *output = {};
- }
-
- UpdateOperationRequest request;
- request.op_handle = operation_handle;
- if (in_params) {
- request.additional_params.Reinitialize(*in_params);
- }
- if (input && input->data_length > 0) {
- size_t max_input_size = SEND_BUF_SIZE - request.SerializedSize();
- request.input.Reinitialize(input->data, std::min(input->data_length, max_input_size));
- }
-
- UpdateOperationResponse response;
- keymaster_error_t err = Send(KM_UPDATE_OPERATION, request, &response);
- if (err != KM_ERROR_OK) {
- return err;
- }
-
- if (response.output_params.size() > 0) {
- if (out_params) {
- response.output_params.CopyToParamSet(out_params);
- } else {
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
- }
- }
- *input_consumed = response.input_consumed;
- if (output) {
- output->data_length = response.output.available_read();
- output->data = DuplicateBuffer(response.output.peek_read(), output->data_length);
- if (!output->data) {
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- }
- } else if (response.output.available_read() > 0) {
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
- }
-
- return KM_ERROR_OK;
-}
-
-keymaster_error_t AmlKeymasterDevice::finish(keymaster_operation_handle_t operation_handle,
- const keymaster_key_param_set_t* in_params,
- const keymaster_blob_t* input,
- const keymaster_blob_t* signature,
- keymaster_key_param_set_t* out_params,
- keymaster_blob_t* output) {
- ALOGD("Device received finish");
-
- bool size_exceeded = false;
- if (error_ != KM_ERROR_OK) {
- return error_;
- }
- if (input && input->data_length > kMaximumFinishInputLength) {
- ALOGE("%zu-byte input to finish; only %zu bytes allowed",
- input->data_length, kMaximumFinishInputLength);
- size_exceeded = true;
- }
-
- if (out_params) {
- *out_params = {};
- }
- if (output) {
- *output = {};
- }
-
- FinishOperationRequest request;
- request.op_handle = operation_handle;
- if (signature && signature->data && signature->data_length > 0) {
- request.signature.Reinitialize(signature->data, signature->data_length);
- }
- if (input && input->data && input->data_length) {
- /* sending fake request to close operation handle */
- if (size_exceeded)
- request.input.Reinitialize(input->data, 1);
- else
- request.input.Reinitialize(input->data, input->data_length);
- }
- if (in_params) {
- request.additional_params.Reinitialize(*in_params);
- }
-
- FinishOperationResponse response;
- keymaster_error_t err = Send(KM_FINISH_OPERATION, request, &response);
- /* drop result in case of fake request */
- if (size_exceeded)
- return KM_ERROR_INVALID_INPUT_LENGTH;
- if (err != KM_ERROR_OK) {
- return err;
- }
-
- if (response.output_params.size() > 0) {
- if (out_params) {
- response.output_params.CopyToParamSet(out_params);
- } else {
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
- }
- }
- if (output) {
- output->data_length = response.output.available_read();
- output->data = DuplicateBuffer(response.output.peek_read(), output->data_length);
- if (!output->data) {
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- }
- } else if (response.output.available_read() > 0) {
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
- }
-
- return KM_ERROR_OK;
-}
-
-keymaster_error_t AmlKeymasterDevice::abort(keymaster_operation_handle_t operation_handle) {
- ALOGD("Device received abort");
-
- if (error_ != KM_ERROR_OK) {
- return error_;
- }
-
- AbortOperationRequest request;
- request.op_handle = operation_handle;
- AbortOperationResponse response;
- return Send(KM_ABORT_OPERATION, request, &response);
-}
-
-hw_device_t* AmlKeymasterDevice::hw_device() {
- return &device_.common;
-}
-
-static inline AmlKeymasterDevice* convert_device(const keymaster2_device_t* dev) {
- return reinterpret_cast<AmlKeymasterDevice*>(const_cast<keymaster2_device_t*>(dev));
-}
-
-/* static */
-int AmlKeymasterDevice::close_device(hw_device_t* dev) {
- delete reinterpret_cast<AmlKeymasterDevice*>(dev);
- return 0;
-}
-
-/* static */
-keymaster_error_t AmlKeymasterDevice::configure(const keymaster2_device_t* dev,
- const keymaster_key_param_set_t* params) {
- return convert_device(dev)->configure(params);
-}
-
-/* static */
-keymaster_error_t AmlKeymasterDevice::add_rng_entropy(const keymaster2_device_t* dev,
- const uint8_t* data, size_t data_length) {
- return convert_device(dev)->add_rng_entropy(data, data_length);
-}
-
-/* static */
-keymaster_error_t AmlKeymasterDevice::generate_key(
- const keymaster2_device_t* dev, const keymaster_key_param_set_t* params,
- keymaster_key_blob_t* key_blob, keymaster_key_characteristics_t* characteristics) {
- return convert_device(dev)->generate_key(params, key_blob, characteristics);
-}
-
-/* static */
-keymaster_error_t AmlKeymasterDevice::get_key_characteristics(
- const keymaster2_device_t* dev, const keymaster_key_blob_t* key_blob,
- const keymaster_blob_t* client_id, const keymaster_blob_t* app_data,
- keymaster_key_characteristics_t* characteristics) {
- return convert_device(dev)->get_key_characteristics(key_blob, client_id, app_data,
- characteristics);
-}
-
-/* static */
-keymaster_error_t AmlKeymasterDevice::import_key(
- const keymaster2_device_t* dev, const keymaster_key_param_set_t* params,
- keymaster_key_format_t key_format, const keymaster_blob_t* key_data,
- keymaster_key_blob_t* key_blob, keymaster_key_characteristics_t* characteristics) {
- return convert_device(dev)->import_key(params, key_format, key_data, key_blob, characteristics);
-}
-
-/* static */
-keymaster_error_t AmlKeymasterDevice::export_key(const keymaster2_device_t* dev,
- keymaster_key_format_t export_format,
- const keymaster_key_blob_t* key_to_export,
- const keymaster_blob_t* client_id,
- const keymaster_blob_t* app_data,
- keymaster_blob_t* export_data) {
- return convert_device(dev)->export_key(export_format, key_to_export, client_id, app_data,
- export_data);
-}
-
-/* static */
-keymaster_error_t AmlKeymasterDevice::attest_key(const keymaster2_device_t* dev,
- const keymaster_key_blob_t* key_to_attest,
- const keymaster_key_param_set_t* attest_params,
- keymaster_cert_chain_t* cert_chain) {
- return convert_device(dev)->attest_key(key_to_attest, attest_params, cert_chain);
-}
-
-/* static */
-keymaster_error_t AmlKeymasterDevice::upgrade_key(const keymaster2_device_t* dev,
- const keymaster_key_blob_t* key_to_upgrade,
- const keymaster_key_param_set_t* upgrade_params,
- keymaster_key_blob_t* upgraded_key) {
- return convert_device(dev)->upgrade_key(key_to_upgrade, upgrade_params, upgraded_key);
-}
-
-/* static */
-keymaster_error_t AmlKeymasterDevice::delete_key(const keymaster2_device_t* dev,
- const keymaster_key_blob_t* key_blob) {
- return convert_device(dev)->delete_key(key_blob);
-}
-
-/* static */
-keymaster_error_t AmlKeymasterDevice::begin(const keymaster2_device_t* dev,
- keymaster_purpose_t purpose,
- const keymaster_key_blob_t* key,
- const keymaster_key_param_set_t* in_params,
- keymaster_key_param_set_t* out_params,
- keymaster_operation_handle_t* operation_handle) {
- return convert_device(dev)->begin(purpose, key, in_params, out_params, operation_handle);
-}
-
-/* static */
-keymaster_error_t AmlKeymasterDevice::update(
- const keymaster2_device_t* dev, keymaster_operation_handle_t operation_handle,
- const keymaster_key_param_set_t* in_params, const keymaster_blob_t* input,
- size_t* input_consumed, keymaster_key_param_set_t* out_params, keymaster_blob_t* output) {
- return convert_device(dev)->update(operation_handle, in_params, input, input_consumed,
- out_params, output);
-}
-
-/* static */
-keymaster_error_t AmlKeymasterDevice::finish(const keymaster2_device_t* dev,
- keymaster_operation_handle_t operation_handle,
- const keymaster_key_param_set_t* in_params,
- const keymaster_blob_t* input,
- const keymaster_blob_t* signature,
- keymaster_key_param_set_t* out_params,
- keymaster_blob_t* output) {
- return convert_device(dev)->finish(operation_handle, in_params, input, signature, out_params,
- output);
-}
-
-/* static */
-keymaster_error_t AmlKeymasterDevice::abort(const keymaster2_device_t* dev,
- keymaster_operation_handle_t operation_handle) {
- return convert_device(dev)->abort(operation_handle);
-}
-
-keymaster_error_t AmlKeymasterDevice::Send(uint32_t command, const Serializable& req,
- KeymasterResponse* rsp) {
- uint32_t req_size = req.SerializedSize();
-
- if (req_size > SEND_BUF_SIZE) {
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- }
- //uint8_t send_buf[SEND_BUF_SIZE];
- UniquePtr<uint8_t[]> send_buf (new (std::nothrow) uint8_t[SEND_BUF_SIZE]);
- if (!send_buf.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- Eraser send_buf_eraser(send_buf.get(), SEND_BUF_SIZE);
- req.Serialize(send_buf.get(), send_buf.get() + req_size);
-
- // Send it
- //uint8_t recv_buf[RECV_BUF_SIZE];
- UniquePtr<uint8_t[]> recv_buf (new (std::nothrow) uint8_t[RECV_BUF_SIZE]);
- if (!recv_buf.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- Eraser recv_buf_eraser(recv_buf.get(), RECV_BUF_SIZE);
- uint32_t rsp_size = RECV_BUF_SIZE;
- ALOGD("Sending cmd: %u with %d byte request\n", command, (int)req.SerializedSize());
- TEEC_Result rc = aml_keymaster_call(&KM_session, command, send_buf.get(), req_size, recv_buf.get(), &rsp_size);
- if (rc != TEEC_SUCCESS) {
- return translate_error(rc);
- } else {
- ALOGD("Received %d byte response\n", rsp_size);
- }
-
- const keymaster_message* msg = (keymaster_message*)recv_buf.get();
- const uint8_t* p = msg->payload;
- if (!rsp->Deserialize(&p, p + rsp_size)) {
- ALOGE("Error deserializing response of size %d\n", (int)rsp_size);
- return KM_ERROR_UNKNOWN_ERROR;
- } else if (rsp->error != KM_ERROR_OK) {
- ALOGE("Response of size %d contained error code %d\n", (int)rsp_size, (int)rsp->error);
- return rsp->error;
- }
- return rsp->error;
-}
-
-} // namespace keymaster
diff --git a/aml_keymaster_device.h b/aml_keymaster_device.h
deleted file mode 100644
index 2066a7c..0000000
--- a/aml_keymaster_device.h
+++ b/dev/null
@@ -1,194 +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 AML_KEYMASTER_AML_KEYMASTER_DEVICE_H_
-#define AML_KEYMASTER_AML_KEYMASTER_DEVICE_H_
-
-#include <hardware/keymaster2.h>
-#include <keymaster/android_keymaster_messages.h>
-
-extern "C" {
-#include <tee_client_api.h>
-}
-
-namespace keymaster {
-
-/**
- * Aml Keymaster device.
- *
- * IMPORTANT MAINTAINER NOTE: Pointers to instances of this class must be castable to hw_device_t
- * and keymaster_device. This means it must remain a standard layout class (no virtual functions and
- * no data members which aren't standard layout), and device_ must be the first data member.
- * Assertions in the constructor validate compliance with those constraints.
- */
-class AmlKeymasterDevice {
- public:
- /*
- * These are the only symbols that will be exported by libamlkeymaster. All functionality
- * can be reached via the function pointers in device_.
- */
- __attribute__((visibility("default"))) explicit AmlKeymasterDevice(const hw_module_t* module);
- __attribute__((visibility("default"))) hw_device_t* hw_device();
-
- ~AmlKeymasterDevice();
-
- keymaster_error_t session_error() { return error_; }
-
- keymaster_error_t configure(const keymaster_key_param_set_t* params);
- keymaster_error_t add_rng_entropy(const uint8_t* data, size_t data_length);
- keymaster_error_t generate_key(const keymaster_key_param_set_t* params,
- keymaster_key_blob_t* key_blob,
- keymaster_key_characteristics_t* characteristics);
- keymaster_error_t get_key_characteristics(const keymaster_key_blob_t* key_blob,
- const keymaster_blob_t* client_id,
- const keymaster_blob_t* app_data,
- keymaster_key_characteristics_t* character);
- keymaster_error_t import_key(const keymaster_key_param_set_t* params,
- keymaster_key_format_t key_format,
- const keymaster_blob_t* key_data, keymaster_key_blob_t* key_blob,
- keymaster_key_characteristics_t* characteristics);
- keymaster_error_t export_key(keymaster_key_format_t export_format,
- const keymaster_key_blob_t* key_to_export,
- const keymaster_blob_t* client_id,
- const keymaster_blob_t* app_data, keymaster_blob_t* export_data);
- keymaster_error_t attest_key(const keymaster_key_blob_t* key_to_attest,
- const keymaster_key_param_set_t* attest_params,
- keymaster_cert_chain_t* cert_chain);
- keymaster_error_t upgrade_key(const keymaster_key_blob_t* key_to_upgrade,
- const keymaster_key_param_set_t* upgrade_params,
- keymaster_key_blob_t* upgraded_key);
- keymaster_error_t delete_key(const keymaster_key_blob_t* key);
- keymaster_error_t begin(keymaster_purpose_t purpose, const keymaster_key_blob_t* key,
- const keymaster_key_param_set_t* in_params,
- keymaster_key_param_set_t* out_params,
- keymaster_operation_handle_t* operation_handle);
- keymaster_error_t update(keymaster_operation_handle_t operation_handle,
- const keymaster_key_param_set_t* in_params,
- const keymaster_blob_t* input, size_t* input_consumed,
- keymaster_key_param_set_t* out_params, keymaster_blob_t* output);
- keymaster_error_t finish(keymaster_operation_handle_t operation_handle,
- const keymaster_key_param_set_t* in_params,
- const keymaster_blob_t* input, const keymaster_blob_t* signature,
- keymaster_key_param_set_t* out_params, keymaster_blob_t* output);
- keymaster_error_t abort(keymaster_operation_handle_t operation_handle);
-
- keymaster_error_t store_encrypted_key(keymaster_key_blob_t* key_blob);
- keymaster_error_t delete_encrypted_key(const keymaster_key_blob_t* key_blob);
- keymaster_error_t simple_bin2ascii(uint8_t *data, size_t data_length, char *out);
- private:
- keymaster_error_t Send(uint32_t command, const Serializable& request,
- KeymasterResponse* response);
-
- /*
- * These static methods are the functions referenced through the function pointers in
- * keymaster_device. They're all trivial wrappers.
- */
- static int close_device(hw_device_t* dev);
- static keymaster_error_t configure(const keymaster2_device_t* dev,
- const keymaster_key_param_set_t* params);
- static keymaster_error_t add_rng_entropy(const keymaster2_device_t* dev, const uint8_t* data,
- size_t data_length);
- static keymaster_error_t generate_key(const keymaster2_device_t* dev,
- const keymaster_key_param_set_t* params,
- keymaster_key_blob_t* key_blob,
- keymaster_key_characteristics_t* characteristics);
- static keymaster_error_t get_key_characteristics(const keymaster2_device_t* dev,
- const keymaster_key_blob_t* key_blob,
- const keymaster_blob_t* client_id,
- const keymaster_blob_t* app_data,
- keymaster_key_characteristics_t* character);
- static keymaster_error_t import_key(const keymaster2_device_t* dev,
- const keymaster_key_param_set_t* params,
- keymaster_key_format_t key_format,
- const keymaster_blob_t* key_data,
- keymaster_key_blob_t* key_blob,
- keymaster_key_characteristics_t* characteristics);
- static keymaster_error_t export_key(const keymaster2_device_t* dev,
- keymaster_key_format_t export_format,
- const keymaster_key_blob_t* key_to_export,
- const keymaster_blob_t* client_id,
- const keymaster_blob_t* app_data,
- keymaster_blob_t* export_data);
- static keymaster_error_t attest_key(const keymaster2_device_t* dev,
- const keymaster_key_blob_t* key_to_attest,
- const keymaster_key_param_set_t* attest_params,
- keymaster_cert_chain_t* cert_chain);
- static keymaster_error_t upgrade_key(const keymaster2_device_t* dev,
- const keymaster_key_blob_t* key_to_upgrade,
- const keymaster_key_param_set_t* upgrade_params,
- keymaster_key_blob_t* upgraded_key);
- static keymaster_error_t delete_key(const keymaster2_device_t* dev,
- const keymaster_key_blob_t* key);
- static keymaster_error_t delete_all_keys(const keymaster2_device_t* dev);
- static keymaster_error_t begin(const keymaster2_device_t* dev, keymaster_purpose_t purpose,
- const keymaster_key_blob_t* key,
- const keymaster_key_param_set_t* in_params,
- keymaster_key_param_set_t* out_params,
- keymaster_operation_handle_t* operation_handle);
- static keymaster_error_t update(const keymaster2_device_t* dev,
- keymaster_operation_handle_t operation_handle,
- const keymaster_key_param_set_t* in_params,
- const keymaster_blob_t* input, size_t* input_consumed,
- keymaster_key_param_set_t* out_params, keymaster_blob_t* output);
- static keymaster_error_t finish(const keymaster2_device_t* dev,
- keymaster_operation_handle_t operation_handle,
- const keymaster_key_param_set_t* in_params,
- const keymaster_blob_t* input, const keymaster_blob_t* signature,
- keymaster_key_param_set_t* out_params, keymaster_blob_t* output);
- static keymaster_error_t abort(const keymaster2_device_t* dev,
- keymaster_operation_handle_t operation_handle);
-
- void dump_tags(const char *name, const keymaster_key_param_set_t *params);
- void dump_tag_item_value(const char *name, const keymaster_key_param_t* item);
-
- keymaster2_device_t device_;
- keymaster_error_t error_;
- int32_t message_version_;
-
- TEEC_Context KM_context;
- TEEC_Session KM_session;
-};
-
-#if ANDROID_PLATFORM_SDK_VERSION == 26 //8.0
-struct ConfigureRequest : public KeymasterMessage {
- explicit ConfigureRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {}
-
- size_t SerializedSize() const override { return sizeof(os_version) + sizeof(os_patchlevel); }
- uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
- buf = append_uint32_to_buf(buf, end, os_version);
- return append_uint32_to_buf(buf, end, os_patchlevel);
- }
- bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
- return copy_uint32_from_buf(buf_ptr, end, &os_version) &&
- copy_uint32_from_buf(buf_ptr, end, &os_patchlevel);
- }
-
- uint32_t os_version;
- uint32_t os_patchlevel;
-};
-
-struct ConfigureResponse : public KeymasterResponse {
- explicit ConfigureResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {}
-
- size_t NonErrorSerializedSize() const override { return 0; }
- uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t*) const override { return buf; }
- bool NonErrorDeserialize(const uint8_t**, const uint8_t*) override { return true; }
-};
-#endif
-
-} // namespace keymaster
-
-#endif // AML_KEYMASTER_AML_KEYMASTER_DEVICE_H_
diff --git a/aml_keymaster_ipc.cpp b/aml_keymaster_ipc.cpp
deleted file mode 100644
index 7270db6..0000000
--- a/aml_keymaster_ipc.cpp
+++ b/dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#define LOG_TAG "AmlKeymaster"
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <log/log.h>
-
-#include "keymaster_ipc.h"
-#include "aml_keymaster_ipc.h"
-
-TEEC_Result aml_keymaster_connect(TEEC_Context *c, TEEC_Session *s) {
- TEEC_Result result = TEEC_SUCCESS;
- TEEC_UUID svc_id = TA_KEYMASTER_UUID;
- TEEC_Operation operation;
- uint32_t err_origin;
- struct timespec time;
- uint64_t millis = 0;
-
- memset(&operation, 0, sizeof(operation));
-
- /* Initialize Context */
- result = TEEC_InitializeContext(NULL, c);
-
- if (result != TEEC_SUCCESS) {
- ALOGD("TEEC_InitializeContext failed with error = %x\n", result);
- return result;
- }
- /* Open Session */
- result = TEEC_OpenSession(c, s, &svc_id,
- TEEC_LOGIN_PUBLIC,
- NULL, NULL,
- &err_origin);
-
- if (result != TEEC_SUCCESS) {
- ALOGD("TEEC_Opensession failed with code 0x%x origin 0x%x",result, err_origin);
- TEEC_FinalizeContext(c);
- return result;
- }
-
- int res = clock_gettime(CLOCK_BOOTTIME, &time);
- if (res < 0)
- millis = 0;
- else
- millis = (time.tv_sec * 1000) + (time.tv_nsec / 1000 / 1000);
-
- /* Init TA */
- operation.paramTypes = TEEC_PARAM_TYPES(
- TEEC_VALUE_INPUT, TEEC_NONE,
- TEEC_NONE, TEEC_NONE);
-
- operation.params[0].value.a = (millis >> 32);
- operation.params[0].value.b = (millis & 0xffffffff);
-
- result = TEEC_InvokeCommand(s,
- KM_TA_INIT,
- &operation,
- NULL);
-
- ALOGE("create id: %d, ctx: %p, ctx: %p\n", s->session_id, s->ctx, c);
- return result;
-}
-
-TEEC_Result aml_keymaster_call(TEEC_Session *s, uint32_t cmd, void* in, uint32_t in_size, uint8_t* out,
- uint32_t* out_size) {
- TEEC_Result res = TEEC_SUCCESS;
- TEEC_Operation op;
- uint32_t ret_orig;
-
- memset(&op, 0, sizeof(op));
-
- op.params[0].tmpref.buffer = in;
- op.params[0].tmpref.size = in_size;
- op.params[1].tmpref.buffer = out;
- op.params[1].tmpref.size = *out_size;
- op.paramTypes = TEEC_PARAM_TYPES(
- TEEC_MEMREF_TEMP_INPUT,
- TEEC_MEMREF_TEMP_OUTPUT,
- TEEC_VALUE_OUTPUT,
- TEEC_NONE);
-
- ALOGE("id: %d, ctx: %p, cmd: %d\n", s->session_id, s->ctx, cmd);
- res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig);
- if (res != TEEC_SUCCESS) {
- ALOGE("Invoke cmd: %u failed with res(%x), ret_orig(%x), return(%d)\n",
- cmd, res, ret_orig, op.params[2].value.a);
- } else {
- *out_size = op.params[2].value.b;
- }
-
- return res;
-}
-
-TEEC_Result aml_keymaster_disconnect(TEEC_Context *c, TEEC_Session *s) {
- TEEC_Operation operation;
- TEEC_Result result = TEEC_SUCCESS;
-
- operation.paramTypes = TEEC_PARAM_TYPES(
- TEEC_NONE, TEEC_NONE,
- TEEC_NONE, TEEC_NONE);
-
- result = TEEC_InvokeCommand(s,
- KM_TA_TERM,
- &operation,
- NULL);
-
- TEEC_CloseSession(s);
- TEEC_FinalizeContext(c);
-
- return result;
-}
diff --git a/aml_keymaster_ipc.h b/aml_keymaster_ipc.h
deleted file mode 100644
index fa4a2da..0000000
--- a/aml_keymaster_ipc.h
+++ b/dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2015 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 AML_KEYMASTER_AML_KEYMASTER_IPC_H_
-#define AML_KEYMASTER_AML_KEYMASTER_IPC_H_
-
-extern "C" {
-#include <tee_client_api.h>
-}
-
-__BEGIN_DECLS
-
-TEEC_Result aml_keymaster_connect(TEEC_Context *c, TEEC_Session *s);
-TEEC_Result aml_keymaster_call(TEEC_Session *s, uint32_t cmd, void* in, uint32_t in_size, uint8_t* out,
- uint32_t* out_size);
-TEEC_Result aml_keymaster_disconnect(TEEC_Context *c, TEEC_Session *s);
-
-__END_DECLS
-
-#endif // AML_KEYMASTER_AML_KEYMASTER_IPC_H_
diff --git a/include/amlogic_keymaster/AmlogicKeymaster.h b/include/amlogic_keymaster/AmlogicKeymaster.h
new file mode 100755
index 0000000..4aacc38
--- a/dev/null
+++ b/include/amlogic_keymaster/AmlogicKeymaster.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2018 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 TRUSTY_KEYMASTER_H_
+#define TRUSTY_KEYMASTER_H_
+
+#include <keymaster/android_keymaster_messages.h>
+#include <amlogic_keymaster/ipc/amlogic_keymaster_ipc.h>
+#if AMLOGIC_MODIFY
+#include <amlogic_keymaster/amlogic_keymaster_messages.h>
+
+extern "C" {
+#include <tee_client_api.h>
+}
+#endif
+namespace keymaster {
+
+class AmlogicKeymaster {
+ public:
+ AmlogicKeymaster();
+ ~AmlogicKeymaster();
+ int Initialize();
+ void GetVersion(const GetVersionRequest& request, GetVersionResponse* response);
+ void SupportedAlgorithms(const SupportedAlgorithmsRequest& request,
+ SupportedAlgorithmsResponse* response);
+ void SupportedBlockModes(const SupportedBlockModesRequest& request,
+ SupportedBlockModesResponse* response);
+ void SupportedPaddingModes(const SupportedPaddingModesRequest& request,
+ SupportedPaddingModesResponse* response);
+ void SupportedDigests(const SupportedDigestsRequest& request,
+ SupportedDigestsResponse* response);
+ void SupportedImportFormats(const SupportedImportFormatsRequest& request,
+ SupportedImportFormatsResponse* response);
+ void SupportedExportFormats(const SupportedExportFormatsRequest& request,
+ SupportedExportFormatsResponse* response);
+ void AddRngEntropy(const AddEntropyRequest& request, AddEntropyResponse* response);
+ void Configure(const ConfigureRequest& request, ConfigureResponse* response);
+ void GenerateKey(const GenerateKeyRequest& request, GenerateKeyResponse* response);
+ void GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
+ GetKeyCharacteristicsResponse* response);
+ void ImportKey(const ImportKeyRequest& request, ImportKeyResponse* response);
+ void ImportWrappedKey(const ImportWrappedKeyRequest& request,
+ ImportWrappedKeyResponse* response);
+ void ExportKey(const ExportKeyRequest& request, ExportKeyResponse* response);
+ void AttestKey(const AttestKeyRequest& request, AttestKeyResponse* response);
+ void UpgradeKey(const UpgradeKeyRequest& request, UpgradeKeyResponse* response);
+ void DeleteKey(const DeleteKeyRequest& request, DeleteKeyResponse* response);
+ void DeleteAllKeys(const DeleteAllKeysRequest& request, DeleteAllKeysResponse* response);
+ void BeginOperation(const BeginOperationRequest& request, BeginOperationResponse* response);
+ void UpdateOperation(const UpdateOperationRequest& request, UpdateOperationResponse* response);
+ void FinishOperation(const FinishOperationRequest& request, FinishOperationResponse* response);
+ void AbortOperation(const AbortOperationRequest& request, AbortOperationResponse* response);
+ GetHmacSharingParametersResponse GetHmacSharingParameters();
+ ComputeSharedHmacResponse ComputeSharedHmac(const ComputeSharedHmacRequest& request);
+ VerifyAuthorizationResponse VerifyAuthorization(const VerifyAuthorizationRequest& request);
+#if AMLOGIC_MODIFY
+ /* Move ForwardCommand from static method into class in order to access private members */
+ void ForwardCommand(enum keymaster_command command, const Serializable& req, KeymasterResponse* rsp);
+ private:
+ void SetBootParams(SetBootParamsRequest& request, SetBootParamsResponse* response);
+#if 0
+ bool HexToBytes(uint8_t* bytes, size_t bytes_len, const std::string& hex);
+ bool NibbleValue(const char& c, uint8_t* value);
+ std::string hex2bin(std::string const& s);
+#endif
+ TEEC_Context KM_context;
+ TEEC_Session KM_session;
+#endif
+};
+
+} // namespace keymaster
+
+#endif // TRUSTY_KEYMASTER_H_
diff --git a/include/amlogic_keymaster/AmlogicKeymaster4Device.h b/include/amlogic_keymaster/AmlogicKeymaster4Device.h
new file mode 100755
index 0000000..f4225eb
--- a/dev/null
+++ b/include/amlogic_keymaster/AmlogicKeymaster4Device.h
@@ -0,0 +1,105 @@
+/*
+ **
+ ** 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.
+ */
+
+#ifndef keymaster_V4_0_AmlogicKeymaster4Device_H_
+#define keymaster_V4_0_AmlogicKeymaster4Device_H_
+
+#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+#include <hidl/Status.h>
+#include <amlogic_keymaster/AmlogicKeymaster.h>
+
+namespace keymaster {
+
+namespace V4_0 {
+
+using ::android::sp;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::keymaster::V4_0::ErrorCode;
+using ::android::hardware::keymaster::V4_0::HardwareAuthenticatorType;
+using ::android::hardware::keymaster::V4_0::HardwareAuthToken;
+using ::android::hardware::keymaster::V4_0::HmacSharingParameters;
+using ::android::hardware::keymaster::V4_0::IKeymasterDevice;
+using ::android::hardware::keymaster::V4_0::KeyCharacteristics;
+using ::android::hardware::keymaster::V4_0::KeyFormat;
+using ::android::hardware::keymaster::V4_0::KeyParameter;
+using ::android::hardware::keymaster::V4_0::KeyPurpose;
+using ::android::hardware::keymaster::V4_0::SecurityLevel;
+using ::android::hardware::keymaster::V4_0::Tag;
+using ::android::hardware::keymaster::V4_0::VerificationToken;
+
+class AmlogicKeymaster4Device : public IKeymasterDevice {
+ public:
+ explicit AmlogicKeymaster4Device(AmlogicKeymaster* impl);
+ virtual ~AmlogicKeymaster4Device();
+
+ Return<void> getHardwareInfo(getHardwareInfo_cb _hidl_cb) override;
+ Return<void> getHmacSharingParameters(getHmacSharingParameters_cb _hidl_cb) override;
+ Return<void> computeSharedHmac(const hidl_vec<HmacSharingParameters>& params,
+ computeSharedHmac_cb) override;
+ Return<void> verifyAuthorization(uint64_t challenge,
+ const hidl_vec<KeyParameter>& parametersToVerify,
+ const HardwareAuthToken& authToken,
+ verifyAuthorization_cb _hidl_cb) override;
+ Return<ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override;
+ Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
+ generateKey_cb _hidl_cb) override;
+ Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
+ const hidl_vec<uint8_t>& clientId,
+ const hidl_vec<uint8_t>& appData,
+ getKeyCharacteristics_cb _hidl_cb) override;
+ Return<void> importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
+ const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) override;
+ Return<void> importWrappedKey(const hidl_vec<uint8_t>& wrappedKeyData,
+ const hidl_vec<uint8_t>& wrappingKeyBlob,
+ const hidl_vec<uint8_t>& maskingKey,
+ const hidl_vec<KeyParameter>& unwrappingParams,
+ uint64_t passwordSid, uint64_t biometricSid,
+ importWrappedKey_cb _hidl_cb) override;
+ Return<void> exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
+ const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
+ exportKey_cb _hidl_cb) override;
+ Return<void> attestKey(const hidl_vec<uint8_t>& keyToAttest,
+ const hidl_vec<KeyParameter>& attestParams,
+ attestKey_cb _hidl_cb) override;
+ Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+ const hidl_vec<KeyParameter>& upgradeParams,
+ upgradeKey_cb _hidl_cb) override;
+ Return<ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override;
+ Return<ErrorCode> deleteAllKeys() override;
+ Return<ErrorCode> destroyAttestationIds() override;
+ Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+ const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
+ begin_cb _hidl_cb) override;
+ Return<void> update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+ const hidl_vec<uint8_t>& input, const HardwareAuthToken& authToken,
+ const VerificationToken& verificationToken, update_cb _hidl_cb) override;
+ Return<void> finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+ const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
+ const HardwareAuthToken& authToken,
+ const VerificationToken& verificationToken, finish_cb _hidl_cb) override;
+ Return<ErrorCode> abort(uint64_t operationHandle) override;
+
+ private:
+ std::unique_ptr<::keymaster::AmlogicKeymaster> impl_;
+};
+
+} // namespace V4_0
+} // namespace keymaster
+
+#endif // keymaster_V4_0_AmlogicKeymaster4Device_H_
diff --git a/include/amlogic_keymaster/amlogic_keymaster_messages.h b/include/amlogic_keymaster/amlogic_keymaster_messages.h
new file mode 100755
index 0000000..a83aa1f
--- a/dev/null
+++ b/include/amlogic_keymaster/amlogic_keymaster_messages.h
@@ -0,0 +1,222 @@
+/*
+ * 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.
+ */
+
+#ifndef TRUSTY_APP_KEYMASTER_TRUSTY_KEYMASTER_MESSAGES_H_
+#define TRUSTY_APP_KEYMASTER_TRUSTY_KEYMASTER_MESSAGES_H_
+
+#include <keymaster/android_keymaster_messages.h>
+
+namespace keymaster {
+
+/**
+ * Generic struct for Keymaster requests which hold a single raw buffer.
+ */
+struct RawBufferRequest : public KeymasterMessage {
+ explicit RawBufferRequest(int32_t ver = MAX_MESSAGE_VERSION)
+ : KeymasterMessage(ver) {}
+
+ size_t SerializedSize() const override { return data.SerializedSize(); }
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
+ return data.Serialize(buf, end);
+ }
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ return data.Deserialize(buf_ptr, end);
+ }
+
+ Buffer data;
+};
+
+/**
+ * Generic struct for Keymaster responses which hold a single raw buffer.
+ */
+struct RawBufferResponse : public KeymasterResponse {
+ explicit RawBufferResponse(int32_t ver = MAX_MESSAGE_VERSION)
+ : KeymasterResponse(ver) {}
+
+ size_t NonErrorSerializedSize() const override {
+ return data.SerializedSize();
+ }
+ uint8_t* NonErrorSerialize(uint8_t* buf,
+ const uint8_t* end) const override {
+ return data.Serialize(buf, end);
+ }
+ bool NonErrorDeserialize(const uint8_t** buf_ptr,
+ const uint8_t* end) override {
+ return data.Deserialize(buf_ptr, end);
+ }
+
+ Buffer data;
+};
+
+/**
+ * Generic struct for Keymaster responses which have no specialized response
+ * data.
+ */
+struct NoResponse : public KeymasterResponse {
+ explicit NoResponse(int32_t ver = MAX_MESSAGE_VERSION)
+ : KeymasterResponse(ver) {}
+
+ size_t NonErrorSerializedSize() const override { return 0; }
+ uint8_t* NonErrorSerialize(uint8_t* buf,
+ const uint8_t* end) const override {
+ (void)end;
+ return buf;
+ }
+ bool NonErrorDeserialize(const uint8_t** buf_ptr,
+ const uint8_t* end) override {
+ (void)buf_ptr;
+ (void)end;
+ return true;
+ }
+};
+
+struct NoRequest : public KeymasterMessage {
+ explicit NoRequest(int32_t ver = MAX_MESSAGE_VERSION)
+ : KeymasterMessage(ver) {}
+
+ size_t SerializedSize() const override { return 0; }
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
+ (void)end;
+ return buf;
+ }
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ (void)buf_ptr;
+ (void)end;
+ return true;
+ }
+};
+
+struct SetBootParamsRequest : public KeymasterMessage {
+ explicit SetBootParamsRequest(int32_t ver = MAX_MESSAGE_VERSION)
+ : KeymasterMessage(ver) {}
+
+ size_t SerializedSize() const override {
+ return (sizeof(os_version) + sizeof(os_patchlevel) +
+ sizeof(device_locked) + sizeof(verified_boot_state) +
+ verified_boot_key.SerializedSize() +
+ verified_boot_hash.SerializedSize());
+ }
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
+ buf = append_uint32_to_buf(buf, end, os_version);
+ buf = append_uint32_to_buf(buf, end, os_patchlevel);
+ buf = append_uint32_to_buf(buf, end, device_locked);
+ buf = append_uint32_to_buf(buf, end, verified_boot_state);
+ buf = verified_boot_key.Serialize(buf, end);
+ return verified_boot_hash.Serialize(buf, end);
+ }
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ return copy_uint32_from_buf(buf_ptr, end, &os_version) &&
+ copy_uint32_from_buf(buf_ptr, end, &os_patchlevel) &&
+ copy_uint32_from_buf(buf_ptr, end, &device_locked) &&
+ copy_uint32_from_buf(buf_ptr, end, &verified_boot_state) &&
+ verified_boot_key.Deserialize(buf_ptr, end) &&
+ verified_boot_hash.Deserialize(buf_ptr, end);
+ }
+
+ uint32_t os_version;
+ uint32_t os_patchlevel;
+ uint32_t device_locked;
+ keymaster_verified_boot_t verified_boot_state;
+ Buffer verified_boot_key;
+ Buffer verified_boot_hash;
+};
+
+struct SetBootParamsResponse : public NoResponse {};
+
+struct SetAttestationKeyRequest : public KeymasterMessage {
+ explicit SetAttestationKeyRequest(int32_t ver = MAX_MESSAGE_VERSION)
+ : KeymasterMessage(ver) {}
+
+ size_t SerializedSize() const override {
+ return sizeof(uint32_t) + key_data.SerializedSize();
+ }
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
+ buf = append_uint32_to_buf(buf, end, algorithm);
+ return key_data.Serialize(buf, end);
+ }
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ return copy_uint32_from_buf(buf_ptr, end, &algorithm) &&
+ key_data.Deserialize(buf_ptr, end);
+ }
+
+ keymaster_algorithm_t algorithm;
+ Buffer key_data;
+};
+
+struct SetAttestationKeyResponse : public NoResponse {};
+
+struct AppendAttestationCertChainRequest : public KeymasterMessage {
+ explicit AppendAttestationCertChainRequest(
+ int32_t ver = MAX_MESSAGE_VERSION)
+ : KeymasterMessage(ver) {}
+
+ size_t SerializedSize() const override {
+ return sizeof(uint32_t) + cert_data.SerializedSize();
+ }
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
+ buf = append_uint32_to_buf(buf, end, algorithm);
+ return cert_data.Serialize(buf, end);
+ }
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ return copy_uint32_from_buf(buf_ptr, end, &algorithm) &&
+ cert_data.Deserialize(buf_ptr, end);
+ }
+
+ keymaster_algorithm_t algorithm;
+ Buffer cert_data;
+};
+
+struct AppendAttestationCertChainResponse : public NoResponse {};
+
+/**
+ * For Android Things Attestation Provisioning (ATAP), the GetCaRequest message
+ * in the protocol are raw opaque messages for the purposes of this IPC call.
+ * Since the SetCaResponse message will be very large (> 10k), SetCaResponse is
+ * split into *Begin, *Update, and *Finish operations.
+ */
+struct AtapGetCaRequestRequest : public RawBufferRequest {};
+struct AtapGetCaRequestResponse : public RawBufferResponse {};
+
+struct AtapSetCaResponseBeginRequest : public KeymasterMessage {
+ explicit AtapSetCaResponseBeginRequest(int32_t ver = MAX_MESSAGE_VERSION)
+ : KeymasterMessage(ver) {}
+
+ size_t SerializedSize() const override { return sizeof(uint32_t); }
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
+ return append_uint32_to_buf(buf, end, ca_response_size);
+ }
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ return copy_uint32_from_buf(buf_ptr, end, &ca_response_size);
+ }
+
+ uint32_t ca_response_size;
+};
+struct AtapSetCaResponseBeginResponse : public NoResponse {};
+
+struct AtapSetCaResponseUpdateRequest : public RawBufferRequest {};
+struct AtapSetCaResponseUpdateResponse : public NoResponse {};
+
+struct AtapSetCaResponseFinishRequest : public NoRequest {};
+struct AtapSetCaResponseFinishResponse : public NoResponse {};
+struct AtapSetProductIdRequest : public RawBufferRequest {};
+struct AtapSetProductIdResponse : public NoResponse {};
+
+struct AtapReadUuidRequest : public NoRequest {};
+struct AtapReadUuidResponse : public RawBufferResponse {};
+
+} // namespace keymaster
+
+#endif // TRUSTY_APP_KEYMASTER_TRUSTY_KEYMASTER_MESSAGES_H_
diff --git a/include/amlogic_keymaster/ipc/amlogic_keymaster_ipc.h b/include/amlogic_keymaster/ipc/amlogic_keymaster_ipc.h
new file mode 100755
index 0000000..26d4001
--- a/dev/null
+++ b/include/amlogic_keymaster/ipc/amlogic_keymaster_ipc.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 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 TRUSTY_KEYMASTER_AMLOGIC_KEYMASTER_IPC_H_
+#define TRUSTY_KEYMASTER_AMLOGIC_KEYMASTER_IPC_H_
+
+#include <keymaster/android_keymaster_messages.h>
+#include <amlogic_keymaster/ipc/keymaster_ipc.h>
+
+extern "C" {
+#include <tee_client_api.h>
+}
+__BEGIN_DECLS
+
+const uint32_t AMLOGIC_KEYMASTER_RECV_BUF_SIZE = 2 * PAGE_SIZE;
+const uint32_t AMLOGIC_KEYMASTER_SEND_BUF_SIZE =
+ (PAGE_SIZE - sizeof(struct keymaster_message) - 16 /* tipc header */);
+#if !AMLOGIC_MODIFY
+int trusty_keymaster_connect(void);
+int trusty_keymaster_call(uint32_t cmd, void* in, uint32_t in_size, uint8_t* out,
+ uint32_t* out_size);
+void trusty_keymaster_disconnect(void);
+
+keymaster_error_t translate_error(int err);
+keymaster_error_t trusty_keymaster_send(uint32_t command, const keymaster::Serializable& req,
+ keymaster::KeymasterResponse* rsp);
+#else
+TEEC_Result aml_keymaster_connect(TEEC_Context *c, TEEC_Session *s);
+TEEC_Result aml_keymaster_call(TEEC_Session *s, uint32_t cmd, void* in, uint32_t in_size, uint8_t* out,
+ uint32_t* out_size);
+TEEC_Result aml_keymaster_disconnect(TEEC_Context *c, TEEC_Session *s);
+keymaster_error_t translate_error(int err);
+keymaster_error_t aml_keymaster_send(TEEC_Session *s, uint32_t command, const keymaster::Serializable& req,
+ keymaster::KeymasterResponse* rsp);
+#endif
+
+__END_DECLS
+
+#endif // TRUSTY_KEYMASTER_AMLOGIC_KEYMASTER_IPC_H_
diff --git a/keymaster_ipc.h b/include/amlogic_keymaster/ipc/keymaster_ipc.h
index 1bbf2c7..9b6416d 100644..100755
--- a/keymaster_ipc.h
+++ b/include/amlogic_keymaster/ipc/keymaster_ipc.h
@@ -21,16 +21,17 @@
#define KEYMASTER_PORT "com.android.trusty.keymaster"
#define KEYMASTER_MAX_BUFFER_LENGTH 4096
+#if AMLOGIC_MODIFY
/* This UUID is generated with uuidgen
the ITU-T UUID generator at http://www.itu.int/ITU-T/asn1/uuid.html */
#define TA_KEYMASTER_UUID {0x8efb1e1c, 0x37e5, 0x4326, \
{ 0xa5, 0xd6, 0x8c, 0x33, 0x72, 0x6c, 0x7d, 0x57} }
-
+#endif
// Commands
enum keymaster_command : uint32_t {
KEYMASTER_RESP_BIT = 1,
- KEYMASTER_STOP_BIT = 2,
- KEYMASTER_REQ_SHIFT = 2,
+ KEYMASTER_STOP_BIT = 2,
+ KEYMASTER_REQ_SHIFT = 2,
KM_GENERATE_KEY = (0 << KEYMASTER_REQ_SHIFT),
KM_BEGIN_OPERATION = (1 << KEYMASTER_REQ_SHIFT),
@@ -51,13 +52,21 @@ enum keymaster_command : uint32_t {
KM_ATTEST_KEY = (16 << KEYMASTER_REQ_SHIFT),
KM_UPGRADE_KEY = (17 << KEYMASTER_REQ_SHIFT),
KM_CONFIGURE = (18 << KEYMASTER_REQ_SHIFT),
-
+ KM_GET_HMAC_SHARING_PARAMETERS = (19 << KEYMASTER_REQ_SHIFT),
+ KM_COMPUTE_SHARED_HMAC = (20 << KEYMASTER_REQ_SHIFT),
+ KM_VERIFY_AUTHORIZATION = (21 << KEYMASTER_REQ_SHIFT),
+ KM_DELETE_KEY = (22 << KEYMASTER_REQ_SHIFT),
+ KM_DELETE_ALL_KEYS = (23 << KEYMASTER_REQ_SHIFT),
+ KM_DESTROY_ATTESTATION_IDS = (24 << KEYMASTER_REQ_SHIFT),
+ KM_IMPORT_WRAPPED_KEY = (25 << KEYMASTER_REQ_SHIFT),
KM_SET_BOOT_PARAMS = (0x1000 << KEYMASTER_REQ_SHIFT),
KM_SET_ATTESTATION_KEY = (0x2000 << KEYMASTER_REQ_SHIFT),
KM_APPEND_ATTESTATION_CERT_CHAIN = (0x3000 << KEYMASTER_REQ_SHIFT),
+#if AMLOGIC_MODIFY
KM_TA_INIT = (0x10000 << KEYMASTER_REQ_SHIFT),
KM_TA_TERM = (0x10001 << KEYMASTER_REQ_SHIFT),
+#endif
};
#ifdef __ANDROID__
diff --git a/ipc/amlogic_keymaster_ipc.cpp b/ipc/amlogic_keymaster_ipc.cpp
new file mode 100755
index 0000000..00e2d26
--- a/dev/null
+++ b/ipc/amlogic_keymaster_ipc.cpp
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#define LOG_TAG "AmlogicKeymaster"
+
+// TODO: make this generic in libtrusty
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+#include <algorithm>
+
+#include <log/log.h>
+#if !AMLOGIC_MODIFY
+#include <trusty/tipc.h>
+#endif
+#include <amlogic_keymaster/ipc/keymaster_ipc.h>
+#include <amlogic_keymaster/ipc/amlogic_keymaster_ipc.h>
+
+#if AMLOGIC_MODIFY
+TEEC_Result aml_keymaster_connect(TEEC_Context *c, TEEC_Session *s) {
+ TEEC_Result result = TEEC_SUCCESS;
+ TEEC_UUID svc_id = TA_KEYMASTER_UUID;
+ TEEC_Operation operation;
+ uint32_t err_origin;
+ struct timespec time;
+ uint64_t millis = 0;
+
+ memset(&operation, 0, sizeof(operation));
+
+ /* Initialize Context */
+ result = TEEC_InitializeContext(NULL, c);
+
+ if (result != TEEC_SUCCESS) {
+ ALOGD("TEEC_InitializeContext failed with error = %x\n", result);
+ return result;
+ }
+ /* Open Session */
+ result = TEEC_OpenSession(c, s, &svc_id,
+ TEEC_LOGIN_PUBLIC,
+ NULL, NULL,
+ &err_origin);
+
+ if (result != TEEC_SUCCESS) {
+ ALOGD("TEEC_Opensession failed with code 0x%x origin 0x%x",result, err_origin);
+ TEEC_FinalizeContext(c);
+ return result;
+ }
+
+ int res = clock_gettime(CLOCK_BOOTTIME, &time);
+ if (res < 0)
+ millis = 0;
+ else
+ millis = (time.tv_sec * 1000) + (time.tv_nsec / 1000 / 1000);
+
+ /* Init TA */
+ operation.paramTypes = TEEC_PARAM_TYPES(
+ TEEC_VALUE_INPUT, TEEC_NONE,
+ TEEC_NONE, TEEC_NONE);
+
+ operation.params[0].value.a = (millis >> 32);
+ operation.params[0].value.b = (millis & 0xffffffff);
+
+ result = TEEC_InvokeCommand(s,
+ KM_TA_INIT,
+ &operation,
+ NULL);
+
+ ALOGD("create id: %d, ctx: %p, ctx: %p\n", s->session_id, s->ctx, c);
+ return result;
+}
+
+TEEC_Result aml_keymaster_call(TEEC_Session *s, uint32_t cmd, void* in, uint32_t in_size, uint8_t* out,
+ uint32_t* out_size) {
+ TEEC_Result res = TEEC_SUCCESS;
+ TEEC_Operation op;
+ uint32_t ret_orig;
+
+ memset(&op, 0, sizeof(op));
+
+ op.params[0].tmpref.buffer = in;
+ op.params[0].tmpref.size = in_size;
+ op.params[1].tmpref.buffer = out;
+ op.params[1].tmpref.size = *out_size;
+ op.paramTypes = TEEC_PARAM_TYPES(
+ TEEC_MEMREF_TEMP_INPUT,
+ TEEC_MEMREF_TEMP_OUTPUT,
+ TEEC_VALUE_OUTPUT,
+ TEEC_NONE);
+
+ ALOGD("id: %d, ctx: %p, cmd: %d\n", s->session_id, s->ctx, cmd);
+ res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig);
+ if (res != TEEC_SUCCESS) {
+ ALOGE("Invoke cmd: %u failed with res(%x), ret_orig(%x), return(%d)\n",
+ cmd, res, ret_orig, op.params[2].value.a);
+ } else {
+ *out_size = op.params[2].value.b;
+ }
+
+ return res;
+}
+
+TEEC_Result aml_keymaster_disconnect(TEEC_Context *c, TEEC_Session *s) {
+ TEEC_Operation operation;
+ TEEC_Result result = TEEC_SUCCESS;
+
+ operation.paramTypes = TEEC_PARAM_TYPES(
+ TEEC_NONE, TEEC_NONE,
+ TEEC_NONE, TEEC_NONE);
+
+ result = TEEC_InvokeCommand(s,
+ KM_TA_TERM,
+ &operation,
+ NULL);
+
+ TEEC_CloseSession(s);
+ TEEC_FinalizeContext(c);
+
+ return result;
+}
+
+keymaster_error_t aml_keymaster_send(TEEC_Session *s, uint32_t command, const keymaster::Serializable& req,
+ keymaster::KeymasterResponse* rsp) {
+ uint32_t req_size = req.SerializedSize();
+ if (req_size > AMLOGIC_KEYMASTER_SEND_BUF_SIZE) {
+ ALOGE("Request too big: %u Max size: %u", req_size, AMLOGIC_KEYMASTER_SEND_BUF_SIZE);
+ return KM_ERROR_INVALID_INPUT_LENGTH;
+ }
+
+ uint8_t send_buf[AMLOGIC_KEYMASTER_SEND_BUF_SIZE];
+ keymaster::Eraser send_buf_eraser(send_buf, AMLOGIC_KEYMASTER_SEND_BUF_SIZE);
+ req.Serialize(send_buf, send_buf + req_size);
+
+ // Send it
+ uint8_t recv_buf[AMLOGIC_KEYMASTER_RECV_BUF_SIZE];
+ keymaster::Eraser recv_buf_eraser(recv_buf, AMLOGIC_KEYMASTER_RECV_BUF_SIZE);
+ uint32_t rsp_size = AMLOGIC_KEYMASTER_RECV_BUF_SIZE;
+ int rc = aml_keymaster_call(s, command, send_buf, req_size, recv_buf, &rsp_size);
+ if (rc < 0) {
+ ALOGE("tipc error: %d\n", rc);
+ // TODO(swillden): Distinguish permanent from transient errors and set error_ appropriately.
+ return translate_error(rc);
+ } else {
+ ALOGD("Received %d byte response\n", rsp_size);
+ }
+
+ const keymaster_message* msg = (keymaster_message*)recv_buf;
+ const uint8_t* p = msg->payload;
+
+ if (!rsp->Deserialize(&p, p + rsp_size)) {
+ ALOGE("Error deserializing response of size %d\n", (int)rsp_size);
+ return KM_ERROR_UNKNOWN_ERROR;
+ } else if (rsp->error != KM_ERROR_OK) {
+ ALOGE("Response of size %d contained error code %d\n", (int)rsp_size, (int)rsp->error);
+ return rsp->error;
+ }
+ return rsp->error;
+}
+#else
+#define TRUSTY_DEVICE_NAME "/dev/trusty-ipc-dev0"
+
+static int handle_ = -1;
+
+int trusty_keymaster_connect() {
+ int rc = tipc_connect(TRUSTY_DEVICE_NAME, KEYMASTER_PORT);
+ if (rc < 0) {
+ return rc;
+ }
+
+ handle_ = rc;
+ return 0;
+}
+
+int trusty_keymaster_call(uint32_t cmd, void* in, uint32_t in_size, uint8_t* out,
+ uint32_t* out_size) {
+ if (handle_ < 0) {
+ ALOGE("not connected\n");
+ return -EINVAL;
+ }
+
+ size_t msg_size = in_size + sizeof(struct keymaster_message);
+ struct keymaster_message* msg = reinterpret_cast<struct keymaster_message*>(malloc(msg_size));
+ if (!msg) {
+ ALOGE("failed to allocate msg buffer\n");
+ return -EINVAL;
+ }
+
+ msg->cmd = cmd;
+ memcpy(msg->payload, in, in_size);
+
+ ssize_t rc = write(handle_, msg, msg_size);
+ free(msg);
+
+ if (rc < 0) {
+ ALOGE("failed to send cmd (%d) to %s: %s\n", cmd, KEYMASTER_PORT, strerror(errno));
+ return -errno;
+ }
+ size_t out_max_size = *out_size;
+ *out_size = 0;
+ struct iovec iov[2];
+ struct keymaster_message header;
+ iov[0] = {.iov_base = &header, .iov_len = sizeof(struct keymaster_message)};
+ while (true) {
+ iov[1] = {.iov_base = out + *out_size,
+ .iov_len = std::min<uint32_t>(KEYMASTER_MAX_BUFFER_LENGTH,
+ out_max_size - *out_size)};
+ rc = readv(handle_, iov, 2);
+ if (rc < 0) {
+ ALOGE("failed to retrieve response for cmd (%d) to %s: %s\n", cmd, KEYMASTER_PORT,
+ strerror(errno));
+ return -errno;
+ }
+
+ if ((size_t)rc < sizeof(struct keymaster_message)) {
+ ALOGE("invalid response size (%d)\n", (int)rc);
+ return -EINVAL;
+ }
+
+ if ((cmd | KEYMASTER_RESP_BIT) != (header.cmd & ~(KEYMASTER_STOP_BIT))) {
+ ALOGE("invalid command (%d)", header.cmd);
+ return -EINVAL;
+ }
+ *out_size += ((size_t)rc - sizeof(struct keymaster_message));
+ if (header.cmd & KEYMASTER_STOP_BIT) {
+ break;
+ }
+ }
+
+ return rc;
+}
+
+void trusty_keymaster_disconnect() {
+ if (handle_ >= 0) {
+ tipc_close(handle_);
+ }
+ handle_ = -1;
+}
+
+#endif // AMLOGIC_MODIFY
+keymaster_error_t translate_error(int err) {
+ switch (err) {
+ case 0:
+ return KM_ERROR_OK;
+ case -EPERM:
+ case -EACCES:
+ return KM_ERROR_SECURE_HW_ACCESS_DENIED;
+
+ case -ECANCELED:
+ return KM_ERROR_OPERATION_CANCELLED;
+
+ case -ENODEV:
+ return KM_ERROR_UNIMPLEMENTED;
+
+ case -ENOMEM:
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+ case -EBUSY:
+ return KM_ERROR_SECURE_HW_BUSY;
+
+ case -EIO:
+ return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
+
+ case -EOVERFLOW:
+ return KM_ERROR_INVALID_INPUT_LENGTH;
+
+ default:
+ return KM_ERROR_UNKNOWN_ERROR;
+ }
+}
+#if !AMLOGIC_MODIFY
+keymaster_error_t trusty_keymaster_send(uint32_t command, const keymaster::Serializable& req,
+ keymaster::KeymasterResponse* rsp) {
+ uint32_t req_size = req.SerializedSize();
+ if (req_size > TRUSTY_KEYMASTER_SEND_BUF_SIZE) {
+ ALOGE("Request too big: %u Max size: %u", req_size, TRUSTY_KEYMASTER_SEND_BUF_SIZE);
+ return KM_ERROR_INVALID_INPUT_LENGTH;
+ }
+
+ uint8_t send_buf[TRUSTY_KEYMASTER_SEND_BUF_SIZE];
+ keymaster::Eraser send_buf_eraser(send_buf, TRUSTY_KEYMASTER_SEND_BUF_SIZE);
+ req.Serialize(send_buf, send_buf + req_size);
+
+ // Send it
+ uint8_t recv_buf[TRUSTY_KEYMASTER_RECV_BUF_SIZE];
+ keymaster::Eraser recv_buf_eraser(recv_buf, TRUSTY_KEYMASTER_RECV_BUF_SIZE);
+ uint32_t rsp_size = TRUSTY_KEYMASTER_RECV_BUF_SIZE;
+ int rc = trusty_keymaster_call(command, send_buf, req_size, recv_buf, &rsp_size);
+ if (rc < 0) {
+ // Reset the connection on tipc error
+ trusty_keymaster_disconnect();
+ trusty_keymaster_connect();
+ ALOGE("tipc error: %d\n", rc);
+ // TODO(swillden): Distinguish permanent from transient errors and set error_ appropriately.
+ return translate_error(rc);
+ } else {
+ ALOGV("Received %d byte response\n", rsp_size);
+ }
+
+ const uint8_t* p = recv_buf;
+ if (!rsp->Deserialize(&p, p + rsp_size)) {
+ ALOGE("Error deserializing response of size %d\n", (int)rsp_size);
+ return KM_ERROR_UNKNOWN_ERROR;
+ } else if (rsp->error != KM_ERROR_OK) {
+ ALOGE("Response of size %d contained error code %d\n", (int)rsp_size, (int)rsp->error);
+ return rsp->error;
+ }
+ return rsp->error;
+}
+#endif //!AMLOGIC_MODIFY
diff --git a/module.cpp b/module.cpp
deleted file mode 100644
index b9ee918..0000000
--- a/module.cpp
+++ b/dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-#include <errno.h>
-#include <string.h>
-
-#include <hardware/hardware.h>
-#include <hardware/keymaster0.h>
-
-#include "aml_keymaster_device.h"
-
-using keymaster::AmlKeymasterDevice;
-
-/*
- * Generic device handling
- */
-static int aml_keymaster_open(const hw_module_t* module, const char* name, hw_device_t** device) {
- if (strcmp(name, KEYSTORE_KEYMASTER) != 0) {
- return -EINVAL;
- }
-
- AmlKeymasterDevice* dev = new AmlKeymasterDevice(module);
- if (dev == NULL) {
- return -ENOMEM;
- }
- *device = dev->hw_device();
- // Do not delete dev; it will get cleaned up when the caller calls device->close(), and must
- // exist until then.
- return 0;
-}
-
-static struct hw_module_methods_t keystore_module_methods = {
- .open = aml_keymaster_open,
-};
-
-struct keystore_module HAL_MODULE_INFO_SYM __attribute__((visibility("default"))) = {
- .common =
- {
- .tag = HARDWARE_MODULE_TAG,
- .module_api_version = KEYMASTER_MODULE_API_VERSION_2_0,
- .hal_api_version = HARDWARE_HAL_API_VERSION,
- .id = KEYSTORE_HARDWARE_MODULE_ID,
- .name = "Amlogic Keymaster HAL",
- .author = "Amlogic Inc.",
- .methods = &keystore_module_methods,
- .dso = 0,
- .reserved = {},
- },
-};
diff --git a/unit_test/android_keymaster_messages_test.cpp b/unit_test/android_keymaster_messages_test.cpp
deleted file mode 100644
index f7e65bc..0000000
--- a/unit_test/android_keymaster_messages_test.cpp
+++ b/dev/null
@@ -1,732 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#include <UniquePtr.h>
-
-#include <gtest/gtest.h>
-
-#include <keymaster/android_keymaster.h>
-#include <keymaster/android_keymaster_utils.h>
-#include <keymaster/keymaster_tags.h>
-
-#include "android_keymaster_test_utils.h"
-
-namespace keymaster {
-namespace test {
-
-/**
- * Serialize and deserialize a message.
- */
-template <typename Message>
-Message* round_trip(int32_t ver, const Message& message, size_t expected_size) {
- size_t size = message.SerializedSize();
- EXPECT_EQ(expected_size, size);
- if (size == 0)
- return NULL;
-
- UniquePtr<uint8_t[]> buf(new uint8_t[size]);
- EXPECT_EQ(buf.get() + size, message.Serialize(buf.get(), buf.get() + size));
-
- Message* deserialized = new Message(ver);
- const uint8_t* p = buf.get();
- EXPECT_TRUE(deserialized->Deserialize(&p, p + size));
- EXPECT_EQ((ptrdiff_t)size, p - buf.get());
- return deserialized;
-}
-
-struct EmptyKeymasterResponse : public KeymasterResponse {
- explicit EmptyKeymasterResponse(int32_t ver) : KeymasterResponse(ver) {}
- size_t NonErrorSerializedSize() const { return 1; }
- uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* /* end */) const {
- *buf++ = 0;
- return buf;
- }
- bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) {
- if (*buf_ptr >= end)
- return false;
- EXPECT_EQ(0, **buf_ptr);
- (*buf_ptr)++;
- return true;
- }
-};
-
-TEST(RoundTrip, EmptyKeymasterResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- EmptyKeymasterResponse msg(ver);
- msg.error = KM_ERROR_OK;
-
- UniquePtr<EmptyKeymasterResponse> deserialized(round_trip(ver, msg, 5));
- }
-}
-
-TEST(RoundTrip, EmptyKeymasterResponseError) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- EmptyKeymasterResponse msg(ver);
- msg.error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- UniquePtr<EmptyKeymasterResponse> deserialized(round_trip(ver, msg, 4));
- }
-}
-
-TEST(RoundTrip, SupportedByAlgorithmRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- SupportedByAlgorithmRequest req(ver);
- req.algorithm = KM_ALGORITHM_EC;
-
- UniquePtr<SupportedByAlgorithmRequest> deserialized(round_trip(ver, req, 4));
- EXPECT_EQ(KM_ALGORITHM_EC, deserialized->algorithm);
- }
-}
-
-TEST(RoundTrip, SupportedByAlgorithmAndPurposeRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- SupportedByAlgorithmAndPurposeRequest req(ver);
- req.algorithm = KM_ALGORITHM_EC;
- req.purpose = KM_PURPOSE_DECRYPT;
-
- UniquePtr<SupportedByAlgorithmAndPurposeRequest> deserialized(round_trip(ver, req, 8));
- EXPECT_EQ(KM_ALGORITHM_EC, deserialized->algorithm);
- EXPECT_EQ(KM_PURPOSE_DECRYPT, deserialized->purpose);
- }
-}
-
-TEST(RoundTrip, SupportedResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- SupportedResponse<keymaster_digest_t> rsp(ver);
- keymaster_digest_t digests[] = {KM_DIGEST_NONE, KM_DIGEST_MD5, KM_DIGEST_SHA1};
- rsp.error = KM_ERROR_OK;
- rsp.SetResults(digests);
-
- UniquePtr<SupportedResponse<keymaster_digest_t>> deserialized(round_trip(ver, rsp, 20));
- EXPECT_EQ(array_length(digests), deserialized->results_length);
- EXPECT_EQ(0, memcmp(deserialized->results, digests, array_size(digests)));
- }
-}
-
-static keymaster_key_param_t params[] = {
- Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
- Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
- Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA),
- Authorization(TAG_USER_ID, 7),
- Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD),
- Authorization(TAG_APPLICATION_ID, "app_id", 6),
- Authorization(TAG_AUTH_TIMEOUT, 300),
-};
-uint8_t TEST_DATA[] = "a key blob";
-
-TEST(RoundTrip, GenerateKeyRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- GenerateKeyRequest req(ver);
- req.key_description.Reinitialize(params, array_length(params));
- UniquePtr<GenerateKeyRequest> deserialized(round_trip(ver, req, 78));
- EXPECT_EQ(deserialized->key_description, req.key_description);
- }
-}
-
-TEST(RoundTrip, GenerateKeyResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- GenerateKeyResponse rsp(ver);
- rsp.error = KM_ERROR_OK;
- rsp.key_blob.key_material = dup_array(TEST_DATA);
- rsp.key_blob.key_material_size = array_length(TEST_DATA);
- rsp.enforced.Reinitialize(params, array_length(params));
-
- UniquePtr<GenerateKeyResponse> deserialized(round_trip(ver, rsp, 109));
- EXPECT_EQ(KM_ERROR_OK, deserialized->error);
- EXPECT_EQ(deserialized->enforced, rsp.enforced);
- EXPECT_EQ(deserialized->unenforced, rsp.unenforced);
- }
-}
-
-TEST(RoundTrip, GenerateKeyResponseTestError) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- GenerateKeyResponse rsp(ver);
- rsp.error = KM_ERROR_UNSUPPORTED_ALGORITHM;
- rsp.key_blob.key_material = dup_array(TEST_DATA);
- rsp.key_blob.key_material_size = array_length(TEST_DATA);
- rsp.enforced.Reinitialize(params, array_length(params));
-
- UniquePtr<GenerateKeyResponse> deserialized(round_trip(ver, rsp, 4));
- EXPECT_EQ(KM_ERROR_UNSUPPORTED_ALGORITHM, deserialized->error);
- EXPECT_EQ(0U, deserialized->enforced.size());
- EXPECT_EQ(0U, deserialized->unenforced.size());
- EXPECT_EQ(0U, deserialized->key_blob.key_material_size);
- }
-}
-
-TEST(RoundTrip, GetKeyCharacteristicsRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- GetKeyCharacteristicsRequest req(ver);
- req.additional_params.Reinitialize(params, array_length(params));
- req.SetKeyMaterial("foo", 3);
-
- UniquePtr<GetKeyCharacteristicsRequest> deserialized(round_trip(ver, req, 85));
- EXPECT_EQ(7U, deserialized->additional_params.size());
- EXPECT_EQ(3U, deserialized->key_blob.key_material_size);
- EXPECT_EQ(0, memcmp(deserialized->key_blob.key_material, "foo", 3));
- }
-}
-
-TEST(RoundTrip, GetKeyCharacteristicsResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- GetKeyCharacteristicsResponse msg(ver);
- msg.error = KM_ERROR_OK;
- msg.enforced.Reinitialize(params, array_length(params));
- msg.unenforced.Reinitialize(params, array_length(params));
-
- UniquePtr<GetKeyCharacteristicsResponse> deserialized(round_trip(ver, msg, 160));
- EXPECT_EQ(msg.enforced, deserialized->enforced);
- EXPECT_EQ(msg.unenforced, deserialized->unenforced);
- }
-}
-
-TEST(RoundTrip, BeginOperationRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- BeginOperationRequest msg(ver);
- msg.purpose = KM_PURPOSE_SIGN;
- msg.SetKeyMaterial("foo", 3);
- msg.additional_params.Reinitialize(params, array_length(params));
-
- UniquePtr<BeginOperationRequest> deserialized(round_trip(ver, msg, 89));
- EXPECT_EQ(KM_PURPOSE_SIGN, deserialized->purpose);
- EXPECT_EQ(3U, deserialized->key_blob.key_material_size);
- EXPECT_EQ(0, memcmp(deserialized->key_blob.key_material, "foo", 3));
- EXPECT_EQ(msg.additional_params, deserialized->additional_params);
- }
-}
-
-TEST(RoundTrip, BeginOperationResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- BeginOperationResponse msg(ver);
- msg.error = KM_ERROR_OK;
- msg.op_handle = 0xDEADBEEF;
- msg.output_params.push_back(Authorization(TAG_NONCE, "foo", 3));
-
- UniquePtr<BeginOperationResponse> deserialized;
- switch (ver) {
- case 0:
- deserialized.reset(round_trip(ver, msg, 12));
- break;
- case 1:
- case 2:
- case 3:
- deserialized.reset(round_trip(ver, msg, 39));
- break;
- default:
- FAIL();
- }
-
- EXPECT_EQ(KM_ERROR_OK, deserialized->error);
- EXPECT_EQ(0xDEADBEEF, deserialized->op_handle);
-
- switch (ver) {
- case 0:
- EXPECT_EQ(0U, deserialized->output_params.size());
- break;
- case 1:
- case 2:
- case 3:
- EXPECT_EQ(msg.output_params, deserialized->output_params);
- break;
- default:
- FAIL();
- }
- }
-}
-
-TEST(RoundTrip, BeginOperationResponseError) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- BeginOperationResponse msg(ver);
- msg.error = KM_ERROR_INVALID_OPERATION_HANDLE;
- msg.op_handle = 0xDEADBEEF;
-
- UniquePtr<BeginOperationResponse> deserialized(round_trip(ver, msg, 4));
- EXPECT_EQ(KM_ERROR_INVALID_OPERATION_HANDLE, deserialized->error);
- }
-}
-
-TEST(RoundTrip, UpdateOperationRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- UpdateOperationRequest msg(ver);
- msg.op_handle = 0xDEADBEEF;
- msg.input.Reinitialize("foo", 3);
-
- UniquePtr<UpdateOperationRequest> deserialized;
- switch (ver) {
- case 0:
- deserialized.reset(round_trip(ver, msg, 15));
- break;
- case 1:
- case 2:
- case 3:
- deserialized.reset(round_trip(ver, msg, 27));
- break;
- default:
- FAIL();
- }
- EXPECT_EQ(3U, deserialized->input.available_read());
- EXPECT_EQ(0, memcmp(deserialized->input.peek_read(), "foo", 3));
- }
-}
-
-TEST(RoundTrip, UpdateOperationResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- UpdateOperationResponse msg(ver);
- msg.error = KM_ERROR_OK;
- msg.output.Reinitialize("foo", 3);
- msg.input_consumed = 99;
- msg.output_params.push_back(TAG_APPLICATION_ID, "bar", 3);
-
- UniquePtr<UpdateOperationResponse> deserialized;
- switch (ver) {
- case 0:
- deserialized.reset(round_trip(ver, msg, 11));
- break;
- case 1:
- deserialized.reset(round_trip(ver, msg, 15));
- break;
- case 2:
- case 3:
- deserialized.reset(round_trip(ver, msg, 42));
- break;
- default:
- FAIL();
- }
- EXPECT_EQ(KM_ERROR_OK, deserialized->error);
- EXPECT_EQ(3U, deserialized->output.available_read());
- EXPECT_EQ(0, memcmp(deserialized->output.peek_read(), "foo", 3));
-
- switch (ver) {
- case 0:
- EXPECT_EQ(0U, deserialized->input_consumed);
- break;
- case 1:
- EXPECT_EQ(99U, deserialized->input_consumed);
- break;
- case 2:
- case 3:
- EXPECT_EQ(99U, deserialized->input_consumed);
- EXPECT_EQ(1U, deserialized->output_params.size());
- break;
- default:
- FAIL();
- }
- }
-}
-
-TEST(RoundTrip, FinishOperationRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- FinishOperationRequest msg(ver);
- msg.op_handle = 0xDEADBEEF;
- msg.signature.Reinitialize("bar", 3);
- msg.input.Reinitialize("baz", 3);
-
- UniquePtr<FinishOperationRequest> deserialized;
- switch (ver) {
- case 0:
- deserialized.reset(round_trip(ver, msg, 15));
- break;
- case 1:
- case 2:
- deserialized.reset(round_trip(ver, msg, 27));
- break;
- case 3:
- deserialized.reset(round_trip(ver, msg, 34));
- break;
- default:
- FAIL();
- }
- EXPECT_EQ(0xDEADBEEF, deserialized->op_handle);
- EXPECT_EQ(3U, deserialized->signature.available_read());
- EXPECT_EQ(0, memcmp(deserialized->signature.peek_read(), "bar", 3));
- }
-}
-
-TEST(Round_Trip, FinishOperationResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- FinishOperationResponse msg(ver);
- msg.error = KM_ERROR_OK;
- msg.output.Reinitialize("foo", 3);
-
- UniquePtr<FinishOperationResponse> deserialized;
- switch (ver) {
- case 0:
- case 1:
- deserialized.reset(round_trip(ver, msg, 11));
- break;
- case 2:
- case 3:
- deserialized.reset(round_trip(ver, msg, 23));
- break;
- default:
- FAIL();
- }
- EXPECT_EQ(msg.error, deserialized->error);
- EXPECT_EQ(msg.output.available_read(), deserialized->output.available_read());
- EXPECT_EQ(0, memcmp(msg.output.peek_read(), deserialized->output.peek_read(),
- msg.output.available_read()));
- }
-}
-
-TEST(RoundTrip, ImportKeyRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- ImportKeyRequest msg(ver);
- msg.key_description.Reinitialize(params, array_length(params));
- msg.key_format = KM_KEY_FORMAT_X509;
- msg.SetKeyMaterial("foo", 3);
-
- UniquePtr<ImportKeyRequest> deserialized(round_trip(ver, msg, 89));
- EXPECT_EQ(msg.key_description, deserialized->key_description);
- EXPECT_EQ(msg.key_format, deserialized->key_format);
- EXPECT_EQ(msg.key_data_length, deserialized->key_data_length);
- EXPECT_EQ(0, memcmp(msg.key_data, deserialized->key_data, msg.key_data_length));
- }
-}
-
-TEST(RoundTrip, ImportKeyResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- ImportKeyResponse msg(ver);
- msg.error = KM_ERROR_OK;
- msg.SetKeyMaterial("foo", 3);
- msg.enforced.Reinitialize(params, array_length(params));
- msg.unenforced.Reinitialize(params, array_length(params));
-
- UniquePtr<ImportKeyResponse> deserialized(round_trip(ver, msg, 167));
- EXPECT_EQ(msg.error, deserialized->error);
- EXPECT_EQ(msg.key_blob.key_material_size, deserialized->key_blob.key_material_size);
- EXPECT_EQ(0, memcmp(msg.key_blob.key_material, deserialized->key_blob.key_material,
- msg.key_blob.key_material_size));
- EXPECT_EQ(msg.enforced, deserialized->enforced);
- EXPECT_EQ(msg.unenforced, deserialized->unenforced);
- }
-}
-
-TEST(RoundTrip, ExportKeyRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- ExportKeyRequest msg(ver);
- msg.additional_params.Reinitialize(params, array_length(params));
- msg.key_format = KM_KEY_FORMAT_X509;
- msg.SetKeyMaterial("foo", 3);
-
- UniquePtr<ExportKeyRequest> deserialized(round_trip(ver, msg, 89));
- EXPECT_EQ(msg.additional_params, deserialized->additional_params);
- EXPECT_EQ(msg.key_format, deserialized->key_format);
- EXPECT_EQ(3U, deserialized->key_blob.key_material_size);
- EXPECT_EQ(0, memcmp("foo", deserialized->key_blob.key_material, 3));
- }
-}
-
-TEST(RoundTrip, ExportKeyResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- ExportKeyResponse msg(ver);
- msg.error = KM_ERROR_OK;
- msg.SetKeyMaterial("foo", 3);
-
- UniquePtr<ExportKeyResponse> deserialized(round_trip(ver, msg, 11));
- EXPECT_EQ(3U, deserialized->key_data_length);
- EXPECT_EQ(0, memcmp("foo", deserialized->key_data, 3));
- }
-}
-
-TEST(RoundTrip, DeleteKeyRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- DeleteKeyRequest msg(ver);
- msg.SetKeyMaterial("foo", 3);
-
- UniquePtr<DeleteKeyRequest> deserialized(round_trip(ver, msg, 7));
- EXPECT_EQ(3U, deserialized->key_blob.key_material_size);
- EXPECT_EQ(0, memcmp("foo", deserialized->key_blob.key_material, 3));
- }
-}
-
-TEST(RoundTrip, DeleteKeyResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- DeleteKeyResponse msg(ver);
- UniquePtr<DeleteKeyResponse> deserialized(round_trip(ver, msg, 4));
- }
-}
-
-TEST(RoundTrip, DeleteAllKeysRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- DeleteAllKeysRequest msg(ver);
- UniquePtr<DeleteAllKeysRequest> deserialized(round_trip(ver, msg, 0));
- }
-}
-
-TEST(RoundTrip, DeleteAllKeysResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- DeleteAllKeysResponse msg(ver);
- UniquePtr<DeleteAllKeysResponse> deserialized(round_trip(ver, msg, 4));
- }
-}
-
-TEST(RoundTrip, GetVersionRequest) {
- GetVersionRequest msg;
-
- size_t size = msg.SerializedSize();
- ASSERT_EQ(0U, size);
-
- UniquePtr<uint8_t[]> buf(new uint8_t[size]);
- EXPECT_EQ(buf.get() + size, msg.Serialize(buf.get(), buf.get() + size));
-
- GetVersionRequest deserialized;
- const uint8_t* p = buf.get();
- EXPECT_TRUE(deserialized.Deserialize(&p, p + size));
- EXPECT_EQ((ptrdiff_t)size, p - buf.get());
-}
-
-TEST(RoundTrip, GetVersionResponse) {
- GetVersionResponse msg;
- msg.error = KM_ERROR_OK;
- msg.major_ver = 9;
- msg.minor_ver = 98;
- msg.subminor_ver = 38;
-
- size_t size = msg.SerializedSize();
- ASSERT_EQ(7U, size);
-
- UniquePtr<uint8_t[]> buf(new uint8_t[size]);
- EXPECT_EQ(buf.get() + size, msg.Serialize(buf.get(), buf.get() + size));
-
- GetVersionResponse deserialized;
- const uint8_t* p = buf.get();
- EXPECT_TRUE(deserialized.Deserialize(&p, p + size));
- EXPECT_EQ((ptrdiff_t)size, p - buf.get());
- EXPECT_EQ(9U, msg.major_ver);
- EXPECT_EQ(98U, msg.minor_ver);
- EXPECT_EQ(38U, msg.subminor_ver);
-}
-
-TEST(RoundTrip, ConfigureRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- ConfigureRequest req(ver);
- req.os_version = 1;
- req.os_patchlevel = 1;
-
- UniquePtr<ConfigureRequest> deserialized(round_trip(ver, req, 8));
- EXPECT_EQ(deserialized->os_version, req.os_version);
- EXPECT_EQ(deserialized->os_patchlevel, req.os_patchlevel);
- }
-}
-
-TEST(RoundTrip, ConfigureResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- ConfigureResponse rsp(ver);
- UniquePtr<ConfigureResponse> deserialized(round_trip(ver, rsp, 4));
- }
-}
-
-TEST(RoundTrip, AddEntropyRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- AddEntropyRequest msg(ver);
- msg.random_data.Reinitialize("foo", 3);
-
- UniquePtr<AddEntropyRequest> deserialized(round_trip(ver, msg, 7));
- EXPECT_EQ(3U, deserialized->random_data.available_read());
- EXPECT_EQ(0, memcmp("foo", deserialized->random_data.peek_read(), 3));
- }
-}
-
-TEST(RoundTrip, AddEntropyResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- AddEntropyResponse msg(ver);
- UniquePtr<AddEntropyResponse> deserialized(round_trip(ver, msg, 4));
- }
-}
-
-TEST(RoundTrip, AbortOperationRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- AbortOperationRequest msg(ver);
- UniquePtr<AbortOperationRequest> deserialized(round_trip(ver, msg, 8));
- }
-}
-
-TEST(RoundTrip, AbortOperationResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- AbortOperationResponse msg(ver);
- UniquePtr<AbortOperationResponse> deserialized(round_trip(ver, msg, 4));
- }
-}
-
-TEST(RoundTrip, AttestKeyRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- AttestKeyRequest msg(ver);
- msg.SetKeyMaterial("foo", 3);
- msg.attest_params.Reinitialize(params, array_length(params));
-
- UniquePtr<AttestKeyRequest> deserialized(round_trip(ver, msg, 85));
- EXPECT_EQ(3U, deserialized->key_blob.key_material_size);
- EXPECT_EQ(0, memcmp("foo", deserialized->key_blob.key_material, 3));
- EXPECT_EQ(msg.attest_params, deserialized->attest_params);
- }
-}
-
-TEST(RoundTrip, AttestKeyResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- AttestKeyResponse msg(ver);
- msg.error = KM_ERROR_OK;
- EXPECT_TRUE(msg.AllocateChain(3));
- msg.certificate_chain.entries[0] = {dup_buffer("foo", 3), 3};
- msg.certificate_chain.entries[1] = {dup_buffer("bar", 3), 3};
- msg.certificate_chain.entries[2] = {dup_buffer("baz", 3), 3};
-
- UniquePtr<AttestKeyResponse> deserialized(round_trip(ver, msg, 29));
- keymaster_cert_chain_t* chain = &deserialized->certificate_chain;
-
- EXPECT_NE(nullptr, chain->entries);
- EXPECT_EQ(3U, chain->entry_count);
- EXPECT_EQ(3U, chain->entries[0].data_length);
- EXPECT_EQ(0, memcmp("foo", chain->entries[0].data, 3));
- EXPECT_EQ(3U, chain->entries[1].data_length);
- EXPECT_EQ(0, memcmp("bar", chain->entries[1].data, 3));
- EXPECT_EQ(3U, chain->entries[2].data_length);
- EXPECT_EQ(0, memcmp("baz", chain->entries[2].data, 3));
- }
-}
-
-TEST(RoundTrip, UpgradeKeyRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- UpgradeKeyRequest msg(ver);
- msg.SetKeyMaterial("foo", 3);
- msg.upgrade_params.Reinitialize(params, array_length(params));
-
- UniquePtr<UpgradeKeyRequest> deserialized(round_trip(ver, msg, 85));
- EXPECT_EQ(3U, deserialized->key_blob.key_material_size);
- EXPECT_EQ(0, memcmp("foo", deserialized->key_blob.key_material, 3));
- EXPECT_EQ(msg.upgrade_params, deserialized->upgrade_params);
- }
-}
-
-TEST(RoundTrip, UpgradeKeyResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- UpgradeKeyResponse req(ver);
- req.error = KM_ERROR_OK;
- req.upgraded_key.key_material = dup_array(TEST_DATA);
- req.upgraded_key.key_material_size = array_length(TEST_DATA);
-
- UniquePtr<UpgradeKeyResponse> deserialized(round_trip(ver, req, 19));
- EXPECT_EQ(KM_ERROR_OK, deserialized->error);
- EXPECT_EQ(req.upgraded_key.key_material_size, deserialized->upgraded_key.key_material_size);
- EXPECT_EQ(0, memcmp(req.upgraded_key.key_material, deserialized->upgraded_key.key_material,
- req.upgraded_key.key_material_size));
- }
-}
-
-uint8_t msgbuf[] = {
- 220, 88, 183, 255, 71, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 173, 0, 0, 0, 228, 174, 98, 187, 191, 135, 253, 200, 51, 230, 114, 247, 151, 109,
- 237, 79, 87, 32, 94, 5, 204, 46, 154, 30, 91, 6, 103, 148, 254, 129, 65, 171, 228,
- 167, 224, 163, 9, 15, 206, 90, 58, 11, 205, 55, 211, 33, 87, 178, 149, 91, 28, 236,
- 218, 112, 231, 34, 82, 82, 134, 103, 137, 115, 27, 156, 102, 159, 220, 226, 89, 42, 25,
- 37, 9, 84, 239, 76, 161, 198, 72, 167, 163, 39, 91, 148, 191, 17, 191, 87, 169, 179,
- 136, 10, 194, 154, 4, 40, 107, 109, 61, 161, 20, 176, 247, 13, 214, 106, 229, 45, 17,
- 5, 60, 189, 64, 39, 166, 208, 14, 57, 25, 140, 148, 25, 177, 246, 189, 43, 181, 88,
- 204, 29, 126, 224, 100, 143, 93, 60, 57, 249, 55, 0, 87, 83, 227, 224, 166, 59, 214,
- 81, 144, 129, 58, 6, 57, 46, 254, 232, 41, 220, 209, 230, 167, 138, 158, 94, 180, 125,
- 247, 26, 162, 116, 238, 202, 187, 100, 65, 13, 180, 44, 245, 159, 83, 161, 176, 58, 72,
- 236, 109, 105, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 11, 0, 0, 0, 98, 0, 0, 0, 1, 0, 0, 32, 2, 0, 0, 0, 1, 0,
- 0, 32, 3, 0, 0, 0, 2, 0, 0, 16, 1, 0, 0, 0, 3, 0, 0, 48, 0,
- 1, 0, 0, 200, 0, 0, 80, 3, 0, 0, 0, 0, 0, 0, 0, 244, 1, 0, 112,
- 1, 246, 1, 0, 112, 1, 189, 2, 0, 96, 144, 178, 236, 250, 255, 255, 255, 255, 145,
- 1, 0, 96, 144, 226, 33, 60, 222, 2, 0, 0, 189, 2, 0, 96, 0, 0, 0, 0,
- 0, 0, 0, 0, 190, 2, 0, 16, 1, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 11, 0,
- 0, 0, 98, 0, 0, 0, 1, 0, 0, 32, 2, 0, 0, 0, 1, 0, 0, 32, 3,
- 0, 0, 0, 2, 0, 0, 16, 1, 0, 0, 0, 3, 0, 0, 48, 0, 1, 0, 0,
- 200, 0, 0, 80, 3, 0, 0, 0, 0, 0, 0, 0, 244, 1, 0, 112, 1, 246, 1,
- 0, 112, 1, 189, 2, 0, 96, 144, 178, 236, 250, 255, 255, 255, 255, 145, 1, 0, 96,
- 144, 226, 33, 60, 222, 2, 0, 0, 189, 2, 0, 96, 0, 0, 0, 0, 0, 0, 0,
- 0, 190, 2, 0, 16, 1, 0, 0, 0,
-};
-
-/*
- * These tests don't have any assertions or expectations. They just try to parse garbage, to see if
- * the result will be a crash. This is especially informative when run under Valgrind memcheck.
- */
-
-template <typename Message> void parse_garbage() {
- for (int32_t ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- Message msg(ver);
- const uint8_t* end = msgbuf + array_length(msgbuf);
- for (size_t i = 0; i < array_length(msgbuf); ++i) {
- const uint8_t* begin = msgbuf + i;
- const uint8_t* p = begin;
- msg.Deserialize(&p, end);
- }
- }
-
- time_t now = time(NULL);
- std::cout << "Seeding rand() with " << now << " for fuzz test." << std::endl;
- srand(now);
-
- // Fill large buffer with random bytes.
- const int kBufSize = 10000;
- UniquePtr<uint8_t[]> buf(new uint8_t[kBufSize]);
- for (size_t i = 0; i < kBufSize; ++i)
- buf[i] = static_cast<uint8_t>(rand());
-
- for (uint32_t ver = 0; ver < MAX_MESSAGE_VERSION; ++ver) {
- Message msg(ver);
- const uint8_t* end = buf.get() + kBufSize;
- for (size_t i = 0; i < kBufSize; ++i) {
- const uint8_t* begin = buf.get() + i;
- const uint8_t* p = begin;
- msg.Deserialize(&p, end);
- }
- }
-}
-#if 0
-#define GARBAGE_TEST(Message) \
- TEST(GarbageTest, Message) { parse_garbage<Message>(); }
-
-GARBAGE_TEST(AbortOperationRequest);
-GARBAGE_TEST(AbortOperationResponse);
-GARBAGE_TEST(AddEntropyRequest);
-GARBAGE_TEST(AddEntropyResponse);
-GARBAGE_TEST(BeginOperationRequest);
-GARBAGE_TEST(BeginOperationResponse);
-GARBAGE_TEST(DeleteAllKeysRequest);
-GARBAGE_TEST(DeleteAllKeysResponse);
-GARBAGE_TEST(DeleteKeyRequest);
-GARBAGE_TEST(DeleteKeyResponse);
-GARBAGE_TEST(ExportKeyRequest);
-GARBAGE_TEST(ExportKeyResponse);
-GARBAGE_TEST(FinishOperationRequest);
-GARBAGE_TEST(FinishOperationResponse);
-GARBAGE_TEST(GenerateKeyRequest);
-GARBAGE_TEST(GenerateKeyResponse);
-GARBAGE_TEST(GetKeyCharacteristicsRequest);
-GARBAGE_TEST(GetKeyCharacteristicsResponse);
-GARBAGE_TEST(ImportKeyRequest);
-GARBAGE_TEST(ImportKeyResponse);
-GARBAGE_TEST(SupportedByAlgorithmAndPurposeRequest)
-GARBAGE_TEST(SupportedByAlgorithmRequest)
-GARBAGE_TEST(UpdateOperationRequest);
-GARBAGE_TEST(UpdateOperationResponse);
-GARBAGE_TEST(AttestKeyRequest);
-GARBAGE_TEST(AttestKeyResponse);
-GARBAGE_TEST(UpgradeKeyRequest);
-GARBAGE_TEST(UpgradeKeyResponse);
-
-// The macro doesn't work on this one.
-TEST(GarbageTest, SupportedResponse) {
- parse_garbage<SupportedResponse<keymaster_digest_t>>();
-}
-#endif
-} // namespace test
-
-} // namespace keymaster
diff --git a/unit_test/android_keymaster_test.cpp b/unit_test/android_keymaster_test.cpp
deleted file mode 100644
index d11b5be..0000000
--- a/unit_test/android_keymaster_test.cpp
+++ b/dev/null
@@ -1,3976 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#include <fstream>
-#include <string>
-#include <vector>
-
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-
-#include <hardware/keymaster0.h>
-#include <keymaster/key_factory.h>
-#include <keymaster/soft_keymaster_context.h>
-#include <keymaster/soft_keymaster_device.h>
-#include <keymaster/softkeymaster.h>
-
-#include "android_keymaster_test_utils.h"
-#include "attestation_record.h"
-#include "keymaster0_engine.h"
-#include "openssl_utils.h"
-
-#define CHECK_FAIL 1
-#define SUPPORT_TEST 1
-#define RSA_TEST 1
-#define EC_TEST 1
-#define AES_TEST 1
-#define HMAC_TEST 1
-#define MAX_TEST 1
-#define ENTROPY_TEST 1
-#define ATTESTATIONTEST 1
-#define KEYUPGRADETEST 0
-using std::ifstream;
-using std::istreambuf_iterator;
-using std::ofstream;
-using std::string;
-using std::unique_ptr;
-using std::vector;
-
-extern "C" {
-int __android_log_print(int prio, const char* tag, const char* fmt);
-int __android_log_print(int prio, const char* tag, const char* fmt) {
- (void)prio, (void)tag, (void)fmt;
- return 0;
-}
-} // extern "C"
-
-namespace keymaster {
-namespace test {
-
-const uint32_t kOsVersion = 060000;
-const uint32_t kOsPatchLevel = 201603;
-
-StdoutLogger logger;
-
-template <typename T> vector<T> make_vector(const T* array, size_t len) {
- return vector<T>(array, array + len);
-}
-
-/**
- * KeymasterEnforcement class for use in testing. It's permissive in the sense that it doesn't
- * check cryptoperiods, but restrictive in the sense that the clock never advances (so rate-limited
- * keys will only work once).
- */
-class TestKeymasterEnforcement : public KeymasterEnforcement {
- public:
- TestKeymasterEnforcement() : KeymasterEnforcement(3, 3) {}
-
- virtual bool activation_date_valid(uint64_t /* activation_date */) const { return true; }
- virtual bool expiration_date_passed(uint64_t /* expiration_date */) const { return false; }
- virtual bool auth_token_timed_out(const hw_auth_token_t& /* token */,
- uint32_t /* timeout */) const {
- return false;
- }
- virtual uint32_t get_current_time() const { return 0; }
- virtual bool ValidateTokenSignature(const hw_auth_token_t& /* token */) const { return true; }
-};
-
-/**
- * Variant of SoftKeymasterContext that provides a TestKeymasterEnforcement.
- */
-class TestKeymasterContext : public SoftKeymasterContext {
- public:
- TestKeymasterContext() {}
- explicit TestKeymasterContext(const string& root_of_trust) : SoftKeymasterContext(root_of_trust) {}
-
- KeymasterEnforcement* enforcement_policy() override { return &test_policy_; }
-
- private:
- TestKeymasterEnforcement test_policy_;
-};
-
-/**
- * Test instance creator that builds a pure software keymaster2 implementation.
- */
-class SoftKeymasterTestInstanceCreator : public Keymaster2TestInstanceCreator {
- public:
- keymaster2_device_t* CreateDevice() const override {
- std::cerr << "Creating software-only device" << std::endl;
- context_ = new TestKeymasterContext;
- SoftKeymasterDevice* device = new SoftKeymasterDevice(context_);
- AuthorizationSet version_info(AuthorizationSetBuilder()
- .Authorization(TAG_OS_VERSION, kOsVersion)
- .Authorization(TAG_OS_PATCHLEVEL, kOsPatchLevel));
- device->keymaster2_device()->configure(device->keymaster2_device(), &version_info);
- return device->keymaster2_device();
- }
-
- bool algorithm_in_km0_hardware(keymaster_algorithm_t) const override { return false; }
- int keymaster0_calls() const override { return 0; }
- bool is_keymaster1_hw() const override { return false; }
- KeymasterContext* keymaster_context() const override { return context_; }
-
- private:
- mutable TestKeymasterContext* context_;
-};
-
-/**
- * Test instance creator that builds a keymaster2 implementations.
- */
-class AmlKeymasterTestInstanceCreator : public Keymaster2TestInstanceCreator {
- public:
- keymaster2_device_t* CreateDevice() const override {
- const hw_module_t* mod;
- keymaster2_device_t* device = NULL;
-
- int rc = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod);
- if (rc) {
- std::cerr << "Could not find any keystore module!" << std::endl;
- } else {
- assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_2_0);
- rc = keymaster2_open(mod, &device);
- if (rc) {
- std::cerr << "Error "<< rc << "opening keystore keymaster2 device" << std::endl;
- return NULL;
- }
- }
-
- std::cerr << "Creating Amlogic keymaster2 device" << std::endl;
- // context_ = new TestKeymasterContext;
- // SoftKeymasterDevice* device = new SoftKeymasterDevice(context_);
- AuthorizationSet version_info(AuthorizationSetBuilder()
- .Authorization(TAG_OS_VERSION, kOsVersion)
- .Authorization(TAG_OS_PATCHLEVEL, kOsPatchLevel));
- device->configure(device, &version_info);
- _device = device;
- return device;
- }
-
- bool algorithm_in_km0_hardware(keymaster_algorithm_t) const override { return false; }
- int keymaster0_calls() const override { return 0; }
- bool is_keymaster1_hw() const override { return false; }
- KeymasterContext* keymaster_context() const override { return (KeymasterContext*) _device; }
-
- private:
- static keymaster2_device_t* _device;
- //mutable TestKeymasterContext* context_;
-};
-
-keymaster2_device_t* AmlKeymasterTestInstanceCreator::_device;
-/**
- * Test instance creator that builds keymaster1 instances which wrap a faked hardware keymaster0
- * instance, with or without EC support.
- */
-class Keymaster0AdapterTestInstanceCreator : public Keymaster2TestInstanceCreator {
- public:
- explicit Keymaster0AdapterTestInstanceCreator(bool support_ec) : support_ec_(support_ec) {}
-
- keymaster2_device_t* CreateDevice() const {
- std::cerr << "Creating keymaster0-backed device (with ec: " << std::boolalpha << support_ec_
- << ")." << std::endl;
- hw_device_t* softkeymaster_device;
- EXPECT_EQ(0, openssl_open(&softkeymaster_module.common, KEYSTORE_KEYMASTER,
- &softkeymaster_device));
- // Make the software device pretend to be hardware
- keymaster0_device_t* keymaster0_device =
- reinterpret_cast<keymaster0_device_t*>(softkeymaster_device);
- keymaster0_device->flags &= ~KEYMASTER_SOFTWARE_ONLY;
-
- if (!support_ec_) {
- // Make the software device pretend not to support EC
- keymaster0_device->flags &= ~KEYMASTER_SUPPORTS_EC;
- }
-
- counting_keymaster0_device_ = new Keymaster0CountingWrapper(keymaster0_device);
-
- context_ = new TestKeymasterContext;
- SoftKeymasterDevice* keymaster = new SoftKeymasterDevice(context_);
- keymaster->SetHardwareDevice(counting_keymaster0_device_);
- AuthorizationSet version_info(AuthorizationSetBuilder()
- .Authorization(TAG_OS_VERSION, kOsVersion)
- .Authorization(TAG_OS_PATCHLEVEL, kOsPatchLevel));
- keymaster->keymaster2_device()->configure(keymaster->keymaster2_device(), &version_info);
- return keymaster->keymaster2_device();
- }
-
- bool algorithm_in_km0_hardware(keymaster_algorithm_t algorithm) const override {
- switch (algorithm) {
- case KM_ALGORITHM_RSA:
- return true;
- case KM_ALGORITHM_EC:
- return support_ec_;
- default:
- return false;
- }
- }
- int keymaster0_calls() const override { return counting_keymaster0_device_->count(); }
- bool is_keymaster1_hw() const override { return false; }
- KeymasterContext* keymaster_context() const override { return context_; }
-
- private:
- mutable TestKeymasterContext* context_;
- mutable Keymaster0CountingWrapper* counting_keymaster0_device_;
- bool support_ec_;
-};
-
-/**
- * Test instance creator that builds a SoftKeymasterDevice which wraps a fake hardware keymaster1
- * instance, with minimal digest support.
- */
-class Sha256OnlyKeymaster2TestInstanceCreator : public Keymaster2TestInstanceCreator {
- keymaster2_device_t* CreateDevice() const {
- std::cerr << "Creating keymaster1-backed device that supports only SHA256";
-
- // fake_device doesn't leak because device (below) takes ownership of it.
- keymaster1_device_t* fake_device = make_device_sha256_only(
- (new SoftKeymasterDevice(new TestKeymasterContext("PseudoHW")))->keymaster_device());
-
- // device doesn't leak; it's cleaned up by device->keymaster_device()->common.close().
- context_ = new TestKeymasterContext;
- SoftKeymasterDevice* device = new SoftKeymasterDevice(context_);
- device->SetHardwareDevice(fake_device);
-
- AuthorizationSet version_info(AuthorizationSetBuilder()
- .Authorization(TAG_OS_VERSION, kOsVersion)
- .Authorization(TAG_OS_PATCHLEVEL, kOsPatchLevel));
- device->keymaster2_device()->configure(device->keymaster2_device(), &version_info);
- return device->keymaster2_device();
- }
-
- bool algorithm_in_km0_hardware(keymaster_algorithm_t) const override { return false; }
- int keymaster0_calls() const override { return 0; }
- int minimal_digest_set() const override { return true; }
- bool is_keymaster1_hw() const override { return true; }
- KeymasterContext* keymaster_context() const override { return context_; }
-
- private:
- mutable TestKeymasterContext* context_;
-};
-
-static auto test_params = testing::Values(
-#if 0
- InstanceCreatorPtr(new SoftKeymasterTestInstanceCreator),
- InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator(true /* support_ec */)),
- InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator(false /* support_ec */)),
- InstanceCreatorPtr(new Sha256OnlyKeymaster2TestInstanceCreator)
-#endif
- InstanceCreatorPtr(new AmlKeymasterTestInstanceCreator)
- );
-
-class NewKeyGeneration : public Keymaster2Test {
- protected:
- void CheckBaseParams() {
- AuthorizationSet auths = sw_enforced();
- auths.Union(hw_enforced());
- EXPECT_GT(auths.SerializedSize(), 12U);
-
- EXPECT_TRUE(contains(auths, TAG_PURPOSE, KM_PURPOSE_SIGN));
- EXPECT_TRUE(contains(auths, TAG_PURPOSE, KM_PURPOSE_VERIFY));
- EXPECT_TRUE(contains(auths, TAG_USER_ID, 7));
- EXPECT_TRUE(contains(auths, TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD));
- EXPECT_TRUE(contains(auths, TAG_AUTH_TIMEOUT, 300));
-
- // Verify that App ID, App data and ROT are NOT included.
- EXPECT_FALSE(contains(auths, TAG_ROOT_OF_TRUST));
- EXPECT_FALSE(contains(auths, TAG_APPLICATION_ID));
- EXPECT_FALSE(contains(auths, TAG_APPLICATION_DATA));
-
- // Just for giggles, check that some unexpected tags/values are NOT present.
- EXPECT_FALSE(contains(auths, TAG_PURPOSE, KM_PURPOSE_ENCRYPT));
- EXPECT_FALSE(contains(auths, TAG_PURPOSE, KM_PURPOSE_DECRYPT));
- EXPECT_FALSE(contains(auths, TAG_AUTH_TIMEOUT, 301));
-
- // Now check that unspecified, defaulted tags are correct.
- EXPECT_TRUE(contains(auths, KM_TAG_CREATION_DATETIME));
- if (GetParam()->is_keymaster1_hw()) {
- // If the underlying (faked) HW is KM1, it will not have version info.
- EXPECT_FALSE(auths.Contains(TAG_OS_VERSION));
- EXPECT_FALSE(auths.Contains(TAG_OS_PATCHLEVEL));
- } else {
- // In all othe cases; SoftKeymasterDevice keys, or keymaster0 keys wrapped by
- // SoftKeymasterDevice, version information will be present and up to date.
- EXPECT_TRUE(contains(auths, TAG_OS_VERSION, kOsVersion));
- EXPECT_TRUE(contains(auths, TAG_OS_PATCHLEVEL, kOsPatchLevel));
- }
- }
-};
-INSTANTIATE_TEST_CASE_P(AndroidKeymasterTest, NewKeyGeneration, test_params);
-#if RSA_TEST
-TEST_P(NewKeyGeneration, Rsa) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(256, 3)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_NONE)));
- CheckBaseParams();
-
- // Check specified tags are all present, and in the right set.
- AuthorizationSet crypto_params;
- AuthorizationSet non_crypto_params;
-#if 0
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA)) {
- EXPECT_NE(0U, hw_enforced().size());
- EXPECT_NE(0U, sw_enforced().size());
- crypto_params.push_back(hw_enforced());
- non_crypto_params.push_back(sw_enforced());
- } else {
- EXPECT_EQ(0U, hw_enforced().size());
- EXPECT_NE(0U, sw_enforced().size());
- crypto_params.push_back(sw_enforced());
- }
-#else
- EXPECT_NE(0U, hw_enforced().size());
- EXPECT_NE(0U, sw_enforced().size());
- crypto_params.push_back(hw_enforced());
- non_crypto_params.push_back(sw_enforced());
-#endif
-
- EXPECT_TRUE(contains(crypto_params, TAG_ALGORITHM, KM_ALGORITHM_RSA));
- EXPECT_FALSE(contains(non_crypto_params, TAG_ALGORITHM, KM_ALGORITHM_RSA));
- EXPECT_TRUE(contains(crypto_params, TAG_KEY_SIZE, 256));
- EXPECT_FALSE(contains(non_crypto_params, TAG_KEY_SIZE, 256));
- EXPECT_TRUE(contains(crypto_params, TAG_RSA_PUBLIC_EXPONENT, 3));
- EXPECT_FALSE(contains(non_crypto_params, TAG_RSA_PUBLIC_EXPONENT, 3));
-
- EXPECT_EQ(KM_ERROR_OK, DeleteKey());
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-#endif
-#if RSA_TEST
-TEST_P(NewKeyGeneration, RsaDefaultSize) {
- ASSERT_EQ(KM_ERROR_UNSUPPORTED_KEY_SIZE,
- GenerateKey(AuthorizationSetBuilder()
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_RSA_PUBLIC_EXPONENT, 3)
- .SigningKey()));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-#if EC_TEST
-TEST_P(NewKeyGeneration, Ecdsa) {
- ASSERT_EQ(KM_ERROR_OK,
- GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(224).Digest(KM_DIGEST_NONE)));
- CheckBaseParams();
-
- // Check specified tags are all present, and in the right set.
- AuthorizationSet crypto_params;
- AuthorizationSet non_crypto_params;
-#if 0
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC)) {
- EXPECT_NE(0U, hw_enforced().size());
- EXPECT_NE(0U, sw_enforced().size());
- crypto_params.push_back(hw_enforced());
- non_crypto_params.push_back(sw_enforced());
- } else {
- EXPECT_EQ(0U, hw_enforced().size());
- EXPECT_NE(0U, sw_enforced().size());
- crypto_params.push_back(sw_enforced());
- }
-#else
- EXPECT_NE(0U, hw_enforced().size());
- EXPECT_NE(0U, sw_enforced().size());
- crypto_params.push_back(hw_enforced());
- non_crypto_params.push_back(sw_enforced());
-#endif
-
- EXPECT_TRUE(contains(crypto_params, TAG_ALGORITHM, KM_ALGORITHM_EC));
- EXPECT_FALSE(contains(non_crypto_params, TAG_ALGORITHM, KM_ALGORITHM_EC));
- EXPECT_TRUE(contains(crypto_params, TAG_KEY_SIZE, 224));
- EXPECT_FALSE(contains(non_crypto_params, TAG_KEY_SIZE, 224));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(1, GetParam()->keymaster0_calls());
-}
-#endif
-#if EC_TEST
-TEST_P(NewKeyGeneration, EcdsaDefaultSize) {
- ASSERT_EQ(KM_ERROR_UNSUPPORTED_KEY_SIZE,
- GenerateKey(AuthorizationSetBuilder()
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_EC)
- .SigningKey()
- .Digest(KM_DIGEST_NONE)));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(NewKeyGeneration, EcdsaInvalidSize) {
- ASSERT_EQ(KM_ERROR_UNSUPPORTED_KEY_SIZE,
- GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(190).Digest(KM_DIGEST_NONE)));
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-
-#if EC_TEST
-TEST_P(NewKeyGeneration, EcdsaMismatchKeySize) {
- ASSERT_EQ(KM_ERROR_INVALID_ARGUMENT,
- GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(224)
- .Authorization(TAG_EC_CURVE, KM_EC_CURVE_P_256)
- .Digest(KM_DIGEST_NONE)));
-}
-#endif
-
-#if EC_TEST
-TEST_P(NewKeyGeneration, EcdsaAllValidSizes) {
- size_t valid_sizes[] = {224, 256, 384, 521};
- for (size_t size : valid_sizes) {
- EXPECT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(size).Digest(
- KM_DIGEST_NONE)))
- << "Failed to generate size: " << size;
- }
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-#endif
-#if HMAC_TEST
-TEST_P(NewKeyGeneration, HmacSha256) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA_2_256)
- .Authorization(TAG_MIN_MAC_LENGTH, 256)));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(NewKeyGeneration, HmacMultipleDigests) {
- ASSERT_EQ(KM_ERROR_UNSUPPORTED_DIGEST,
- GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA1)
- .Digest(KM_DIGEST_SHA_2_256)
- .Authorization(TAG_MIN_MAC_LENGTH, 128)));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(NewKeyGeneration, HmacDigestNone) {
- ASSERT_EQ(KM_ERROR_UNSUPPORTED_DIGEST,
- GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_NONE)
- .Authorization(TAG_MIN_MAC_LENGTH, 128)));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(NewKeyGeneration, HmacSha256TooShortMacLength) {
- ASSERT_EQ(KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH,
- GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA_2_256)
- .Authorization(TAG_MIN_MAC_LENGTH, 48)));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(NewKeyGeneration, HmacSha256NonIntegralOctetMacLength) {
- ASSERT_EQ(KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH,
- GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA_2_256)
- .Authorization(TAG_MIN_MAC_LENGTH, 130)));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(NewKeyGeneration, HmacSha256TooLongMacLength) {
- ASSERT_EQ(KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH,
- GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA_2_256)
- .Authorization(TAG_MIN_MAC_LENGTH, 384)));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-typedef Keymaster2Test GetKeyCharacteristics;
-INSTANTIATE_TEST_CASE_P(AndroidKeymasterTest, GetKeyCharacteristics, test_params);
-
-#if RSA_TEST
-TEST_P(GetKeyCharacteristics, SimpleRsa) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(256, 3)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_NONE)));
- AuthorizationSet original(sw_enforced());
-
- ASSERT_EQ(KM_ERROR_OK, GetCharacteristics());
- EXPECT_EQ(original, sw_enforced());
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(1, GetParam()->keymaster0_calls());
-}
-#endif
-typedef Keymaster2Test SigningOperationsTest;
-INSTANTIATE_TEST_CASE_P(AndroidKeymasterTest, SigningOperationsTest, test_params);
-#if RSA_TEST
-TEST_P(SigningOperationsTest, RsaSuccess) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(256, 3)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_NONE)));
- string message = "12345678901234567890123456789012";
- string signature;
- SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
-}
-#endif
-#if RSA_TEST
-TEST_P(SigningOperationsTest, RsaPssSha256Success) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(768, 3)
- .Digest(KM_DIGEST_SHA_2_256)
- .Padding(KM_PAD_RSA_PSS)));
- // Use large message, which won't work without digesting.
- string message(1024, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PSS);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, RsaPaddingNoneDoesNotAllowOther) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(512, 3)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_NONE)));
- string message = "12345678901234567890123456789012";
- string signature;
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
- begin_params.push_back(TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN);
- EXPECT_EQ(KM_ERROR_INCOMPATIBLE_PADDING_MODE, BeginOperation(KM_PURPOSE_SIGN, begin_params));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, RsaPkcs1Sha256Success) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(512, 3)
- .Digest(KM_DIGEST_SHA_2_256)
- .Padding(KM_PAD_RSA_PKCS1_1_5_SIGN)));
- string message(1024, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PKCS1_1_5_SIGN);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
-}
-#endif
-#if RSA_TEST
-TEST_P(SigningOperationsTest, RsaPkcs1NoDigestSuccess) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(512, 3)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_RSA_PKCS1_1_5_SIGN)));
- string message(53, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_RSA_PKCS1_1_5_SIGN);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
-}
-#endif
-#if RSA_TEST
-TEST_P(SigningOperationsTest, RsaPkcs1NoDigestTooLarge) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(512, 3)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_RSA_PKCS1_1_5_SIGN)));
- string message(54, 'a');
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
- begin_params.push_back(TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN);
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_SIGN, begin_params));
- string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- string signature;
- EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&signature));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-#endif
-#if CHECK_FAIL
-TEST_P(SigningOperationsTest, RsaPssSha256TooSmallKey) {
- // Key must be at least 10 bytes larger than hash, to provide eight bytes of random salt, so
- // verify that nine bytes larger than hash won't work.
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(256 + 9 * 8, 3)
- .Digest(KM_DIGEST_SHA_2_256)
- .Padding(KM_PAD_RSA_PSS)));
- string message(1024, 'a');
- string signature;
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA_2_256);
- begin_params.push_back(TAG_PADDING, KM_PAD_RSA_PSS);
- EXPECT_EQ(KM_ERROR_INCOMPATIBLE_DIGEST, BeginOperation(KM_PURPOSE_SIGN, begin_params));
-}
-#endif
-#if CHECK_FAIL
-TEST_P(SigningOperationsTest, RsaNoPaddingHugeData) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(256, 3)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_RSA_PKCS1_1_5_SIGN)));
- string message(64 * 1024, 'a');
- string signature;
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
- begin_params.push_back(TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN);
- ASSERT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_SIGN, begin_params));
- string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, UpdateOperation(message, &result, &input_consumed));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-#endif
-#if CHECK_FAIL
-TEST_P(SigningOperationsTest, RsaAbort) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(256, 3)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_NONE)));
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- ASSERT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_SIGN, begin_params));
- EXPECT_EQ(KM_ERROR_OK, AbortOperation());
- // Another abort should fail
- EXPECT_EQ(KM_ERROR_INVALID_OPERATION_HANDLE, AbortOperation());
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-#endif
-#if RSA_TEST
-TEST_P(SigningOperationsTest, RsaUnsupportedPadding) {
- GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(256, 3)
- .Digest(KM_DIGEST_SHA_2_256 /* supported digest */)
- .Padding(KM_PAD_PKCS7));
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA_2_256);
- ASSERT_EQ(KM_ERROR_UNSUPPORTED_PADDING_MODE, BeginOperation(KM_PURPOSE_SIGN, begin_params));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, RsaNoDigest) {
- // PSS requires a digest.
- GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(256, 3)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_RSA_PSS));
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
- begin_params.push_back(TAG_PADDING, KM_PAD_RSA_PSS);
- ASSERT_EQ(KM_ERROR_INCOMPATIBLE_DIGEST, BeginOperation(KM_PURPOSE_SIGN, begin_params));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, RsaNoPadding) {
- // Padding must be specified
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().RsaKey(256, 3).SigningKey().Digest(
- KM_DIGEST_NONE)));
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
- ASSERT_EQ(KM_ERROR_UNSUPPORTED_PADDING_MODE, BeginOperation(KM_PURPOSE_SIGN, begin_params));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, RsaTooShortMessage) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(256, 3)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_NONE)));
- string message = "1234567890123456789012345678901";
- string signature;
- SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, RsaSignWithEncryptionKey) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaEncryptionKey(256, 3)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_NONE)));
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
- ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_SIGN, begin_params));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, RsaSignTooLargeMessage) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(256, 3)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_NONE)));
- string message(256 / 8, static_cast<char>(0xff));
- string signature;
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
- ASSERT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_SIGN, begin_params));
- string result;
- size_t input_consumed;
- ASSERT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- ASSERT_EQ(message.size(), input_consumed);
- string output;
- ASSERT_EQ(KM_ERROR_INVALID_ARGUMENT, FinishOperation(&output));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
-}
-#endif
-#if EC_TEST
-TEST_P(SigningOperationsTest, EcdsaSuccess) {
- ASSERT_EQ(KM_ERROR_OK,
- GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(224).Digest(KM_DIGEST_NONE)));
- string message(224 / 8, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
-}
-#endif
-#if EC_TEST
-TEST_P(SigningOperationsTest, EcdsaSha256Success) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(224).Digest(
- KM_DIGEST_SHA_2_256)));
- string message(1024, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_SHA_2_256);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, EcdsaSha384Success) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(224).Digest(
- KM_DIGEST_SHA_2_384)));
- string message(1024, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_SHA_2_384);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, EcdsaNoPaddingHugeData) {
- ASSERT_EQ(KM_ERROR_OK,
- GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(224).Digest(KM_DIGEST_NONE)));
- string message(64 * 1024, 'a');
- string signature;
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
- ASSERT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_SIGN, begin_params));
- string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, EcdsaAllSizesAndHashes) {
- vector<int> key_sizes = {224, 256, 384, 521};
- vector<keymaster_digest_t> digests = {
- KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224, KM_DIGEST_SHA_2_256,
- KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512,
- };
-
- for (int key_size : key_sizes) {
- for (keymaster_digest_t digest : digests) {
- ASSERT_EQ(
- KM_ERROR_OK,
- GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(key_size).Digest(digest)));
-
- string message(1024, 'a');
- string signature;
- if (digest == KM_DIGEST_NONE)
- message.resize(key_size / 8);
- SignMessage(message, &signature, digest);
- }
- }
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(digests.size() * key_sizes.size() * 3,
- static_cast<size_t>(GetParam()->keymaster0_calls()));
-}
-#endif
-#if AES_TEST
-TEST_P(SigningOperationsTest, AesEcbSign) {
- ASSERT_EQ(KM_ERROR_OK,
- GenerateKey(AuthorizationSetBuilder().AesEncryptionKey(128).Authorization(
- TAG_BLOCK_MODE, KM_MODE_ECB)));
- ASSERT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE, BeginOperation(KM_PURPOSE_SIGN));
- ASSERT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE, BeginOperation(KM_PURPOSE_VERIFY));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-#if HMAC_TEST
-TEST_P(SigningOperationsTest, HmacSha1Success) {
- if (GetParam()->minimal_digest_set())
- // Can't emulate other digests for HMAC.
- return;
-
- GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA1)
- .Authorization(TAG_MIN_MAC_LENGTH, 160));
- string message = "12345678901234567890123456789012";
- string signature;
- MacMessage(message, &signature, 160);
- ASSERT_EQ(20U, signature.size());
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-#if HMAC_TEST
-TEST_P(SigningOperationsTest, HmacSha224Success) {
- if (GetParam()->minimal_digest_set())
- // Can't emulate other digests for HMAC.
- return;
-
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA_2_224)
- .Authorization(TAG_MIN_MAC_LENGTH, 160)));
- string message = "12345678901234567890123456789012";
- string signature;
- MacMessage(message, &signature, 224);
- ASSERT_EQ(28U, signature.size());
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, HmacSha256Success) {
- if (GetParam()->minimal_digest_set())
- // Can't emulate other digests for HMAC.
- return;
-
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA_2_256)
- .Authorization(TAG_MIN_MAC_LENGTH, 256)));
- string message = "12345678901234567890123456789012";
- string signature;
- MacMessage(message, &signature, 256);
- ASSERT_EQ(32U, signature.size());
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, HmacSha384Success) {
- if (GetParam()->minimal_digest_set())
- // Can't emulate other digests for HMAC.
- return;
-
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA_2_384)
- .Authorization(TAG_MIN_MAC_LENGTH, 384)));
-
- string message = "12345678901234567890123456789012";
- string signature;
- MacMessage(message, &signature, 384);
- ASSERT_EQ(48U, signature.size());
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, HmacSha512Success) {
- if (GetParam()->minimal_digest_set())
- // Can't emulate other digests for HMAC.
- return;
-
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA_2_512)
- .Authorization(TAG_MIN_MAC_LENGTH, 384)));
- string message = "12345678901234567890123456789012";
- string signature;
- MacMessage(message, &signature, 512);
- ASSERT_EQ(64U, signature.size());
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, HmacLengthInKey) {
- // TODO(swillden): unified API should generate an error on key generation.
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA_2_256)
- .Authorization(TAG_MIN_MAC_LENGTH, 128)));
- string message = "12345678901234567890123456789012";
- string signature;
- MacMessage(message, &signature, 160);
- ASSERT_EQ(20U, signature.size());
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, HmacRfc4231TestCase1) {
- uint8_t key_data[] = {
- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
- };
- string message = "Hi There";
- uint8_t sha_224_expected[] = {
- 0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19, 0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d,
- 0xf3, 0x3f, 0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f, 0x53, 0x68, 0x4b, 0x22,
- };
- uint8_t sha_256_expected[] = {
- 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf,
- 0xce, 0xaf, 0x0b, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83,
- 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7,
- };
- uint8_t sha_384_expected[] = {
- 0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62, 0x6b, 0x08, 0x25, 0xf4,
- 0xab, 0x46, 0x90, 0x7f, 0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6,
- 0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c, 0xfa, 0xea, 0x9e, 0xa9,
- 0x07, 0x6e, 0xde, 0x7f, 0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6,
- };
- uint8_t sha_512_expected[] = {
- 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d, 0x4f, 0xf0, 0xb4, 0x24, 0x1a,
- 0x1d, 0x6c, 0xb0, 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78, 0x7a, 0xd0,
- 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde, 0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7,
- 0x02, 0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4, 0xbe, 0x9d, 0x91, 0x4e,
- 0xeb, 0x61, 0xf1, 0x70, 0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54,
- };
-
- string key = make_string(key_data);
-
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- if (!GetParam()->minimal_digest_set()) {
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
- }
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, HmacRfc4231TestCase2) {
- string key = "Jefe";
- string message = "what do ya want for nothing?";
- uint8_t sha_224_expected[] = {
- 0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf, 0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e,
- 0x6d, 0x0f, 0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00, 0x8f, 0xd0, 0x5e, 0x44,
- };
- uint8_t sha_256_expected[] = {
- 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24,
- 0x26, 0x08, 0x95, 0x75, 0xc7, 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27,
- 0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43,
- };
- uint8_t sha_384_expected[] = {
- 0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31, 0x61, 0x7f, 0x78, 0xd2,
- 0xb5, 0x8a, 0x6b, 0x1b, 0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47,
- 0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e, 0x8e, 0x22, 0x40, 0xca,
- 0x5e, 0x69, 0xe2, 0xc7, 0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49,
- };
- uint8_t sha_512_expected[] = {
- 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 0xe3, 0x95, 0xfb, 0xe7, 0x3b,
- 0x56, 0xe0, 0xa3, 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, 0x10, 0x27,
- 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54, 0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99,
- 0x4a, 0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd, 0xca, 0xea, 0xb1, 0xa3,
- 0x4d, 0x4a, 0x6b, 0x4b, 0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37,
- };
-
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- if (!GetParam()->minimal_digest_set()) {
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
- }
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, HmacRfc4231TestCase3) {
- string key(20, 0xaa);
- string message(50, 0xdd);
- uint8_t sha_224_expected[] = {
- 0x7f, 0xb3, 0xcb, 0x35, 0x88, 0xc6, 0xc1, 0xf6, 0xff, 0xa9, 0x69, 0x4d, 0x7d, 0x6a,
- 0xd2, 0x64, 0x93, 0x65, 0xb0, 0xc1, 0xf6, 0x5d, 0x69, 0xd1, 0xec, 0x83, 0x33, 0xea,
- };
- uint8_t sha_256_expected[] = {
- 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8,
- 0xeb, 0xd0, 0x91, 0x81, 0xa7, 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8,
- 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe,
- };
- uint8_t sha_384_expected[] = {
- 0x88, 0x06, 0x26, 0x08, 0xd3, 0xe6, 0xad, 0x8a, 0x0a, 0xa2, 0xac, 0xe0,
- 0x14, 0xc8, 0xa8, 0x6f, 0x0a, 0xa6, 0x35, 0xd9, 0x47, 0xac, 0x9f, 0xeb,
- 0xe8, 0x3e, 0xf4, 0xe5, 0x59, 0x66, 0x14, 0x4b, 0x2a, 0x5a, 0xb3, 0x9d,
- 0xc1, 0x38, 0x14, 0xb9, 0x4e, 0x3a, 0xb6, 0xe1, 0x01, 0xa3, 0x4f, 0x27,
- };
- uint8_t sha_512_expected[] = {
- 0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84, 0xef, 0xb0, 0xf0, 0x75, 0x6c,
- 0x89, 0x0b, 0xe9, 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36, 0x55, 0xf8,
- 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39, 0xbf, 0x3e, 0x84, 0x82, 0x79, 0xa7, 0x22,
- 0xc8, 0x06, 0xb4, 0x85, 0xa4, 0x7e, 0x67, 0xc8, 0x07, 0xb9, 0x46, 0xa3, 0x37,
- 0xbe, 0xe8, 0x94, 0x26, 0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb,
- };
-
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- if (!GetParam()->minimal_digest_set()) {
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
- }
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, HmacRfc4231TestCase4) {
- uint8_t key_data[25] = {
- 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,
- };
- string key = make_string(key_data);
- string message(50, 0xcd);
- uint8_t sha_224_expected[] = {
- 0x6c, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3c, 0xac, 0x6a, 0x2a, 0xbc, 0x1b, 0xb3, 0x82,
- 0x62, 0x7c, 0xec, 0x6a, 0x90, 0xd8, 0x6e, 0xfc, 0x01, 0x2d, 0xe7, 0xaf, 0xec, 0x5a,
- };
- uint8_t sha_256_expected[] = {
- 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81,
- 0x98, 0x99, 0xf2, 0x08, 0x3a, 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78,
- 0xf8, 0x07, 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b,
- };
- uint8_t sha_384_expected[] = {
- 0x3e, 0x8a, 0x69, 0xb7, 0x78, 0x3c, 0x25, 0x85, 0x19, 0x33, 0xab, 0x62,
- 0x90, 0xaf, 0x6c, 0xa7, 0x7a, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9c,
- 0xc5, 0x57, 0x7c, 0x6e, 0x1f, 0x57, 0x3b, 0x4e, 0x68, 0x01, 0xdd, 0x23,
- 0xc4, 0xa7, 0xd6, 0x79, 0xcc, 0xf8, 0xa3, 0x86, 0xc6, 0x74, 0xcf, 0xfb,
- };
- uint8_t sha_512_expected[] = {
- 0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69, 0x90, 0xe5, 0xa8, 0xc5, 0xf6,
- 0x1d, 0x4a, 0xf7, 0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d, 0xe7, 0x6f,
- 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb, 0xa9, 0x1c, 0xa5, 0xc1, 0x1a, 0xa2, 0x5e,
- 0xb4, 0xd6, 0x79, 0x27, 0x5c, 0xc5, 0x78, 0x80, 0x63, 0xa5, 0xf1, 0x97, 0x41,
- 0x12, 0x0c, 0x4f, 0x2d, 0xe2, 0xad, 0xeb, 0xeb, 0x10, 0xa2, 0x98, 0xdd,
- };
-
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- if (!GetParam()->minimal_digest_set()) {
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
- }
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, HmacRfc4231TestCase5) {
- string key(20, 0x0c);
- string message = "Test With Truncation";
-
- uint8_t sha_224_expected[] = {
- 0x0e, 0x2a, 0xea, 0x68, 0xa9, 0x0c, 0x8d, 0x37,
- 0xc9, 0x88, 0xbc, 0xdb, 0x9f, 0xca, 0x6f, 0xa8,
- };
- uint8_t sha_256_expected[] = {
- 0xa3, 0xb6, 0x16, 0x74, 0x73, 0x10, 0x0e, 0xe0,
- 0x6e, 0x0c, 0x79, 0x6c, 0x29, 0x55, 0x55, 0x2b,
- };
- uint8_t sha_384_expected[] = {
- 0x3a, 0xbf, 0x34, 0xc3, 0x50, 0x3b, 0x2a, 0x23,
- 0xa4, 0x6e, 0xfc, 0x61, 0x9b, 0xae, 0xf8, 0x97,
- };
- uint8_t sha_512_expected[] = {
- 0x41, 0x5f, 0xad, 0x62, 0x71, 0x58, 0x0a, 0x53,
- 0x1d, 0x41, 0x79, 0xbc, 0x89, 0x1d, 0x87, 0xa6,
- };
-
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- if (!GetParam()->minimal_digest_set()) {
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
- }
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-
-#if HMAC_TEST
-TEST_P(SigningOperationsTest, HmacRfc4231TestCase6) {
- string key(131, 0xaa);
- string message = "Test Using Larger Than Block-Size Key - Hash Key First";
-
- uint8_t sha_224_expected[] = {
- 0x95, 0xe9, 0xa0, 0xdb, 0x96, 0x20, 0x95, 0xad, 0xae, 0xbe, 0x9b, 0x2d, 0x6f, 0x0d,
- 0xbc, 0xe2, 0xd4, 0x99, 0xf1, 0x12, 0xf2, 0xd2, 0xb7, 0x27, 0x3f, 0xa6, 0x87, 0x0e,
- };
- uint8_t sha_256_expected[] = {
- 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26,
- 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28,
- 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54,
- };
- uint8_t sha_384_expected[] = {
- 0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90, 0x88, 0xd2, 0xc6, 0x3a,
- 0x04, 0x1b, 0xc5, 0xb4, 0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f,
- 0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6, 0x0c, 0x2e, 0xf6, 0xab,
- 0x40, 0x30, 0xfe, 0x82, 0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52,
- };
- uint8_t sha_512_expected[] = {
- 0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb, 0xb7, 0x14, 0x93, 0xc1, 0xdd,
- 0x7b, 0xe8, 0xb4, 0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1, 0x12, 0x1b,
- 0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52, 0x6b, 0x56, 0xd0, 0x37, 0xe0, 0x5f, 0x25,
- 0x98, 0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52, 0x95, 0xe6, 0x4f, 0x73,
- 0xf6, 0x3f, 0x0a, 0xec, 0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98,
- };
-
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- if (!GetParam()->minimal_digest_set()) {
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
- }
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-
-#if HMAC_TEST
-TEST_P(SigningOperationsTest, HmacRfc4231TestCase7) {
- string key(131, 0xaa);
- string message = "This is a test using a larger than block-size key and a larger than "
- "block-size data. The key needs to be hashed before being used by the HMAC "
- "algorithm.";
-
- uint8_t sha_224_expected[] = {
- 0x3a, 0x85, 0x41, 0x66, 0xac, 0x5d, 0x9f, 0x02, 0x3f, 0x54, 0xd5, 0x17, 0xd0, 0xb3,
- 0x9d, 0xbd, 0x94, 0x67, 0x70, 0xdb, 0x9c, 0x2b, 0x95, 0xc9, 0xf6, 0xf5, 0x65, 0xd1,
- };
- uint8_t sha_256_expected[] = {
- 0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f,
- 0xbc, 0xd5, 0xb0, 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07,
- 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2,
- };
- uint8_t sha_384_expected[] = {
- 0x66, 0x17, 0x17, 0x8e, 0x94, 0x1f, 0x02, 0x0d, 0x35, 0x1e, 0x2f, 0x25,
- 0x4e, 0x8f, 0xd3, 0x2c, 0x60, 0x24, 0x20, 0xfe, 0xb0, 0xb8, 0xfb, 0x9a,
- 0xdc, 0xce, 0xbb, 0x82, 0x46, 0x1e, 0x99, 0xc5, 0xa6, 0x78, 0xcc, 0x31,
- 0xe7, 0x99, 0x17, 0x6d, 0x38, 0x60, 0xe6, 0x11, 0x0c, 0x46, 0x52, 0x3e,
- };
- uint8_t sha_512_expected[] = {
- 0xe3, 0x7b, 0x6a, 0x77, 0x5d, 0xc8, 0x7d, 0xba, 0xa4, 0xdf, 0xa9, 0xf9, 0x6e,
- 0x5e, 0x3f, 0xfd, 0xde, 0xbd, 0x71, 0xf8, 0x86, 0x72, 0x89, 0x86, 0x5d, 0xf5,
- 0xa3, 0x2d, 0x20, 0xcd, 0xc9, 0x44, 0xb6, 0x02, 0x2c, 0xac, 0x3c, 0x49, 0x82,
- 0xb1, 0x0d, 0x5e, 0xeb, 0x55, 0xc3, 0xe4, 0xde, 0x15, 0x13, 0x46, 0x76, 0xfb,
- 0x6d, 0xe0, 0x44, 0x60, 0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58,
- };
-
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- if (!GetParam()->minimal_digest_set()) {
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
- }
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, HmacSha256TooLargeMacLength) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA_2_256)
- .Authorization(TAG_MIN_MAC_LENGTH, 256)));
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_MAC_LENGTH, 264);
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA_2_256);
- ASSERT_EQ(KM_ERROR_UNSUPPORTED_MAC_LENGTH,
- BeginOperation(KM_PURPOSE_SIGN, begin_params, nullptr /* output_params */));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, HmacSha256TooSmallMacLength) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA_2_256)
- .Authorization(TAG_MIN_MAC_LENGTH, 128)));
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_MAC_LENGTH, 120);
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA_2_256);
- ASSERT_EQ(KM_ERROR_INVALID_MAC_LENGTH,
- BeginOperation(KM_PURPOSE_SIGN, begin_params, nullptr /* output_params */));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-// TODO(swillden): Add more verification failure tests.
-
-typedef Keymaster2Test VerificationOperationsTest;
-INSTANTIATE_TEST_CASE_P(AndroidKeymasterTest, VerificationOperationsTest, test_params);
-#if RSA_TEST
-TEST_P(VerificationOperationsTest, RsaSuccess) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(256, 3)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_NONE)));
- string message = "12345678901234567890123456789012";
- string signature;
- SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
- VerifyMessage(message, signature, KM_DIGEST_NONE, KM_PAD_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-
-TEST_P(VerificationOperationsTest, RsaPssSha256Success) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(768, 3)
- .Digest(KM_DIGEST_SHA_2_256)
- .Padding(KM_PAD_RSA_PSS)));
- // Use large message, which won't work without digesting.
- string message(1024, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PSS);
- VerifyMessage(message, signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PSS);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-
-TEST_P(VerificationOperationsTest, RsaPssSha224Success) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(512, 3)
- .Digest(KM_DIGEST_SHA_2_224)
- .Padding(KM_PAD_RSA_PSS)));
- // Use large message, which won't work without digesting.
- string message(1024, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_SHA_2_224, KM_PAD_RSA_PSS);
- VerifyMessage(message, signature, KM_DIGEST_SHA_2_224, KM_PAD_RSA_PSS);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-
- // Verify with OpenSSL.
- string pubkey;
- EXPECT_EQ(KM_ERROR_OK, ExportKey(KM_KEY_FORMAT_X509, &pubkey));
-
- const uint8_t* p = reinterpret_cast<const uint8_t*>(pubkey.data());
- unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
- d2i_PUBKEY(nullptr /* alloc new */, &p, pubkey.size()));
- ASSERT_TRUE(pkey.get());
-
- EVP_MD_CTX digest_ctx;
- EVP_MD_CTX_init(&digest_ctx);
- EVP_PKEY_CTX* pkey_ctx;
- EXPECT_EQ(1, EVP_DigestVerifyInit(&digest_ctx, &pkey_ctx, EVP_sha224(), nullptr /* engine */,
- pkey.get()));
- EXPECT_EQ(1, EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING));
- EXPECT_EQ(1, EVP_DigestVerifyUpdate(&digest_ctx, message.data(), message.size()));
- EXPECT_EQ(1,
- EVP_DigestVerifyFinal(&digest_ctx, reinterpret_cast<const uint8_t*>(signature.data()),
- signature.size()));
- EVP_MD_CTX_cleanup(&digest_ctx);
-}
-
-TEST_P(VerificationOperationsTest, RsaPssSha256CorruptSignature) {
- GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(768, 3)
- .Digest(KM_DIGEST_SHA_2_256)
- .Padding(KM_PAD_RSA_PSS));
- string message(1024, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PSS);
- ++signature[signature.size() / 2];
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA_2_256);
- begin_params.push_back(TAG_PADDING, KM_PAD_RSA_PSS);
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_VERIFY, begin_params));
-
- string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-
-TEST_P(VerificationOperationsTest, RsaPssSha256CorruptInput) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(768, 3)
- .Digest(KM_DIGEST_SHA_2_256)
- .Padding(KM_PAD_RSA_PSS)));
- // Use large message, which won't work without digesting.
- string message(1024, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PSS);
- ++message[message.size() / 2];
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA_2_256);
- begin_params.push_back(TAG_PADDING, KM_PAD_RSA_PSS);
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_VERIFY, begin_params));
-
- string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-
-TEST_P(VerificationOperationsTest, RsaPkcs1Sha256Success) {
- GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(512, 3)
- .Digest(KM_DIGEST_SHA_2_256)
- .Padding(KM_PAD_RSA_PKCS1_1_5_SIGN));
- string message(1024, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PKCS1_1_5_SIGN);
- VerifyMessage(message, signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PKCS1_1_5_SIGN);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-
-TEST_P(VerificationOperationsTest, RsaPks1Sha224Success) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(512, 3)
- .Digest(KM_DIGEST_SHA_2_224)
- .Padding(KM_PAD_RSA_PKCS1_1_5_SIGN)));
- // Use large message, which won't work without digesting.
- string message(1024, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_SHA_2_224, KM_PAD_RSA_PKCS1_1_5_SIGN);
- VerifyMessage(message, signature, KM_DIGEST_SHA_2_224, KM_PAD_RSA_PKCS1_1_5_SIGN);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-
- // Verify with OpenSSL.
- string pubkey;
- EXPECT_EQ(KM_ERROR_OK, ExportKey(KM_KEY_FORMAT_X509, &pubkey));
-
- const uint8_t* p = reinterpret_cast<const uint8_t*>(pubkey.data());
- unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
- d2i_PUBKEY(nullptr /* alloc new */, &p, pubkey.size()));
- ASSERT_TRUE(pkey.get());
-
- EVP_MD_CTX digest_ctx;
- EVP_MD_CTX_init(&digest_ctx);
- EVP_PKEY_CTX* pkey_ctx;
- EXPECT_EQ(1, EVP_DigestVerifyInit(&digest_ctx, &pkey_ctx, EVP_sha224(), nullptr /* engine */,
- pkey.get()));
- EXPECT_EQ(1, EVP_DigestVerifyUpdate(&digest_ctx, message.data(), message.size()));
- EXPECT_EQ(1,
- EVP_DigestVerifyFinal(&digest_ctx, reinterpret_cast<const uint8_t*>(signature.data()),
- signature.size()));
- EVP_MD_CTX_cleanup(&digest_ctx);
-}
-
-TEST_P(VerificationOperationsTest, RsaPkcs1Sha256CorruptSignature) {
- GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(512, 3)
- .Digest(KM_DIGEST_SHA_2_256)
- .Padding(KM_PAD_RSA_PKCS1_1_5_SIGN));
- string message(1024, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PKCS1_1_5_SIGN);
- ++signature[signature.size() / 2];
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA_2_256);
- begin_params.push_back(TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN);
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_VERIFY, begin_params));
-
- string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-
-TEST_P(VerificationOperationsTest, RsaPkcs1Sha256CorruptInput) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(512, 3)
- .Digest(KM_DIGEST_SHA_2_256)
- .Padding(KM_PAD_RSA_PKCS1_1_5_SIGN)));
- // Use large message, which won't work without digesting.
- string message(1024, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PKCS1_1_5_SIGN);
- ++message[message.size() / 2];
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA_2_256);
- begin_params.push_back(TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN);
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_VERIFY, begin_params));
-
- string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-#endif
-#if CHECK_FAIL
-TEST_P(VerificationOperationsTest, RsaAllDigestAndPadCombinations) {
- vector<keymaster_digest_t> digests = {
- KM_DIGEST_NONE, KM_DIGEST_MD5, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
- KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512,
- };
-
- vector<keymaster_padding_t> padding_modes{
- KM_PAD_NONE, KM_PAD_RSA_PKCS1_1_5_SIGN, KM_PAD_RSA_PSS,
- };
-
- int trial_count = 0;
- for (keymaster_padding_t padding_mode : padding_modes) {
- for (keymaster_digest_t digest : digests) {
- if (digest != KM_DIGEST_NONE && padding_mode == KM_PAD_NONE)
- // Digesting requires padding
- continue;
-
- // Compute key & message size that will work.
- size_t key_bits = 0;
- size_t message_len = 1000;
-
- if (digest == KM_DIGEST_NONE) {
- key_bits = 256;
- switch (padding_mode) {
- case KM_PAD_NONE:
- // Match key size.
- message_len = key_bits / 8;
- break;
- case KM_PAD_RSA_PKCS1_1_5_SIGN:
- message_len = key_bits / 8 - 11;
- break;
- case KM_PAD_RSA_PSS:
- // PSS requires a digest.
- continue;
- default:
- FAIL() << "Missing padding";
- break;
- }
- } else {
- size_t digest_bits;
- switch (digest) {
- case KM_DIGEST_MD5:
- digest_bits = 128;
- break;
- case KM_DIGEST_SHA1:
- digest_bits = 160;
- break;
- case KM_DIGEST_SHA_2_224:
- digest_bits = 224;
- break;
- case KM_DIGEST_SHA_2_256:
- digest_bits = 256;
- break;
- case KM_DIGEST_SHA_2_384:
- digest_bits = 384;
- break;
- case KM_DIGEST_SHA_2_512:
- digest_bits = 512;
- break;
- default:
- FAIL() << "Missing digest";
- }
-
- switch (padding_mode) {
- case KM_PAD_RSA_PKCS1_1_5_SIGN:
- key_bits = digest_bits + 8 * (11 + 19);
- break;
- case KM_PAD_RSA_PSS:
- key_bits = digest_bits * 2 + 2 * 8;
- break;
- default:
- FAIL() << "Missing padding";
- break;
- }
- }
-
- // round up to 128 bits because new boringssl supports only 128 bit mulitples
- key_bits += 127;
- key_bits &= ~127;
- GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(key_bits, 3)
- .Digest(digest)
- .Padding(padding_mode));
- string message(message_len, 'a');
- string signature;
- SignMessage(message, &signature, digest, padding_mode);
- VerifyMessage(message, signature, digest, padding_mode);
- ++trial_count;
- }
- }
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(trial_count * 4, GetParam()->keymaster0_calls());
-}
-#endif
-#if EC_TEST
-TEST_P(VerificationOperationsTest, EcdsaSuccess) {
- ASSERT_EQ(KM_ERROR_OK,
- GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(256).Digest(KM_DIGEST_NONE)));
- string message = "12345678901234567890123456789012";
- string signature;
- SignMessage(message, &signature, KM_DIGEST_NONE);
- VerifyMessage(message, signature, KM_DIGEST_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-
-TEST_P(VerificationOperationsTest, EcdsaTooShort) {
- ASSERT_EQ(KM_ERROR_OK,
- GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(256).Digest(KM_DIGEST_NONE)));
- string message = "12345678901234567890";
- string signature;
- SignMessage(message, &signature, KM_DIGEST_NONE);
- VerifyMessage(message, signature, KM_DIGEST_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-
-TEST_P(VerificationOperationsTest, EcdsaSlightlyTooLong) {
- ASSERT_EQ(KM_ERROR_OK,
- GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(521).Digest(KM_DIGEST_NONE)));
-
- string message(66, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_NONE);
- VerifyMessage(message, signature, KM_DIGEST_NONE);
-
- // Modifying low-order bits doesn't matter, because they didn't get signed. Ugh.
- message[65] ^= 7;
- VerifyMessage(message, signature, KM_DIGEST_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(5, GetParam()->keymaster0_calls());
-}
-
-TEST_P(VerificationOperationsTest, EcdsaSha256Success) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(256)
- .Digest(KM_DIGEST_SHA_2_256)
- .Digest(KM_DIGEST_NONE)));
- string message = "12345678901234567890123456789012";
- string signature;
- SignMessage(message, &signature, KM_DIGEST_SHA_2_256);
- VerifyMessage(message, signature, KM_DIGEST_SHA_2_256);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-
- // Just for giggles, try verifying with the wrong digest.
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_VERIFY, begin_params));
-
- string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
-}
-
-TEST_P(VerificationOperationsTest, EcdsaSha224Success) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(256).Digest(
- KM_DIGEST_SHA_2_224)));
-
- string message = "12345678901234567890123456789012";
- string signature;
- SignMessage(message, &signature, KM_DIGEST_SHA_2_224);
- VerifyMessage(message, signature, KM_DIGEST_SHA_2_224);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-
- // Just for giggles, try verifying with the wrong digest.
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_VERIFY, begin_params));
-
- string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
-}
-
-TEST_P(VerificationOperationsTest, EcdsaAllDigestsAndKeySizes) {
- keymaster_digest_t digests[] = {
- KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224, KM_DIGEST_SHA_2_256,
- KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512,
- };
- size_t key_sizes[] = {224, 256, 384, 521};
-
- string message = "1234567890";
- string signature;
-
- for (auto key_size : key_sizes) {
- AuthorizationSetBuilder builder;
- builder.EcdsaSigningKey(key_size);
- for (auto digest : digests)
- builder.Digest(digest);
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(builder));
-
- for (auto digest : digests) {
- SignMessage(message, &signature, digest);
- VerifyMessage(message, signature, digest);
- }
- }
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(static_cast<int>(array_length(key_sizes) * (1 + 3 * array_length(digests))),
- GetParam()->keymaster0_calls());
-}
-#endif
-#if HMAC_TEST
-TEST_P(VerificationOperationsTest, HmacSha1Success) {
- if (GetParam()->minimal_digest_set())
- // Can't emulate missing digests for HMAC.
- return;
-
- GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA1)
- .Authorization(TAG_MIN_MAC_LENGTH, 128));
- string message = "123456789012345678901234567890123456789012345678";
- string signature;
- MacMessage(message, &signature, 160);
- VerifyMac(message, signature);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(VerificationOperationsTest, HmacSha224Success) {
- if (GetParam()->minimal_digest_set())
- // Can't emulate missing digests for HMAC.
- return;
-
- GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA_2_224)
- .Authorization(TAG_MIN_MAC_LENGTH, 128));
- string message = "123456789012345678901234567890123456789012345678";
- string signature;
- MacMessage(message, &signature, 224);
- VerifyMac(message, signature);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(VerificationOperationsTest, HmacSha256Success) {
- GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA_2_256)
- .Authorization(TAG_MIN_MAC_LENGTH, 128));
- string message = "123456789012345678901234567890123456789012345678";
- string signature;
- MacMessage(message, &signature, 256);
- VerifyMac(message, signature);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(VerificationOperationsTest, HmacSha256TooShortMac) {
- GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA_2_256)
- .Authorization(TAG_MIN_MAC_LENGTH, 128));
- string message = "123456789012345678901234567890123456789012345678";
- string signature;
- MacMessage(message, &signature, 256);
-
- // Shorten to 128 bits, should still work.
- signature.resize(128 / 8);
- VerifyMac(message, signature);
-
- // Drop one more byte.
- signature.resize(signature.length() - 1);
-
- AuthorizationSet begin_params(client_params());
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_VERIFY, begin_params));
- string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(KM_ERROR_INVALID_MAC_LENGTH, FinishOperation(signature, &result));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(VerificationOperationsTest, HmacSha384Success) {
- if (GetParam()->minimal_digest_set())
- // Can't emulate missing digests for HMAC.
- return;
-
- GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA_2_384)
- .Authorization(TAG_MIN_MAC_LENGTH, 128));
- string message = "123456789012345678901234567890123456789012345678";
- string signature;
- MacMessage(message, &signature, 384);
- VerifyMac(message, signature);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(VerificationOperationsTest, HmacSha512Success) {
- if (GetParam()->minimal_digest_set())
- // Can't emulate missing digests for HMAC.
- return;
-
- GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA_2_512)
- .Authorization(TAG_MIN_MAC_LENGTH, 128));
- string message = "123456789012345678901234567890123456789012345678";
- string signature;
- MacMessage(message, &signature, 512);
- VerifyMac(message, signature);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-typedef Keymaster2Test ExportKeyTest;
-INSTANTIATE_TEST_CASE_P(AndroidKeymasterTest, ExportKeyTest, test_params);
-#if RSA_TEST
-TEST_P(ExportKeyTest, RsaSuccess) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(256, 3)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_NONE)));
- string export_data;
- ASSERT_EQ(KM_ERROR_OK, ExportKey(KM_KEY_FORMAT_X509, &export_data));
- EXPECT_GT(export_data.length(), 0U);
-
- // TODO(swillden): Verify that the exported key is actually usable to verify signatures.
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-#endif
-#if EC_TEST
-TEST_P(ExportKeyTest, EcdsaSuccess) {
- ASSERT_EQ(KM_ERROR_OK,
- GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(224).Digest(KM_DIGEST_NONE)));
- string export_data;
- ASSERT_EQ(KM_ERROR_OK, ExportKey(KM_KEY_FORMAT_X509, &export_data));
- EXPECT_GT(export_data.length(), 0U);
-
- // TODO(swillden): Verify that the exported key is actually usable to verify signatures.
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-#endif
-#if RSA_TEST
-TEST_P(ExportKeyTest, RsaUnsupportedKeyFormat) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(256, 3)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_NONE)));
- string export_data;
- ASSERT_EQ(KM_ERROR_UNSUPPORTED_KEY_FORMAT, ExportKey(KM_KEY_FORMAT_PKCS8, &export_data));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-
-TEST_P(ExportKeyTest, RsaCorruptedKeyBlob) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(256, 3)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_NONE)));
- corrupt_key_blob();
- string export_data;
- ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, ExportKey(KM_KEY_FORMAT_X509, &export_data));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-#endif
-#if AES_TEST
-TEST_P(ExportKeyTest, AesKeyExportFails) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().AesEncryptionKey(128)));
- string export_data;
-
- EXPECT_EQ(KM_ERROR_UNSUPPORTED_KEY_FORMAT, ExportKey(KM_KEY_FORMAT_X509, &export_data));
- EXPECT_EQ(KM_ERROR_UNSUPPORTED_KEY_FORMAT, ExportKey(KM_KEY_FORMAT_PKCS8, &export_data));
- EXPECT_EQ(KM_ERROR_UNSUPPORTED_KEY_FORMAT, ExportKey(KM_KEY_FORMAT_RAW, &export_data));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-static string read_file(const string& file_name) {
- ifstream file_stream(file_name, std::ios::binary);
- istreambuf_iterator<char> file_begin(file_stream);
- istreambuf_iterator<char> file_end;
- return string(file_begin, file_end);
-}
-
-typedef Keymaster2Test ImportKeyTest;
-INSTANTIATE_TEST_CASE_P(AndroidKeymasterTest, ImportKeyTest, test_params);
-#if RSA_TEST
-TEST_P(ImportKeyTest, RsaSuccess) {
- string pk8_key = read_file("rsa_privkey_pk8.der");
- ASSERT_EQ(633U, pk8_key.size());
-
- ASSERT_EQ(KM_ERROR_OK, ImportKey(AuthorizationSetBuilder()
- .RsaSigningKey(1024, 65537)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_NONE),
- KM_KEY_FORMAT_PKCS8, pk8_key));
-
- // Check values derived from the key.
- EXPECT_TRUE(contains(hw_enforced(), TAG_ALGORITHM, KM_ALGORITHM_RSA));
- EXPECT_TRUE(contains(hw_enforced(), TAG_KEY_SIZE, 1024));
- EXPECT_TRUE(contains(hw_enforced(), TAG_RSA_PUBLIC_EXPONENT, 65537U));
-
- // And values provided by AndroidKeymaster
- EXPECT_TRUE(contains(hw_enforced(), TAG_ORIGIN, KM_ORIGIN_IMPORTED));
- EXPECT_TRUE(contains(sw_enforced(), KM_TAG_CREATION_DATETIME));
-
- string message(1024 / 8, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
- VerifyMessage(message, signature, KM_DIGEST_NONE, KM_PAD_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-#endif
-#if RSA_TEST
-TEST_P(ImportKeyTest, RsaKeySizeMismatch) {
- string pk8_key = read_file("rsa_privkey_pk8.der");
- ASSERT_EQ(633U, pk8_key.size());
- ASSERT_EQ(KM_ERROR_IMPORT_PARAMETER_MISMATCH,
- ImportKey(AuthorizationSetBuilder()
- .RsaSigningKey(2048 /* Doesn't match key */, 3)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_NONE),
- KM_KEY_FORMAT_PKCS8, pk8_key));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(ImportKeyTest, RsaPublicExponenMismatch) {
- string pk8_key = read_file("rsa_privkey_pk8.der");
- ASSERT_EQ(633U, pk8_key.size());
- ASSERT_EQ(KM_ERROR_IMPORT_PARAMETER_MISMATCH,
- ImportKey(AuthorizationSetBuilder()
- .RsaSigningKey(256, 3 /* Doesnt' match key */)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_NONE),
- KM_KEY_FORMAT_PKCS8, pk8_key));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-#if EC_TEST
-TEST_P(ImportKeyTest, EcdsaSuccess) {
- string pk8_key = read_file("ec_privkey_pk8.der");
- ASSERT_EQ(138U, pk8_key.size());
-
- ASSERT_EQ(KM_ERROR_OK,
- ImportKey(AuthorizationSetBuilder().EcdsaSigningKey(256).Digest(KM_DIGEST_NONE),
- KM_KEY_FORMAT_PKCS8, pk8_key));
-
- // Check values derived from the key.
- EXPECT_TRUE(contains(hw_enforced(), TAG_ALGORITHM, KM_ALGORITHM_EC));
- EXPECT_TRUE(contains(hw_enforced(), TAG_KEY_SIZE, 256));
-
- // And values provided by AndroidKeymaster
- EXPECT_TRUE(contains(hw_enforced(), TAG_ORIGIN, KM_ORIGIN_IMPORTED));
- EXPECT_TRUE(contains(sw_enforced(), KM_TAG_CREATION_DATETIME));
-
- string message(32, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_NONE);
- VerifyMessage(message, signature, KM_DIGEST_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-
-TEST_P(ImportKeyTest, EcdsaSizeSpecified) {
- string pk8_key = read_file("ec_privkey_pk8.der");
- ASSERT_EQ(138U, pk8_key.size());
-
- ASSERT_EQ(KM_ERROR_OK,
- ImportKey(AuthorizationSetBuilder().EcdsaSigningKey(256).Digest(KM_DIGEST_NONE),
- KM_KEY_FORMAT_PKCS8, pk8_key));
-
- // Check values derived from the key.
- EXPECT_TRUE(contains(hw_enforced(), TAG_ALGORITHM, KM_ALGORITHM_EC));
- EXPECT_TRUE(contains(hw_enforced(), TAG_KEY_SIZE, 256));
-
- // And values provided by AndroidKeymaster
- EXPECT_TRUE(contains(hw_enforced(), TAG_ORIGIN, KM_ORIGIN_IMPORTED));
- EXPECT_TRUE(contains(sw_enforced(), KM_TAG_CREATION_DATETIME));
-
- string message(32, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_NONE);
- VerifyMessage(message, signature, KM_DIGEST_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-
-TEST_P(ImportKeyTest, EcdsaSizeMismatch) {
- string pk8_key = read_file("ec_privkey_pk8.der");
- ASSERT_EQ(138U, pk8_key.size());
- ASSERT_EQ(KM_ERROR_IMPORT_PARAMETER_MISMATCH,
- ImportKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(224 /* Doesn't match key */)
- .Digest(KM_DIGEST_NONE),
- KM_KEY_FORMAT_PKCS8, pk8_key));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-#if AES_TEST
-TEST_P(ImportKeyTest, AesKeySuccess) {
- char key_data[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- string key(key_data, sizeof(key_data));
- ASSERT_EQ(KM_ERROR_OK,
- ImportKey(AuthorizationSetBuilder().AesEncryptionKey(128).EcbMode().Authorization(
- TAG_PADDING, KM_PAD_PKCS7),
- KM_KEY_FORMAT_RAW, key));
-
- EXPECT_TRUE(contains(hw_enforced(), TAG_ORIGIN, KM_ORIGIN_IMPORTED));
- EXPECT_TRUE(contains(sw_enforced(), KM_TAG_CREATION_DATETIME));
-
- string message = "Hello World!";
- string ciphertext = EncryptMessage(message, KM_MODE_ECB, KM_PAD_PKCS7);
- string plaintext = DecryptMessage(ciphertext, KM_MODE_ECB, KM_PAD_PKCS7);
- EXPECT_EQ(message, plaintext);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-#if HMAC_TEST
-TEST_P(ImportKeyTest, HmacSha256KeySuccess) {
- char key_data[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- string key(key_data, sizeof(key_data));
- ASSERT_EQ(KM_ERROR_OK, ImportKey(AuthorizationSetBuilder()
- .HmacKey(sizeof(key_data) * 8)
- .Digest(KM_DIGEST_SHA_2_256)
- .Authorization(TAG_MIN_MAC_LENGTH, 256),
- KM_KEY_FORMAT_RAW, key));
-
- EXPECT_TRUE(contains(hw_enforced(), TAG_ORIGIN, KM_ORIGIN_IMPORTED));
- EXPECT_TRUE(contains(sw_enforced(), KM_TAG_CREATION_DATETIME));
-
- string message = "Hello World!";
- string signature;
- MacMessage(message, &signature, 256);
- VerifyMac(message, signature);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-typedef Keymaster2Test EncryptionOperationsTest;
-INSTANTIATE_TEST_CASE_P(AndroidKeymasterTest, EncryptionOperationsTest, test_params);
-#if RSA_TEST
-TEST_P(EncryptionOperationsTest, RsaNoPaddingSuccess) {
- ASSERT_EQ(KM_ERROR_OK,
- GenerateKey(AuthorizationSetBuilder().RsaEncryptionKey(256, 3).Padding(KM_PAD_NONE)));
-
- string message = "12345678901234567890123456789012";
- string ciphertext1 = EncryptMessage(string(message), KM_PAD_NONE);
- EXPECT_EQ(256U / 8, ciphertext1.size());
-
- string ciphertext2 = EncryptMessage(string(message), KM_PAD_NONE);
- EXPECT_EQ(256U / 8, ciphertext2.size());
-
- // Unpadded RSA is deterministic
- EXPECT_EQ(ciphertext1, ciphertext2);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, RsaNoPaddingTooShort) {
- ASSERT_EQ(KM_ERROR_OK,
- GenerateKey(AuthorizationSetBuilder().RsaEncryptionKey(256, 3).Padding(KM_PAD_NONE)));
-
- string message = "1";
-
- string ciphertext = EncryptMessage(message, KM_PAD_NONE);
- EXPECT_EQ(256U / 8, ciphertext.size());
-
- string expected_plaintext = string(256 / 8 - 1, 0) + message;
- string plaintext = DecryptMessage(ciphertext, KM_PAD_NONE);
-
- EXPECT_EQ(expected_plaintext, plaintext);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, RsaNoPaddingTooLong) {
- ASSERT_EQ(KM_ERROR_OK,
- GenerateKey(AuthorizationSetBuilder().RsaEncryptionKey(256, 3).Padding(KM_PAD_NONE)));
-
- string message = "123456789012345678901234567890123";
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
-
- string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, UpdateOperation(message, &result, &input_consumed));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, RsaNoPaddingLargerThanModulus) {
- ASSERT_EQ(KM_ERROR_OK,
- GenerateKey(AuthorizationSetBuilder().RsaEncryptionKey(256, 3).Padding(KM_PAD_NONE)));
-
- string exported;
- ASSERT_EQ(KM_ERROR_OK, ExportKey(KM_KEY_FORMAT_X509, &exported));
-
- const uint8_t* p = reinterpret_cast<const uint8_t*>(exported.data());
- unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
- d2i_PUBKEY(nullptr /* alloc new */, &p, exported.size()));
- unique_ptr<RSA, RSA_Delete> rsa(EVP_PKEY_get1_RSA(pkey.get()));
-
- size_t modulus_len = BN_num_bytes(rsa->n);
- ASSERT_EQ(256U / 8, modulus_len);
- unique_ptr<uint8_t[]> modulus_buf(new uint8_t[modulus_len]);
- BN_bn2bin(rsa->n, modulus_buf.get());
-
- // The modulus is too big to encrypt.
- string message(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
-
- string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(KM_ERROR_INVALID_ARGUMENT, FinishOperation(&result));
-
- // One smaller than the modulus is okay.
- BN_sub(rsa->n, rsa->n, BN_value_one());
- modulus_len = BN_num_bytes(rsa->n);
- ASSERT_EQ(256U / 8, modulus_len);
- BN_bn2bin(rsa->n, modulus_buf.get());
- message = string(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&result));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-#endif
-#if RSA_TEST
-TEST_P(EncryptionOperationsTest, RsaOaepSuccess) {
- size_t key_size = 768;
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaEncryptionKey(key_size, 3)
- .Padding(KM_PAD_RSA_OAEP)
- .Digest(KM_DIGEST_SHA_2_256)));
-
- string message = "Hello";
- string ciphertext1 = EncryptMessage(string(message), KM_DIGEST_SHA_2_256, KM_PAD_RSA_OAEP);
- EXPECT_EQ(key_size / 8, ciphertext1.size());
-
- string ciphertext2 = EncryptMessage(string(message), KM_DIGEST_SHA_2_256, KM_PAD_RSA_OAEP);
- EXPECT_EQ(key_size / 8, ciphertext2.size());
-
- // OAEP randomizes padding so every result should be different.
- EXPECT_NE(ciphertext1, ciphertext2);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
-}
-#endif
-#if RSA_TEST
-TEST_P(EncryptionOperationsTest, RsaOaepSha224Success) {
- size_t key_size = 768;
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaEncryptionKey(key_size, 3)
- .Padding(KM_PAD_RSA_OAEP)
- .Digest(KM_DIGEST_SHA_2_224)));
-
- string message = "Hello";
- string ciphertext1 = EncryptMessage(string(message), KM_DIGEST_SHA_2_224, KM_PAD_RSA_OAEP);
- EXPECT_EQ(key_size / 8, ciphertext1.size());
-
- string ciphertext2 = EncryptMessage(string(message), KM_DIGEST_SHA_2_224, KM_PAD_RSA_OAEP);
- EXPECT_EQ(key_size / 8, ciphertext2.size());
-
- // OAEP randomizes padding so every result should be different.
- EXPECT_NE(ciphertext1, ciphertext2);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, RsaOaepRoundTrip) {
- size_t key_size = 768;
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaEncryptionKey(key_size, 3)
- .Padding(KM_PAD_RSA_OAEP)
- .Digest(KM_DIGEST_SHA_2_256)));
- string message = "Hello World!";
- string ciphertext = EncryptMessage(string(message), KM_DIGEST_SHA_2_256, KM_PAD_RSA_OAEP);
- EXPECT_EQ(key_size / 8, ciphertext.size());
-
- string plaintext = DecryptMessage(ciphertext, KM_DIGEST_SHA_2_256, KM_PAD_RSA_OAEP);
- EXPECT_EQ(message, plaintext);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, RsaOaepSha224RoundTrip) {
- size_t key_size = 768;
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaEncryptionKey(key_size, 3)
- .Padding(KM_PAD_RSA_OAEP)
- .Digest(KM_DIGEST_SHA_2_224)));
- string message = "Hello World!";
- string ciphertext = EncryptMessage(string(message), KM_DIGEST_SHA_2_224, KM_PAD_RSA_OAEP);
- EXPECT_EQ(key_size / 8, ciphertext.size());
-
- string plaintext = DecryptMessage(ciphertext, KM_DIGEST_SHA_2_224, KM_PAD_RSA_OAEP);
- EXPECT_EQ(message, plaintext);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, RsaOaepInvalidDigest) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaEncryptionKey(512, 3)
- .Padding(KM_PAD_RSA_OAEP)
- .Digest(KM_DIGEST_NONE)));
- string message = "Hello World!";
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, KM_PAD_RSA_OAEP);
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
- EXPECT_EQ(KM_ERROR_INCOMPATIBLE_DIGEST, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, RsaOaepUnauthorizedDigest) {
- if (GetParam()->minimal_digest_set())
- // We don't have two supported digests, so we can't try authorizing one and using another.
- return;
-
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaEncryptionKey(512, 3)
- .Padding(KM_PAD_RSA_OAEP)
- .Digest(KM_DIGEST_SHA_2_256)));
- string message = "Hello World!";
- // Works because encryption is a public key operation.
- EncryptMessage(string(message), KM_DIGEST_SHA1, KM_PAD_RSA_OAEP);
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, KM_PAD_RSA_OAEP);
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA1);
- EXPECT_EQ(KM_ERROR_INCOMPATIBLE_DIGEST, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, RsaOaepDecryptWithWrongDigest) {
- if (GetParam()->minimal_digest_set())
- // We don't have two supported digests, so we can't try encrypting with one and decrypting
- // with another.
- return;
-
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaEncryptionKey(768, 3)
- .Padding(KM_PAD_RSA_OAEP)
- .Digest(KM_DIGEST_SHA_2_256)
- .Digest(KM_DIGEST_SHA_2_384)));
- string message = "Hello World!";
- string ciphertext = EncryptMessage(string(message), KM_DIGEST_SHA_2_256, KM_PAD_RSA_OAEP);
-
- string result;
- size_t input_consumed;
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, KM_PAD_RSA_OAEP);
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA_2_384);
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(ciphertext, &result, &input_consumed));
- EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, FinishOperation(&result));
- EXPECT_EQ(0U, result.size());
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, RsaOaepTooLarge) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaEncryptionKey(512, 3)
- .Padding(KM_PAD_RSA_OAEP)
- .Digest(KM_DIGEST_SHA1)));
- string message = "12345678901234567890123";
- string result;
- size_t input_consumed;
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, KM_PAD_RSA_OAEP);
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA1);
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&result));
- EXPECT_EQ(0U, result.size());
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, RsaOaepCorruptedDecrypt) {
- size_t key_size = 768;
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaEncryptionKey(768, 3)
- .Padding(KM_PAD_RSA_OAEP)
- .Digest(KM_DIGEST_SHA_2_256)));
- string message = "Hello World!";
- string ciphertext = EncryptMessage(string(message), KM_DIGEST_SHA_2_256, KM_PAD_RSA_OAEP);
- EXPECT_EQ(key_size / 8, ciphertext.size());
-
- // Corrupt the ciphertext
- ciphertext[key_size / 8 / 2]++;
-
- string result;
- size_t input_consumed;
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, KM_PAD_RSA_OAEP);
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA_2_256);
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(ciphertext, &result, &input_consumed));
- EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, FinishOperation(&result));
- EXPECT_EQ(0U, result.size());
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-#endif
-#if RSA_TEST
-TEST_P(EncryptionOperationsTest, RsaPkcs1Success) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().RsaEncryptionKey(512, 3).Padding(
- KM_PAD_RSA_PKCS1_1_5_ENCRYPT)));
- string message = "Hello World!";
- string ciphertext1 = EncryptMessage(message, KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
- EXPECT_EQ(512U / 8, ciphertext1.size());
-
- string ciphertext2 = EncryptMessage(message, KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
- EXPECT_EQ(512U / 8, ciphertext2.size());
-
- // PKCS1 v1.5 randomizes padding so every result should be different.
- EXPECT_NE(ciphertext1, ciphertext2);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, RsaPkcs1RoundTrip) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().RsaEncryptionKey(512, 3).Padding(
- KM_PAD_RSA_PKCS1_1_5_ENCRYPT)));
- string message = "Hello World!";
- string ciphertext = EncryptMessage(message, KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
- EXPECT_EQ(512U / 8, ciphertext.size());
-
- string plaintext = DecryptMessage(ciphertext, KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
- EXPECT_EQ(message, plaintext);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-#endif
-#if CHECK_FAIL
-TEST_P(EncryptionOperationsTest, RsaRoundTripAllCombinations) {
- size_t key_size = 2048;
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaEncryptionKey(key_size, 3)
- .Padding(KM_PAD_RSA_PKCS1_1_5_ENCRYPT)
- .Padding(KM_PAD_RSA_OAEP)
- .Digest(KM_DIGEST_NONE)
- .Digest(KM_DIGEST_MD5)
- .Digest(KM_DIGEST_SHA1)
- .Digest(KM_DIGEST_SHA_2_224)
- .Digest(KM_DIGEST_SHA_2_256)
- .Digest(KM_DIGEST_SHA_2_384)
- .Digest(KM_DIGEST_SHA_2_512)));
-
- string message = "Hello World!";
-
- keymaster_padding_t padding_modes[] = {KM_PAD_RSA_OAEP, KM_PAD_RSA_PKCS1_1_5_ENCRYPT};
- keymaster_digest_t digests[] = {
- KM_DIGEST_NONE, KM_DIGEST_MD5, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
- KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512,
- };
-
- for (auto padding : padding_modes)
- for (auto digest : digests) {
- if (padding == KM_PAD_RSA_OAEP && digest == KM_DIGEST_NONE)
- // OAEP requires a digest.
- continue;
-
- string ciphertext = EncryptMessage(message, digest, padding);
- EXPECT_EQ(key_size / 8, ciphertext.size());
-
- string plaintext = DecryptMessage(ciphertext, digest, padding);
- EXPECT_EQ(message, plaintext);
- }
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(40, GetParam()->keymaster0_calls());
-}
-#endif
-#if RSA_TEST
-TEST_P(EncryptionOperationsTest, RsaPkcs1TooLarge) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().RsaEncryptionKey(512, 3).Padding(
- KM_PAD_RSA_PKCS1_1_5_ENCRYPT)));
- string message = "123456789012345678901234567890123456789012345678901234";
- string result;
- size_t input_consumed;
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&result));
- EXPECT_EQ(0U, result.size());
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, RsaPkcs1CorruptedDecrypt) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().RsaEncryptionKey(512, 3).Padding(
- KM_PAD_RSA_PKCS1_1_5_ENCRYPT)));
- string message = "Hello World!";
- string ciphertext = EncryptMessage(string(message), KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
- EXPECT_EQ(512U / 8, ciphertext.size());
-
- // Corrupt the ciphertext
- ciphertext[512 / 8 / 2]++;
-
- string result;
- size_t input_consumed;
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(ciphertext, &result, &input_consumed));
- EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, FinishOperation(&result));
- EXPECT_EQ(0U, result.size());
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, RsaEncryptWithSigningKey) {
- ASSERT_EQ(KM_ERROR_OK,
- GenerateKey(AuthorizationSetBuilder().RsaSigningKey(256, 3).Padding(KM_PAD_NONE)));
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-#endif
-#if EC_TEST
-TEST_P(EncryptionOperationsTest, EcdsaEncrypt) {
- ASSERT_EQ(KM_ERROR_OK,
- GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(224).Digest(KM_DIGEST_NONE)));
- ASSERT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE, BeginOperation(KM_PURPOSE_ENCRYPT));
- ASSERT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE, BeginOperation(KM_PURPOSE_DECRYPT));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
-}
-#endif
-#if HMAC_TEST
-TEST_P(EncryptionOperationsTest, HmacEncrypt) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Digest(KM_DIGEST_SHA_2_256)
- .Padding(KM_PAD_NONE)
- .Authorization(TAG_MIN_MAC_LENGTH, 128)));
- ASSERT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE, BeginOperation(KM_PURPOSE_ENCRYPT));
- ASSERT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE, BeginOperation(KM_PURPOSE_DECRYPT));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-#if AES_TEST
-TEST_P(EncryptionOperationsTest, AesEcbRoundTripSuccess) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_ECB)
- .Padding(KM_PAD_NONE)));
- // Two-block message.
- string message = "12345678901234567890123456789012";
- string ciphertext1 = EncryptMessage(message, KM_MODE_ECB, KM_PAD_NONE);
- EXPECT_EQ(message.size(), ciphertext1.size());
-
- string ciphertext2 = EncryptMessage(string(message), KM_MODE_ECB, KM_PAD_NONE);
- EXPECT_EQ(message.size(), ciphertext2.size());
-
- // ECB is deterministic.
- EXPECT_EQ(ciphertext1, ciphertext2);
-
- string plaintext = DecryptMessage(ciphertext1, KM_MODE_ECB, KM_PAD_NONE);
- EXPECT_EQ(message, plaintext);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, AesEcbNotAuthorized) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_CBC)
- .Padding(KM_PAD_NONE)));
- // Two-block message.
- string message = "12345678901234567890123456789012";
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_ECB);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- EXPECT_EQ(KM_ERROR_INCOMPATIBLE_BLOCK_MODE, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, AesEcbNoPaddingWrongInputSize) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_ECB)
- .Padding(KM_PAD_NONE)));
- // Message is slightly shorter than two blocks.
- string message = "1234567890123456789012345678901";
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_ECB);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
- string ciphertext;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &ciphertext, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&ciphertext));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-#if AES_TEST
-TEST_P(EncryptionOperationsTest, AesEcbPkcs7Padding) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_ECB)
- .Authorization(TAG_PADDING, KM_PAD_PKCS7)));
-
- // Try various message lengths; all should work.
- for (size_t i = 0; i < 32; ++i) {
- string message(i, 'a');
- string ciphertext = EncryptMessage(message, KM_MODE_ECB, KM_PAD_PKCS7);
- EXPECT_EQ(i + 16 - (i % 16), ciphertext.size());
- string plaintext = DecryptMessage(ciphertext, KM_MODE_ECB, KM_PAD_PKCS7);
- EXPECT_EQ(message, plaintext);
- }
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-#if AES_TEST
-TEST_P(EncryptionOperationsTest, AesEcbNoPaddingKeyWithPkcs7Padding) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_ECB)
- .Authorization(TAG_PADDING, KM_PAD_NONE)));
-
- // Try various message lengths; all should fail.
- for (size_t i = 0; i < 32; ++i) {
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_ECB);
- begin_params.push_back(TAG_PADDING, KM_PAD_PKCS7);
- EXPECT_EQ(KM_ERROR_INCOMPATIBLE_PADDING_MODE,
- BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
- }
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-
-#if AES_TEST
-TEST_P(EncryptionOperationsTest, AesEcbPkcs7PaddingCorrupted) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_ECB)
- .Authorization(TAG_PADDING, KM_PAD_PKCS7)));
-
- string message = "a";
- string ciphertext = EncryptMessage(message, KM_MODE_ECB, KM_PAD_PKCS7);
- EXPECT_EQ(16U, ciphertext.size());
- EXPECT_NE(ciphertext, message);
- ++ciphertext[ciphertext.size() / 2];
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_ECB);
- begin_params.push_back(TAG_PADDING, KM_PAD_PKCS7);
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
- string plaintext;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(ciphertext, &plaintext, &input_consumed));
- EXPECT_EQ(ciphertext.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_INVALID_ARGUMENT, FinishOperation(&plaintext));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-
-#if AES_TEST
-TEST_P(EncryptionOperationsTest, AesCtrRoundTripSuccess) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_CTR)
- .Padding(KM_PAD_NONE)));
- string message = "123";
- string iv1;
- string ciphertext1 = EncryptMessage(message, KM_MODE_CTR, KM_PAD_NONE, &iv1);
- EXPECT_EQ(message.size(), ciphertext1.size());
- EXPECT_EQ(16U, iv1.size());
-
- string iv2;
- string ciphertext2 = EncryptMessage(message, KM_MODE_CTR, KM_PAD_NONE, &iv2);
- EXPECT_EQ(message.size(), ciphertext2.size());
- EXPECT_EQ(16U, iv2.size());
-
- // IVs should be random, so ciphertexts should differ.
- EXPECT_NE(iv1, iv2);
- EXPECT_NE(ciphertext1, ciphertext2);
-
- string plaintext = DecryptMessage(ciphertext1, KM_MODE_CTR, KM_PAD_NONE, iv1);
- EXPECT_EQ(message, plaintext);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, AesCtrIncremental) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_CTR)
- .Padding(KM_PAD_NONE)));
-
- int increment = 15;
- string message(239, 'a');
- AuthorizationSet input_params(client_params());
- input_params.push_back(TAG_BLOCK_MODE, KM_MODE_CTR);
- input_params.push_back(TAG_PADDING, KM_PAD_NONE);
- AuthorizationSet output_params;
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, input_params, &output_params));
-
- string ciphertext;
- size_t input_consumed;
- for (size_t i = 0; i < message.size(); i += increment)
- EXPECT_EQ(KM_ERROR_OK,
- UpdateOperation(message.substr(i, increment), &ciphertext, &input_consumed));
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&ciphertext));
- EXPECT_EQ(message.size(), ciphertext.size());
-
- // Move TAG_NONCE into input_params
- input_params.Reinitialize(output_params);
- input_params.push_back(client_params());
- input_params.push_back(TAG_BLOCK_MODE, KM_MODE_CTR);
- input_params.push_back(TAG_PADDING, KM_PAD_NONE);
- output_params.Clear();
-
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_DECRYPT, input_params, &output_params));
- string plaintext;
- for (size_t i = 0; i < ciphertext.size(); i += increment)
- EXPECT_EQ(KM_ERROR_OK,
- UpdateOperation(ciphertext.substr(i, increment), &plaintext, &input_consumed));
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&plaintext));
- EXPECT_EQ(ciphertext.size(), plaintext.size());
- EXPECT_EQ(message, plaintext);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-struct AesCtrSp80038aTestVector {
- const char* key;
- const char* nonce;
- const char* plaintext;
- const char* ciphertext;
-};
-
-// These test vectors are taken from
-// http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf, section F.5.
-static const AesCtrSp80038aTestVector kAesCtrSp80038aTestVectors[] = {
- // AES-128
- {
- "2b7e151628aed2a6abf7158809cf4f3c", "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
- "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51"
- "30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
- "874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff"
- "5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee",
- },
- // AES-192
- {
- "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
- "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51"
- "30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
- "1abc932417521ca24f2b0459fe7e6e0b090339ec0aa6faefd5ccc2c6f4ce8e94"
- "1e36b26bd1ebc670d1bd1d665620abf74f78a7f6d29809585a97daec58c6b050",
- },
- // AES-256
- {
- "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
- "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
- "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51"
- "30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
- "601ec313775789a5b7a7f504bbf3d228f443e3ca4d62b59aca84e990cacaf5c5"
- "2b0930daa23de94ce87017ba2d84988ddfc9c58db67aada613c2dd08457941a6",
- },
-};
-
-TEST_P(EncryptionOperationsTest, AesCtrSp80038aTestVector) {
- for (size_t i = 0; i < 3; i++) {
- const AesCtrSp80038aTestVector& test(kAesCtrSp80038aTestVectors[i]);
- const string key = hex2str(test.key);
- const string nonce = hex2str(test.nonce);
- const string plaintext = hex2str(test.plaintext);
- const string ciphertext = hex2str(test.ciphertext);
- CheckAesCtrTestVector(key, nonce, plaintext, ciphertext);
- }
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, AesCtrInvalidPaddingMode) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_CTR)
- .Authorization(TAG_PADDING, KM_PAD_PKCS7)));
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_CTR);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- EXPECT_EQ(KM_ERROR_INCOMPATIBLE_PADDING_MODE, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, AesCtrInvalidCallerNonce) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_CTR)
- .Authorization(TAG_CALLER_NONCE)
- .Padding(KM_PAD_NONE)));
-
- AuthorizationSet input_params(client_params());
- input_params.push_back(TAG_BLOCK_MODE, KM_MODE_CTR);
- input_params.push_back(TAG_PADDING, KM_PAD_NONE);
- input_params.push_back(TAG_NONCE, "123", 3);
- EXPECT_EQ(KM_ERROR_INVALID_NONCE, BeginOperation(KM_PURPOSE_ENCRYPT, input_params));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, AesCbcRoundTripSuccess) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_CBC)
- .Padding(KM_PAD_NONE)));
- // Two-block message.
- string message = "12345678901234567890123456789012";
- string iv1;
- string ciphertext1 = EncryptMessage(message, KM_MODE_CBC, KM_PAD_NONE, &iv1);
- EXPECT_EQ(message.size(), ciphertext1.size());
-
- string iv2;
- string ciphertext2 = EncryptMessage(message, KM_MODE_CBC, KM_PAD_NONE, &iv2);
- EXPECT_EQ(message.size(), ciphertext2.size());
-
- // IVs should be random, so ciphertexts should differ.
- EXPECT_NE(iv1, iv2);
- EXPECT_NE(ciphertext1, ciphertext2);
-
- string plaintext = DecryptMessage(ciphertext1, KM_MODE_CBC, KM_PAD_NONE, iv1);
- EXPECT_EQ(message, plaintext);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, AesCallerNonce) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_CBC)
- .Authorization(TAG_CALLER_NONCE)
- .Padding(KM_PAD_NONE)));
- string message = "12345678901234567890123456789012";
- string iv1;
- // Don't specify nonce, should get a random one.
- string ciphertext1 = EncryptMessage(message, KM_MODE_CBC, KM_PAD_NONE, &iv1);
- EXPECT_EQ(message.size(), ciphertext1.size());
- EXPECT_EQ(16U, iv1.size());
-
- string plaintext = DecryptMessage(ciphertext1, KM_MODE_CBC, KM_PAD_NONE, iv1);
- EXPECT_EQ(message, plaintext);
-
- // Now specify a nonce, should also work.
- AuthorizationSet input_params(client_params());
- AuthorizationSet update_params;
- AuthorizationSet output_params;
- input_params.push_back(TAG_NONCE, "abcdefghijklmnop", 16);
- input_params.push_back(TAG_BLOCK_MODE, KM_MODE_CBC);
- input_params.push_back(TAG_PADDING, KM_PAD_NONE);
- string ciphertext2 =
- ProcessMessage(KM_PURPOSE_ENCRYPT, message, input_params, update_params, &output_params);
-
- // Decrypt with correct nonce.
- plaintext = ProcessMessage(KM_PURPOSE_DECRYPT, ciphertext2, input_params, update_params,
- &output_params);
- EXPECT_EQ(message, plaintext);
-
- // Now try with wrong nonce.
- input_params.Reinitialize(client_params());
- input_params.push_back(TAG_BLOCK_MODE, KM_MODE_CBC);
- input_params.push_back(TAG_PADDING, KM_PAD_NONE);
- input_params.push_back(TAG_NONCE, "aaaaaaaaaaaaaaaa", 16);
- plaintext = ProcessMessage(KM_PURPOSE_DECRYPT, ciphertext2, input_params, update_params,
- &output_params);
- EXPECT_NE(message, plaintext);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, AesCallerNonceProhibited) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_CBC)
- .Padding(KM_PAD_NONE)));
-
- string message = "12345678901234567890123456789012";
- string iv1;
- // Don't specify nonce, should get a random one.
- string ciphertext1 = EncryptMessage(message, KM_MODE_CBC, KM_PAD_NONE, &iv1);
- EXPECT_EQ(message.size(), ciphertext1.size());
- EXPECT_EQ(16U, iv1.size());
-
- string plaintext = DecryptMessage(ciphertext1, KM_MODE_CBC, KM_PAD_NONE, iv1);
- EXPECT_EQ(message, plaintext);
-
- // Now specify a nonce, should fail.
- AuthorizationSet input_params(client_params());
- AuthorizationSet update_params;
- AuthorizationSet output_params;
- input_params.push_back(TAG_NONCE, "abcdefghijklmnop", 16);
- input_params.push_back(TAG_BLOCK_MODE, KM_MODE_CBC);
- input_params.push_back(TAG_PADDING, KM_PAD_NONE);
-
- EXPECT_EQ(KM_ERROR_CALLER_NONCE_PROHIBITED,
- BeginOperation(KM_PURPOSE_ENCRYPT, input_params, &output_params));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, AesCbcIncrementalNoPadding) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_CBC)
- .Padding(KM_PAD_NONE)));
-
- int increment = 15;
- string message(240, 'a');
- AuthorizationSet input_params(client_params());
- input_params.push_back(TAG_BLOCK_MODE, KM_MODE_CBC);
- input_params.push_back(TAG_PADDING, KM_PAD_NONE);
- AuthorizationSet output_params;
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, input_params, &output_params));
-
- string ciphertext;
- size_t input_consumed;
- for (size_t i = 0; i < message.size(); i += increment)
- EXPECT_EQ(KM_ERROR_OK,
- UpdateOperation(message.substr(i, increment), &ciphertext, &input_consumed));
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&ciphertext));
- EXPECT_EQ(message.size(), ciphertext.size());
-
- // Move TAG_NONCE into input_params
- input_params.Reinitialize(output_params);
- input_params.push_back(client_params());
- input_params.push_back(TAG_BLOCK_MODE, KM_MODE_CBC);
- input_params.push_back(TAG_PADDING, KM_PAD_NONE);
- output_params.Clear();
-
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_DECRYPT, input_params, &output_params));
- string plaintext;
- for (size_t i = 0; i < ciphertext.size(); i += increment)
- EXPECT_EQ(KM_ERROR_OK,
- UpdateOperation(ciphertext.substr(i, increment), &plaintext, &input_consumed));
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&plaintext));
- EXPECT_EQ(ciphertext.size(), plaintext.size());
- EXPECT_EQ(message, plaintext);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-
-#if AES_TEST
-TEST_P(EncryptionOperationsTest, AesCbcPkcs7Padding) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_CBC)
- .Authorization(TAG_PADDING, KM_PAD_PKCS7)));
-
- // Try various message lengths; all should work.
- for (size_t i = 0; i < 32; ++i) {
- string message(i, 'a');
- string iv;
- string ciphertext = EncryptMessage(message, KM_MODE_CBC, KM_PAD_PKCS7, &iv);
- EXPECT_EQ(i + 16 - (i % 16), ciphertext.size());
- string plaintext = DecryptMessage(ciphertext, KM_MODE_CBC, KM_PAD_PKCS7, iv);
- EXPECT_EQ(message, plaintext);
- }
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-#if AES_TEST
-TEST_P(EncryptionOperationsTest, AesGcmRoundTripSuccess) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_GCM)
- .Authorization(TAG_PADDING, KM_PAD_NONE)
- .Authorization(TAG_MIN_MAC_LENGTH, 128)));
- string aad = "foobar";
- string message = "123456789012345678901234567890123456";
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_GCM);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- begin_params.push_back(TAG_MAC_LENGTH, 128);
-
- AuthorizationSet update_params;
- update_params.push_back(TAG_ASSOCIATED_DATA, aad.data(), aad.size());
-
- // Encrypt
- AuthorizationSet begin_out_params;
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params, &begin_out_params));
- string ciphertext;
- size_t input_consumed;
- AuthorizationSet update_out_params;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, message, &update_out_params, &ciphertext,
- &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&ciphertext));
-
- // Grab nonce
- EXPECT_NE(-1, begin_out_params.find(TAG_NONCE));
- begin_params.push_back(begin_out_params);
-
- // Decrypt.
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
- string plaintext;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, ciphertext, &update_out_params,
- &plaintext, &input_consumed));
- EXPECT_EQ(ciphertext.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&plaintext));
-
- EXPECT_EQ(message, plaintext);
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, AesGcmTooShortTag) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_GCM)
- .Authorization(TAG_PADDING, KM_PAD_NONE)
- .Authorization(TAG_MIN_MAC_LENGTH, 128)));
- string aad = "foobar";
- string message = "123456789012345678901234567890123456";
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_GCM);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- begin_params.push_back(TAG_MAC_LENGTH, 96);
-
- AuthorizationSet update_params;
- update_params.push_back(TAG_ASSOCIATED_DATA, aad.data(), aad.size());
-
- AuthorizationSet begin_out_params;
- EXPECT_EQ(KM_ERROR_INVALID_MAC_LENGTH,
- BeginOperation(KM_PURPOSE_ENCRYPT, begin_params, &begin_out_params));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, AesGcmTooShortTagOnDecrypt) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_GCM)
- .Authorization(TAG_PADDING, KM_PAD_NONE)
- .Authorization(TAG_MIN_MAC_LENGTH, 128)));
- string aad = "foobar";
- string message = "123456789012345678901234567890123456";
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_GCM);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- begin_params.push_back(TAG_MAC_LENGTH, 128);
-
- AuthorizationSet update_params;
- update_params.push_back(TAG_ASSOCIATED_DATA, aad.data(), aad.size());
-
- // Encrypt
- AuthorizationSet begin_out_params;
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params, &begin_out_params));
- string ciphertext;
- size_t input_consumed;
- AuthorizationSet update_out_params;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, message, &update_out_params, &ciphertext,
- &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&ciphertext));
-
- // Grab nonce
- EXPECT_NE(-1, begin_out_params.find(TAG_NONCE));
- begin_params.Reinitialize(client_params());
- begin_params.push_back(begin_out_params);
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_GCM);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- begin_params.push_back(TAG_MAC_LENGTH, 96);
-
- // Decrypt.
- EXPECT_EQ(KM_ERROR_INVALID_MAC_LENGTH, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, AesGcmCorruptKey) {
- uint8_t nonce[] = {
- 0xb7, 0x94, 0x37, 0xae, 0x08, 0xff, 0x35, 0x5d, 0x7d, 0x8a, 0x4d, 0x0f,
- };
- uint8_t ciphertext[] = {
- 0xb3, 0xf6, 0x79, 0x9e, 0x8f, 0x93, 0x26, 0xf2, 0xdf, 0x1e, 0x80, 0xfc, 0xd2, 0xcb, 0x16,
- 0xd7, 0x8c, 0x9d, 0xc7, 0xcc, 0x14, 0xbb, 0x67, 0x78, 0x62, 0xdc, 0x6c, 0x63, 0x9b, 0x3a,
- 0x63, 0x38, 0xd2, 0x4b, 0x31, 0x2d, 0x39, 0x89, 0xe5, 0x92, 0x0b, 0x5d, 0xbf, 0xc9, 0x76,
- 0x76, 0x5e, 0xfb, 0xfe, 0x57, 0xbb, 0x38, 0x59, 0x40, 0xa7, 0xa4, 0x3b, 0xdf, 0x05, 0xbd,
- 0xda, 0xe3, 0xc9, 0xd6, 0xa2, 0xfb, 0xbd, 0xfc, 0xc0, 0xcb, 0xa0,
- };
- string ciphertext_str(reinterpret_cast<char*>(ciphertext), sizeof(ciphertext));
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_GCM);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- begin_params.push_back(TAG_MAC_LENGTH, 128);
- begin_params.push_back(TAG_NONCE, nonce, sizeof(nonce));
-
- string plaintext;
- size_t input_consumed;
-
- // Import correct key and decrypt
- uint8_t good_key[] = {
- 0xba, 0x76, 0x35, 0x4f, 0x0a, 0xed, 0x6e, 0x8d,
- 0x91, 0xf4, 0x5c, 0x4f, 0xf5, 0xa0, 0x62, 0xdb,
- };
- string good_key_str(reinterpret_cast<char*>(good_key), sizeof(good_key));
- ASSERT_EQ(KM_ERROR_OK, ImportKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_GCM)
- .Authorization(TAG_PADDING, KM_PAD_NONE)
- .Authorization(TAG_CALLER_NONCE)
- .Authorization(TAG_MIN_MAC_LENGTH, 128),
- KM_KEY_FORMAT_RAW, good_key_str));
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(ciphertext_str, &plaintext, &input_consumed));
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&plaintext));
-
- // Import bad key and decrypt
- uint8_t bad_key[] = {
- 0xbb, 0x76, 0x35, 0x4f, 0x0a, 0xed, 0x6e, 0x8d,
- 0x91, 0xf4, 0x5c, 0x4f, 0xf5, 0xa0, 0x62, 0xdb,
- };
- string bad_key_str(reinterpret_cast<char*>(bad_key), sizeof(bad_key));
- ASSERT_EQ(KM_ERROR_OK, ImportKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_GCM)
- .Authorization(TAG_PADDING, KM_PAD_NONE)
- .Authorization(TAG_MIN_MAC_LENGTH, 128),
- KM_KEY_FORMAT_RAW, bad_key_str));
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(ciphertext_str, &plaintext, &input_consumed));
- EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(&plaintext));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, AesGcmAadNoData) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_GCM)
- .Authorization(TAG_PADDING, KM_PAD_NONE)
- .Authorization(TAG_MIN_MAC_LENGTH, 128)));
- string aad = "123456789012345678";
- string empty_message;
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_GCM);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- begin_params.push_back(TAG_MAC_LENGTH, 128);
-
- AuthorizationSet update_params;
- update_params.push_back(TAG_ASSOCIATED_DATA, aad.data(), aad.size());
-
- // Encrypt
- AuthorizationSet begin_out_params;
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params, &begin_out_params));
- string ciphertext;
- size_t input_consumed;
- AuthorizationSet update_out_params;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, empty_message, &update_out_params,
- &ciphertext, &input_consumed));
- EXPECT_EQ(0U, input_consumed);
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&ciphertext));
-
- // Grab nonce
- EXPECT_NE(-1, begin_out_params.find(TAG_NONCE));
- begin_params.push_back(begin_out_params);
-
- // Decrypt.
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
- string plaintext;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, ciphertext, &update_out_params,
- &plaintext, &input_consumed));
- EXPECT_EQ(ciphertext.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&plaintext));
-
- EXPECT_EQ(empty_message, plaintext);
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-#if AES_TEST
-TEST_P(EncryptionOperationsTest, AesGcmIncremental) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_GCM)
- .Authorization(TAG_PADDING, KM_PAD_NONE)
- .Authorization(TAG_MIN_MAC_LENGTH, 128)));
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_GCM);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- begin_params.push_back(TAG_MAC_LENGTH, 128);
-
- AuthorizationSet update_params;
- update_params.push_back(TAG_ASSOCIATED_DATA, "b", 1);
-
- // Encrypt
- AuthorizationSet begin_out_params;
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params, &begin_out_params));
- string ciphertext;
- size_t input_consumed;
- AuthorizationSet update_out_params;
-
- // Send AAD, incrementally
- for (int i = 0; i < 1000; ++i) {
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, "", &update_out_params, &ciphertext,
- &input_consumed));
- EXPECT_EQ(0U, input_consumed);
- EXPECT_EQ(0U, ciphertext.size());
- }
-
- // Now send data, incrementally, no data.
- AuthorizationSet empty_params;
- for (int i = 0; i < 1000; ++i) {
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(empty_params, "a", &update_out_params, &ciphertext,
- &input_consumed));
- EXPECT_EQ(1U, input_consumed);
- }
- EXPECT_EQ(1000U, ciphertext.size());
-
- // And finish.
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&ciphertext));
- EXPECT_EQ(1016U, ciphertext.size());
-
- // Grab nonce
- EXPECT_NE(-1, begin_out_params.find(TAG_NONCE));
- begin_params.push_back(begin_out_params);
-
- // Decrypt.
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
- string plaintext;
-
- // Send AAD, incrementally, no data
- for (int i = 0; i < 1000; ++i) {
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, "", &update_out_params, &plaintext,
- &input_consumed));
- EXPECT_EQ(0U, input_consumed);
- EXPECT_EQ(0U, plaintext.size());
- }
-
- // Now send data, incrementally.
- for (size_t i = 0; i < ciphertext.length(); ++i) {
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(empty_params, string(ciphertext.data() + i, 1),
- &update_out_params, &plaintext, &input_consumed));
- EXPECT_EQ(1U, input_consumed);
- }
- EXPECT_EQ(1000U, plaintext.size());
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&plaintext));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, AesGcmMultiPartAad) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_GCM)
- .Authorization(TAG_PADDING, KM_PAD_NONE)
- .Authorization(TAG_MIN_MAC_LENGTH, 128)));
- string message = "123456789012345678901234567890123456";
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_GCM);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- begin_params.push_back(TAG_MAC_LENGTH, 128);
- AuthorizationSet begin_out_params;
-
- AuthorizationSet update_params;
- update_params.push_back(TAG_ASSOCIATED_DATA, "foo", 3);
-
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params, &begin_out_params));
-
- // No data, AAD only.
- string ciphertext;
- size_t input_consumed;
- AuthorizationSet update_out_params;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, "" /* message */, &update_out_params,
- &ciphertext, &input_consumed));
- EXPECT_EQ(0U, input_consumed);
-
- // AAD and data.
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, message, &update_out_params, &ciphertext,
- &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&ciphertext));
-
- // Grab nonce.
- EXPECT_NE(-1, begin_out_params.find(TAG_NONCE));
- begin_params.push_back(begin_out_params);
-
- // Decrypt
- update_params.Clear();
- update_params.push_back(TAG_ASSOCIATED_DATA, "foofoo", 6);
-
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
- string plaintext;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, ciphertext, &update_out_params,
- &plaintext, &input_consumed));
- EXPECT_EQ(ciphertext.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&plaintext));
-
- EXPECT_EQ(message, plaintext);
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, AesGcmBadAad) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_GCM)
- .Authorization(TAG_PADDING, KM_PAD_NONE)
- .Authorization(TAG_MIN_MAC_LENGTH, 128)));
- string message = "12345678901234567890123456789012";
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_GCM);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- begin_params.push_back(TAG_MAC_LENGTH, 128);
-
- AuthorizationSet update_params;
- update_params.push_back(TAG_ASSOCIATED_DATA, "foobar", 6);
-
- AuthorizationSet finish_params;
- AuthorizationSet finish_out_params;
-
- // Encrypt
- AuthorizationSet begin_out_params;
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params, &begin_out_params));
- AuthorizationSet update_out_params;
- string ciphertext;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, message, &update_out_params, &ciphertext,
- &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&ciphertext));
-
- // Grab nonce
- EXPECT_NE(-1, begin_out_params.find(TAG_NONCE));
- begin_params.push_back(begin_out_params);
-
- update_params.Clear();
- update_params.push_back(TAG_ASSOCIATED_DATA, "barfoo" /* Wrong AAD */, 6);
-
- // Decrypt.
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_DECRYPT, begin_params, &begin_out_params));
- string plaintext;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, ciphertext, &update_out_params,
- &plaintext, &input_consumed));
- EXPECT_EQ(ciphertext.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(&plaintext));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, AesGcmWrongNonce) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_GCM)
- .Authorization(TAG_PADDING, KM_PAD_NONE)
- .Authorization(TAG_MIN_MAC_LENGTH, 128)));
- string message = "12345678901234567890123456789012";
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_GCM);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- begin_params.push_back(TAG_MAC_LENGTH, 128);
-
- AuthorizationSet update_params;
- update_params.push_back(TAG_ASSOCIATED_DATA, "foobar", 6);
-
- // Encrypt
- AuthorizationSet begin_out_params;
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params, &begin_out_params));
- AuthorizationSet update_out_params;
- string ciphertext;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, message, &update_out_params, &ciphertext,
- &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&ciphertext));
-
- begin_params.push_back(TAG_NONCE, "123456789012", 12);
-
- // Decrypt
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_DECRYPT, begin_params, &begin_out_params));
- string plaintext;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, ciphertext, &update_out_params,
- &plaintext, &input_consumed));
- EXPECT_EQ(ciphertext.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(&plaintext));
-
- // With wrong nonce, should have gotten garbage plaintext.
- EXPECT_NE(message, plaintext);
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-#if AES_TEST
-TEST_P(EncryptionOperationsTest, AesGcmCorruptTag) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_GCM)
- .Authorization(TAG_PADDING, KM_PAD_NONE)
- .Authorization(TAG_MIN_MAC_LENGTH, 128)));
- string aad = "foobar";
- string message = "123456789012345678901234567890123456";
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_GCM);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- begin_params.push_back(TAG_MAC_LENGTH, 128);
- AuthorizationSet begin_out_params;
-
- AuthorizationSet update_params;
- update_params.push_back(TAG_ASSOCIATED_DATA, aad.data(), aad.size());
-
- // Encrypt
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params, &begin_out_params));
- AuthorizationSet update_out_params;
- string ciphertext;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, message, &update_out_params, &ciphertext,
- &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&ciphertext));
-
- // Corrupt tag
- (*ciphertext.rbegin())++;
-
- // Grab nonce.
- EXPECT_NE(-1, begin_out_params.find(TAG_NONCE));
- begin_params.push_back(begin_out_params);
-
- // Decrypt.
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_DECRYPT, begin_params, &begin_out_params));
- string plaintext;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, ciphertext, &update_out_params,
- &plaintext, &input_consumed));
- EXPECT_EQ(ciphertext.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(&plaintext));
-
- EXPECT_EQ(message, plaintext);
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-typedef Keymaster2Test MaxOperationsTest;
-INSTANTIATE_TEST_CASE_P(AndroidKeymasterTest, MaxOperationsTest, test_params);
-#if MAX_TEST
-TEST_P(MaxOperationsTest, TestLimit) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .EcbMode()
- .Authorization(TAG_PADDING, KM_PAD_NONE)
- .Authorization(TAG_MAX_USES_PER_BOOT, 3)));
-
- string message = "1234567890123456";
- string ciphertext1 = EncryptMessage(message, KM_MODE_ECB, KM_PAD_NONE);
- string ciphertext2 = EncryptMessage(message, KM_MODE_ECB, KM_PAD_NONE);
- string ciphertext3 = EncryptMessage(message, KM_MODE_ECB, KM_PAD_NONE);
-
- // Fourth time should fail.
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_ECB);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- EXPECT_EQ(KM_ERROR_KEY_MAX_OPS_EXCEEDED, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(MaxOperationsTest, TestAbort) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .EcbMode()
- .Authorization(TAG_PADDING, KM_PAD_NONE)
- .Authorization(TAG_MAX_USES_PER_BOOT, 3)));
-
- string message = "1234567890123456";
- string ciphertext1 = EncryptMessage(message, KM_MODE_ECB, KM_PAD_NONE);
- string ciphertext2 = EncryptMessage(message, KM_MODE_ECB, KM_PAD_NONE);
- string ciphertext3 = EncryptMessage(message, KM_MODE_ECB, KM_PAD_NONE);
-
- // Fourth time should fail.
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_ECB);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- EXPECT_EQ(KM_ERROR_KEY_MAX_OPS_EXCEEDED, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-typedef Keymaster2Test AddEntropyTest;
-INSTANTIATE_TEST_CASE_P(AndroidKeymasterTest, AddEntropyTest, test_params);
-#if ENTROPY_TEST
-TEST_P(AddEntropyTest, AddEntropy) {
- // There's no obvious way to test that entropy is actually added, but we can test that the API
- // doesn't blow up or return an error.
- EXPECT_EQ(KM_ERROR_OK,
- device()->add_rng_entropy(device(), reinterpret_cast<const uint8_t*>("foo"), 3));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-typedef Keymaster2Test Keymaster0AdapterTest;
-#if 0
-INSTANTIATE_TEST_CASE_P(
- AndroidKeymasterTest, Keymaster0AdapterTest,
- ::testing::Values(
- InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator(true /* support_ec */)),
- InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator(false /* support_ec */))));
-#endif
-TEST_P(Keymaster0AdapterTest, OldSoftwareKeymaster1RsaBlob) {
- // Load and use an old-style Keymaster1 software key blob. These blobs contain OCB-encrypted
- // key data.
- string km1_sw = read_file("km1_sw_rsa_512.blob");
- EXPECT_EQ(486U, km1_sw.length());
-
- uint8_t* key_data = reinterpret_cast<uint8_t*>(malloc(km1_sw.length()));
- memcpy(key_data, km1_sw.data(), km1_sw.length());
- set_key_blob(key_data, km1_sw.length());
-
- string message(64, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(Keymaster0AdapterTest, UnversionedSoftwareKeymaster1RsaBlob) {
- // Load and use an old-style Keymaster1 software key blob, without the version byte. These
- // blobs contain OCB-encrypted key data.
- string km1_sw = read_file("km1_sw_rsa_512_unversioned.blob");
- EXPECT_EQ(477U, km1_sw.length());
-
- uint8_t* key_data = reinterpret_cast<uint8_t*>(malloc(km1_sw.length()));
- memcpy(key_data, km1_sw.data(), km1_sw.length());
- set_key_blob(key_data, km1_sw.length());
-
- string message(64, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(Keymaster0AdapterTest, OldSoftwareKeymaster1EcdsaBlob) {
- // Load and use an old-style Keymaster1 software key blob. These blobs contain OCB-encrypted
- // key data.
- string km1_sw = read_file("km1_sw_ecdsa_256.blob");
- EXPECT_EQ(270U, km1_sw.length());
-
- uint8_t* key_data = reinterpret_cast<uint8_t*>(malloc(km1_sw.length()));
- memcpy(key_data, km1_sw.data(), km1_sw.length());
- set_key_blob(key_data, km1_sw.length());
-
- string message(32, static_cast<char>(0xFF));
- string signature;
- SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-struct Malloc_Delete {
- void operator()(void* p) { free(p); }
-};
-
-TEST_P(Keymaster0AdapterTest, OldSoftwareKeymaster0RsaBlob) {
- // Load and use an old softkeymaster blob. These blobs contain PKCS#8 key data.
- string km0_sw = read_file("km0_sw_rsa_512.blob");
- EXPECT_EQ(333U, km0_sw.length());
-
- uint8_t* key_data = reinterpret_cast<uint8_t*>(malloc(km0_sw.length()));
- memcpy(key_data, km0_sw.data(), km0_sw.length());
- set_key_blob(key_data, km0_sw.length());
-
- string message(64, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(Keymaster0AdapterTest, OldSwKeymaster0RsaBlobGetCharacteristics) {
- // Load and use an old softkeymaster blob. These blobs contain PKCS#8 key data.
- string km0_sw = read_file("km0_sw_rsa_512.blob");
- EXPECT_EQ(333U, km0_sw.length());
-
- uint8_t* key_data = reinterpret_cast<uint8_t*>(malloc(km0_sw.length()));
- memcpy(key_data, km0_sw.data(), km0_sw.length());
- set_key_blob(key_data, km0_sw.length());
-
- EXPECT_EQ(KM_ERROR_OK, GetCharacteristics());
- EXPECT_TRUE(contains(sw_enforced(), TAG_ALGORITHM, KM_ALGORITHM_RSA));
- EXPECT_TRUE(contains(sw_enforced(), TAG_KEY_SIZE, 512));
- EXPECT_TRUE(contains(sw_enforced(), TAG_RSA_PUBLIC_EXPONENT, 3));
- EXPECT_TRUE(contains(sw_enforced(), TAG_DIGEST, KM_DIGEST_NONE));
- EXPECT_TRUE(contains(sw_enforced(), TAG_PADDING, KM_PAD_NONE));
- EXPECT_TRUE(contains(sw_enforced(), TAG_PURPOSE, KM_PURPOSE_SIGN));
- EXPECT_TRUE(contains(sw_enforced(), TAG_PURPOSE, KM_PURPOSE_VERIFY));
- EXPECT_TRUE(sw_enforced().GetTagValue(TAG_ALL_USERS));
- EXPECT_TRUE(sw_enforced().GetTagValue(TAG_NO_AUTH_REQUIRED));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(Keymaster0AdapterTest, OldHwKeymaster0RsaBlob) {
- // Load and use an old softkeymaster blob. These blobs contain PKCS#8 key data.
- string km0_sw = read_file("km0_sw_rsa_512.blob");
- EXPECT_EQ(333U, km0_sw.length());
-
- // The keymaster0 wrapper swaps the old softkeymaster leading 'P' for a 'Q' to make the key not
- // be recognized as a software key. Do the same here to pretend this is a hardware key.
- EXPECT_EQ('P', km0_sw[0]);
- km0_sw[0] = 'Q';
-
- uint8_t* key_data = reinterpret_cast<uint8_t*>(malloc(km0_sw.length()));
- memcpy(key_data, km0_sw.data(), km0_sw.length());
- set_key_blob(key_data, km0_sw.length());
-
- string message(64, 'a');
- string signature;
- SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
- VerifyMessage(message, signature, KM_DIGEST_NONE, KM_PAD_NONE);
-
- EXPECT_EQ(5, GetParam()->keymaster0_calls());
-}
-
-TEST_P(Keymaster0AdapterTest, OldHwKeymaster0RsaBlobGetCharacteristics) {
- // Load and use an old softkeymaster blob. These blobs contain PKCS#8 key data.
- string km0_sw = read_file("km0_sw_rsa_512.blob");
- EXPECT_EQ(333U, km0_sw.length());
-
- // The keymaster0 wrapper swaps the old softkeymaster leading 'P' for a 'Q' to make the key not
- // be recognized as a software key. Do the same here to pretend this is a hardware key.
- EXPECT_EQ('P', km0_sw[0]);
- km0_sw[0] = 'Q';
-
- uint8_t* key_data = reinterpret_cast<uint8_t*>(malloc(km0_sw.length()));
- memcpy(key_data, km0_sw.data(), km0_sw.length());
- set_key_blob(key_data, km0_sw.length());
-
- EXPECT_EQ(KM_ERROR_OK, GetCharacteristics());
- EXPECT_TRUE(contains(hw_enforced(), TAG_ALGORITHM, KM_ALGORITHM_RSA));
- EXPECT_TRUE(contains(hw_enforced(), TAG_KEY_SIZE, 512));
- EXPECT_TRUE(contains(hw_enforced(), TAG_RSA_PUBLIC_EXPONENT, 3));
- EXPECT_TRUE(contains(hw_enforced(), TAG_DIGEST, KM_DIGEST_NONE));
- EXPECT_TRUE(contains(hw_enforced(), TAG_DIGEST, KM_DIGEST_MD5));
- EXPECT_TRUE(contains(hw_enforced(), TAG_DIGEST, KM_DIGEST_SHA1));
- EXPECT_TRUE(contains(hw_enforced(), TAG_DIGEST, KM_DIGEST_SHA_2_224));
- EXPECT_TRUE(contains(hw_enforced(), TAG_DIGEST, KM_DIGEST_SHA_2_256));
- EXPECT_TRUE(contains(hw_enforced(), TAG_DIGEST, KM_DIGEST_SHA_2_384));
- EXPECT_TRUE(contains(hw_enforced(), TAG_DIGEST, KM_DIGEST_SHA_2_512));
- EXPECT_TRUE(contains(hw_enforced(), TAG_PADDING, KM_PAD_NONE));
- EXPECT_TRUE(contains(hw_enforced(), TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_ENCRYPT));
- EXPECT_TRUE(contains(hw_enforced(), TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN));
- EXPECT_TRUE(contains(hw_enforced(), TAG_PADDING, KM_PAD_RSA_OAEP));
- EXPECT_TRUE(contains(hw_enforced(), TAG_PADDING, KM_PAD_RSA_PSS));
- EXPECT_EQ(15U, hw_enforced().size());
-
- EXPECT_TRUE(contains(sw_enforced(), TAG_PURPOSE, KM_PURPOSE_SIGN));
- EXPECT_TRUE(contains(sw_enforced(), TAG_PURPOSE, KM_PURPOSE_VERIFY));
- EXPECT_TRUE(sw_enforced().GetTagValue(TAG_ALL_USERS));
- EXPECT_TRUE(sw_enforced().GetTagValue(TAG_NO_AUTH_REQUIRED));
-
- EXPECT_FALSE(contains(sw_enforced(), TAG_ALGORITHM, KM_ALGORITHM_RSA));
- EXPECT_FALSE(contains(sw_enforced(), TAG_KEY_SIZE, 512));
- EXPECT_FALSE(contains(sw_enforced(), TAG_RSA_PUBLIC_EXPONENT, 3));
- EXPECT_FALSE(contains(sw_enforced(), TAG_DIGEST, KM_DIGEST_NONE));
- EXPECT_FALSE(contains(sw_enforced(), TAG_PADDING, KM_PAD_NONE));
-
- EXPECT_EQ(1, GetParam()->keymaster0_calls());
-}
-
-typedef Keymaster2Test AttestationTest;
-INSTANTIATE_TEST_CASE_P(AndroidKeymasterTest, AttestationTest, test_params);
-
-#if ATTESTATIONTEST
-static X509* parse_cert_blob(const keymaster_blob_t& blob) {
- const uint8_t* p = blob.data;
- return d2i_X509(nullptr, &p, blob.data_length);
-}
-
-static bool verify_chain(const keymaster_cert_chain_t& chain) {
- for (size_t i = 0; i < chain.entry_count - 1; ++i) {
- keymaster_blob_t& key_cert_blob = chain.entries[i];
- keymaster_blob_t& signing_cert_blob = chain.entries[i + 1];
-
- X509_Ptr key_cert(parse_cert_blob(key_cert_blob));
- X509_Ptr signing_cert(parse_cert_blob(signing_cert_blob));
- EXPECT_TRUE(!!key_cert.get() && !!signing_cert.get());
- if (!key_cert.get() || !signing_cert.get())
- return false;
-
- EVP_PKEY_Ptr signing_pubkey(X509_get_pubkey(signing_cert.get()));
- EXPECT_TRUE(!!signing_pubkey.get());
- if (!signing_pubkey.get())
- return false;
-
- EXPECT_EQ(1, X509_verify(key_cert.get(), signing_pubkey.get()))
- << "Verification of certificate " << i << " failed";
- }
-
- return true;
-}
-
-// Extract attestation record from cert. Returned object is still part of cert; don't free it
-// separately.
-static ASN1_OCTET_STRING* get_attestation_record(X509* certificate) {
- ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1 /* dotted string format */));
- EXPECT_TRUE(!!oid.get());
- if (!oid.get())
- return nullptr;
-
- int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1 /* search from beginning */);
- EXPECT_NE(-1, location);
- if (location == -1)
- return nullptr;
-
- X509_EXTENSION* attest_rec_ext = X509_get_ext(certificate, location);
- EXPECT_TRUE(!!attest_rec_ext);
- if (!attest_rec_ext)
- return nullptr;
-
- ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext);
- EXPECT_TRUE(!!attest_rec);
- return attest_rec;
-}
-
-static bool verify_attestation_record(const string& challenge,
- AuthorizationSet expected_sw_enforced,
- AuthorizationSet expected_tee_enforced,
- uint32_t expected_keymaster_version,
- keymaster_security_level_t expected_keymaster_security_level,
- const keymaster_blob_t& attestation_cert) {
-
- X509_Ptr cert(parse_cert_blob(attestation_cert));
- EXPECT_TRUE(!!cert.get());
- if (!cert.get())
- return false;
-
- ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get());
- EXPECT_TRUE(!!attest_rec);
- if (!attest_rec)
- return false;
-
- AuthorizationSet att_sw_enforced;
- AuthorizationSet att_tee_enforced;
- uint32_t att_attestation_version;
- uint32_t att_keymaster_version;
- keymaster_security_level_t att_attestation_security_level;
- keymaster_security_level_t att_keymaster_security_level;
- keymaster_blob_t att_challenge = {};
- keymaster_blob_t att_unique_id = {};
-
- EXPECT_EQ(KM_ERROR_OK, parse_attestation_record(
- attest_rec->data, attest_rec->length, &att_attestation_version,
- &att_attestation_security_level, &att_keymaster_version,
- &att_keymaster_security_level, &att_challenge, &att_sw_enforced,
- &att_tee_enforced, &att_unique_id));
-
- EXPECT_EQ(1U, att_attestation_version);
- EXPECT_EQ(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT, att_attestation_security_level);
- EXPECT_EQ(expected_keymaster_version, att_keymaster_version);
- EXPECT_EQ(expected_keymaster_security_level, att_keymaster_security_level);
-
- EXPECT_EQ(challenge.length(), att_challenge.data_length);
- EXPECT_EQ(0, memcmp(challenge.data(), att_challenge.data, challenge.length()));
-
- // Add TAG_USER_ID to the relevant attestation list, because user IDs are not included in
- // attestations, since they're meaningless off-device.
- uint32_t user_id;
- if (expected_sw_enforced.GetTagValue(TAG_USER_ID, &user_id))
- att_sw_enforced.push_back(TAG_USER_ID, user_id);
- if (expected_tee_enforced.GetTagValue(TAG_USER_ID, &user_id))
- att_tee_enforced.push_back(TAG_USER_ID, user_id);
-
- // Add TAG_INCLUDE_UNIQUE_ID to the relevant attestation list, because that tag is not included
- // in the attestation.
- if (expected_sw_enforced.GetTagValue(TAG_INCLUDE_UNIQUE_ID))
- att_sw_enforced.push_back(TAG_INCLUDE_UNIQUE_ID);
- if (expected_tee_enforced.GetTagValue(TAG_INCLUDE_UNIQUE_ID))
- att_tee_enforced.push_back(TAG_INCLUDE_UNIQUE_ID);
-
- att_sw_enforced.Sort();
- expected_sw_enforced.Sort();
- EXPECT_EQ(expected_sw_enforced, att_sw_enforced);
-
- att_tee_enforced.Sort();
- expected_tee_enforced.Sort();
- EXPECT_EQ(expected_tee_enforced, att_tee_enforced);
-
- return true;
-}
-#endif
-#if ATTESTATIONTEST
-TEST_P(AttestationTest, RsaAttestation) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(256, 3)
- .Digest(KM_DIGEST_NONE)
- .Padding(KM_PAD_NONE)
- .Authorization(TAG_INCLUDE_UNIQUE_ID)));
-
- keymaster_cert_chain_t cert_chain;
- EXPECT_EQ(KM_ERROR_OK, AttestKey("challenge", &cert_chain));
- EXPECT_EQ(3U, cert_chain.entry_count);
- EXPECT_TRUE(verify_chain(cert_chain));
-
- uint32_t expected_keymaster_version;
- keymaster_security_level_t expected_keymaster_security_level;
- expected_keymaster_version = 2;
- expected_keymaster_security_level = KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT;
-
- EXPECT_TRUE(verify_attestation_record(
- "challenge", sw_enforced(), hw_enforced(), expected_keymaster_version,
- expected_keymaster_security_level, cert_chain.entries[0]));
-
- keymaster_free_cert_chain(&cert_chain);
-}
-#endif
-#if ATTESTATIONTEST
-TEST_P(AttestationTest, EcAttestation) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(256).Digest(
- KM_DIGEST_SHA_2_256)));
-
- uint32_t expected_keymaster_version;
- keymaster_security_level_t expected_keymaster_security_level;
- expected_keymaster_version = 2;
- expected_keymaster_security_level = KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT;
-
- keymaster_cert_chain_t cert_chain;
- EXPECT_EQ(KM_ERROR_OK, AttestKey("challenge", &cert_chain));
- EXPECT_EQ(3U, cert_chain.entry_count);
- EXPECT_TRUE(verify_chain(cert_chain));
- EXPECT_TRUE(verify_attestation_record(
- "challenge", sw_enforced(), hw_enforced(), expected_keymaster_version,
- expected_keymaster_security_level, cert_chain.entries[0]));
-
- keymaster_free_cert_chain(&cert_chain);
-}
-#endif
-typedef Keymaster2Test KeyUpgradeTest;
-INSTANTIATE_TEST_CASE_P(AndroidKeymasterTest, KeyUpgradeTest, test_params);
-#if KEYUPGRADETEST
-TEST_P(KeyUpgradeTest, AesVersionUpgrade) {
- // A workaround for testing TEE based keymaster 2 from normal world
- keymaster2_device_t* device = (keymaster2_device_t* )GetParam()->keymaster_context();
- AuthorizationSet version_info(AuthorizationSetBuilder()
- .Authorization(TAG_OS_VERSION, 1)
- .Authorization(TAG_OS_PATCHLEVEL, 1));
- device->configure(device, &version_info);
-
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_ECB)
- .Padding(KM_PAD_NONE)));
-
- // Key should operate fine.
- string message = "1234567890123456";
- string ciphertext = EncryptMessage(message, KM_MODE_ECB, KM_PAD_NONE);
- EXPECT_EQ(message, DecryptMessage(ciphertext, KM_MODE_ECB, KM_PAD_NONE));
-
- // Increase patch level. Key usage should fail with KM_ERROR_KEY_REQUIRES_UPGRADE.
- AuthorizationSet version_info_1_2(AuthorizationSetBuilder()
- .Authorization(TAG_OS_VERSION, 1)
- .Authorization(TAG_OS_PATCHLEVEL, 2));
- device->configure(device, &version_info_1_2);
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_ECB);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- if (GetParam()->is_keymaster1_hw()) {
- // Keymaster1 hardware can't support version binding. The key will work regardless
- // of system version. Just abort the remainder of the test.
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
- EXPECT_EQ(KM_ERROR_OK, AbortOperation());
- return;
- }
- EXPECT_EQ(KM_ERROR_KEY_REQUIRES_UPGRADE, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
-
- // Getting characteristics should also fail
- EXPECT_EQ(KM_ERROR_KEY_REQUIRES_UPGRADE, GetCharacteristics());
-
- // Upgrade key.
- EXPECT_EQ(KM_ERROR_OK, UpgradeKey(client_params()));
-
- // Key should work again
- ciphertext = EncryptMessage(message, KM_MODE_ECB, KM_PAD_NONE);
- EXPECT_EQ(message, DecryptMessage(ciphertext, KM_MODE_ECB, KM_PAD_NONE));
-
- // Decrease patch level. Key usage should fail with KM_ERROR_INVALID_KEY_BLOB.
- AuthorizationSet version_info_1_1(AuthorizationSetBuilder()
- .Authorization(TAG_OS_VERSION, 1)
- .Authorization(TAG_OS_PATCHLEVEL, 1));
- device->configure(device, &version_info_1_1);
-
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, GetCharacteristics());
-
- // Upgrade should fail
- EXPECT_EQ(KM_ERROR_INVALID_ARGUMENT, UpgradeKey(client_params()));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-#endif
-#if 0//KEYUPGRADETEST
-//this test is no longer valid because boring ssl rejects rsa keys less than 256 bits
-TEST_P(KeyUpgradeTest, RsaVersionUpgrade) {
- keymaster2_device_t* device = (keymaster2_device_t* )GetParam()->keymaster_context();
- AuthorizationSet version_info(AuthorizationSetBuilder()
- .Authorization(TAG_OS_VERSION, 1)
- .Authorization(TAG_OS_PATCHLEVEL, 1));
- device->configure(device, &version_info);
-
- ASSERT_EQ(KM_ERROR_OK,
- GenerateKey(AuthorizationSetBuilder().RsaEncryptionKey(128, 3).Padding(KM_PAD_NONE)));
-
- // Key should operate fine.
- string message = "1234567890123456";
- string ciphertext = EncryptMessage(message, KM_PAD_NONE);
- EXPECT_EQ(message, DecryptMessage(ciphertext, KM_PAD_NONE));
-
- // Increase patch level. Key usage should fail with KM_ERROR_KEY_REQUIRES_UPGRADE.
- AuthorizationSet version_info_1_2(AuthorizationSetBuilder()
- .Authorization(TAG_OS_VERSION, 1)
- .Authorization(TAG_OS_PATCHLEVEL, 2));
- device->configure(device, &version_info_1_2);
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- if (GetParam()->is_keymaster1_hw()) {
- // Keymaster1 hardware can't support version binding. The key will work regardless
- // of system version. Just abort the remainder of the test.
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
- EXPECT_EQ(KM_ERROR_OK, AbortOperation());
- return;
- }
- EXPECT_EQ(KM_ERROR_KEY_REQUIRES_UPGRADE, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
-
- // Getting characteristics should also fail
- EXPECT_EQ(KM_ERROR_KEY_REQUIRES_UPGRADE, GetCharacteristics());
-
- // Upgrade key.
- EXPECT_EQ(KM_ERROR_OK, UpgradeKey(client_params()));
-
- // Key should work again
- ciphertext = EncryptMessage(message, KM_PAD_NONE);
- EXPECT_EQ(message, DecryptMessage(ciphertext, KM_PAD_NONE));
-
- // Decrease patch level. Key usage should fail with KM_ERROR_INVALID_KEY_BLOB.
- AuthorizationSet version_info_1_1(AuthorizationSetBuilder()
- .Authorization(TAG_OS_VERSION, 1)
- .Authorization(TAG_OS_PATCHLEVEL, 1));
- device->configure(device, &version_info_1_1);
-
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, GetCharacteristics());
-
- // Upgrade should fail
- EXPECT_EQ(KM_ERROR_INVALID_ARGUMENT, UpgradeKey(client_params()));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(7, GetParam()->keymaster0_calls());
-}
-#endif
-#if KEYUPGRADETEST
-TEST_P(KeyUpgradeTest, EcVersionUpgrade) {
- keymaster2_device_t* device = (keymaster2_device_t* )GetParam()->keymaster_context();
- AuthorizationSet version_info(AuthorizationSetBuilder()
- .Authorization(TAG_OS_VERSION, 1)
- .Authorization(TAG_OS_PATCHLEVEL, 1));
- device->configure(device, &version_info);
-
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(256).Digest(
- KM_DIGEST_SHA_2_256)));
-
- // Key should operate fine.
- string message = "1234567890123456";
- string signature;
- SignMessage(message, &signature, KM_DIGEST_SHA_2_256);
- VerifyMessage(message, signature, KM_DIGEST_SHA_2_256);
-
- // Increase patch level. Key usage should fail with KM_ERROR_KEY_REQUIRES_UPGRADE.
- AuthorizationSet version_info_1_2(AuthorizationSetBuilder()
- .Authorization(TAG_OS_VERSION, 1)
- .Authorization(TAG_OS_PATCHLEVEL, 2));
- device->configure(device, &version_info_1_2);
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA_2_256);
- if (GetParam()->is_keymaster1_hw()) {
- // Keymaster1 hardware can't support version binding. The key will work regardless
- // of system version. Just abort the remainder of the test.
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_SIGN, begin_params));
- EXPECT_EQ(KM_ERROR_OK, AbortOperation());
- return;
- }
- EXPECT_EQ(KM_ERROR_KEY_REQUIRES_UPGRADE, BeginOperation(KM_PURPOSE_SIGN, begin_params));
-
- // Getting characteristics should also fail
- EXPECT_EQ(KM_ERROR_KEY_REQUIRES_UPGRADE, GetCharacteristics());
-
- // Upgrade key.
- EXPECT_EQ(KM_ERROR_OK, UpgradeKey(client_params()));
-
- // Key should work again
- SignMessage(message, &signature, KM_DIGEST_SHA_2_256);
- VerifyMessage(message, signature, KM_DIGEST_SHA_2_256);
-
- // Decrease patch level. Key usage should fail with KM_ERROR_INVALID_KEY_BLOB.
- AuthorizationSet version_info_1_1(AuthorizationSetBuilder()
- .Authorization(TAG_OS_VERSION, 1)
- .Authorization(TAG_OS_PATCHLEVEL, 1));
- device->configure(device, &version_info_1_1);
-
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, GetCharacteristics());
-
- // Upgrade should fail
- EXPECT_EQ(KM_ERROR_INVALID_ARGUMENT, UpgradeKey(client_params()));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(7, GetParam()->keymaster0_calls());
-}
-#endif
-#if 0
-TEST(SoftKeymasterWrapperTest, CheckKeymaster2Device) {
- // Make a good fake device, and wrap it.
- SoftKeymasterDevice* good_fake(new SoftKeymasterDevice(new TestKeymasterContext));
-
- // Wrap it and check it.
- SoftKeymasterDevice* good_fake_wrapper(new SoftKeymasterDevice(new TestKeymasterContext));
- good_fake_wrapper->SetHardwareDevice(good_fake->keymaster_device());
- EXPECT_TRUE(good_fake_wrapper->Keymaster1DeviceIsGood());
-
- // Close and clean up wrapper and wrapped
- good_fake_wrapper->keymaster_device()->common.close(good_fake_wrapper->hw_device());
-
- // Make a "bad" (doesn't support all digests) device;
- keymaster1_device_t* sha256_only_fake = make_device_sha256_only(
- (new SoftKeymasterDevice(new TestKeymasterContext("256")))->keymaster_device());
-
- // Wrap it and check it.
- SoftKeymasterDevice* sha256_only_fake_wrapper(
- (new SoftKeymasterDevice(new TestKeymasterContext)));
- sha256_only_fake_wrapper->SetHardwareDevice(sha256_only_fake);
- EXPECT_FALSE(sha256_only_fake_wrapper->Keymaster1DeviceIsGood());
-
- // Close and clean up wrapper and wrapped
- sha256_only_fake_wrapper->keymaster_device()->common.close(
- sha256_only_fake_wrapper->hw_device());
-}
-#endif
-
-} // namespace test
-} // namespace keymaster
diff --git a/unit_test/android_keymaster_test_utils.cpp b/unit_test/android_keymaster_test_utils.cpp
deleted file mode 100644
index ecaee62..0000000
--- a/unit_test/android_keymaster_test_utils.cpp
+++ b/dev/null
@@ -1,902 +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.
- */
-
-#include "android_keymaster_test_utils.h"
-
-#include <algorithm>
-
-#include <openssl/rand.h>
-
-#include <keymaster/android_keymaster_messages.h>
-#include <keymaster/android_keymaster_utils.h>
-
-using std::copy_if;
-using std::find_if;
-using std::is_permutation;
-using std::ostream;
-using std::string;
-using std::vector;
-
-#ifndef KEYMASTER_NAME_TAGS
-#error Keymaster test code requires that KEYMASTER_NAME_TAGS is defined
-#endif
-
-std::ostream& operator<<(std::ostream& os, const keymaster_key_param_t& param) {
- os << "Tag: " << keymaster::StringifyTag(param.tag);
- switch (keymaster_tag_get_type(param.tag)) {
- case KM_INVALID:
- os << " Invalid";
- break;
- case KM_UINT_REP:
- os << " (Rep)";
- /* Falls through */
- case KM_UINT:
- os << " Int: " << param.integer;
- break;
- case KM_ENUM_REP:
- os << " (Rep)";
- /* Falls through */
- case KM_ENUM:
- os << " Enum: " << param.enumerated;
- break;
- case KM_ULONG_REP:
- os << " (Rep)";
- /* Falls through */
- case KM_ULONG:
- os << " Long: " << param.long_integer;
- break;
- case KM_DATE:
- os << " Date: " << param.date_time;
- break;
- case KM_BOOL:
- os << " Bool: " << param.boolean;
- break;
- case KM_BIGNUM:
- os << " Bignum: ";
- if (!param.blob.data)
- os << "(null)";
- else
- for (size_t i = 0; i < param.blob.data_length; ++i)
- os << std::hex << std::setw(2) << static_cast<int>(param.blob.data[i]) << std::dec;
- break;
- case KM_BYTES:
- os << " Bytes: ";
- if (!param.blob.data)
- os << "(null)";
- else
- for (size_t i = 0; i < param.blob.data_length; ++i)
- os << std::hex << std::setw(2) << static_cast<int>(param.blob.data[i]) << std::dec;
- break;
- }
- return os;
-}
-
-bool operator==(const keymaster_key_param_t& a, const keymaster_key_param_t& b) {
- if (a.tag != b.tag) {
- return false;
- }
-
- switch (keymaster_tag_get_type(a.tag)) {
- case KM_INVALID:
- return true;
- case KM_UINT_REP:
- case KM_UINT:
- return a.integer == b.integer;
- case KM_ENUM_REP:
- case KM_ENUM:
- return a.enumerated == b.enumerated;
- case KM_ULONG:
- case KM_ULONG_REP:
- return a.long_integer == b.long_integer;
- case KM_DATE:
- return a.date_time == b.date_time;
- case KM_BOOL:
- return a.boolean == b.boolean;
- case KM_BIGNUM:
- case KM_BYTES:
- if ((a.blob.data == NULL || b.blob.data == NULL) && a.blob.data != b.blob.data)
- return false;
- return a.blob.data_length == b.blob.data_length &&
- (memcmp(a.blob.data, b.blob.data, a.blob.data_length) == 0);
- }
-
- return false;
-}
-
-static char hex_value[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, // '0'..'9'
- 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'A'..'F'
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, // 'a'..'f'
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
-string hex2str(string a) {
- string b;
- size_t num = a.size() / 2;
- b.resize(num);
- for (size_t i = 0; i < num; i++) {
- b[i] = (hex_value[a[i * 2] & 0xFF] << 4) + (hex_value[a[i * 2 + 1] & 0xFF]);
- }
- return b;
-}
-
-namespace keymaster {
-
-bool operator==(const AuthorizationSet& a, const AuthorizationSet& b) {
- if (a.size() != b.size())
- return false;
-
- for (size_t i = 0; i < a.size(); ++i)
- if (!(a[i] == b[i]))
- return false;
- return true;
-}
-
-bool operator!=(const AuthorizationSet& a, const AuthorizationSet& b) {
- return !(a == b);
-}
-
-std::ostream& operator<<(std::ostream& os, const AuthorizationSet& set) {
- if (set.size() == 0)
- os << "(Empty)" << std::endl;
- else {
- os << "\n";
- for (size_t i = 0; i < set.size(); ++i)
- os << set[i] << std::endl;
- }
- return os;
-}
-
-namespace test {
-
-Keymaster2Test::Keymaster2Test() : op_handle_(OP_HANDLE_SENTINEL) {
- memset(&characteristics_, 0, sizeof(characteristics_));
- blob_.key_material = nullptr;
- RAND_seed("foobar", 6);
- blob_.key_material = 0;
- device_ = GetParam()->CreateDevice();
-}
-
-Keymaster2Test::~Keymaster2Test() {
- FreeCharacteristics();
- FreeKeyBlob();
- device_->common.close(reinterpret_cast<hw_device_t*>(device_));
-}
-
-keymaster2_device_t* Keymaster2Test::device() {
- return device_;
-}
-
-keymaster_error_t Keymaster2Test::GenerateKey(const AuthorizationSetBuilder& builder) {
- AuthorizationSet params(builder.build());
- params.push_back(UserAuthParams());
- params.push_back(ClientParams());
-
- FreeKeyBlob();
- FreeCharacteristics();
- return device()->generate_key(device(), &params, &blob_, &characteristics_);
-}
-
-keymaster_error_t Keymaster2Test::DeleteKey() {
- return device()->delete_key(device(), &blob_);
-}
-
-keymaster_error_t Keymaster2Test::ImportKey(const AuthorizationSetBuilder& builder,
- keymaster_key_format_t format,
- const string& key_material) {
- AuthorizationSet params(builder.build());
- params.push_back(UserAuthParams());
- params.push_back(ClientParams());
-
- FreeKeyBlob();
- FreeCharacteristics();
- keymaster_blob_t key = {reinterpret_cast<const uint8_t*>(key_material.c_str()),
- key_material.length()};
- return device()->import_key(device(), &params, format, &key, &blob_, &characteristics_);
-}
-
-AuthorizationSet Keymaster2Test::UserAuthParams() {
- AuthorizationSet set;
- set.push_back(TAG_USER_ID, 7);
- set.push_back(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD);
- set.push_back(TAG_AUTH_TIMEOUT, 300);
- return set;
-}
-
-AuthorizationSet Keymaster2Test::ClientParams() {
- AuthorizationSet set;
- set.push_back(TAG_APPLICATION_ID, "app_id", 6);
- return set;
-}
-
-keymaster_error_t Keymaster2Test::BeginOperation(keymaster_purpose_t purpose) {
- AuthorizationSet in_params(client_params());
- keymaster_key_param_set_t out_params;
- keymaster_error_t error =
- device()->begin(device(), purpose, &blob_, &in_params, &out_params, &op_handle_);
- EXPECT_EQ(0U, out_params.length);
- EXPECT_TRUE(out_params.params == nullptr);
- return error;
-}
-
-keymaster_error_t Keymaster2Test::BeginOperation(keymaster_purpose_t purpose,
- const AuthorizationSet& input_set,
- AuthorizationSet* output_set) {
- keymaster_key_param_set_t out_params;
- keymaster_error_t error =
- device()->begin(device(), purpose, &blob_, &input_set, &out_params, &op_handle_);
- if (error == KM_ERROR_OK) {
- if (output_set) {
- output_set->Reinitialize(out_params);
- } else {
- EXPECT_EQ(0U, out_params.length);
- EXPECT_TRUE(out_params.params == nullptr);
- }
- keymaster_free_param_set(&out_params);
- }
- return error;
-}
-
-keymaster_error_t Keymaster2Test::UpdateOperation(const string& message, string* output,
- size_t* input_consumed) {
- EXPECT_NE(op_handle_, OP_HANDLE_SENTINEL);
- keymaster_blob_t input = {reinterpret_cast<const uint8_t*>(message.c_str()), message.length()};
- keymaster_blob_t out_tmp;
- keymaster_key_param_set_t out_params;
- keymaster_error_t error = device()->update(device(), op_handle_, nullptr /* params */, &input,
- input_consumed, &out_params, &out_tmp);
- if (error == KM_ERROR_OK && out_tmp.data)
- output->append(reinterpret_cast<const char*>(out_tmp.data), out_tmp.data_length);
- free(const_cast<uint8_t*>(out_tmp.data));
- return error;
-}
-
-keymaster_error_t Keymaster2Test::UpdateOperation(const AuthorizationSet& additional_params,
- const string& message,
- AuthorizationSet* output_params, string* output,
- size_t* input_consumed) {
- EXPECT_NE(op_handle_, OP_HANDLE_SENTINEL);
- keymaster_blob_t input = {reinterpret_cast<const uint8_t*>(message.c_str()), message.length()};
- keymaster_blob_t out_tmp;
- keymaster_key_param_set_t out_params;
- keymaster_error_t error = device()->update(device(), op_handle_, &additional_params, &input,
- input_consumed, &out_params, &out_tmp);
- if (error == KM_ERROR_OK && out_tmp.data)
- output->append(reinterpret_cast<const char*>(out_tmp.data), out_tmp.data_length);
- free((void*)out_tmp.data);
- if (output_params)
- output_params->Reinitialize(out_params);
- keymaster_free_param_set(&out_params);
- return error;
-}
-
-keymaster_error_t Keymaster2Test::FinishOperation(string* output) {
- return FinishOperation("", output);
-}
-
-keymaster_error_t Keymaster2Test::FinishOperation(const string& signature, string* output) {
- AuthorizationSet additional_params;
- AuthorizationSet output_params;
- return FinishOperation(additional_params, signature, &output_params, output);
-}
-
-keymaster_error_t Keymaster2Test::FinishOperation(const AuthorizationSet& additional_params,
- const string& signature,
- AuthorizationSet* output_params, string* output) {
- keymaster_blob_t sig = {reinterpret_cast<const uint8_t*>(signature.c_str()),
- signature.length()};
- keymaster_blob_t out_tmp;
- keymaster_key_param_set_t out_params;
- keymaster_error_t error = device()->finish(device(), op_handle_, &additional_params,
- nullptr /* input */, &sig, &out_params, &out_tmp);
- if (error != KM_ERROR_OK) {
- EXPECT_TRUE(out_tmp.data == nullptr);
- EXPECT_TRUE(out_params.params == nullptr);
- return error;
- }
-
- if (out_tmp.data)
- output->append(reinterpret_cast<const char*>(out_tmp.data), out_tmp.data_length);
- free((void*)out_tmp.data);
- if (output_params)
- output_params->Reinitialize(out_params);
- keymaster_free_param_set(&out_params);
- return error;
-}
-
-keymaster_error_t Keymaster2Test::AbortOperation() {
- return device()->abort(device(), op_handle_);
-}
-
-keymaster_error_t Keymaster2Test::AttestKey(const string& attest_challenge,
- keymaster_cert_chain_t* cert_chain) {
- AuthorizationSet attest_params;
- attest_params.push_back(UserAuthParams());
- attest_params.push_back(ClientParams());
- attest_params.push_back(TAG_ATTESTATION_CHALLENGE, attest_challenge.data(),
- attest_challenge.length());
- return device()->attest_key(device(), &blob_, &attest_params, cert_chain);
-}
-
-keymaster_error_t Keymaster2Test::UpgradeKey(const AuthorizationSet& upgrade_params) {
- keymaster_key_blob_t upgraded_blob;
- keymaster_error_t error =
- device()->upgrade_key(device(), &blob_, &upgrade_params, &upgraded_blob);
- if (error == KM_ERROR_OK) {
- FreeKeyBlob();
- blob_ = upgraded_blob;
- }
- return error;
-}
-
-string Keymaster2Test::ProcessMessage(keymaster_purpose_t purpose, const string& message) {
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(purpose, client_params(), NULL /* output_params */));
-
- string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&result));
- return result;
-}
-
-string Keymaster2Test::ProcessMessage(keymaster_purpose_t purpose, const string& message,
- const AuthorizationSet& begin_params,
- const AuthorizationSet& update_params,
- AuthorizationSet* begin_out_params) {
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(purpose, begin_params, begin_out_params));
-
- string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, message, nullptr /* output_params */,
- &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(update_params, "", &result));
- return result;
-}
-
-string Keymaster2Test::ProcessMessage(keymaster_purpose_t purpose, const string& message,
- const string& signature, const AuthorizationSet& begin_params,
- const AuthorizationSet& update_params,
- AuthorizationSet* output_params) {
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(purpose, begin_params, output_params));
-
- string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, message, nullptr /* output_params */,
- &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(update_params, signature, &result));
- return result;
-}
-
-string Keymaster2Test::ProcessMessage(keymaster_purpose_t purpose, const string& message,
- const string& signature) {
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(purpose, client_params(), NULL /* output_params */));
-
- string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(signature, &result));
- return result;
-}
-
-void Keymaster2Test::SignMessage(const string& message, string* signature,
- keymaster_digest_t digest) {
- SCOPED_TRACE("SignMessage");
- AuthorizationSet input_params(AuthorizationSet(client_params_, array_length(client_params_)));
- input_params.push_back(TAG_DIGEST, digest);
- AuthorizationSet update_params;
- AuthorizationSet output_params;
- *signature =
- ProcessMessage(KM_PURPOSE_SIGN, message, input_params, update_params, &output_params);
- EXPECT_GT(signature->size(), 0U);
-}
-
-void Keymaster2Test::SignMessage(const string& message, string* signature,
- keymaster_digest_t digest, keymaster_padding_t padding) {
- SCOPED_TRACE("SignMessage");
- AuthorizationSet input_params(AuthorizationSet(client_params_, array_length(client_params_)));
- input_params.push_back(TAG_DIGEST, digest);
- input_params.push_back(TAG_PADDING, padding);
- AuthorizationSet update_params;
- AuthorizationSet output_params;
- *signature =
- ProcessMessage(KM_PURPOSE_SIGN, message, input_params, update_params, &output_params);
- EXPECT_GT(signature->size(), 0U);
-}
-
-void Keymaster2Test::MacMessage(const string& message, string* signature, size_t mac_length) {
- SCOPED_TRACE("SignMessage");
- AuthorizationSet input_params(AuthorizationSet(client_params_, array_length(client_params_)));
- input_params.push_back(TAG_MAC_LENGTH, mac_length);
- AuthorizationSet update_params;
- AuthorizationSet output_params;
- *signature =
- ProcessMessage(KM_PURPOSE_SIGN, message, input_params, update_params, &output_params);
- EXPECT_GT(signature->size(), 0U);
-}
-
-void Keymaster2Test::VerifyMessage(const string& message, const string& signature,
- keymaster_digest_t digest) {
- SCOPED_TRACE("VerifyMessage");
- AuthorizationSet input_params(client_params());
- input_params.push_back(TAG_DIGEST, digest);
- AuthorizationSet update_params;
- AuthorizationSet output_params;
- ProcessMessage(KM_PURPOSE_VERIFY, message, signature, input_params, update_params,
- &output_params);
-}
-
-void Keymaster2Test::VerifyMessage(const string& message, const string& signature,
- keymaster_digest_t digest, keymaster_padding_t padding) {
- SCOPED_TRACE("VerifyMessage");
- AuthorizationSet input_params(client_params());
- input_params.push_back(TAG_DIGEST, digest);
- input_params.push_back(TAG_PADDING, padding);
- AuthorizationSet update_params;
- AuthorizationSet output_params;
- ProcessMessage(KM_PURPOSE_VERIFY, message, signature, input_params, update_params,
- &output_params);
-}
-
-void Keymaster2Test::VerifyMac(const string& message, const string& signature) {
- SCOPED_TRACE("VerifyMac");
- ProcessMessage(KM_PURPOSE_VERIFY, message, signature);
-}
-
-string Keymaster2Test::EncryptMessage(const string& message, keymaster_padding_t padding,
- string* generated_nonce) {
- SCOPED_TRACE("EncryptMessage");
- AuthorizationSet begin_params(client_params()), output_params;
- begin_params.push_back(TAG_PADDING, padding);
- AuthorizationSet update_params;
- string ciphertext =
- ProcessMessage(KM_PURPOSE_ENCRYPT, message, begin_params, update_params, &output_params);
- if (generated_nonce) {
- keymaster_blob_t nonce_blob;
- EXPECT_TRUE(output_params.GetTagValue(TAG_NONCE, &nonce_blob));
- *generated_nonce = make_string(nonce_blob.data, nonce_blob.data_length);
- } else {
- EXPECT_EQ(-1, output_params.find(TAG_NONCE));
- }
- return ciphertext;
-}
-
-string Keymaster2Test::EncryptMessage(const string& message, keymaster_digest_t digest,
- keymaster_padding_t padding, string* generated_nonce) {
- AuthorizationSet update_params;
- return EncryptMessage(update_params, message, digest, padding, generated_nonce);
-}
-
-string Keymaster2Test::EncryptMessage(const string& message, keymaster_block_mode_t block_mode,
- keymaster_padding_t padding, string* generated_nonce) {
- AuthorizationSet update_params;
- return EncryptMessage(update_params, message, block_mode, padding, generated_nonce);
-}
-
-string Keymaster2Test::EncryptMessage(const AuthorizationSet& update_params, const string& message,
- keymaster_digest_t digest, keymaster_padding_t padding,
- string* generated_nonce) {
- SCOPED_TRACE("EncryptMessage");
- AuthorizationSet begin_params(client_params()), output_params;
- begin_params.push_back(TAG_PADDING, padding);
- begin_params.push_back(TAG_DIGEST, digest);
- string ciphertext =
- ProcessMessage(KM_PURPOSE_ENCRYPT, message, begin_params, update_params, &output_params);
- if (generated_nonce) {
- keymaster_blob_t nonce_blob;
- EXPECT_TRUE(output_params.GetTagValue(TAG_NONCE, &nonce_blob));
- *generated_nonce = make_string(nonce_blob.data, nonce_blob.data_length);
- } else {
- EXPECT_EQ(-1, output_params.find(TAG_NONCE));
- }
- return ciphertext;
-}
-
-string Keymaster2Test::EncryptMessage(const AuthorizationSet& update_params, const string& message,
- keymaster_block_mode_t block_mode,
- keymaster_padding_t padding, string* generated_nonce) {
- SCOPED_TRACE("EncryptMessage");
- AuthorizationSet begin_params(client_params()), output_params;
- begin_params.push_back(TAG_PADDING, padding);
- begin_params.push_back(TAG_BLOCK_MODE, block_mode);
- string ciphertext =
- ProcessMessage(KM_PURPOSE_ENCRYPT, message, begin_params, update_params, &output_params);
- if (generated_nonce) {
- keymaster_blob_t nonce_blob;
- EXPECT_TRUE(output_params.GetTagValue(TAG_NONCE, &nonce_blob));
- *generated_nonce = make_string(nonce_blob.data, nonce_blob.data_length);
- } else {
- EXPECT_EQ(-1, output_params.find(TAG_NONCE));
- }
- return ciphertext;
-}
-
-string Keymaster2Test::EncryptMessageWithParams(const string& message,
- const AuthorizationSet& begin_params,
- const AuthorizationSet& update_params,
- AuthorizationSet* output_params) {
- SCOPED_TRACE("EncryptMessageWithParams");
- return ProcessMessage(KM_PURPOSE_ENCRYPT, message, begin_params, update_params, output_params);
-}
-
-string Keymaster2Test::DecryptMessage(const string& ciphertext, keymaster_padding_t padding) {
- SCOPED_TRACE("DecryptMessage");
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, padding);
- AuthorizationSet update_params;
- return ProcessMessage(KM_PURPOSE_DECRYPT, ciphertext, begin_params, update_params);
-}
-
-string Keymaster2Test::DecryptMessage(const string& ciphertext, keymaster_digest_t digest,
- keymaster_padding_t padding) {
- SCOPED_TRACE("DecryptMessage");
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, padding);
- begin_params.push_back(TAG_DIGEST, digest);
- AuthorizationSet update_params;
- return ProcessMessage(KM_PURPOSE_DECRYPT, ciphertext, begin_params, update_params);
-}
-
-string Keymaster2Test::DecryptMessage(const string& ciphertext, keymaster_block_mode_t block_mode,
- keymaster_padding_t padding) {
- SCOPED_TRACE("DecryptMessage");
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, padding);
- begin_params.push_back(TAG_BLOCK_MODE, block_mode);
- AuthorizationSet update_params;
- return ProcessMessage(KM_PURPOSE_DECRYPT, ciphertext, begin_params, update_params);
-}
-
-string Keymaster2Test::DecryptMessage(const string& ciphertext, keymaster_digest_t digest,
- keymaster_padding_t padding, const string& nonce) {
- SCOPED_TRACE("DecryptMessage");
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, padding);
- begin_params.push_back(TAG_DIGEST, digest);
- begin_params.push_back(TAG_NONCE, nonce.data(), nonce.size());
- AuthorizationSet update_params;
- return ProcessMessage(KM_PURPOSE_DECRYPT, ciphertext, begin_params, update_params);
-}
-
-string Keymaster2Test::DecryptMessage(const string& ciphertext, keymaster_block_mode_t block_mode,
- keymaster_padding_t padding, const string& nonce) {
- SCOPED_TRACE("DecryptMessage");
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, padding);
- begin_params.push_back(TAG_BLOCK_MODE, block_mode);
- begin_params.push_back(TAG_NONCE, nonce.data(), nonce.size());
- AuthorizationSet update_params;
- return ProcessMessage(KM_PURPOSE_DECRYPT, ciphertext, begin_params, update_params);
-}
-
-string Keymaster2Test::DecryptMessage(const AuthorizationSet& update_params,
- const string& ciphertext, keymaster_digest_t digest,
- keymaster_padding_t padding, const string& nonce) {
- SCOPED_TRACE("DecryptMessage");
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, padding);
- begin_params.push_back(TAG_DIGEST, digest);
- begin_params.push_back(TAG_NONCE, nonce.data(), nonce.size());
- return ProcessMessage(KM_PURPOSE_DECRYPT, ciphertext, begin_params, update_params);
-}
-
-keymaster_error_t Keymaster2Test::GetCharacteristics() {
- FreeCharacteristics();
- return device()->get_key_characteristics(device(), &blob_, &client_id_, NULL /* app_data */,
- &characteristics_);
-}
-
-keymaster_error_t Keymaster2Test::ExportKey(keymaster_key_format_t format, string* export_data) {
- keymaster_blob_t export_tmp;
- keymaster_error_t error = device()->export_key(device(), format, &blob_, &client_id_,
- NULL /* app_data */, &export_tmp);
-
- if (error != KM_ERROR_OK)
- return error;
-
- *export_data = string(reinterpret_cast<const char*>(export_tmp.data), export_tmp.data_length);
- free((void*)export_tmp.data);
- return error;
-}
-
-void Keymaster2Test::CheckHmacTestVector(const string& key, const string& message, keymaster_digest_t digest,
- string expected_mac) {
- ASSERT_EQ(KM_ERROR_OK, ImportKey(AuthorizationSetBuilder()
- .HmacKey(key.size() * 8)
- .Authorization(TAG_MIN_MAC_LENGTH, expected_mac.size() * 8)
- .Digest(digest),
- KM_KEY_FORMAT_RAW, key));
- string signature;
- MacMessage(message, &signature, expected_mac.size() * 8);
- EXPECT_EQ(expected_mac, signature) << "Test vector didn't match for digest " << (int)digest;
-}
-
-void Keymaster2Test::CheckAesCtrTestVector(const string& key, const string& nonce,
- const string& message,
- const string& expected_ciphertext) {
- ASSERT_EQ(KM_ERROR_OK, ImportKey(AuthorizationSetBuilder()
- .AesEncryptionKey(key.size() * 8)
- .Authorization(TAG_BLOCK_MODE, KM_MODE_CTR)
- .Authorization(TAG_CALLER_NONCE)
- .Padding(KM_PAD_NONE),
- KM_KEY_FORMAT_RAW, key));
-
- AuthorizationSet begin_params(client_params()), update_params, output_params;
- begin_params.push_back(TAG_NONCE, nonce.data(), nonce.size());
- begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_CTR);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- string ciphertext =
- EncryptMessageWithParams(message, begin_params, update_params, &output_params);
- EXPECT_EQ(expected_ciphertext, ciphertext);
-}
-
-AuthorizationSet Keymaster2Test::hw_enforced() {
- return AuthorizationSet(characteristics_.hw_enforced);
-}
-
-AuthorizationSet Keymaster2Test::sw_enforced() {
- return AuthorizationSet(characteristics_.sw_enforced);
-}
-
-void Keymaster2Test::FreeCharacteristics() {
- keymaster_free_characteristics(&characteristics_);
-}
-
-void Keymaster2Test::FreeKeyBlob() {
- free(const_cast<uint8_t*>(blob_.key_material));
- blob_.key_material = NULL;
-}
-
-void Keymaster2Test::corrupt_key_blob() {
- assert(blob_.key_material);
- uint8_t* tmp = const_cast<uint8_t*>(blob_.key_material);
- ++tmp[blob_.key_material_size / 2];
-}
-
-class Sha256OnlyWrapper {
- public:
- explicit Sha256OnlyWrapper(const keymaster1_device_t* wrapped_device) : wrapped_device_(wrapped_device) {
-
- new_module = *wrapped_device_->common.module;
- new_module_name = std::string("SHA 256-only ") + wrapped_device_->common.module->name;
- new_module.name = new_module_name.c_str();
-
- memset(&device_, 0, sizeof(device_));
- device_.common.module = &new_module;
-
- device_.common.close = close_device;
- device_.get_supported_algorithms = get_supported_algorithms;
- device_.get_supported_block_modes = get_supported_block_modes;
- device_.get_supported_padding_modes = get_supported_padding_modes;
- device_.get_supported_digests = get_supported_digests;
- device_.get_supported_import_formats = get_supported_import_formats;
- device_.get_supported_export_formats = get_supported_export_formats;
- device_.add_rng_entropy = add_rng_entropy;
- device_.generate_key = generate_key;
- device_.get_key_characteristics = get_key_characteristics;
- device_.import_key = import_key;
- device_.export_key = export_key;
- device_.begin = begin;
- device_.update = update;
- device_.finish = finish;
- device_.abort = abort;
- }
-
- keymaster1_device_t* keymaster_device() { return &device_; }
-
- static bool is_supported(keymaster_digest_t digest) {
- return digest == KM_DIGEST_NONE || digest == KM_DIGEST_SHA_2_256;
- }
-
- static bool all_digests_supported(const keymaster_key_param_set_t* params) {
- for (size_t i = 0; i < params->length; ++i)
- if (params->params[i].tag == TAG_DIGEST)
- if (!is_supported(static_cast<keymaster_digest_t>(params->params[i].enumerated)))
- return false;
- return true;
- }
-
- static const keymaster_key_param_t*
- get_algorithm_param(const keymaster_key_param_set_t* params) {
- keymaster_key_param_t* end = params->params + params->length;
- auto alg_ptr = std::find_if(params->params, end, [](keymaster_key_param_t& p) {
- return p.tag == KM_TAG_ALGORITHM;
- });
- if (alg_ptr == end)
- return nullptr;
- return alg_ptr;
- }
-
- static int close_device(hw_device_t* dev) {
- Sha256OnlyWrapper* wrapper = reinterpret_cast<Sha256OnlyWrapper*>(dev);
- const keymaster1_device_t* wrapped_device = wrapper->wrapped_device_;
- delete wrapper;
- return wrapped_device->common.close(const_cast<hw_device_t*>(&wrapped_device->common));
- }
-
- static const keymaster1_device_t* unwrap(const keymaster1_device_t* dev) {
- return reinterpret_cast<const Sha256OnlyWrapper*>(dev)->wrapped_device_;
- }
-
- static keymaster_error_t get_supported_algorithms(const struct keymaster1_device* dev,
- keymaster_algorithm_t** algorithms,
- size_t* algorithms_length) {
- return unwrap(dev)->get_supported_algorithms(unwrap(dev), algorithms, algorithms_length);
- }
- static keymaster_error_t get_supported_block_modes(const struct keymaster1_device* dev,
- keymaster_algorithm_t algorithm,
- keymaster_purpose_t purpose,
- keymaster_block_mode_t** modes,
- size_t* modes_length) {
- return unwrap(dev)->get_supported_block_modes(unwrap(dev), algorithm, purpose, modes,
- modes_length);
- }
- static keymaster_error_t get_supported_padding_modes(const struct keymaster1_device* dev,
- keymaster_algorithm_t algorithm,
- keymaster_purpose_t purpose,
- keymaster_padding_t** modes,
- size_t* modes_length) {
- return unwrap(dev)->get_supported_padding_modes(unwrap(dev), algorithm, purpose, modes,
- modes_length);
- }
-
- static keymaster_error_t get_supported_digests(const keymaster1_device_t* dev,
- keymaster_algorithm_t algorithm,
- keymaster_purpose_t purpose,
- keymaster_digest_t** digests,
- size_t* digests_length) {
- keymaster_error_t error = unwrap(dev)->get_supported_digests(
- unwrap(dev), algorithm, purpose, digests, digests_length);
- if (error != KM_ERROR_OK)
- return error;
-
- std::vector<keymaster_digest_t> filtered_digests;
- std::copy_if(*digests, *digests + *digests_length, std::back_inserter(filtered_digests),
- [](keymaster_digest_t digest) { return is_supported(digest); });
-
- free(*digests);
- *digests_length = filtered_digests.size();
- *digests = reinterpret_cast<keymaster_digest_t*>(
- malloc(*digests_length * sizeof(keymaster_digest_t)));
- std::copy(filtered_digests.begin(), filtered_digests.end(), *digests);
-
- return KM_ERROR_OK;
- }
-
- static keymaster_error_t get_supported_import_formats(const struct keymaster1_device* dev,
- keymaster_algorithm_t algorithm,
- keymaster_key_format_t** formats,
- size_t* formats_length) {
- return unwrap(dev)->get_supported_import_formats(unwrap(dev), algorithm, formats,
- formats_length);
- }
- static keymaster_error_t get_supported_export_formats(const struct keymaster1_device* dev,
- keymaster_algorithm_t algorithm,
- keymaster_key_format_t** formats,
- size_t* formats_length) {
- return unwrap(dev)->get_supported_export_formats(unwrap(dev), algorithm, formats,
- formats_length);
- }
- static keymaster_error_t add_rng_entropy(const struct keymaster1_device* dev,
- const uint8_t* data, size_t data_length) {
- return unwrap(dev)->add_rng_entropy(unwrap(dev), data, data_length);
- }
-
- static keymaster_error_t generate_key(const keymaster1_device_t* dev,
- const keymaster_key_param_set_t* params,
- keymaster_key_blob_t* key_blob,
- keymaster_key_characteristics_t** characteristics) {
- auto alg_ptr = get_algorithm_param(params);
- if (!alg_ptr)
- return KM_ERROR_UNSUPPORTED_ALGORITHM;
- if (alg_ptr->enumerated == KM_ALGORITHM_HMAC && !all_digests_supported(params))
- return KM_ERROR_UNSUPPORTED_DIGEST;
-
- return unwrap(dev)->generate_key(unwrap(dev), params, key_blob, characteristics);
- }
-
- static keymaster_error_t
- get_key_characteristics(const struct keymaster1_device* dev,
- const keymaster_key_blob_t* key_blob, const keymaster_blob_t* client_id,
- const keymaster_blob_t* app_data,
- keymaster_key_characteristics_t** characteristics) {
- return unwrap(dev)->get_key_characteristics(unwrap(dev), key_blob, client_id, app_data,
- characteristics);
- }
-
- static keymaster_error_t
- import_key(const keymaster1_device_t* dev, const keymaster_key_param_set_t* params,
- keymaster_key_format_t key_format, const keymaster_blob_t* key_data,
- keymaster_key_blob_t* key_blob, keymaster_key_characteristics_t** characteristics) {
- auto alg_ptr = get_algorithm_param(params);
- if (!alg_ptr)
- return KM_ERROR_UNSUPPORTED_ALGORITHM;
- if (alg_ptr->enumerated == KM_ALGORITHM_HMAC && !all_digests_supported(params))
- return KM_ERROR_UNSUPPORTED_DIGEST;
-
- return unwrap(dev)->import_key(unwrap(dev), params, key_format, key_data, key_blob,
- characteristics);
- }
-
- static keymaster_error_t export_key(const struct keymaster1_device* dev, //
- keymaster_key_format_t export_format,
- const keymaster_key_blob_t* key_to_export,
- const keymaster_blob_t* client_id,
- const keymaster_blob_t* app_data,
- keymaster_blob_t* export_data) {
- return unwrap(dev)->export_key(unwrap(dev), export_format, key_to_export, client_id,
- app_data, export_data);
- }
-
- static keymaster_error_t begin(const keymaster1_device_t* dev, //
- keymaster_purpose_t purpose, const keymaster_key_blob_t* key,
- const keymaster_key_param_set_t* in_params,
- keymaster_key_param_set_t* out_params,
- keymaster_operation_handle_t* operation_handle) {
- if (!all_digests_supported(in_params))
- return KM_ERROR_UNSUPPORTED_DIGEST;
- return unwrap(dev)->begin(unwrap(dev), purpose, key, in_params, out_params,
- operation_handle);
- }
-
- static keymaster_error_t update(const keymaster1_device_t* dev,
- keymaster_operation_handle_t operation_handle,
- const keymaster_key_param_set_t* in_params,
- const keymaster_blob_t* input, size_t* input_consumed,
- keymaster_key_param_set_t* out_params,
- keymaster_blob_t* output) {
- return unwrap(dev)->update(unwrap(dev), operation_handle, in_params, input, input_consumed,
- out_params, output);
- }
-
- static keymaster_error_t finish(const struct keymaster1_device* dev, //
- keymaster_operation_handle_t operation_handle,
- const keymaster_key_param_set_t* in_params,
- const keymaster_blob_t* signature,
- keymaster_key_param_set_t* out_params,
- keymaster_blob_t* output) {
- return unwrap(dev)->finish(unwrap(dev), operation_handle, in_params, signature, out_params,
- output);
- }
-
- static keymaster_error_t abort(const struct keymaster1_device* dev,
- keymaster_operation_handle_t operation_handle) {
- return unwrap(dev)->abort(unwrap(dev), operation_handle);
- }
-
- private:
- keymaster1_device_t device_;
- const keymaster1_device_t* wrapped_device_;
- hw_module_t new_module;
- string new_module_name;
-};
-
-keymaster1_device_t* make_device_sha256_only(keymaster1_device_t* device) {
- return (new Sha256OnlyWrapper(device))->keymaster_device();
-}
-
-} // namespace test
-} // namespace keymaster
diff --git a/unit_test/android_keymaster_test_utils.h b/unit_test/android_keymaster_test_utils.h
deleted file mode 100644
index 5dd0f76..0000000
--- a/unit_test/android_keymaster_test_utils.h
+++ b/dev/null
@@ -1,470 +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_KEYMASTER_ANDROID_KEYMASTER_TEST_UTILS_H_
-#define SYSTEM_KEYMASTER_ANDROID_KEYMASTER_TEST_UTILS_H_
-
-/*
- * Utilities used to help with testing. Not used in production code.
- */
-
-#include <stdarg.h>
-
-#include <algorithm>
-#include <memory>
-#include <ostream>
-#include <string>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include <hardware/keymaster0.h>
-#include <hardware/keymaster1.h>
-#include <hardware/keymaster2.h>
-#include <hardware/keymaster_defs.h>
-
-#include <keymaster/android_keymaster_utils.h>
-#include <keymaster/authorization_set.h>
-#include <keymaster/keymaster_context.h>
-#include <keymaster/logger.h>
-
-std::ostream& operator<<(std::ostream& os, const keymaster_key_param_t& param);
-bool operator==(const keymaster_key_param_t& a, const keymaster_key_param_t& b);
-std::string hex2str(std::string);
-
-namespace keymaster {
-
-bool operator==(const AuthorizationSet& a, const AuthorizationSet& b);
-bool operator!=(const AuthorizationSet& a, const AuthorizationSet& b);
-
-std::ostream& operator<<(std::ostream& os, const AuthorizationSet& set);
-
-namespace test {
-
-template <keymaster_tag_t Tag, typename KeymasterEnum>
-bool contains(const AuthorizationSet& set, TypedEnumTag<KM_ENUM, Tag, KeymasterEnum> tag,
- KeymasterEnum val) {
- int pos = set.find(tag);
- return pos != -1 && static_cast<KeymasterEnum>(set[pos].enumerated) == val;
-}
-
-template <keymaster_tag_t Tag, typename KeymasterEnum>
-bool contains(const AuthorizationSet& set, TypedEnumTag<KM_ENUM_REP, Tag, KeymasterEnum> tag,
- KeymasterEnum val) {
- int pos = -1;
- while ((pos = set.find(tag, pos)) != -1)
- if (static_cast<KeymasterEnum>(set[pos].enumerated) == val)
- return true;
- return false;
-}
-
-template <keymaster_tag_t Tag>
-bool contains(const AuthorizationSet& set, TypedTag<KM_UINT, Tag> tag, uint32_t val) {
- int pos = set.find(tag);
- return pos != -1 && set[pos].integer == val;
-}
-
-template <keymaster_tag_t Tag>
-bool contains(const AuthorizationSet& set, TypedTag<KM_UINT_REP, Tag> tag, uint32_t val) {
- int pos = -1;
- while ((pos = set.find(tag, pos)) != -1)
- if (set[pos].integer == val)
- return true;
- return false;
-}
-
-template <keymaster_tag_t Tag>
-bool contains(const AuthorizationSet& set, TypedTag<KM_ULONG, Tag> tag, uint64_t val) {
- int pos = set.find(tag);
- return pos != -1 && set[pos].long_integer == val;
-}
-
-template <keymaster_tag_t Tag>
-bool contains(const AuthorizationSet& set, TypedTag<KM_BYTES, Tag> tag, const std::string& val) {
- int pos = set.find(tag);
- return pos != -1 &&
- std::string(reinterpret_cast<const char*>(set[pos].blob.data),
- set[pos].blob.data_length) == val;
-}
-
-template <keymaster_tag_t Tag>
-bool contains(const AuthorizationSet& set, TypedTag<KM_BIGNUM, Tag> tag, const std::string& val) {
- int pos = set.find(tag);
- return pos != -1 &&
- std::string(reinterpret_cast<const char*>(set[pos].blob.data),
- set[pos].blob.data_length) == val;
-}
-
-inline bool contains(const AuthorizationSet& set, keymaster_tag_t tag) {
- return set.find(tag) != -1;
-}
-
-class StdoutLogger : public Logger {
- public:
- StdoutLogger() { set_instance(this); }
-
- int log_msg(LogLevel level, const char* fmt, va_list args) const {
- int output_len = 0;
- switch (level) {
- case DEBUG_LVL:
- output_len = printf("DEBUG: ");
- break;
- case INFO_LVL:
- output_len = printf("INFO: ");
- break;
- case WARNING_LVL:
- output_len = printf("WARNING: ");
- break;
- case ERROR_LVL:
- output_len = printf("ERROR: ");
- break;
- case SEVERE_LVL:
- output_len = printf("SEVERE: ");
- break;
- }
-
- output_len += vprintf(fmt, args);
- output_len += printf("\n");
- return output_len;
- }
-};
-
-inline std::string make_string(const uint8_t* data, size_t length) {
- return std::string(reinterpret_cast<const char*>(data), length);
-}
-
-template <size_t N> std::string make_string(const uint8_t (&a)[N]) {
- return make_string(a, N);
-}
-
-/**
- * Keymaster2TestInstance is used to parameterize Keymaster2Tests. Its main function is to create a
- * keymaster2_device_t to which test calls can be directed. It also provides a place to specify
- * various bits of alternative behavior, in cases where different devices are expected to behave
- * differently (any such cases are a potential bug, but sometimes they may make sense).
- */
-class Keymaster2TestInstanceCreator {
- public:
- virtual ~Keymaster2TestInstanceCreator(){};
- virtual keymaster2_device_t* CreateDevice() const = 0;
-
- virtual bool algorithm_in_km0_hardware(keymaster_algorithm_t algorithm) const = 0;
- virtual int keymaster0_calls() const = 0;
- virtual int minimal_digest_set() const { return false; }
- virtual bool is_keymaster1_hw() const = 0;
- virtual KeymasterContext* keymaster_context() const = 0;
-};
-
-// Use a shared_ptr because it's copyable.
-typedef std::shared_ptr<Keymaster2TestInstanceCreator> InstanceCreatorPtr;
-
-const uint64_t OP_HANDLE_SENTINEL = 0xFFFFFFFFFFFFFFFF;
-class Keymaster2Test : public testing::TestWithParam<InstanceCreatorPtr> {
- protected:
- Keymaster2Test();
- ~Keymaster2Test();
-
- keymaster2_device_t* device();
-
- keymaster_error_t GenerateKey(const AuthorizationSetBuilder& builder);
-
- keymaster_error_t DeleteKey();
-
- keymaster_error_t ImportKey(const AuthorizationSetBuilder& builder,
- keymaster_key_format_t format, const std::string& key_material);
-
- keymaster_error_t ExportKey(keymaster_key_format_t format, std::string* export_data);
-
- keymaster_error_t GetCharacteristics();
-
- keymaster_error_t BeginOperation(keymaster_purpose_t purpose);
- keymaster_error_t BeginOperation(keymaster_purpose_t purpose, const AuthorizationSet& input_set,
- AuthorizationSet* output_set = NULL);
-
- keymaster_error_t UpdateOperation(const std::string& message, std::string* output,
- size_t* input_consumed);
- keymaster_error_t UpdateOperation(const AuthorizationSet& additional_params,
- const std::string& message, AuthorizationSet* output_params,
- std::string* output, size_t* input_consumed);
-
- keymaster_error_t FinishOperation(std::string* output);
- keymaster_error_t FinishOperation(const std::string& signature, std::string* output);
- keymaster_error_t FinishOperation(const AuthorizationSet& additional_params,
- const std::string& signature, std::string* output) {
- return FinishOperation(additional_params, signature, nullptr /* output_params */, output);
- }
- keymaster_error_t FinishOperation(const AuthorizationSet& additional_params,
- const std::string& signature, AuthorizationSet* output_params,
- std::string* output);
-
- keymaster_error_t AbortOperation();
-
- keymaster_error_t AttestKey(const std::string& attest_challenge, keymaster_cert_chain_t* chain);
-
- keymaster_error_t UpgradeKey(const AuthorizationSet& upgrade_params);
-
- keymaster_error_t GetVersion(uint8_t* major, uint8_t* minor, uint8_t* subminor);
-
- std::string ProcessMessage(keymaster_purpose_t purpose, const std::string& message);
- std::string ProcessMessage(keymaster_purpose_t purpose, const std::string& message,
- const AuthorizationSet& begin_params,
- const AuthorizationSet& update_params,
- AuthorizationSet* output_params = NULL);
- std::string ProcessMessage(keymaster_purpose_t purpose, const std::string& message,
- const std::string& signature, const AuthorizationSet& begin_params,
- const AuthorizationSet& update_params,
- AuthorizationSet* output_params = NULL);
- std::string ProcessMessage(keymaster_purpose_t purpose, const std::string& message,
- const std::string& signature);
-
- void SignMessage(const std::string& message, std::string* signature, keymaster_digest_t digest);
- void SignMessage(const std::string& message, std::string* signature, keymaster_digest_t digest,
- keymaster_padding_t padding);
- void MacMessage(const std::string& message, std::string* signature, size_t mac_length);
-
- void VerifyMessage(const std::string& message, const std::string& signature,
- keymaster_digest_t digest);
- void VerifyMessage(const std::string& message, const std::string& signature,
- keymaster_digest_t digest, keymaster_padding_t padding);
- void VerifyMac(const std::string& message, const std::string& signature);
-
- std::string EncryptMessage(const std::string& message, keymaster_padding_t padding,
- std::string* generated_nonce = NULL);
- std::string EncryptMessage(const std::string& message, keymaster_digest_t digest,
- keymaster_padding_t padding, std::string* generated_nonce = NULL);
- std::string EncryptMessage(const std::string& message, keymaster_block_mode_t block_mode,
- keymaster_padding_t padding, std::string* generated_nonce = NULL);
- std::string EncryptMessage(const AuthorizationSet& update_params, const std::string& message,
- keymaster_digest_t digest, keymaster_padding_t padding,
- std::string* generated_nonce = NULL);
- std::string EncryptMessage(const AuthorizationSet& update_params, const std::string& message,
- keymaster_block_mode_t block_mode, keymaster_padding_t padding,
- std::string* generated_nonce = NULL);
- std::string EncryptMessageWithParams(const std::string& message,
- const AuthorizationSet& begin_params,
- const AuthorizationSet& update_params,
- AuthorizationSet* output_params);
-
- std::string DecryptMessage(const std::string& ciphertext, keymaster_padding_t padding);
- std::string DecryptMessage(const std::string& ciphertext, keymaster_digest_t digest,
- keymaster_padding_t padding);
- std::string DecryptMessage(const std::string& ciphertext, keymaster_block_mode_t block_mode,
- keymaster_padding_t padding);
- std::string DecryptMessage(const std::string& ciphertext, keymaster_digest_t digest,
- keymaster_padding_t padding, const std::string& nonce);
- std::string DecryptMessage(const std::string& ciphertext, keymaster_block_mode_t block_mode,
- keymaster_padding_t padding, const std::string& nonce);
- std::string DecryptMessage(const AuthorizationSet& update_params, const std::string& ciphertext,
- keymaster_digest_t digest, keymaster_padding_t padding,
- const std::string& nonce);
- std::string DecryptMessage(const AuthorizationSet& update_params, const std::string& ciphertext,
- keymaster_block_mode_t block_mode, keymaster_padding_t padding,
- const std::string& nonce);
-
- void CheckHmacTestVector(const std::string& key, const std::string& message, keymaster_digest_t digest,
- std::string expected_mac);
- void CheckAesOcbTestVector(const std::string& key, const std::string& nonce,
- const std::string& associated_data, const std::string& message,
- const std::string& expected_ciphertext);
- void CheckAesCtrTestVector(const std::string& key, const std::string& nonce,
- const std::string& message, const std::string& expected_ciphertext);
- AuthorizationSet UserAuthParams();
- AuthorizationSet ClientParams();
-
- template <typename T>
- bool ResponseContains(const std::vector<T>& expected, const T* values, size_t len) {
- return expected.size() == len &&
- std::is_permutation(values, values + len, expected.begin());
- }
-
- template <typename T> bool ResponseContains(T expected, const T* values, size_t len) {
- return (len == 1 && *values == expected);
- }
-
- AuthorizationSet hw_enforced();
- AuthorizationSet sw_enforced();
-
- void FreeCharacteristics();
- void FreeKeyBlob();
-
- void corrupt_key_blob();
-
- void set_key_blob(const uint8_t* key, size_t key_length) {
- FreeKeyBlob();
- blob_.key_material = key;
- blob_.key_material_size = key_length;
- }
-
- AuthorizationSet client_params() {
- return AuthorizationSet(client_params_, sizeof(client_params_) / sizeof(client_params_[0]));
- }
-
- private:
- keymaster2_device_t* device_;
- keymaster_blob_t client_id_ = {.data = reinterpret_cast<const uint8_t*>("app_id"),
- .data_length = 6};
- keymaster_key_param_t client_params_[1] = {
- Authorization(TAG_APPLICATION_ID, client_id_.data, client_id_.data_length)};
-
- uint64_t op_handle_;
-
- keymaster_key_blob_t blob_;
- keymaster_key_characteristics_t characteristics_;
-};
-
-struct Keymaster0CountingWrapper : public keymaster0_device_t {
- explicit Keymaster0CountingWrapper(keymaster0_device_t* device) : device_(device), counter_(0) {
- common = device_->common;
- common.close = counting_close_device;
- client_version = device_->client_version;
- flags = device_->flags;
- context = this;
-
- generate_keypair = counting_generate_keypair;
- import_keypair = counting_import_keypair;
- get_keypair_public = counting_get_keypair_public;
- delete_keypair = counting_delete_keypair;
- delete_all = counting_delete_all;
- sign_data = counting_sign_data;
- verify_data = counting_verify_data;
- }
-
- int count() { return counter_; }
-
- // The blobs generated by the underlying softkeymaster start with "PK#8". Tweak the prefix so
- // they don't get identified as softkeymaster blobs.
- static void munge_blob(uint8_t* blob, size_t blob_length) {
- if (blob && blob_length > 0 && *blob == 'P')
- *blob = 'Q'; // Mind your Ps and Qs!
- }
-
- // Copy and un-modfy the blob. The caller must clean up the return value.
- static uint8_t* unmunge_blob(const uint8_t* blob, size_t blob_length) {
- uint8_t* dup_blob = dup_buffer(blob, blob_length);
- if (dup_blob && blob_length > 0 && *dup_blob == 'Q')
- *dup_blob = 'P';
- return dup_blob;
- }
-
- static keymaster0_device_t* device(const keymaster0_device_t* dev) {
- Keymaster0CountingWrapper* wrapper =
- reinterpret_cast<Keymaster0CountingWrapper*>(dev->context);
- return wrapper->device_;
- }
-
- static void increment(const keymaster0_device_t* dev) {
- Keymaster0CountingWrapper* wrapper =
- reinterpret_cast<Keymaster0CountingWrapper*>(dev->context);
- wrapper->counter_++;
- }
-
- static int counting_close_device(hw_device_t* dev) {
- keymaster0_device_t* k0_dev = reinterpret_cast<keymaster0_device_t*>(dev);
- increment(k0_dev);
- Keymaster0CountingWrapper* wrapper =
- reinterpret_cast<Keymaster0CountingWrapper*>(k0_dev->context);
- int retval =
- wrapper->device_->common.close(reinterpret_cast<hw_device_t*>(wrapper->device_));
- delete wrapper;
- return retval;
- }
-
- static int counting_generate_keypair(const struct keymaster0_device* dev,
- const keymaster_keypair_t key_type, const void* key_params,
- uint8_t** key_blob, size_t* key_blob_length) {
- increment(dev);
- int result = device(dev)->generate_keypair(device(dev), key_type, key_params, key_blob,
- key_blob_length);
- if (result == 0)
- munge_blob(*key_blob, *key_blob_length);
- return result;
- }
-
- static int counting_import_keypair(const struct keymaster0_device* dev, const uint8_t* key,
- const size_t key_length, uint8_t** key_blob,
- size_t* key_blob_length) {
- increment(dev);
- int result =
- device(dev)->import_keypair(device(dev), key, key_length, key_blob, key_blob_length);
- if (result == 0)
- munge_blob(*key_blob, *key_blob_length);
- return result;
- }
-
- static int counting_get_keypair_public(const struct keymaster0_device* dev,
- const uint8_t* key_blob, const size_t key_blob_length,
- uint8_t** x509_data, size_t* x509_data_length) {
- increment(dev);
- std::unique_ptr<uint8_t[]> dup_blob(unmunge_blob(key_blob, key_blob_length));
- return device(dev)->get_keypair_public(device(dev), dup_blob.get(), key_blob_length,
- x509_data, x509_data_length);
- }
-
- static int counting_delete_keypair(const struct keymaster0_device* dev, const uint8_t* key_blob,
- const size_t key_blob_length) {
- increment(dev);
- if (key_blob && key_blob_length > 0)
- EXPECT_EQ('Q', *key_blob);
- if (device(dev)->delete_keypair) {
- std::unique_ptr<uint8_t[]> dup_blob(unmunge_blob(key_blob, key_blob_length));
- return device(dev)->delete_keypair(device(dev), dup_blob.get(), key_blob_length);
- }
- return 0;
- }
-
- static int counting_delete_all(const struct keymaster0_device* dev) {
- increment(dev);
- if (device(dev)->delete_all)
- return device(dev)->delete_all(device(dev));
- return 0;
- }
-
- static int counting_sign_data(const struct keymaster0_device* dev, const void* signing_params,
- const uint8_t* key_blob, const size_t key_blob_length,
- const uint8_t* data, const size_t data_length,
- uint8_t** signed_data, size_t* signed_data_length) {
- increment(dev);
- std::unique_ptr<uint8_t[]> dup_blob(unmunge_blob(key_blob, key_blob_length));
- return device(dev)->sign_data(device(dev), signing_params, dup_blob.get(), key_blob_length,
- data, data_length, signed_data, signed_data_length);
- }
-
- static int counting_verify_data(const struct keymaster0_device* dev, const void* signing_params,
- const uint8_t* key_blob, const size_t key_blob_length,
- const uint8_t* signed_data, const size_t signed_data_length,
- const uint8_t* signature, const size_t signature_length) {
- increment(dev);
- std::unique_ptr<uint8_t[]> dup_blob(unmunge_blob(key_blob, key_blob_length));
- return device(dev)->verify_data(device(dev), signing_params, dup_blob.get(),
- key_blob_length, signed_data, signed_data_length, signature,
- signature_length);
- }
-
- private:
- keymaster0_device_t* device_;
- int counter_;
-};
-
-/**
- * This function takes a keymaster1_device_t and wraps it in an adapter that supports only
- * KM_DIGEST_SHA_2_256.
- */
-keymaster1_device_t* make_device_sha256_only(keymaster1_device_t* device);
-
-} // namespace test
-} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_ANDROID_KEYMASTER_TEST_UTILS_H_
diff --git a/unit_test/android_keymaster_utils.h b/unit_test/android_keymaster_utils.h
deleted file mode 100644
index b957dd1..0000000
--- a/unit_test/android_keymaster_utils.h
+++ b/dev/null
@@ -1,306 +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_KEYMASTER_ANDROID_KEYMASTER_UTILS_H_
-#define SYSTEM_KEYMASTER_ANDROID_KEYMASTER_UTILS_H_
-
-#include <stdint.h>
-#include <string.h>
-#include <time.h> // for time_t.
-
-#include <UniquePtr.h>
-
-#include <hardware/keymaster_defs.h>
-#include <keymaster/serializable.h>
-
-namespace keymaster {
-
-/**
- * Convert the specified time value into "Java time", which is a signed 64-bit integer representing
- * elapsed milliseconds since Jan 1, 1970.
- */
-inline int64_t java_time(time_t time) {
- // The exact meaning of a time_t value is implementation-dependent. If this code is ported to a
- // platform that doesn't define it as "seconds since Jan 1, 1970 UTC", this function will have
- // to be revised.
- return time * 1000;
-}
-
-/*
- * Array Manipulation functions. This set of templated inline functions provides some nice tools
- * for operating on c-style arrays. C-style arrays actually do have a defined size associated with
- * them, as long as they are not allowed to decay to a pointer. These template methods exploit this
- * to allow size-based array operations without explicitly specifying the size. If passed a pointer
- * rather than an array, they'll fail to compile.
- */
-
-/**
- * Return the size in bytes of the array \p a.
- */
-template <typename T, size_t N> inline size_t array_size(const T(&a)[N]) {
- return sizeof(a);
-}
-
-/**
- * Return the number of elements in array \p a.
- */
-template <typename T, size_t N> inline size_t array_length(const T(&)[N]) {
- return N;
-}
-
-/**
- * Duplicate the array \p a. The memory for the new array is allocated and the caller takes
- * responsibility.
- */
-template <typename T> inline T* dup_array(const T* a, size_t n) {
- T* dup = new (std::nothrow) T[n];
- if (dup)
- for (size_t i = 0; i < n; ++i)
- dup[i] = a[i];
- return dup;
-}
-
-/**
- * Duplicate the array \p a. The memory for the new array is allocated and the caller takes
- * responsibility. Note that the dup is necessarily returned as a pointer, so size is lost. Call
- * array_length() on the original array to discover the size.
- */
-template <typename T, size_t N> inline T* dup_array(const T(&a)[N]) {
- return dup_array(a, N);
-}
-
-/**
- * Duplicate the buffer \p buf. The memory for the new buffer is allocated and the caller takes
- * responsibility.
- */
-uint8_t* dup_buffer(const void* buf, size_t size);
-
-/**
- * Copy the contents of array \p arr to \p dest.
- */
-template <typename T, size_t N> inline void copy_array(const T(&arr)[N], T* dest) {
- for (size_t i = 0; i < N; ++i)
- dest[i] = arr[i];
-}
-
-/**
- * Search array \p a for value \p val, returning true if found. Note that this function is
- * early-exit, meaning that it should not be used in contexts where timing analysis attacks could be
- * a concern.
- */
-template <typename T, size_t N> inline bool array_contains(const T(&a)[N], T val) {
- for (size_t i = 0; i < N; ++i) {
- if (a[i] == val) {
- return true;
- }
- }
- return false;
-}
-
-/**
- * Variant of memset() that uses GCC-specific pragmas to disable optimizations, so effect is not
- * optimized away. This is important because we often need to wipe blocks of sensitive data from
- * memory. As an additional convenience, this implementation avoids writing to NULL pointers.
- */
-#ifdef __clang__
-#define OPTNONE __attribute__((optnone))
-#else // not __clang__
-#define OPTNONE __attribute__((optimize("O0")))
-#endif // not __clang__
-inline OPTNONE void* memset_s(void* s, int c, size_t n) {
- if (!s)
- return s;
- return memset(s, c, n);
-}
-#undef OPTNONE
-
-/**
- * Variant of memcmp that has the same runtime regardless of whether the data matches (i.e. doesn't
- * short-circuit). Not an exact equivalent to memcmp because it doesn't return <0 if p1 < p2, just
- * 0 for match and non-zero for non-match.
- */
-int memcmp_s(const void* p1, const void* p2, size_t length);
-
-/**
- * Eraser clears buffers. Construct it with a buffer or object and the destructor will ensure that
- * it is zeroed.
- */
-class Eraser {
- public:
- /* Not implemented. If this gets used, we want a link error. */
- template <typename T> explicit Eraser(T* t);
-
- template <typename T>
- explicit Eraser(T& t)
- : buf_(reinterpret_cast<uint8_t*>(&t)), size_(sizeof(t)) {}
-
- template <size_t N> explicit Eraser(uint8_t(&arr)[N]) : buf_(arr), size_(N) {}
-
- Eraser(void* buf, size_t size) : buf_(static_cast<uint8_t*>(buf)), size_(size) {}
- ~Eraser() { memset_s(buf_, 0, size_); }
-
- private:
- Eraser(const Eraser&);
- void operator=(const Eraser&);
-
- uint8_t* buf_;
- size_t size_;
-};
-
-/**
- * ArrayWrapper is a trivial wrapper around a C-style array that provides begin() and end()
- * methods. This is primarily to facilitate range-based iteration on arrays. It does not copy, nor
- * does it take ownership; it just holds pointers.
- */
-template <typename T> class ArrayWrapper {
- public:
- ArrayWrapper(T* array, size_t size) : begin_(array), end_(array + size) {}
-
- T* begin() { return begin_; }
- T* end() { return end_; }
-
- private:
- T* begin_;
- T* end_;
-};
-
-/**
- * Convert any unsigned integer from network to host order. We implement this here rather than
- * using the functions from arpa/inet.h because the TEE doesn't have inet.h. This isn't the most
- * efficient implementation, but the compiler should unroll the loop and tighten it up.
- */
-template <typename T> T ntoh(T t) {
- const uint8_t* byte_ptr = reinterpret_cast<const uint8_t*>(&t);
- T retval = 0;
- for (size_t i = 0; i < sizeof(t); ++i) {
- retval <<= 8;
- retval |= byte_ptr[i];
- }
- return retval;
-}
-
-/**
- * Convert any unsigned integer from host to network order. We implement this here rather than
- * using the functions from arpa/inet.h because the TEE doesn't have inet.h. This isn't the most
- * efficient implementation, but the compiler should unroll the loop and tighten it up.
- */
-template <typename T> T hton(T t) {
- T retval;
- uint8_t* byte_ptr = reinterpret_cast<uint8_t*>(&retval);
- for (size_t i = sizeof(t); i > 0; --i) {
- byte_ptr[i - 1] = t & 0xFF;
- t >>= 8;
- }
- return retval;
-}
-
-/**
- * KeymasterKeyBlob is a very simple extension of the C struct keymaster_key_blob_t. It manages its
- * own memory, which makes avoiding memory leaks much easier.
- */
-struct KeymasterKeyBlob : public keymaster_key_blob_t {
- KeymasterKeyBlob() {
- key_material = nullptr;
- key_material_size = 0;
- }
-
- KeymasterKeyBlob(const uint8_t* data, size_t size) {
- key_material_size = 0;
- key_material = dup_buffer(data, size);
- if (key_material)
- key_material_size = size;
- }
-
- explicit KeymasterKeyBlob(size_t size) {
- key_material_size = 0;
- key_material = new (std::nothrow) uint8_t[size];
- if (key_material)
- key_material_size = size;
- }
-
- explicit KeymasterKeyBlob(const keymaster_key_blob_t& blob) {
- key_material_size = 0;
- key_material = dup_buffer(blob.key_material, blob.key_material_size);
- if (key_material)
- key_material_size = blob.key_material_size;
- }
-
- KeymasterKeyBlob(const KeymasterKeyBlob& blob) {
- key_material_size = 0;
- key_material = dup_buffer(blob.key_material, blob.key_material_size);
- if (key_material)
- key_material_size = blob.key_material_size;
- }
-
- void operator=(const KeymasterKeyBlob& blob) {
- Clear();
- key_material = dup_buffer(blob.key_material, blob.key_material_size);
- key_material_size = blob.key_material_size;
- }
-
- ~KeymasterKeyBlob() { Clear(); }
-
- const uint8_t* begin() const { return key_material; }
- const uint8_t* end() const { return key_material + key_material_size; }
-
- void Clear() {
- memset_s(const_cast<uint8_t*>(key_material), 0, key_material_size);
- delete[] key_material;
- key_material = nullptr;
- key_material_size = 0;
- }
-
- const uint8_t* Reset(size_t new_size) {
- Clear();
- key_material = new (std::nothrow) uint8_t[new_size];
- if (key_material)
- key_material_size = new_size;
- return key_material;
- }
-
- // The key_material in keymaster_key_blob_t is const, which is the right thing in most
- // circumstances, but occasionally we do need to write into it. This method exposes a non-const
- // version of the pointer. Use sparingly.
- uint8_t* writable_data() { return const_cast<uint8_t*>(key_material); }
-
- keymaster_key_blob_t release() {
- keymaster_key_blob_t tmp = {key_material, key_material_size};
- key_material = nullptr;
- key_material_size = 0;
- return tmp;
- }
-
- size_t SerializedSize() const { return sizeof(uint32_t) + key_material_size; }
- uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const {
- return append_size_and_data_to_buf(buf, end, key_material, key_material_size);
- }
-
- bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
- Clear();
- UniquePtr<uint8_t[]> tmp;
- if (!copy_size_and_data_from_buf(buf_ptr, end, &key_material_size, &tmp)) {
- key_material = nullptr;
- key_material_size = 0;
- return false;
- }
- key_material = tmp.release();
- return true;
- }
-};
-
-} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_ANDROID_KEYMASTER_UTILS_H_
diff --git a/unit_test/attestation_record.cpp b/unit_test/attestation_record.cpp
deleted file mode 100644
index 8ba5a8a..0000000
--- a/unit_test/attestation_record.cpp
+++ b/dev/null
@@ -1,690 +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 "attestation_record.h"
-
-#include <assert.h>
-
-#include <openssl/asn1t.h>
-
-#include "openssl_err.h"
-#include "openssl_utils.h"
-
-#include <keymaster/android_keymaster_utils.h>
-#include <keymaster/keymaster_context.h>
-
-namespace keymaster {
-
-struct stack_st_ASN1_TYPE_Delete {
- void operator()(stack_st_ASN1_TYPE* p) { sk_ASN1_TYPE_free(p); }
-};
-
-struct ASN1_STRING_Delete {
- void operator()(ASN1_STRING* p) { ASN1_STRING_free(p); }
-};
-
-struct ASN1_TYPE_Delete {
- void operator()(ASN1_TYPE* p) { ASN1_TYPE_free(p); }
-};
-
-#define ASN1_INTEGER_SET STACK_OF(ASN1_INTEGER)
-
-typedef struct km_root_of_trust {
- ASN1_OCTET_STRING* verified_boot_key;
- ASN1_BOOLEAN* device_locked;
- ASN1_ENUMERATED* verified_boot_state;
-} KM_ROOT_OF_TRUST;
-
-ASN1_SEQUENCE(KM_ROOT_OF_TRUST) = {
- ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_key, ASN1_OCTET_STRING),
- ASN1_SIMPLE(KM_ROOT_OF_TRUST, device_locked, ASN1_BOOLEAN),
- ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_state, ASN1_ENUMERATED),
-} ASN1_SEQUENCE_END(KM_ROOT_OF_TRUST);
-IMPLEMENT_ASN1_FUNCTIONS(KM_ROOT_OF_TRUST);
-
-typedef struct km_auth_list {
- ASN1_INTEGER_SET* purpose;
- ASN1_INTEGER* algorithm;
- ASN1_INTEGER* key_size;
- ASN1_INTEGER_SET* digest;
- ASN1_INTEGER_SET* padding;
- ASN1_INTEGER_SET* kdf;
- ASN1_INTEGER* ec_curve;
- ASN1_INTEGER* rsa_public_exponent;
- ASN1_INTEGER* active_date_time;
- ASN1_INTEGER* origination_expire_date_time;
- ASN1_INTEGER* usage_expire_date_time;
- ASN1_NULL* no_auth_required;
- ASN1_INTEGER* user_auth_type;
- ASN1_INTEGER* auth_timeout;
- ASN1_NULL* allow_while_on_body;
- ASN1_NULL* all_applications;
- ASN1_OCTET_STRING* application_id;
- ASN1_INTEGER* creation_date_time;
- ASN1_INTEGER* origin;
- ASN1_NULL* rollback_resistant;
- KM_ROOT_OF_TRUST* root_of_trust;
- ASN1_INTEGER* os_version;
- ASN1_INTEGER* os_patchlevel;
-} KM_AUTH_LIST;
-
-ASN1_SEQUENCE(KM_AUTH_LIST) = {
- ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, purpose, ASN1_INTEGER, TAG_PURPOSE.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, algorithm, ASN1_INTEGER, TAG_ALGORITHM.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, key_size, ASN1_INTEGER, TAG_KEY_SIZE.masked_tag()),
- ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, digest, ASN1_INTEGER, TAG_DIGEST.masked_tag()),
- ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, padding, ASN1_INTEGER, TAG_PADDING.masked_tag()),
- ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, kdf, ASN1_INTEGER, TAG_KDF.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, ec_curve, ASN1_INTEGER, TAG_EC_CURVE.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, rsa_public_exponent, ASN1_INTEGER,
- TAG_RSA_PUBLIC_EXPONENT.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
- TAG_ORIGINATION_EXPIRE_DATETIME.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
- TAG_USAGE_EXPIRE_DATETIME.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, no_auth_required, ASN1_NULL, TAG_NO_AUTH_REQUIRED.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, user_auth_type, ASN1_INTEGER, TAG_USER_AUTH_TYPE.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, auth_timeout, ASN1_INTEGER, TAG_AUTH_TIMEOUT.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, allow_while_on_body, ASN1_NULL,
- TAG_ALLOW_WHILE_ON_BODY.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, all_applications, ASN1_NULL, TAG_ALL_APPLICATIONS.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, application_id, ASN1_OCTET_STRING, TAG_APPLICATION_ID.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, creation_date_time, ASN1_INTEGER,
- TAG_CREATION_DATETIME.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, origin, ASN1_INTEGER, TAG_ORIGIN.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistant, ASN1_NULL, TAG_ROLLBACK_RESISTANT.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.masked_tag()),
-} ASN1_SEQUENCE_END(KM_AUTH_LIST);
-IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
-
-typedef struct km_key_description {
- ASN1_INTEGER* attestation_version;
- ASN1_ENUMERATED* attestation_security_level;
- ASN1_INTEGER* keymaster_version;
- ASN1_ENUMERATED* keymaster_security_level;
- ASN1_OCTET_STRING* attestation_challenge;
- KM_AUTH_LIST* software_enforced;
- KM_AUTH_LIST* tee_enforced;
- ASN1_INTEGER* unique_id;
-} KM_KEY_DESCRIPTION;
-
-ASN1_SEQUENCE(KM_KEY_DESCRIPTION) = {
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_version, ASN1_INTEGER),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_security_level, ASN1_ENUMERATED),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, keymaster_version, ASN1_INTEGER),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, keymaster_security_level, ASN1_ENUMERATED),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_challenge, ASN1_OCTET_STRING),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, unique_id, ASN1_OCTET_STRING),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, software_enforced, KM_AUTH_LIST),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, tee_enforced, KM_AUTH_LIST),
-} ASN1_SEQUENCE_END(KM_KEY_DESCRIPTION);
-IMPLEMENT_ASN1_FUNCTIONS(KM_KEY_DESCRIPTION);
-
-struct KM_AUTH_LIST_Delete {
- void operator()(KM_AUTH_LIST* p) { KM_AUTH_LIST_free(p); }
-};
-
-struct KM_KEY_DESCRIPTION_Delete {
- void operator()(KM_KEY_DESCRIPTION* p) { KM_KEY_DESCRIPTION_free(p); }
-};
-
-static uint32_t get_uint32_value(const keymaster_key_param_t& param) {
- switch (keymaster_tag_get_type(param.tag)) {
- case KM_ENUM:
- case KM_ENUM_REP:
- return param.enumerated;
- case KM_UINT:
- case KM_UINT_REP:
- return param.integer;
- default:
- assert(false);
- return 0xFFFFFFFF;
- }
-}
-
-// Insert value in either the dest_integer or the dest_integer_set, whichever is provided.
-static keymaster_error_t insert_integer(ASN1_INTEGER* value, ASN1_INTEGER** dest_integer,
- ASN1_INTEGER_SET** dest_integer_set) {
- assert((dest_integer == nullptr) ^ (dest_integer_set == nullptr));
- assert(value);
-
- if (dest_integer_set) {
- if (!*dest_integer_set)
- *dest_integer_set = sk_ASN1_INTEGER_new_null();
- if (!*dest_integer_set)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- if (!sk_ASN1_INTEGER_push(*dest_integer_set, value))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- return KM_ERROR_OK;
-
- } else if (dest_integer) {
- if (*dest_integer)
- ASN1_INTEGER_free(*dest_integer);
- *dest_integer = value;
- return KM_ERROR_OK;
- }
-
- assert(false); // Should never get here.
- return KM_ERROR_OK;
-}
-
-// Put the contents of the keymaster AuthorizationSet auth_list in to the ASN.1 record structure,
-// record.
-static keymaster_error_t build_auth_list(const AuthorizationSet& auth_list, KM_AUTH_LIST* record) {
- assert(record);
-
- if (auth_list.empty())
- return KM_ERROR_OK;
-
- for (auto entry : auth_list) {
-
- ASN1_INTEGER_SET** integer_set = nullptr;
- ASN1_INTEGER** integer_ptr = nullptr;
- ASN1_OCTET_STRING** string_ptr = nullptr;
- ASN1_NULL** bool_ptr = nullptr;
-
- switch (entry.tag) {
-
- /* Ignored tags */
- case KM_TAG_INVALID:
- case KM_TAG_ASSOCIATED_DATA:
- case KM_TAG_NONCE:
- case KM_TAG_AUTH_TOKEN:
- case KM_TAG_MAC_LENGTH:
- case KM_TAG_ALL_USERS:
- case KM_TAG_USER_ID:
- case KM_TAG_USER_SECURE_ID:
- case KM_TAG_EXPORTABLE:
- case KM_TAG_RESET_SINCE_ID_ROTATION:
- case KM_TAG_ATTESTATION_CHALLENGE:
- case KM_TAG_BLOCK_MODE:
- case KM_TAG_CALLER_NONCE:
- case KM_TAG_MIN_MAC_LENGTH:
- case KM_TAG_ECIES_SINGLE_HASH_MODE:
- case KM_TAG_INCLUDE_UNIQUE_ID:
- case KM_TAG_BLOB_USAGE_REQUIREMENTS:
- case KM_TAG_BOOTLOADER_ONLY:
- case KM_TAG_MIN_SECONDS_BETWEEN_OPS:
- case KM_TAG_MAX_USES_PER_BOOT:
- case KM_TAG_APPLICATION_DATA:
- case KM_TAG_UNIQUE_ID:
- case KM_TAG_ROOT_OF_TRUST:
- continue;
-
- /* Non-repeating enumerations */
- case KM_TAG_ALGORITHM:
- integer_ptr = &record->algorithm;
- break;
- case KM_TAG_EC_CURVE:
- integer_ptr = &record->ec_curve;
- break;
- case KM_TAG_USER_AUTH_TYPE:
- integer_ptr = &record->user_auth_type;
- break;
- case KM_TAG_ORIGIN:
- integer_ptr = &record->origin;
- break;
-
- /* Repeating enumerations */
- case KM_TAG_PURPOSE:
- integer_set = &record->purpose;
- break;
- case KM_TAG_PADDING:
- integer_set = &record->padding;
- break;
- case KM_TAG_DIGEST:
- integer_set = &record->digest;
- break;
- case KM_TAG_KDF:
- integer_set = &record->kdf;
- break;
-
- /* Non-repeating unsigned integers */
- case KM_TAG_KEY_SIZE:
- integer_ptr = &record->key_size;
- break;
- case KM_TAG_AUTH_TIMEOUT:
- integer_ptr = &record->auth_timeout;
- break;
- case KM_TAG_OS_VERSION:
- integer_ptr = &record->os_version;
- break;
- case KM_TAG_OS_PATCHLEVEL:
- integer_ptr = &record->os_patchlevel;
- break;
-
- /* Non-repeating long unsigned integers */
- case KM_TAG_RSA_PUBLIC_EXPONENT:
- integer_ptr = &record->rsa_public_exponent;
- break;
-
- /* Dates */
- case KM_TAG_ACTIVE_DATETIME:
- integer_ptr = &record->active_date_time;
- break;
- case KM_TAG_ORIGINATION_EXPIRE_DATETIME:
- integer_ptr = &record->origination_expire_date_time;
- break;
- case KM_TAG_USAGE_EXPIRE_DATETIME:
- integer_ptr = &record->usage_expire_date_time;
- break;
- case KM_TAG_CREATION_DATETIME:
- integer_ptr = &record->creation_date_time;
- break;
-
- /* Booleans */
- case KM_TAG_NO_AUTH_REQUIRED:
- bool_ptr = &record->no_auth_required;
- break;
- case KM_TAG_ALL_APPLICATIONS:
- bool_ptr = &record->all_applications;
- break;
- case KM_TAG_ROLLBACK_RESISTANT:
- bool_ptr = &record->rollback_resistant;
- break;
- case KM_TAG_ALLOW_WHILE_ON_BODY:
- bool_ptr = &record->allow_while_on_body;
- break;
-
- /* Byte arrays*/
- case KM_TAG_APPLICATION_ID:
- string_ptr = &record->application_id;
- break;
- default:
- break;
- }
-
- keymaster_tag_type_t type = keymaster_tag_get_type(entry.tag);
- switch (type) {
- case KM_ENUM:
- case KM_ENUM_REP:
- case KM_UINT:
- case KM_UINT_REP: {
- assert((keymaster_tag_repeatable(entry.tag) && integer_set) ||
- (!keymaster_tag_repeatable(entry.tag) && integer_ptr));
-
- UniquePtr<ASN1_INTEGER, ASN1_INTEGER_Delete> value(ASN1_INTEGER_new());
- if (!value.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- if (!ASN1_INTEGER_set(value.get(), get_uint32_value(entry)))
- return TranslateLastOpenSslError();
-
- insert_integer(value.release(), integer_ptr, integer_set);
- break;
- }
-
- case KM_ULONG:
- case KM_ULONG_REP:
- case KM_DATE: {
- assert((keymaster_tag_repeatable(entry.tag) && integer_set) ||
- (!keymaster_tag_repeatable(entry.tag) && integer_ptr));
-
- UniquePtr<BIGNUM, BIGNUM_Delete> bn_value(BN_new());
- if (!bn_value.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- if (type == KM_DATE) {
- if (!BN_set_u64(bn_value.get(), entry.date_time)) {
- return TranslateLastOpenSslError();
- }
- } else {
- if (!BN_set_u64(bn_value.get(), entry.long_integer)) {
- return TranslateLastOpenSslError();
- }
- }
-
- UniquePtr<ASN1_INTEGER, ASN1_INTEGER_Delete> value(
- BN_to_ASN1_INTEGER(bn_value.get(), nullptr));
- if (!value.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- insert_integer(value.release(), integer_ptr, integer_set);
- break;
- }
-
- case KM_BOOL:
- assert(bool_ptr);
- if (!*bool_ptr)
- *bool_ptr = ASN1_NULL_new();
- if (!*bool_ptr)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- break;
-
- /* Byte arrays*/
- case KM_BYTES:
- assert(string_ptr);
- if (!*string_ptr)
- *string_ptr = ASN1_OCTET_STRING_new();
- if (!*string_ptr)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- if (!ASN1_OCTET_STRING_set(*string_ptr, entry.blob.data, entry.blob.data_length))
- return TranslateLastOpenSslError();
- break;
-
- default:
- return KM_ERROR_UNIMPLEMENTED;
- }
- }
-
- keymaster_ec_curve_t ec_curve;
- uint32_t key_size;
- if (auth_list.Contains(TAG_ALGORITHM, KM_ALGORITHM_EC) && //
- !auth_list.Contains(TAG_EC_CURVE) && //
- auth_list.GetTagValue(TAG_KEY_SIZE, &key_size)) {
- // This must be a keymaster1 key. It's an EC key with no curve. Insert the curve.
-
- keymaster_error_t error = EcKeySizeToCurve(key_size, &ec_curve);
- if (error != KM_ERROR_OK)
- return error;
-
- UniquePtr<ASN1_INTEGER, ASN1_INTEGER_Delete> value(ASN1_INTEGER_new());
- if (!value.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- if (!ASN1_INTEGER_set(value.get(), ec_curve))
- return TranslateLastOpenSslError();
-
- insert_integer(value.release(), &record->ec_curve, nullptr);
- }
-
- return KM_ERROR_OK;
-}
-
-// Construct an ASN1.1 DER-encoded attestation record containing the values from sw_enforced and
-// tee_enforced.
-keymaster_error_t build_attestation_record(const AuthorizationSet& attestation_params,
- const AuthorizationSet& sw_enforced,
- const AuthorizationSet& tee_enforced,
- const KeymasterContext& context,
- UniquePtr<uint8_t[]>* asn1_key_desc,
- size_t* asn1_key_desc_len) {
- assert(asn1_key_desc && asn1_key_desc_len);
-
- UniquePtr<KM_KEY_DESCRIPTION, KM_KEY_DESCRIPTION_Delete> key_desc(KM_KEY_DESCRIPTION_new());
- if (!key_desc.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- keymaster_security_level_t keymaster_security_level;
- uint32_t keymaster_version = UINT32_MAX;
- if (tee_enforced.empty()) {
- // Software key.
- keymaster_security_level = KM_SECURITY_LEVEL_SOFTWARE;
- keymaster_version = 2;
- } else {
- keymaster_security_level = KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT;
- switch (context.GetSecurityLevel()) {
- case KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT:
- // We're running in a TEE, so the key is KM2.
- keymaster_version = 2;
- break;
-
- case KM_SECURITY_LEVEL_SOFTWARE:
- // We're running in software, wrapping some KM hardware. Is it KM0 or KM1? KM1 keys
- // have the purpose in the tee_enforced list. It's possible that a key could be created
- // without a purpose, which would fool this test into reporting it's a KM0 key. That
- // corner case doesn't matter much, because purpose-less keys are not usable anyway.
- // Also, KM1 TEEs should disappear rapidly.
- keymaster_version = tee_enforced.Contains(TAG_PURPOSE) ? 1 : 0;
- break;
- }
-
- if (keymaster_version == UINT32_MAX)
- return KM_ERROR_UNKNOWN_ERROR;
- }
-
- if (!ASN1_INTEGER_set(key_desc->attestation_version, 1) ||
- !ASN1_ENUMERATED_set(key_desc->attestation_security_level, context.GetSecurityLevel()) ||
- !ASN1_INTEGER_set(key_desc->keymaster_version, keymaster_version) ||
- !ASN1_ENUMERATED_set(key_desc->keymaster_security_level, keymaster_security_level))
- return TranslateLastOpenSslError();
-
- keymaster_blob_t attestation_challenge = {nullptr, 0};
- if (!attestation_params.GetTagValue(TAG_ATTESTATION_CHALLENGE, &attestation_challenge))
- return KM_ERROR_ATTESTATION_CHALLENGE_MISSING;
- if (!ASN1_OCTET_STRING_set(key_desc->attestation_challenge, attestation_challenge.data,
- attestation_challenge.data_length))
- return TranslateLastOpenSslError();
-
- keymaster_error_t error = build_auth_list(sw_enforced, key_desc->software_enforced);
- if (error != KM_ERROR_OK)
- return error;
-
- error = build_auth_list(tee_enforced, key_desc->tee_enforced);
- if (error != KM_ERROR_OK)
- return error;
-
- // Only check tee_enforced for TAG_INCLUDE_UNIQUE_ID. If we don't have hardware we can't
- // generate unique IDs.
- if (tee_enforced.GetTagValue(TAG_INCLUDE_UNIQUE_ID)) {
- uint64_t creation_datetime;
- // Only check sw_enforced for TAG_CREATION_DATETIME, since it shouldn't be in tee_enforced,
- // since this implementation has no secure wall clock.
- if (!sw_enforced.GetTagValue(TAG_CREATION_DATETIME, &creation_datetime)) {
- LOG_E("Unique ID cannot be created without creation datetime", 0);
- return KM_ERROR_INVALID_KEY_BLOB;
- }
-
- keymaster_blob_t application_id = {nullptr, 0};
- sw_enforced.GetTagValue(TAG_APPLICATION_ID, &application_id);
-
- Buffer unique_id;
- error = context.GenerateUniqueId(
- creation_datetime, application_id,
- attestation_params.GetTagValue(TAG_RESET_SINCE_ID_ROTATION), &unique_id);
- if (error != KM_ERROR_OK)
- return error;
-
- key_desc->unique_id = ASN1_OCTET_STRING_new();
- if (!key_desc->unique_id ||
- !ASN1_OCTET_STRING_set(key_desc->unique_id, unique_id.peek_read(),
- unique_id.available_read()))
- return TranslateLastOpenSslError();
- }
-
- int len = i2d_KM_KEY_DESCRIPTION(key_desc.get(), nullptr);
- if (len < 0)
- return TranslateLastOpenSslError();
- *asn1_key_desc_len = len;
- asn1_key_desc->reset(new uint8_t[*asn1_key_desc_len]);
- if (!asn1_key_desc->get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- uint8_t* p = asn1_key_desc->get();
- len = i2d_KM_KEY_DESCRIPTION(key_desc.get(), &p);
- if (len < 0)
- return TranslateLastOpenSslError();
-
- return KM_ERROR_OK;
-}
-
-// Copy all enumerated values with the specified tag from stack to auth_list.
-static bool get_repeated_enums(const stack_st_ASN1_INTEGER* stack, keymaster_tag_t tag,
- AuthorizationSet* auth_list) {
- assert(keymaster_tag_get_type(tag) == KM_ENUM_REP);
- for (size_t i = 0; i < sk_ASN1_INTEGER_num(stack); ++i) {
- if (!auth_list->push_back(
- keymaster_param_enum(tag, ASN1_INTEGER_get(sk_ASN1_INTEGER_value(stack, i)))))
- return false;
- }
- return true;
-}
-
-// Add the specified integer tag/value pair to auth_list.
-template <keymaster_tag_type_t Type, keymaster_tag_t Tag, typename KeymasterEnum>
-static bool get_enum(const ASN1_INTEGER* asn1_int, TypedEnumTag<Type, Tag, KeymasterEnum> tag,
- AuthorizationSet* auth_list) {
- if (!asn1_int)
- return true;
- return auth_list->push_back(tag, static_cast<KeymasterEnum>(ASN1_INTEGER_get(asn1_int)));
-}
-
-// Add the specified ulong tag/value pair to auth_list.
-static bool get_ulong(const ASN1_INTEGER* asn1_int, keymaster_tag_t tag,
- AuthorizationSet* auth_list) {
- if (!asn1_int)
- return true;
- UniquePtr<BIGNUM, BIGNUM_Delete> bn(ASN1_INTEGER_to_BN(asn1_int, nullptr));
- if (!bn.get())
- return false;
- uint64_t ulong = BN_get_word(bn.get());
- return auth_list->push_back(keymaster_param_long(tag, ulong));
-}
-
-// Extract the values from the specified ASN.1 record and place them in auth_list.
-static keymaster_error_t extract_auth_list(const KM_AUTH_LIST* record,
- AuthorizationSet* auth_list) {
- if (!record)
- return KM_ERROR_OK;
-
- // Purpose
- if (!get_repeated_enums(record->purpose, TAG_PURPOSE, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Algorithm
- if (!get_enum(record->algorithm, TAG_ALGORITHM, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Key size
- if (record->key_size && !auth_list->push_back(TAG_KEY_SIZE, ASN1_INTEGER_get(record->key_size)))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Digest
- if (!get_repeated_enums(record->digest, TAG_DIGEST, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Padding
- if (!get_repeated_enums(record->padding, TAG_PADDING, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // EC curve
- if (!get_enum(record->ec_curve, TAG_EC_CURVE, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // RSA public exponent
- if (!get_ulong(record->rsa_public_exponent, TAG_RSA_PUBLIC_EXPONENT, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Active date time
- if (!get_ulong(record->active_date_time, TAG_ACTIVE_DATETIME, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Origination expire date time
- if (!get_ulong(record->origination_expire_date_time, TAG_ORIGINATION_EXPIRE_DATETIME,
- auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Usage Expire date time
- if (!get_ulong(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // No auth required
- if (record->no_auth_required && !auth_list->push_back(TAG_NO_AUTH_REQUIRED))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // User auth type
- if (!get_enum(record->user_auth_type, TAG_USER_AUTH_TYPE, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Auth timeout
- if (record->auth_timeout &&
- !auth_list->push_back(TAG_AUTH_TIMEOUT, ASN1_INTEGER_get(record->auth_timeout)))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // All applications
- if (record->all_applications && !auth_list->push_back(TAG_ALL_APPLICATIONS))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Application ID
- if (record->application_id &&
- !auth_list->push_back(TAG_APPLICATION_ID, record->application_id->data,
- record->application_id->length))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Creation date time
- if (!get_ulong(record->creation_date_time, TAG_CREATION_DATETIME, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Origin
- if (!get_enum(record->origin, TAG_ORIGIN, auth_list))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Rollback resistant
- if (record->rollback_resistant && !auth_list->push_back(TAG_ROLLBACK_RESISTANT))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Root of trust
- if (record->root_of_trust) {
- KM_ROOT_OF_TRUST* rot = record->root_of_trust;
- if (!rot->verified_boot_key)
- return KM_ERROR_INVALID_KEY_BLOB;
-
- // Other root of trust fields are not mapped to auth set entries.
- }
-
- // OS Version
- if (record->os_version &&
- !auth_list->push_back(TAG_OS_VERSION, ASN1_INTEGER_get(record->os_version)))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // OS Patch level
- if (record->os_patchlevel &&
- !auth_list->push_back(TAG_OS_PATCHLEVEL, ASN1_INTEGER_get(record->os_patchlevel)))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- return KM_ERROR_OK;
-}
-
-// Parse the DER-encoded attestation record, placing the results in keymaster_version,
-// attestation_challenge, software_enforced, tee_enforced and unique_id.
-keymaster_error_t parse_attestation_record(const uint8_t* asn1_key_desc, size_t asn1_key_desc_len,
- uint32_t* attestation_version, //
- keymaster_security_level_t* attestation_security_level,
- uint32_t* keymaster_version,
- keymaster_security_level_t* keymaster_security_level,
- keymaster_blob_t* attestation_challenge,
- AuthorizationSet* software_enforced,
- AuthorizationSet* tee_enforced,
- keymaster_blob_t* unique_id) {
- const uint8_t* p = asn1_key_desc;
- UniquePtr<KM_KEY_DESCRIPTION, KM_KEY_DESCRIPTION_Delete> record(
- d2i_KM_KEY_DESCRIPTION(nullptr, &p, asn1_key_desc_len));
- if (!record.get())
- return TranslateLastOpenSslError();
-
- *attestation_version = ASN1_INTEGER_get(record->attestation_version);
- *attestation_security_level = static_cast<keymaster_security_level_t>(
- ASN1_ENUMERATED_get(record->attestation_security_level));
- *keymaster_version = ASN1_INTEGER_get(record->keymaster_version);
- *keymaster_security_level = static_cast<keymaster_security_level_t>(
- ASN1_ENUMERATED_get(record->keymaster_security_level));
-
- attestation_challenge->data =
- dup_buffer(record->attestation_challenge->data, record->attestation_challenge->length);
- attestation_challenge->data_length = record->attestation_challenge->length;
-
- unique_id->data = dup_buffer(record->unique_id->data, record->unique_id->length);
- unique_id->data_length = record->unique_id->length;
-
- keymaster_error_t error = extract_auth_list(record->software_enforced, software_enforced);
- if (error != KM_ERROR_OK)
- return error;
-
- return extract_auth_list(record->tee_enforced, tee_enforced);
-}
-
-} // namepace keymaster
diff --git a/unit_test/attestation_record.h b/unit_test/attestation_record.h
deleted file mode 100644
index 64acabc..0000000
--- a/unit_test/attestation_record.h
+++ b/dev/null
@@ -1,62 +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.
- */
-
-#ifndef SYSTEM_KEYMASTER_ATTESTATION_RECORD_H_
-#define SYSTEM_KEYMASTER_ATTESTATION_RECORD_H_
-
-#include <hardware/keymaster_defs.h>
-
-#include <keymaster/authorization_set.h>
-
-namespace keymaster {
-
-class KeymasterContext;
-
-/**
- * The OID for Android attestation records. For the curious, it breaks down as follows:
- *
- * 1 = ISO
- * 3 = org
- * 6 = DoD (Huh? OIDs are weird.)
- * 1 = IANA
- * 4 = Private
- * 1 = Enterprises
- * 11129 = Google
- * 2 = Google security
- * 1 = certificate extension
- * 17 = Android attestation extension.
- */
-static const char kAttestionRecordOid[] = "1.3.6.1.4.1.11129.2.1.17";
-
-keymaster_error_t build_attestation_record(const AuthorizationSet& attestation_params,
- const AuthorizationSet& software_enforced,
- const AuthorizationSet& tee_enforced,
- const KeymasterContext& context,
- UniquePtr<uint8_t[]>* asn1_key_desc,
- size_t* asn1_key_desc_len);
-
-keymaster_error_t parse_attestation_record(const uint8_t* asn1_key_desc, size_t asn1_key_desc_len,
- uint32_t* attestation_version, //
- keymaster_security_level_t* attestation_security_level,
- uint32_t* keymaster_version,
- keymaster_security_level_t* keymaster_security_level,
- keymaster_blob_t* attestation_challenge,
- AuthorizationSet* software_enforced,
- AuthorizationSet* tee_enforced,
- keymaster_blob_t* unique_id);
-}
-
-#endif // SYSTEM_KEYMASTER_ATTESTATION_RECORD_H_
diff --git a/unit_test/attestation_record_test.cpp b/unit_test/attestation_record_test.cpp
deleted file mode 100644
index 1cf8630..0000000
--- a/unit_test/attestation_record_test.cpp
+++ b/dev/null
@@ -1,145 +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 <fstream>
-
-#include <gtest/gtest.h>
-
-#include <keymaster/keymaster_context.h>
-
-#include "android_keymaster_test_utils.h"
-#include "attestation_record.h"
-
-#include <keymaster/keymaster_context.h>
-
-namespace keymaster {
-namespace test {
-
-class TestContext : public KeymasterContext {
- public:
- keymaster_security_level_t GetSecurityLevel() const override {
- return KM_SECURITY_LEVEL_SOFTWARE;
- }
- keymaster_error_t SetSystemVersion(uint32_t /* os_version */,
- uint32_t /* os_patchlevel */) override {
- return KM_ERROR_UNIMPLEMENTED;
- }
- void GetSystemVersion(uint32_t* os_version, uint32_t* os_patchlevel) const override {
- *os_version = 0;
- *os_patchlevel = 0;
- }
- KeyFactory* GetKeyFactory(keymaster_algorithm_t /* algorithm */) const override {
- return nullptr;
- }
- OperationFactory* GetOperationFactory(keymaster_algorithm_t /* algorithm */,
- keymaster_purpose_t /* purpose */) const override {
- return nullptr;
- }
- keymaster_algorithm_t* GetSupportedAlgorithms(size_t* /* algorithms_count */) const override {
- return nullptr;
- }
- keymaster_error_t CreateKeyBlob(const AuthorizationSet& /* key_description */,
- keymaster_key_origin_t /* origin */,
- const KeymasterKeyBlob& /* key_material */,
- KeymasterKeyBlob* /* blob */,
- AuthorizationSet* /* hw_enforced */,
- AuthorizationSet* /* sw_enforced */) const override {
- return KM_ERROR_UNIMPLEMENTED;
- }
- keymaster_error_t UpgradeKeyBlob(const KeymasterKeyBlob& /* key_to_upgrade */,
- const AuthorizationSet& /* upgrade_params */,
- KeymasterKeyBlob* /* upgraded_key */) const override {
- return KM_ERROR_UNIMPLEMENTED;
- }
- keymaster_error_t ParseKeyBlob(const KeymasterKeyBlob& /* blob */,
- const AuthorizationSet& /* additional_params */,
- KeymasterKeyBlob* /* key_material */,
- AuthorizationSet* /* hw_enforced */,
- AuthorizationSet* /* sw_enforced */) const override {
- return KM_ERROR_UNIMPLEMENTED;
- }
- keymaster_error_t AddRngEntropy(const uint8_t* /* buf */, size_t /* length */) const override {
- return KM_ERROR_UNIMPLEMENTED;
- }
- keymaster_error_t GenerateRandom(uint8_t* /* buf */, size_t /* length */) const override {
- return KM_ERROR_UNIMPLEMENTED;
- }
- KeymasterEnforcement* enforcement_policy() { return nullptr; }
- EVP_PKEY* AttestationKey(keymaster_algorithm_t /* algorithm */,
- keymaster_error_t* /* error */) const override {
- return nullptr;
- }
- keymaster_cert_chain_t* AttestationChain(keymaster_algorithm_t /* algorithm */,
- keymaster_error_t* /* error */) const override {
- return nullptr;
- }
- keymaster_error_t GenerateUniqueId(uint64_t /* creation_date_time */,
- const keymaster_blob_t& /* application_id */,
- bool /* reset_since_rotation */, Buffer* unique_id) const {
- // Finally, the reason for defining this class:
- unique_id->Reinitialize("foo", 3);
- return KM_ERROR_OK;
- }
-};
-
-TEST(AttestTest, Simple) {
- AuthorizationSet hw_set(AuthorizationSetBuilder()
- .RsaSigningKey(512, 3)
- .Digest(KM_DIGEST_SHA_2_256)
- .Digest(KM_DIGEST_SHA_2_384)
- .Authorization(TAG_OS_VERSION, 60000)
- .Authorization(TAG_OS_PATCHLEVEL, 201512)
- .Authorization(TAG_APPLICATION_ID, "bar", 3));
- AuthorizationSet sw_set(AuthorizationSetBuilder().Authorization(TAG_ACTIVE_DATETIME, 10));
-
- UniquePtr<uint8_t[]> asn1;
- size_t asn1_len;
- AuthorizationSet attest_params(
- AuthorizationSetBuilder().Authorization(TAG_ATTESTATION_CHALLENGE, "hello", 5));
- EXPECT_EQ(KM_ERROR_OK, build_attestation_record(attest_params, sw_set, hw_set, TestContext(),
- &asn1, &asn1_len));
- EXPECT_GT(asn1_len, 0U);
-
- std::ofstream output("attest.der",
- std::ofstream::out | std::ofstream::binary | std::ofstream::trunc);
- if (output)
- output.write(reinterpret_cast<const char*>(asn1.get()), asn1_len);
- output.close();
-
- AuthorizationSet parsed_hw_set;
- AuthorizationSet parsed_sw_set;
- uint32_t attestation_version;
- uint32_t keymaster_version;
- keymaster_security_level_t attestation_security_level;
- keymaster_security_level_t keymaster_security_level;
- keymaster_blob_t attestation_challenge = {};
- keymaster_blob_t unique_id = {};
- EXPECT_EQ(KM_ERROR_OK,
- parse_attestation_record(asn1.get(), asn1_len, &attestation_version,
- &attestation_security_level, &keymaster_version,
- &keymaster_security_level, &attestation_challenge,
- &parsed_sw_set, &parsed_hw_set, &unique_id));
-
- hw_set.Sort();
- sw_set.Sort();
- parsed_hw_set.Sort();
- parsed_sw_set.Sort();
- EXPECT_EQ(hw_set, parsed_hw_set);
- EXPECT_EQ(sw_set, parsed_sw_set);
-}
-
-} // namespace test
-} // namespace keymaster
diff --git a/unit_test/authorization_set_test.cpp b/unit_test/authorization_set_test.cpp
deleted file mode 100644
index f3f4412..0000000
--- a/unit_test/authorization_set_test.cpp
+++ b/dev/null
@@ -1,745 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#include <gtest/gtest.h>
-
-#include <keymaster/authorization_set.h>
-#include <keymaster/android_keymaster_utils.h>
-
-#include "android_keymaster_test_utils.h"
-
-namespace keymaster {
-
-namespace test {
-
-TEST(Construction, ListProvided) {
- keymaster_key_param_t params[] = {
- Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
- Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), Authorization(TAG_USER_ID, 7),
- Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD),
- Authorization(TAG_APPLICATION_ID, "my_app", 6), Authorization(TAG_KEY_SIZE, 256),
- Authorization(TAG_AUTH_TIMEOUT, 300),
- };
- AuthorizationSet set(params, array_length(params));
- EXPECT_EQ(8U, set.size());
-}
-
-TEST(Construction, Copy) {
- keymaster_key_param_t params[] = {
- Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
- Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), Authorization(TAG_USER_ID, 7),
- Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD),
- Authorization(TAG_APPLICATION_ID, "my_app", 6), Authorization(TAG_KEY_SIZE, 256),
- Authorization(TAG_AUTH_TIMEOUT, 300),
- };
- AuthorizationSet set(params, array_length(params));
- AuthorizationSet set2(set);
- EXPECT_EQ(set, set2);
-}
-
-TEST(Construction, NullProvided) {
- keymaster_key_param_t params[] = {
- Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
- };
-
- AuthorizationSet set1(params, 0);
- EXPECT_EQ(0U, set1.size());
- EXPECT_EQ(AuthorizationSet::OK, set1.is_valid());
-
- AuthorizationSet set2(reinterpret_cast<keymaster_key_param_t*>(NULL), array_length(params));
- EXPECT_EQ(0U, set2.size());
- EXPECT_EQ(AuthorizationSet::OK, set2.is_valid());
-}
-
-TEST(Lookup, NonRepeated) {
- AuthorizationSet set(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD)
- .Authorization(TAG_APPLICATION_ID, "my_app", 6)
- .Authorization(TAG_KEY_SIZE, 256)
- .Authorization(TAG_AUTH_TIMEOUT, 300));
-
- EXPECT_EQ(8U, set.size());
-
- int pos = set.find(TAG_ALGORITHM);
- ASSERT_NE(-1, pos);
- EXPECT_EQ(KM_TAG_ALGORITHM, set[pos].tag);
- EXPECT_EQ(KM_ALGORITHM_RSA, set[pos].enumerated);
-
- pos = set.find(TAG_MAC_LENGTH);
- EXPECT_EQ(-1, pos);
-
- uint32_t int_val = 0;
- EXPECT_TRUE(set.GetTagValue(TAG_USER_ID, &int_val));
- EXPECT_EQ(7U, int_val);
-
- keymaster_blob_t blob_val;
- EXPECT_TRUE(set.GetTagValue(TAG_APPLICATION_ID, &blob_val));
- EXPECT_EQ(6U, blob_val.data_length);
- EXPECT_EQ(0, memcmp(blob_val.data, "my_app", 6));
-}
-
-TEST(Lookup, Repeated) {
- AuthorizationSet set(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_USER_SECURE_ID, 47727)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD)
- .Authorization(TAG_APPLICATION_ID, "my_app", 6)
- .Authorization(TAG_KEY_SIZE, 256)
- .Authorization(TAG_AUTH_TIMEOUT, 300));
- EXPECT_EQ(9U, set.size());
-
- int pos = set.find(TAG_PURPOSE);
- ASSERT_FALSE(pos == -1);
- EXPECT_EQ(KM_TAG_PURPOSE, set[pos].tag);
- EXPECT_EQ(KM_PURPOSE_SIGN, set[pos].enumerated);
-
- pos = set.find(TAG_PURPOSE, pos);
- EXPECT_EQ(KM_TAG_PURPOSE, set[pos].tag);
- EXPECT_EQ(KM_PURPOSE_VERIFY, set[pos].enumerated);
-
- EXPECT_EQ(-1, set.find(TAG_PURPOSE, pos));
-
- pos = set.find(TAG_USER_SECURE_ID, pos);
- EXPECT_EQ(KM_TAG_USER_SECURE_ID, set[pos].tag);
- EXPECT_EQ(47727U, set[pos].long_integer);
-}
-
-TEST(Lookup, Indexed) {
- AuthorizationSet set(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD)
- .Authorization(TAG_APPLICATION_ID, "my_app", 6)
- .Authorization(TAG_KEY_SIZE, 256)
- .Authorization(TAG_AUTH_TIMEOUT, 300));
- EXPECT_EQ(8U, set.size());
-
- EXPECT_EQ(KM_TAG_PURPOSE, set[0].tag);
- EXPECT_EQ(KM_PURPOSE_SIGN, set[0].enumerated);
-
- // Lookup beyond end doesn't work, just returns zeros, but doens't blow up either (verify by
- // running under valgrind).
- EXPECT_EQ(KM_TAG_INVALID, set[10].tag);
-}
-
-TEST(Serialization, RoundTrip) {
- AuthorizationSet set(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD)
- .Authorization(TAG_APPLICATION_ID, "my_app", 6)
- .Authorization(TAG_KEY_SIZE, 256)
- .Authorization(TAG_USER_SECURE_ID, 47727)
- .Authorization(TAG_AUTH_TIMEOUT, 300)
- .Authorization(TAG_ALL_USERS)
- .Authorization(TAG_RSA_PUBLIC_EXPONENT, 3)
- .Authorization(TAG_ACTIVE_DATETIME, 10));
-
- size_t size = set.SerializedSize();
- EXPECT_TRUE(size > 0);
-
- UniquePtr<uint8_t[]> buf(new uint8_t[size]);
- EXPECT_EQ(buf.get() + size, set.Serialize(buf.get(), buf.get() + size));
- AuthorizationSet deserialized(buf.get(), size);
-
- EXPECT_EQ(AuthorizationSet::OK, deserialized.is_valid());
- EXPECT_EQ(set, deserialized);
-
- int pos = deserialized.find(TAG_APPLICATION_ID);
- ASSERT_NE(-1, pos);
- EXPECT_EQ(KM_TAG_APPLICATION_ID, deserialized[pos].tag);
- EXPECT_EQ(6U, deserialized[pos].blob.data_length);
- EXPECT_EQ(0, memcmp(deserialized[pos].blob.data, "my_app", 6));
-}
-
-TEST(Deserialization, Deserialize) {
- AuthorizationSet set(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD)
- .Authorization(TAG_APPLICATION_ID, "my_app", 6)
- .Authorization(TAG_KEY_SIZE, 256)
- .Authorization(TAG_AUTH_TIMEOUT, 300));
-
- size_t size = set.SerializedSize();
- EXPECT_TRUE(size > 0);
-
- UniquePtr<uint8_t[]> buf(new uint8_t[size]);
- EXPECT_EQ(buf.get() + size, set.Serialize(buf.get(), buf.get() + size));
- AuthorizationSet deserialized;
- const uint8_t* p = buf.get();
- EXPECT_TRUE(deserialized.Deserialize(&p, p + size));
- EXPECT_EQ(p, buf.get() + size);
-
- EXPECT_EQ(AuthorizationSet::OK, deserialized.is_valid());
-
- EXPECT_EQ(set.size(), deserialized.size());
- for (size_t i = 0; i < set.size(); ++i) {
- EXPECT_EQ(set[i].tag, deserialized[i].tag);
- }
-
- int pos = deserialized.find(TAG_APPLICATION_ID);
- ASSERT_NE(-1, pos);
- EXPECT_EQ(KM_TAG_APPLICATION_ID, deserialized[pos].tag);
- EXPECT_EQ(6U, deserialized[pos].blob.data_length);
- EXPECT_EQ(0, memcmp(deserialized[pos].blob.data, "my_app", 6));
-}
-
-TEST(Deserialization, TooShortBuffer) {
- uint8_t buf[] = {0, 0, 0};
- AuthorizationSet deserialized(buf, array_length(buf));
- EXPECT_EQ(AuthorizationSet::MALFORMED_DATA, deserialized.is_valid());
-
- const uint8_t* p = buf;
- EXPECT_FALSE(deserialized.Deserialize(&p, p + array_length(buf)));
- EXPECT_EQ(AuthorizationSet::MALFORMED_DATA, deserialized.is_valid());
-}
-
-TEST(Deserialization, InvalidLengthField) {
- AuthorizationSet set(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD)
- .Authorization(TAG_APPLICATION_ID, "my_app", 6)
- .Authorization(TAG_KEY_SIZE, 256)
- .Authorization(TAG_AUTH_TIMEOUT, 300));
-
- size_t size = set.SerializedSize();
- EXPECT_TRUE(size > 0);
-
- UniquePtr<uint8_t[]> buf(new uint8_t[size]);
- EXPECT_EQ(buf.get() + size, set.Serialize(buf.get(), buf.get() + size));
- *reinterpret_cast<uint32_t*>(buf.get()) = 9;
-
- AuthorizationSet deserialized(buf.get(), size);
- EXPECT_EQ(AuthorizationSet::MALFORMED_DATA, deserialized.is_valid());
-
- const uint8_t* p = buf.get();
- EXPECT_FALSE(deserialized.Deserialize(&p, p + size));
- EXPECT_EQ(AuthorizationSet::MALFORMED_DATA, deserialized.is_valid());
-}
-
-static uint32_t read_uint32(const uint8_t* buf) {
- uint32_t val;
- memcpy(&val, buf, sizeof(val));
- return val;
-}
-
-static void add_to_uint32(uint8_t* buf, int delta) {
- uint32_t val;
- memcpy(&val, buf, sizeof(val));
- val += delta;
- memcpy(buf, &val, sizeof(val));
-}
-
-TEST(Deserialization, MalformedIndirectData) {
- AuthorizationSet set(AuthorizationSetBuilder()
- .Authorization(TAG_APPLICATION_ID, "my_app", 6)
- .Authorization(TAG_APPLICATION_DATA, "foo", 3));
- size_t size = set.SerializedSize();
-
- UniquePtr<uint8_t[]> buf(new uint8_t[size]);
- EXPECT_EQ(buf.get() + size, set.Serialize(buf.get(), buf.get() + size));
-
- // This sucks. This test, as written, requires intimate knowledge of the serialized layout of
- // this particular set, which means it's brittle. But it's important to test that we handle
- // broken serialized data and I can't think of a better way to write this.
- //
- // The contents of buf are:
- //
- // Bytes: Content:
- // 0-3 Length of string data, which is 9.
- // 4-9 "my_app"
- // 10-12 "foo"
- // 13-16 Number of elements, which is 2.
- // 17-20 Length of elements, which is 24.
- // 21-24 First tag, TAG_APPLICATION_ID
- // 25-28 Length of string "my_app", 6
- // 29-32 Offset of string "my_app", 0
- // 33-36 Second tag, TAG_APPLICATION_DATA
- // 37-40 Length of string "foo", 3
- // 41-44 Offset of string "foo", 6
-
- // Check that stuff is where we think.
- EXPECT_EQ('m', buf[4]);
- EXPECT_EQ('f', buf[10]);
- // Length of "my_app"
- EXPECT_EQ(6U, read_uint32(buf.get() + 25));
- // Offset of "my_app"
- EXPECT_EQ(0U, read_uint32(buf.get() + 29));
- // Length of "foo"
- EXPECT_EQ(3U, read_uint32(buf.get() + 37));
- // Offset of "foo"
- EXPECT_EQ(6U, read_uint32(buf.get() + 41));
-
- // Check that deserialization works.
- AuthorizationSet deserialized1(buf.get(), size);
- EXPECT_EQ(AuthorizationSet::OK, deserialized1.is_valid());
-
- const uint8_t* p = buf.get();
- EXPECT_TRUE(deserialized1.Deserialize(&p, p + size));
- EXPECT_EQ(AuthorizationSet::OK, deserialized1.is_valid());
-
- //
- // Now mess them up in various ways:
- //
-
- // Move "foo" offset so offset + length goes off the end
- add_to_uint32(buf.get() + 41, 1);
- AuthorizationSet deserialized2(buf.get(), size);
- EXPECT_EQ(AuthorizationSet::MALFORMED_DATA, deserialized2.is_valid());
- add_to_uint32(buf.get() + 41, -1);
-
- // Shorten the "my_app" length to make a gap between the blobs.
- add_to_uint32(buf.get() + 25, -1);
- AuthorizationSet deserialized3(buf.get(), size);
- EXPECT_EQ(AuthorizationSet::MALFORMED_DATA, deserialized3.is_valid());
- add_to_uint32(buf.get() + 25, 1);
-
- // Extend the "my_app" length to make them overlap, and decrease the "foo" length to keep the
- // total length the same. We don't detect this but should.
- // TODO(swillden): Detect overlaps and holes that leave total size correct.
- add_to_uint32(buf.get() + 25, 1);
- add_to_uint32(buf.get() + 37, -1);
- AuthorizationSet deserialized4(buf.get(), size);
- EXPECT_EQ(AuthorizationSet::OK, deserialized4.is_valid());
-}
-
-TEST(Growable, SuccessfulRoundTrip) {
- AuthorizationSet growable;
- EXPECT_TRUE(growable.push_back(Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)));
- EXPECT_EQ(1U, growable.size());
-
- EXPECT_TRUE(growable.push_back(Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)));
- EXPECT_EQ(2U, growable.size());
-
- EXPECT_TRUE(growable.push_back(Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)));
- EXPECT_EQ(3U, growable.size());
-
- EXPECT_TRUE(growable.push_back(Authorization(TAG_APPLICATION_ID, "data", 4)));
- EXPECT_EQ(4U, growable.size());
-
- EXPECT_TRUE(growable.push_back(Authorization(TAG_APPLICATION_DATA, "some more data", 14)));
- EXPECT_EQ(5U, growable.size());
-
- size_t serialize_size = growable.SerializedSize();
- UniquePtr<uint8_t[]> serialized(new uint8_t[serialize_size]);
- EXPECT_EQ(serialized.get() + serialize_size,
- growable.Serialize(serialized.get(), serialized.get() + serialize_size));
-
- AuthorizationSet deserialized(serialized.get(), serialize_size);
- EXPECT_EQ(growable, deserialized);
-}
-
-TEST(Growable, InsufficientElemBuf) {
- AuthorizationSet growable;
- EXPECT_EQ(AuthorizationSet::OK, growable.is_valid());
-
- // First insertion fits.
- EXPECT_TRUE(growable.push_back(Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)));
- EXPECT_EQ(1U, growable.size());
- EXPECT_EQ(AuthorizationSet::OK, growable.is_valid());
-
- // Second does too.
- EXPECT_TRUE(growable.push_back(Authorization(TAG_RSA_PUBLIC_EXPONENT, 3)));
- EXPECT_EQ(2U, growable.size());
-}
-
-TEST(Growable, InsufficientIndirectBuf) {
- AuthorizationSet growable;
- EXPECT_EQ(AuthorizationSet::OK, growable.is_valid());
-
- EXPECT_TRUE(growable.push_back(Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)));
- EXPECT_EQ(1U, growable.size());
- EXPECT_EQ(AuthorizationSet::OK, growable.is_valid());
-
- EXPECT_TRUE(growable.push_back(Authorization(TAG_APPLICATION_ID, "1234567890", 10)));
- EXPECT_EQ(2U, growable.size());
- EXPECT_EQ(AuthorizationSet::OK, growable.is_valid());
-
- EXPECT_TRUE(growable.push_back(Authorization(TAG_APPLICATION_DATA, "1", 1)));
- EXPECT_EQ(3U, growable.size());
- EXPECT_EQ(AuthorizationSet::OK, growable.is_valid());
-
- // Can still add another entry without indirect data. Now it's full.
- EXPECT_TRUE(growable.push_back(Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)));
- EXPECT_EQ(4U, growable.size());
- EXPECT_EQ(AuthorizationSet::OK, growable.is_valid());
-}
-
-TEST(Growable, PushBackSets) {
- AuthorizationSetBuilder builder;
- builder.Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD)
- .Authorization(TAG_APPLICATION_ID, "my_app", 6)
- .Authorization(TAG_KEY_SIZE, 256)
- .Authorization(TAG_AUTH_TIMEOUT, 300);
-
- AuthorizationSet set1(builder.build());
- AuthorizationSet set2(builder.build());
-
- AuthorizationSet combined;
- EXPECT_TRUE(combined.push_back(set1));
- EXPECT_TRUE(combined.push_back(set2));
- EXPECT_EQ(set1.size() + set2.size(), combined.size());
- EXPECT_EQ(12U, combined.indirect_size());
-}
-
-TEST(GetValue, GetInt) {
- AuthorizationSet set(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD)
- .Authorization(TAG_APPLICATION_ID, "my_app", 6)
- .Authorization(TAG_AUTH_TIMEOUT, 300));
-
- uint32_t val;
- EXPECT_TRUE(set.GetTagValue(TAG_USER_ID, &val));
- EXPECT_EQ(7U, val);
-
- // Find one that isn't there
- EXPECT_FALSE(set.GetTagValue(TAG_KEY_SIZE, &val));
-}
-
-TEST(GetValue, GetLong) {
- AuthorizationSet set1(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_RSA_PUBLIC_EXPONENT, 3));
-
- AuthorizationSet set2(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA));
-
- uint64_t val;
- EXPECT_TRUE(set1.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &val));
- EXPECT_EQ(3U, val);
-
- // Find one that isn't there
- EXPECT_FALSE(set2.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &val));
-}
-
-TEST(GetValue, GetLongRep) {
- AuthorizationSet set1(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_SECURE_ID, 8338)
- .Authorization(TAG_USER_SECURE_ID, 4334)
- .Authorization(TAG_RSA_PUBLIC_EXPONENT, 3));
-
- AuthorizationSet set2(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA));
-
- uint64_t val;
- EXPECT_TRUE(set1.GetTagValue(TAG_USER_SECURE_ID, 0, &val));
- EXPECT_EQ(8338U, val);
- EXPECT_TRUE(set1.GetTagValue(TAG_USER_SECURE_ID, 1, &val));
- EXPECT_EQ(4334U, val);
-
- // Find one that isn't there
- EXPECT_FALSE(set2.GetTagValue(TAG_USER_SECURE_ID, &val));
-}
-
-TEST(GetValue, GetEnum) {
- AuthorizationSet set(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD)
- .Authorization(TAG_APPLICATION_ID, "my_app", 6)
- .Authorization(TAG_AUTH_TIMEOUT, 300));
-
- keymaster_algorithm_t val;
- EXPECT_TRUE(set.GetTagValue(TAG_ALGORITHM, &val));
- EXPECT_EQ(KM_ALGORITHM_RSA, val);
-
- // Find one that isn't there
- keymaster_padding_t val2;
- EXPECT_FALSE(set.GetTagValue(TAG_PADDING, &val2));
-}
-
-TEST(GetValue, GetEnumRep) {
- AuthorizationSet set(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD)
- .Authorization(TAG_APPLICATION_ID, "my_app", 6)
- .Authorization(TAG_AUTH_TIMEOUT, 300));
-
- keymaster_purpose_t val;
- EXPECT_TRUE(set.GetTagValue(TAG_PURPOSE, 0, &val));
- EXPECT_EQ(KM_PURPOSE_SIGN, val);
- EXPECT_TRUE(set.GetTagValue(TAG_PURPOSE, 1, &val));
- EXPECT_EQ(KM_PURPOSE_VERIFY, val);
-
- // Find one that isn't there
- EXPECT_FALSE(set.GetTagValue(TAG_PURPOSE, 2, &val));
-}
-
-TEST(GetValue, GetDate) {
- AuthorizationSet set(AuthorizationSetBuilder()
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD)
- .Authorization(TAG_APPLICATION_ID, "my_app", 6)
- .Authorization(TAG_AUTH_TIMEOUT, 300));
-
- uint64_t val;
- EXPECT_TRUE(set.GetTagValue(TAG_ACTIVE_DATETIME, &val));
- EXPECT_EQ(10U, val);
-
- // Find one that isn't there
- EXPECT_FALSE(set.GetTagValue(TAG_USAGE_EXPIRE_DATETIME, &val));
-}
-
-TEST(GetValue, GetBlob) {
- AuthorizationSet set(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD)
- .Authorization(TAG_APPLICATION_ID, "my_app", 6)
- .Authorization(TAG_AUTH_TIMEOUT, 300));
-
- keymaster_blob_t val;
- EXPECT_TRUE(set.GetTagValue(TAG_APPLICATION_ID, &val));
- EXPECT_EQ(6U, val.data_length);
- EXPECT_EQ(0, memcmp(val.data, "my_app", 6));
-
- // Find one that isn't there
- EXPECT_FALSE(set.GetTagValue(TAG_APPLICATION_DATA, &val));
-}
-
-TEST(Deduplication, NoDuplicates) {
- AuthorizationSet set(AuthorizationSetBuilder()
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD));
- AuthorizationSet copy(set);
-
- EXPECT_EQ(copy, set);
- set.Deduplicate();
- EXPECT_EQ(copy.size(), set.size());
-
- // Sets no longer compare equal, because of ordering (ugh, maybe it should be
- // AuthorizationList, not AuthorizationSet).
- EXPECT_NE(copy, set);
-}
-
-TEST(Deduplication, NoDuplicatesHasInvalid) {
- AuthorizationSet set(AuthorizationSetBuilder()
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_INVALID)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD));
- AuthorizationSet copy(set);
-
- EXPECT_EQ(copy, set);
- set.Deduplicate();
-
- // Deduplicate should have removed the invalid.
- EXPECT_EQ(copy.size() - 1, set.size());
- EXPECT_NE(copy, set);
-}
-
-TEST(Deduplication, DuplicateEnum) {
- AuthorizationSet set(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD));
- AuthorizationSet copy(set);
-
- EXPECT_EQ(copy, set);
- set.Deduplicate();
- EXPECT_EQ(copy.size() - 2, set.size());
- EXPECT_NE(copy, set);
-}
-
-TEST(Deduplication, DuplicateBlob) {
- AuthorizationSet set(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_APPLICATION_DATA, "data", 4)
- .Authorization(TAG_APPLICATION_DATA, "foo", 3)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD));
- AuthorizationSet copy(set);
-
- EXPECT_EQ(copy, set);
- set.Deduplicate();
- EXPECT_EQ(copy.size() - 3, set.size());
- EXPECT_NE(copy, set);
-
- // The real test here is that valgrind reports no leak.
-}
-
-TEST(Union, Disjoint) {
- AuthorizationSet set1(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
-
- AuthorizationSet set2(AuthorizationSetBuilder()
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_APPLICATION_DATA, "foo", 3)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD));
-
- AuthorizationSet expected(AuthorizationSetBuilder()
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4)
- .Authorization(TAG_APPLICATION_DATA, "foo", 3));
-
- set1.Union(set2);
- EXPECT_EQ(expected, set1);
-}
-
-TEST(Union, Overlap) {
- AuthorizationSet set1(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
-
- AuthorizationSet set2(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
-
- AuthorizationSet expected(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
-
- set1.Union(set2);
- EXPECT_EQ(expected, set1);
-}
-
-TEST(Union, Empty) {
- AuthorizationSet set1(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
-
- AuthorizationSet set2;
-
- AuthorizationSet expected(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
-
- set1.Union(set2);
- EXPECT_EQ(expected, set1);
-}
-
-TEST(Difference, Disjoint) {
- AuthorizationSet set1(AuthorizationSetBuilder()
- .Authorization(TAG_APPLICATION_DATA, "data", 4)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10));
-
- AuthorizationSet set2(AuthorizationSetBuilder()
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_APPLICATION_DATA, "foo", 3)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD));
-
- // Elements are the same as set1, but happen to be in a different order
- AuthorizationSet expected(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
-
- set1.Difference(set2);
- EXPECT_EQ(expected, set1);
-}
-
-TEST(Difference, Overlap) {
- AuthorizationSet set1(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
-
- AuthorizationSet set2(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
-
- AuthorizationSet empty;
- set1.Difference(set2);
- EXPECT_EQ(empty, set1);
- EXPECT_EQ(0U, set1.size());
-}
-
-TEST(Difference, NullSet) {
- AuthorizationSet set1(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
-
- AuthorizationSet set2;
-
- AuthorizationSet expected(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
-
- set1.Difference(set2);
- EXPECT_EQ(expected, set1);
-}
-
-} // namespace test
-} // namespace keymaster
diff --git a/unit_test/ecies_kem_test.cpp b/unit_test/ecies_kem_test.cpp
deleted file mode 100644
index f653dc0..0000000
--- a/unit_test/ecies_kem_test.cpp
+++ b/dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2015 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 "ecies_kem.h"
-
-#include <gtest/gtest.h>
-#include <openssl/evp.h>
-
-#include <hardware/keymaster_defs.h>
-#include <keymaster/android_keymaster_utils.h>
-
-#include "android_keymaster_test_utils.h"
-#include "nist_curve_key_exchange.h"
-
-using std::string;
-
-namespace keymaster {
-namespace test {
-
-StdoutLogger logger;
-
-static const keymaster_ec_curve_t kEcCurves[] = {KM_EC_CURVE_P_224, KM_EC_CURVE_P_256,
- KM_EC_CURVE_P_384, KM_EC_CURVE_P_521};
-
-/**
- * TestConsistency just tests that the basic key encapsulation hold.
- */
-TEST(EciesKem, TestConsistency) {
- static const uint32_t kKeyLen = 32;
- for (auto& curve : kEcCurves) {
- AuthorizationSet kem_description(AuthorizationSetBuilder()
- .Authorization(TAG_EC_CURVE, curve)
- .Authorization(TAG_KDF, KM_KDF_RFC5869_SHA256)
- .Authorization(TAG_ECIES_SINGLE_HASH_MODE)
- .Authorization(TAG_KEY_SIZE, kKeyLen));
- keymaster_error_t error;
- EciesKem* kem = new EciesKem(kem_description, &error);
- ASSERT_EQ(KM_ERROR_OK, error);
-
- NistCurveKeyExchange* key_exchange = NistCurveKeyExchange::GenerateKeyExchange(curve);
- Buffer peer_public_value;
- ASSERT_TRUE(key_exchange->public_value(&peer_public_value));
-
- Buffer output_clear_key;
- Buffer output_encrypted_key;
- ASSERT_TRUE(kem->Encrypt(peer_public_value, &output_clear_key, &output_encrypted_key));
- ASSERT_EQ(kKeyLen, output_clear_key.available_read());
- ASSERT_EQ(peer_public_value.available_read(), output_encrypted_key.available_read());
-
- Buffer decrypted_clear_key;
- ASSERT_TRUE(
- kem->Decrypt(key_exchange->private_key(), output_encrypted_key, &decrypted_clear_key));
- ASSERT_EQ(kKeyLen, decrypted_clear_key.available_read());
- EXPECT_EQ(0, memcmp(output_clear_key.peek_read(), decrypted_clear_key.peek_read(),
- output_clear_key.available_read()));
- }
-}
-
-} // namespace test
-} // namespace keymaster
diff --git a/unit_test/gtest_main.cpp b/unit_test/gtest_main.cpp
deleted file mode 100644
index 6072749..0000000
--- a/unit_test/gtest_main.cpp
+++ b/dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2015 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 <gtest/gtest.h>
-
-#include <openssl/engine.h>
-
-int main(int argc, char** argv) {
-#if !defined(OPENSSL_IS_BORINGSSL)
- ERR_load_crypto_strings();
-#endif // not OPENSSL_IS_BORINGSSL
- ::testing::InitGoogleTest(&argc, argv);
- int result = RUN_ALL_TESTS();
-#if !defined(OPENSSL_IS_BORINGSSL)
- // Clean up stuff OpenSSL leaves around, so Valgrind doesn't complain.
- CRYPTO_cleanup_all_ex_data();
- ERR_remove_thread_state(NULL);
- ERR_free_strings();
-#endif // not OPENSSL_IS_BORINGSSL
- return result;
-}
diff --git a/unit_test/hkdf_test.cpp b/unit_test/hkdf_test.cpp
deleted file mode 100644
index 3d3f092..0000000
--- a/unit_test/hkdf_test.cpp
+++ b/dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2015 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 "hkdf.h"
-
-#include <gtest/gtest.h>
-#include <string.h>
-
-#include "android_keymaster_test_utils.h"
-
-using std::string;
-
-namespace keymaster {
-namespace test {
-
-struct HkdfTest {
- const char* key_hex;
- const char* salt_hex;
- const char* info_hex;
- const char* output_hex;
-};
-
-// These test cases are taken from
-// https://tools.ietf.org/html/rfc5869#appendix-A.
-static const HkdfTest kHkdfTests[] = {
- {
- "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "000102030405060708090a0b0c",
- "f0f1f2f3f4f5f6f7f8f9",
- "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865",
- },
- {
- "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c"
- "2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f",
- "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c"
- "8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf",
- "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdc"
- "dddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
- "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e"
- "590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87",
- },
- {
- "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "", "",
- "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8",
- },
-};
-
-TEST(HkdfTest, Hkdf) {
- for (auto& test : kHkdfTests) {
- const string key = hex2str(test.key_hex);
- const string salt = hex2str(test.salt_hex);
- const string info = hex2str(test.info_hex);
- const string expected = hex2str(test.output_hex);
- size_t output_len = expected.size();
- uint8_t output[output_len];
- Rfc5869Sha256Kdf hkdf;
- ASSERT_TRUE(hkdf.Init(reinterpret_cast<const uint8_t*>(key.data()), key.size(),
- reinterpret_cast<const uint8_t*>(salt.data()), salt.size()));
- ASSERT_TRUE(hkdf.GenerateKey(reinterpret_cast<const uint8_t*>(info.data()), info.size(),
- output, output_len));
- EXPECT_EQ(0, memcmp(output, expected.data(), output_len));
- }
-}
-
-} // namespace test
-} // namespace keymaster
diff --git a/unit_test/hmac_test.cpp b/unit_test/hmac_test.cpp
deleted file mode 100644
index 04f9356..0000000
--- a/unit_test/hmac_test.cpp
+++ b/dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2015 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 "hmac.h"
-
-#include <gtest/gtest.h>
-#include <string.h>
-
-#include "android_keymaster_test_utils.h"
-
-using std::string;
-
-namespace keymaster {
-
-namespace test {
-
-struct HmacTest {
- const char* data;
- const char* key;
- uint8_t digest[32];
-};
-
-static const HmacTest kHmacTests[] = {
- {
- "Test Using Larger Than Block-Size Key - Hash Key First",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- {
- 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5,
- 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f,
- 0x0e, 0xe3, 0x7f, 0x54,
- },
- },
- {
- "The test message for the MD2, MD5, and SHA-1 hashing algorithms.",
- "46697265666f7820616e64205468756e64657242697264206172652061776573"
- "6f6d652100",
- {
- 0x05, 0x75, 0x9a, 0x9e, 0x70, 0x5e, 0xe7, 0x44, 0xe2, 0x46, 0x4b, 0x92, 0x22, 0x14,
- 0x22, 0xe0, 0x1b, 0x92, 0x8a, 0x0c, 0xfe, 0xf5, 0x49, 0xe9, 0xa7, 0x1b, 0x56, 0x7d,
- 0x1d, 0x29, 0x40, 0x48,
- },
- },
-};
-
-TEST(HmacTest, SHA256) {
- for (size_t i = 0; i < 2; i++) {
- const HmacTest& test(kHmacTests[i]);
-
- HmacSha256 hmac;
- const string key = hex2str(test.key);
- Buffer key_buffer(key.data(), key.size());
- ASSERT_TRUE(hmac.Init(key_buffer));
-
- uint8_t digest_copy[sizeof(test.digest)];
- memcpy(digest_copy, test.digest, sizeof(test.digest));
- Buffer digest_buffer(reinterpret_cast<uint8_t*>(digest_copy), sizeof(digest_copy));
-
- Buffer data_buffer(test.data, strlen(test.data));
- EXPECT_TRUE(hmac.Verify(data_buffer, digest_buffer));
-
- digest_copy[16] ^= 0x80;
- digest_buffer.Reinitialize(reinterpret_cast<uint8_t*>(digest_copy), sizeof(digest_copy));
- EXPECT_FALSE(hmac.Verify(data_buffer, digest_buffer));
- }
-}
-
-} // namespace test
-} // namespace keymaster
diff --git a/unit_test/kdf1_test.cpp b/unit_test/kdf1_test.cpp
deleted file mode 100644
index 9c8b0d5..0000000
--- a/unit_test/kdf1_test.cpp
+++ b/dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2015 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 "kdf1.h"
-#include <gtest/gtest.h>
-#include <string.h>
-
-#include "android_keymaster_test_utils.h"
-
-using std::string;
-
-namespace keymaster {
-
-namespace test {
-
-struct Kdf1Test {
- const char* key_hex;
- const char* expected_output_hex;
- keymaster_digest_t digest_type;
-};
-
-static const Kdf1Test kKdf1Tests[] = {
- {"032e45326fa859a72ec235acff929b15d1372e30b207255f0611b8f785d764374152e0ac009e509e7ba30cd2f1778"
- "e113b64e135cf4e2292c75efe5288edfda4",
- "5f8de105b5e96b2e490ddecbd147dd1def7e3b8e0e6a26eb7b956ccb8b3bdc1ca975bc57c3989e8fbad31a224655d"
- "800c46954840ff32052cdf0d640562bdfadfa263cfccf3c52b29f2af4a1869959bc77f854cf15bd7a25192985a842"
- "dbff8e13efee5b7e7e55bbe4d389647c686a9a9ab3fb889b2d7767d3837eea4e0a2f04",
- KM_DIGEST_SHA1}};
-
-TEST(Kdf1Test, Kdf1) {
- for (auto& test : kKdf1Tests) {
- const string key = hex2str(test.key_hex);
- const string expected_output = hex2str(test.expected_output_hex);
- size_t output_len = expected_output.size();
- uint8_t output[output_len];
-
- Kdf1 kdf1;
- ASSERT_TRUE(
- kdf1.Init(test.digest_type, reinterpret_cast<const uint8_t*>(key.data()), key.size()));
- ASSERT_TRUE(kdf1.GenerateKey(nullptr, 0, output, output_len));
- EXPECT_EQ(0, memcmp(output, expected_output.data(), output_len));
- }
-}
-
-} // namespace test
-
-} // namespace keymaster
diff --git a/unit_test/kdf2_test.cpp b/unit_test/kdf2_test.cpp
deleted file mode 100644
index 29ff40a..0000000
--- a/unit_test/kdf2_test.cpp
+++ b/dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2015 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 "kdf2.h"
-#include <gtest/gtest.h>
-#include <string.h>
-
-#include "android_keymaster_test_utils.h"
-
-using std::string;
-
-namespace keymaster {
-
-namespace test {
-
-struct Kdf2Test {
- const char* key_hex;
- const char* info_hex;
- const char* expected_output_hex;
- keymaster_digest_t digest_type;
-};
-
-static const Kdf2Test kKdf2Tests[] = {
- {"032e45326fa859a72ec235acff929b15d1372e30b207255f0611b8f785d764374152e0ac009e509e7ba30cd2f1778"
- "e113b64e135cf4e2292c75efe5288edfda4",
- "",
- "10a2403db42a8743cb989de86e668d168cbe6046e23ff26f741e87949a3bba1311ac179f819a3d18412e9eb45668f"
- "2923c087c1299005f8d5fd42ca257bc93e8fee0c5a0d2a8aa70185401fbbd99379ec76c663e9a29d0b70f3fe261a5"
- "9cdc24875a60b4aacb1319fa11c3365a8b79a44669f26fba933d012db213d7e3b16349",
- KM_DIGEST_SHA_2_256},
- {"032e45326fa859a72ec235acff929b15d1372e30b207255f0611b8f785d764374152e0ac009e509e7ba30cd2f1778"
- "e113b64e135cf4e2292c75efe5288edfda4",
- "",
- "0e6a26eb7b956ccb8b3bdc1ca975bc57c3989e8fbad31a224655d800c46954840ff32052cdf0d640562bdfadfa263"
- "cfccf3c52b29f2af4a1869959bc77f854cf15bd7a25192985a842dbff8e13efee5b7e7e55bbe4d389647c686a9a9a"
- "b3fb889b2d7767d3837eea4e0a2f04b53ca8f50fb31225c1be2d0126c8c7a4753b0807",
- KM_DIGEST_SHA1},
- {"CA7C0F8C3FFA87A96E1B74AC8E6AF594347BB40A", "", "744AB703F5BC082E59185F6D049D2D367DB245C2",
- KM_DIGEST_SHA1},
- {"0499B502FC8B5BAFB0F4047E731D1F9FD8CD0D8881", "",
- "03C62280C894E103C680B13CD4B4AE740A5EF0C72547292F82DC6B1777F47D63BA9D1EA73"
- "2DBF386",
- KM_DIGEST_SHA1},
- {"5E10B967A95606853E528F04262AD18A4767C761163971391E17CB05A21668D4CE2B9F151617408042CE091958382"
- "3FD346D1751FBE2341AF2EE0461B62F100FFAD4F723F70C18B38238ED183E9398C8CA517EE0CBBEFFF9C59471FE27"
- "8093924089480DBC5A38E9A1A97D23038106847D0D22ECF85F49A861821199BAFCB0D74E6ACFFD7D142765EBF4C71"
- "2414FE4B6AB957F4CB466B46601289BB82060428272842EE28F113CD11F39431CBFFD823254CE472E2105E49B3D7F"
- "113B825076E6264585807BC46454665F27C5E4E1A4BD03470486322981FDC894CCA1E2930987C92C15A38BC42EB38"
- "810E867C4432F07259EC00CDBBB0FB99E1727C706DA58DD",
- "484D4143204B6579", "BC98EB018CB00EE26D1F97A15AE166912A7AC4C5", KM_DIGEST_SHA1},
-
-};
-
-TEST(Kdf2Test, Kdf2) {
- for (auto& test : kKdf2Tests) {
- const string key = hex2str(test.key_hex);
- const string info = hex2str(test.info_hex);
- const string expected_output = hex2str(test.expected_output_hex);
- size_t output_len = expected_output.size();
- uint8_t output[output_len];
-
- Kdf2 kdf2;
- ASSERT_TRUE(
- kdf2.Init(test.digest_type, reinterpret_cast<const uint8_t*>(key.data()), key.size()));
- ASSERT_TRUE(kdf2.GenerateKey(reinterpret_cast<const uint8_t*>(info.data()), info.size(),
- output, output_len));
- EXPECT_EQ(0, memcmp(output, expected_output.data(), output_len));
- }
-}
-
-} // namespace test
-
-} // namespace keymaster
diff --git a/unit_test/kdf_test.cpp b/unit_test/kdf_test.cpp
deleted file mode 100644
index f6f4a93..0000000
--- a/unit_test/kdf_test.cpp
+++ b/dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2015 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 "kdf.h"
-#include <gtest/gtest.h>
-
-namespace keymaster {
-
-namespace test {
-
-class ForTestAbstractKdf : public Kdf {
- bool GenerateKey(const uint8_t* /* info */, size_t /* info_len */, uint8_t* /* output */,
- size_t /* output_len */) {
- return true;
- }
-};
-
-TEST(KdfTest, Kdf) {
- ForTestAbstractKdf kdf;
- uint8_t key[128];
- uint8_t salt[128];
- ASSERT_TRUE(kdf.Init(KM_DIGEST_SHA1, key, 128, salt, 128));
- ASSERT_TRUE(kdf.Init(KM_DIGEST_SHA_2_256, key, 128, salt, 128));
- ASSERT_TRUE(kdf.Init(KM_DIGEST_SHA1, key, 128, nullptr, 0));
- ASSERT_FALSE(kdf.Init(KM_DIGEST_MD5, key, 128, salt, 128));
- ASSERT_FALSE(kdf.Init(KM_DIGEST_SHA1, nullptr, 0, salt, 128));
- ASSERT_FALSE(kdf.Init(KM_DIGEST_SHA1, nullptr, 128, salt, 128));
- ASSERT_FALSE(kdf.Init(KM_DIGEST_SHA1, key, 0, salt, 128));
-}
-
-} // namespace test
-
-} // namespace keymaster
diff --git a/unit_test/key_blob_test.cpp b/unit_test/key_blob_test.cpp
deleted file mode 100644
index 1e590f0..0000000
--- a/unit_test/key_blob_test.cpp
+++ b/dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#include <algorithm>
-
-#include <gtest/gtest.h>
-
-#include <openssl/engine.h>
-#include <openssl/rand.h>
-
-#include <keymaster/authorization_set.h>
-#include <keymaster/android_keymaster_utils.h>
-#include <keymaster/keymaster_tags.h>
-
-#include "android_keymaster_test_utils.h"
-#include "auth_encrypted_key_blob.h"
-#include "integrity_assured_key_blob.h"
-#include "ocb_utils.h"
-
-namespace keymaster {
-
-namespace test {
-
-const uint8_t master_key_data[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-const uint8_t key_data[5] = {21, 22, 23, 24, 25};
-
-class KeyBlobTest : public testing::Test {
- protected:
- KeyBlobTest()
- : master_key_(master_key_data, array_length(master_key_data)),
- key_material_(key_data, array_length(key_data)) {
- hw_enforced_.push_back(TAG_ALGORITHM, KM_ALGORITHM_RSA);
- hw_enforced_.push_back(TAG_KEY_SIZE, 256);
- hw_enforced_.push_back(TAG_BLOB_USAGE_REQUIREMENTS, KM_BLOB_STANDALONE);
- hw_enforced_.push_back(TAG_MIN_SECONDS_BETWEEN_OPS, 10);
- hw_enforced_.push_back(TAG_ALL_USERS);
- hw_enforced_.push_back(TAG_NO_AUTH_REQUIRED);
- hw_enforced_.push_back(TAG_ORIGIN, KM_ORIGIN_GENERATED);
-
- sw_enforced_.push_back(TAG_ACTIVE_DATETIME, 10);
- sw_enforced_.push_back(TAG_ORIGINATION_EXPIRE_DATETIME, 100);
- sw_enforced_.push_back(TAG_CREATION_DATETIME, 10);
-
- hidden_.push_back(TAG_ROOT_OF_TRUST, "foo", 3);
- hidden_.push_back(TAG_APPLICATION_ID, "my_app", 6);
-
- nonce_.reserve(OCB_NONCE_LENGTH);
- EXPECT_EQ(1, RAND_bytes(nonce_.peek_write(), OCB_NONCE_LENGTH));
- nonce_.advance_write(OCB_NONCE_LENGTH);
-
- tag_.reserve(OCB_TAG_LENGTH);
- }
-
- keymaster_error_t Encrypt() {
- return OcbEncryptKey(hw_enforced_, sw_enforced_, hidden_, master_key_, key_material_,
- nonce_, &ciphertext_, &tag_);
- }
-
- keymaster_error_t Decrypt() {
- return OcbDecryptKey(hw_enforced_, sw_enforced_, hidden_, master_key_, ciphertext_, nonce_,
- tag_, &decrypted_plaintext_);
- }
-
- keymaster_error_t Serialize() {
- return SerializeAuthEncryptedBlob(ciphertext_, hw_enforced_, sw_enforced_, nonce_, tag_,
- &serialized_blob_);
- }
-
- keymaster_error_t Deserialize() {
- return DeserializeAuthEncryptedBlob(serialized_blob_, &ciphertext_, &hw_enforced_,
- &sw_enforced_, &nonce_, &tag_);
- }
-
- AuthorizationSet hw_enforced_;
- AuthorizationSet sw_enforced_;
- AuthorizationSet hidden_;
- Buffer nonce_, tag_;
-
- KeymasterKeyBlob master_key_;
- KeymasterKeyBlob key_material_;
- KeymasterKeyBlob ciphertext_;
- KeymasterKeyBlob decrypted_plaintext_;
- KeymasterKeyBlob serialized_blob_;
-};
-
-TEST_F(KeyBlobTest, EncryptDecrypt) {
- ASSERT_EQ(KM_ERROR_OK, Encrypt());
- ASSERT_EQ(KM_ERROR_OK, Serialize());
-
- // key_data shouldn't be anywhere in the blob, ciphertext should.
- EXPECT_EQ(serialized_blob_.end(), std::search(serialized_blob_.begin(), serialized_blob_.end(),
- key_material_.begin(), key_material_.end()));
- EXPECT_NE(serialized_blob_.end(), std::search(serialized_blob_.begin(), serialized_blob_.end(),
- ciphertext_.begin(), ciphertext_.end()));
-
- ciphertext_.Clear();
- nonce_.Clear();
- tag_.Clear();
- AuthorizationSet hw2;
- AuthorizationSet sw2;
-
- ASSERT_EQ(KM_ERROR_OK, DeserializeAuthEncryptedBlob(serialized_blob_, &ciphertext_, &hw2, &sw2,
- &nonce_, &tag_));
- KeymasterKeyBlob plaintext;
- OcbDecryptKey(hw2, sw2, hidden_, master_key_, ciphertext_, nonce_, tag_, &plaintext);
-
- EXPECT_EQ(hw_enforced_, hw2);
- EXPECT_EQ(sw_enforced_, sw2);
-
- ASSERT_EQ(key_material_.key_material_size, plaintext.key_material_size);
- EXPECT_EQ(0, memcmp(plaintext.begin(), key_material_.begin(), plaintext.key_material_size));
-}
-
-TEST_F(KeyBlobTest, WrongKeyLength) {
- ASSERT_EQ(KM_ERROR_OK, Encrypt());
- ASSERT_EQ(KM_ERROR_OK, Serialize());
-
- // Modify the key length, shouldn't be able to parse.
- serialized_blob_.writable_data()[1 /* version */ + 4 /* nonce len */ + 12 /* nonce */ + 3]++;
-
- ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, Deserialize());
-}
-
-TEST_F(KeyBlobTest, WrongNonce) {
- ASSERT_EQ(KM_ERROR_OK, Encrypt());
- ASSERT_EQ(KM_ERROR_OK, Serialize());
-
- // Find the nonce, then modify it.
- auto nonce_ptr =
- std::search(serialized_blob_.begin(), serialized_blob_.end(), nonce_.begin(), nonce_.end());
- ASSERT_NE(nonce_ptr, serialized_blob_.end());
- EXPECT_EQ(serialized_blob_.end(),
- std::search(nonce_ptr + 1, serialized_blob_.end(), nonce_.begin(), nonce_.end()));
- (*const_cast<uint8_t*>(nonce_ptr))++;
-
- // Deserialization shouldn't be affected, but decryption should fail.
- ASSERT_EQ(KM_ERROR_OK, Deserialize());
- ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, Decrypt());
-}
-
-TEST_F(KeyBlobTest, WrongTag) {
- ASSERT_EQ(KM_ERROR_OK, Encrypt());
- ASSERT_EQ(KM_ERROR_OK, Serialize());
-
- // Find the tag, them modify it.
- auto tag_ptr =
- std::search(serialized_blob_.begin(), serialized_blob_.end(), tag_.begin(), tag_.end());
- ASSERT_NE(tag_ptr, serialized_blob_.end());
- EXPECT_EQ(serialized_blob_.end(),
- std::search(tag_ptr + 1, serialized_blob_.end(), tag_.begin(), tag_.end()));
- (*const_cast<uint8_t*>(tag_ptr))++;
-
- // Deserialization shouldn't be affected, but decryption should fail.
- ASSERT_EQ(KM_ERROR_OK, Deserialize());
- ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, Decrypt());
-}
-
-TEST_F(KeyBlobTest, WrongCiphertext) {
- ASSERT_EQ(KM_ERROR_OK, Encrypt());
- ASSERT_EQ(KM_ERROR_OK, Serialize());
-
- // Find the ciphertext, them modify it.
- auto ciphertext_ptr = std::search(serialized_blob_.begin(), serialized_blob_.end(),
- ciphertext_.begin(), ciphertext_.end());
- ASSERT_NE(ciphertext_ptr, serialized_blob_.end());
- EXPECT_EQ(serialized_blob_.end(), std::search(ciphertext_ptr + 1, serialized_blob_.end(),
- ciphertext_.begin(), ciphertext_.end()));
- (*const_cast<uint8_t*>(ciphertext_ptr))++;
-
- // Deserialization shouldn't be affected, but decryption should fail.
- ASSERT_EQ(KM_ERROR_OK, Deserialize());
- ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, Decrypt());
-}
-
-TEST_F(KeyBlobTest, WrongMasterKey) {
- ASSERT_EQ(KM_ERROR_OK, Encrypt());
- ASSERT_EQ(KM_ERROR_OK, Serialize());
-
- uint8_t wrong_master_data[] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- KeymasterKeyBlob wrong_master(wrong_master_data, array_length(wrong_master_data));
-
- // Decrypting with wrong master key should fail.
- ASSERT_EQ(KM_ERROR_OK, Deserialize());
- ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB,
- OcbDecryptKey(hw_enforced_, sw_enforced_, hidden_, wrong_master, ciphertext_, nonce_,
- tag_, &decrypted_plaintext_));
-}
-
-TEST_F(KeyBlobTest, WrongHwEnforced) {
- ASSERT_EQ(KM_ERROR_OK, Encrypt());
- ASSERT_EQ(KM_ERROR_OK, Serialize());
-
- // Find enforced serialization data and modify it.
- size_t hw_enforced_size = hw_enforced_.SerializedSize();
- UniquePtr<uint8_t[]> hw_enforced_data(new uint8_t[hw_enforced_size]);
- hw_enforced_.Serialize(hw_enforced_data.get(), hw_enforced_data.get() + hw_enforced_size);
-
- auto hw_enforced_ptr =
- std::search(serialized_blob_.begin(), serialized_blob_.end(), hw_enforced_data.get(),
- hw_enforced_data.get() + hw_enforced_size);
- ASSERT_NE(serialized_blob_.end(), hw_enforced_ptr);
- EXPECT_EQ(serialized_blob_.end(),
- std::search(hw_enforced_ptr + 1, serialized_blob_.end(), hw_enforced_data.get(),
- hw_enforced_data.get() + hw_enforced_size));
- (*(const_cast<uint8_t*>(hw_enforced_ptr) + hw_enforced_size - 1))++;
-
- // Deserialization shouldn't be affected, but decryption should fail.
- ASSERT_EQ(KM_ERROR_OK, Deserialize());
- ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, Decrypt());
-}
-
-TEST_F(KeyBlobTest, WrongSwEnforced) {
- ASSERT_EQ(KM_ERROR_OK, Encrypt());
- ASSERT_EQ(KM_ERROR_OK, Serialize());
-
- // Find enforced serialization data and modify it.
- size_t sw_enforced_size = sw_enforced_.SerializedSize();
- UniquePtr<uint8_t[]> sw_enforced_data(new uint8_t[sw_enforced_size]);
- sw_enforced_.Serialize(sw_enforced_data.get(), sw_enforced_data.get() + sw_enforced_size);
-
- auto sw_enforced_ptr =
- std::search(serialized_blob_.begin(), serialized_blob_.end(), sw_enforced_data.get(),
- sw_enforced_data.get() + sw_enforced_size);
- ASSERT_NE(serialized_blob_.end(), sw_enforced_ptr);
- EXPECT_EQ(serialized_blob_.end(),
- std::search(sw_enforced_ptr + 1, serialized_blob_.end(), sw_enforced_data.get(),
- sw_enforced_data.get() + sw_enforced_size));
- (*(const_cast<uint8_t*>(sw_enforced_ptr) + sw_enforced_size - 1))++;
-
- // Deserialization shouldn't be affected, but decryption should fail.
- ASSERT_EQ(KM_ERROR_OK, Deserialize());
- ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, Decrypt());
-}
-
-TEST_F(KeyBlobTest, EmptyHidden) {
- ASSERT_EQ(KM_ERROR_OK, Encrypt());
- ASSERT_EQ(KM_ERROR_OK, Serialize());
-
- AuthorizationSet wrong_hidden;
-
- // Deserialization shouldn't be affected, but decryption should fail.
- ASSERT_EQ(KM_ERROR_OK, Deserialize());
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB,
- OcbDecryptKey(hw_enforced_, sw_enforced_, wrong_hidden, master_key_, ciphertext_,
- nonce_, tag_, &decrypted_plaintext_));
-}
-
-TEST_F(KeyBlobTest, WrongRootOfTrust) {
- ASSERT_EQ(KM_ERROR_OK, Encrypt());
- ASSERT_EQ(KM_ERROR_OK, Serialize());
-
- AuthorizationSet wrong_hidden;
- wrong_hidden.push_back(TAG_ROOT_OF_TRUST, "bar", 2);
- wrong_hidden.push_back(TAG_APPLICATION_ID, "my_app", 6);
-
- // Deserialization shouldn't be affected, but decryption should fail.
- ASSERT_EQ(KM_ERROR_OK, Deserialize());
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB,
- OcbDecryptKey(hw_enforced_, sw_enforced_, wrong_hidden, master_key_, ciphertext_,
- nonce_, tag_, &decrypted_plaintext_));
-}
-
-TEST_F(KeyBlobTest, WrongAppId) {
- ASSERT_EQ(KM_ERROR_OK, Encrypt());
- ASSERT_EQ(KM_ERROR_OK, Serialize());
-
- AuthorizationSet wrong_hidden;
- wrong_hidden.push_back(TAG_ROOT_OF_TRUST, "foo", 3);
- wrong_hidden.push_back(TAG_APPLICATION_ID, "your_app", 7);
-
- // Deserialization shouldn't be affected, but decryption should fail.
- ASSERT_EQ(KM_ERROR_OK, Deserialize());
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB,
- OcbDecryptKey(hw_enforced_, sw_enforced_, wrong_hidden, master_key_, ciphertext_,
- nonce_, tag_, &decrypted_plaintext_));
-}
-
-// This test is especially useful when compiled for 32-bit mode and run under valgrind.
-TEST_F(KeyBlobTest, FuzzTest) {
- time_t now = time(NULL);
- std::cout << "Seeding rand() with " << now << " for fuzz test." << std::endl;
- srand(now);
-
- // Fill large buffer with random bytes.
- const int kBufSize = 10000;
- UniquePtr<uint8_t[]> buf(new uint8_t[kBufSize]);
- for (size_t i = 0; i < kBufSize; ++i)
- buf[i] = static_cast<uint8_t>(rand());
-
- // Try to deserialize every offset with multiple methods.
- size_t deserialize_auth_encrypted_success = 0;
- for (size_t i = 0; i < kBufSize; ++i) {
- keymaster_key_blob_t blob = {buf.get() + i, kBufSize - i};
- KeymasterKeyBlob key_blob(blob);
-
- // Integrity-assured blob.
- ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB,
- DeserializeIntegrityAssuredBlob(key_blob, hidden_, &key_material_, &hw_enforced_,
- &sw_enforced_));
-
- // Auth-encrypted OCB blob.
- keymaster_error_t error = DeserializeAuthEncryptedBlob(
- key_blob, &ciphertext_, &hw_enforced_, &sw_enforced_, &nonce_, &tag_);
- if (error == KM_ERROR_OK) {
- // It's possible to deserialize successfully. Decryption should always fail.
- ++deserialize_auth_encrypted_success;
- error = OcbDecryptKey(hw_enforced_, sw_enforced_, hidden_, master_key_, ciphertext_,
- nonce_, tag_, &decrypted_plaintext_);
- }
- ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, error)
- << "Somehow sucessfully parsed a blob with seed " << now << " at offset " << i;
- }
-}
-
-TEST_F(KeyBlobTest, UnderflowTest) {
- uint8_t buf[0];
- keymaster_key_blob_t blob = {buf, 0};
- KeymasterKeyBlob key_blob(blob);
- EXPECT_NE(nullptr, key_blob.key_material);
- EXPECT_EQ(0U, key_blob.key_material_size);
-
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB,
- DeserializeIntegrityAssuredBlob(key_blob, hidden_, &key_material_, &hw_enforced_,
- &sw_enforced_));
-
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB,
- DeserializeAuthEncryptedBlob(key_blob, &ciphertext_, &hw_enforced_, &sw_enforced_,
- &nonce_, &tag_));
-}
-
-TEST_F(KeyBlobTest, DupBufferToolarge) {
- uint8_t buf[0];
- keymaster_key_blob_t blob = {buf, 0};
- blob.key_material_size = 16 * 1024 * 1024 + 1;
- KeymasterKeyBlob key_blob(blob);
- EXPECT_EQ(nullptr, key_blob.key_material);
- EXPECT_EQ(0U, key_blob.key_material_size);
-
- ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB,
- DeserializeIntegrityAssuredBlob(key_blob, hidden_, &key_material_, &hw_enforced_,
- &sw_enforced_));
-
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB,
- DeserializeAuthEncryptedBlob(key_blob, &ciphertext_, &hw_enforced_, &sw_enforced_,
- &nonce_, &tag_));
-}
-
-} // namespace test
-} // namespace keymaster
diff --git a/unit_test/keymaster0_engine.h b/unit_test/keymaster0_engine.h
deleted file mode 100644
index aedd85c..0000000
--- a/unit_test/keymaster0_engine.h
+++ b/dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2015 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_KEYMASTER_KEYMASTER0_ENGINE_H_
-#define SYSTEM_KEYMASTER_KEYMASTER0_ENGINE_H_
-
-#include <memory>
-
-#include <openssl/ec.h>
-#include <openssl/engine.h>
-#include <openssl/ex_data.h>
-#include <openssl/rsa.h>
-
-#include <hardware/keymaster0.h>
-#include <hardware/keymaster_defs.h>
-
-namespace keymaster {
-
-struct KeymasterKeyBlob;
-
-/* Keymaster0Engine is a BoringSSL ENGINE that implements RSA & EC by forwarding the requested
- * operations to a keymaster0 module. */
-class Keymaster0Engine {
- public:
- /**
- * Create a Keymaster0Engine, wrapping the provided keymaster0_device. The engine takes
- * ownership of the device, and will close it during destruction.
- */
- explicit Keymaster0Engine(const keymaster0_device_t* keymaster0_device);
- ~Keymaster0Engine();
-
- bool supports_ec() const { return supports_ec_; }
-
- bool GenerateRsaKey(uint64_t public_exponent, uint32_t public_modulus,
- KeymasterKeyBlob* key_material) const;
- bool GenerateEcKey(uint32_t key_size, KeymasterKeyBlob* key_material) const;
-
- bool ImportKey(keymaster_key_format_t key_format, const KeymasterKeyBlob& to_import,
- KeymasterKeyBlob* imported_key_material) const;
- bool DeleteKey(const KeymasterKeyBlob& blob) const;
- bool DeleteAllKeys() const;
-
- RSA* BlobToRsaKey(const KeymasterKeyBlob& blob) const;
- EC_KEY* BlobToEcKey(const KeymasterKeyBlob& blob) const;
-
- const keymaster_key_blob_t* RsaKeyToBlob(const RSA* rsa) const;
- const keymaster_key_blob_t* EcKeyToBlob(const EC_KEY* rsa) const;
-
- const keymaster0_device_t* device() { return keymaster0_device_; }
-
- EVP_PKEY* GetKeymaster0PublicKey(const KeymasterKeyBlob& blob) const;
-
- private:
- Keymaster0Engine(const Keymaster0Engine&); // Uncopyable
- void operator=(const Keymaster0Engine&); // Unassignable
-
- static int keyblob_dup(CRYPTO_EX_DATA* to, const CRYPTO_EX_DATA* from, void** from_d, int index,
- long argl, void* argp);
- static void keyblob_free(void* parent, void* ptr, CRYPTO_EX_DATA* data, int index, long argl,
- void* argp);
- static int rsa_private_transform(RSA* rsa, uint8_t* out, const uint8_t* in, size_t len);
- static int ecdsa_sign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
- unsigned int* sig_len, EC_KEY* ec_key);
-
- struct Malloc_Delete {
- void operator()(void* p) { free(p); }
- };
-
- bool Keymaster0Sign(const void* signing_params, const keymaster_key_blob_t& key_blob,
- const uint8_t* data, const size_t data_length,
- std::unique_ptr<uint8_t[], Malloc_Delete>* signature,
- size_t* signature_length) const;
-
- int RsaPrivateTransform(RSA* rsa, uint8_t* out, const uint8_t* in, size_t len) const;
- int EcdsaSign(const uint8_t* digest, size_t digest_len, uint8_t* sig, unsigned int* sig_len,
- EC_KEY* ec_key) const;
-
- const keymaster0_device_t* keymaster0_device_;
- ENGINE* const engine_;
- int rsa_index_, ec_key_index_;
- bool supports_ec_;
- RSA_METHOD rsa_method_;
- ECDSA_METHOD ecdsa_method_;
-
- static Keymaster0Engine* instance_;
-};
-
-} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_KEYMASTER0_ENGINE_H_
diff --git a/unit_test/keymaster1_engine.h b/unit_test/keymaster1_engine.h
deleted file mode 100644
index 9e2f13e..0000000
--- a/unit_test/keymaster1_engine.h
+++ b/dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2015 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_KEYMASTER_KEYMASTER1_ENGINE_H_
-#define SYSTEM_KEYMASTER_KEYMASTER1_ENGINE_H_
-
-#include <memory>
-
-#include <openssl/ec.h>
-#include <openssl/engine.h>
-#include <openssl/ex_data.h>
-#include <openssl/rsa.h>
-
-#include <hardware/keymaster1.h>
-#include <hardware/keymaster_defs.h>
-
-#include <keymaster/android_keymaster_utils.h>
-#include <keymaster/authorization_set.h>
-
-#include "openssl_utils.h"
-
-namespace keymaster {
-
-class Keymaster1Engine {
- public:
- /**
- * Create a Keymaster1Engine, wrapping the provided keymaster1_device. The engine takes
- * ownership of the device, and will close it during destruction.
- */
- explicit Keymaster1Engine(const keymaster1_device_t* keymaster1_device);
- ~Keymaster1Engine();
-
- keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
- KeymasterKeyBlob* key_material, AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const;
-
- keymaster_error_t ImportKey(const AuthorizationSet& key_description,
- keymaster_key_format_t input_key_material_format,
- const KeymasterKeyBlob& input_key_material,
- KeymasterKeyBlob* output_key_blob, AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const;
- keymaster_error_t DeleteKey(const KeymasterKeyBlob& blob) const;
- keymaster_error_t DeleteAllKeys() const;
-
- struct KeyData {
- KeyData(const KeymasterKeyBlob& blob, const AuthorizationSet& params)
- : op_handle(0), begin_params(params), key_material(blob), error(KM_ERROR_OK),
- expected_openssl_padding(-1) {}
-
- keymaster_operation_handle_t op_handle;
- AuthorizationSet begin_params;
- AuthorizationSet finish_params;
- KeymasterKeyBlob key_material;
- keymaster_error_t error;
- int expected_openssl_padding;
- };
-
- RSA* BuildRsaKey(const KeymasterKeyBlob& blob, const AuthorizationSet& additional_params,
- keymaster_error_t* error) const;
- EC_KEY* BuildEcKey(const KeymasterKeyBlob& blob, const AuthorizationSet& additional_params,
- keymaster_error_t* error) const;
-
- KeyData* GetData(EVP_PKEY* key) const;
- KeyData* GetData(const RSA* rsa) const;
- KeyData* GetData(const EC_KEY* rsa) const;
-
- const keymaster1_device_t* device() const { return keymaster1_device_; }
-
- EVP_PKEY* GetKeymaster1PublicKey(const KeymasterKeyBlob& blob,
- const AuthorizationSet& additional_params,
- keymaster_error_t* error) const;
-
- private:
- Keymaster1Engine(const Keymaster1Engine&); // Uncopyable
- void operator=(const Keymaster1Engine&); // Unassignable
-
- RSA_METHOD BuildRsaMethod();
- ECDSA_METHOD BuildEcdsaMethod();
- void ConfigureEngineForRsa();
- void ConfigureEngineForEcdsa();
-
- keymaster_error_t Keymaster1Finish(const KeyData* key_data, const keymaster_blob_t& input,
- keymaster_blob_t* output);
-
- static int duplicate_key_data(CRYPTO_EX_DATA* to, const CRYPTO_EX_DATA* from, void** from_d,
- int index, long argl, void* argp);
- static void free_key_data(void* parent, void* ptr, CRYPTO_EX_DATA* data, int index, long argl,
- void* argp);
-
- static int rsa_sign_raw(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out,
- const uint8_t* in, size_t in_len, int padding);
- static int rsa_decrypt(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out,
- const uint8_t* in, size_t in_len, int padding);
- static int ecdsa_sign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
- unsigned int* sig_len, EC_KEY* ec_key);
-
- const keymaster1_device_t* const keymaster1_device_;
- const std::unique_ptr<ENGINE, ENGINE_Delete> engine_;
- const int rsa_index_;
- const int ec_key_index_;
-
- const RSA_METHOD rsa_method_;
- const ECDSA_METHOD ecdsa_method_;
-
- static Keymaster1Engine* instance_;
-};
-
-} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_KEYMASTER1_ENGINE_H_
diff --git a/unit_test/keymaster_configuration_test.cpp b/unit_test/keymaster_configuration_test.cpp
deleted file mode 100644
index 81e9598..0000000
--- a/unit_test/keymaster_configuration_test.cpp
+++ b/dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <gtest/gtest.h>
-
-#include <keymaster/keymaster_configuration.h>
-
-#ifdef HOST_BUILD
-extern "C" {
-int __android_log_print(int prio, const char* tag, const char* fmt);
-int __android_log_print(int prio, const char* tag, const char* fmt) {
- (void)prio, (void)tag, (void)fmt;
- std::cout << fmt << std::endl;
- return 0;
-}
-} // extern "C"
-#endif // HOST_BUILD
-
-namespace keymaster {
-namespace test {
-
-TEST(VersionParsingTest, Full) {
- EXPECT_EQ(612334U, GetOsVersion("61.23.34"));
- EXPECT_EQ(680000U, GetOsVersion("681.23.24"));
- EXPECT_EQ(682300U, GetOsVersion("68.231.24"));
- EXPECT_EQ(682324U, GetOsVersion("68.23.241"));
- EXPECT_EQ(60102U, GetOsVersion("6.1.2-extrajunk"));
- EXPECT_EQ(0U, GetOsVersion("extra6.1.2"));
-}
-
-TEST(VersionParsingTest, FullWithExtraChars) {}
-
-TEST(VersionParsingTest, MajorOnly) {
- EXPECT_EQ(60000U, GetOsVersion("6"));
- EXPECT_EQ(680000U, GetOsVersion("68"));
- EXPECT_EQ(680000U, GetOsVersion("681"));
- EXPECT_EQ(60000U, GetOsVersion("6.junk"));
-}
-
-TEST(VersionParsingTest, MajorMinorOnly) {
- EXPECT_EQ(60100U, GetOsVersion("6.1"));
- EXPECT_EQ(60100U, GetOsVersion("6.1junk"));
-}
-
-TEST(PatchLevelParsingTest, Full) {
- EXPECT_EQ(201603U, GetOsPatchlevel("2016-03-23"));
- EXPECT_EQ(0U, GetOsPatchlevel("2016-13-23"));
- EXPECT_EQ(0U, GetOsPatchlevel("2016-03"));
- EXPECT_EQ(0U, GetOsPatchlevel("2016-3-23"));
- EXPECT_EQ(0U, GetOsPatchlevel("2016-03-23r"));
- EXPECT_EQ(0U, GetOsPatchlevel("r2016-03-23"));
-}
-
-} // namespace test
-} // namespace keymaster
diff --git a/unit_test/keymaster_enforcement_test.cpp b/unit_test/keymaster_enforcement_test.cpp
deleted file mode 100644
index 3874744..0000000
--- a/unit_test/keymaster_enforcement_test.cpp
+++ b/dev/null
@@ -1,872 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#include <errno.h>
-#include <stdio.h>
-#include <time.h>
-
-#include <keymaster/android_keymaster.h>
-#include <keymaster/authorization_set.h>
-#include <keymaster/keymaster_enforcement.h>
-
-#include "android_keymaster_test_utils.h"
-
-namespace keymaster {
-namespace test {
-
-class TestKeymasterEnforcement : public KeymasterEnforcement {
- public:
- TestKeymasterEnforcement()
- : KeymasterEnforcement(3, 3), current_time_(10000), report_token_valid_(true) {}
-
- keymaster_error_t AuthorizeOperation(const keymaster_purpose_t purpose, const km_id_t keyid,
- const AuthorizationSet& auth_set) {
- AuthorizationSet empty_set;
- return KeymasterEnforcement::AuthorizeOperation(
- purpose, keyid, auth_set, empty_set, 0 /* op_handle */, true /* is_begin_operation */);
- }
- using KeymasterEnforcement::AuthorizeOperation;
-
- uint32_t get_current_time() const override { return current_time_; }
- bool activation_date_valid(uint64_t activation_date) const override {
- // Convert java date to time_t, non-portably.
- time_t activation_time = activation_date / 1000;
- return difftime(time(NULL), activation_time) >= 0;
- }
- bool expiration_date_passed(uint64_t expiration_date) const override {
- // Convert jave date to time_t, non-portably.
- time_t expiration_time = expiration_date / 1000;
- return difftime(time(NULL), expiration_time) > 0;
- }
- bool auth_token_timed_out(const hw_auth_token_t& token, uint32_t timeout) const {
- return current_time_ > ntoh(token.timestamp) + timeout;
- }
- bool ValidateTokenSignature(const hw_auth_token_t&) const override {
- return report_token_valid_;
- }
-
- void tick(unsigned seconds = 1) { current_time_ += seconds; }
- uint32_t current_time() { return current_time_; }
- void set_report_token_valid(bool report_token_valid) {
- report_token_valid_ = report_token_valid;
- }
-
- private:
- uint32_t current_time_;
- bool report_token_valid_;
-};
-
-class KeymasterBaseTest : public ::testing::Test {
- protected:
- KeymasterBaseTest() {
- past_time = 0;
-
- time_t t = time(NULL);
- future_tm = localtime(&t);
- future_tm->tm_year += 1;
- future_time = static_cast<uint64_t>(mktime(future_tm)) * 1000;
- sign_param = Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN);
- }
- virtual ~KeymasterBaseTest() {}
-
- TestKeymasterEnforcement kmen;
-
- tm past_tm;
- tm* future_tm;
- uint64_t past_time;
- uint64_t future_time;
- static const km_id_t key_id = 0xa;
- static const uid_t uid = 0xf;
- keymaster_key_param_t sign_param;
-};
-
-TEST_F(KeymasterBaseTest, TestValidKeyPeriodNoTags) {
- keymaster_key_param_t params[] = {
- sign_param,
- };
- AuthorizationSet single_auth_set(params, array_length(params));
-
- keymaster_error_t kmer = kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, single_auth_set);
- ASSERT_EQ(KM_ERROR_OK, kmer);
-}
-
-TEST_F(KeymasterBaseTest, TestInvalidActiveTime) {
- keymaster_key_param_t params[] = {
- Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
- Authorization(TAG_NO_AUTH_REQUIRED), Authorization(TAG_ACTIVE_DATETIME, future_time),
- };
-
- AuthorizationSet auth_set(params, array_length(params));
-
- ASSERT_EQ(KM_ERROR_KEY_NOT_YET_VALID,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set));
-
- // Pubkey ops allowed.
- ASSERT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set));
-}
-
-TEST_F(KeymasterBaseTest, TestValidActiveTime) {
- keymaster_key_param_t params[] = {
- Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_ACTIVE_DATETIME, past_time),
- };
-
- AuthorizationSet auth_set(params, array_length(params));
-
- keymaster_error_t kmer_valid_time = kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set);
- ASSERT_EQ(KM_ERROR_OK, kmer_valid_time);
-}
-
-TEST_F(KeymasterBaseTest, TestInvalidOriginationExpireTime) {
- keymaster_key_param_t params[] = {
- Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
- Authorization(TAG_ORIGINATION_EXPIRE_DATETIME, past_time),
- };
-
- AuthorizationSet auth_set(params, array_length(params));
-
- ASSERT_EQ(KM_ERROR_KEY_EXPIRED, kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set));
-
- // Pubkey ops allowed.
- ASSERT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set));
-}
-
-TEST_F(KeymasterBaseTest, TestInvalidOriginationExpireTimeOnUsgae) {
- keymaster_key_param_t params[] = {
- Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
- Authorization(TAG_ORIGINATION_EXPIRE_DATETIME, past_time),
- };
-
- AuthorizationSet auth_set(params, array_length(params));
-
- keymaster_error_t kmer_invalid_origination =
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set);
- ASSERT_EQ(KM_ERROR_OK, kmer_invalid_origination);
-}
-
-TEST_F(KeymasterBaseTest, TestValidOriginationExpireTime) {
- keymaster_key_param_t params[] = {
- Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
- Authorization(TAG_ORIGINATION_EXPIRE_DATETIME, future_time),
- };
-
- AuthorizationSet auth_set(params, array_length(params));
-
- keymaster_error_t kmer_valid_origination =
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set);
- ASSERT_EQ(KM_ERROR_OK, kmer_valid_origination);
-}
-
-TEST_F(KeymasterBaseTest, TestInvalidUsageExpireTime) {
- keymaster_key_param_t params[] = {
- Authorization(TAG_ALGORITHM, KM_ALGORITHM_AES),
- Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
- Authorization(TAG_USAGE_EXPIRE_DATETIME, past_time),
- };
-
- AuthorizationSet auth_set(params, array_length(params));
-
- keymaster_error_t kmer_invalid_origination =
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set);
- ASSERT_EQ(KM_ERROR_KEY_EXPIRED, kmer_invalid_origination);
-}
-
-TEST_F(KeymasterBaseTest, TestInvalidPubkeyUsageExpireTime) {
- keymaster_key_param_t params[] = {
- Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA),
- Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
- Authorization(TAG_USAGE_EXPIRE_DATETIME, past_time),
- };
-
- AuthorizationSet auth_set(params, array_length(params));
-
- keymaster_error_t kmer_invalid_origination =
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set);
- // Pubkey ops allowed.
- ASSERT_EQ(KM_ERROR_OK, kmer_invalid_origination);
-}
-
-TEST_F(KeymasterBaseTest, TestInvalidUsageExpireTimeOnOrigination) {
- keymaster_key_param_t params[] = {
- Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
- Authorization(TAG_USAGE_EXPIRE_DATETIME, past_time),
- };
-
- AuthorizationSet auth_set(params, array_length(params));
-
- keymaster_error_t kmer_invalid_origination =
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set);
- ASSERT_EQ(KM_ERROR_OK, kmer_invalid_origination);
-}
-
-TEST_F(KeymasterBaseTest, TestValidUsageExpireTime) {
- keymaster_key_param_t params[] = {
- Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
- Authorization(TAG_USAGE_EXPIRE_DATETIME, future_time),
- };
-
- AuthorizationSet auth_set(params, array_length(params));
-
- keymaster_error_t kmer_valid_usage =
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set);
- ASSERT_EQ(KM_ERROR_OK, kmer_valid_usage);
-}
-
-TEST_F(KeymasterBaseTest, TestValidSingleUseAccesses) {
- keymaster_key_param_t params[] = {
- Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
- };
-
- AuthorizationSet auth_set(params, array_length(params));
-
- keymaster_error_t kmer1 = kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set);
- keymaster_error_t kmer2 = kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set);
-
- ASSERT_EQ(KM_ERROR_OK, kmer1);
- ASSERT_EQ(KM_ERROR_OK, kmer2);
-}
-
-TEST_F(KeymasterBaseTest, TestInvalidMaxOps) {
- keymaster_key_param_t params[] = {
- Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA),
- Authorization(TAG_MAX_USES_PER_BOOT, 4),
- };
-
- AuthorizationSet auth_set(params, array_length(params));
-
- ASSERT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set));
- ASSERT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set));
- ASSERT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set));
- ASSERT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set));
- ASSERT_EQ(KM_ERROR_KEY_MAX_OPS_EXCEEDED,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set));
- // Pubkey ops allowed.
- ASSERT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set));
-}
-
-TEST_F(KeymasterBaseTest, TestOverFlowMaxOpsTable) {
- keymaster_key_param_t params[] = {
- Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
- Authorization(TAG_MAX_USES_PER_BOOT, 2),
- };
-
- AuthorizationSet auth_set(params, array_length(params));
-
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_SIGN, 1 /* key_id */, auth_set));
-
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_SIGN, 2 /* key_id */, auth_set));
-
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_SIGN, 3 /* key_id */, auth_set));
-
- // Key 4 should fail, because table is full.
- EXPECT_EQ(KM_ERROR_TOO_MANY_OPERATIONS,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, 4 /* key_id */, auth_set));
-
- // Key 1 still works, because it's already in the table and hasn't reached max.
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_SIGN, 1 /* key_id */, auth_set));
-
- // Key 1 no longer works, because it's reached max.
- EXPECT_EQ(KM_ERROR_KEY_MAX_OPS_EXCEEDED,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, 1 /* key_id */, auth_set));
-
- // Key 4 should fail, because table is (still and forever) full.
- EXPECT_EQ(KM_ERROR_TOO_MANY_OPERATIONS,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, 4 /* key_id */, auth_set));
-
- // Pubkey ops allowed.
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 1 /* key_id */, auth_set));
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 4 /* key_id */, auth_set));
-}
-
-TEST_F(KeymasterBaseTest, TestInvalidTimeBetweenOps) {
- keymaster_key_param_t params[] = {
- Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
- Authorization(TAG_MIN_SECONDS_BETWEEN_OPS, 10),
- };
-
- AuthorizationSet auth_set(params, array_length(params));
-
- keymaster_error_t kmer1 = kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set);
- keymaster_error_t kmer2 = kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set);
- keymaster_error_t kmer3 = kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set);
-
- ASSERT_EQ(KM_ERROR_OK, kmer1);
- kmen.tick(2);
- ASSERT_EQ(KM_ERROR_KEY_RATE_LIMIT_EXCEEDED, kmer2);
-
- // Allowed because it's a pubkey op.
- ASSERT_EQ(KM_ERROR_OK, kmer3);
-}
-
-TEST_F(KeymasterBaseTest, TestValidTimeBetweenOps) {
- keymaster_key_param_t params[] = {
- Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
- Authorization(TAG_MIN_SECONDS_BETWEEN_OPS, 2),
- };
-
- AuthorizationSet auth_set(params, array_length(params));
-
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set));
- kmen.tick();
- EXPECT_EQ(KM_ERROR_KEY_RATE_LIMIT_EXCEEDED,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set));
- kmen.tick();
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set));
-}
-
-TEST_F(KeymasterBaseTest, TestOptTimeoutTableOverflow) {
- keymaster_key_param_t params[] = {
- Authorization(TAG_ALGORITHM, KM_ALGORITHM_AES),
- Authorization(TAG_MIN_SECONDS_BETWEEN_OPS, 4),
- Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
- };
-
- AuthorizationSet auth_set(params, array_length(params));
-
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 1 /* key_id */, auth_set));
-
- kmen.tick();
-
- // Key 1 fails because it's too soon
- EXPECT_EQ(KM_ERROR_KEY_RATE_LIMIT_EXCEEDED,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 1 /* key_id */, auth_set));
-
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 2 /* key_id */, auth_set));
-
- kmen.tick();
-
- // Key 1 fails because it's too soon
- EXPECT_EQ(KM_ERROR_KEY_RATE_LIMIT_EXCEEDED,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 1 /* key_id */, auth_set));
- // Key 2 fails because it's too soon
- EXPECT_EQ(KM_ERROR_KEY_RATE_LIMIT_EXCEEDED,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 2 /* key_id */, auth_set));
-
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 3 /* key_id */, auth_set));
-
- kmen.tick();
-
- // Key 1 fails because it's too soon
- EXPECT_EQ(KM_ERROR_KEY_RATE_LIMIT_EXCEEDED,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 1 /* key_id */, auth_set));
- // Key 2 fails because it's too soon
- EXPECT_EQ(KM_ERROR_KEY_RATE_LIMIT_EXCEEDED,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 2 /* key_id */, auth_set));
- // Key 3 fails because it's too soon
- EXPECT_EQ(KM_ERROR_KEY_RATE_LIMIT_EXCEEDED,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 3 /* key_id */, auth_set));
- // Key 4 fails because the table is full
- EXPECT_EQ(KM_ERROR_TOO_MANY_OPERATIONS,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 4 /* key_id */, auth_set));
-
- kmen.tick();
-
- // Key 4 succeeds because key 1 expired.
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 4 /* key_id */, auth_set));
-
- // Key 1 fails because the table is full... and key 1 is no longer in it.
- EXPECT_EQ(KM_ERROR_TOO_MANY_OPERATIONS,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 1 /* key_id */, auth_set));
- // Key 2 fails because it's too soon
- EXPECT_EQ(KM_ERROR_KEY_RATE_LIMIT_EXCEEDED,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 2 /* key_id */, auth_set));
- // Key 3 fails because it's too soon
- EXPECT_EQ(KM_ERROR_KEY_RATE_LIMIT_EXCEEDED,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 3 /* key_id */, auth_set));
-
- kmen.tick();
-
- // Key 1 succeeds because key 2 expired
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 1 /* key_id */, auth_set));
- // Key 2 fails because the table is full... and key 2 is no longer in it.
- EXPECT_EQ(KM_ERROR_TOO_MANY_OPERATIONS,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 2 /* key_id */, auth_set));
- // Key 3 fails because it's too soon
- EXPECT_EQ(KM_ERROR_KEY_RATE_LIMIT_EXCEEDED,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 3 /* key_id */, auth_set));
- // Key 4 fails because it's too soon
- EXPECT_EQ(KM_ERROR_KEY_RATE_LIMIT_EXCEEDED,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 4 /* key_id */, auth_set));
-
- kmen.tick(4);
-
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 1 /* key_id */, auth_set));
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 2 /* key_id */, auth_set));
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 3 /* key_id */, auth_set));
-}
-
-TEST_F(KeymasterBaseTest, TestPubkeyOptTimeoutTableOverflow) {
- keymaster_key_param_t params[] = {
- Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA),
- Authorization(TAG_MIN_SECONDS_BETWEEN_OPS, 4), Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
- };
-
- AuthorizationSet auth_set(params, array_length(params));
-
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_SIGN, 1 /* key_id */, auth_set));
-
- kmen.tick();
-
- // Key 1 fails because it's too soon
- EXPECT_EQ(KM_ERROR_KEY_RATE_LIMIT_EXCEEDED,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, 1 /* key_id */, auth_set));
- // Too soo, but pubkey ops allowed.
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, 1 /* key_id */, auth_set));
-}
-
-TEST_F(KeymasterBaseTest, TestInvalidPurpose) {
- keymaster_purpose_t invalidPurpose1 = static_cast<keymaster_purpose_t>(-1);
- keymaster_purpose_t invalidPurpose2 = static_cast<keymaster_purpose_t>(4);
-
- AuthorizationSet auth_set(
- AuthorizationSetBuilder().Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY));
-
- EXPECT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE,
- kmen.AuthorizeOperation(invalidPurpose1, key_id, auth_set));
- EXPECT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE,
- kmen.AuthorizeOperation(invalidPurpose2, key_id, auth_set));
-}
-
-TEST_F(KeymasterBaseTest, TestIncompatiblePurposeSymmetricKey) {
- AuthorizationSet auth_set(AuthorizationSetBuilder()
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_AES)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN));
-
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set));
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set));
-
- EXPECT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE,
- kmen.AuthorizeOperation(KM_PURPOSE_ENCRYPT, key_id, auth_set));
- EXPECT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE,
- kmen.AuthorizeOperation(KM_PURPOSE_DECRYPT, key_id, auth_set));
-}
-
-TEST_F(KeymasterBaseTest, TestIncompatiblePurposeAssymmetricKey) {
- AuthorizationSet auth_set(AuthorizationSetBuilder()
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN));
-
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set));
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set));
-
- // This one is allowed because it's a pubkey op.
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_ENCRYPT, key_id, auth_set));
- EXPECT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE,
- kmen.AuthorizeOperation(KM_PURPOSE_DECRYPT, key_id, auth_set));
-}
-
-TEST_F(KeymasterBaseTest, TestInvalidCallerNonce) {
- AuthorizationSet no_caller_nonce(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_ENCRYPT)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_DECRYPT)
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_AES));
- AuthorizationSet caller_nonce(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_ENCRYPT)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_DECRYPT)
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_HMAC)
- .Authorization(TAG_CALLER_NONCE));
- AuthorizationSet begin_params(AuthorizationSetBuilder().Authorization(TAG_NONCE, "foo", 3));
-
- EXPECT_EQ(KM_ERROR_OK,
- kmen.AuthorizeOperation(KM_PURPOSE_ENCRYPT, key_id, caller_nonce, begin_params,
- 0 /* challenge */, true /* is_begin_operation */));
- EXPECT_EQ(KM_ERROR_OK,
- kmen.AuthorizeOperation(KM_PURPOSE_DECRYPT, key_id, caller_nonce, begin_params,
- 0 /* challenge */, true /* is_begin_operation */));
- EXPECT_EQ(KM_ERROR_CALLER_NONCE_PROHIBITED,
- kmen.AuthorizeOperation(KM_PURPOSE_ENCRYPT, key_id, no_caller_nonce, begin_params,
- 0 /* challenge */, true /* is_begin_operation */));
- EXPECT_EQ(KM_ERROR_OK,
- kmen.AuthorizeOperation(KM_PURPOSE_DECRYPT, key_id, no_caller_nonce, begin_params,
- 0 /* challenge */, true /* is_begin_operation */));
-}
-
-TEST_F(KeymasterBaseTest, TestBootloaderOnly) {
- AuthorizationSet auth_set(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_BOOTLOADER_ONLY));
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set));
-
- // Pubkey ops allowed.
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set));
-}
-
-TEST_F(KeymasterBaseTest, TestInvalidTag) {
- AuthorizationSet auth_set(AuthorizationSetBuilder()
- .Authorization(TAG_INVALID)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN));
-
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set));
-}
-
-TEST_F(KeymasterBaseTest, TestAuthPerOpSuccess) {
- hw_auth_token_t token;
- memset(&token, 0, sizeof(token));
- token.version = HW_AUTH_TOKEN_VERSION;
- token.challenge = 99;
- token.user_id = 9;
- token.authenticator_id = 0;
- token.authenticator_type = hton(static_cast<uint32_t>(HW_AUTH_PASSWORD));
- token.timestamp = 0;
-
- AuthorizationSet auth_set(AuthorizationSetBuilder()
- .Authorization(TAG_USER_SECURE_ID, token.user_id)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_ANY)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN));
-
- AuthorizationSet op_params;
- op_params.push_back(Authorization(TAG_AUTH_TOKEN, &token, sizeof(token)));
-
- EXPECT_EQ(KM_ERROR_OK,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set, op_params, token.challenge,
- false /* is_begin_operation */));
-}
-
-TEST_F(KeymasterBaseTest, TestAuthPerOpInvalidTokenSignature) {
- hw_auth_token_t token;
- memset(&token, 0, sizeof(token));
- token.version = HW_AUTH_TOKEN_VERSION;
- token.challenge = 99;
- token.user_id = 9;
- token.authenticator_id = 0;
- token.authenticator_type = hton(static_cast<uint32_t>(HW_AUTH_PASSWORD));
- token.timestamp = 0;
-
- AuthorizationSet auth_set(AuthorizationSetBuilder()
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_EC)
- .Authorization(TAG_USER_SECURE_ID, token.user_id)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_ANY)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN));
-
- AuthorizationSet op_params;
- op_params.push_back(Authorization(TAG_AUTH_TOKEN, &token, sizeof(token)));
-
- kmen.set_report_token_valid(false);
- EXPECT_EQ(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set, op_params, token.challenge,
- false /* is_begin_operation */));
- // Pubkey ops allowed.
- EXPECT_EQ(KM_ERROR_OK,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set, op_params,
- token.challenge, false /* is_begin_operation */));
-}
-
-TEST_F(KeymasterBaseTest, TestAuthPerOpWrongChallenge) {
- hw_auth_token_t token;
- memset(&token, 0, sizeof(token));
- token.version = HW_AUTH_TOKEN_VERSION;
- token.challenge = 99;
- token.user_id = 9;
- token.authenticator_id = 0;
- token.authenticator_type = hton(static_cast<uint32_t>(HW_AUTH_PASSWORD));
- token.timestamp = 0;
-
- AuthorizationSet auth_set(AuthorizationSetBuilder()
- .Authorization(TAG_USER_SECURE_ID, token.user_id)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_ANY)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN));
-
- AuthorizationSet op_params;
- op_params.push_back(Authorization(TAG_AUTH_TOKEN, &token, sizeof(token)));
-
- EXPECT_EQ(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set, op_params,
- token.challenge + 1 /* doesn't match token */,
- false /* is_begin_operation */));
-}
-
-TEST_F(KeymasterBaseTest, TestAuthPerOpNoAuthType) {
- hw_auth_token_t token;
- memset(&token, 0, sizeof(token));
- token.version = HW_AUTH_TOKEN_VERSION;
- token.challenge = 99;
- token.user_id = 9;
- token.authenticator_id = 0;
- token.authenticator_type = hton(static_cast<uint32_t>(HW_AUTH_PASSWORD));
- token.timestamp = 0;
-
- AuthorizationSet auth_set(AuthorizationSetBuilder()
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_SECURE_ID, token.user_id)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN));
-
- AuthorizationSet op_params;
- op_params.push_back(Authorization(TAG_AUTH_TOKEN, &token, sizeof(token)));
-
- EXPECT_EQ(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set, op_params, token.challenge,
- false /* is_begin_operation */));
- // Pubkey ops allowed.
- EXPECT_EQ(KM_ERROR_OK,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set, op_params,
- token.challenge, false /* is_begin_operation */));
-}
-
-TEST_F(KeymasterBaseTest, TestAuthPerOpWrongAuthType) {
- hw_auth_token_t token;
- memset(&token, 0, sizeof(token));
- token.version = HW_AUTH_TOKEN_VERSION;
- token.challenge = 99;
- token.user_id = 9;
- token.authenticator_id = 0;
- token.authenticator_type = hton(static_cast<uint32_t>(HW_AUTH_PASSWORD));
- token.timestamp = 0;
-
- AuthorizationSet auth_set(
- AuthorizationSetBuilder()
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_SECURE_ID, token.user_id)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_FINGERPRINT /* doesn't match token */)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN));
-
- AuthorizationSet op_params;
- op_params.push_back(Authorization(TAG_AUTH_TOKEN, &token, sizeof(token)));
-
- EXPECT_EQ(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set, op_params, token.challenge,
- false /* is_begin_operation */));
- // Pubkey ops allowed.
- EXPECT_EQ(KM_ERROR_OK,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set, op_params,
- token.challenge, false /* is_begin_operation */));
-}
-
-TEST_F(KeymasterBaseTest, TestAuthPerOpWrongSid) {
- hw_auth_token_t token;
- memset(&token, 0, sizeof(token));
- token.version = HW_AUTH_TOKEN_VERSION;
- token.challenge = 99;
- token.user_id = 9;
- token.authenticator_id = 0;
- token.authenticator_type = hton(static_cast<uint32_t>(HW_AUTH_PASSWORD));
- token.timestamp = 0;
-
- AuthorizationSet auth_set(
- AuthorizationSetBuilder()
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_SECURE_ID, token.user_id + 1 /* doesn't match token */)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_ANY)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN));
-
- AuthorizationSet op_params;
- op_params.push_back(Authorization(TAG_AUTH_TOKEN, &token, sizeof(token)));
-
- EXPECT_EQ(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set, op_params, token.challenge,
- false /* is_begin_operation */));
- // Pubkey op allowed.
- EXPECT_EQ(KM_ERROR_OK,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set, op_params,
- token.challenge, false /* is_begin_operation */));
-}
-
-TEST_F(KeymasterBaseTest, TestAuthPerOpSuccessAlternateSid) {
- hw_auth_token_t token;
- memset(&token, 0, sizeof(token));
- token.version = HW_AUTH_TOKEN_VERSION;
- token.challenge = 99;
- token.user_id = 9;
- token.authenticator_id = 10;
- token.authenticator_type = hton(static_cast<uint32_t>(HW_AUTH_PASSWORD));
- token.timestamp = 0;
-
- AuthorizationSet auth_set(AuthorizationSetBuilder()
- .Authorization(TAG_USER_SECURE_ID, token.authenticator_id)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_ANY)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN));
-
- AuthorizationSet op_params;
- op_params.push_back(Authorization(TAG_AUTH_TOKEN, &token, sizeof(token)));
-
- EXPECT_EQ(KM_ERROR_OK,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set, op_params, token.challenge,
- false /* is_begin_operation */));
-}
-
-TEST_F(KeymasterBaseTest, TestAuthPerOpMissingToken) {
- hw_auth_token_t token;
- memset(&token, 0, sizeof(token));
- token.version = HW_AUTH_TOKEN_VERSION;
- token.challenge = 99;
- token.user_id = 9;
- token.authenticator_id = 0;
- token.authenticator_type = hton(static_cast<uint32_t>(HW_AUTH_PASSWORD));
- token.timestamp = 0;
-
- AuthorizationSet auth_set(AuthorizationSetBuilder()
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_SECURE_ID, token.user_id)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_ANY)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN));
-
- AuthorizationSet op_params;
-
- // During begin we can skip the auth token
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set, op_params,
- token.challenge, true /* is_begin_operation */));
- // Afterwards we must have authentication
- EXPECT_EQ(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set, op_params, token.challenge,
- false /* is_begin_operation */));
- // Pubkey ops allowed
- EXPECT_EQ(KM_ERROR_OK,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set, op_params,
- token.challenge, false /* is_begin_operation */));
-
- auth_set.Reinitialize(AuthorizationSetBuilder()
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_AES)
- .Authorization(TAG_USER_SECURE_ID, token.user_id)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_ANY)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN)
- .build());
-
- EXPECT_EQ(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set, op_params,
- token.challenge, false /* is_begin_operation */));
-}
-
-TEST_F(KeymasterBaseTest, TestAuthAndNoAuth) {
- AuthorizationSet auth_set(AuthorizationSetBuilder()
- .Authorization(TAG_USER_SECURE_ID, 1)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN));
-
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set));
-}
-
-TEST_F(KeymasterBaseTest, TestTimedAuthSuccess) {
- hw_auth_token_t token;
- memset(&token, 0, sizeof(token));
- token.version = HW_AUTH_TOKEN_VERSION;
- token.challenge = 99;
- token.user_id = 9;
- token.authenticator_id = 0;
- token.authenticator_type = hton(static_cast<uint32_t>(HW_AUTH_PASSWORD));
- token.timestamp = hton(kmen.current_time());
-
- AuthorizationSet auth_set(AuthorizationSetBuilder()
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_SECURE_ID, token.user_id)
- .Authorization(TAG_AUTH_TIMEOUT, 1)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_ANY)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN));
-
- AuthorizationSet op_params;
- op_params.push_back(Authorization(TAG_AUTH_TOKEN, &token, sizeof(token)));
-
- EXPECT_EQ(KM_ERROR_OK,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set, op_params,
- 0 /* irrelevant */, false /* is_begin_operation */));
-}
-
-TEST_F(KeymasterBaseTest, TestTimedAuthTimedOut) {
- hw_auth_token_t token;
- memset(&token, 0, sizeof(token));
- token.version = HW_AUTH_TOKEN_VERSION;
- token.challenge = 99;
- token.user_id = 9;
- token.authenticator_id = 0;
- token.authenticator_type = hton(static_cast<uint32_t>(HW_AUTH_PASSWORD));
- token.timestamp = hton(static_cast<uint64_t>(kmen.current_time()));
-
- AuthorizationSet auth_set(AuthorizationSetBuilder()
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_SECURE_ID, token.user_id)
- .Authorization(TAG_AUTH_TIMEOUT, 1)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_ANY)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN));
-
- AuthorizationSet op_params;
- op_params.push_back(Authorization(TAG_AUTH_TOKEN, &token, sizeof(token)));
-
- EXPECT_EQ(KM_ERROR_OK,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set, op_params,
- 0 /* irrelevant */, false /* is_begin_operation */));
-
- kmen.tick(1);
-
- // token still good
- EXPECT_EQ(KM_ERROR_OK,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set, op_params,
- 0 /* irrelevant */, false /* is_begin_operation */));
-
- kmen.tick(1);
-
- // token expired, not allowed during begin.
- EXPECT_EQ(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set, op_params,
- 0 /* irrelevant */, true /* is_begin_operation */));
-
- // token expired, afterwards it's okay.
- EXPECT_EQ(KM_ERROR_OK,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set, op_params,
- 0 /* irrelevant */, false /* is_begin_operation */));
-
- // Pubkey ops allowed.
- EXPECT_EQ(KM_ERROR_OK,
- kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set, op_params,
- 0 /* irrelevant */, true /* is_begin_operation */));
-}
-
-TEST_F(KeymasterBaseTest, TestTimedAuthMissingToken) {
- hw_auth_token_t token;
- memset(&token, 0, sizeof(token));
- token.version = HW_AUTH_TOKEN_VERSION;
- token.challenge = 99;
- token.user_id = 9;
- token.authenticator_id = 0;
- token.authenticator_type = hton(static_cast<uint32_t>(HW_AUTH_PASSWORD));
- token.timestamp = hton(static_cast<uint64_t>(kmen.current_time()));
-
- AuthorizationSet auth_set(AuthorizationSetBuilder()
- .Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
- .Authorization(TAG_USER_SECURE_ID, token.user_id)
- .Authorization(TAG_AUTH_TIMEOUT, 1)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_ANY)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN));
-
- AuthorizationSet op_params;
-
- // Unlike auth-per-op, must have the auth token during begin.
- EXPECT_EQ(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set, op_params, token.challenge,
- true /* is_begin_operation */));
-
- // Later we don't check (though begin would fail, so there wouldn't be a later).
- EXPECT_EQ(KM_ERROR_OK,
- kmen.AuthorizeOperation(KM_PURPOSE_SIGN, key_id, auth_set, op_params, token.challenge,
- false /* is_begin_operation */));
-
- // Pubkey ops allowed.
- EXPECT_EQ(KM_ERROR_OK, kmen.AuthorizeOperation(KM_PURPOSE_VERIFY, key_id, auth_set, op_params,
- token.challenge, true /* is_begin_operation */));
-}
-
-TEST_F(KeymasterBaseTest, TestCreateKeyId) {
- keymaster_key_blob_t blob = {reinterpret_cast<const uint8_t*>("foobar"), 6};
-
- km_id_t key_id = 0;
- EXPECT_TRUE(KeymasterEnforcement::CreateKeyId(blob, &key_id));
- EXPECT_NE(0U, key_id);
-}
-
-}; /* namespace test */
-}; /* namespace keymaster */
diff --git a/unit_test/keymaster_tags.cpp b/unit_test/keymaster_tags.cpp
deleted file mode 100644
index 238bc33..0000000
--- a/unit_test/keymaster_tags.cpp
+++ b/dev/null
@@ -1,173 +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.
- */
-
-#include <keymaster/keymaster_tags.h>
-
-namespace keymaster {
-
-#ifdef KEYMASTER_NAME_TAGS
-const char* StringifyTag(keymaster_tag_t tag) {
- switch (tag) {
- case KM_TAG_INVALID:
- return "KM_TAG_INVALID";
- case KM_TAG_PURPOSE:
- return "KM_TAG_PURPOSE";
- case KM_TAG_ALGORITHM:
- return "KM_TAG_ALGORITHM";
- case KM_TAG_KEY_SIZE:
- return "KM_TAG_KEY_SIZE";
- case KM_TAG_BLOCK_MODE:
- return "KM_TAG_BLOCK_MODE";
- case KM_TAG_DIGEST:
- return "KM_TAG_DIGEST";
- case KM_TAG_PADDING:
- return "KM_TAG_PADDING";
- case KM_TAG_CALLER_NONCE:
- return "KM_TAG_CALLER_NONCE";
- case KM_TAG_MIN_MAC_LENGTH:
- return "KM_TAG_MIN_MAC_LENGTH";
- case KM_TAG_RSA_PUBLIC_EXPONENT:
- return "KM_TAG_RSA_PUBLIC_EXPONENT";
- case KM_TAG_BLOB_USAGE_REQUIREMENTS:
- return "KM_TAG_BLOB_USAGE_REQUIREMENTS";
- case KM_TAG_BOOTLOADER_ONLY:
- return "KM_TAG_BOOTLOADER_ONLY";
- case KM_TAG_ACTIVE_DATETIME:
- return "KM_TAG_ACTIVE_DATETIME";
- case KM_TAG_ORIGINATION_EXPIRE_DATETIME:
- return "KM_TAG_ORIGINATION_EXPIRE_DATETIME";
- case KM_TAG_USAGE_EXPIRE_DATETIME:
- return "KM_TAG_USAGE_EXPIRE_DATETIME";
- case KM_TAG_MIN_SECONDS_BETWEEN_OPS:
- return "KM_TAG_MIN_SECONDS_BETWEEN_OPS";
- case KM_TAG_MAX_USES_PER_BOOT:
- return "KM_TAG_MAX_USES_PER_BOOT";
- case KM_TAG_ALL_USERS:
- return "KM_TAG_ALL_USERS";
- case KM_TAG_USER_ID:
- return "KM_TAG_USER_ID";
- case KM_TAG_USER_SECURE_ID:
- return "KM_TAG_USER_SECURE_ID";
- case KM_TAG_NO_AUTH_REQUIRED:
- return "KM_TAG_NO_AUTH_REQUIRED";
- case KM_TAG_USER_AUTH_TYPE:
- return "KM_TAG_USER_AUTH_TYPE";
- case KM_TAG_AUTH_TIMEOUT:
- return "KM_TAG_AUTH_TIMEOUT";
- case KM_TAG_ALL_APPLICATIONS:
- return "KM_TAG_ALL_APPLICATIONS";
- case KM_TAG_APPLICATION_ID:
- return "KM_TAG_APPLICATION_ID";
- case KM_TAG_APPLICATION_DATA:
- return "KM_TAG_APPLICATION_DATA";
- case KM_TAG_CREATION_DATETIME:
- return "KM_TAG_CREATION_DATETIME";
- case KM_TAG_ORIGIN:
- return "KM_TAG_ORIGIN";
- case KM_TAG_ROLLBACK_RESISTANT:
- return "KM_TAG_ROLLBACK_RESISTANT";
- case KM_TAG_ROOT_OF_TRUST:
- return "KM_TAG_ROOT_OF_TRUST";
- case KM_TAG_ASSOCIATED_DATA:
- return "KM_TAG_ASSOCIATED_DATA";
- case KM_TAG_NONCE:
- return "KM_TAG_NONCE";
- case KM_TAG_AUTH_TOKEN:
- return "KM_TAG_AUTH_TOKEN";
- case KM_TAG_MAC_LENGTH:
- return "KM_TAG_MAC_LENGTH";
- case KM_TAG_KDF:
- return "KM_TAG_KDF";
- case KM_TAG_EC_CURVE:
- return "KM_TAG_EC_CURVE";
- case KM_TAG_ECIES_SINGLE_HASH_MODE:
- return "KM_TAG_ECIES_SINGLE_HASH_MODE";
- case KM_TAG_OS_VERSION:
- return "KM_TAG_OS_VERSION";
- case KM_TAG_OS_PATCHLEVEL:
- return "KM_TAG_OS_PATCHLEVEL";
- case KM_TAG_EXPORTABLE:
- return "KM_TAG_EXPORTABLE";
- case KM_TAG_UNIQUE_ID:
- return "KM_TAG_UNIQUE_ID";
- case KM_TAG_INCLUDE_UNIQUE_ID:
- return "KM_TAG_INCLUDE_UNIQUE_ID";
- case KM_TAG_RESET_SINCE_ID_ROTATION:
- return "KM_TAG_RESET_SINCE_ID_ROTATION";
- case KM_TAG_ALLOW_WHILE_ON_BODY:
- return "KM_TAG_ALLOW_WHILE_ON_BODY";
- case KM_TAG_ATTESTATION_CHALLENGE:
- return "KM_TAG_ATTESTATION_CHALLENGE";
- }
- return "<Unknown>";
-}
-#endif // KEYMASTER_NAME_TAGS
-
-// DEFINE_KEYMASTER_TAG is used to create TypedTag instances for each non-enum keymaster tag.
-#define DEFINE_KEYMASTER_TAG(type, name) TypedTag<type, KM_##name> name
-
-DEFINE_KEYMASTER_TAG(KM_INVALID, TAG_INVALID);
-DEFINE_KEYMASTER_TAG(KM_UINT, TAG_KEY_SIZE);
-DEFINE_KEYMASTER_TAG(KM_UINT, TAG_MAC_LENGTH);
-DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_CALLER_NONCE);
-DEFINE_KEYMASTER_TAG(KM_UINT, TAG_MIN_MAC_LENGTH);
-DEFINE_KEYMASTER_TAG(KM_ULONG, TAG_RSA_PUBLIC_EXPONENT);
-DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_ECIES_SINGLE_HASH_MODE);
-DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_INCLUDE_UNIQUE_ID);
-DEFINE_KEYMASTER_TAG(KM_DATE, TAG_ACTIVE_DATETIME);
-DEFINE_KEYMASTER_TAG(KM_DATE, TAG_ORIGINATION_EXPIRE_DATETIME);
-DEFINE_KEYMASTER_TAG(KM_DATE, TAG_USAGE_EXPIRE_DATETIME);
-DEFINE_KEYMASTER_TAG(KM_UINT, TAG_MIN_SECONDS_BETWEEN_OPS);
-DEFINE_KEYMASTER_TAG(KM_UINT, TAG_MAX_USES_PER_BOOT);
-DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_ALL_USERS);
-DEFINE_KEYMASTER_TAG(KM_UINT, TAG_USER_ID);
-DEFINE_KEYMASTER_TAG(KM_ULONG_REP, TAG_USER_SECURE_ID);
-DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_NO_AUTH_REQUIRED);
-DEFINE_KEYMASTER_TAG(KM_UINT, TAG_AUTH_TIMEOUT);
-DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_ALLOW_WHILE_ON_BODY);
-DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_ALL_APPLICATIONS);
-DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_APPLICATION_ID);
-DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_APPLICATION_DATA);
-DEFINE_KEYMASTER_TAG(KM_DATE, TAG_CREATION_DATETIME);
-DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_ROLLBACK_RESISTANT);
-DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ROOT_OF_TRUST);
-DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ASSOCIATED_DATA);
-DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_NONCE);
-DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_AUTH_TOKEN);
-DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_BOOTLOADER_ONLY);
-DEFINE_KEYMASTER_TAG(KM_UINT, TAG_OS_VERSION);
-DEFINE_KEYMASTER_TAG(KM_UINT, TAG_OS_PATCHLEVEL);
-DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_UNIQUE_ID);
-
-// DEFINE_KEYMASTER_ENUM_TAG is used to create TypedEnumTag instances for each enum keymaster tag.
-
-#define DEFINE_KEYMASTER_ENUM_TAG(type, name, enumtype) TypedEnumTag<type, KM_##name, enumtype> name
-
-DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_PURPOSE, keymaster_purpose_t);
-DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_ALGORITHM, keymaster_algorithm_t);
-DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_BLOCK_MODE, keymaster_block_mode_t);
-DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_DIGEST, keymaster_digest_t);
-DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_DIGEST_OLD, keymaster_digest_t);
-DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_PADDING, keymaster_padding_t);
-DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_PADDING_OLD, keymaster_padding_t);
-DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_BLOB_USAGE_REQUIREMENTS,
- keymaster_key_blob_usage_requirements_t);
-DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_ORIGIN, keymaster_key_origin_t);
-DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_USER_AUTH_TYPE, hw_authenticator_type_t);
-DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_KDF, keymaster_kdf_t);
-DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_EC_CURVE, keymaster_ec_curve_t);
-
-} // namespace keymaster
diff --git a/unit_test/nist_curve_key_exchange_test.cpp b/unit_test/nist_curve_key_exchange_test.cpp
deleted file mode 100644
index 39ea38b..0000000
--- a/unit_test/nist_curve_key_exchange_test.cpp
+++ b/dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright 2015 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 "nist_curve_key_exchange.h"
-
-#include <gtest/gtest.h>
-#include <openssl/evp.h>
-
-#include <hardware/keymaster_defs.h>
-#include <keymaster/android_keymaster_utils.h>
-
-#include "android_keymaster_test_utils.h"
-
-using std::string;
-
-namespace keymaster {
-namespace test {
-
-StdoutLogger logger;
-
-static const keymaster_ec_curve_t kEcCurves[] = {KM_EC_CURVE_P_224, KM_EC_CURVE_P_256,
- KM_EC_CURVE_P_384, KM_EC_CURVE_P_521};
-
-/**
- * SharedKey just tests that the basic key exchange identity holds: that both
- * parties end up with the same key.
- */
-TEST(NistCurveKeyExchange, SharedKey) {
- for (auto& curve : kEcCurves) {
- AuthorizationSet kex_description(
- AuthorizationSetBuilder().Authorization(TAG_EC_CURVE, curve));
- for (size_t j = 0; j < 5; j++) {
- NistCurveKeyExchange* alice_keyex = NistCurveKeyExchange::GenerateKeyExchange(curve);
- NistCurveKeyExchange* bob_keyex = NistCurveKeyExchange::GenerateKeyExchange(curve);
-
- ASSERT_TRUE(alice_keyex != nullptr);
- ASSERT_TRUE(bob_keyex != nullptr);
-
- Buffer alice_public_value;
- ASSERT_TRUE(alice_keyex->public_value(&alice_public_value));
- Buffer bob_public_value;
- ASSERT_TRUE(bob_keyex->public_value(&bob_public_value));
-
- Buffer alice_shared, bob_shared;
- ASSERT_TRUE(alice_keyex->CalculateSharedKey(bob_public_value, &alice_shared));
- ASSERT_TRUE(bob_keyex->CalculateSharedKey(alice_public_value, &bob_shared));
- EXPECT_EQ(alice_shared.available_read(), bob_shared.available_read());
- EXPECT_EQ(0, memcmp(alice_shared.peek_read(), bob_shared.peek_read(),
- alice_shared.available_read()));
- }
- }
-}
-
-/*
- * This test tries a key agreement with a false public key (i.e. with
- * a point not on the curve.)
- * The expected result of such a protocol should be that the
- * key agreement fails and returns an error.
-*/
-static const char* kInvalidPublicKeys[] = {
- "04" // uncompressed public key
- "deadbeef7f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287"
- "db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac",
-};
-
-TEST(NistCurveKeyExchange, InvalidPublicKey) {
- for (auto& curve : kEcCurves) {
- AuthorizationSet kex_description(
- AuthorizationSetBuilder().Authorization(TAG_EC_CURVE, curve));
- KeyExchange* key_exchange = NistCurveKeyExchange::GenerateKeyExchange(curve);
- ASSERT_TRUE(key_exchange != nullptr);
-
- string peer_public_key = hex2str(kInvalidPublicKeys[0]);
- Buffer computed_shared_secret;
- ASSERT_FALSE(key_exchange->CalculateSharedKey(
- reinterpret_cast<const uint8_t*>(peer_public_key.data()), peer_public_key.size(),
- &computed_shared_secret));
- }
-}
-
-/**
- * Test that key exchange fails when peer public key is the point at infinity.
- */
-TEST(NistCurveKeyExchange, TestInfinity) {
- for (auto& curve : kEcCurves) {
- /* Obtain the point at infinity */
- EC_GROUP* group = ec_get_group(curve);
- EC_POINT* point_at_infinity = EC_POINT_new(group);
- EC_POINT_set_to_infinity(group, point_at_infinity);
- EXPECT_EQ(1, EC_POINT_is_on_curve(group, point_at_infinity, nullptr));
- size_t field_len_in_bits;
- ec_get_group_size(group, &field_len_in_bits);
- size_t field_len = (field_len_in_bits + 7) / 8;
- size_t public_key_len = (field_len * 2) + 1;
- uint8_t* public_key = new uint8_t[public_key_len];
- public_key_len = EC_POINT_point2oct(group, point_at_infinity, POINT_CONVERSION_UNCOMPRESSED,
- public_key, public_key_len, nullptr /* ctx */);
-
- /* Perform the key exchange */
- AuthorizationSet kex_description(
- AuthorizationSetBuilder().Authorization(TAG_EC_CURVE, curve));
- NistCurveKeyExchange* key_exchange = NistCurveKeyExchange::GenerateKeyExchange(curve);
- ASSERT_TRUE(key_exchange != nullptr);
- Buffer computed_shared_secret;
- /* It should fail */
- ASSERT_FALSE(key_exchange->CalculateSharedKey(reinterpret_cast<const uint8_t*>(public_key),
- public_key_len, &computed_shared_secret));
-
- /* Explicitly test that ECDH_compute_key fails when the public key is the point at infinity
- */
- UniquePtr<uint8_t[]> result(new uint8_t[field_len]);
- EXPECT_EQ(-1 /* error */, ECDH_compute_key(result.get(), field_len, point_at_infinity,
- key_exchange->private_key(), nullptr /* kdf */));
- }
-}
-
-/* Test vectors for P-256, downloaded from NIST. */
-struct NistCurveTest {
- const keymaster_ec_curve_t curve;
- const char* peer_public_key;
- const char* my_private_key;
- const char* shared_secret;
-};
-
-static const NistCurveTest kNistCurveTests[] = {
- {
- KM_EC_CURVE_P_256,
- "04" // uncompressed public key
- "700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287"
- "db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac",
- // https://tools.ietf.org/html/rfc5915
- "30770201010420" // DER-encodeded EC private key header
- "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534" // private key
- "a00a06082a8648ce3d030107a144034200" // DER-encoded curve OID,
- "04"
- "ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b230"
- "28af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141",
- "46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b",
- },
- {
- KM_EC_CURVE_P_256, "04"
- "809f04289c64348c01515eb03d5ce7ac1a8cb9498f5caa50197e58d43a86a7ae"
- "b29d84e811197f25eba8f5194092cb6ff440e26d4421011372461f579271cda3",
- // https://tools.ietf.org/html/rfc5915
- "30770201010420" // DER-encodeded EC private key header
- "38f65d6dce47676044d58ce5139582d568f64bb16098d179dbab07741dd5caf5" // private key
- "a00a06082a8648ce3d030107a144034200" // DER-encoded curve OID,
- "04"
- "119f2f047902782ab0c9e27a54aff5eb9b964829ca99c06b02ddba95b0a3f6d0"
- "8f52b726664cac366fc98ac7a012b2682cbd962e5acb544671d41b9445704d1d",
- "057d636096cb80b67a8c038c890e887d1adfa4195e9b3ce241c8a778c59cda67",
- },
- {
- KM_EC_CURVE_P_256, "04"
- "df3989b9fa55495719b3cf46dccd28b5153f7808191dd518eff0c3cff2b705ed"
- "422294ff46003429d739a33206c8752552c8ba54a270defc06e221e0feaf6ac4",
- // https://tools.ietf.org/html/rfc5915
- "30770201010420" // DER-encodeded EC private key header
- "207c43a79bfee03db6f4b944f53d2fb76cc49ef1c9c4d34d51b6c65c4db6932d" // private key
- "a00a06082a8648ce3d030107a144034200" // DER-encoded curve OID,
- "04"
- "24277c33f450462dcb3d4801d57b9ced05188f16c28eda873258048cd1607e0d"
- "c4789753e2b1f63b32ff014ec42cd6a69fac81dfe6d0d6fd4af372ae27c46f88",
- "96441259534b80f6aee3d287a6bb17b5094dd4277d9e294f8fe73e48bf2a0024",
- },
-};
-
-/**
- * Test that key exchange works with NIST test vectors.
- */
-TEST(NistCurveKeyExchange, NistTestVectors) {
- for (auto& test : kNistCurveTests) {
- string private_key = hex2str(test.my_private_key);
- string shared_secret = hex2str(test.shared_secret);
-
- const uint8_t* private_key_data = reinterpret_cast<const uint8_t*>(private_key.data());
- UniquePtr<EC_KEY, EC_KEY_Delete> ec_key(
- d2i_ECPrivateKey(nullptr, &private_key_data, private_key.size()));
- ASSERT_TRUE(ec_key.get() && EC_KEY_check_key(ec_key.get()));
-
- keymaster_error_t error;
- NistCurveKeyExchange* key_exchange = new NistCurveKeyExchange(ec_key.release(), &error);
- EXPECT_EQ(KM_ERROR_OK, error);
- ASSERT_TRUE(key_exchange != nullptr);
-
- Buffer computed_shared_secret;
- string peer_public_key = hex2str(test.peer_public_key);
- ASSERT_TRUE(key_exchange->CalculateSharedKey(
- reinterpret_cast<const uint8_t*>(peer_public_key.data()), peer_public_key.size(),
- &computed_shared_secret));
- EXPECT_EQ(shared_secret.size(), computed_shared_secret.available_read());
- EXPECT_EQ(0, memcmp(shared_secret.data(), computed_shared_secret.peek_read(),
- shared_secret.size()));
-
- for (size_t i = 0; i < peer_public_key.size(); i++) {
- // randomly flip some bits in the peer public key to make it invalid
- peer_public_key[i] ^= 0xff;
- ASSERT_FALSE(key_exchange->CalculateSharedKey(
- reinterpret_cast<const uint8_t*>(peer_public_key.data()), peer_public_key.size(),
- &computed_shared_secret));
- }
- }
-}
-
-} // namespace test
-} // namespace keymaster
diff --git a/unit_test/openssl_utils.h b/unit_test/openssl_utils.h
deleted file mode 100644
index 9fa6ec1..0000000
--- a/unit_test/openssl_utils.h
+++ b/dev/null
@@ -1,100 +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_KEYMASTER_OPENSSL_UTILS_H_
-#define SYSTEM_KEYMASTER_OPENSSL_UTILS_H_
-
-#include <openssl/bn.h>
-#include <openssl/ec.h>
-#include <openssl/engine.h>
-#include <openssl/evp.h>
-#include <openssl/rsa.h>
-#include <openssl/x509.h>
-
-#include <UniquePtr.h>
-
-#include <hardware/keymaster_defs.h>
-
-namespace keymaster {
-
-struct KeymasterKeyBlob;
-
-class EvpMdCtxCleaner {
- public:
- explicit EvpMdCtxCleaner(EVP_MD_CTX* ctx) : ctx_(ctx) {}
- ~EvpMdCtxCleaner() { EVP_MD_CTX_cleanup(ctx_); }
-
- private:
- EVP_MD_CTX* ctx_;
-};
-
-template <typename T, void (*FreeFunc)(T*)> struct OpenSslObjectDeleter {
- void operator()(T* p) { FreeFunc(p); }
-};
-
-#define DEFINE_OPENSSL_OBJECT_POINTER(name) \
- typedef OpenSslObjectDeleter<name, name##_free> name##_Delete; \
- typedef UniquePtr<name, name##_Delete> name##_Ptr;
-
-DEFINE_OPENSSL_OBJECT_POINTER(ASN1_BIT_STRING)
-DEFINE_OPENSSL_OBJECT_POINTER(ASN1_INTEGER)
-DEFINE_OPENSSL_OBJECT_POINTER(ASN1_OBJECT)
-DEFINE_OPENSSL_OBJECT_POINTER(ASN1_OCTET_STRING)
-DEFINE_OPENSSL_OBJECT_POINTER(ASN1_TIME)
-DEFINE_OPENSSL_OBJECT_POINTER(BN_CTX)
-DEFINE_OPENSSL_OBJECT_POINTER(EC_GROUP)
-DEFINE_OPENSSL_OBJECT_POINTER(EC_KEY)
-DEFINE_OPENSSL_OBJECT_POINTER(EC_POINT)
-DEFINE_OPENSSL_OBJECT_POINTER(ENGINE)
-DEFINE_OPENSSL_OBJECT_POINTER(EVP_PKEY)
-DEFINE_OPENSSL_OBJECT_POINTER(PKCS8_PRIV_KEY_INFO)
-DEFINE_OPENSSL_OBJECT_POINTER(RSA)
-DEFINE_OPENSSL_OBJECT_POINTER(X509)
-DEFINE_OPENSSL_OBJECT_POINTER(X509_EXTENSION)
-DEFINE_OPENSSL_OBJECT_POINTER(X509_NAME)
-
-typedef OpenSslObjectDeleter<BIGNUM, BN_free> BIGNUM_Delete;
-typedef UniquePtr<BIGNUM, BIGNUM_Delete> BIGNUM_Ptr;
-
-keymaster_error_t ec_get_group_size(const EC_GROUP* group, size_t* key_size_bits);
-EC_GROUP* ec_get_group(keymaster_ec_curve_t curve);
-
-/**
- * Many OpenSSL APIs take ownership of an argument on success but don't free the argument on
- * failure. This means we need to tell our scoped pointers when we've transferred ownership, without
- * triggering a warning by not using the result of release().
- */
-template <typename T, typename Delete_T>
-inline void release_because_ownership_transferred(UniquePtr<T, Delete_T>& p) {
- T* val __attribute__((unused)) = p.release();
-}
-
-keymaster_error_t convert_pkcs8_blob_to_evp(const uint8_t* key_data, size_t key_length,
- keymaster_algorithm_t expected_algorithm,
- UniquePtr<EVP_PKEY, EVP_PKEY_Delete>* pkey);
-
-keymaster_error_t KeyMaterialToEvpKey(keymaster_key_format_t key_format,
- const KeymasterKeyBlob& key_material,
- keymaster_algorithm_t expected_algorithm,
- UniquePtr<EVP_PKEY, EVP_PKEY_Delete>* evp_pkey);
-
-keymaster_error_t EvpKeyToKeyMaterial(const EVP_PKEY* evp_pkey, KeymasterKeyBlob* key_blob);
-
-size_t ec_group_size_bits(EC_KEY* ec_key);
-
-} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_OPENSSL_UTILS_H_
diff --git a/unit_test/sw_rsa_attest_root.key.pem b/unit_test/sw_rsa_attest_root.key.pem
deleted file mode 100644
index 387a852..0000000
--- a/unit_test/sw_rsa_attest_root.key.pem
+++ b/dev/null
@@ -1,15 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIICXQIBAAKBgQCia63rbi5EYe/VDoLmt5TRdSMfd5tjkWP/96r/C3JHTsAsQ+wz
-fNes7UA+jCigZtX3hwszl94OuE4TQKuvpSe/lWmgMdsGUmX4RFlXYfC78hdLt0GA
-ZMAoDo9Sd47b0ke2RekZyOmLw9vCkT/X11DEHTVm+Vfkl5YLCazOkjWFmwIDAQAB
-AoGAU8dxXchmqzVNbbvff7zgUa63YErk51Yem/EXzhkMaIXRkMO0edaCtZtnkRvg
-9OQ2qEiLWaCTlUoyU7H/HUn2lwTQsOXyZI7dHijVDRMIv1mmrHCrGW/JC8FXfPLS
-r3L3KoHXQVYL2mslbR8Rpogxq4WwnwK6XqSTH9mynFwQwEkCQQDMX3EZk3ricWVH
-ruXD0BpXOMMpZuLu4rg5+1L51WEJvItIMeSjLuNa+g3AI8AYTYYi/aSLk6XEv82L
-iXFGmJ2XAkEAy3M8k8Z0QzHae4olduqoHVWEarBtDE+fqFQBWgdm8fZhdHWrvlAc
-qwJIXMUVc+dWm/FAQarCjbqWqhCRdaYgnQJBAJ7z7GdUCVNtlrQ2F4ZAqPwFreTZ
-nM7njxmpm1Os3hhQiJPSGl3A7huoOGGkbJd6VEWKuRvF7jwkYZ2RfITH1mkCQAvh
-X9E1Toa5+4spRwTJsSV9X+0m/kcwwx7+QNH0CrPockptsKi9Xt8xk+4u6BDLmogi
-r2DmStQh6DhoHUZkfBUCQQCOgBkqH/15drpdR+BQH3VaP4/ALFfxR9E3G+lS+M5a
-IqJEk9kh8vjuGzTaAZyU5keUmpWNc1gI7OvDMaH4+8vQ
------END RSA PRIVATE KEY-----