blob: b6f27674f780376eb41692d06acd27b863b07283 [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 <map>
#include <utility>
#include <vector>
#include <base/optional.h>
#include <brillo/secure_blob.h>
#include <chromeos/cbor/writer.h>
#include <crypto/scoped_openssl_types.h>
#include <gtest/gtest.h>
#include <openssl/bn.h>
#include "cryptohome/crypto/big_num_util.h"
#include "cryptohome/crypto/elliptic_curve.h"
#include "cryptohome/crypto/secure_blob_util.h"
#include "cryptohome/cryptorecovery/recovery_crypto_util.h"
namespace cryptohome {
namespace cryptorecovery {
namespace {
constexpr EllipticCurve::CurveType kCurve = EllipticCurve::CurveType::kPrime256;
// Size of public/private key for EllipticCurve::CurveType::kPrime256.
constexpr size_t kEc256PubKeySize = 65;
constexpr size_t kEc256PrivKeySize = 32;
const char kOnboardingData[] = "fake onboarding data";
const char kFakeRequestData[] = "fake request metadata";
const char kFakeHsmPayloadCipherText[] = "fake hsm payload cipher text";
const char kFakeHsmPayloadAd[] = "fake hsm payload ad";
const char kFakeHsmPayloadIv[] = "fake hsm payload iv";
const char kFakeHsmPayloadTag[] = "fake hsm payload tag";
const char kFakeResponseData[] = "fake response metadata";
const char kFakeResponseSalt[] = "fake response salt";
bool CreateCborMapForTesting(const cbor::Value::MapValue& map,
brillo::SecureBlob* serialized_cbor_map) {
base::Optional<std::vector<uint8_t>> serialized =
cbor::Writer::Write(cbor::Value(map));
if (!serialized) {
LOG(ERROR) << "Failed to serialize CBOR Map.";
return false;
}
serialized_cbor_map->assign(serialized.value().begin(),
serialized.value().end());
return true;
}
void ExpectSerializedCborMapContainsValue(
const brillo::SecureBlob& cbor_output,
const std::string& key,
const brillo::SecureBlob& expected_value) {
brillo::SecureBlob deserialized_value;
EXPECT_TRUE(GetBytestringValueFromCborMapByKeyForTesting(
cbor_output, key, &deserialized_value));
EXPECT_EQ(deserialized_value, expected_value);
}
void ExpectCborMapContainsValue(const cbor::Value::MapValue& map,
const std::string& key,
const brillo::SecureBlob& expected_value) {
const auto entry = map.find(cbor::Value(key));
ASSERT_TRUE(entry != map.end());
ASSERT_TRUE(entry->second.is_bytestring());
brillo::SecureBlob result(entry->second.GetBytestring().begin(),
entry->second.GetBytestring().end());
EXPECT_EQ(result, expected_value);
}
} // namespace
class HsmPayloadCborHelperTest : public testing::Test {
public:
void SetUp() override {
context_ = CreateBigNumContext();
ASSERT_TRUE(context_);
ec_ = EllipticCurve::Create(kCurve, context_.get());
ASSERT_TRUE(ec_);
ASSERT_TRUE(ec_->GenerateKeysAsSecureBlobs(
&publisher_pub_key_, &publisher_priv_key_, context_.get()));
ASSERT_TRUE(ec_->GenerateKeysAsSecureBlobs(
&channel_pub_key_, &channel_priv_key_, context_.get()));
ASSERT_TRUE(ec_->GenerateKeysAsSecureBlobs(
&dealer_pub_key_, &dealer_priv_key_, context_.get()));
}
protected:
ScopedBN_CTX context_;
base::Optional<EllipticCurve> ec_;
brillo::SecureBlob publisher_pub_key_;
brillo::SecureBlob publisher_priv_key_;
brillo::SecureBlob channel_pub_key_;
brillo::SecureBlob channel_priv_key_;
brillo::SecureBlob dealer_pub_key_;
brillo::SecureBlob dealer_priv_key_;
};
class AeadPayloadHelper {
public:
AeadPayloadHelper() {
fake_aead_payload_.cipher_text = brillo::SecureBlob("fake cipher text");
fake_aead_payload_.associated_data =
brillo::SecureBlob("fake associated data");
fake_aead_payload_.iv = brillo::SecureBlob("fake iv");
fake_aead_payload_.tag = brillo::SecureBlob("fake tag");
}
const AeadPayload& GetFakePayload() const { return fake_aead_payload_; }
cbor::Value::MapValue GetFakePayloadCborMap() const {
cbor::Value::MapValue payload;
payload.emplace(kAeadCipherText, fake_aead_payload_.cipher_text);
payload.emplace(kAeadAd, fake_aead_payload_.associated_data);
payload.emplace(kAeadIv, fake_aead_payload_.iv);
payload.emplace(kAeadTag, fake_aead_payload_.tag);
return payload;
}
void ExpectEqualsToFakeAeadPayload(const AeadPayload& payload) const {
EXPECT_EQ(payload.cipher_text, fake_aead_payload_.cipher_text);
EXPECT_EQ(payload.associated_data, fake_aead_payload_.associated_data);
EXPECT_EQ(payload.iv, fake_aead_payload_.iv);
EXPECT_EQ(payload.tag, fake_aead_payload_.tag);
}
void ExpectEqualsToFakeAeadPayload(
const cbor::Value::MapValue& cbor_map) const {
ExpectCborMapContainsValue(cbor_map, kAeadCipherText,
fake_aead_payload_.cipher_text);
ExpectCborMapContainsValue(cbor_map, kAeadAd,
fake_aead_payload_.associated_data);
ExpectCborMapContainsValue(cbor_map, kAeadIv, fake_aead_payload_.iv);
ExpectCborMapContainsValue(cbor_map, kAeadTag, fake_aead_payload_.tag);
}
private:
AeadPayload fake_aead_payload_;
};
class RecoveryRequestCborHelperTest : public testing::Test {
public:
void SetUp() override {
context_ = CreateBigNumContext();
ASSERT_TRUE(context_);
ec_ = EllipticCurve::Create(kCurve, context_.get());
ASSERT_TRUE(ec_);
ASSERT_TRUE(ec_->GenerateKeysAsSecureBlobs(
&epoch_pub_key_, &epoch_priv_key_, context_.get()));
}
protected:
AeadPayloadHelper aead_helper_;
ScopedBN_CTX context_;
base::Optional<EllipticCurve> ec_;
brillo::SecureBlob epoch_pub_key_;
brillo::SecureBlob epoch_priv_key_;
};
class RecoveryResponseCborHelperTest : public testing::Test {
protected:
AeadPayloadHelper aead_helper_;
const int fake_error_code_ = 2;
const std::string fake_error_string_ = "fake error string";
const brillo::SecureBlob fake_pub_key_ =
CreateSecureRandomBlob(kEc256PubKeySize);
const brillo::SecureBlob fake_priv_key_ =
CreateSecureRandomBlob(kEc256PrivKeySize);
const brillo::SecureBlob metadata_{kFakeResponseData};
const brillo::SecureBlob salt_{kFakeResponseSalt};
};
// Verifies serialization of HSM payload associated data to CBOR.
TEST_F(HsmPayloadCborHelperTest, GenerateAdCborWithEmptyRsaPublicKey) {
brillo::SecureBlob cbor_output;
HsmAssociatedData args;
args.publisher_pub_key = publisher_pub_key_;
args.channel_pub_key = channel_pub_key_;
args.onboarding_meta_data = brillo::SecureBlob(kOnboardingData);
ASSERT_TRUE(SerializeHsmAssociatedDataToCbor(args, &cbor_output));
ExpectSerializedCborMapContainsValue(cbor_output, kPublisherPublicKey,
publisher_pub_key_);
ExpectSerializedCborMapContainsValue(cbor_output, kChannelPublicKey,
channel_pub_key_);
ExpectSerializedCborMapContainsValue(cbor_output, kOnboardingMetaData,
brillo::SecureBlob(kOnboardingData));
EXPECT_EQ(4, GetCborMapSize(cbor_output));
}
// Verifies serialization of HSM payload plain text encrypted payload to CBOR.
TEST_F(HsmPayloadCborHelperTest, GeneratePlainTextHsmPayloadCbor) {
brillo::SecureBlob mediator_share;
brillo::SecureBlob cbor_output;
crypto::ScopedBIGNUM scalar = BigNumFromValue(123123123u);
ASSERT_TRUE(scalar);
ASSERT_TRUE(BigNumToSecureBlob(*scalar, 10, &mediator_share));
// Serialize plain text payload with empty kav.
HsmPlainText hsm_plain_text;
hsm_plain_text.mediator_share = mediator_share;
hsm_plain_text.dealer_pub_key = dealer_pub_key_;
hsm_plain_text.key_auth_value = brillo::SecureBlob();
ASSERT_TRUE(SerializeHsmPlainTextToCbor(hsm_plain_text, &cbor_output));
ExpectSerializedCborMapContainsValue(cbor_output, kDealerPublicKey,
dealer_pub_key_);
ExpectSerializedCborMapContainsValue(cbor_output, kKeyAuthValue,
brillo::SecureBlob());
brillo::SecureBlob deserialized_mediator_share;
EXPECT_TRUE(GetBytestringValueFromCborMapByKeyForTesting(
cbor_output, kMediatorShare, &deserialized_mediator_share));
EXPECT_EQ(BN_get_word(scalar.get()),
BN_get_word(SecureBlobToBigNum(deserialized_mediator_share).get()));
EXPECT_EQ(3, GetCborMapSize(cbor_output));
}
// Verifies deserialization of HSM payload plain text from CBOR.
TEST_F(HsmPayloadCborHelperTest, DeserializePlainTextHsmPayload) {
brillo::SecureBlob mediator_share;
brillo::SecureBlob cbor_output;
crypto::ScopedBIGNUM scalar = BigNumFromValue(123123123u);
ASSERT_TRUE(scalar);
ASSERT_TRUE(BigNumToSecureBlob(*scalar, 10, &mediator_share));
// Serialize plain text payload with empty kav.
cbor::Value::MapValue fake_map;
fake_map.emplace(kDealerPublicKey, dealer_pub_key_);
fake_map.emplace(kMediatorShare, mediator_share);
fake_map.emplace(kKeyAuthValue, brillo::SecureBlob());
brillo::SecureBlob hsm_cbor;
ASSERT_TRUE(CreateCborMapForTesting(fake_map, &hsm_cbor));
HsmPlainText hsm_plain_text;
DeserializeHsmPlainTextFromCbor(hsm_cbor, &hsm_plain_text);
EXPECT_EQ(hsm_plain_text.dealer_pub_key, dealer_pub_key_);
EXPECT_EQ(hsm_plain_text.mediator_share, mediator_share);
EXPECT_TRUE(hsm_plain_text.key_auth_value.empty());
}
// Verifies that the deserialization of HSM payload plain text from CBOR fails
// if input is not a CBOR.
TEST_F(HsmPayloadCborHelperTest, DeserializePlainTextHsmPayloadNotCbor) {
HsmPlainText hsm_plain_text;
brillo::SecureBlob hsm_cbor("actually not a CBOR");
EXPECT_FALSE(DeserializeHsmPlainTextFromCbor(hsm_cbor, &hsm_plain_text));
}
// Verifies that the deserialization of HSM payload plain text from CBOR fails
// if input is not a CBOR map.
TEST_F(HsmPayloadCborHelperTest, DeserializePlainTextHsmPayloadNotMap) {
HsmPlainText hsm_plain_text;
base::Optional<std::vector<uint8_t>> serialized =
cbor::Writer::Write(cbor::Value("a CBOR but not a map"));
ASSERT_TRUE(serialized.has_value());
brillo::SecureBlob hsm_cbor(serialized.value().begin(),
serialized.value().end());
EXPECT_FALSE(DeserializeHsmPlainTextFromCbor(hsm_cbor, &hsm_plain_text));
}
// Verifies that the deserialization of HSM payload plain text from CBOR fails
// if CBOR has wrong format.
TEST_F(HsmPayloadCborHelperTest, DeserializePlainTextHsmPayloadWrongFormat) {
HsmPlainText hsm_plain_text;
brillo::SecureBlob cbor_output;
cbor::Value::MapValue fake_map;
fake_map.emplace(kMediatorShare, "a string value instead of bytes");
fake_map.emplace(kDealerPublicKey, dealer_pub_key_);
fake_map.emplace(kKeyAuthValue, brillo::SecureBlob());
brillo::SecureBlob hsm_cbor;
ASSERT_TRUE(CreateCborMapForTesting(fake_map, &hsm_cbor));
EXPECT_FALSE(DeserializeHsmPlainTextFromCbor(hsm_cbor, &hsm_plain_text));
}
// Simulates failed attempt to get dealer public key from the Hsm payload
// associated data.
TEST_F(HsmPayloadCborHelperTest, FailedAttemptToGetPlainTextFieldFromAd) {
brillo::SecureBlob cbor_output;
HsmAssociatedData args;
args.publisher_pub_key = publisher_pub_key_;
args.channel_pub_key = channel_pub_key_;
args.onboarding_meta_data = brillo::SecureBlob(kOnboardingData);
ASSERT_TRUE(SerializeHsmAssociatedDataToCbor(args, &cbor_output));
brillo::SecureBlob deserialized_dealer_pub_key;
EXPECT_FALSE(GetBytestringValueFromCborMapByKeyForTesting(
cbor_output, kDealerPublicKey, &deserialized_dealer_pub_key));
}
// Verifies serialization of Recovery Request payload associated data to CBOR.
TEST_F(RecoveryRequestCborHelperTest, GenerateAd) {
brillo::SecureBlob salt("fake salt");
brillo::SecureBlob cbor_output;
HsmPayload hsm_payload;
hsm_payload.cipher_text = brillo::SecureBlob(kFakeHsmPayloadCipherText);
hsm_payload.associated_data = brillo::SecureBlob(kFakeHsmPayloadAd);
hsm_payload.iv = brillo::SecureBlob(kFakeHsmPayloadIv);
hsm_payload.tag = brillo::SecureBlob(kFakeHsmPayloadTag);
RecoveryRequestAssociatedData request_ad;
request_ad.hsm_payload = std::move(hsm_payload);
request_ad.request_meta_data = brillo::SecureBlob(kFakeRequestData);
request_ad.epoch_pub_key = epoch_pub_key_;
request_ad.request_payload_salt = salt;
ASSERT_TRUE(
SerializeRecoveryRequestAssociatedDataToCbor(request_ad, &cbor_output));
HsmPayload deserialized_hsm_payload;
brillo::SecureBlob deserialized_epoch_pub_key;
brillo::SecureBlob deserialized_request_meta_data;
int schema_version;
ASSERT_TRUE(
GetRequestPayloadSchemaVersionForTesting(cbor_output, &schema_version));
EXPECT_EQ(schema_version, kProtocolVersion);
ASSERT_TRUE(GetHsmPayloadFromRequestAdForTesting(cbor_output,
&deserialized_hsm_payload));
EXPECT_EQ(deserialized_hsm_payload.cipher_text.to_string(),
kFakeHsmPayloadCipherText);
EXPECT_EQ(deserialized_hsm_payload.associated_data.to_string(),
kFakeHsmPayloadAd);
EXPECT_EQ(deserialized_hsm_payload.iv.to_string(), kFakeHsmPayloadIv);
EXPECT_EQ(deserialized_hsm_payload.tag.to_string(), kFakeHsmPayloadTag);
ExpectSerializedCborMapContainsValue(cbor_output, kEpochPublicKey,
epoch_pub_key_);
ExpectSerializedCborMapContainsValue(cbor_output, kRequestPayloadSalt, salt);
ExpectSerializedCborMapContainsValue(cbor_output, kRequestMetaData,
brillo::SecureBlob(kFakeRequestData));
// TODO(anastasiian): add schema_version to structs according to the protocol
// description.
// 4 fields + schema version:
EXPECT_EQ(5, GetCborMapSize(cbor_output));
}
// Verifies serialization of Recovery Request payload plain text encrypted
// payload to CBOR.
TEST_F(RecoveryRequestCborHelperTest, GeneratePlainText) {
brillo::SecureBlob ephemeral_inverse_key;
crypto::ScopedBIGNUM scalar = BigNumFromValue(123u);
ASSERT_TRUE(scalar);
BN_set_negative(scalar.get(), 1);
crypto::ScopedEC_POINT inverse_point =
ec_->MultiplyWithGenerator(*scalar, context_.get());
ASSERT_TRUE(ec_->PointToSecureBlob(*inverse_point, &ephemeral_inverse_key,
context_.get()));
brillo::SecureBlob cbor_output;
RecoveryRequestPlainText plain_text;
plain_text.ephemeral_pub_inv_key = ephemeral_inverse_key;
ASSERT_TRUE(
SerializeRecoveryRequestPlainTextToCbor(plain_text, &cbor_output));
ExpectSerializedCborMapContainsValue(cbor_output, kEphemeralPublicInvKey,
ephemeral_inverse_key);
EXPECT_EQ(1, GetCborMapSize(cbor_output));
}
// Verifies serialization of Recovery Request to CBOR.
TEST_F(RecoveryRequestCborHelperTest, SerializeRecoveryRequest) {
RecoveryRequest request;
request.request_payload = aead_helper_.GetFakePayload();
brillo::SecureBlob cbor_output;
EXPECT_TRUE(SerializeRecoveryRequestToCbor(request, &cbor_output));
cbor::Value deserialized_request_payload;
EXPECT_TRUE(GetValueFromCborMapByKeyForTesting(
cbor_output, kRequestAead, &deserialized_request_payload));
ASSERT_TRUE(deserialized_request_payload.is_map());
aead_helper_.ExpectEqualsToFakeAeadPayload(
deserialized_request_payload.GetMap());
}
// Verifies deserialization of Recovery Request from CBOR.
TEST_F(RecoveryRequestCborHelperTest, DeserializeRecoveryRequest) {
cbor::Value::MapValue request;
request.emplace(kRequestAead, aead_helper_.GetFakePayloadCborMap());
brillo::SecureBlob request_cbor;
ASSERT_TRUE(CreateCborMapForTesting(request, &request_cbor));
RecoveryRequest recovery_request;
EXPECT_TRUE(
DeserializeRecoveryRequestFromCbor(request_cbor, &recovery_request));
aead_helper_.ExpectEqualsToFakeAeadPayload(recovery_request.request_payload);
}
// Verifies that deserialization of Recovery Request from CBOR fails if payload
// has wrong format.
TEST_F(RecoveryRequestCborHelperTest, DeserializeRecoveryRequestWrongFormat) {
brillo::SecureBlob payload_cbor;
ASSERT_TRUE(CreateCborMapForTesting(aead_helper_.GetFakePayloadCborMap(),
&payload_cbor));
cbor::Value::MapValue request;
// Field value is serialized CBOR instead of nested map.
request.emplace(kRequestAead, payload_cbor);
brillo::SecureBlob request_cbor;
ASSERT_TRUE(CreateCborMapForTesting(request, &request_cbor));
RecoveryRequest recovery_request;
EXPECT_FALSE(
DeserializeRecoveryRequestFromCbor(request_cbor, &recovery_request));
}
// Verifies that deserialization of Recovery Request from CBOR fails if payload
// has a missing field.
TEST_F(RecoveryRequestCborHelperTest, DeserializeRecoveryRequestMissingField) {
cbor::Value::MapValue payload = aead_helper_.GetFakePayloadCborMap();
// Remove `iv` value.
payload.erase(payload.find(cbor::Value(kAeadIv)));
cbor::Value::MapValue request;
request.emplace(kRequestAead, payload);
brillo::SecureBlob request_cbor;
ASSERT_TRUE(CreateCborMapForTesting(request, &request_cbor));
RecoveryRequest recovery_request;
EXPECT_FALSE(
DeserializeRecoveryRequestFromCbor(request_cbor, &recovery_request));
}
// Verifies serialization of Response payload associated data to CBOR.
TEST_F(RecoveryResponseCborHelperTest, SerializeAssociatedData) {
HsmResponseAssociatedData response_ad;
response_ad.response_meta_data = metadata_;
response_ad.response_payload_salt = salt_;
brillo::SecureBlob cbor_output;
ASSERT_TRUE(
SerializeHsmResponseAssociatedDataToCbor(response_ad, &cbor_output));
ExpectSerializedCborMapContainsValue(cbor_output, kResponseMetaData,
metadata_);
ExpectSerializedCborMapContainsValue(cbor_output, kResponsePayloadSalt,
salt_);
EXPECT_EQ(2, GetCborMapSize(cbor_output));
}
// Verifies serialization of Response payload plain text to CBOR, without kav.
TEST_F(RecoveryResponseCborHelperTest, SerializePlainTextWithoutKav) {
brillo::SecureBlob mediated_point("mediated point");
HsmResponsePlainText response_plain_text;
response_plain_text.mediated_point = mediated_point;
response_plain_text.dealer_pub_key = fake_pub_key_;
response_plain_text.key_auth_value = brillo::SecureBlob();
brillo::SecureBlob cbor_output;
ASSERT_TRUE(
SerializeHsmResponsePlainTextToCbor(response_plain_text, &cbor_output));
ExpectSerializedCborMapContainsValue(cbor_output, kMediatedPoint,
mediated_point);
ExpectSerializedCborMapContainsValue(cbor_output, kDealerPublicKey,
fake_pub_key_);
ExpectSerializedCborMapContainsValue(cbor_output, kKeyAuthValue,
brillo::SecureBlob());
EXPECT_EQ(3, GetCborMapSize(cbor_output));
}
// Verifies serialization of Response payload plain text to CBOR.
TEST_F(RecoveryResponseCborHelperTest, SerializePlainText) {
brillo::SecureBlob mediated_point("mediated point");
brillo::SecureBlob key_auth_value("key auth value");
HsmResponsePlainText response_plain_text;
response_plain_text.mediated_point = mediated_point;
response_plain_text.dealer_pub_key = fake_pub_key_;
response_plain_text.key_auth_value = key_auth_value;
brillo::SecureBlob cbor_output;
ASSERT_TRUE(
SerializeHsmResponsePlainTextToCbor(response_plain_text, &cbor_output));
ExpectSerializedCborMapContainsValue(cbor_output, kMediatedPoint,
mediated_point);
ExpectSerializedCborMapContainsValue(cbor_output, kDealerPublicKey,
fake_pub_key_);
ExpectSerializedCborMapContainsValue(cbor_output, kKeyAuthValue,
key_auth_value);
EXPECT_EQ(3, GetCborMapSize(cbor_output));
}
// Verifies deserialization of Response payload associated data from CBOR.
TEST_F(RecoveryResponseCborHelperTest, DeserializeAssociatedData) {
cbor::Value::MapValue fake_map;
fake_map.emplace(kResponseMetaData, metadata_);
fake_map.emplace(kResponsePayloadSalt, salt_);
brillo::SecureBlob response_cbor;
ASSERT_TRUE(CreateCborMapForTesting(fake_map, &response_cbor));
HsmResponseAssociatedData response_ad;
EXPECT_TRUE(DeserializeHsmResponseAssociatedDataFromCbor(response_cbor,
&response_ad));
EXPECT_EQ(response_ad.response_meta_data, metadata_);
EXPECT_EQ(response_ad.response_payload_salt, salt_);
}
// Verifies that deserialization of Response payload associated data from CBOR
// fails when input is not a map.
TEST_F(RecoveryResponseCborHelperTest, DeserializeAssociatedDataNotMap) {
base::Optional<std::vector<uint8_t>> serialized =
cbor::Writer::Write(cbor::Value("a CBOR but not a map"));
ASSERT_TRUE(serialized.has_value());
brillo::SecureBlob response_cbor(serialized.value().begin(),
serialized.value().end());
HsmResponseAssociatedData response_ad;
EXPECT_FALSE(DeserializeHsmResponseAssociatedDataFromCbor(response_cbor,
&response_ad));
}
// Verifies that deserialization of Response payload associated data from CBOR
// fails when a field has a wrong format.
TEST_F(RecoveryResponseCborHelperTest, DeserializeAssociatedDataWrongFormat) {
cbor::Value::MapValue fake_map;
fake_map.emplace(kResponseMetaData, "a string value instead of bytes");
fake_map.emplace(kResponsePayloadSalt, salt_);
brillo::SecureBlob response_cbor;
ASSERT_TRUE(CreateCborMapForTesting(fake_map, &response_cbor));
HsmResponseAssociatedData response_ad;
EXPECT_FALSE(DeserializeHsmResponseAssociatedDataFromCbor(response_cbor,
&response_ad));
}
// Verifies deserialization of Response payload plain text from CBOR.
TEST_F(RecoveryResponseCborHelperTest, DeserializePlainText) {
brillo::SecureBlob mediated_point("mediated point");
cbor::Value::MapValue fake_map;
fake_map.emplace(kMediatedPoint, mediated_point);
fake_map.emplace(kDealerPublicKey, fake_pub_key_);
fake_map.emplace(kKeyAuthValue, brillo::SecureBlob());
brillo::SecureBlob response_cbor;
ASSERT_TRUE(CreateCborMapForTesting(fake_map, &response_cbor));
HsmResponsePlainText response_plain_text;
EXPECT_TRUE(DeserializeHsmResponsePlainTextFromCbor(response_cbor,
&response_plain_text));
EXPECT_EQ(response_plain_text.mediated_point, mediated_point);
EXPECT_EQ(response_plain_text.dealer_pub_key, fake_pub_key_);
EXPECT_EQ(response_plain_text.key_auth_value, brillo::SecureBlob());
}
// Verifies that deserialization of Response payload plain text from CBOR fails
// when input is not a map.
TEST_F(RecoveryResponseCborHelperTest, DeserializePlainTextNotMap) {
base::Optional<std::vector<uint8_t>> serialized =
cbor::Writer::Write(cbor::Value("a CBOR but not a map"));
ASSERT_TRUE(serialized.has_value());
brillo::SecureBlob response_cbor(serialized.value().begin(),
serialized.value().end());
HsmResponsePlainText response_plain_text;
EXPECT_FALSE(DeserializeHsmResponsePlainTextFromCbor(response_cbor,
&response_plain_text));
}
// Verifies that deserialization of Response payload plain text from CBOR fails
// when a field has a wrong format.
TEST_F(RecoveryResponseCborHelperTest, DeserializePlainTextWrongFormat) {
cbor::Value::MapValue fake_map;
fake_map.emplace(kMediatedPoint, "a string value instead of bytes");
fake_map.emplace(kDealerPublicKey, fake_pub_key_);
fake_map.emplace(kKeyAuthValue, brillo::SecureBlob());
brillo::SecureBlob response_cbor;
ASSERT_TRUE(CreateCborMapForTesting(fake_map, &response_cbor));
HsmResponsePlainText response_plain_text;
EXPECT_FALSE(DeserializeHsmResponsePlainTextFromCbor(response_cbor,
&response_plain_text));
}
// Verifies serialization of Recovery Response to CBOR.
TEST_F(RecoveryResponseCborHelperTest, SerializeRecoveryResponse) {
RecoveryResponse response;
response.response_payload = aead_helper_.GetFakePayload();
response.error_code = fake_error_code_;
response.error_string = fake_error_string_;
brillo::SecureBlob cbor_output;
EXPECT_TRUE(SerializeRecoveryResponseToCbor(response, &cbor_output));
cbor::Value deserialized_error_code;
EXPECT_TRUE(GetValueFromCborMapByKeyForTesting(
cbor_output, kResponseErrorCode, &deserialized_error_code));
ASSERT_TRUE(deserialized_error_code.is_integer());
EXPECT_EQ(deserialized_error_code.GetInteger(), response.error_code);
cbor::Value deserialized_error_string;
EXPECT_TRUE(GetValueFromCborMapByKeyForTesting(
cbor_output, kResponseErrorString, &deserialized_error_string));
ASSERT_TRUE(deserialized_error_string.is_string());
EXPECT_EQ(deserialized_error_string.GetString(), response.error_string);
cbor::Value deserialized_response_payload;
EXPECT_TRUE(GetValueFromCborMapByKeyForTesting(
cbor_output, kResponseAead, &deserialized_response_payload));
ASSERT_TRUE(deserialized_response_payload.is_map());
aead_helper_.ExpectEqualsToFakeAeadPayload(
deserialized_response_payload.GetMap());
EXPECT_EQ(3, GetCborMapSize(cbor_output));
}
// Verifies deserialization of Recovery Response from CBOR.
TEST_F(RecoveryResponseCborHelperTest, DeserializeRecoveryResponse) {
cbor::Value::MapValue response;
response.emplace(kResponseAead, aead_helper_.GetFakePayloadCborMap());
response.emplace(kResponseErrorCode, fake_error_code_);
response.emplace(kResponseErrorString, fake_error_string_);
brillo::SecureBlob response_cbor;
ASSERT_TRUE(CreateCborMapForTesting(response, &response_cbor));
RecoveryResponse recovery_response;
EXPECT_TRUE(
DeserializeRecoveryResponseFromCbor(response_cbor, &recovery_response));
EXPECT_EQ(recovery_response.error_code, fake_error_code_);
EXPECT_EQ(recovery_response.error_string, fake_error_string_);
aead_helper_.ExpectEqualsToFakeAeadPayload(
recovery_response.response_payload);
}
// Verifies that deserialization of Recovery Response from CBOR fails if payload
// has a wrong format.
TEST_F(RecoveryResponseCborHelperTest, DeserializeRecoveryResponseWrongFormat) {
brillo::SecureBlob payload_cbor;
ASSERT_TRUE(CreateCborMapForTesting(aead_helper_.GetFakePayloadCborMap(),
&payload_cbor));
cbor::Value::MapValue response;
// Field value is serialized CBOR instead of nested map.
response.emplace(kResponseAead, payload_cbor);
response.emplace(kResponseErrorCode, fake_error_code_);
response.emplace(kResponseErrorString, fake_error_string_);
brillo::SecureBlob response_cbor;
ASSERT_TRUE(CreateCborMapForTesting(response, &response_cbor));
RecoveryResponse recovery_response;
EXPECT_FALSE(
DeserializeRecoveryResponseFromCbor(response_cbor, &recovery_response));
}
} // namespace cryptorecovery
} // namespace cryptohome