blob: 625657207860e952778171ee5f3acabe7e9161a8 [file] [log] [blame] [edit]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <cstdint>
#include <memory>
#include <utility>
#include <gtest/gtest.h>
#include <libhwsec-foundation/error/testing_helper.h>
#include <trunks/mock_tpm_utility.h>
#include "base/hash/sha1.h"
#include "libhwsec/backend/tpm2/backend_test_base.h"
#include "trunks/tpm_generated.h"
// Prevent the conflict definition from tss.h
#undef TPM_ALG_RSA
using hwsec_foundation::error::testing::IsOk;
using hwsec_foundation::error::testing::IsOkAndHolds;
using hwsec_foundation::error::testing::NotOk;
using hwsec_foundation::error::testing::NotOkWith;
using hwsec_foundation::error::testing::ReturnError;
using hwsec_foundation::error::testing::ReturnValue;
using testing::_;
using testing::DoAll;
using testing::NiceMock;
using testing::Return;
using testing::SaveArg;
using testing::SetArgPointee;
using tpm_manager::TpmManagerStatus;
namespace hwsec {
using BackendSigningTpm2Test = BackendTpm2TestBase;
TEST_F(BackendSigningTpm2Test, SignRSA) {
const OperationPolicy kFakePolicy{};
const std::string kFakeKeyBlob = "fake_key_blob";
const std::string kDataToSign = "data_to_sign";
const std::string kSignature = "signature";
const uint32_t kFakeKeyHandle = 0x1337;
const trunks::TPMT_PUBLIC kFakePublic = {
.type = trunks::TPM_ALG_RSA,
.name_alg = trunks::TPM_ALG_SHA256,
.object_attributes =
trunks::kFixedTPM | trunks::kFixedParent | trunks::kSign,
.auth_policy = trunks::TPM2B_DIGEST{.size = 0},
.parameters =
trunks::TPMU_PUBLIC_PARMS{
.rsa_detail =
trunks::TPMS_RSA_PARMS{
.symmetric =
trunks::TPMT_SYM_DEF_OBJECT{
.algorithm = trunks::TPM_ALG_NULL,
},
.scheme =
trunks::TPMT_RSA_SCHEME{
.scheme = trunks::TPM_ALG_NULL,
},
.key_bits = 2048,
.exponent = 0,
},
},
.unique =
trunks::TPMU_PUBLIC_ID{
.rsa =
trunks::TPM2B_PUBLIC_KEY_RSA{
.size = 10,
.buffer = "9876543210",
},
},
};
EXPECT_CALL(proxy_->GetMockTpmUtility(), LoadKey(kFakeKeyBlob, _, _))
.WillOnce(DoAll(SetArgPointee<2>(kFakeKeyHandle),
Return(trunks::TPM_RC_SUCCESS)));
EXPECT_CALL(proxy_->GetMockTpmUtility(), GetKeyPublicArea(kFakeKeyHandle, _))
.WillOnce(
DoAll(SetArgPointee<1>(kFakePublic), Return(trunks::TPM_RC_SUCCESS)));
auto key = backend_->GetKeyManagementTpm2().LoadKey(
kFakePolicy, brillo::BlobFromString(kFakeKeyBlob),
Backend::KeyManagement::LoadKeyOptions{});
ASSERT_OK(key);
EXPECT_CALL(proxy_->GetMockTpmUtility(),
Sign(kFakeKeyHandle, trunks::TPM_ALG_RSASSA,
trunks::TPM_ALG_SHA256, kDataToSign, false, _, _))
.WillOnce(
DoAll(SetArgPointee<6>(kSignature), Return(trunks::TPM_RC_SUCCESS)));
EXPECT_THAT(
backend_->GetSigningTpm2().RawSign(
key->GetKey(), brillo::BlobFromString(kDataToSign),
SigningOptions{
.digest_algorithm = DigestAlgorithm::kSha256,
.rsa_padding_scheme = SigningOptions::RsaPaddingScheme::kPkcs1v15,
}),
IsOkAndHolds(brillo::BlobFromString(kSignature)));
}
TEST_F(BackendSigningTpm2Test, SignECCSha1Raw) {
const OperationPolicy kFakePolicy{};
const std::string kFakeKeyBlob = "fake_key_blob";
const std::string kDataToHash = "data_to_sign";
const std::string kDataToSign = base::SHA1HashString(kDataToHash);
trunks::TPMT_SIGNATURE fake_signature;
const std::string kSignatureR = "signature_r";
const std::string kSignatureS = "signature_s";
fake_signature.sig_alg = trunks::TPM_ALG_ECDSA;
fake_signature.signature.ecdsa.signature_r =
trunks::Make_TPM2B_ECC_PARAMETER(kSignatureR);
fake_signature.signature.ecdsa.signature_s =
trunks::Make_TPM2B_ECC_PARAMETER(kSignatureS);
std::string kSignature;
ASSERT_EQ(Serialize_TPMT_SIGNATURE(fake_signature, &kSignature),
trunks::TPM_RC_SUCCESS);
const uint32_t kFakeKeyHandle = 0x1337;
const trunks::TPMT_PUBLIC kFakePublic = {
.type = trunks::TPM_ALG_ECC,
.name_alg = trunks::TPM_ALG_SHA1,
.object_attributes =
trunks::kFixedTPM | trunks::kFixedParent | trunks::kSign,
.auth_policy = trunks::TPM2B_DIGEST{.size = 0},
.parameters =
trunks::TPMU_PUBLIC_PARMS{
.ecc_detail =
trunks::TPMS_ECC_PARMS{
.symmetric =
trunks::TPMT_SYM_DEF_OBJECT{
.algorithm = trunks::TPM_ALG_NULL,
},
.scheme =
trunks::TPMT_ECC_SCHEME{
.scheme = trunks::TPM_ALG_NULL,
},
.curve_id = trunks::TPM_ECC_NIST_P256,
.kdf =
trunks::TPMT_KDF_SCHEME{
.scheme = trunks::TPM_ALG_NULL,
},
},
},
.unique =
trunks::TPMU_PUBLIC_ID{
.ecc =
trunks::TPMS_ECC_POINT{
.x =
trunks::TPM2B_ECC_PARAMETER{
.size = 10,
.buffer = "0123456789",
},
.y = trunks::TPM2B_ECC_PARAMETER{.size = 0},
},
},
};
EXPECT_CALL(proxy_->GetMockTpmUtility(), LoadKey(kFakeKeyBlob, _, _))
.WillOnce(DoAll(SetArgPointee<2>(kFakeKeyHandle),
Return(trunks::TPM_RC_SUCCESS)));
EXPECT_CALL(proxy_->GetMockTpmUtility(), GetKeyPublicArea(kFakeKeyHandle, _))
.WillOnce(
DoAll(SetArgPointee<1>(kFakePublic), Return(trunks::TPM_RC_SUCCESS)));
auto key = backend_->GetKeyManagementTpm2().LoadKey(
kFakePolicy, brillo::BlobFromString(kFakeKeyBlob),
Backend::KeyManagement::LoadKeyOptions{});
ASSERT_OK(key);
EXPECT_CALL(proxy_->GetMockTpmUtility(),
Sign(kFakeKeyHandle, trunks::TPM_ALG_ECDSA, trunks::TPM_ALG_SHA1,
kDataToSign, false, _, _))
.WillOnce(
DoAll(SetArgPointee<6>(kSignature), Return(trunks::TPM_RC_SUCCESS)));
EXPECT_THAT(backend_->GetSigningTpm2().RawSign(
key->GetKey(), brillo::BlobFromString(kDataToSign),
SigningOptions{
.digest_algorithm = DigestAlgorithm::kNoDigest,
}),
IsOkAndHolds(brillo::BlobFromString(kSignatureR + kSignatureS)));
}
TEST_F(BackendSigningTpm2Test, SignECC) {
const OperationPolicy kFakePolicy{};
const std::string kFakeKeyBlob = "fake_key_blob";
const std::string kDataToSign = "data_to_sign";
trunks::TPMT_SIGNATURE fake_signature;
const std::string kSignatureR = "signature_r";
const std::string kSignatureS = "signature_s";
fake_signature.sig_alg = trunks::TPM_ALG_ECDSA;
fake_signature.signature.ecdsa.signature_r =
trunks::Make_TPM2B_ECC_PARAMETER(kSignatureR);
fake_signature.signature.ecdsa.signature_s =
trunks::Make_TPM2B_ECC_PARAMETER(kSignatureS);
std::string kSignature;
ASSERT_EQ(Serialize_TPMT_SIGNATURE(fake_signature, &kSignature),
trunks::TPM_RC_SUCCESS);
const uint32_t kFakeKeyHandle = 0x1337;
const trunks::TPMT_PUBLIC kFakePublic = {
.type = trunks::TPM_ALG_ECC,
.name_alg = trunks::TPM_ALG_SHA1,
.object_attributes =
trunks::kFixedTPM | trunks::kFixedParent | trunks::kSign,
.auth_policy = trunks::TPM2B_DIGEST{.size = 0},
.parameters =
trunks::TPMU_PUBLIC_PARMS{
.ecc_detail =
trunks::TPMS_ECC_PARMS{
.symmetric =
trunks::TPMT_SYM_DEF_OBJECT{
.algorithm = trunks::TPM_ALG_NULL,
},
.scheme =
trunks::TPMT_ECC_SCHEME{
.scheme = trunks::TPM_ALG_NULL,
},
.curve_id = trunks::TPM_ECC_NIST_P256,
.kdf =
trunks::TPMT_KDF_SCHEME{
.scheme = trunks::TPM_ALG_NULL,
},
},
},
.unique =
trunks::TPMU_PUBLIC_ID{
.ecc =
trunks::TPMS_ECC_POINT{
.x =
trunks::TPM2B_ECC_PARAMETER{
.size = 10,
.buffer = "0123456789",
},
.y = trunks::TPM2B_ECC_PARAMETER{.size = 0},
},
},
};
EXPECT_CALL(proxy_->GetMockTpmUtility(), LoadKey(kFakeKeyBlob, _, _))
.WillOnce(DoAll(SetArgPointee<2>(kFakeKeyHandle),
Return(trunks::TPM_RC_SUCCESS)));
EXPECT_CALL(proxy_->GetMockTpmUtility(), GetKeyPublicArea(kFakeKeyHandle, _))
.WillOnce(
DoAll(SetArgPointee<1>(kFakePublic), Return(trunks::TPM_RC_SUCCESS)));
auto key = backend_->GetKeyManagementTpm2().LoadKey(
kFakePolicy, brillo::BlobFromString(kFakeKeyBlob),
Backend::KeyManagement::LoadKeyOptions{});
ASSERT_OK(key);
EXPECT_CALL(proxy_->GetMockTpmUtility(),
Sign(kFakeKeyHandle, trunks::TPM_ALG_ECDSA, trunks::TPM_ALG_SHA1,
kDataToSign, false, _, _))
.WillOnce(
DoAll(SetArgPointee<6>(kSignature), Return(trunks::TPM_RC_SUCCESS)));
EXPECT_THAT(backend_->GetSigningTpm2().RawSign(
key->GetKey(), brillo::BlobFromString(kDataToSign),
SigningOptions{
.digest_algorithm = DigestAlgorithm::kSha1,
}),
IsOkAndHolds(brillo::BlobFromString(kSignatureR + kSignatureS)));
}
TEST_F(BackendSigningTpm2Test, SignECCWrongResponse) {
const OperationPolicy kFakePolicy{};
const std::string kFakeKeyBlob = "fake_key_blob";
const std::string kDataToSign = "data_to_sign";
const std::string kSignature = "wrong_signature";
const uint32_t kFakeKeyHandle = 0x1337;
const trunks::TPMT_PUBLIC kFakePublic = {
.type = trunks::TPM_ALG_ECC,
.name_alg = trunks::TPM_ALG_SHA256,
.object_attributes =
trunks::kFixedTPM | trunks::kFixedParent | trunks::kSign,
.auth_policy = trunks::TPM2B_DIGEST{.size = 0},
.parameters =
trunks::TPMU_PUBLIC_PARMS{
.ecc_detail =
trunks::TPMS_ECC_PARMS{
.symmetric =
trunks::TPMT_SYM_DEF_OBJECT{
.algorithm = trunks::TPM_ALG_NULL,
},
.scheme =
trunks::TPMT_ECC_SCHEME{
.scheme = trunks::TPM_ALG_NULL,
},
.curve_id = trunks::TPM_ECC_NIST_P256,
.kdf =
trunks::TPMT_KDF_SCHEME{
.scheme = trunks::TPM_ALG_NULL,
},
},
},
.unique =
trunks::TPMU_PUBLIC_ID{
.ecc =
trunks::TPMS_ECC_POINT{
.x =
trunks::TPM2B_ECC_PARAMETER{
.size = 10,
.buffer = "0123456789",
},
.y = trunks::TPM2B_ECC_PARAMETER{.size = 0},
},
},
};
EXPECT_CALL(proxy_->GetMockTpmUtility(), LoadKey(kFakeKeyBlob, _, _))
.WillOnce(DoAll(SetArgPointee<2>(kFakeKeyHandle),
Return(trunks::TPM_RC_SUCCESS)));
EXPECT_CALL(proxy_->GetMockTpmUtility(), GetKeyPublicArea(kFakeKeyHandle, _))
.WillOnce(
DoAll(SetArgPointee<1>(kFakePublic), Return(trunks::TPM_RC_SUCCESS)));
auto key = backend_->GetKeyManagementTpm2().LoadKey(
kFakePolicy, brillo::BlobFromString(kFakeKeyBlob),
Backend::KeyManagement::LoadKeyOptions{});
ASSERT_OK(key);
EXPECT_CALL(proxy_->GetMockTpmUtility(),
Sign(kFakeKeyHandle, trunks::TPM_ALG_ECDSA,
trunks::TPM_ALG_SHA256, kDataToSign, false, _, _))
.WillOnce(
DoAll(SetArgPointee<6>(kSignature), Return(trunks::TPM_RC_SUCCESS)));
EXPECT_THAT(backend_->GetSigningTpm2().RawSign(
key->GetKey(), brillo::BlobFromString(kDataToSign),
SigningOptions{
.digest_algorithm = DigestAlgorithm::kSha256,
}),
NotOk());
}
TEST_F(BackendSigningTpm2Test, SignUnknownKey) {
const OperationPolicy kFakePolicy{};
const std::string kFakeKeyBlob = "fake_key_blob";
const std::string kDataToSign = "data_to_sign";
const std::string kSignature = "signature";
const uint32_t kFakeKeyHandle = 0x1337;
const trunks::TPMT_PUBLIC kFakePublic = {
.type = trunks::TPM_ALG_KEYEDHASH,
.name_alg = trunks::TPM_ALG_SHA256,
.object_attributes = trunks::kFixedTPM | trunks::kFixedParent,
.auth_policy = trunks::TPM2B_DIGEST{.size = 0},
};
EXPECT_CALL(proxy_->GetMockTpmUtility(), LoadKey(kFakeKeyBlob, _, _))
.WillOnce(DoAll(SetArgPointee<2>(kFakeKeyHandle),
Return(trunks::TPM_RC_SUCCESS)));
EXPECT_CALL(proxy_->GetMockTpmUtility(), GetKeyPublicArea(kFakeKeyHandle, _))
.WillOnce(
DoAll(SetArgPointee<1>(kFakePublic), Return(trunks::TPM_RC_SUCCESS)));
auto key = backend_->GetKeyManagementTpm2().LoadKey(
kFakePolicy, brillo::BlobFromString(kFakeKeyBlob),
Backend::KeyManagement::LoadKeyOptions{});
ASSERT_OK(key);
EXPECT_THAT(
backend_->GetSigningTpm2().Sign(
key->GetKey(), brillo::BlobFromString(kDataToSign),
SigningOptions{
.digest_algorithm = DigestAlgorithm::kSha256,
.rsa_padding_scheme = SigningOptions::RsaPaddingScheme::kPkcs1v15,
}),
NotOkWith("Unknown TPM key type"));
}
TEST_F(BackendSigningTpm2Test, SignRSAPkcs1v15WithNull) {
const OperationPolicy kFakePolicy{};
const std::string kFakeKeyBlob = "fake_key_blob";
const std::string kDataToSign = "data_to_sign";
const std::string kSignature = "signature";
const uint32_t kFakeKeyHandle = 0x1337;
const trunks::TPMT_PUBLIC kFakePublic = {
.type = trunks::TPM_ALG_RSA,
.name_alg = trunks::TPM_ALG_SHA256,
.object_attributes =
trunks::kFixedTPM | trunks::kFixedParent | trunks::kSign,
.auth_policy = trunks::TPM2B_DIGEST{.size = 0},
.parameters =
trunks::TPMU_PUBLIC_PARMS{
.rsa_detail =
trunks::TPMS_RSA_PARMS{
.symmetric =
trunks::TPMT_SYM_DEF_OBJECT{
.algorithm = trunks::TPM_ALG_NULL,
},
.scheme =
trunks::TPMT_RSA_SCHEME{
.scheme = trunks::TPM_ALG_NULL,
},
.key_bits = 2048,
.exponent = 0,
},
},
.unique =
trunks::TPMU_PUBLIC_ID{
.rsa =
trunks::TPM2B_PUBLIC_KEY_RSA{
.size = 10,
.buffer = "9876543210",
},
},
};
EXPECT_CALL(proxy_->GetMockTpmUtility(), LoadKey(kFakeKeyBlob, _, _))
.WillOnce(DoAll(SetArgPointee<2>(kFakeKeyHandle),
Return(trunks::TPM_RC_SUCCESS)));
EXPECT_CALL(proxy_->GetMockTpmUtility(), GetKeyPublicArea(kFakeKeyHandle, _))
.WillOnce(
DoAll(SetArgPointee<1>(kFakePublic), Return(trunks::TPM_RC_SUCCESS)));
auto key = backend_->GetKeyManagementTpm2().LoadKey(
kFakePolicy, brillo::BlobFromString(kFakeKeyBlob),
Backend::KeyManagement::LoadKeyOptions{});
ASSERT_OK(key);
EXPECT_CALL(proxy_->GetMockTpmUtility(),
Sign(kFakeKeyHandle, trunks::TPM_ALG_RSASSA, trunks::TPM_ALG_NULL,
_, false, _, _))
.WillOnce(
DoAll(SetArgPointee<6>(kSignature), Return(trunks::TPM_RC_SUCCESS)));
EXPECT_THAT(
backend_->GetSigningTpm2().RawSign(
key->GetKey(), brillo::BlobFromString(kDataToSign),
SigningOptions{
.digest_algorithm = DigestAlgorithm::kMd5,
.rsa_padding_scheme = SigningOptions::RsaPaddingScheme::kPkcs1v15,
}),
IsOkAndHolds(brillo::BlobFromString(kSignature)));
}
TEST_F(BackendSigningTpm2Test, SignRSARsassaPss) {
const OperationPolicy kFakePolicy{};
const std::string kFakeKeyBlob = "fake_key_blob";
const std::string kDataToSign = "data_to_sign";
const std::string kSignature = "signature";
const uint32_t kFakeKeyHandle = 0x1337;
const trunks::TPMT_PUBLIC kFakePublic = {
.type = trunks::TPM_ALG_RSA,
.name_alg = trunks::TPM_ALG_SHA256,
.object_attributes =
trunks::kFixedTPM | trunks::kFixedParent | trunks::kSign,
.auth_policy = trunks::TPM2B_DIGEST{.size = 0},
.parameters =
trunks::TPMU_PUBLIC_PARMS{
.rsa_detail =
trunks::TPMS_RSA_PARMS{
.symmetric =
trunks::TPMT_SYM_DEF_OBJECT{
.algorithm = trunks::TPM_ALG_NULL,
},
.scheme =
trunks::TPMT_RSA_SCHEME{
.scheme = trunks::TPM_ALG_NULL,
},
.key_bits = 2048,
.exponent = 0,
},
},
.unique =
trunks::TPMU_PUBLIC_ID{
.rsa =
trunks::TPM2B_PUBLIC_KEY_RSA{
.size = 10,
.buffer = "9876543210",
},
},
};
EXPECT_CALL(proxy_->GetMockTpmUtility(), LoadKey(kFakeKeyBlob, _, _))
.WillOnce(DoAll(SetArgPointee<2>(kFakeKeyHandle),
Return(trunks::TPM_RC_SUCCESS)));
EXPECT_CALL(proxy_->GetMockTpmUtility(), GetKeyPublicArea(kFakeKeyHandle, _))
.WillOnce(
DoAll(SetArgPointee<1>(kFakePublic), Return(trunks::TPM_RC_SUCCESS)));
auto key = backend_->GetKeyManagementTpm2().LoadKey(
kFakePolicy, brillo::BlobFromString(kFakeKeyBlob),
Backend::KeyManagement::LoadKeyOptions{});
ASSERT_OK(key);
EXPECT_CALL(proxy_->GetMockTpmUtility(),
Sign(kFakeKeyHandle, trunks::TPM_ALG_RSAPSS,
trunks::TPM_ALG_SHA512, kDataToSign, false, _, _))
.WillOnce(
DoAll(SetArgPointee<6>(kSignature), Return(trunks::TPM_RC_SUCCESS)));
EXPECT_THAT(backend_->GetSigningTpm2().RawSign(
key->GetKey(), brillo::BlobFromString(kDataToSign),
SigningOptions{
.digest_algorithm = DigestAlgorithm::kSha512,
.rsa_padding_scheme =
SigningOptions::RsaPaddingScheme::kRsassaPss,
}),
IsOkAndHolds(brillo::BlobFromString(kSignature)));
}
TEST_F(BackendSigningTpm2Test, SignRSARsassaPssUnsupported) {
const OperationPolicy kFakePolicy{};
const std::string kFakeKeyBlob = "fake_key_blob";
const std::string kDataToSign = "data_to_sign";
const std::string kSignature = "signature";
const uint32_t kFakeKeyHandle = 0x1337;
const trunks::TPMT_PUBLIC kFakePublic = {
.type = trunks::TPM_ALG_RSA,
.name_alg = trunks::TPM_ALG_SHA256,
.object_attributes =
trunks::kFixedTPM | trunks::kFixedParent | trunks::kSign,
.auth_policy = trunks::TPM2B_DIGEST{.size = 0},
.parameters =
trunks::TPMU_PUBLIC_PARMS{
.rsa_detail =
trunks::TPMS_RSA_PARMS{
.symmetric =
trunks::TPMT_SYM_DEF_OBJECT{
.algorithm = trunks::TPM_ALG_NULL,
},
.scheme =
trunks::TPMT_RSA_SCHEME{
.scheme = trunks::TPM_ALG_NULL,
},
.key_bits = 2048,
.exponent = 0,
},
},
.unique =
trunks::TPMU_PUBLIC_ID{
.rsa =
trunks::TPM2B_PUBLIC_KEY_RSA{
.size = 10,
.buffer = "9876543210",
},
},
};
EXPECT_CALL(proxy_->GetMockTpmUtility(), LoadKey(kFakeKeyBlob, _, _))
.WillOnce(DoAll(SetArgPointee<2>(kFakeKeyHandle),
Return(trunks::TPM_RC_SUCCESS)));
EXPECT_CALL(proxy_->GetMockTpmUtility(), GetKeyPublicArea(kFakeKeyHandle, _))
.WillOnce(
DoAll(SetArgPointee<1>(kFakePublic), Return(trunks::TPM_RC_SUCCESS)));
auto key = backend_->GetKeyManagementTpm2().LoadKey(
kFakePolicy, brillo::BlobFromString(kFakeKeyBlob),
Backend::KeyManagement::LoadKeyOptions{});
ASSERT_OK(key);
EXPECT_THAT(backend_->GetSigningTpm2().RawSign(
key->GetKey(), brillo::BlobFromString(kDataToSign),
SigningOptions{
.digest_algorithm = DigestAlgorithm::kMd5,
.rsa_padding_scheme =
SigningOptions::RsaPaddingScheme::kRsassaPss,
}),
NotOkWith("Unsupported digest algorithm combination"));
}
TEST_F(BackendSigningTpm2Test, SignRSAPkcs1v15WithDecrypt) {
const OperationPolicy kFakePolicy{};
const std::string kFakeKeyBlob = "fake_key_blob";
const std::string kDataToSign = "data_to_sign";
const std::string kSignature = "signature";
const uint32_t kFakeKeyHandle = 0x1337;
const trunks::TPMT_PUBLIC kFakePublic = {
.type = trunks::TPM_ALG_RSA,
.name_alg = trunks::TPM_ALG_SHA256,
.object_attributes = trunks::kFixedTPM | trunks::kFixedParent |
trunks::kSign | trunks::kDecrypt,
.auth_policy = trunks::TPM2B_DIGEST{.size = 0},
.parameters =
trunks::TPMU_PUBLIC_PARMS{
.rsa_detail =
trunks::TPMS_RSA_PARMS{
.symmetric =
trunks::TPMT_SYM_DEF_OBJECT{
.algorithm = trunks::TPM_ALG_NULL,
},
.scheme =
trunks::TPMT_RSA_SCHEME{
.scheme = trunks::TPM_ALG_NULL,
},
.key_bits = 2048,
.exponent = 0,
},
},
.unique =
trunks::TPMU_PUBLIC_ID{
.rsa =
trunks::TPM2B_PUBLIC_KEY_RSA{
.size = 64,
.buffer = "9876543210987654321098765432109876543210987654"
"321098765432104321",
},
},
};
EXPECT_CALL(proxy_->GetMockTpmUtility(), LoadKey(kFakeKeyBlob, _, _))
.WillOnce(DoAll(SetArgPointee<2>(kFakeKeyHandle),
Return(trunks::TPM_RC_SUCCESS)));
EXPECT_CALL(proxy_->GetMockTpmUtility(), GetKeyPublicArea(kFakeKeyHandle, _))
.WillOnce(
DoAll(SetArgPointee<1>(kFakePublic), Return(trunks::TPM_RC_SUCCESS)));
auto key = backend_->GetKeyManagementTpm2().LoadKey(
kFakePolicy, brillo::BlobFromString(kFakeKeyBlob),
Backend::KeyManagement::LoadKeyOptions{});
ASSERT_OK(key);
EXPECT_CALL(proxy_->GetMockTpmUtility(),
AsymmetricDecrypt(kFakeKeyHandle, trunks::TPM_ALG_NULL,
trunks::TPM_ALG_NULL, _, _, _))
.WillOnce(
DoAll(SetArgPointee<5>(kSignature), Return(trunks::TPM_RC_SUCCESS)));
EXPECT_THAT(
backend_->GetSigningTpm2().RawSign(
key->GetKey(), brillo::BlobFromString(kDataToSign),
SigningOptions{
.digest_algorithm = DigestAlgorithm::kSha384,
.rsa_padding_scheme = SigningOptions::RsaPaddingScheme::kPkcs1v15,
}),
IsOkAndHolds(brillo::BlobFromString(kSignature)));
}
TEST_F(BackendSigningTpm2Test, SignRSAPkcs1v15WithDecryptTooLong) {
const OperationPolicy kFakePolicy{};
const std::string kFakeKeyBlob = "fake_key_blob";
const std::string kDataToSign = "data_to_sign";
const std::string kSignature = "signature";
const uint32_t kFakeKeyHandle = 0x1337;
const trunks::TPMT_PUBLIC kFakePublic = {
.type = trunks::TPM_ALG_RSA,
.name_alg = trunks::TPM_ALG_SHA256,
.object_attributes = trunks::kFixedTPM | trunks::kFixedParent |
trunks::kSign | trunks::kDecrypt,
.auth_policy = trunks::TPM2B_DIGEST{.size = 0},
.parameters =
trunks::TPMU_PUBLIC_PARMS{
.rsa_detail =
trunks::TPMS_RSA_PARMS{
.symmetric =
trunks::TPMT_SYM_DEF_OBJECT{
.algorithm = trunks::TPM_ALG_NULL,
},
.scheme =
trunks::TPMT_RSA_SCHEME{
.scheme = trunks::TPM_ALG_NULL,
},
.key_bits = 2048,
.exponent = 0,
},
},
.unique =
trunks::TPMU_PUBLIC_ID{
.rsa =
trunks::TPM2B_PUBLIC_KEY_RSA{
.size = 32,
.buffer = "98765432109876543210987654321012",
},
},
};
EXPECT_CALL(proxy_->GetMockTpmUtility(), LoadKey(kFakeKeyBlob, _, _))
.WillOnce(DoAll(SetArgPointee<2>(kFakeKeyHandle),
Return(trunks::TPM_RC_SUCCESS)));
EXPECT_CALL(proxy_->GetMockTpmUtility(), GetKeyPublicArea(kFakeKeyHandle, _))
.WillOnce(
DoAll(SetArgPointee<1>(kFakePublic), Return(trunks::TPM_RC_SUCCESS)));
auto key = backend_->GetKeyManagementTpm2().LoadKey(
kFakePolicy, brillo::BlobFromString(kFakeKeyBlob),
Backend::KeyManagement::LoadKeyOptions{});
ASSERT_OK(key);
EXPECT_THAT(
backend_->GetSigningTpm2().RawSign(
key->GetKey(), brillo::BlobFromString(kDataToSign),
SigningOptions{
.digest_algorithm = DigestAlgorithm::kSha384,
.rsa_padding_scheme = SigningOptions::RsaPaddingScheme::kPkcs1v15,
}),
NotOkWith("Message too long"));
}
TEST_F(BackendSigningTpm2Test, SignRSARsassaPssWithDecrypt) {
const OperationPolicy kFakePolicy{};
const std::string kFakeKeyBlob = "fake_key_blob";
const std::string kDataToSign(20, 'D');
const std::string kSignature = "signature";
const uint32_t kFakeKeyHandle = 0x1337;
const trunks::TPMT_PUBLIC kFakePublic = {
.type = trunks::TPM_ALG_RSA,
.name_alg = trunks::TPM_ALG_SHA256,
.object_attributes = trunks::kFixedTPM | trunks::kFixedParent |
trunks::kSign | trunks::kDecrypt,
.auth_policy = trunks::TPM2B_DIGEST{.size = 0},
.parameters =
trunks::TPMU_PUBLIC_PARMS{
.rsa_detail =
trunks::TPMS_RSA_PARMS{
.symmetric =
trunks::TPMT_SYM_DEF_OBJECT{
.algorithm = trunks::TPM_ALG_NULL,
},
.scheme =
trunks::TPMT_RSA_SCHEME{
.scheme = trunks::TPM_ALG_NULL,
},
.key_bits = 2048,
.exponent = 0,
},
},
.unique =
trunks::TPMU_PUBLIC_ID{
.rsa =
trunks::TPM2B_PUBLIC_KEY_RSA{
.size = 64,
.buffer = "9876543210987654321098765432109876543210987654"
"321098765432104321",
},
},
};
EXPECT_CALL(proxy_->GetMockTpmUtility(), LoadKey(kFakeKeyBlob, _, _))
.WillOnce(DoAll(SetArgPointee<2>(kFakeKeyHandle),
Return(trunks::TPM_RC_SUCCESS)));
EXPECT_CALL(proxy_->GetMockTpmUtility(), GetKeyPublicArea(kFakeKeyHandle, _))
.WillOnce(
DoAll(SetArgPointee<1>(kFakePublic), Return(trunks::TPM_RC_SUCCESS)));
auto key = backend_->GetKeyManagementTpm2().LoadKey(
kFakePolicy, brillo::BlobFromString(kFakeKeyBlob),
Backend::KeyManagement::LoadKeyOptions{});
ASSERT_OK(key);
EXPECT_CALL(proxy_->GetMockTpmUtility(),
AsymmetricDecrypt(kFakeKeyHandle, trunks::TPM_ALG_NULL,
trunks::TPM_ALG_NULL, _, _, _))
.WillOnce(
DoAll(SetArgPointee<5>(kSignature), Return(trunks::TPM_RC_SUCCESS)));
EXPECT_THAT(backend_->GetSigningTpm2().RawSign(
key->GetKey(), brillo::BlobFromString(kDataToSign),
SigningOptions{
.digest_algorithm = DigestAlgorithm::kSha1,
.rsa_padding_scheme =
SigningOptions::RsaPaddingScheme::kRsassaPss,
}),
IsOkAndHolds(brillo::BlobFromString(kSignature)));
}
TEST_F(BackendSigningTpm2Test, SignRSARsassaPssWithDecryptDataTooSmall) {
const OperationPolicy kFakePolicy{};
const std::string kFakeKeyBlob = "fake_key_blob";
const std::string kDataToSign = "data";
const std::string kSignature = "signature";
const uint32_t kFakeKeyHandle = 0x1337;
const trunks::TPMT_PUBLIC kFakePublic = {
.type = trunks::TPM_ALG_RSA,
.name_alg = trunks::TPM_ALG_SHA256,
.object_attributes = trunks::kFixedTPM | trunks::kFixedParent |
trunks::kSign | trunks::kDecrypt,
.auth_policy = trunks::TPM2B_DIGEST{.size = 0},
.parameters =
trunks::TPMU_PUBLIC_PARMS{
.rsa_detail =
trunks::TPMS_RSA_PARMS{
.symmetric =
trunks::TPMT_SYM_DEF_OBJECT{
.algorithm = trunks::TPM_ALG_NULL,
},
.scheme =
trunks::TPMT_RSA_SCHEME{
.scheme = trunks::TPM_ALG_NULL,
},
.key_bits = 2048,
.exponent = 0,
},
},
.unique =
trunks::TPMU_PUBLIC_ID{
.rsa =
trunks::TPM2B_PUBLIC_KEY_RSA{
.size = 64,
.buffer = "9876543210987654321098765432109876543210987654"
"321098765432104321",
},
},
};
EXPECT_CALL(proxy_->GetMockTpmUtility(), LoadKey(kFakeKeyBlob, _, _))
.WillOnce(DoAll(SetArgPointee<2>(kFakeKeyHandle),
Return(trunks::TPM_RC_SUCCESS)));
EXPECT_CALL(proxy_->GetMockTpmUtility(), GetKeyPublicArea(kFakeKeyHandle, _))
.WillOnce(
DoAll(SetArgPointee<1>(kFakePublic), Return(trunks::TPM_RC_SUCCESS)));
auto key = backend_->GetKeyManagementTpm2().LoadKey(
kFakePolicy, brillo::BlobFromString(kFakeKeyBlob),
Backend::KeyManagement::LoadKeyOptions{});
ASSERT_OK(key);
EXPECT_THAT(backend_->GetSigningTpm2().RawSign(
key->GetKey(), brillo::BlobFromString(kDataToSign),
SigningOptions{
.digest_algorithm = DigestAlgorithm::kSha1,
.rsa_padding_scheme =
SigningOptions::RsaPaddingScheme::kRsassaPss,
}),
NotOkWith("Data to sign is too small"));
}
TEST_F(BackendSigningTpm2Test, SignRSARsassaPssWithDecryptUnsupportedMgf1Alg) {
const OperationPolicy kFakePolicy{};
const std::string kFakeKeyBlob = "fake_key_blob";
const std::string kDataToSign(20, 'D');
const std::string kSignature = "signature";
const uint32_t kFakeKeyHandle = 0x1337;
const trunks::TPMT_PUBLIC kFakePublic = {
.type = trunks::TPM_ALG_RSA,
.name_alg = trunks::TPM_ALG_SHA256,
.object_attributes = trunks::kFixedTPM | trunks::kFixedParent |
trunks::kSign | trunks::kDecrypt,
.auth_policy = trunks::TPM2B_DIGEST{.size = 0},
.parameters =
trunks::TPMU_PUBLIC_PARMS{
.rsa_detail =
trunks::TPMS_RSA_PARMS{
.symmetric =
trunks::TPMT_SYM_DEF_OBJECT{
.algorithm = trunks::TPM_ALG_NULL,
},
.scheme =
trunks::TPMT_RSA_SCHEME{
.scheme = trunks::TPM_ALG_NULL,
},
.key_bits = 2048,
.exponent = 0,
},
},
.unique =
trunks::TPMU_PUBLIC_ID{
.rsa =
trunks::TPM2B_PUBLIC_KEY_RSA{
.size = 64,
.buffer = "9876543210987654321098765432109876543210987654"
"321098765432104321",
},
},
};
EXPECT_CALL(proxy_->GetMockTpmUtility(), LoadKey(kFakeKeyBlob, _, _))
.WillOnce(DoAll(SetArgPointee<2>(kFakeKeyHandle),
Return(trunks::TPM_RC_SUCCESS)));
EXPECT_CALL(proxy_->GetMockTpmUtility(), GetKeyPublicArea(kFakeKeyHandle, _))
.WillOnce(
DoAll(SetArgPointee<1>(kFakePublic), Return(trunks::TPM_RC_SUCCESS)));
auto key = backend_->GetKeyManagementTpm2().LoadKey(
kFakePolicy, brillo::BlobFromString(kFakeKeyBlob),
Backend::KeyManagement::LoadKeyOptions{});
ASSERT_OK(key);
EXPECT_THAT(backend_->GetSigningTpm2().RawSign(
key->GetKey(), brillo::BlobFromString(kDataToSign),
SigningOptions{
.digest_algorithm = DigestAlgorithm::kSha1,
.rsa_padding_scheme =
SigningOptions::RsaPaddingScheme::kRsassaPss,
.pss_params =
SigningOptions::PssParams{
.mgf1_algorithm = DigestAlgorithm::kNoDigest,
.salt_length = 1024,
},
}),
NotOkWith("Failed to produce the PSA PSS paddings"));
}
TEST_F(BackendSigningTpm2Test, SignRSAPkcs1v15WithoutDigestAlgorithm) {
constexpr uint8_t kSha512DigestInfo[] = {
0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
const OperationPolicy kFakePolicy{};
const std::string kFakeKeyBlob = "fake_key_blob";
const std::string kDataToSign = std::string(64, 'X');
const std::string kFullDataToSign =
std::string(kSha512DigestInfo,
kSha512DigestInfo + sizeof(kSha512DigestInfo)) +
kDataToSign;
const std::string kSignature = "signature";
const uint32_t kFakeKeyHandle = 0x1337;
const trunks::TPMT_PUBLIC kFakePublic = {
.type = trunks::TPM_ALG_RSA,
.name_alg = trunks::TPM_ALG_SHA256,
.object_attributes =
trunks::kFixedTPM | trunks::kFixedParent | trunks::kSign,
.auth_policy = trunks::TPM2B_DIGEST{.size = 0},
.parameters =
trunks::TPMU_PUBLIC_PARMS{
.rsa_detail =
trunks::TPMS_RSA_PARMS{
.symmetric =
trunks::TPMT_SYM_DEF_OBJECT{
.algorithm = trunks::TPM_ALG_NULL,
},
.scheme =
trunks::TPMT_RSA_SCHEME{
.scheme = trunks::TPM_ALG_NULL,
},
.key_bits = 2048,
.exponent = 0,
},
},
.unique =
trunks::TPMU_PUBLIC_ID{
.rsa =
trunks::TPM2B_PUBLIC_KEY_RSA{
.size = 10,
.buffer = "9876543210",
},
},
};
EXPECT_CALL(proxy_->GetMockTpmUtility(), LoadKey(kFakeKeyBlob, _, _))
.WillOnce(DoAll(SetArgPointee<2>(kFakeKeyHandle),
Return(trunks::TPM_RC_SUCCESS)));
EXPECT_CALL(proxy_->GetMockTpmUtility(), GetKeyPublicArea(kFakeKeyHandle, _))
.WillOnce(
DoAll(SetArgPointee<1>(kFakePublic), Return(trunks::TPM_RC_SUCCESS)));
auto key = backend_->GetKeyManagementTpm2().LoadKey(
kFakePolicy, brillo::BlobFromString(kFakeKeyBlob),
Backend::KeyManagement::LoadKeyOptions{});
ASSERT_OK(key);
EXPECT_CALL(proxy_->GetMockTpmUtility(),
Sign(kFakeKeyHandle, trunks::TPM_ALG_RSASSA,
trunks::TPM_ALG_SHA512, _, false, _, _))
.WillOnce(
DoAll(SetArgPointee<6>(kSignature), Return(trunks::TPM_RC_SUCCESS)));
EXPECT_THAT(
backend_->GetSigningTpm2().RawSign(
key->GetKey(), brillo::BlobFromString(kFullDataToSign),
SigningOptions{
.digest_algorithm = DigestAlgorithm::kNoDigest,
.rsa_padding_scheme = SigningOptions::RsaPaddingScheme::kPkcs1v15,
}),
IsOkAndHolds(brillo::BlobFromString(kSignature)));
}
} // namespace hwsec