blob: 1a1a1b02893d27a12e1d7039c036d7f3774690a5 [file] [log] [blame] [edit]
// 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