blob: 474f8e5fbd96f902d47c77d826262443a0a2e458 [file] [log] [blame]
// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cryptohome/cryptorecovery/recovery_crypto_hsm_cbor_serialization.h"
#include <string>
#include <optional>
#include <utility>
#include <vector>
#include <base/logging.h>
#include <brillo/secure_blob.h>
#include <chromeos/cbor/reader.h>
#include <chromeos/cbor/values.h>
#include <chromeos/cbor/writer.h>
#include "cryptohome/cryptorecovery/recovery_crypto_util.h"
namespace cryptohome {
namespace cryptorecovery {
namespace {
bool SerializeCborMap(const cbor::Value::MapValue& cbor_map,
brillo::SecureBlob* blob_cbor) {
std::optional<std::vector<uint8_t>> serialized =
cbor::Writer::Write(cbor::Value(std::move(cbor_map)));
if (!serialized) {
LOG(ERROR) << "Failed to serialize CBOR Map.";
return false;
}
blob_cbor->assign(serialized.value().begin(), serialized.value().end());
return true;
}
std::optional<cbor::Value> ReadCborMap(const brillo::SecureBlob& map_cbor) {
cbor::Reader::DecoderError error_code;
cbor::Reader::Config config;
config.error_code_out = &error_code;
config.allow_and_canonicalize_out_of_order_keys = true;
std::optional<cbor::Value> cbor_response =
cbor::Reader::Read(map_cbor, config);
if (!cbor_response) {
LOG(ERROR) << "Unable to create CBOR reader: "
<< cbor::Reader::ErrorCodeToString(error_code);
return std::nullopt;
}
if (error_code != cbor::Reader::DecoderError::CBOR_NO_ERROR) {
LOG(ERROR) << "Error when parsing CBOR input: "
<< cbor::Reader::ErrorCodeToString(error_code);
return std::nullopt;
}
if (!cbor_response->is_map()) {
LOG(ERROR) << "CBOR input is not a map.";
return std::nullopt;
}
return cbor_response;
}
bool FindBytestringValueInCborMap(const cbor::Value::MapValue& map,
const std::string& key,
brillo::SecureBlob* blob) {
const auto entry = map.find(cbor::Value(key));
if (entry == map.end()) {
LOG(ERROR) << "No `" + key + "` entry in the CBOR map.";
return false;
}
if (!entry->second.is_bytestring()) {
LOG(ERROR) << "Wrongly formatted `" + key + "` entry in the CBOR map.";
return false;
}
blob->assign(entry->second.GetBytestring().begin(),
entry->second.GetBytestring().end());
return true;
}
cbor::Value::MapValue ConvertAeadPayloadToCborMap(const AeadPayload& payload) {
cbor::Value::MapValue result;
result.emplace(kAeadCipherText, payload.cipher_text);
result.emplace(kAeadAd, payload.associated_data);
result.emplace(kAeadIv, payload.iv);
result.emplace(kAeadTag, payload.tag);
return result;
}
bool ConvertCborMapToAeadPayload(const cbor::Value::MapValue& aead_payload_map,
AeadPayload* aead_payload) {
brillo::SecureBlob cipher_text;
if (!FindBytestringValueInCborMap(aead_payload_map, kAeadCipherText,
&cipher_text)) {
LOG(ERROR) << "Failed to get cipher text from the AEAD CBOR map.";
return false;
}
brillo::SecureBlob associated_data;
if (!FindBytestringValueInCborMap(aead_payload_map, kAeadAd,
&associated_data)) {
LOG(ERROR) << "Failed to get associated data from the AEAD CBOR map.";
return false;
}
brillo::SecureBlob iv;
if (!FindBytestringValueInCborMap(aead_payload_map, kAeadIv, &iv)) {
LOG(ERROR) << "Failed to get iv from the AEAD CBOR map.";
return false;
}
brillo::SecureBlob tag;
if (!FindBytestringValueInCborMap(aead_payload_map, kAeadTag, &tag)) {
LOG(ERROR) << "Failed to get tag from the AEAD CBOR map.";
return false;
}
aead_payload->cipher_text = std::move(cipher_text);
aead_payload->associated_data = std::move(associated_data);
aead_payload->iv = std::move(iv);
aead_payload->tag = std::move(tag);
return true;
}
cbor::Value::MapValue ConvertRequestMetadataToCborMap(
const RequestMetadata& metadata) {
cbor::Value::MapValue auth_claim;
auth_claim.emplace(kGaiaAccessToken, metadata.auth_claim.gaia_access_token);
auth_claim.emplace(kGaiaReauthProofToken,
metadata.auth_claim.gaia_reauth_proof_token);
cbor::Value::MapValue request_meta_data;
request_meta_data.emplace(kSchemaVersion, kRequestMetaDataSchemaVersion);
request_meta_data.emplace(kAuthClaim, std::move(auth_claim));
request_meta_data.emplace(kRequestorUser, metadata.requestor_user_id);
request_meta_data.emplace(kRequestorUserType,
static_cast<int>(metadata.requestor_user_id_type));
return request_meta_data;
}
cbor::Value::MapValue ConvertHsmMetadataToCborMap(
const HsmMetaData& hsm_meta_data) {
cbor::Value::MapValue hsm_meta_data_map;
hsm_meta_data_map.emplace(kSchemaVersion, kHsmMetaDataSchemaVersion);
return hsm_meta_data_map;
}
} // namespace
// !!! DO NOT MODIFY !!!
// All the consts below are used as keys in the CBOR blog exchanged with the
// server and must be synced with the server/HSM implementation (or the other
// party will not be able to decrypt the data).
const char kSchemaVersion[] = "schema_version";
const char kMediatorShare[] = "mediator_share";
const char kMediatedShare[] = "mediated_share";
const char kKeyAuthValue[] = "key_auth_value";
const char kDealerPublicKey[] = "dealer_pub_key";
const char kPublisherPublicKey[] = "publisher_pub_key";
const char kChannelPublicKey[] = "channel_pub_key";
const char kRsaPublicKey[] = "rsa_pub_key";
const char kOnboardingMetaData[] = "onboarding_meta_data";
const char kHsmAead[] = "hsm_aead";
const char kAeadCipherText[] = "ct";
const char kAeadAd[] = "ad";
const char kAeadIv[] = "iv";
const char kAeadTag[] = "tag";
const char kRequestMetaData[] = "request_meta_data";
const char kRequestAead[] = "req_aead";
const char kRequestRsaSignature[] = "rsa_signature";
const char kEpochPublicKey[] = "epoch_pub_key";
const char kEphemeralPublicInvKey[] = "ephemeral_pub_inv_key";
const char kRequestPayloadSalt[] = "request_salt";
const char kResponseAead[] = "resp_aead";
const char kResponseHsmMetaData[] = "hsm_meta_data";
const char kResponsePayloadSalt[] = "response_salt";
const char kResponseErrorCode[] = "error_code";
const char kResponseErrorString[] = "error_string";
const char kCryptohomeUser[] = "cryptohome_user";
const char kCryptohomeUserType[] = "cryptohome_user_type";
const char kDeviceUserId[] = "device_user_id";
const char kBoardName[] = "board_name";
const char kModelName[] = "model_name";
const char kRecoveryId[] = "recovery_id";
const char kAuthClaim[] = "auth_claim";
const char kRequestorUser[] = "requestor_user";
const char kRequestorUserType[] = "requestor_user_type";
const char kGaiaAccessToken[] = "gaia_access_token";
const char kGaiaReauthProofToken[] = "gaia_reauth_proof_token";
const char kEpochMetaData[] = "epoch_meta_data";
const int kHsmAssociatedDataSchemaVersion = 1;
const int kOnboardingMetaDataSchemaVersion = 1;
const int kRequestMetaDataSchemaVersion = 1;
const int kHsmMetaDataSchemaVersion = 1;
bool SerializeRecoveryRequestPayloadToCbor(
const RequestPayload& request_payload,
brillo::SecureBlob* request_payload_cbor) {
cbor::Value::MapValue request_payload_map =
ConvertAeadPayloadToCborMap(request_payload);
if (!SerializeCborMap(request_payload_map, request_payload_cbor)) {
LOG(ERROR) << "Failed to serialize Recovery Request payload to CBOR";
return false;
}
return true;
}
bool SerializeRecoveryRequestToCbor(const RecoveryRequest& request,
brillo::SecureBlob* request_cbor) {
cbor::Value::MapValue request_map;
request_map.emplace(kRequestAead, request.request_payload);
// Attach rsa_signature if a signature is generated
if (!request.rsa_signature.empty()) {
request_map.emplace(kRequestRsaSignature, request.rsa_signature);
}
if (!SerializeCborMap(request_map, request_cbor)) {
LOG(ERROR) << "Failed to serialize Recovery Request to CBOR";
return false;
}
return true;
}
bool SerializeHsmAssociatedDataToCbor(const HsmAssociatedData& args,
brillo::SecureBlob* ad_cbor) {
cbor::Value::MapValue ad_map;
ad_map.emplace(kSchemaVersion, kHsmAssociatedDataSchemaVersion);
ad_map.emplace(kPublisherPublicKey, args.publisher_pub_key);
ad_map.emplace(kChannelPublicKey, args.channel_pub_key);
// Attach rsa_public_key if a public key is generated
if (!args.rsa_public_key.empty()) {
ad_map.emplace(kRsaPublicKey, args.rsa_public_key);
}
cbor::Value::MapValue onboarding_meta_data_map;
onboarding_meta_data_map.emplace(kSchemaVersion,
kOnboardingMetaDataSchemaVersion);
onboarding_meta_data_map.emplace(kCryptohomeUser,
args.onboarding_meta_data.cryptohome_user);
onboarding_meta_data_map.emplace(
kCryptohomeUserType,
static_cast<int>(args.onboarding_meta_data.cryptohome_user_type));
onboarding_meta_data_map.emplace(kDeviceUserId,
args.onboarding_meta_data.device_user_id);
onboarding_meta_data_map.emplace(kBoardName,
args.onboarding_meta_data.board_name);
onboarding_meta_data_map.emplace(kModelName,
args.onboarding_meta_data.model_name);
onboarding_meta_data_map.emplace(kRecoveryId,
args.onboarding_meta_data.recovery_id);
ad_map.emplace(kOnboardingMetaData, std::move(onboarding_meta_data_map));
if (!SerializeCborMap(ad_map, ad_cbor)) {
LOG(ERROR) << "Failed to serialize HSM Associated Data to CBOR";
return false;
}
return true;
}
bool SerializeRecoveryRequestAssociatedDataToCbor(
const RecoveryRequestAssociatedData& args,
brillo::SecureBlob* request_ad_cbor) {
cbor::Value::MapValue ad_map;
ad_map.emplace(kHsmAead, ConvertAeadPayloadToCborMap(args.hsm_payload));
ad_map.emplace(kEpochPublicKey, args.epoch_pub_key);
ad_map.emplace(kRequestPayloadSalt, args.request_payload_salt);
ad_map.emplace(kRequestMetaData,
ConvertRequestMetadataToCborMap(args.request_meta_data));
ad_map.emplace(kEpochMetaData, args.epoch_meta_data.meta_data_cbor.Clone());
if (!SerializeCborMap(ad_map, request_ad_cbor)) {
LOG(ERROR)
<< "Failed to serialize Recovery Request Associated Data to CBOR";
return false;
}
return true;
}
bool SerializeHsmResponseAssociatedDataToCbor(
const HsmResponseAssociatedData& response_ad,
brillo::SecureBlob* response_ad_cbor) {
cbor::Value::MapValue ad_map;
ad_map.emplace(kResponseHsmMetaData,
ConvertHsmMetadataToCborMap(response_ad.hsm_meta_data));
ad_map.emplace(kResponsePayloadSalt, response_ad.response_payload_salt);
if (!SerializeCborMap(ad_map, response_ad_cbor)) {
LOG(ERROR) << "Failed to serialize HSM Response Associated Data to CBOR";
return false;
}
return true;
}
bool SerializeHsmPlainTextToCbor(const HsmPlainText& plain_text,
brillo::SecureBlob* plain_text_cbor) {
cbor::Value::MapValue pt_map;
pt_map.emplace(kDealerPublicKey, plain_text.dealer_pub_key);
pt_map.emplace(kMediatorShare, plain_text.mediator_share);
// Attach key_auth_value only if it's generated
if (!plain_text.key_auth_value.empty()) {
pt_map.emplace(kKeyAuthValue, plain_text.key_auth_value);
}
if (!SerializeCborMap(pt_map, plain_text_cbor)) {
LOG(ERROR) << "Failed to serialize HSM plain text to CBOR";
return false;
}
return true;
}
bool SerializeRecoveryRequestPlainTextToCbor(
const RecoveryRequestPlainText& plain_text,
brillo::SecureBlob* plain_text_cbor) {
cbor::Value::MapValue pt_map;
pt_map.emplace(kEphemeralPublicInvKey, plain_text.ephemeral_pub_inv_key);
if (!SerializeCborMap(pt_map, plain_text_cbor)) {
LOG(ERROR) << "Failed to serialize Recovery Request plain text to CBOR";
return false;
}
return true;
}
bool SerializeRecoveryResponseToCbor(const RecoveryResponse& response,
brillo::SecureBlob* response_cbor) {
cbor::Value::MapValue response_map;
response_map.emplace(kResponseAead,
ConvertAeadPayloadToCborMap(response.response_payload));
response_map.emplace(kResponseErrorCode, response.error_code);
response_map.emplace(kResponseErrorString, response.error_string);
if (!SerializeCborMap(response_map, response_cbor)) {
LOG(ERROR) << "Failed to serialize Recovery Response to CBOR";
return false;
}
return true;
}
bool SerializeHsmResponsePlainTextToCbor(const HsmResponsePlainText& plain_text,
brillo::SecureBlob* response_cbor) {
cbor::Value::MapValue pt_map;
pt_map.emplace(kDealerPublicKey, plain_text.dealer_pub_key);
pt_map.emplace(kMediatedShare, plain_text.mediated_point);
pt_map.emplace(kKeyAuthValue, plain_text.key_auth_value);
if (!SerializeCborMap(pt_map, response_cbor)) {
LOG(ERROR) << "Failed to serialize HSM responce payload to CBOR";
return false;
}
return true;
}
bool SerializeHsmPayloadToCbor(const HsmPayload& hsm_payload,
brillo::SecureBlob* serialized_cbor) {
cbor::Value::MapValue hsm_payload_map =
ConvertAeadPayloadToCborMap(hsm_payload);
if (!SerializeCborMap(hsm_payload_map, serialized_cbor)) {
LOG(ERROR) << "Failed to serialize HSM payload to CBOR";
return false;
}
return true;
}
bool DeserializeHsmPayloadFromCbor(const brillo::SecureBlob& serialized_cbor,
HsmPayload* hsm_payload) {
const auto& cbor = ReadCborMap(serialized_cbor);
if (!cbor) {
return false;
}
if (!ConvertCborMapToAeadPayload(cbor->GetMap(), hsm_payload)) {
LOG(ERROR) << "Failed to deserialize HSM payload from CBOR.";
return false;
}
return true;
}
bool DeserializeHsmPlainTextFromCbor(
const brillo::SecureBlob& hsm_plain_text_cbor,
HsmPlainText* hsm_plain_text) {
const auto& cbor = ReadCborMap(hsm_plain_text_cbor);
if (!cbor) {
return false;
}
const cbor::Value::MapValue& response_map = cbor->GetMap();
brillo::SecureBlob dealer_pub_key;
if (!FindBytestringValueInCborMap(response_map, kDealerPublicKey,
&dealer_pub_key)) {
LOG(ERROR) << "Failed to get dealer public key from the HSM response map.";
return false;
}
brillo::SecureBlob mediator_share;
if (!FindBytestringValueInCborMap(response_map, kMediatorShare,
&mediator_share)) {
LOG(ERROR) << "Failed to get mediator share from the HSM response map.";
return false;
}
// Parse out key_auth_value if it is attached.
if (response_map.contains(cbor::Value(kKeyAuthValue))) {
brillo::SecureBlob key_auth_value;
if (!FindBytestringValueInCborMap(response_map, kKeyAuthValue,
&key_auth_value)) {
LOG(ERROR) << "Failed to get key auth value from the HSM response map.";
return false;
}
hsm_plain_text->key_auth_value = std::move(key_auth_value);
}
hsm_plain_text->dealer_pub_key = std::move(dealer_pub_key);
hsm_plain_text->mediator_share = std::move(mediator_share);
return true;
}
bool DeserializeHsmAssociatedDataFromCbor(
const brillo::SecureBlob& hsm_associated_data_cbor,
HsmAssociatedData* hsm_associated_data) {
const auto& cbor = ReadCborMap(hsm_associated_data_cbor);
if (!cbor) {
return false;
}
const cbor::Value::MapValue& response_map = cbor->GetMap();
brillo::SecureBlob publisher_pub_key;
if (!FindBytestringValueInCborMap(response_map, kPublisherPublicKey,
&publisher_pub_key)) {
LOG(ERROR) << "Failed to get publisher public key from the HSM associated "
"data map.";
return false;
}
brillo::SecureBlob channel_pub_key;
if (!FindBytestringValueInCborMap(response_map, kChannelPublicKey,
&channel_pub_key)) {
LOG(ERROR)
<< "Failed to get Channel public key from the HSM associated data map.";
return false;
}
// Parse out rsa_public_key if it is attached
const auto rsa_public_key_entry =
response_map.find(cbor::Value(kRsaPublicKey));
if (rsa_public_key_entry != response_map.end()) {
brillo::SecureBlob rsa_public_key;
if (!FindBytestringValueInCborMap(response_map, kRsaPublicKey,
&rsa_public_key)) {
LOG(ERROR)
<< "Failed to get RSA public key from the HSM associated data map.";
return false;
}
hsm_associated_data->rsa_public_key = std::move(rsa_public_key);
}
hsm_associated_data->publisher_pub_key = std::move(publisher_pub_key);
hsm_associated_data->channel_pub_key = std::move(channel_pub_key);
return true;
}
bool DeserializeRecoveryRequestPlainTextFromCbor(
const brillo::SecureBlob& request_plain_text_cbor,
RecoveryRequestPlainText* request_plain_text) {
const auto& cbor = ReadCborMap(request_plain_text_cbor);
if (!cbor) {
return false;
}
const cbor::Value::MapValue& request_map = cbor->GetMap();
brillo::SecureBlob ephemeral_pub_inv_key;
if (!FindBytestringValueInCborMap(request_map, kEphemeralPublicInvKey,
&ephemeral_pub_inv_key)) {
LOG(ERROR) << "Failed to get ephemeral public inverse key from the "
"Recovery Request map.";
return false;
}
request_plain_text->ephemeral_pub_inv_key = std::move(ephemeral_pub_inv_key);
return true;
}
bool DeserializeRecoveryRequestFromCbor(
const brillo::SecureBlob& recovery_request_cbor,
RecoveryRequest* recovery_request) {
const auto& cbor = ReadCborMap(recovery_request_cbor);
if (!cbor) {
return false;
}
const cbor::Value::MapValue& cbor_map = cbor->GetMap();
// Parse out request_payload SecureBlob
brillo::SecureBlob request_payload;
if (!FindBytestringValueInCborMap(cbor_map, kRequestAead, &request_payload)) {
LOG(ERROR) << "Failed to get request payload from Recovery Request map.";
return false;
}
recovery_request->request_payload = std::move(request_payload);
// Parse out rsa_signature if it is attached
const auto rsa_signature_entry =
cbor_map.find(cbor::Value(kRequestRsaSignature));
if (rsa_signature_entry != cbor_map.end()) {
brillo::SecureBlob rsa_signature;
if (!FindBytestringValueInCborMap(cbor_map, kRequestRsaSignature,
&rsa_signature)) {
LOG(ERROR) << "Failed to get RSA signature from the recovery request.";
return false;
}
recovery_request->rsa_signature = std::move(rsa_signature);
}
return true;
}
bool DeserializeRecoveryRequestPayloadFromCbor(
const brillo::SecureBlob& serialized_cbor,
RequestPayload* request_payload) {
const auto& cbor = ReadCborMap(serialized_cbor);
if (!cbor) {
return false;
}
if (!ConvertCborMapToAeadPayload(cbor->GetMap(), request_payload)) {
LOG(ERROR) << "Failed to deserialize Recovery Request payload from CBOR.";
return false;
}
return true;
}
bool DeserializeHsmResponsePlainTextFromCbor(
const brillo::SecureBlob& response_payload_cbor,
HsmResponsePlainText* response_payload) {
const auto& cbor = ReadCborMap(response_payload_cbor);
if (!cbor) {
return false;
}
const cbor::Value::MapValue& response_map = cbor->GetMap();
brillo::SecureBlob dealer_pub_key;
if (!FindBytestringValueInCborMap(response_map, kDealerPublicKey,
&dealer_pub_key)) {
LOG(ERROR) << "Failed to get dealer public key from the HSM response map.";
return false;
}
brillo::SecureBlob mediated_point;
if (!FindBytestringValueInCborMap(response_map, kMediatedShare,
&mediated_point)) {
LOG(ERROR) << "Failed to get mediated point from the HSM response map.";
return false;
}
// Key Auth Value is optional.
brillo::SecureBlob key_auth_value;
const auto key_auth_value_entry =
response_map.find(cbor::Value(kKeyAuthValue));
if (key_auth_value_entry != response_map.end()) {
if (!key_auth_value_entry->second.is_bytestring()) {
LOG(ERROR) << "Wrongly formatted `" << kKeyAuthValue
<< "` entry in the Response plain text CBOR map.";
return false;
}
key_auth_value.assign(key_auth_value_entry->second.GetBytestring().begin(),
key_auth_value_entry->second.GetBytestring().end());
}
response_payload->dealer_pub_key = std::move(dealer_pub_key);
response_payload->mediated_point = std::move(mediated_point);
response_payload->key_auth_value = std::move(key_auth_value);
return true;
}
bool DeserializeHsmResponseAssociatedDataFromCbor(
const brillo::SecureBlob& response_ad_cbor,
HsmResponseAssociatedData* response_ad) {
const auto& cbor = ReadCborMap(response_ad_cbor);
if (!cbor) {
return false;
}
const cbor::Value::MapValue& response_map = cbor->GetMap();
brillo::SecureBlob response_payload_salt;
if (!FindBytestringValueInCborMap(response_map, kResponsePayloadSalt,
&response_payload_salt)) {
LOG(ERROR) << "Failed to get response payload salt from the HSM response "
"associated data map.";
return false;
}
const auto hsm_meta_data_entry =
response_map.find(cbor::Value(kResponseHsmMetaData));
if (hsm_meta_data_entry == response_map.end()) {
LOG(ERROR) << "No " << kResponseHsmMetaData
<< " entry in the HSM Response associated data map.";
return false;
}
if (!hsm_meta_data_entry->second.is_map()) {
LOG(ERROR) << "Wrongly formatted " << kResponseHsmMetaData
<< " entry in the HSM Response associated data map.";
return false;
}
response_ad->response_payload_salt = std::move(response_payload_salt);
return true;
}
bool DeserializeRecoveryResponseFromCbor(
const brillo::SecureBlob& response_cbor, RecoveryResponse* response) {
const auto& cbor = ReadCborMap(response_cbor);
if (!cbor) {
return false;
}
const cbor::Value::MapValue& response_map = cbor->GetMap();
const auto error_code_entry =
response_map.find(cbor::Value(kResponseErrorCode));
if (error_code_entry == response_map.end()) {
LOG(ERROR) << "No " << kResponseErrorCode
<< " entry in the Recovery Response map.";
return false;
}
if (!error_code_entry->second.is_integer()) {
LOG(ERROR) << "Wrongly formatted " << kResponseErrorCode
<< " entry in the Recovery Response map.";
return false;
}
const auto error_string_entry =
response_map.find(cbor::Value(kResponseErrorString));
if (error_string_entry == response_map.end()) {
LOG(ERROR) << "No " << kResponseErrorString
<< " entry in the Recovery Response map.";
return false;
}
if (!error_string_entry->second.is_string()) {
LOG(ERROR) << "Wrongly formatted " << kResponseErrorString
<< " entry in the Recovery Response map.";
return false;
}
const auto response_payload_entry =
response_map.find(cbor::Value(kResponseAead));
if (response_payload_entry == response_map.end()) {
LOG(ERROR) << "No " << kResponseAead
<< " entry in the Recovery Response map.";
return false;
}
if (!response_payload_entry->second.is_map()) {
LOG(ERROR) << "Wrongly formatted " << kResponseAead
<< " entry in the Recovery Response map.";
return false;
}
ResponsePayload response_payload;
if (!ConvertCborMapToAeadPayload(response_payload_entry->second.GetMap(),
&response_payload)) {
LOG(ERROR) << "Failed to deserialize Response payload from CBOR.";
return false;
}
response->response_payload = std::move(response_payload);
response->error_code = error_code_entry->second.GetInteger();
response->error_string = error_string_entry->second.GetString();
return true;
}
bool DeserializeEpochMetadataFromCbor(
const brillo::SecureBlob& epoch_metadata_cbor,
EpochMetadata* epoch_metadata) {
auto cbor = ReadCborMap(epoch_metadata_cbor);
if (!cbor) {
return false;
}
epoch_metadata->meta_data_cbor = std::move(cbor.value());
return true;
}
bool GetValueFromCborMapByKeyForTesting(const brillo::SecureBlob& input_cbor,
const std::string& map_key,
cbor::Value* value) {
const auto& cbor = ReadCborMap(input_cbor);
if (!cbor) {
return false;
}
const cbor::Value::MapValue& map = cbor->GetMap();
const auto entry = map.find(cbor::Value(map_key));
if (entry == map.end()) {
LOG(ERROR) << "No `" + map_key + "` entry in the CBOR map.";
return false;
}
*value = entry->second.Clone();
return true;
}
bool GetBytestringValueFromCborMapByKeyForTesting(
const brillo::SecureBlob& input_cbor,
const std::string& map_key,
brillo::SecureBlob* value) {
const auto& cbor = ReadCborMap(input_cbor);
if (!cbor) {
return false;
}
if (!FindBytestringValueInCborMap(cbor->GetMap(), map_key, value)) {
LOG(ERROR) << "Failed to get keyed entry from cbor map.";
return false;
}
return true;
}
bool GetHsmPayloadFromRequestAdForTesting(
const brillo::SecureBlob& request_payload_cbor, HsmPayload* hsm_payload) {
const auto& cbor = ReadCborMap(request_payload_cbor);
if (!cbor) {
return false;
}
const cbor::Value::MapValue& cbor_map = cbor->GetMap();
const auto hsm_payload_entry = cbor_map.find(cbor::Value(kHsmAead));
if (hsm_payload_entry == cbor_map.end()) {
LOG(ERROR) << "No HSM payload entry in the Request cbor map.";
return false;
}
if (!hsm_payload_entry->second.is_map()) {
LOG(ERROR)
<< "HSM payload entry in the Request cbor map has a wrong format.";
return false;
}
const cbor::Value::MapValue& hsm_map = hsm_payload_entry->second.GetMap();
brillo::SecureBlob cipher_text;
if (!FindBytestringValueInCborMap(hsm_map, kAeadCipherText, &cipher_text)) {
LOG(ERROR) << "Failed to get cipher text from the HSM payload map.";
return false;
}
brillo::SecureBlob associated_data;
if (!FindBytestringValueInCborMap(hsm_map, kAeadAd, &associated_data)) {
LOG(ERROR) << "Failed to get associated data from the HSM payload map.";
return false;
}
brillo::SecureBlob iv;
if (!FindBytestringValueInCborMap(hsm_map, kAeadIv, &iv)) {
LOG(ERROR) << "Failed to get iv from the HSM payload map.";
return false;
}
brillo::SecureBlob tag;
if (!FindBytestringValueInCborMap(hsm_map, kAeadTag, &tag)) {
LOG(ERROR) << "Failed to get tag from the HSM payload map.";
return false;
}
hsm_payload->cipher_text = std::move(cipher_text);
hsm_payload->associated_data = std::move(associated_data);
hsm_payload->iv = std::move(iv);
hsm_payload->tag = std::move(tag);
return true;
}
int GetCborMapSize(const brillo::SecureBlob& input_cbor) {
const auto& cbor = ReadCborMap(input_cbor);
if (!cbor) {
return -1;
}
return cbor->GetMap().size();
}
bool SerializeCborForTesting(const cbor::Value& cbor,
brillo::SecureBlob* serialized_cbor) {
std::optional<std::vector<uint8_t>> serialized = cbor::Writer::Write(cbor);
if (!serialized) {
LOG(ERROR) << "Failed to serialize CBOR Map.";
return false;
}
serialized_cbor->assign(serialized.value().begin(), serialized.value().end());
return true;
}
} // namespace cryptorecovery
} // namespace cryptohome