blob: af8ce089429041f34b5f778d07ff906f16b14180 [file] [log] [blame]
// 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 "cryptohome/smart_card_verifier.h"
#include <base/memory/ptr_util.h>
#include "cryptohome/auth_factor/auth_factor_metadata.h"
#include "cryptohome/auth_factor/auth_factor_type.h"
#include "cryptohome/error/cryptohome_error.h"
#include "cryptohome/error/location_utils.h"
namespace cryptohome {
using error::CryptohomeError;
using error::ErrorAction;
using error::ErrorActionSet;
using ::hwsec_foundation::status::MakeStatus;
using ::hwsec_foundation::status::OkStatus;
using ::hwsec_foundation::status::StatusChain;
SmartCardVerifier::SmartCardVerifier(
std::string auth_factor_label,
const brillo::Blob& public_key_blob,
ChallengeCredentialsHelper* challenge_credentials_helper,
KeyChallengeServiceFactory* key_challenge_service_factory)
: AsyncCredentialVerifier(
AuthFactorType::kSmartCard,
std::move(auth_factor_label),
{.metadata = SmartCardAuthFactorMetadata{.public_key_spki_der =
public_key_blob}}),
challenge_credentials_helper_(challenge_credentials_helper),
key_challenge_service_factory_(key_challenge_service_factory) {
CHECK(challenge_credentials_helper_);
CHECK(key_challenge_service_factory_);
}
std::unique_ptr<SmartCardVerifier> SmartCardVerifier::Create(
std::string auth_factor_label,
const brillo::Blob& public_key_blob,
ChallengeCredentialsHelper* challenge_credentials_helper,
KeyChallengeServiceFactory* key_challenge_service_factory) {
return base::WrapUnique(new SmartCardVerifier(
std::move(auth_factor_label), public_key_blob,
challenge_credentials_helper, key_challenge_service_factory));
}
void SmartCardVerifier::VerifyAsync(const AuthInput& auth_input,
StatusCallback callback) const {
if (!key_challenge_service_factory_) {
LOG(ERROR) << __func__ << ": No valid key challenge service.";
std::move(callback).Run(MakeStatus<CryptohomeError>(
CRYPTOHOME_ERR_LOC(kLocSmartCardVerifierNoKeyService),
ErrorActionSet({ErrorAction::kDevCheckUnexpectedState}),
user_data_auth::CryptohomeErrorCode::
CRYPTOHOME_ERROR_INVALID_ARGUMENT));
return;
}
if (auth_input.username->empty()) {
LOG(ERROR) << __func__ << ": No valid username.";
std::move(callback).Run(MakeStatus<CryptohomeError>(
CRYPTOHOME_ERR_LOC(kLocSmartCardVerifierNoInputUser),
ErrorActionSet({ErrorAction::kDevCheckUnexpectedState}),
user_data_auth::CryptohomeErrorCode::
CRYPTOHOME_ERROR_INVALID_ARGUMENT));
return;
}
if (!auth_input.challenge_credential_auth_input.has_value()) {
LOG(ERROR) << __func__ << ": No valid challenge credential auth input.";
std::move(callback).Run(MakeStatus<CryptohomeError>(
CRYPTOHOME_ERR_LOC(kLocSmartCardVerifierNoInputAuth),
ErrorActionSet(
{ErrorAction::kDevCheckUnexpectedState, ErrorAction::kAuth}),
user_data_auth::CryptohomeErrorCode::
CRYPTOHOME_ERROR_INVALID_ARGUMENT));
return;
}
if (auth_input.challenge_credential_auth_input.value()
.challenge_signature_algorithms.empty()) {
LOG(ERROR) << __func__ << ": No valid challenge signature algorithms.";
std::move(callback).Run(MakeStatus<CryptohomeError>(
CRYPTOHOME_ERR_LOC(kLocSmartCardVerifierNoInputAlg),
ErrorActionSet(
{ErrorAction::kDevCheckUnexpectedState, ErrorAction::kAuth}),
user_data_auth::CryptohomeErrorCode::
CRYPTOHOME_ERROR_INVALID_ARGUMENT));
return;
}
auto key_challenge_service = key_challenge_service_factory_->New(
auth_input.challenge_credential_auth_input->dbus_service_name);
structure::ChallengePublicKeyInfo public_key_info{
.public_key_spki_der = auth_input.challenge_credential_auth_input.value()
.public_key_spki_der,
.signature_algorithm = auth_input.challenge_credential_auth_input.value()
.challenge_signature_algorithms,
};
// Attempt the lightweight check against the found user session.
challenge_credentials_helper_->VerifyKey(
std::move(auth_input.username), std::move(public_key_info),
std::move(key_challenge_service),
base::BindOnce(&SmartCardVerifier::OnVerifyContinue,
base::Unretained(this), std::move(callback)));
}
void SmartCardVerifier::OnVerifyContinue(StatusCallback callback,
TPMStatus status) const {
if (!status.ok()) {
std::move(callback).Run(
MakeStatus<CryptohomeError>(
CRYPTOHOME_ERR_LOC(kLocSmartCardVerifierCannotVerify))
.Wrap(std::move(status)));
return;
}
// Note that the LE credentials are not reset here, since we don't have the
// full credentials after the lightweight check.
std::move(callback).Run(OkStatus<CryptohomeError>());
}
} // namespace cryptohome