File: passkey_browser_binder.h

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (215 lines) | stat: -rw-r--r-- 9,027 bytes parent folder | download | duplicates (2)
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_PAYMENTS_CONTENT_BROWSER_BINDING_PASSKEY_BROWSER_BINDER_H_
#define COMPONENTS_PAYMENTS_CONTENT_BROWSER_BINDING_PASSKEY_BROWSER_BINDER_H_

#include <cstdint>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/functional/callback.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "components/payments/content/browser_binding/browser_bound_key_store.h"
#include "components/payments/content/payment_manifest_web_data_service.h"
#include "components/webdata/common/web_data_service_consumer.h"

namespace payments {

class BrowserBoundKey;
struct BrowserBoundKeyMetadata;

// Facilitates binding browser bound keys to passkeys.
//
// Browser bound keys (BBK) are temporarily not bound to passkeys while creating
// the passkey. The BBK needs to be created before the passkey since the BBK's
// public key will be set in the client data json and itself is an input to
// creating the passkey. Once the passkey has been created then its credential
// id becomes known and the BBK can be bound to the passkey.
//
// Example passkey creation usage:
//
// auto binder = PasskeyBrowserBinder(
//     std::move(key_store), payment_manifest_web_data_service);
//
// // Create an unbound key.
// PasskeyBrowserBinder::UnboundKey unbound_key =
//     binder.CreateUnboundKey(std::move(allowed_algorithms));
//
// // Get the public key and include it in some authenticator creation request.
// auto passkey = CreatePasskey(...,
//     unbound_key.Get()->GetPublicKeyAsCoseKey());
//
// // Finally bind the key given the passkey's credential identifier.
// binder.BindKey(
//     std::move(unbound_key), passkey.GetCredentialId(), relying_party_id);
//
//
// Example retrieval usage:
//
// auto passkey = ...; // After retrieving the passkey.
//
// binder_ = std::make_unique<PasskeyBrowserBinder>(
//     std::move(key_store), payment_manifest_web_data_service);
//
// binder_->GetOrCreateBoundKeyForPasskey(
//     passkey.GetCredentialId(),
//     passkey.GetRelyingPartyId(),
//     allowed_algorithms,
//     [](std::unique_ptr<BrowserBoundKey> key) {
//       if (!key) {
//         // Handle the browser bound key could not be found nor created.
//       }
//       // Use the browser bound key to sign something.
//       key->Sign(client_data_json);
//     });
//
// This class depends on an implementation of BrowserBoundKeyStore and the
// payment manifest web data service for storing the BBK and passkey
// identifiers.
class PasskeyBrowserBinder : public WebDataServiceConsumer {
 public:
  PasskeyBrowserBinder(
      scoped_refptr<BrowserBoundKeyStore> key_store,
      scoped_refptr<PaymentManifestWebDataService> web_data_service);
  PasskeyBrowserBinder(const PasskeyBrowserBinder&) = delete;
  PasskeyBrowserBinder& operator=(const PasskeyBrowserBinder&) = delete;
  ~PasskeyBrowserBinder() override;

  // Represents a browser bound key that has not yet been associated. If
  // BindKey() is not called when this class goes out of scope, the wrapped
  // BrowserBoundKey will be deleted.
  class UnboundKey {
   public:
    UnboundKey(std::vector<uint8_t> browser_bound_key_id,
               std::unique_ptr<BrowserBoundKey> browser_bound_key,
               scoped_refptr<BrowserBoundKeyStore> key_store);
    UnboundKey(const UnboundKey&) = delete;
    UnboundKey& operator=(const UnboundKey&) = delete;
    UnboundKey(UnboundKey&&);
    UnboundKey& operator=(UnboundKey&&);
    ~UnboundKey();

    // Returns a reference to the underlying browser bound key, this is the only
    // way by which the browser bound key can be accessed before having been
    // associated.
    BrowserBoundKey& Get() { return *browser_bound_key_; }

   private:
    friend PasskeyBrowserBinder;

    // Marks the BrowserBoundKey as bound. After calling, destruction of this
    // UnboundKey will not delete the browser bound key.
    //
    // Do not call other methods on UnboundKey after calling
    // MarkKeyBoundAndReset().
    void MarkKeyBoundAndReset();

    std::vector<uint8_t> browser_bound_key_id_;
    std::unique_ptr<BrowserBoundKey> browser_bound_key_;
    scoped_refptr<BrowserBoundKeyStore> key_store_;
  };

  // Creates a browser bound key that is not yet associated to a passkey. The
  // UnboundKey should be bound using BindKey() after the credential id has
  // been created.
  std::optional<UnboundKey> CreateUnboundKey(
      const BrowserBoundKeyStore::CredentialInfoList& allowed_algorithms);

