blob: c68ba5f24264567f2d593384781419cf48e7bfd2 [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/crypto/recovery_crypto_hsm_cbor_serialization.h"
#include <base/optional.h>
#include <brillo/secure_blob.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"
namespace cryptohome {
namespace {
constexpr EllipticCurve::CurveType kCurve = EllipticCurve::CurveType::kPrime256;
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";
} // 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 RequestPayloadCborHelperTest : 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:
ScopedBN_CTX context_;
base::Optional<EllipticCurve> ec_;
brillo::SecureBlob epoch_pub_key_;
brillo::SecureBlob epoch_priv_key_;
};
// Verifies serialization of HSM payload associated data to CBOR.
TEST_F(HsmPayloadCborHelperTest, GenerateAdCborWithoutRsaPublicKey) {
brillo::SecureBlob rsa_public_key;
brillo::SecureBlob onboarding_data(kOnboardingData);
brillo::SecureBlob cbor_output;
ASSERT_TRUE(SerializeHsmAssociatedDataToCbor(publisher_pub_key_,
channel_pub_key_, rsa_public_key,
onboarding_data, &cbor_output));
brillo::SecureBlob deserialized_publisher_pub_key;
brillo::SecureBlob deserialized_channel_pub_key;
brillo::SecureBlob deserialized_onboarding_data;
ASSERT_TRUE(GetHsmCborMapByKeyForTesting(cbor_output, kPublisherPublicKey,
&deserialized_publisher_pub_key));
EXPECT_EQ(publisher_pub_key_, deserialized_publisher_pub_key);
ASSERT_TRUE(GetHsmCborMapByKeyForTesting(cbor_output, kChannelPublicKey,
&deserialized_channel_pub_key));
EXPECT_EQ(channel_pub_key_, deserialized_channel_pub_key);
ASSERT_TRUE(GetHsmCborMapByKeyForTesting(cbor_output, kOnboardingMetaData,
&deserialized_onboarding_data));
EXPECT_EQ(deserialized_onboarding_data.to_string(), kOnboardingData);
}
// 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.
ASSERT_TRUE(SerializeHsmPlainTextToCbor(mediator_share, dealer_pub_key_,
/*kav=*/brillo::SecureBlob(),
&cbor_output));
brillo::SecureBlob deserialized_dealer_pub_key;
brillo::SecureBlob deserialized_mediator_share;
brillo::SecureBlob deserialized_key_auth_value;
ASSERT_TRUE(GetHsmCborMapByKeyForTesting(cbor_output, kDealerPublicKey,
&deserialized_dealer_pub_key));
EXPECT_EQ(dealer_pub_key_, deserialized_dealer_pub_key);
ASSERT_TRUE(GetHsmCborMapByKeyForTesting(cbor_output, kMediatorShare,
&deserialized_mediator_share));
EXPECT_EQ(BN_get_word(scalar.get()),
BN_get_word(SecureBlobToBigNum(deserialized_mediator_share).get()));
ASSERT_TRUE(GetHsmCborMapByKeyForTesting(cbor_output, kKeyAuthValue,
&deserialized_key_auth_value));
EXPECT_TRUE(deserialized_key_auth_value.empty());
}
// Simulates failed attempt to get dealer public key from the Hsm payload
// associated data..
TEST_F(HsmPayloadCborHelperTest, FailedAttemptToGetPlainTextFieldFromAd) {
brillo::SecureBlob onboarding_data(kOnboardingData);
brillo::SecureBlob cbor_output;
ASSERT_TRUE(SerializeHsmAssociatedDataToCbor(
publisher_pub_key_, channel_pub_key_,
/*rsa_public_key*/ brillo::SecureBlob(), onboarding_data, &cbor_output));
brillo::SecureBlob deserialized_dealer_pub_key;
EXPECT_FALSE(GetHsmCborMapByKeyForTesting(cbor_output, kDealerPublicKey,
&deserialized_dealer_pub_key));
}
// Verifies serialization of Recovery Request payload associated data to CBOR.
TEST_F(RequestPayloadCborHelperTest, GenerateAd) {
brillo::SecureBlob request_meta_data(kFakeRequestData);
brillo::SecureBlob hsm_aead_ct(kFakeHsmPayloadCipherText);
brillo::SecureBlob hsm_aead_ad(kFakeHsmPayloadAd);
brillo::SecureBlob hsm_aead_iv(kFakeHsmPayloadIv);
brillo::SecureBlob hsm_aead_tag(kFakeHsmPayloadTag);
brillo::SecureBlob cbor_output;
ASSERT_TRUE(SerializeRecoveryRequestAssociatedDataToCbor(
hsm_aead_ct, hsm_aead_ad, hsm_aead_iv, hsm_aead_tag, request_meta_data,
epoch_pub_key_, &cbor_output));
brillo::SecureBlob deserialized_epoch_pub_key;
brillo::SecureBlob deserialized_hsm_aead_ct;
brillo::SecureBlob deserialized_hsm_aead_ad;
brillo::SecureBlob deserialized_hsm_aead_iv;
brillo::SecureBlob deserialized_hsm_aead_tag;
brillo::SecureBlob deserialized_request_meta_data;
int schema_version;
ASSERT_TRUE(
GetRequestPayloadSchemaVersionForTesting(cbor_output, &schema_version));
EXPECT_EQ(schema_version, kProtocolVersion);
ASSERT_TRUE(GetHsmCborMapByKeyForTesting(cbor_output, kHsmAeadCipherText,
&deserialized_hsm_aead_ct));
EXPECT_EQ(deserialized_hsm_aead_ct.to_string(), kFakeHsmPayloadCipherText);
ASSERT_TRUE(GetHsmCborMapByKeyForTesting(cbor_output, kHsmAeadAd,
&deserialized_hsm_aead_ad));
EXPECT_EQ(deserialized_hsm_aead_ad.to_string(), kFakeHsmPayloadAd);
ASSERT_TRUE(GetHsmCborMapByKeyForTesting(cbor_output, kHsmAeadIv,
&deserialized_hsm_aead_iv));
EXPECT_EQ(deserialized_hsm_aead_iv.to_string(), kFakeHsmPayloadIv);
ASSERT_TRUE(GetHsmCborMapByKeyForTesting(cbor_output, kHsmAeadTag,
&deserialized_hsm_aead_tag));
EXPECT_EQ(deserialized_hsm_aead_tag.to_string(), kFakeHsmPayloadTag);
ASSERT_TRUE(GetHsmCborMapByKeyForTesting(cbor_output, kEpochPublicKey,
&deserialized_epoch_pub_key));
EXPECT_EQ(epoch_pub_key_, deserialized_epoch_pub_key);
ASSERT_TRUE(GetHsmCborMapByKeyForTesting(cbor_output, kRequestMetaData,
&deserialized_request_meta_data));
EXPECT_EQ(deserialized_request_meta_data.to_string(), kFakeRequestData);
}
// Verifies serialization of Recovery Request payload plain text encrypted
// payload to CBOR.
TEST_F(RequestPayloadCborHelperTest, 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;
ASSERT_TRUE(SerializeRecoveryRequestPlainTextToCbor(ephemeral_inverse_key,
&cbor_output));
brillo::SecureBlob deserialized_ephemeral_inverse_key;
ASSERT_TRUE(
GetHsmCborMapByKeyForTesting(cbor_output, kEphemeralPublicInvKey,
&deserialized_ephemeral_inverse_key));
EXPECT_EQ(ephemeral_inverse_key, deserialized_ephemeral_inverse_key);
}
} // namespace cryptohome