| // 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 |