  // Gets a browser bound key for the given `credential_id` and `relying_party`
  // only if a browser bound key already exists for the credential.
  void GetBoundKeyForPasskey(
      std::vector<uint8_t> credential_id,
      std::string relying_party,
      base::OnceCallback<void(std::unique_ptr<BrowserBoundKey>)> callback);

  // Gets or creates a browser bound key for the given `credential_id`,
  // `relying_party` and `allowed_algorithms` returning the browser bound key
  // by running `callback`.
  void GetOrCreateBoundKeyForPasskey(
      std::vector<uint8_t> credential_id,
      std::string relying_party,
      const BrowserBoundKeyStore::CredentialInfoList& allowed_algorithms,
      base::OnceCallback<void(std::unique_ptr<BrowserBoundKey>)> callback);

  // Stores the association of the `key` to a `credential_id` and
  // `relying_party`. The UnboundKey must be std::moved and is thus
  // intentionally no longer available to the caller. If the BrowserBoundKey is
  // needed thereafter, then retrieve it using BoundKeyForPasskey().
  void BindKey(UnboundKey key,
               const std::vector<uint8_t>& credential_id,
               const std::string& relying_party);

  // Deletes all unknown browser bound keys, querying using the provided
  // `get_matching_credential_ids_callback` to find credentials matching each
  // relying party in the BBK storage. The
  // `get_matching_credential_ids_callback` must be valid until `callback` is
  // invoked. `callback` may hold and release the reference to this
  // PasskeyBrowserBinder object (DeleteAllUnknownBrowserBoundKeys will run
  // `callback` as its last action).
  void DeleteAllUnknownBrowserBoundKeys(
      base::RepeatingCallback<
          void(const std::string& relying_party_id,
               const std::vector<std::vector<uint8_t>>& credential_ids,
               bool require_third_party_payment_bit_set,
               base::OnceCallback<void(std::vector<std::vector<uint8_t>>)>)>
          get_matching_credential_ids_callback,
      base::OnceClosure callback);

  // WebDataServiceConsumer:
  void OnWebDataServiceRequestDone(
      WebDataServiceBase::Handle h,
      std::unique_ptr<WDTypedResult> result) override;

  // Injects the random bytes function for testing.
  void SetRandomBytesAsVectorCallbackForTesting(
      base::RepeatingCallback<std::vector<uint8_t>(size_t length)>);

  BrowserBoundKeyStore* GetBrowserBoundKeyStoreForTesting();
  PaymentManifestWebDataService* GetWebDataServiceForTesting();

 private:
  // Called after retrieving the possibly empty `existing_browser_bound_key_id`
  // to retrieve the matching browser bound key. Runs `callback` with nullptr if
  // there is no matching browser bound key.
  void GetBrowserBoundKey(
      base::OnceCallback<void(std::unique_ptr<BrowserBoundKey>)> callback,
      std::vector<uint8_t> existing_browser_bound_key_id);

  // Called after retrieving the possibly empty `existing_browser_bound_key_id`
  // to retrieve the matching browser bound key. Otherwise creates a new browser
  // bound key and saves its id. The browser bound key is returned by running
  // `callback`.
  void GetOrCreateBrowserBoundKey(
      std::vector<uint8_t> credential_id,
      std::string relying_party,
      BrowserBoundKeyStore::CredentialInfoList allowed_algorithms,
      base::OnceCallback<void(std::unique_ptr<BrowserBoundKey>)> callback,
      std::vector<uint8_t> existing_browser_bound_key_id);

  // Called after internal authenticator was called to find stale BBKs.
  // `callback` is Run once the database operation completes.
  void DeleteBrowserBoundKeys(
      base::OnceClosure callback,
      std::vector<BrowserBoundKeyMetadata> stale_bbk_metas);

  scoped_refptr<BrowserBoundKeyStore> key_store_;
  scoped_refptr<PaymentManifestWebDataService> web_data_service_;
  std::map<WebDataServiceBase::Handle, base::OnceCallback<void(bool)>>
      set_browser_bound_key_handlers_;
  std::map<WebDataServiceBase::Handle,
           base::OnceCallback<void(std::vector<uint8_t>)>>
      get_browser_bound_key_handlers_;
  base::RepeatingCallback<std::vector<uint8_t>(size_t)>
      random_bytes_as_vector_callback_;
  base::WeakPtrFactory<PasskeyBrowserBinder> weak_ptr_factory_{this};
};

}  // namespace payments

#endif  // COMPONENTS_PAYMENTS_CONTENT_BROWSER_BINDING_PASSKEY_BROWSER_BINDER_H_