blob: ad223da0549df068ea2a74bc274cff469e0f82da [file] [log] [blame] [edit]
// Copyright 2024 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/fp_migration/utility.h"
#include <string>
#include <utility>
#include <libhwsec/frontend/cryptohome/frontend.h>
#include <libhwsec-foundation/crypto/secure_blob_util.h>
#include <libhwsec-foundation/status/status_chain.h>
#include <libhwsec-foundation/status/status_chain_macros.h>
#include "cryptohome/error/action.h"
#include "cryptohome/error/cryptohome_crypto_error.h"
#include "cryptohome/error/cryptohome_error.h"
#include "cryptohome/error/cryptohome_tpm_error.h"
#include "cryptohome/error/locations.h"
#include "cryptohome/features.h"
namespace cryptohome {
namespace {
using ::cryptohome::error::CryptohomeCryptoError;
using ::cryptohome::error::CryptohomeError;
using ::cryptohome::error::CryptohomeTPMError;
using ::cryptohome::error::ErrorActionSet;
using ::cryptohome::error::PossibleAction;
using ::hwsec::PinWeaverManagerFrontend;
using ::hwsec::PinWeaverManagerFrontend::AuthChannel::kFingerprintAuthChannel;
using ::hwsec_foundation::status::MakeStatus;
using ::hwsec_foundation::status::OkStatus;
// The version number corresponding to the latest rollout attempt.
// Every time the fp migration feature flag is rolled back globally,
// increase this value by 1 for the next rollout attempt.
constexpr uint64_t kMigrationRolloutVersion = 1;
} // namespace
// static
std::string FpMigrationUtility::MigratedLegacyFpLabel(size_t index) {
return base::StringPrintf("legacy-fp-%zu", index);
}
// Returns the desired migration rollout version. The version is
// determined by the latest feature flag for migration rollout.
uint64_t FpMigrationUtility::GetLegacyFingerprintMigrationRollout() {
if (features_->IsFeatureEnabled(Features::kMigrateLegacyFingerprint)) {
return kMigrationRolloutVersion;
}
return 0;
}
bool FpMigrationUtility::NeedsMigration(std::optional<uint64_t> last_rollout) {
uint64_t desired_rollout = GetLegacyFingerprintMigrationRollout();
if (desired_rollout > 0) {
if (!last_rollout || *last_rollout < desired_rollout) {
return true;
}
}
return false;
}
void FpMigrationUtility::PrepareLegacyTemplate(const AuthInput& auth_input,
StatusCallback callback) {
if (!bio_service_) {
std::move(callback).Run(MakeStatus<CryptohomeError>(
CRYPTOHOME_ERR_LOC(kLocFpMigrationPrepareLegacyTemplateNoService),
ErrorActionSet({PossibleAction::kRetry}),
user_data_auth::CRYPTOHOME_ERROR_FINGERPRINT_ERROR_INTERNAL));
return;
}
bio_service_->GetNonce(base::BindOnce(
&FpMigrationUtility::EnrollLegacyTemplate, weak_factory_.GetWeakPtr(),
std::move(callback), auth_input));
}
void FpMigrationUtility::EnrollLegacyTemplate(
StatusCallback callback,
const AuthInput& auth_input,
std::optional<brillo::Blob> nonce) {
if (!auth_input.rate_limiter_label.has_value() ||
!auth_input.fingerprint_auth_input.has_value() ||
!auth_input.fingerprint_auth_input->legacy_record_id.has_value()) {
std::move(callback).Run(MakeStatus<CryptohomeError>(
CRYPTOHOME_ERR_LOC(kLocFpMigrationPrepareTemplateBadAuthInput),
ErrorActionSet({PossibleAction::kRetry}),
user_data_auth::CRYPTOHOME_ERROR_FINGERPRINT_ERROR_INTERNAL));
return;
}
if (!nonce.has_value()) {
std::move(callback).Run(MakeStatus<CryptohomeError>(
CRYPTOHOME_ERR_LOC(kLocFpMigrationGetNonceFailed),
ErrorActionSet({PossibleAction::kRetry}),
user_data_auth::CRYPTOHOME_ERROR_FINGERPRINT_ERROR_INTERNAL));
return;
}
hwsec::StatusOr<PinWeaverManagerFrontend::StartBiometricsAuthReply> reply =
crypto_->GetPinWeaverManager()->StartBiometricsAuth(
kFingerprintAuthChannel, *auth_input.rate_limiter_label,
std::move(*nonce));
if (!reply.ok()) {
std::move(callback).Run(
MakeStatus<CryptohomeCryptoError>(
CRYPTOHOME_ERR_LOC(kLocFpMigrationStartBioAuthFailed))
.Wrap(
MakeStatus<CryptohomeTPMError>(std::move(reply).err_status())));
return;
}
BiometricsAuthBlockService::OperationInput input{
.nonce = std::move(reply->server_nonce),
.encrypted_label_seed = std::move(reply->encrypted_he_secret),
.iv = std::move(reply->iv),
};
bio_service_->EnrollLegacyTemplate(
AuthFactorType::kFingerprint,
*auth_input.fingerprint_auth_input->legacy_record_id, std::move(input),
std::move(callback));
}
void FpMigrationUtility::ListLegacyRecords(LegacyRecordsCallback callback) {
if (!bio_service_) {
std::move(callback).Run(MakeStatus<CryptohomeError>(
CRYPTOHOME_ERR_LOC(kLocFpMigrationListLegacyRecordsNoService),
ErrorActionSet({PossibleAction::kRetry}),
user_data_auth::CRYPTOHOME_ERROR_FINGERPRINT_ERROR_INTERNAL));
return;
}
bio_service_->ListLegacyRecords(std::move(callback));
}
} // namespace cryptohome