From 5f98c979d780115f85f8c815e57a620b73471bfc Mon Sep 17 00:00:00 2001 From: Xindong Xu Date: Mon, 27 Apr 2020 01:42:41 +0000 Subject: keymaster: sync to ref q 2e847b99eabc67bc7ba1fccb77d7aa3399eb7d75 Change-Id: I37fbba12c99ce802dd1f636d1b69922ab037875e --- 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 +#include +#include +#include +#include + +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(value); +} + +inline hw_authenticator_type_t legacy_enum_conversion(const HardwareAuthenticatorType value) { + return static_cast(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& 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 kmBlob2hidlVec(const keymaster_key_blob_t& blob) { + hidl_vec result; + result.setToExternal(const_cast(blob.key_material), blob.key_material_size); + return result; +} + +inline hidl_vec kmBlob2hidlVec(const keymaster_blob_t& blob) { + hidl_vec result; + result.setToExternal(const_cast(blob.data), blob.data_length); + return result; +} + +inline hidl_vec kmBuffer2hidlVec(const ::keymaster::Buffer& buf) { + hidl_vec result; + result.setToExternal(const_cast(buf.peek_read()), buf.available_read()); + return result; +} + +inline static hidl_vec> kmCertChain2Hidl( + const keymaster_cert_chain_t& cert_chain) { + hidl_vec> 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 kmParamSet2Hidl(const keymaster_key_param_set_t& set) { + hidl_vec 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(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& clientId, const hidl_vec& 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 AmlogicKeymaster4Device::getHardwareInfo(getHardwareInfo_cb _hidl_cb) { + _hidl_cb(SecurityLevel::TRUSTED_ENVIRONMENT, "AmlogicKeymaster", "Google"); + return Void(); +} + +Return 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(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 AmlogicKeymaster4Device::computeSharedHmac( + const hidl_vec& 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 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 AmlogicKeymaster4Device::verifyAuthorization( + uint64_t challenge, const hidl_vec& 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 AmlogicKeymaster4Device::addRngEntropy(const hidl_vec& 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 AmlogicKeymaster4Device::generateKey(const hidl_vec& keyParams, + generateKey_cb _hidl_cb) { + GenerateKeyRequest request; + request.key_description.Reinitialize(KmParamSet(keyParams)); + + GenerateKeyResponse response; + impl_->GenerateKey(request, &response); + + KeyCharacteristics resultCharacteristics; + hidl_vec 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 AmlogicKeymaster4Device::getKeyCharacteristics(const hidl_vec& keyBlob, + const hidl_vec& clientId, + const hidl_vec& 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 AmlogicKeymaster4Device::importKey(const hidl_vec& params, + KeyFormat keyFormat, + const hidl_vec& 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 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 AmlogicKeymaster4Device::importWrappedKey( + const hidl_vec& wrappedKeyData, const hidl_vec& wrappingKeyBlob, + const hidl_vec& maskingKey, const hidl_vec& 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 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 AmlogicKeymaster4Device::exportKey(KeyFormat exportFormat, + const hidl_vec& keyBlob, + const hidl_vec& clientId, + const hidl_vec& 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 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 AmlogicKeymaster4Device::attestKey(const hidl_vec& keyToAttest, + const hidl_vec& 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> resultCertChain; + if (response.error == KM_ERROR_OK) { + resultCertChain = kmCertChain2Hidl(response.certificate_chain); + } + _hidl_cb(legacy_enum_conversion(response.error), resultCertChain); + return Void(); +} + +Return AmlogicKeymaster4Device::upgradeKey(const hidl_vec& keyBlobToUpgrade, + const hidl_vec& 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()); + } + return Void(); +} + +Return AmlogicKeymaster4Device::deleteKey(const hidl_vec& keyBlob) { + DeleteKeyRequest request; + request.SetKeyMaterial(keyBlob.data(), keyBlob.size()); + + DeleteKeyResponse response; + impl_->DeleteKey(request, &response); + + return legacy_enum_conversion(response.error); +} + +Return AmlogicKeymaster4Device::deleteAllKeys() { + DeleteAllKeysRequest request; + DeleteAllKeysResponse response; + impl_->DeleteAllKeys(request, &response); + + return legacy_enum_conversion(response.error); +} + +Return AmlogicKeymaster4Device::destroyAttestationIds() { + return ErrorCode::UNIMPLEMENTED; +} + +Return AmlogicKeymaster4Device::begin(KeyPurpose purpose, const hidl_vec& key, + const hidl_vec& 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 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 AmlogicKeymaster4Device::update(uint64_t operationHandle, + const hidl_vec& inParams, + const hidl_vec& input, + const HardwareAuthToken& authToken, + const VerificationToken& verificationToken, + update_cb _hidl_cb) { + (void)authToken; + (void)verificationToken; + UpdateOperationRequest request; + UpdateOperationResponse response; + hidl_vec resultParams; + hidl_vec 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 AmlogicKeymaster4Device::finish(uint64_t operationHandle, + const hidl_vec& inParams, + const hidl_vec& input, + const hidl_vec& 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 resultParams; + hidl_vec 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 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 +#include +#include +#include +#include + +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 -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<'5ah,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* 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 '!Ǹ}xnO}orgȢ}c - ?G5 q}#w($@{2 -˾L*~e)Y:o_XGJDlr - KhQK$O9O:I8JD|6H(|HH |HhfODDDO6wD'D4@T@Do@7DN7GND4D~@4DNt$Db@2DN2rD .DU@5DNuUVD7Dn@7DN7GD +D ND^O&GDf:DBDYObDb 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!@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?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 eO0NN 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 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ڥNNnHN>lN>ncfIWJ}{視|BH{טּTAuX~qceIVJ}{視|AH{טּS@tH~Lppr(tHvh  s~xpGSHA512 block transform for ARMv4/NEON, CRYPTOGAMS by - - 0S͂aQna -be` -b\A -@HPa!@!BN.D(TA@r!t!&NA#1 t@H&ADt - -"n/J -V!BaFa -0 Bx¨th:@zhvvh8Hth@~hvhz(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؅F~(rrH0j:H<؅f|jH4H>ftpp(rN؅F~(rrH0j:H<؅f|jH4H>ftpp(rNpG@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)F(F\@F"YFfE; + "9F(F? + + +F #DiB +K {D;:4F + +@K#@, -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 -,`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+ +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:zS@+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## {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@# -! +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`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? @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 -So(>e> #o F > >F -MFF K}DT - -L -N M|D K~D}D0FX*F3K0*FXp@+ - -DFO -o -FFFo f (FfB. o8f -o #`[>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 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(# -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,>C#,>C,>>BB>B"\@ +CYFU@! +@0+ 0+0# +0# 0#0+ +=pfC -\, "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$>[ 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  -AyC -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@PEO - -@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 FO14  + +,!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\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$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`DHFQ2F1) -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 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<VtX@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@ 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 xR>x2| -j -{* - p'd'_0 lb^xGf -kG| -ෑJ .MfOʜ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]ė*lFBWP5MϺ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;>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*~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<'5ah,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 +*h8,4$_@r %(IXkq'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 +*"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 +*"$8,4_@r %<(I A9q ޳؜Vd{a2plHt\BWaes_nohw_encrypt +XE,?k:AOgst"57unGq)ʼnobV>Ky xZݨ31Y'_`QJ -zɜ;M*?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 >>>>#>)>/>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 >>>>#>)>/>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?~?@Ն@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 xT>x2| +YG=6D^:հ5mp?LPiBl)+18{k Ψ`%cfc}Ҵ#ZoAsu0RhEf;SMfOʜ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]ė*lFBWP5MϺ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;>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 + + + + + + + + + + + + + + + 123456789 + amlogic + amlogic + amlogic + amlogic + franklin +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 +#include +#include +#include +#include + +#if AMLOGIC_MODIFY +#include + +#include +#include +#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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#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::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(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(malloc(size)); - if (tmp) { - memcpy(tmp, buffer, size); - } - return tmp; -} - -template -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 hash_buf(new (std::nothrow) uint8_t[SHA256_DIGEST_LENGTH + 1]); - UniquePtr 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 hash_buf(new (std::nothrow) uint8_t[SHA256_DIGEST_LENGTH + 1]); - UniquePtr 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( - 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(const_cast(dev)); -} - -/* static */ -int AmlKeymasterDevice::close_device(hw_device_t* dev) { - delete reinterpret_cast(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 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 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 -#include - -extern "C" { -#include -} - -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 -#include -#include -#include - -#include - -#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 -} - -__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 +#include +#if AMLOGIC_MODIFY +#include + +extern "C" { +#include +} +#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 +#include +#include + +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 getHardwareInfo(getHardwareInfo_cb _hidl_cb) override; + Return getHmacSharingParameters(getHmacSharingParameters_cb _hidl_cb) override; + Return computeSharedHmac(const hidl_vec& params, + computeSharedHmac_cb) override; + Return verifyAuthorization(uint64_t challenge, + const hidl_vec& parametersToVerify, + const HardwareAuthToken& authToken, + verifyAuthorization_cb _hidl_cb) override; + Return addRngEntropy(const hidl_vec& data) override; + Return generateKey(const hidl_vec& keyParams, + generateKey_cb _hidl_cb) override; + Return getKeyCharacteristics(const hidl_vec& keyBlob, + const hidl_vec& clientId, + const hidl_vec& appData, + getKeyCharacteristics_cb _hidl_cb) override; + Return importKey(const hidl_vec& params, KeyFormat keyFormat, + const hidl_vec& keyData, importKey_cb _hidl_cb) override; + Return importWrappedKey(const hidl_vec& wrappedKeyData, + const hidl_vec& wrappingKeyBlob, + const hidl_vec& maskingKey, + const hidl_vec& unwrappingParams, + uint64_t passwordSid, uint64_t biometricSid, + importWrappedKey_cb _hidl_cb) override; + Return exportKey(KeyFormat exportFormat, const hidl_vec& keyBlob, + const hidl_vec& clientId, const hidl_vec& appData, + exportKey_cb _hidl_cb) override; + Return attestKey(const hidl_vec& keyToAttest, + const hidl_vec& attestParams, + attestKey_cb _hidl_cb) override; + Return upgradeKey(const hidl_vec& keyBlobToUpgrade, + const hidl_vec& upgradeParams, + upgradeKey_cb _hidl_cb) override; + Return deleteKey(const hidl_vec& keyBlob) override; + Return deleteAllKeys() override; + Return destroyAttestationIds() override; + Return begin(KeyPurpose purpose, const hidl_vec& key, + const hidl_vec& inParams, const HardwareAuthToken& authToken, + begin_cb _hidl_cb) override; + Return update(uint64_t operationHandle, const hidl_vec& inParams, + const hidl_vec& input, const HardwareAuthToken& authToken, + const VerificationToken& verificationToken, update_cb _hidl_cb) override; + Return finish(uint64_t operationHandle, const hidl_vec& inParams, + const hidl_vec& input, const hidl_vec& signature, + const HardwareAuthToken& authToken, + const VerificationToken& verificationToken, finish_cb _hidl_cb) override; + Return 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 + +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 +#include + +extern "C" { +#include +} +__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 +#include +#include +#include +#include + +#include + +#include +#if !AMLOGIC_MODIFY +#include +#endif +#include +#include + +#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(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(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 -#include - -#include -#include - -#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 - -#include - -#include -#include -#include - -#include "android_keymaster_test_utils.h" - -namespace keymaster { -namespace test { - -/** - * Serialize and deserialize a message. - */ -template -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 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 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 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 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 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 rsp(ver); - keymaster_digest_t digests[] = {KM_DIGEST_NONE, KM_DIGEST_MD5, KM_DIGEST_SHA1}; - rsp.error = KM_ERROR_OK; - rsp.SetResults(digests); - - UniquePtr> 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 deserialized(round_trip(ver, msg, 4)); - } -} - -TEST(RoundTrip, DeleteAllKeysRequest) { - for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) { - DeleteAllKeysRequest msg(ver); - UniquePtr deserialized(round_trip(ver, msg, 0)); - } -} - -TEST(RoundTrip, DeleteAllKeysResponse) { - for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) { - DeleteAllKeysResponse msg(ver); - UniquePtr deserialized(round_trip(ver, msg, 4)); - } -} - -TEST(RoundTrip, GetVersionRequest) { - GetVersionRequest msg; - - size_t size = msg.SerializedSize(); - ASSERT_EQ(0U, size); - - UniquePtr 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 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 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 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 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 deserialized(round_trip(ver, msg, 4)); - } -} - -TEST(RoundTrip, AbortOperationRequest) { - for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) { - AbortOperationRequest msg(ver); - UniquePtr deserialized(round_trip(ver, msg, 8)); - } -} - -TEST(RoundTrip, AbortOperationResponse) { - for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) { - AbortOperationResponse msg(ver); - UniquePtr 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 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 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 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 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 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 buf(new uint8_t[kBufSize]); - for (size_t i = 0; i < kBufSize; ++i) - buf[i] = static_cast(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(); } - -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>(); -} -#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 -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#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 vector make_vector(const T* array, size_t len) { - return vector(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(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(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 key_sizes = {224, 256, 384, 521}; - vector 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(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(pubkey.data()); - unique_ptr 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(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(pubkey.data()); - unique_ptr 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(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 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 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(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 file_begin(file_stream); - istreambuf_iterator 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(exported.data()); - unique_ptr pkey( - d2i_PUBKEY(nullptr /* alloc new */, &p, exported.size())); - unique_ptr rsa(EVP_PKEY_get1_RSA(pkey.get())); - - size_t modulus_len = BN_num_bytes(rsa->n); - ASSERT_EQ(256U / 8, modulus_len); - unique_ptr 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(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(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(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(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(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("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(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(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(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(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(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(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(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(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 - -#include - -#include -#include - -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(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(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(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(), ¶ms, &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(key_material.c_str()), - key_material.length()}; - return device()->import_key(device(), ¶ms, 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(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(out_tmp.data), out_tmp.data_length); - free(const_cast(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(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(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(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(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(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(blob_.key_material)); - blob_.key_material = NULL; -} - -void Keymaster2Test::corrupt_key_blob() { - assert(blob_.key_material); - uint8_t* tmp = const_cast(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(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(dev); - const keymaster1_device_t* wrapped_device = wrapper->wrapped_device_; - delete wrapper; - return wrapped_device->common.close(const_cast(&wrapped_device->common)); - } - - static const keymaster1_device_t* unwrap(const keymaster1_device_t* dev) { - return reinterpret_cast(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 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( - 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 - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -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 -bool contains(const AuthorizationSet& set, TypedEnumTag tag, - KeymasterEnum val) { - int pos = set.find(tag); - return pos != -1 && static_cast(set[pos].enumerated) == val; -} - -template -bool contains(const AuthorizationSet& set, TypedEnumTag tag, - KeymasterEnum val) { - int pos = -1; - while ((pos = set.find(tag, pos)) != -1) - if (static_cast(set[pos].enumerated) == val) - return true; - return false; -} - -template -bool contains(const AuthorizationSet& set, TypedTag tag, uint32_t val) { - int pos = set.find(tag); - return pos != -1 && set[pos].integer == val; -} - -template -bool contains(const AuthorizationSet& set, TypedTag tag, uint32_t val) { - int pos = -1; - while ((pos = set.find(tag, pos)) != -1) - if (set[pos].integer == val) - return true; - return false; -} - -template -bool contains(const AuthorizationSet& set, TypedTag tag, uint64_t val) { - int pos = set.find(tag); - return pos != -1 && set[pos].long_integer == val; -} - -template -bool contains(const AuthorizationSet& set, TypedTag tag, const std::string& val) { - int pos = set.find(tag); - return pos != -1 && - std::string(reinterpret_cast(set[pos].blob.data), - set[pos].blob.data_length) == val; -} - -template -bool contains(const AuthorizationSet& set, TypedTag tag, const std::string& val) { - int pos = set.find(tag); - return pos != -1 && - std::string(reinterpret_cast(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(data), length); -} - -template 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 InstanceCreatorPtr; - -const uint64_t OP_HANDLE_SENTINEL = 0xFFFFFFFFFFFFFFFF; -class Keymaster2Test : public testing::TestWithParam { - 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 - bool ResponseContains(const std::vector& expected, const T* values, size_t len) { - return expected.size() == len && - std::is_permutation(values, values + len, expected.begin()); - } - - template 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("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(dev->context); - return wrapper->device_; - } - - static void increment(const keymaster0_device_t* dev) { - Keymaster0CountingWrapper* wrapper = - reinterpret_cast(dev->context); - wrapper->counter_++; - } - - static int counting_close_device(hw_device_t* dev) { - keymaster0_device_t* k0_dev = reinterpret_cast(dev); - increment(k0_dev); - Keymaster0CountingWrapper* wrapper = - reinterpret_cast(k0_dev->context); - int retval = - wrapper->device_->common.close(reinterpret_cast(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 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 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 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 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 -#include -#include // for time_t. - -#include - -#include -#include - -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 inline size_t array_size(const T(&a)[N]) { - return sizeof(a); -} - -/** - * Return the number of elements in array \p a. - */ -template 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 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 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 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 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 explicit Eraser(T* t); - - template - explicit Eraser(T& t) - : buf_(reinterpret_cast(&t)), size_(sizeof(t)) {} - - template explicit Eraser(uint8_t(&arr)[N]) : buf_(arr), size_(N) {} - - Eraser(void* buf, size_t size) : buf_(static_cast(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 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 T ntoh(T t) { - const uint8_t* byte_ptr = reinterpret_cast(&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 T hton(T t) { - T retval; - uint8_t* byte_ptr = reinterpret_cast(&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(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(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 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 - -#include - -#include "openssl_err.h" -#include "openssl_utils.h" - -#include -#include - -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 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 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 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 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* asn1_key_desc, - size_t* asn1_key_desc_len) { - assert(asn1_key_desc && asn1_key_desc_len); - - UniquePtr 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 -static bool get_enum(const ASN1_INTEGER* asn1_int, TypedEnumTag tag, - AuthorizationSet* auth_list) { - if (!asn1_int) - return true; - return auth_list->push_back(tag, static_cast(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 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 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( - ASN1_ENUMERATED_get(record->attestation_security_level)); - *keymaster_version = ASN1_INTEGER_get(record->keymaster_version); - *keymaster_security_level = static_cast( - 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 - -#include - -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* 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 - -#include - -#include - -#include "android_keymaster_test_utils.h" -#include "attestation_record.h" - -#include - -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 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(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 - -#include -#include - -#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(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 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 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 buf(new uint8_t[size]); - EXPECT_EQ(buf.get() + size, set.Serialize(buf.get(), buf.get() + size)); - *reinterpret_cast(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 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 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 -#include - -#include -#include - -#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 - -#include - -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 -#include - -#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(key.data()), key.size(), - reinterpret_cast(salt.data()), salt.size())); - ASSERT_TRUE(hkdf.GenerateKey(reinterpret_cast(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 -#include - -#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(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(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 -#include - -#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(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 -#include - -#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(key.data()), key.size())); - ASSERT_TRUE(kdf2.GenerateKey(reinterpret_cast(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 - -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 - -#include - -#include -#include - -#include -#include -#include - -#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(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(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(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 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(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 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(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 buf(new uint8_t[kBufSize]); - for (size_t i = 0; i < kBufSize; ++i) - buf[i] = static_cast(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 - -#include -#include -#include -#include - -#include -#include - -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* 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 - -#include -#include -#include -#include - -#include -#include - -#include -#include - -#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_; - 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 - -#include - -#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 -#include -#include - -#include -#include -#include - -#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(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(-1); - keymaster_purpose_t invalidPurpose2 = static_cast(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(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(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(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(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(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(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(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(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(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(HW_AUTH_PASSWORD)); - token.timestamp = hton(static_cast(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(HW_AUTH_PASSWORD)); - token.timestamp = hton(static_cast(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("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 - -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 ""; -} -#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 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 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 -#include - -#include -#include - -#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(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(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 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(private_key.data()); - UniquePtr 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(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(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 -#include -#include -#include -#include -#include - -#include - -#include - -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 struct OpenSslObjectDeleter { - void operator()(T* p) { FreeFunc(p); } -}; - -#define DEFINE_OPENSSL_OBJECT_POINTER(name) \ - typedef OpenSslObjectDeleter name##_Delete; \ - typedef UniquePtr 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_Delete; -typedef UniquePtr 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 -inline void release_because_ownership_transferred(UniquePtr& 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* pkey); - -keymaster_error_t KeyMaterialToEvpKey(keymaster_key_format_t key_format, - const KeymasterKeyBlob& key_material, - keymaster_algorithm_t expected_algorithm, - UniquePtr* 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----- -- cgit