| // Copyright 2023 The ChromiumOS Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "arc/keymint/conversion.h" | |
| #include <algorithm> | |
| #include <utility> | |
| namespace arc::keymint { | |
| namespace { | |
| class KmParamSet { | |
| public: | |
| explicit KmParamSet( | |
| const std::vector<arc::mojom::keymint::KeyParameterPtr>& data) { | |
| param_set_.params = new keymaster_key_param_t[data.size()]; | |
| param_set_.length = data.size(); | |
| for (size_t i = 0; i < data.size(); ++i) { | |
| keymaster_tag_t tag = ConvertEnum(data[i]->tag); | |
| switch (keymaster_tag_get_type(tag)) { | |
| case KM_ENUM: | |
| case KM_ENUM_REP: | |
| param_set_.params[i] = ConvertEnum(data[i]); | |
| break; | |
| case KM_UINT: | |
| case KM_UINT_REP: | |
| if (data[i]->value->is_integer()) { | |
| param_set_.params[i] = | |
| keymaster_param_int(tag, data[i]->value->get_integer()); | |
| } else { | |
| param_set_.params[i].tag = KM_TAG_INVALID; | |
| } | |
| break; | |
| case KM_ULONG: | |
| case KM_ULONG_REP: | |
| if (data[i]->value->is_long_integer()) { | |
| param_set_.params[i] = | |
| keymaster_param_long(tag, data[i]->value->get_long_integer()); | |
| } else { | |
| param_set_.params[i].tag = KM_TAG_INVALID; | |
| } | |
| break; | |
| case KM_DATE: | |
| if (data[i]->value->is_date_time()) { | |
| param_set_.params[i] = | |
| keymaster_param_date(tag, data[i]->value->get_date_time()); | |
| } else { | |
| param_set_.params[i].tag = KM_TAG_INVALID; | |
| } | |
| break; | |
| case KM_BOOL: | |
| if (data[i]->value->is_bool_value() && | |
| data[i]->value->get_bool_value()) { | |
| // This function takes a single argument. Default value is TRUE. | |
| param_set_.params[i] = keymaster_param_bool(tag); | |
| } else { | |
| param_set_.params[i].tag = KM_TAG_INVALID; | |
| } | |
| break; | |
| case KM_BIGNUM: | |
| case KM_BYTES: | |
| if (data[i]->value->is_blob()) { | |
| param_set_.params[i] = | |
| keymaster_param_blob(tag, data[i]->value->get_blob().data(), | |
| data[i]->value->get_blob().size()); | |
| } else { | |
| param_set_.params[i].tag = KM_TAG_INVALID; | |
| } | |
| break; | |
| case KM_INVALID: | |
| default: | |
| param_set_.params[i].tag = KM_TAG_INVALID; | |
| // just skip | |
| break; | |
| } | |
| } | |
| } | |
| KmParamSet(KmParamSet&& other) | |
| : param_set_{other.param_set_.params, other.param_set_.length} { | |
| other.param_set_.length = 0; | |
| other.param_set_.params = nullptr; | |
| } | |
| KmParamSet(const KmParamSet&) = delete; | |
| KmParamSet& operator=(const KmParamSet&) = delete; | |
| ~KmParamSet() { delete[] param_set_.params; } | |
| inline const keymaster_key_param_set_t& param_set() const { | |
| return param_set_; | |
| } | |
| private: | |
| keymaster_key_param_set_t param_set_; | |
| }; | |
| } // namespace | |
| std::vector<uint8_t> authToken2AidlVec( | |
| const arc::mojom::keymint::HardwareAuthToken& token) { | |
| static_assert( | |
| 1 /* version size */ + sizeof(token.challenge) + sizeof(token.user_id) + | |
| sizeof(token.authenticator_id) + | |
| sizeof(token.authenticator_type) + sizeof(*token.timestamp) + | |
| 32 /* HMAC size */ | |
| == sizeof(hw_auth_token_t), | |
| "HardwareAuthToken content size does not match hw_auth_token_t size"); | |
| std::vector<uint8_t> result; | |
| if (token.mac.size() != 32) { | |
| return result; | |
| } | |
| result.resize(sizeof(hw_auth_token_t)); | |
| auto pos = result.begin(); | |
| *pos++ = 0; // Version byte | |
| pos = copy_bytes_to_iterator(token.challenge, pos); | |
| pos = copy_bytes_to_iterator(token.user_id, pos); | |
| pos = copy_bytes_to_iterator(token.authenticator_id, pos); | |
| pos = copy_bytes_to_iterator( | |
| ::keymaster::hton(static_cast<uint32_t>(token.authenticator_type)), pos); | |
| pos = copy_bytes_to_iterator( | |
| ::keymaster::hton(token.timestamp->milli_seconds), pos); | |
| pos = std::copy(token.mac.data(), token.mac.data() + token.mac.size(), pos); | |
| return result; | |
| } | |
| // TODO(b/274723521) : Add more required ConvertEnum functions for KeyMint | |
| // Server. | |
| keymaster_tag_t ConvertEnum(arc::mojom::keymint::Tag tag) { | |
| return static_cast<keymaster_tag_t>(tag); | |
| } | |
| arc::mojom::keymint::Tag ConvertKeymasterTag(keymaster_tag_t tag) { | |
| return static_cast<arc::mojom::keymint::Tag>(tag); | |
| } | |
| keymaster_key_format_t ConvertEnum(arc::mojom::keymint::KeyFormat key_format) { | |
| return static_cast<keymaster_key_format_t>(key_format); | |
| } | |
| keymaster_purpose_t ConvertEnum(arc::mojom::keymint::KeyPurpose key_purpose) { | |
| return static_cast<keymaster_purpose_t>(key_purpose); | |
| } | |
| keymaster_key_param_t kInvalidKeyParam{.tag = KM_TAG_INVALID, .integer = 0}; | |
| keymaster_key_param_t ConvertEnum( | |
| const arc::mojom::keymint::KeyParameterPtr& param) { | |
| if (param.is_null() || param->value.is_null()) { | |
| return kInvalidKeyParam; | |
| } | |
| keymaster_tag_t tag = ConvertEnum(param->tag); | |
| switch (tag) { | |
| case KM_TAG_PURPOSE: | |
| if (param->value->is_key_purpose() && | |
| param->value->get_key_purpose() != | |
| arc::mojom::keymint::KeyPurpose::UNKNOWN) { | |
| return keymaster_param_enum( | |
| tag, static_cast<uint32_t>(param->value->get_key_purpose())); | |
| } else { | |
| return kInvalidKeyParam; | |
| } | |
| break; | |
| case KM_TAG_ALGORITHM: | |
| if (param->value->is_algorithm() && | |
| param->value->get_algorithm() != | |
| arc::mojom::keymint::Algorithm::UNKNOWN) { | |
| return keymaster_param_enum( | |
| tag, static_cast<uint32_t>(param->value->get_algorithm())); | |
| } else { | |
| return kInvalidKeyParam; | |
| } | |
| break; | |
| case KM_TAG_BLOCK_MODE: | |
| if (param->value->is_block_mode() && | |
| param->value->get_block_mode() != | |
| arc::mojom::keymint::BlockMode::UNKNOWN) { | |
| return keymaster_param_enum( | |
| tag, static_cast<uint32_t>(param->value->get_block_mode())); | |
| } else { | |
| return kInvalidKeyParam; | |
| } | |
| break; | |
| case KM_TAG_DIGEST: | |
| case KM_TAG_RSA_OAEP_MGF_DIGEST: | |
| if (param->value->is_digest() && | |
| param->value->get_digest() != arc::mojom::keymint::Digest::UNKNOWN) { | |
| return keymaster_param_enum( | |
| tag, static_cast<uint32_t>(param->value->get_digest())); | |
| } else { | |
| return kInvalidKeyParam; | |
| } | |
| break; | |
| case KM_TAG_PADDING: | |
| if (param->value->is_padding_mode() && | |
| param->value->get_padding_mode() != | |
| arc::mojom::keymint::PaddingMode::UNKNOWN) { | |
| return keymaster_param_enum( | |
| tag, static_cast<uint32_t>(param->value->get_padding_mode())); | |
| } else { | |
| return kInvalidKeyParam; | |
| } | |
| break; | |
| case KM_TAG_EC_CURVE: | |
| if (param->value->is_ec_curve() && | |
| param->value->get_ec_curve() != | |
| arc::mojom::keymint::EcCurve::UNKNOWN) { | |
| return keymaster_param_enum( | |
| tag, static_cast<uint32_t>(param->value->get_ec_curve())); | |
| } else { | |
| return kInvalidKeyParam; | |
| } | |
| break; | |
| case KM_TAG_USER_AUTH_TYPE: | |
| if (param->value->is_hardware_authenticator_type() && | |
| param->value->get_hardware_authenticator_type() != | |
| arc::mojom::keymint::HardwareAuthenticatorType::UNKNOWN) { | |
| return keymaster_param_enum( | |
| tag, static_cast<uint32_t>( | |
| param->value->get_hardware_authenticator_type())); | |
| } else { | |
| return kInvalidKeyParam; | |
| } | |
| break; | |
| case KM_TAG_ORIGIN: | |
| if (param->value->is_origin() && | |
| param->value->get_origin() != | |
| arc::mojom::keymint::KeyOrigin::UNKNOWN) { | |
| return keymaster_param_enum( | |
| tag, static_cast<uint32_t>(param->value->get_origin())); | |
| } else { | |
| return kInvalidKeyParam; | |
| } | |
| break; | |
| // The 2 Cases below are unused. | |
| case KM_TAG_BLOB_USAGE_REQUIREMENTS: | |
| case KM_TAG_KDF: | |
| default: | |
| CHECK(false) << "Unknown or unused enum tag: Something is broken"; | |
| LOG(ERROR) << "Unknown or unused enum tag: " << tag; | |
| return kInvalidKeyParam; | |
| } | |
| } | |
| std::vector<uint8_t> ConvertFromKeymasterMessage(const uint8_t* data, | |
| const size_t size) { | |
| return std::vector<uint8_t>(data, data + size); | |
| } | |
| std::vector<arc::mojom::keymint::CertificatePtr> ConvertFromKeymasterMessage( | |
| const ::keymaster::CertificateChain& cert_chain) { | |
| std::vector<arc::mojom::keymint::CertificatePtr> out; | |
| if (cert_chain.entry_count == 0 || cert_chain.entries == nullptr) { | |
| return out; | |
| } | |
| out.reserve(cert_chain.entry_count); | |
| for (size_t i = 0; i < cert_chain.entry_count; ++i) { | |
| const auto& entry = cert_chain.entries[i]; | |
| auto cert_vector = | |
| ConvertFromKeymasterMessage(entry.data, entry.data_length); | |
| auto mojo_cert = | |
| arc::mojom::keymint::Certificate::New(std::move(cert_vector)); | |
| out.push_back(std::move(mojo_cert)); | |
| } | |
| return out; | |
| } | |
| arc::mojom::keymint::KeyParameterValuePtr ConvertEnumParamFromKeymasterMessage( | |
| const keymaster_key_param_t& param) { | |
| keymaster_tag_t tag = param.tag; | |
| keymaster_tag_type_t tag_type = keymaster_tag_get_type(tag); | |
| arc::mojom::keymint::KeyParameterValuePtr out; | |
| if (tag_type != KM_ENUM && tag_type != KM_ENUM_REP) { | |
| LOG(ERROR) << "Mismatched Tag type received. Expected ENUM or ENUM_REP"; | |
| return arc::mojom::keymint::KeyParameterValue::NewInvalid( | |
| static_cast<uint32_t>(param.enumerated)); | |
| } | |
| switch (tag) { | |
| case KM_TAG_PURPOSE: | |
| out = arc::mojom::keymint::KeyParameterValue::NewKeyPurpose( | |
| static_cast<arc::mojom::keymint::KeyPurpose>(param.enumerated)); | |
| break; | |
| case KM_TAG_ALGORITHM: | |
| out = arc::mojom::keymint::KeyParameterValue::NewAlgorithm( | |
| static_cast<arc::mojom::keymint::Algorithm>(param.enumerated)); | |
| break; | |
| case KM_TAG_BLOCK_MODE: | |
| out = arc::mojom::keymint::KeyParameterValue::NewBlockMode( | |
| static_cast<arc::mojom::keymint::BlockMode>(param.enumerated)); | |
| break; | |
| case KM_TAG_DIGEST: | |
| case KM_TAG_RSA_OAEP_MGF_DIGEST: | |
| out = arc::mojom::keymint::KeyParameterValue::NewDigest( | |
| static_cast<arc::mojom::keymint::Digest>(param.enumerated)); | |
| break; | |
| case KM_TAG_PADDING: | |
| out = arc::mojom::keymint::KeyParameterValue::NewPaddingMode( | |
| static_cast<arc::mojom::keymint::PaddingMode>(param.enumerated)); | |
| break; | |
| case KM_TAG_EC_CURVE: | |
| out = arc::mojom::keymint::KeyParameterValue::NewEcCurve( | |
| static_cast<arc::mojom::keymint::EcCurve>(param.enumerated)); | |
| break; | |
| case KM_TAG_USER_AUTH_TYPE: | |
| out = | |
| arc::mojom::keymint::KeyParameterValue::NewHardwareAuthenticatorType( | |
| static_cast<arc::mojom::keymint::HardwareAuthenticatorType>( | |
| param.enumerated)); | |
| break; | |
| case KM_TAG_ORIGIN: | |
| out = arc::mojom::keymint::KeyParameterValue::NewOrigin( | |
| static_cast<arc::mojom::keymint::KeyOrigin>(param.enumerated)); | |
| break; | |
| // The 2 Cases below are unused. | |
| case KM_TAG_BLOB_USAGE_REQUIREMENTS: | |
| case KM_TAG_KDF: | |
| default: | |
| CHECK(false) << "Unknown or unused enum tag: Something is broken"; | |
| LOG(ERROR) << "Unknown or unused enum tag: " << tag; | |
| out = arc::mojom::keymint::KeyParameterValue::NewInvalid( | |
| static_cast<uint32_t>(param.enumerated)); | |
| } | |
| return out; | |
| } | |
| std::vector<arc::mojom::keymint::KeyParameterPtr> ConvertFromKeymasterMessage( | |
| const keymaster_key_param_set_t& param_set) { | |
| if (param_set.length == 0 || !param_set.params) { | |
| return std::vector<arc::mojom::keymint::KeyParameterPtr>(); | |
| } | |
| std::vector<arc::mojom::keymint::KeyParameterPtr> out(param_set.length); | |
| const keymaster_key_param_t* params = param_set.params; | |
| for (size_t i = 0; i < param_set.length; ++i) { | |
| keymaster_tag_t tag = params[i].tag; | |
| arc::mojom::keymint::KeyParameterValuePtr param; | |
| switch (keymaster_tag_get_type(tag)) { | |
| case KM_ENUM: | |
| case KM_ENUM_REP: | |
| param = ConvertEnumParamFromKeymasterMessage(params[i]); | |
| break; | |
| case KM_UINT: | |
| case KM_UINT_REP: | |
| param = arc::mojom::keymint::KeyParameterValue::NewInteger( | |
| params[i].integer); | |
| break; | |
| case KM_ULONG: | |
| case KM_ULONG_REP: | |
| param = arc::mojom::keymint::KeyParameterValue::NewLongInteger( | |
| params[i].long_integer); | |
| break; | |
| case KM_DATE: | |
| param = arc::mojom::keymint::KeyParameterValue::NewDateTime( | |
| params[i].date_time); | |
| break; | |
| case KM_BOOL: | |
| param = arc::mojom::keymint::KeyParameterValue::NewBoolValue( | |
| params[i].boolean); | |
| break; | |
| case KM_BIGNUM: | |
| case KM_BYTES: | |
| param = arc::mojom::keymint::KeyParameterValue::NewBlob( | |
| ConvertFromKeymasterMessage(params[i].blob.data, | |
| params[i].blob.data_length)); | |
| break; | |
| case KM_INVALID: | |
| tag = KM_TAG_INVALID; | |
| // just skip | |
| break; | |
| } | |
| out[i] = arc::mojom::keymint::KeyParameter::New( | |
| static_cast<arc::mojom::keymint::Tag>(tag), std::move(param)); | |
| } | |
| return out; | |
| } | |
| arc::mojom::keymint::KeyMintKeyBlobPtr ConvertFromKeyMintKeyBlob( | |
| const ::keymaster::KeymasterKeyBlob& key_blob) { | |
| arc::mojom::keymint::KeyMintKeyBlobPtr out; | |
| if (key_blob.key_material == nullptr || key_blob.key_material_size == 0) { | |
| return out; | |
| } | |
| out = arc::mojom::keymint::KeyMintKeyBlob::New(ConvertFromKeymasterMessage( | |
| key_blob.key_material, key_blob.key_material_size)); | |
| return out; | |
| } | |
| arc::mojom::keymint::KeyMintBlobPtr ConvertFromKeyMintBlob( | |
| const ::keymaster::KeymasterBlob& blob) { | |
| arc::mojom::keymint::KeyMintBlobPtr out; | |
| if (blob.data == nullptr || blob.data_length == 0) { | |
| return out; | |
| } | |
| out = arc::mojom::keymint::KeyMintBlob::New( | |
| ConvertFromKeymasterMessage(blob.data, blob.data_length)); | |
| return out; | |
| } | |
| void ConvertToKeymasterMessage(const std::vector<uint8_t>& data, | |
| ::keymaster::Buffer* out) { | |
| out->Reinitialize(data.data(), data.size()); | |
| } | |
| void ConvertToKeymasterMessage(const std::vector<uint8_t>& clientId, | |
| const std::vector<uint8_t>& appData, | |
| ::keymaster::AuthorizationSet* params) { | |
| params->Clear(); | |
| if (!clientId.empty()) { | |
| params->push_back(::keymaster::TAG_APPLICATION_ID, clientId.data(), | |
| clientId.size()); | |
| } | |
| if (!appData.empty()) { | |
| params->push_back(::keymaster::TAG_APPLICATION_DATA, appData.data(), | |
| appData.size()); | |
| } | |
| } | |
| void ConvertToKeymasterMessage( | |
| const std::vector<arc::mojom::keymint::KeyParameterPtr>& data, | |
| ::keymaster::AuthorizationSet* out) { | |
| KmParamSet param_set(data); | |
| out->Reinitialize(param_set.param_set()); | |
| } | |
| std::vector<arc::mojom::keymint::KeyCharacteristicsPtr> | |
| ConvertKeyCharacteristics(const ::keymaster::AuthorizationSet& hw_enforced, | |
| const ::keymaster::AuthorizationSet& sw_enforced, | |
| bool include_keystore_enforced = true) { | |
| // TODO(b/299981713) : Add conversion for Software Security level. | |
| // The current function makes the assumption that we are not using Software | |
| // Security Level. | |
| std::vector<arc::mojom::keymint::KeyCharacteristicsPtr> key_chars_array; | |
| // KeyMint Enforced Key Characteristics. | |
| auto keyMintEnforcedChars = arc::mojom::keymint::KeyCharacteristics::New( | |
| arc::mojom::keymint::SecurityLevel::TRUSTED_ENVIRONMENT, | |
| ConvertFromKeymasterMessage(hw_enforced)); | |
| if (!keyMintEnforcedChars.is_null() && | |
| !keyMintEnforcedChars->authorizations.empty()) { | |
| key_chars_array.push_back(std::move(keyMintEnforcedChars)); | |
| } | |
| // Keystore Enforced Key characteristics. | |
| auto keystoreEnforcedChars = arc::mojom::keymint::KeyCharacteristics::New( | |
| arc::mojom::keymint::SecurityLevel::KEYSTORE, | |
| ConvertFromKeymasterMessage(sw_enforced)); | |
| if (include_keystore_enforced && !keystoreEnforcedChars.is_null() && | |
| !keystoreEnforcedChars->authorizations.empty()) { | |
| key_chars_array.push_back(std::move(keystoreEnforcedChars)); | |
| } | |
| return key_chars_array; | |
| } | |
| // Request Methods. | |
| std::unique_ptr<::keymaster::GetKeyCharacteristicsRequest> | |
| MakeGetKeyCharacteristicsRequest( | |
| const ::arc::mojom::keymint::GetKeyCharacteristicsRequestPtr& value, | |
| const int32_t keymint_message_version) { | |
| auto out = std::make_unique<::keymaster::GetKeyCharacteristicsRequest>( | |
| keymint_message_version); | |
| out->SetKeyMaterial(value->key_blob.data(), value->key_blob.size()); | |
| ConvertToKeymasterMessage(value->app_id, value->app_data, | |
| &out->additional_params); | |
| return out; | |
| } | |
| std::unique_ptr<::keymaster::GenerateKeyRequest> MakeGenerateKeyRequest( | |
| const arc::mojom::keymint::GenerateKeyRequestPtr& request, | |
| const int32_t keymint_message_version) { | |
| auto out = std::make_unique<::keymaster::GenerateKeyRequest>( | |
| keymint_message_version); | |
| ConvertToKeymasterMessage(request->key_params, &out->key_description); | |
| // If mojo request carries an attestation key, convert it to Keymaster | |
| // message type. | |
| if (!request->attestation_key.is_null()) { | |
| out->attestation_signing_key_blob = ::keymaster::KeymasterKeyBlob( | |
| request->attestation_key->key_blob.data(), | |
| request->attestation_key->key_blob.size()); | |
| ConvertToKeymasterMessage(request->attestation_key->attest_key_params, | |
| &out->attest_key_params); | |
| out->issuer_subject = ::keymaster::KeymasterBlob( | |
| request->attestation_key->issuer_subject_name.data(), | |
| request->attestation_key->issuer_subject_name.size()); | |
| } | |
| return out; | |
| } | |
| std::unique_ptr<::keymaster::ImportKeyRequest> MakeImportKeyRequest( | |
| const arc::mojom::keymint::ImportKeyRequestPtr& request, | |
| const int32_t keymint_message_version) { | |
| auto out = | |
| std::make_unique<::keymaster::ImportKeyRequest>(keymint_message_version); | |
| ConvertToKeymasterMessage(request->key_params, &out->key_description); | |
| out->key_format = ConvertEnum(request->key_format); | |
| out->key_data = ::keymaster::KeymasterKeyBlob(request->key_data.data(), | |
| request->key_data.size()); | |
| // If mojo request carries an attestation key, convert it to Keymaster | |
| // message type. | |
| if (!request->attestation_key.is_null()) { | |
| out->attestation_signing_key_blob = ::keymaster::KeymasterKeyBlob( | |
| request->attestation_key->key_blob.data(), | |
| request->attestation_key->key_blob.size()); | |
| ConvertToKeymasterMessage(request->attestation_key->attest_key_params, | |
| &out->attest_key_params); | |
| out->issuer_subject = ::keymaster::KeymasterBlob( | |
| request->attestation_key->issuer_subject_name.data(), | |
| request->attestation_key->issuer_subject_name.size()); | |
| } | |
| return out; | |
| } | |
| std::unique_ptr<::keymaster::ImportWrappedKeyRequest> | |
| MakeImportWrappedKeyRequest( | |
| const arc::mojom::keymint::ImportWrappedKeyRequestPtr& request, | |
| const int32_t keymint_message_version) { | |
| auto out = std::make_unique<::keymaster::ImportWrappedKeyRequest>( | |
| keymint_message_version); | |
| out->SetWrappedMaterial(request->wrapped_key_data.data(), | |
| request->wrapped_key_data.size()); | |
| out->SetWrappingMaterial(request->wrapping_key_blob.data(), | |
| request->wrapping_key_blob.size()); | |
| out->SetMaskingKeyMaterial(request->masking_key.data(), | |
| request->masking_key.size()); | |
| ConvertToKeymasterMessage(request->unwrapping_params, | |
| &out->additional_params); | |
| out->password_sid = request->password_sid; | |
| out->biometric_sid = request->biometric_sid; | |
| return out; | |
| } | |
| std::unique_ptr<::keymaster::UpgradeKeyRequest> MakeUpgradeKeyRequest( | |
| const arc::mojom::keymint::UpgradeKeyRequestPtr& request, | |
| const int32_t keymint_message_version) { | |
| auto out = | |
| std::make_unique<::keymaster::UpgradeKeyRequest>(keymint_message_version); | |
| ConvertToKeymasterMessage(request->upgrade_params, &out->upgrade_params); | |
| out->SetKeyMaterial(request->key_blob_to_upgrade.data(), | |
| request->key_blob_to_upgrade.size()); | |
| return out; | |
| } | |
| std::unique_ptr<::keymaster::UpdateOperationRequest> MakeUpdateOperationRequest( | |
| const arc::mojom::keymint::UpdateRequestPtr& request, | |
| const int32_t keymint_message_version) { | |
| auto out = std::make_unique<::keymaster::UpdateOperationRequest>( | |
| keymint_message_version); | |
| out->op_handle = request->op_handle; | |
| ConvertToKeymasterMessage(request->input, &out->input); | |
| std::vector<arc::mojom::keymint::KeyParameterPtr> key_param_array; | |
| // UpdateOperationRequest also carries TimeStampTokenPtr, which is | |
| // unused yet and hence not converted. However, if it is used | |
| // in future by the reference implementation and the AIDL interface, | |
| // it will be added here. | |
| if (request->auth_token) { | |
| auto tokenAsVec(authToken2AidlVec(*request->auth_token)); | |
| auto key_param_ptr = arc::mojom::keymint::KeyParameter::New( | |
| static_cast<arc::mojom::keymint::Tag>(KM_TAG_AUTH_TOKEN), | |
| arc::mojom::keymint::KeyParameterValue::NewBlob(std::move(tokenAsVec))); | |
| key_param_array.push_back(std::move(key_param_ptr)); | |
| } | |
| ConvertToKeymasterMessage(std::move(key_param_array), | |
| &out->additional_params); | |
| return out; | |
| } | |
| std::unique_ptr<::keymaster::UpdateOperationRequest> | |
| MakeUpdateAadOperationRequest( | |
| const arc::mojom::keymint::UpdateRequestPtr& request, | |
| const int32_t keymint_message_version) { | |
| auto out = std::make_unique<::keymaster::UpdateOperationRequest>( | |
| keymint_message_version); | |
| out->op_handle = request->op_handle; | |
| std::vector<arc::mojom::keymint::KeyParameterPtr> key_param_array; | |
| auto associated_data_param = arc::mojom::keymint::KeyParameter::New( | |
| static_cast<arc::mojom::keymint::Tag>(KM_TAG_ASSOCIATED_DATA), | |
| arc::mojom::keymint::KeyParameterValue::NewBlob(request->input)); | |
| key_param_array.push_back(std::move(associated_data_param)); | |
| // UpdateAadOperationRequest also carries TimeStampTokenPtr, which is | |
| // unused yet and hence not converted. However, if it is used | |
| // in future by the reference implementation and the AIDL interface, | |
| // it will be added here. | |
| if (request->auth_token) { | |
| auto tokenAsVec(authToken2AidlVec(*request->auth_token)); | |
| auto key_param_ptr = arc::mojom::keymint::KeyParameter::New( | |
| static_cast<arc::mojom::keymint::Tag>(KM_TAG_AUTH_TOKEN), | |
| arc::mojom::keymint::KeyParameterValue::NewBlob(std::move(tokenAsVec))); | |
| key_param_array.push_back(std::move(key_param_ptr)); | |
| } | |
| ConvertToKeymasterMessage(std::move(key_param_array), | |
| &out->additional_params); | |
| return out; | |
| } | |
| std::unique_ptr<::keymaster::BeginOperationRequest> MakeBeginOperationRequest( | |
| const arc::mojom::keymint::BeginRequestPtr& request, | |
| const int32_t keymint_message_version) { | |
| auto out = std::make_unique<::keymaster::BeginOperationRequest>( | |
| keymint_message_version); | |
| out->purpose = ConvertEnum(request->key_purpose); | |
| out->SetKeyMaterial(request->key_blob.data(), request->key_blob.size()); | |
| if (request->auth_token) { | |
| auto tokenAsVec(authToken2AidlVec(*request->auth_token)); | |
| auto key_param_ptr = arc::mojom::keymint::KeyParameter::New( | |
| static_cast<arc::mojom::keymint::Tag>(KM_TAG_AUTH_TOKEN), | |
| arc::mojom::keymint::KeyParameterValue::NewBlob(std::move(tokenAsVec))); | |
| request->params.push_back(std::move(key_param_ptr)); | |
| } | |
| ConvertToKeymasterMessage(request->params, &out->additional_params); | |
| return out; | |
| } | |
| std::unique_ptr<::keymaster::DeviceLockedRequest> MakeDeviceLockedRequest( | |
| bool password_only, | |
| const arc::mojom::keymint::TimeStampTokenPtr& timestamp_token, | |
| const int32_t keymint_message_version) { | |
| auto out = std::make_unique<::keymaster::DeviceLockedRequest>( | |
| keymint_message_version); | |
| out->passwordOnly = password_only; | |
| if (timestamp_token) { | |
| out->token.challenge = timestamp_token->challenge; | |
| out->token.mac = {timestamp_token->mac.data(), timestamp_token->mac.size()}; | |
| if (!timestamp_token->timestamp) { | |
| LOG(ERROR) << "Timestamp token should have a valid timestamp."; | |
| return out; | |
| } | |
| out->token.timestamp = timestamp_token->timestamp->milli_seconds; | |
| } | |
| return out; | |
| } | |
| std::unique_ptr<::keymaster::FinishOperationRequest> MakeFinishOperationRequest( | |
| const arc::mojom::keymint::FinishRequestPtr& request, | |
| const int32_t keymint_message_version) { | |
| auto out = std::make_unique<::keymaster::FinishOperationRequest>( | |
| keymint_message_version); | |
| if (request.is_null()) { | |
| LOG(ERROR) << "KeyMint Error: Finish Operation Request is null"; | |
| return out; | |
| } | |
| out->op_handle = request->op_handle; | |
| if (request->input.has_value()) { | |
| ConvertToKeymasterMessage(request->input.value(), &out->input); | |
| } | |
| if (request->signature.has_value()) { | |
| ConvertToKeymasterMessage(request->signature.value(), &out->signature); | |
| } | |
| std::vector<arc::mojom::keymint::KeyParameterPtr> key_param_array; | |
| if (request->auth_token) { | |
| auto tokenAsVec(authToken2AidlVec(*request->auth_token)); | |
| auto key_param_ptr = arc::mojom::keymint::KeyParameter::New( | |
| static_cast<arc::mojom::keymint::Tag>(KM_TAG_AUTH_TOKEN), | |
| arc::mojom::keymint::KeyParameterValue::NewBlob(std::move(tokenAsVec))); | |
| key_param_array.push_back(std::move(key_param_ptr)); | |
| } | |
| // TimeStamp Token and Confirmation Token are not used | |
| // here since they are not passed from the AIDL. | |
| // If they are added in future, they will be converted here. | |
| ConvertToKeymasterMessage(std::move(key_param_array), | |
| &out->additional_params); | |
| return out; | |
| } | |
| std::unique_ptr<::keymaster::ComputeSharedHmacRequest> | |
| MakeComputeSharedSecretRequest( | |
| const std::vector<arc::mojom::keymint::SharedSecretParametersPtr>& request, | |
| const int32_t keymint_message_version) { | |
| auto out = std::make_unique<::keymaster::ComputeSharedHmacRequest>( | |
| keymint_message_version); | |
| // Allocate memory for HmacSharingParametersArray. | |
| out->params_array.params_array = | |
| new (std::nothrow)::keymaster::HmacSharingParameters[request.size()]; | |
| if (out->params_array.params_array == nullptr) { | |
| LOG(ERROR) | |
| << "KeyMint Error: Null Pointer received for ComputeSharedHmacRequest"; | |
| return out; | |
| } | |
| out->params_array.num_params = request.size(); | |
| // Transform each shared secret's nonce and seed to Keymaster request. | |
| for (size_t i = 0; i < request.size(); ++i) { | |
| out->params_array.params_array[i].seed = {request[i]->seed.data(), | |
| request[i]->seed.size()}; | |
| // Only copy memory if the nonce size is same for the Keymaster request | |
| // and Shared secret parameter. | |
| if (sizeof(out->params_array.params_array[i].nonce) != | |
| request[i]->nonce.size()) { | |
| LOG(ERROR) | |
| << "KeyMint Error: Different Nonce Size for Shared Secret Parameter"; | |
| return out; | |
| } | |
| std::copy(request[i]->nonce.data(), | |
| request[i]->nonce.data() + request[i]->nonce.size(), | |
| out->params_array.params_array[i].nonce); | |
| } | |
| return out; | |
| } | |
| // Mojo Result Methods. | |
| arc::mojom::keymint::KeyCharacteristicsArrayOrErrorPtr | |
| MakeGetKeyCharacteristicsResult( | |
| const ::keymaster::GetKeyCharacteristicsResponse& km_response) { | |
| if (km_response.error != KM_ERROR_OK) { | |
| return arc::mojom::keymint::KeyCharacteristicsArrayOrError::NewError( | |
| km_response.error); | |
| } | |
| auto output = | |
| ConvertKeyCharacteristics(km_response.enforced, km_response.unenforced, | |
| /* include_keystore_enforced = */ false); | |
| return arc::mojom::keymint::KeyCharacteristicsArrayOrError:: | |
| NewKeyCharacteristics(std::move(output)); | |
| } | |
| arc::mojom::keymint::KeyCreationResultOrErrorPtr MakeGenerateKeyResult( | |
| const ::keymaster::GenerateKeyResponse& km_response) { | |
| if (km_response.error != KM_ERROR_OK) { | |
| return arc::mojom::keymint::KeyCreationResultOrError::NewError( | |
| km_response.error); | |
| } | |
| // Create the Key Blob. | |
| auto key_blob = | |
| ConvertFromKeymasterMessage(km_response.key_blob.key_material, | |
| km_response.key_blob.key_material_size); | |
| // Create the Key Characteristics Array. | |
| auto key_chars_array = | |
| ConvertKeyCharacteristics(km_response.enforced, km_response.unenforced); | |
| // Create the Certificate Array. | |
| std::vector<arc::mojom::keymint::CertificatePtr> cert_array = | |
| ConvertFromKeymasterMessage(km_response.certificate_chain); | |
| auto key_result = arc::mojom::keymint::KeyCreationResult::New( | |
| std::move(key_blob), std::move(key_chars_array), std::move(cert_array)); | |
| return arc::mojom::keymint::KeyCreationResultOrError::NewKeyCreationResult( | |
| std::move(key_result)); | |
| } | |
| arc::mojom::keymint::KeyCreationResultOrErrorPtr MakeImportKeyResult( | |
| const ::keymaster::ImportKeyResponse& km_response) { | |
| if (km_response.error != KM_ERROR_OK) { | |
| return arc::mojom::keymint::KeyCreationResultOrError::NewError( | |
| km_response.error); | |
| } | |
| // Create the Key Blob. | |
| auto key_blob = | |
| ConvertFromKeymasterMessage(km_response.key_blob.key_material, | |
| km_response.key_blob.key_material_size); | |
| // Create the Key Characteristics Array. | |
| auto key_chars_array = | |
| ConvertKeyCharacteristics(km_response.enforced, km_response.unenforced); | |
| // Create the Certificate Array. | |
| std::vector<arc::mojom::keymint::CertificatePtr> cert_array = | |
| ConvertFromKeymasterMessage(km_response.certificate_chain); | |
| auto key_creation_result = arc::mojom::keymint::KeyCreationResult::New( | |
| std::move(key_blob), std::move(key_chars_array), std::move(cert_array)); | |
| return arc::mojom::keymint::KeyCreationResultOrError::NewKeyCreationResult( | |
| std::move(key_creation_result)); | |
| } | |
| arc::mojom::keymint::KeyCreationResultOrErrorPtr MakeImportWrappedKeyResult( | |
| const ::keymaster::ImportWrappedKeyResponse& km_response) { | |
| if (km_response.error != KM_ERROR_OK) { | |
| return arc::mojom::keymint::KeyCreationResultOrError::NewError( | |
| km_response.error); | |
| } | |
| // Create the Key Blob. | |
| auto key_blob = | |
| ConvertFromKeymasterMessage(km_response.key_blob.key_material, | |
| km_response.key_blob.key_material_size); | |
| // Create the Key Characteristics Array. | |
| auto key_chars_array = | |
| ConvertKeyCharacteristics(km_response.enforced, km_response.unenforced); | |
| // Create the Certificate Array. | |
| std::vector<arc::mojom::keymint::CertificatePtr> cert_array = | |
| ConvertFromKeymasterMessage(km_response.certificate_chain); | |
| auto key_creation_result = arc::mojom::keymint::KeyCreationResult::New( | |
| std::move(key_blob), std::move(key_chars_array), std::move(cert_array)); | |
| return arc::mojom::keymint::KeyCreationResultOrError::NewKeyCreationResult( | |
| std::move(key_creation_result)); | |
| } | |
| arc::mojom::keymint::ByteArrayOrErrorPtr MakeUpgradeKeyResult( | |
| const ::keymaster::UpgradeKeyResponse& km_response) { | |
| if (km_response.error != KM_ERROR_OK) { | |
| return arc::mojom::keymint::ByteArrayOrError::NewError(km_response.error); | |
| } | |
| // Create the Key Blob. | |
| auto upgraded_key_blob = | |
| ConvertFromKeymasterMessage(km_response.upgraded_key.key_material, | |
| km_response.upgraded_key.key_material_size); | |
| return arc::mojom::keymint::ByteArrayOrError::NewOutput( | |
| std::move(upgraded_key_blob)); | |
| } | |
| arc::mojom::keymint::ByteArrayOrErrorPtr MakeUpdateResult( | |
| const ::keymaster::UpdateOperationResponse& km_response) { | |
| if (km_response.error != KM_ERROR_OK) { | |
| return arc::mojom::keymint::ByteArrayOrError::NewError(km_response.error); | |
| } | |
| // UpdateOperationResponse also carries a field - |input_consumed|, | |
| // which is used in keymint_server.cc file. | |
| // It also carries another field - |output_params|, which is a | |
| // part of |output| returned from here. | |
| auto output = ConvertFromKeymasterMessage( | |
| km_response.output.begin(), km_response.output.available_read()); | |
| return arc::mojom::keymint::ByteArrayOrError::NewOutput(std::move(output)); | |
| } | |
| arc::mojom::keymint::BeginResultOrErrorPtr MakeBeginResult( | |
| const ::keymaster::BeginOperationResponse& km_response) { | |
| if (km_response.error != KM_ERROR_OK) { | |
| return arc::mojom::keymint::BeginResultOrError::NewError(km_response.error); | |
| } | |
| uint64_t challenge = km_response.op_handle; | |
| uint64_t op_handle = km_response.op_handle; | |
| auto begin_result = arc::mojom::keymint::BeginResult::New( | |
| std::move(challenge), | |
| ConvertFromKeymasterMessage(km_response.output_params), | |
| std::move(op_handle)); | |
| return arc::mojom::keymint::BeginResultOrError::NewBeginResult( | |
| std::move(begin_result)); | |
| } | |
| arc::mojom::keymint::ByteArrayOrErrorPtr MakeFinishResult( | |
| const ::keymaster::FinishOperationResponse& km_response) { | |
| if (km_response.error != KM_ERROR_OK) { | |
| return arc::mojom::keymint::ByteArrayOrError::NewError(km_response.error); | |
| } | |
| auto output = ConvertFromKeymasterMessage( | |
| km_response.output.begin(), km_response.output.available_read()); | |
| return arc::mojom::keymint::ByteArrayOrError::NewOutput(std::move(output)); | |
| } | |
| arc::mojom::keymint::SharedSecretParametersOrErrorPtr | |
| MakeGetSharedSecretParametersResult( | |
| const ::keymaster::GetHmacSharingParametersResponse& km_response) { | |
| if (km_response.error != KM_ERROR_OK) { | |
| return arc::mojom::keymint::SharedSecretParametersOrError::NewError( | |
| km_response.error); | |
| } | |
| // Create seed and nonce. | |
| std::vector<uint8_t> seed = ConvertFromKeymasterMessage( | |
| km_response.params.seed.begin(), km_response.params.seed.size()); | |
| std::vector<uint8_t> nonce(std::begin(km_response.params.nonce), | |
| std::end(km_response.params.nonce)); | |
| auto params = arc::mojom::keymint::SharedSecretParameters::New( | |
| std::move(seed), std::move(nonce)); | |
| return arc::mojom::keymint::SharedSecretParametersOrError:: | |
| NewSecretParameters(std::move(params)); | |
| } | |
| arc::mojom::keymint::ByteArrayOrErrorPtr MakeComputeSharedSecretResult( | |
| const ::keymaster::ComputeSharedHmacResponse& km_response) { | |
| if (km_response.error != KM_ERROR_OK) { | |
| return arc::mojom::keymint::ByteArrayOrError::NewError(km_response.error); | |
| } | |
| std::vector<uint8_t> result( | |
| km_response.sharing_check.data, | |
| km_response.sharing_check.data + km_response.sharing_check.data_length); | |
| return arc::mojom::keymint::ByteArrayOrError::NewOutput(std::move(result)); | |
| } | |
| arc::mojom::keymint::TimeStampTokenOrErrorPtr MakeGenerateTimeStampTokenResult( | |
| const ::keymaster::GenerateTimestampTokenResponse& km_response) { | |
| if (km_response.error != KM_ERROR_OK) { | |
| return arc::mojom::keymint::TimeStampTokenOrError::NewError( | |
| km_response.error); | |
| } | |
| uint64_t challenge = km_response.token.challenge; | |
| auto time_stamp = arc::mojom::keymint::Timestamp::New( | |
| base::strict_cast<uint64_t>(km_response.token.timestamp)); | |
| std::vector<uint8_t> mac( | |
| km_response.token.mac.data, | |
| km_response.token.mac.data + km_response.token.mac.data_length); | |
| auto time_stamp_token = arc::mojom::keymint::TimeStampToken::New( | |
| std::move(challenge), std::move(time_stamp), std::move(mac)); | |
| return arc::mojom::keymint::TimeStampTokenOrError::NewTimestampToken( | |
| std::move(time_stamp_token)); | |
| } | |
| arc::mojom::keymint::GenerateEcdsaP256KeyPairResultOrErrorPtr | |
| MakeGenerateEcdsaP256KeyPairResult( | |
| const ::keymaster::GenerateRkpKeyResponse& km_response) { | |
| if (km_response.error != KM_ERROR_OK) { | |
| return arc::mojom::keymint::GenerateEcdsaP256KeyPairResultOrError::NewError( | |
| km_response.error); | |
| } | |
| arc::mojom::keymint::KeyMintBlobPtr maced_public_key = | |
| ConvertFromKeyMintBlob(km_response.maced_public_key); | |
| arc::mojom::keymint::KeyMintKeyBlobPtr handle_to_private_key = | |
| ConvertFromKeyMintKeyBlob(km_response.key_blob); | |
| auto result = arc::mojom::keymint::GenerateEcdsaP256KeyPairResult::New( | |
| std::move(maced_public_key), std::move(handle_to_private_key)); | |
| return arc::mojom::keymint::GenerateEcdsaP256KeyPairResultOrError:: | |
| NewKeyPairResult(std::move(result)); | |
| } | |
| } // namespace arc::keymint |