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