1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_WEBAUTHN_GPM_ENCLAVE_TRANSACTION_H_
#define CHROME_BROWSER_WEBAUTHN_GPM_ENCLAVE_TRANSACTION_H_
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/webauthn/enclave_manager.h"
namespace device {
enum class FidoRequestType : uint8_t;
}
namespace device::enclave {
struct ClaimedPIN;
struct CredentialRequest;
enum class PINValidationResult : int;
} // namespace device::enclave
namespace signin {
class PrimaryAccountAccessTokenFetcher;
}
namespace webauthn {
class PasskeyModel;
}
namespace sync_pb {
class WebauthnCredentialSpecifics;
}
// EnclaveUserVerificationMethod enumerates the possible ways that user
// verification will be performed for an enclave transaction.
enum class EnclaveUserVerificationMethod {
// No user verification will be performed. The user acknowledged the operation
// in browser UI.
kUserPresenceOnly,
// The user will enter a GPM PIN.
kPIN,
// User verification is satisfied because the user performed account recovery.
kImplicit,
// The operating system will perform user verification and allow signing
// with the UV key.
kUVKeyWithSystemUI,
// The device is in a state waiting for an OS UV key to be created, which can
// be done when a UV request is required.
kDeferredUVKeyWithSystemUI,
// Chrome will show user verification UI for the operating system, which will
// then allow signing
// with the UV key.
kUVKeyWithChromeUI,
// A 'silent' request. No user verification is performed, and the user did not
// explicitly acknowledge the operation in browser UI either. This is only
// used for passkey upgrades (i.e. registration with mediation=conditional).
kNoUserVerificationAndNoUserPresence,
// The request cannot be satisfied.
kUnsatisfiable,
};
// GPMEnclaveTransaction encapsulates a single request (MakeCredential or
// GetAssertion) made to the enclave authenticator.
class GPMEnclaveTransaction {
public:
// Dispatches a CredentialRequest instance to the EnclaveAuthenticator.
using EnclaveRequestCallback = base::RepeatingCallback<void(
std::unique_ptr<device::enclave::CredentialRequest>)>;
class Delegate {
public:
// Invoked when transaction encounters an error. This is useful for updating
// UI.
virtual void HandleEnclaveTransactionError() = 0;
// Invoked to build UVKeyOptions for the request. This is only invoked for
// requests that perform UV.
virtual void BuildUVKeyOptions(EnclaveManager::UVKeyOptions& options) = 0;
// Invoked with the result of the PIN claim of the transaction if PIN UV was
// performed.
virtual void HandlePINValidationResult(
device::enclave::PINValidationResult result) = 0;
// Invoked after a successful MakeCredential request.
virtual void OnPasskeyCreated(
const sync_pb::WebauthnCredentialSpecifics& passkey) = 0;
// Returns the UV method to be used for the transaction.
virtual EnclaveUserVerificationMethod GetUvMethod() = 0;
};
// `delegate`, `model` and `enclave_manager` must be non-null and outlive the
// transaction. If `uv_method` is `kPIN` `pin` must be non-null.
// `selected_credential_id` must be non-null iff `request_type` is
// `kGetAssertion`.
GPMEnclaveTransaction(
Delegate* delegate,
webauthn::PasskeyModel* model,
device::FidoRequestType request_type,
std::string rp_id,
EnclaveManager* enclave_manager,
std::optional<std::string> pin,
std::optional<std::vector<uint8_t>> selected_credential_id,
EnclaveRequestCallback enclave_request_callback);
~GPMEnclaveTransaction();
// Dispatches the request to the enclave authenticator.
void Start();
private:
// Called when the UI has reached a state where it needs to do an enclave
// operation, and an OAuth token for the enclave has been fetched.
void MaybeHashPinAndStartEnclaveTransaction(std::optional<std::string> token);
// Called when the UI has reached a state where it needs to do an enclave
// operation, an OAuth token for the enclave has been fetched, and any PIN
// hashing has been completed.
void StartEnclaveTransaction(std::optional<std::string> token,
std::unique_ptr<device::enclave::ClaimedPIN>);
void HandlePINValidationResult(device::enclave::PINValidationResult result);
void OnPasskeyCreated(sync_pb::WebauthnCredentialSpecifics passkey);
raw_ptr<Delegate> delegate_;
raw_ptr<webauthn::PasskeyModel> passkey_model_;
device::FidoRequestType request_type_;
std::string rp_id_;
raw_ptr<EnclaveManager> enclave_manager_;
std::optional<std::string> pin_;
std::optional<std::vector<uint8_t>> selected_credential_id_;
EnclaveRequestCallback enclave_request_callback_;
// Taken when attempting to create a deferred UV key. Released on destruction.
std::unique_ptr<EnclaveManager::UvKeyCreationLock> uv_key_lock_;
// The pending request to fetch an OAuth token for the enclave request.
std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher>
access_token_fetcher_;
base::WeakPtrFactory<GPMEnclaveTransaction> weak_ptr_factory_{this};
};
#endif // CHROME_BROWSER_WEBAUTHN_GPM_ENCLAVE_TRANSACTION_H_
|