blob: f4d3d9f0594811cf3f06d47de2d8e300062af415 [file] [log] [blame]
// Copyright 2018 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.
// Tests for the ChallengeCredentialsDecryptOperation class.
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <brillo/secure_blob.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "cryptohome/challenge_credentials/challenge_credentials_decrypt_operation.h"
#include "cryptohome/challenge_credentials/challenge_credentials_test_utils.h"
#include "cryptohome/cryptolib.h"
#include "cryptohome/mock_key_challenge_service.h"
#include "cryptohome/mock_signature_sealing_backend.h"
#include "cryptohome/mock_tpm.h"
#include "cryptohome/signature_sealing_backend.h"
#include "cryptohome/signature_sealing_backend_test_utils.h"
#include "cryptohome/username_passkey.h"
#include "key.pb.h" // NOLINT(build/include)
#include "rpc.pb.h" // NOLINT(build/include)
#include "signature_sealed_data.pb.h" // NOLINT(build/include)
using brillo::Blob;
using brillo::BlobToString;
using brillo::CombineBlobs;
using testing::Return;
using testing::StrictMock;
using testing::Values;
namespace cryptohome {
using KeysetSignatureChallengeInfo =
ChallengeCredentialsDecryptOperation::KeysetSignatureChallengeInfo;
namespace {
KeyData MakeKeyData(
const Blob& set_public_key_spki_der,
const std::vector<ChallengeSignatureAlgorithm>& key_algorithms) {
KeyData key_data;
key_data.set_type(KeyData::KEY_TYPE_CHALLENGE_RESPONSE);
ChallengePublicKeyInfo* const public_key_info =
key_data.add_challenge_response_key();
public_key_info->set_public_key_spki_der(
BlobToString(set_public_key_spki_der));
for (auto key_algorithm : key_algorithms)
public_key_info->add_signature_algorithm(key_algorithm);
return key_data;
}
KeysetSignatureChallengeInfo MakeFakeKeysetChallengeInfo(
const Blob& public_key_spki_der,
const Blob& salt,
ChallengeSignatureAlgorithm salt_challenge_algorithm) {
KeysetSignatureChallengeInfo keyset_challenge_info;
keyset_challenge_info.set_public_key_spki_der(
BlobToString(public_key_spki_der));
*keyset_challenge_info.mutable_sealed_secret() =
MakeFakeSignatureSealedData(public_key_spki_der);
keyset_challenge_info.set_salt(BlobToString(salt));
keyset_challenge_info.set_salt_signature_algorithm(salt_challenge_algorithm);
return keyset_challenge_info;
}
// Base fixture class that provides some common constants, helpers and mocks for
// testing a single instance of ChallengeCredentialsDecryptOperation.
class ChallengeCredentialsDecryptOperationTestBase : public testing::Test {
protected:
void PrepareSignatureSealingBackend(bool enabled) {
SignatureSealingBackend* const return_value =
enabled ? &sealing_backend_ : nullptr;
EXPECT_CALL(tpm_, GetSignatureSealingBackend())
.WillRepeatedly(Return(return_value));
}
// Create an instance of ChallengeCredentialsDecryptOperation to be tested.
// When |pass_salt_signature| is true, it additionally passes the signature of
// salt as it were precomputed before.
void CreateOperation(
const std::vector<ChallengeSignatureAlgorithm>& key_algorithms,
ChallengeSignatureAlgorithm salt_challenge_algorithm,
const Blob& salt,
bool pass_salt_signature) {
DCHECK(!operation_);
std::unique_ptr<Blob> salt_signature;
if (pass_salt_signature)
salt_signature = std::make_unique<Blob>(kSaltSignature);
const KeyData key_data = MakeKeyData(kPublicKeySpkiDer, key_algorithms);
const KeysetSignatureChallengeInfo keyset_challenge_info =
MakeFakeKeysetChallengeInfo(kPublicKeySpkiDer, salt,
salt_challenge_algorithm);
operation_ = std::make_unique<ChallengeCredentialsDecryptOperation>(
&challenge_service_, &tpm_, kDelegateBlob, kDelegateSecret, kUserEmail,
key_data, keyset_challenge_info, std::move(salt_signature),
MakeChallengeCredentialsDecryptResultWriter(&operation_result_));
}
void StartOperation() { operation_->Start(); }
void AbortOperation() { operation_->Abort(); }
// Whether the tested operation completed with some result.
bool has_result() const { return static_cast<bool>(operation_result_); }
// Assert that the tested operation completed with a valid success result.
void VerifySuccessfulResult() const {
ASSERT_TRUE(operation_result_);
VerifySuccessfulChallengeCredentialsDecryptResult(
*operation_result_,
kUserEmail,
brillo::SecureBlob(kPasskey.begin(), kPasskey.end()));
}
// Assert that the tested operation completed with a failure result.
void VerifyFailedResult() const {
ASSERT_TRUE(operation_result_);
VerifyFailedChallengeCredentialsDecryptResult(*operation_result_);
}
// Returns a helper object that aids mocking of the secret unsealing
// functionality (SignatureSealingBackend::CreateUnsealingSession() et al.).
std::unique_ptr<SignatureSealedUnsealingMocker> MakeUnsealingMocker(
const std::vector<ChallengeSignatureAlgorithm>& key_algorithms,
ChallengeSignatureAlgorithm unsealing_algorithm) {
auto mocker =
std::make_unique<SignatureSealedUnsealingMocker>(&sealing_backend_);
mocker->set_public_key_spki_der(kPublicKeySpkiDer);
mocker->set_key_algorithms(key_algorithms);
mocker->set_delegate_blob(kDelegateBlob);
mocker->set_delegate_secret(kDelegateSecret);
mocker->set_chosen_algorithm(unsealing_algorithm);
mocker->set_challenge_value(kUnsealingChallengeValue);
mocker->set_challenge_signature(kUnsealingChallengeSignature);
mocker->set_secret_value(kUnsealedSecret);
return mocker;
}
// Sets up an expectation that the salt challenge request will be issued via
// |challenge_service_|.
void ExpectSaltChallenge(
ChallengeSignatureAlgorithm salt_challenge_algorithm) {
salt_challenge_mock_controller_.ExpectSignatureChallenge(
kUserEmail, kPublicKeySpkiDer, kSalt, salt_challenge_algorithm);
}
// Whether the salt challenge request has been started.
bool is_salt_challenge_requested() const {
return salt_challenge_mock_controller_.is_challenge_requested();
}
// Injects a simulated successful response for the currently running salt
// challenge request.
void SimulateSaltChallengeResponse() {
salt_challenge_mock_controller_.SimulateSignatureChallengeResponse(
kSaltSignature);
}
// Injects a simulated failure response for the currently running salt
// challenge request.
void SimulateSaltChallengeFailure() {
salt_challenge_mock_controller_.SimulateFailureResponse();
}
// Sets up an expectation that the secret unsealing challenge request will be
// issued via |challenge_service_|.
void ExpectUnsealingChallenge(
ChallengeSignatureAlgorithm unsealing_algorithm) {
unsealing_challenge_mock_controller_.ExpectSignatureChallenge(
kUserEmail, kPublicKeySpkiDer, kUnsealingChallengeValue,
unsealing_algorithm);
}
// Whether the secret unsealing challenge request has been started.
bool is_unsealing_challenge_requested() const {
return unsealing_challenge_mock_controller_.is_challenge_requested();
}
// Injects a simulated successful response for the currently running secret
// unsealing challenge request.
void SimulateUnsealingChallengeResponse() {
unsealing_challenge_mock_controller_.SimulateSignatureChallengeResponse(
kUnsealingChallengeSignature);
}
// Injects a simulated failure response for the currently running secret
// unsealing challenge request.
void SimulateUnsealingChallengeFailure() {
unsealing_challenge_mock_controller_.SimulateFailureResponse();
}
protected:
// Constants which are passed as fake data inputs to the
// ChallengeCredentialsDecryptOperation operation:
// Fake TPM delegate. It's supplied to the operation constructor. Then it's
// verified to be passed into SignatureSealingBackend methods.
const Blob kDelegateBlob{{1, 1, 1}};
const Blob kDelegateSecret{{2, 2, 2}};
// Fake user e-mail. It's supplied to the operation constructor. Then it's
// verified to be passed alongside challenge requests made via
// KeyChallengeService, and to be present in the resulting UsernamePasskey.
const std::string kUserEmail = "foo@example.com";
// Fake Subject Public Key Information of the challenged cryptographic key.
// It's supplied to the operation as a field of both |key_data| and
// |keyset_challenge_info| parameters. Then it's verified to be passed into
// SignatureSealingBackend methods and to be used for challenge requests made
// via KeyChallengeService.
const Blob kPublicKeySpkiDer{{3, 3, 3}};
// Fake salt value. It's supplied to the operation as a field of the
// |keyset_challenge_info| parameter. Then it's verified to be used as the
// challenge value for one of requests made via KeyChallengeService.
const Blob kSalt = CombineBlobs(
{ChallengeCredentialsOperation::GetSaltConstantPrefix(), Blob{4, 4, 4}});
// Constants which are injected as fake data into intermediate steps of the
// tested operation:
// Fake signature of |kSalt| using the |salt_challenge_algorithm_| algorithm.
// It's injected as a fake response to the salt challenge request made via
// KeyChallengeService. Then it's implicitly verified to be used for the
// generation of the passkey in the resulting UsernamePasskey - see the
// |kPasskey| constant.
const Blob kSaltSignature{{5, 5, 5}};
// Fake challenge value for unsealing the secret. It's injected as a fake
// value returned from SignatureSealingBackend::UnsealingSession. Then it's
// verified to be used as the challenge value for one of requests made via
// KeyChallengeService.
const Blob kUnsealingChallengeValue{{6, 6, 6}};
// Fake signature of |kUnsealingChallengeValue| using the
// |unsealing_algorithm_| algorithm. It's injected as a fake response to the
// unsealing challenge request made via KeyChallengeService. Then it's
// verified to be passed to the Unseal() method of
// SignatureSealingBackend::UnsealingSession.
const Blob kUnsealingChallengeSignature{{7, 7, 7}};
// Fake unsealed secret. It's injected as a fake result of the Unseal() method
// of SignatureSealingBackend::UnsealingSession.
const Blob kUnsealedSecret{{8, 8, 8}};
// The expected passkey of the resulting UsernamePasskey returned from the
// tested operation. Its value is derived from the injected fake data.
const Blob kPasskey =
CombineBlobs({kUnsealedSecret, CryptoLib::Sha256(kSaltSignature)});
private:
// Mock objects:
StrictMock<MockTpm> tpm_;
StrictMock<MockSignatureSealingBackend> sealing_backend_;
StrictMock<MockKeyChallengeService> challenge_service_;
KeyChallengeServiceMockController salt_challenge_mock_controller_{
&challenge_service_};
KeyChallengeServiceMockController unsealing_challenge_mock_controller_{
&challenge_service_};
// Result returned from the tested operation, or null if nothing yet.
std::unique_ptr<ChallengeCredentialsDecryptResult> operation_result_;
// The tested operation.
std::unique_ptr<ChallengeCredentialsDecryptOperation> operation_;
};
// Base fixture class that uses a single algorithm for simplicity.
class ChallengeCredentialsDecryptOperationSingleAlgorithmTestBase
: public ChallengeCredentialsDecryptOperationTestBase {
protected:
// The single algorithm to be used in this test.
static constexpr ChallengeSignatureAlgorithm kAlgorithm =
CHALLENGE_RSASSA_PKCS1_V1_5_SHA256;
};
// Base fixture class that uses a single algorithm and have the sealing backend
// available.
class ChallengeCredentialsDecryptOperationNoOperationConstructedBasicTest
: public ChallengeCredentialsDecryptOperationSingleAlgorithmTestBase {
protected:
// The single algorithm to be used in this test.
static constexpr ChallengeSignatureAlgorithm kAlgorithm =
CHALLENGE_RSASSA_PKCS1_V1_5_SHA256;
ChallengeCredentialsDecryptOperationNoOperationConstructedBasicTest() {
PrepareSignatureSealingBackend(true /* enabled */);
}
};
} // namespace
// Test failure of the operation due to the input salt being empty.
TEST_F(ChallengeCredentialsDecryptOperationNoOperationConstructedBasicTest,
EmptySaltFailure) {
CreateOperation({kAlgorithm} /* key_algorithms */,
kAlgorithm /* salt_challenge_algorithm */, Blob() /* salt */,
false /* pass_salt_signature */);
StartOperation();
VerifyFailedResult();
}
// Test failure of the operation due to the input salt not starting with the
// expected constant prefix.
TEST_F(ChallengeCredentialsDecryptOperationNoOperationConstructedBasicTest,
BadSaltNotPrefixedFailure) {
Blob salt = kSalt;
salt[ChallengeCredentialsOperation::GetSaltConstantPrefix().size() - 1] ^= 1;
CreateOperation({kAlgorithm} /* key_algorithms */,
kAlgorithm /* salt_challenge_algorithm */, salt,
false /* pass_salt_signature */);
StartOperation();
VerifyFailedResult();
}
// Test failure of the operation due to the input salt containing nothing
// besides the expected constant prefix.
TEST_F(ChallengeCredentialsDecryptOperationNoOperationConstructedBasicTest,
BadSaltNothingBesidesPrefixFailure) {
CreateOperation(
{kAlgorithm} /* key_algorithms */,
kAlgorithm /* salt_challenge_algorithm */,
ChallengeCredentialsOperation::GetSaltConstantPrefix() /* salt */,
false /* pass_salt_signature */);
StartOperation();
VerifyFailedResult();
}
namespace {
// Basic tests that use a single algorithm, have the sealing backend available
// and don't skip signing of salt.
class ChallengeCredentialsDecryptOperationBasicTest
: public ChallengeCredentialsDecryptOperationSingleAlgorithmTestBase {
protected:
ChallengeCredentialsDecryptOperationBasicTest() {
PrepareSignatureSealingBackend(true /* enabled */);
CreateOperation({kAlgorithm} /* key_algorithms */,
kAlgorithm /* salt_challenge_algorithm */, kSalt,
false /* pass_salt_signature */);
}
};
} // namespace
// Test success of the operation in scenario when the salt challenge response
// comes before the unsealing challenge response.
TEST_F(ChallengeCredentialsDecryptOperationBasicTest,
SuccessSaltThenUnsealing) {
ExpectSaltChallenge(kAlgorithm /* salt_challenge_algorithm */);
ExpectUnsealingChallenge(kAlgorithm /* unsealing_algorithm */);
MakeUnsealingMocker({kAlgorithm} /* key_algorithms */,
kAlgorithm /* unsealing_algorithm */)
->SetUpSuccessfulMock();
StartOperation();
EXPECT_TRUE(is_salt_challenge_requested());
EXPECT_TRUE(is_unsealing_challenge_requested());
SimulateSaltChallengeResponse();
EXPECT_FALSE(has_result());
SimulateUnsealingChallengeResponse();
VerifySuccessfulResult();
}
// Test success of the operation in scenario when the unsealing challenge
// response comes before the salt challenge response.
TEST_F(ChallengeCredentialsDecryptOperationBasicTest,
SuccessUnsealingThenSalt) {
ExpectSaltChallenge(kAlgorithm /* salt_challenge_algorithm */);
ExpectUnsealingChallenge(kAlgorithm /* unsealing_algorithm */);
MakeUnsealingMocker({kAlgorithm} /* key_algorithms */,
kAlgorithm /* unsealing_algorithm */)
->SetUpSuccessfulMock();
StartOperation();
EXPECT_TRUE(is_salt_challenge_requested());
EXPECT_TRUE(is_unsealing_challenge_requested());
SimulateUnsealingChallengeResponse();
EXPECT_FALSE(has_result());
SimulateSaltChallengeResponse();
VerifySuccessfulResult();
}
// Test failure of the operation due to failure of unsealing session creation.
TEST_F(ChallengeCredentialsDecryptOperationBasicTest,
UnsealingSessionCreationFailure) {
EXPECT_FALSE(has_result());
ExpectSaltChallenge(kAlgorithm /* salt_challenge_algorithm */);
MakeUnsealingMocker({kAlgorithm} /* key_algorithms */,
kAlgorithm /* unsealing_algorithm */)
->SetUpCreationFailingMock(true /* mock_repeatedly */);
StartOperation();
EXPECT_TRUE(is_salt_challenge_requested());
VerifyFailedResult();
// Responding to the salt challenge shouldn't have any effect.
SimulateSaltChallengeResponse();
}
// Test failure of the operation due to failure of unsealing.
TEST_F(ChallengeCredentialsDecryptOperationBasicTest, UnsealingFailure) {
ExpectSaltChallenge(kAlgorithm /* salt_challenge_algorithm */);
ExpectUnsealingChallenge(kAlgorithm /* unsealing_algorithm */);
MakeUnsealingMocker({kAlgorithm} /* key_algorithms */,
kAlgorithm /* unsealing_algorithm */)
->SetUpUsealingFailingMock();
StartOperation();
EXPECT_TRUE(is_salt_challenge_requested());
EXPECT_TRUE(is_unsealing_challenge_requested());
EXPECT_FALSE(has_result());
SimulateUnsealingChallengeResponse();
VerifyFailedResult();
// Responding to the salt challenge shouldn't have any effect.
SimulateSaltChallengeResponse();
}
// Test failure of the operation due to failure of salt challenge request.
TEST_F(ChallengeCredentialsDecryptOperationBasicTest, SaltChallengeFailure) {
ExpectSaltChallenge(kAlgorithm /* salt_challenge_algorithm */);
ExpectUnsealingChallenge(kAlgorithm /* unsealing_algorithm */);
MakeUnsealingMocker({kAlgorithm} /* key_algorithms */,
kAlgorithm /* unsealing_algorithm */)
->SetUpUnsealingNotCalledMock();
StartOperation();
EXPECT_TRUE(is_salt_challenge_requested());
EXPECT_TRUE(is_unsealing_challenge_requested());
EXPECT_FALSE(has_result());
SimulateSaltChallengeFailure();
VerifyFailedResult();
// Responding to the unsealing challenge shouldn't have any effect.
SimulateUnsealingChallengeResponse();
}
// Test failure of the operation due to failure of unsealing challenge request.
TEST_F(ChallengeCredentialsDecryptOperationBasicTest,
UnsealingChallengeFailure) {
ExpectSaltChallenge(kAlgorithm /* salt_challenge_algorithm */);
ExpectUnsealingChallenge(kAlgorithm /* unsealing_algorithm */);
MakeUnsealingMocker({kAlgorithm} /* key_algorithms */,
kAlgorithm /* unsealing_algorithm */)
->SetUpUnsealingNotCalledMock();
StartOperation();
EXPECT_TRUE(is_salt_challenge_requested());
EXPECT_TRUE(is_unsealing_challenge_requested());
EXPECT_FALSE(has_result());
SimulateUnsealingChallengeFailure();
VerifyFailedResult();
// Responding to the salt challenge shouldn't have any effect.
SimulateSaltChallengeResponse();
}
// Test failure of the operation due to its abortion before any of the
// challenges is completed.
TEST_F(ChallengeCredentialsDecryptOperationBasicTest, AbortBeforeChallenges) {
ExpectSaltChallenge(kAlgorithm /* salt_challenge_algorithm */);
ExpectUnsealingChallenge(kAlgorithm /* unsealing_algorithm */);
MakeUnsealingMocker({kAlgorithm} /* key_algorithms */,
kAlgorithm /* unsealing_algorithm */)
->SetUpUnsealingNotCalledMock();
StartOperation();
EXPECT_TRUE(is_salt_challenge_requested());
EXPECT_TRUE(is_unsealing_challenge_requested());
EXPECT_FALSE(has_result());
AbortOperation();
VerifyFailedResult();
// Responding to the challenges shouldn't have any effect.
SimulateSaltChallengeResponse();
SimulateUnsealingChallengeResponse();
}
// Test failure of the operation due to its abortion after the salt challenge
// completes.
TEST_F(ChallengeCredentialsDecryptOperationBasicTest, AbortAfterSaltChallenge) {
ExpectSaltChallenge(kAlgorithm /* salt_challenge_algorithm */);
ExpectUnsealingChallenge(kAlgorithm /* unsealing_algorithm */);
MakeUnsealingMocker({kAlgorithm} /* key_algorithms */,
kAlgorithm /* unsealing_algorithm */)
->SetUpUnsealingNotCalledMock();
StartOperation();
EXPECT_TRUE(is_salt_challenge_requested());
EXPECT_TRUE(is_unsealing_challenge_requested());
SimulateSaltChallengeResponse();
EXPECT_FALSE(has_result());
AbortOperation();
VerifyFailedResult();
// Responding to the unsealing challenge shouldn't have any effect.
SimulateUnsealingChallengeResponse();
}
// Test failure of the operation due to its abortion after the unsealing
// completes.
TEST_F(ChallengeCredentialsDecryptOperationBasicTest, AbortAfterUnsealing) {
ExpectSaltChallenge(kAlgorithm /* salt_challenge_algorithm */);
ExpectUnsealingChallenge(kAlgorithm /* unsealing_algorithm */);
MakeUnsealingMocker({kAlgorithm} /* key_algorithms */,
kAlgorithm /* unsealing_algorithm */)
->SetUpSuccessfulMock();
StartOperation();
EXPECT_TRUE(is_salt_challenge_requested());
EXPECT_TRUE(is_unsealing_challenge_requested());
SimulateUnsealingChallengeResponse();
EXPECT_FALSE(has_result());
AbortOperation();
VerifyFailedResult();
// Responding to the salt challenge shouldn't have any effect.
SimulateSaltChallengeResponse();
}
namespace {
// Tests that have the salt signature already passed to the tested operation as
// an input parameter.
class ChallengeCredentialsDecryptOperationSaltSkippingTest
: public ChallengeCredentialsDecryptOperationSingleAlgorithmTestBase {
protected:
ChallengeCredentialsDecryptOperationSaltSkippingTest() {
PrepareSignatureSealingBackend(true /* enabled */);
CreateOperation({kAlgorithm} /* key_algorithms */,
kAlgorithm /* salt_challenge_algorithm */, kSalt,
true /* pass_salt_signature */);
}
};
// Test success of the operation when the salt signature is passed as a
// parameter.
TEST_F(ChallengeCredentialsDecryptOperationSaltSkippingTest, Success) {
ExpectUnsealingChallenge(kAlgorithm /* unsealing_algorithm */);
MakeUnsealingMocker({kAlgorithm} /* key_algorithms */,
kAlgorithm /* unsealing_algorithm */)
->SetUpSuccessfulMock();
StartOperation();
EXPECT_TRUE(is_unsealing_challenge_requested());
EXPECT_FALSE(has_result());
SimulateUnsealingChallengeResponse();
VerifySuccessfulResult();
}
} // namespace
namespace {
// Tests with simulation of SignatureSealingBackend absence.
class ChallengeCredentialsDecryptOperationNoBackendTest
: public ChallengeCredentialsDecryptOperationSingleAlgorithmTestBase {
protected:
ChallengeCredentialsDecryptOperationNoBackendTest() {
PrepareSignatureSealingBackend(false /* enabled */);
CreateOperation({kAlgorithm} /* key_algorithms */,
kAlgorithm /* salt_challenge_algorithm */, kSalt,
false /* pass_salt_signature */);
}
};
} // namespace
// Test failure of the operation due to the absence of the sealing backend.
TEST_F(ChallengeCredentialsDecryptOperationNoBackendTest, Failure) {
EXPECT_FALSE(has_result());
StartOperation();
VerifyFailedResult();
}
namespace {
// Test parameters for ChallengeCredentialsDecryptOperationAlgorithmsTest.
struct AlgorithmsTestParam {
std::vector<ChallengeSignatureAlgorithm> key_algorithms;
ChallengeSignatureAlgorithm salt_challenge_algorithm;
ChallengeSignatureAlgorithm unsealing_algorithm;
};
// Tests various combinations of multiple algorithms.
class ChallengeCredentialsDecryptOperationAlgorithmsTest
: public ChallengeCredentialsDecryptOperationTestBase,
public testing::WithParamInterface<AlgorithmsTestParam> {
protected:
ChallengeCredentialsDecryptOperationAlgorithmsTest() {
PrepareSignatureSealingBackend(true /* enabled */);
CreateOperation(GetParam().key_algorithms,
GetParam().salt_challenge_algorithm, kSalt,
false /* pass_salt_signature */);
}
};
} // namespace
// Test success of the operation with the specified combination of algorithms.
TEST_P(ChallengeCredentialsDecryptOperationAlgorithmsTest, Success) {
ExpectSaltChallenge(GetParam().salt_challenge_algorithm);
ExpectUnsealingChallenge(GetParam().unsealing_algorithm);
MakeUnsealingMocker(GetParam().key_algorithms, GetParam().unsealing_algorithm)
->SetUpSuccessfulMock();
StartOperation();
EXPECT_TRUE(is_salt_challenge_requested());
EXPECT_TRUE(is_unsealing_challenge_requested());
SimulateSaltChallengeResponse();
EXPECT_FALSE(has_result());
SimulateUnsealingChallengeResponse();
VerifySuccessfulResult();
}
// Test that SHA-1 algorithms are the least preferred and chosen only if there's
// no other option.
INSTANTIATE_TEST_CASE_P(
LowPriorityOfSha1,
ChallengeCredentialsDecryptOperationAlgorithmsTest,
Values(
AlgorithmsTestParam{
{CHALLENGE_RSASSA_PKCS1_V1_5_SHA1,
CHALLENGE_RSASSA_PKCS1_V1_5_SHA256} /* key_algorithms */,
CHALLENGE_RSASSA_PKCS1_V1_5_SHA256 /* salt_challenge_algorithm */,
CHALLENGE_RSASSA_PKCS1_V1_5_SHA256 /* unsealing_algorithm */},
AlgorithmsTestParam{
{CHALLENGE_RSASSA_PKCS1_V1_5_SHA1} /* key_algorithms */,
CHALLENGE_RSASSA_PKCS1_V1_5_SHA1 /* salt_challenge_algorithm */,
CHALLENGE_RSASSA_PKCS1_V1_5_SHA1 /* unsealing_algorithm */}));
// Test prioritization of algorithms according to their order in the input.
INSTANTIATE_TEST_CASE_P(
InputPrioritization,
ChallengeCredentialsDecryptOperationAlgorithmsTest,
Values(
AlgorithmsTestParam{
{CHALLENGE_RSASSA_PKCS1_V1_5_SHA256,
CHALLENGE_RSASSA_PKCS1_V1_5_SHA512} /* key_algorithms */,
CHALLENGE_RSASSA_PKCS1_V1_5_SHA256 /* salt_challenge_algorithm */,
CHALLENGE_RSASSA_PKCS1_V1_5_SHA256 /* unsealing_algorithm */},
AlgorithmsTestParam{
{CHALLENGE_RSASSA_PKCS1_V1_5_SHA512,
CHALLENGE_RSASSA_PKCS1_V1_5_SHA256} /* key_algorithms */,
CHALLENGE_RSASSA_PKCS1_V1_5_SHA512 /* salt_challenge_algorithm */,
CHALLENGE_RSASSA_PKCS1_V1_5_SHA512 /* unsealing_algorithm */}));
} // namespace cryptohome