1*6777b538SAndroid Build Coastguard Worker // Copyright 2024 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include <atomic>
6*6777b538SAndroid Build Coastguard Worker #include <functional>
7*6777b538SAndroid Build Coastguard Worker #include <utility>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <windows.foundation.h>
10*6777b538SAndroid Build Coastguard Worker #include <windows.security.credentials.h>
11*6777b538SAndroid Build Coastguard Worker #include <windows.security.cryptography.core.h>
12*6777b538SAndroid Build Coastguard Worker #include <windows.storage.streams.h>
13*6777b538SAndroid Build Coastguard Worker
14*6777b538SAndroid Build Coastguard Worker #include "base/base64.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback_helpers.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/memory/scoped_refptr.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/memory/weak_ptr.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/strings/strcat.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/task/bind_post_task.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/task/single_thread_task_runner.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/task/thread_pool.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/threading/scoped_thread_priority.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/win/core_winrt_util.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/win/post_async_results.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/win/scoped_hstring.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/win/winrt_storage_util.h"
28*6777b538SAndroid Build Coastguard Worker #include "crypto/random.h"
29*6777b538SAndroid Build Coastguard Worker #include "crypto/user_verifying_key.h"
30*6777b538SAndroid Build Coastguard Worker
31*6777b538SAndroid Build Coastguard Worker using ABI::Windows::Foundation::IAsyncAction;
32*6777b538SAndroid Build Coastguard Worker using ABI::Windows::Foundation::IAsyncOperation;
33*6777b538SAndroid Build Coastguard Worker using ABI::Windows::Security::Credentials::IKeyCredential;
34*6777b538SAndroid Build Coastguard Worker using ABI::Windows::Security::Credentials::IKeyCredentialManagerStatics;
35*6777b538SAndroid Build Coastguard Worker using ABI::Windows::Security::Credentials::IKeyCredentialOperationResult;
36*6777b538SAndroid Build Coastguard Worker using ABI::Windows::Security::Credentials::IKeyCredentialRetrievalResult;
37*6777b538SAndroid Build Coastguard Worker using ABI::Windows::Security::Credentials::KeyCredentialCreationOption;
38*6777b538SAndroid Build Coastguard Worker using ABI::Windows::Security::Credentials::KeyCredentialOperationResult;
39*6777b538SAndroid Build Coastguard Worker using ABI::Windows::Security::Credentials::KeyCredentialRetrievalResult;
40*6777b538SAndroid Build Coastguard Worker using ABI::Windows::Security::Credentials::KeyCredentialStatus;
41*6777b538SAndroid Build Coastguard Worker using ABI::Windows::Security::Credentials::KeyCredentialStatus_Success;
42*6777b538SAndroid Build Coastguard Worker using ABI::Windows::Security::Cryptography::Core::
43*6777b538SAndroid Build Coastguard Worker CryptographicPublicKeyBlobType_X509SubjectPublicKeyInfo;
44*6777b538SAndroid Build Coastguard Worker using ABI::Windows::Storage::Streams::IBuffer;
45*6777b538SAndroid Build Coastguard Worker using Microsoft::WRL::ComPtr;
46*6777b538SAndroid Build Coastguard Worker
47*6777b538SAndroid Build Coastguard Worker namespace crypto {
48*6777b538SAndroid Build Coastguard Worker
49*6777b538SAndroid Build Coastguard Worker namespace {
50*6777b538SAndroid Build Coastguard Worker
51*6777b538SAndroid Build Coastguard Worker enum KeyCredentialManagerAvailability {
52*6777b538SAndroid Build Coastguard Worker kUnknown = 0,
53*6777b538SAndroid Build Coastguard Worker kAvailable = 1,
54*6777b538SAndroid Build Coastguard Worker kUnavailable = 2,
55*6777b538SAndroid Build Coastguard Worker };
56*6777b538SAndroid Build Coastguard Worker
FormatError(std::string message,HRESULT hr)57*6777b538SAndroid Build Coastguard Worker std::string FormatError(std::string message, HRESULT hr) {
58*6777b538SAndroid Build Coastguard Worker return base::StrCat(
59*6777b538SAndroid Build Coastguard Worker {message, " (hr = ", logging::SystemErrorCodeToString(hr), ")"});
60*6777b538SAndroid Build Coastguard Worker }
61*6777b538SAndroid Build Coastguard Worker
62*6777b538SAndroid Build Coastguard Worker // This helper splits OnceCallback three ways for use with `PostAsyncHandlers`,
63*6777b538SAndroid Build Coastguard Worker // which has three separate paths to outcomes: Invoke a success callback, invoke
64*6777b538SAndroid Build Coastguard Worker // an error callback, or return an error.
65*6777b538SAndroid Build Coastguard Worker template <typename... Args>
66*6777b538SAndroid Build Coastguard Worker std::tuple<base::OnceCallback<void(Args...)>,
67*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(Args...)>,
68*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(Args...)>>
SplitOnceCallbackIntoThree(base::OnceCallback<void (Args...)> callback)69*6777b538SAndroid Build Coastguard Worker SplitOnceCallbackIntoThree(base::OnceCallback<void(Args...)> callback) {
70*6777b538SAndroid Build Coastguard Worker auto first_split = base::SplitOnceCallback(std::move(callback));
71*6777b538SAndroid Build Coastguard Worker auto second_split = base::SplitOnceCallback(std::move(first_split.first));
72*6777b538SAndroid Build Coastguard Worker return {std::move(first_split.second), std::move(second_split.first),
73*6777b538SAndroid Build Coastguard Worker std::move(second_split.second)};
74*6777b538SAndroid Build Coastguard Worker }
75*6777b538SAndroid Build Coastguard Worker
OnSigningSuccess(base::OnceCallback<void (std::optional<std::vector<uint8_t>>)> callback,ComPtr<IKeyCredentialOperationResult> sign_result)76*6777b538SAndroid Build Coastguard Worker void OnSigningSuccess(
77*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(std::optional<std::vector<uint8_t>>)> callback,
78*6777b538SAndroid Build Coastguard Worker ComPtr<IKeyCredentialOperationResult> sign_result) {
79*6777b538SAndroid Build Coastguard Worker KeyCredentialStatus status;
80*6777b538SAndroid Build Coastguard Worker HRESULT hr = sign_result->get_Status(&status);
81*6777b538SAndroid Build Coastguard Worker if (FAILED(hr) || status != KeyCredentialStatus_Success) {
82*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << FormatError(
83*6777b538SAndroid Build Coastguard Worker "Failed to obtain Status from IKeyCredentialOperationResult", hr);
84*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(std::nullopt);
85*6777b538SAndroid Build Coastguard Worker return;
86*6777b538SAndroid Build Coastguard Worker }
87*6777b538SAndroid Build Coastguard Worker
88*6777b538SAndroid Build Coastguard Worker ComPtr<IBuffer> signature_buffer;
89*6777b538SAndroid Build Coastguard Worker hr = sign_result->get_Result(&signature_buffer);
90*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) {
91*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << FormatError(
92*6777b538SAndroid Build Coastguard Worker "Failed to obtain Result from IKeyCredentialOperationResult", hr);
93*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(std::nullopt);
94*6777b538SAndroid Build Coastguard Worker return;
95*6777b538SAndroid Build Coastguard Worker }
96*6777b538SAndroid Build Coastguard Worker
97*6777b538SAndroid Build Coastguard Worker uint8_t* signature_data = nullptr;
98*6777b538SAndroid Build Coastguard Worker uint32_t signature_length = 0;
99*6777b538SAndroid Build Coastguard Worker hr = base::win::GetPointerToBufferData(signature_buffer.Get(),
100*6777b538SAndroid Build Coastguard Worker &signature_data, &signature_length);
101*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) {
102*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << FormatError("Failed to obtain data from signature buffer",
103*6777b538SAndroid Build Coastguard Worker hr);
104*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(std::nullopt);
105*6777b538SAndroid Build Coastguard Worker return;
106*6777b538SAndroid Build Coastguard Worker }
107*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(
108*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t>(signature_data, signature_data + signature_length));
109*6777b538SAndroid Build Coastguard Worker }
110*6777b538SAndroid Build Coastguard Worker
OnSigningError(base::OnceCallback<void (std::optional<std::vector<uint8_t>>)> callback,HRESULT hr)111*6777b538SAndroid Build Coastguard Worker void OnSigningError(
112*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(std::optional<std::vector<uint8_t>>)> callback,
113*6777b538SAndroid Build Coastguard Worker HRESULT hr) {
114*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << FormatError("Failed to sign with user-verifying signature", hr);
115*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(std::nullopt);
116*6777b538SAndroid Build Coastguard Worker }
117*6777b538SAndroid Build Coastguard Worker
SignInternal(std::vector<uint8_t> data,ComPtr<IKeyCredential> credential,base::OnceCallback<void (std::optional<std::vector<uint8_t>>)> callback)118*6777b538SAndroid Build Coastguard Worker void SignInternal(
119*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t> data,
120*6777b538SAndroid Build Coastguard Worker ComPtr<IKeyCredential> credential,
121*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(std::optional<std::vector<uint8_t>>)> callback) {
122*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::ComPtr<IBuffer> signing_buf;
123*6777b538SAndroid Build Coastguard Worker HRESULT hr =
124*6777b538SAndroid Build Coastguard Worker base::win::CreateIBufferFromData(data.data(), data.size(), &signing_buf);
125*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) {
126*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << FormatError("SignInternal: IBuffer creation failed", hr);
127*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(std::nullopt);
128*6777b538SAndroid Build Coastguard Worker return;
129*6777b538SAndroid Build Coastguard Worker }
130*6777b538SAndroid Build Coastguard Worker
131*6777b538SAndroid Build Coastguard Worker ComPtr<IAsyncOperation<KeyCredentialOperationResult*>> sign_result;
132*6777b538SAndroid Build Coastguard Worker hr = credential->RequestSignAsync(signing_buf.Get(), &sign_result);
133*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) {
134*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << FormatError("SignInternal: Call to RequestSignAsync failed",
135*6777b538SAndroid Build Coastguard Worker hr);
136*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(std::nullopt);
137*6777b538SAndroid Build Coastguard Worker return;
138*6777b538SAndroid Build Coastguard Worker }
139*6777b538SAndroid Build Coastguard Worker
140*6777b538SAndroid Build Coastguard Worker auto callback_splits = SplitOnceCallbackIntoThree(std::move(callback));
141*6777b538SAndroid Build Coastguard Worker hr = base::win::PostAsyncHandlers(
142*6777b538SAndroid Build Coastguard Worker sign_result.Get(),
143*6777b538SAndroid Build Coastguard Worker base::BindOnce(&OnSigningSuccess,
144*6777b538SAndroid Build Coastguard Worker std::move(std::get<0>(callback_splits))),
145*6777b538SAndroid Build Coastguard Worker base::BindOnce(&OnSigningError, std::move(std::get<1>(callback_splits))));
146*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) {
147*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << FormatError("SignInternal: Call to PostAsyncHandlers failed",
148*6777b538SAndroid Build Coastguard Worker hr);
149*6777b538SAndroid Build Coastguard Worker std::move(std::get<2>(callback_splits)).Run(std::nullopt);
150*6777b538SAndroid Build Coastguard Worker return;
151*6777b538SAndroid Build Coastguard Worker }
152*6777b538SAndroid Build Coastguard Worker }
153*6777b538SAndroid Build Coastguard Worker
154*6777b538SAndroid Build Coastguard Worker class UserVerifyingSigningKeyWin : public UserVerifyingSigningKey {
155*6777b538SAndroid Build Coastguard Worker public:
UserVerifyingSigningKeyWin(std::string key_name,ComPtr<IKeyCredential> credential)156*6777b538SAndroid Build Coastguard Worker UserVerifyingSigningKeyWin(std::string key_name,
157*6777b538SAndroid Build Coastguard Worker ComPtr<IKeyCredential> credential)
158*6777b538SAndroid Build Coastguard Worker : key_name_(std::move(key_name)), credential_(std::move(credential)) {}
159*6777b538SAndroid Build Coastguard Worker ~UserVerifyingSigningKeyWin() override = default;
160*6777b538SAndroid Build Coastguard Worker
Sign(base::span<const uint8_t> data,base::OnceCallback<void (std::optional<std::vector<uint8_t>>)> callback)161*6777b538SAndroid Build Coastguard Worker void Sign(base::span<const uint8_t> data,
162*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(std::optional<std::vector<uint8_t>>)>
163*6777b538SAndroid Build Coastguard Worker callback) override {
164*6777b538SAndroid Build Coastguard Worker scoped_refptr<base::SequencedTaskRunner> task_runner =
165*6777b538SAndroid Build Coastguard Worker base::ThreadPool::CreateSequencedTaskRunner(
166*6777b538SAndroid Build Coastguard Worker {base::MayBlock(), base::TaskPriority::USER_BLOCKING});
167*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t> vec_data(data.begin(), data.end());
168*6777b538SAndroid Build Coastguard Worker task_runner->PostTask(
169*6777b538SAndroid Build Coastguard Worker FROM_HERE,
170*6777b538SAndroid Build Coastguard Worker base::BindOnce(
171*6777b538SAndroid Build Coastguard Worker &SignInternal, std::move(vec_data), credential_,
172*6777b538SAndroid Build Coastguard Worker base::BindPostTaskToCurrentDefault(std::move(callback))));
173*6777b538SAndroid Build Coastguard Worker }
174*6777b538SAndroid Build Coastguard Worker
GetPublicKey() const175*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t> GetPublicKey() const override {
176*6777b538SAndroid Build Coastguard Worker ComPtr<IBuffer> key_buf;
177*6777b538SAndroid Build Coastguard Worker HRESULT hr = credential_->RetrievePublicKeyWithBlobType(
178*6777b538SAndroid Build Coastguard Worker CryptographicPublicKeyBlobType_X509SubjectPublicKeyInfo, &key_buf);
179*6777b538SAndroid Build Coastguard Worker CHECK(SUCCEEDED(hr)) << FormatError(
180*6777b538SAndroid Build Coastguard Worker "Failed to obtain public key from KeyCredential", hr);
181*6777b538SAndroid Build Coastguard Worker
182*6777b538SAndroid Build Coastguard Worker uint8_t* pub_key_data = nullptr;
183*6777b538SAndroid Build Coastguard Worker uint32_t pub_key_length = 0;
184*6777b538SAndroid Build Coastguard Worker hr = base::win::GetPointerToBufferData(key_buf.Get(), &pub_key_data,
185*6777b538SAndroid Build Coastguard Worker &pub_key_length);
186*6777b538SAndroid Build Coastguard Worker CHECK(SUCCEEDED(hr)) << FormatError(
187*6777b538SAndroid Build Coastguard Worker "Failed to access public key buffer data", hr);
188*6777b538SAndroid Build Coastguard Worker return std::vector<uint8_t>(pub_key_data, pub_key_data + pub_key_length);
189*6777b538SAndroid Build Coastguard Worker }
190*6777b538SAndroid Build Coastguard Worker
GetKeyLabel() const191*6777b538SAndroid Build Coastguard Worker const UserVerifyingKeyLabel& GetKeyLabel() const override {
192*6777b538SAndroid Build Coastguard Worker return key_name_;
193*6777b538SAndroid Build Coastguard Worker }
194*6777b538SAndroid Build Coastguard Worker
195*6777b538SAndroid Build Coastguard Worker private:
196*6777b538SAndroid Build Coastguard Worker std::string key_name_;
197*6777b538SAndroid Build Coastguard Worker ComPtr<IKeyCredential> credential_;
198*6777b538SAndroid Build Coastguard Worker };
199*6777b538SAndroid Build Coastguard Worker
OnKeyCreationCompletionSuccess(base::OnceCallback<void (std::unique_ptr<UserVerifyingSigningKey>)> callback,std::string key_name,ComPtr<IKeyCredentialRetrievalResult> key_result)200*6777b538SAndroid Build Coastguard Worker void OnKeyCreationCompletionSuccess(
201*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(std::unique_ptr<UserVerifyingSigningKey>)> callback,
202*6777b538SAndroid Build Coastguard Worker std::string key_name,
203*6777b538SAndroid Build Coastguard Worker ComPtr<IKeyCredentialRetrievalResult> key_result) {
204*6777b538SAndroid Build Coastguard Worker KeyCredentialStatus status;
205*6777b538SAndroid Build Coastguard Worker HRESULT hr = key_result->get_Status(&status);
206*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) {
207*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << FormatError(
208*6777b538SAndroid Build Coastguard Worker "Failed to obtain Status from IKeyCredentialRetrievalResult", hr);
209*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(nullptr);
210*6777b538SAndroid Build Coastguard Worker return;
211*6777b538SAndroid Build Coastguard Worker } else if (status != KeyCredentialStatus_Success) {
212*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << "IKeyCredentialRetrievalResult failed with status "
213*6777b538SAndroid Build Coastguard Worker << static_cast<uint32_t>(status);
214*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(nullptr);
215*6777b538SAndroid Build Coastguard Worker return;
216*6777b538SAndroid Build Coastguard Worker }
217*6777b538SAndroid Build Coastguard Worker
218*6777b538SAndroid Build Coastguard Worker ComPtr<IKeyCredential> credential;
219*6777b538SAndroid Build Coastguard Worker hr = key_result->get_Credential(&credential);
220*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) {
221*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << FormatError(
222*6777b538SAndroid Build Coastguard Worker "Failed to obtain KeyCredential from KeyCredentialRetrievalResult", hr);
223*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(nullptr);
224*6777b538SAndroid Build Coastguard Worker return;
225*6777b538SAndroid Build Coastguard Worker }
226*6777b538SAndroid Build Coastguard Worker auto key = std::make_unique<UserVerifyingSigningKeyWin>(
227*6777b538SAndroid Build Coastguard Worker std::move(key_name), std::move(credential));
228*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(std::move(key));
229*6777b538SAndroid Build Coastguard Worker }
230*6777b538SAndroid Build Coastguard Worker
OnKeyCreationCompletionError(base::OnceCallback<void (std::unique_ptr<UserVerifyingSigningKey>)> callback,HRESULT hr)231*6777b538SAndroid Build Coastguard Worker void OnKeyCreationCompletionError(
232*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(std::unique_ptr<UserVerifyingSigningKey>)> callback,
233*6777b538SAndroid Build Coastguard Worker HRESULT hr) {
234*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << FormatError("Failed to obtain user-verifying key from system",
235*6777b538SAndroid Build Coastguard Worker hr);
236*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(nullptr);
237*6777b538SAndroid Build Coastguard Worker }
238*6777b538SAndroid Build Coastguard Worker
GenerateUserVerifyingSigningKeyInternal(std::string key_label,base::OnceCallback<void (std::unique_ptr<UserVerifyingSigningKey>)> callback)239*6777b538SAndroid Build Coastguard Worker void GenerateUserVerifyingSigningKeyInternal(
240*6777b538SAndroid Build Coastguard Worker std::string key_label,
241*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(std::unique_ptr<UserVerifyingSigningKey>)>
242*6777b538SAndroid Build Coastguard Worker callback) {
243*6777b538SAndroid Build Coastguard Worker SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
244*6777b538SAndroid Build Coastguard Worker auto key_name = base::win::ScopedHString::Create(key_label);
245*6777b538SAndroid Build Coastguard Worker
246*6777b538SAndroid Build Coastguard Worker ComPtr<IKeyCredentialManagerStatics> factory;
247*6777b538SAndroid Build Coastguard Worker HRESULT hr = base::win::GetActivationFactory<
248*6777b538SAndroid Build Coastguard Worker IKeyCredentialManagerStatics,
249*6777b538SAndroid Build Coastguard Worker RuntimeClass_Windows_Security_Credentials_KeyCredentialManager>(&factory);
250*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) {
251*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << FormatError(
252*6777b538SAndroid Build Coastguard Worker "GenerateUserVerifyingSigningKeyInternal: Failed to obtain activation "
253*6777b538SAndroid Build Coastguard Worker "factory for KeyCredentialManager",
254*6777b538SAndroid Build Coastguard Worker hr);
255*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(nullptr);
256*6777b538SAndroid Build Coastguard Worker return;
257*6777b538SAndroid Build Coastguard Worker }
258*6777b538SAndroid Build Coastguard Worker
259*6777b538SAndroid Build Coastguard Worker ComPtr<IAsyncOperation<KeyCredentialRetrievalResult*>> create_result;
260*6777b538SAndroid Build Coastguard Worker hr = factory->RequestCreateAsync(
261*6777b538SAndroid Build Coastguard Worker key_name.get(),
262*6777b538SAndroid Build Coastguard Worker KeyCredentialCreationOption::KeyCredentialCreationOption_ReplaceExisting,
263*6777b538SAndroid Build Coastguard Worker &create_result);
264*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) {
265*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << FormatError(
266*6777b538SAndroid Build Coastguard Worker "GenerateUserVerifyingSigningKeyInternal: Call to RequestCreateAsync "
267*6777b538SAndroid Build Coastguard Worker "failed",
268*6777b538SAndroid Build Coastguard Worker hr);
269*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(nullptr);
270*6777b538SAndroid Build Coastguard Worker return;
271*6777b538SAndroid Build Coastguard Worker }
272*6777b538SAndroid Build Coastguard Worker
273*6777b538SAndroid Build Coastguard Worker auto callback_splits = SplitOnceCallbackIntoThree(std::move(callback));
274*6777b538SAndroid Build Coastguard Worker hr = base::win::PostAsyncHandlers(
275*6777b538SAndroid Build Coastguard Worker create_result.Get(),
276*6777b538SAndroid Build Coastguard Worker base::BindOnce(&OnKeyCreationCompletionSuccess,
277*6777b538SAndroid Build Coastguard Worker std::move(std::get<0>(callback_splits)),
278*6777b538SAndroid Build Coastguard Worker std::move(key_label)),
279*6777b538SAndroid Build Coastguard Worker base::BindOnce(&OnKeyCreationCompletionError,
280*6777b538SAndroid Build Coastguard Worker std::move(std::get<1>(callback_splits))));
281*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) {
282*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << FormatError(
283*6777b538SAndroid Build Coastguard Worker "GenerateUserVerifyingSigningKeyInternal: Call to PostAsyncHandlers "
284*6777b538SAndroid Build Coastguard Worker "failed",
285*6777b538SAndroid Build Coastguard Worker hr);
286*6777b538SAndroid Build Coastguard Worker std::move(std::get<2>(callback_splits)).Run(nullptr);
287*6777b538SAndroid Build Coastguard Worker return;
288*6777b538SAndroid Build Coastguard Worker }
289*6777b538SAndroid Build Coastguard Worker }
290*6777b538SAndroid Build Coastguard Worker
GetUserVerifyingSigningKeyInternal(std::string key_label,base::OnceCallback<void (std::unique_ptr<UserVerifyingSigningKey>)> callback)291*6777b538SAndroid Build Coastguard Worker void GetUserVerifyingSigningKeyInternal(
292*6777b538SAndroid Build Coastguard Worker std::string key_label,
293*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(std::unique_ptr<UserVerifyingSigningKey>)>
294*6777b538SAndroid Build Coastguard Worker callback) {
295*6777b538SAndroid Build Coastguard Worker SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
296*6777b538SAndroid Build Coastguard Worker auto key_name = base::win::ScopedHString::Create(key_label);
297*6777b538SAndroid Build Coastguard Worker
298*6777b538SAndroid Build Coastguard Worker ComPtr<IKeyCredentialManagerStatics> factory;
299*6777b538SAndroid Build Coastguard Worker HRESULT hr = base::win::GetActivationFactory<
300*6777b538SAndroid Build Coastguard Worker IKeyCredentialManagerStatics,
301*6777b538SAndroid Build Coastguard Worker RuntimeClass_Windows_Security_Credentials_KeyCredentialManager>(&factory);
302*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) {
303*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << FormatError(
304*6777b538SAndroid Build Coastguard Worker "GetUserVerifyingSigningKeyInternal: Failed to obtain activation "
305*6777b538SAndroid Build Coastguard Worker "factory for KeyCredentialManager",
306*6777b538SAndroid Build Coastguard Worker hr);
307*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(nullptr);
308*6777b538SAndroid Build Coastguard Worker return;
309*6777b538SAndroid Build Coastguard Worker }
310*6777b538SAndroid Build Coastguard Worker
311*6777b538SAndroid Build Coastguard Worker ComPtr<IAsyncOperation<KeyCredentialRetrievalResult*>> open_result;
312*6777b538SAndroid Build Coastguard Worker hr = factory->OpenAsync(key_name.get(), &open_result);
313*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) {
314*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << FormatError(
315*6777b538SAndroid Build Coastguard Worker "GetUserVerifyingSigningKeyInternal: Call to OpenAsync failed", hr);
316*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(nullptr);
317*6777b538SAndroid Build Coastguard Worker return;
318*6777b538SAndroid Build Coastguard Worker }
319*6777b538SAndroid Build Coastguard Worker
320*6777b538SAndroid Build Coastguard Worker auto callback_splits = SplitOnceCallbackIntoThree(std::move(callback));
321*6777b538SAndroid Build Coastguard Worker hr = base::win::PostAsyncHandlers(
322*6777b538SAndroid Build Coastguard Worker open_result.Get(),
323*6777b538SAndroid Build Coastguard Worker base::BindOnce(&OnKeyCreationCompletionSuccess,
324*6777b538SAndroid Build Coastguard Worker std::move(std::get<0>(callback_splits)),
325*6777b538SAndroid Build Coastguard Worker std::move(key_label)),
326*6777b538SAndroid Build Coastguard Worker base::BindOnce(&OnKeyCreationCompletionError,
327*6777b538SAndroid Build Coastguard Worker std::move(std::get<1>(callback_splits))));
328*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) {
329*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << FormatError(
330*6777b538SAndroid Build Coastguard Worker "GetUserVerifyingSigningKeyInternal: Call to PostAsyncHandlers failed",
331*6777b538SAndroid Build Coastguard Worker hr);
332*6777b538SAndroid Build Coastguard Worker std::move(std::get<2>(callback_splits)).Run(nullptr);
333*6777b538SAndroid Build Coastguard Worker return;
334*6777b538SAndroid Build Coastguard Worker }
335*6777b538SAndroid Build Coastguard Worker }
336*6777b538SAndroid Build Coastguard Worker
DeleteUserVerifyingKeyInternal(UserVerifyingKeyLabel key_label,base::OnceCallback<void (bool)> callback)337*6777b538SAndroid Build Coastguard Worker void DeleteUserVerifyingKeyInternal(UserVerifyingKeyLabel key_label,
338*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(bool)> callback) {
339*6777b538SAndroid Build Coastguard Worker SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
340*6777b538SAndroid Build Coastguard Worker
341*6777b538SAndroid Build Coastguard Worker ComPtr<IKeyCredentialManagerStatics> factory;
342*6777b538SAndroid Build Coastguard Worker HRESULT hr = base::win::GetActivationFactory<
343*6777b538SAndroid Build Coastguard Worker IKeyCredentialManagerStatics,
344*6777b538SAndroid Build Coastguard Worker RuntimeClass_Windows_Security_Credentials_KeyCredentialManager>(&factory);
345*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) {
346*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << FormatError(
347*6777b538SAndroid Build Coastguard Worker "DeleteUserVerifyingKeyInternal: Failed to obtain activation "
348*6777b538SAndroid Build Coastguard Worker "factory for KeyCredentialManager",
349*6777b538SAndroid Build Coastguard Worker hr);
350*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(false);
351*6777b538SAndroid Build Coastguard Worker return;
352*6777b538SAndroid Build Coastguard Worker }
353*6777b538SAndroid Build Coastguard Worker
354*6777b538SAndroid Build Coastguard Worker ComPtr<IAsyncAction> delete_operation;
355*6777b538SAndroid Build Coastguard Worker auto key_name = base::win::ScopedHString::Create(key_label);
356*6777b538SAndroid Build Coastguard Worker hr = factory->DeleteAsync(key_name.get(), &delete_operation);
357*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) {
358*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << FormatError(
359*6777b538SAndroid Build Coastguard Worker "DeleteUserVerifyingKeyInternal: Call to DeleteAsync failed", hr);
360*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(false);
361*6777b538SAndroid Build Coastguard Worker return;
362*6777b538SAndroid Build Coastguard Worker }
363*6777b538SAndroid Build Coastguard Worker
364*6777b538SAndroid Build Coastguard Worker // DeleteAsync does not report a value, so we have to assume success.
365*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(true);
366*6777b538SAndroid Build Coastguard Worker }
367*6777b538SAndroid Build Coastguard Worker
SelectAlgorithm(base::span<const SignatureVerifier::SignatureAlgorithm> acceptable_algorithms)368*6777b538SAndroid Build Coastguard Worker std::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm(
369*6777b538SAndroid Build Coastguard Worker base::span<const SignatureVerifier::SignatureAlgorithm>
370*6777b538SAndroid Build Coastguard Worker acceptable_algorithms) {
371*6777b538SAndroid Build Coastguard Worker // Windows keys come in any algorithm you want, as long as it's RSA 2048.
372*6777b538SAndroid Build Coastguard Worker for (auto algorithm : acceptable_algorithms) {
373*6777b538SAndroid Build Coastguard Worker if (algorithm == SignatureVerifier::SignatureAlgorithm::RSA_PKCS1_SHA256) {
374*6777b538SAndroid Build Coastguard Worker return algorithm;
375*6777b538SAndroid Build Coastguard Worker }
376*6777b538SAndroid Build Coastguard Worker }
377*6777b538SAndroid Build Coastguard Worker return std::nullopt;
378*6777b538SAndroid Build Coastguard Worker }
379*6777b538SAndroid Build Coastguard Worker
380*6777b538SAndroid Build Coastguard Worker class UserVerifyingKeyProviderWin : public UserVerifyingKeyProvider {
381*6777b538SAndroid Build Coastguard Worker public:
382*6777b538SAndroid Build Coastguard Worker UserVerifyingKeyProviderWin() = default;
383*6777b538SAndroid Build Coastguard Worker ~UserVerifyingKeyProviderWin() override = default;
384*6777b538SAndroid Build Coastguard Worker
GenerateUserVerifyingSigningKey(base::span<const SignatureVerifier::SignatureAlgorithm> acceptable_algorithms,base::OnceCallback<void (std::unique_ptr<UserVerifyingSigningKey>)> callback)385*6777b538SAndroid Build Coastguard Worker void GenerateUserVerifyingSigningKey(
386*6777b538SAndroid Build Coastguard Worker base::span<const SignatureVerifier::SignatureAlgorithm>
387*6777b538SAndroid Build Coastguard Worker acceptable_algorithms,
388*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(std::unique_ptr<UserVerifyingSigningKey>)>
389*6777b538SAndroid Build Coastguard Worker callback) override {
390*6777b538SAndroid Build Coastguard Worker // Ignore the non-empty return value of `SelectAlgorithm` unless in the
391*6777b538SAndroid Build Coastguard Worker // future Windows supports more algorithms.
392*6777b538SAndroid Build Coastguard Worker if (!SelectAlgorithm(acceptable_algorithms)) {
393*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << "Key generation does not include a supported algorithm.";
394*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(nullptr);
395*6777b538SAndroid Build Coastguard Worker return;
396*6777b538SAndroid Build Coastguard Worker }
397*6777b538SAndroid Build Coastguard Worker
398*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t> random(16);
399*6777b538SAndroid Build Coastguard Worker crypto::RandBytes(random);
400*6777b538SAndroid Build Coastguard Worker UserVerifyingKeyLabel key_label =
401*6777b538SAndroid Build Coastguard Worker base::StrCat({"uvkey-", base::Base64Encode(random)});
402*6777b538SAndroid Build Coastguard Worker
403*6777b538SAndroid Build Coastguard Worker scoped_refptr<base::SequencedTaskRunner> task_runner =
404*6777b538SAndroid Build Coastguard Worker base::ThreadPool::CreateSequencedTaskRunner(
405*6777b538SAndroid Build Coastguard Worker {base::MayBlock(), base::TaskPriority::USER_BLOCKING});
406*6777b538SAndroid Build Coastguard Worker task_runner->PostTask(
407*6777b538SAndroid Build Coastguard Worker FROM_HERE,
408*6777b538SAndroid Build Coastguard Worker base::BindOnce(
409*6777b538SAndroid Build Coastguard Worker &GenerateUserVerifyingSigningKeyInternal, std::move(key_label),
410*6777b538SAndroid Build Coastguard Worker base::BindPostTaskToCurrentDefault(std::move(callback))));
411*6777b538SAndroid Build Coastguard Worker }
412*6777b538SAndroid Build Coastguard Worker
GetUserVerifyingSigningKey(UserVerifyingKeyLabel key_label,base::OnceCallback<void (std::unique_ptr<UserVerifyingSigningKey>)> callback)413*6777b538SAndroid Build Coastguard Worker void GetUserVerifyingSigningKey(
414*6777b538SAndroid Build Coastguard Worker UserVerifyingKeyLabel key_label,
415*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(std::unique_ptr<UserVerifyingSigningKey>)>
416*6777b538SAndroid Build Coastguard Worker callback) override {
417*6777b538SAndroid Build Coastguard Worker scoped_refptr<base::SequencedTaskRunner> task_runner =
418*6777b538SAndroid Build Coastguard Worker base::ThreadPool::CreateSequencedTaskRunner(
419*6777b538SAndroid Build Coastguard Worker {base::MayBlock(), base::TaskPriority::USER_BLOCKING});
420*6777b538SAndroid Build Coastguard Worker task_runner->PostTask(
421*6777b538SAndroid Build Coastguard Worker FROM_HERE,
422*6777b538SAndroid Build Coastguard Worker base::BindOnce(
423*6777b538SAndroid Build Coastguard Worker &GetUserVerifyingSigningKeyInternal, key_label,
424*6777b538SAndroid Build Coastguard Worker base::BindPostTaskToCurrentDefault(std::move(callback))));
425*6777b538SAndroid Build Coastguard Worker }
426*6777b538SAndroid Build Coastguard Worker
DeleteUserVerifyingKey(UserVerifyingKeyLabel key_label,base::OnceCallback<void (bool)> callback)427*6777b538SAndroid Build Coastguard Worker void DeleteUserVerifyingKey(
428*6777b538SAndroid Build Coastguard Worker UserVerifyingKeyLabel key_label,
429*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(bool)> callback) override {
430*6777b538SAndroid Build Coastguard Worker scoped_refptr<base::SequencedTaskRunner> task_runner =
431*6777b538SAndroid Build Coastguard Worker base::ThreadPool::CreateSequencedTaskRunner(
432*6777b538SAndroid Build Coastguard Worker {base::MayBlock(), base::TaskPriority::USER_BLOCKING});
433*6777b538SAndroid Build Coastguard Worker task_runner->PostTask(
434*6777b538SAndroid Build Coastguard Worker FROM_HERE, base::BindOnce(DeleteUserVerifyingKeyInternal, key_label,
435*6777b538SAndroid Build Coastguard Worker base::BindPostTaskToCurrentDefault(
436*6777b538SAndroid Build Coastguard Worker std::move(callback))));
437*6777b538SAndroid Build Coastguard Worker }
438*6777b538SAndroid Build Coastguard Worker };
439*6777b538SAndroid Build Coastguard Worker
IsKeyCredentialManagerAvailableInternal(base::OnceCallback<void (bool)> callback)440*6777b538SAndroid Build Coastguard Worker void IsKeyCredentialManagerAvailableInternal(
441*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(bool)> callback) {
442*6777b538SAndroid Build Coastguard Worker SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
443*6777b538SAndroid Build Coastguard Worker // Lookup requires an asynchronous system API call, so cache the value.
444*6777b538SAndroid Build Coastguard Worker static std::atomic<KeyCredentialManagerAvailability> availability =
445*6777b538SAndroid Build Coastguard Worker KeyCredentialManagerAvailability::kUnknown;
446*6777b538SAndroid Build Coastguard Worker
447*6777b538SAndroid Build Coastguard Worker // Read once to ensure consistency.
448*6777b538SAndroid Build Coastguard Worker const KeyCredentialManagerAvailability current_availability = availability;
449*6777b538SAndroid Build Coastguard Worker if (current_availability != KeyCredentialManagerAvailability::kUnknown) {
450*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(current_availability ==
451*6777b538SAndroid Build Coastguard Worker KeyCredentialManagerAvailability::kAvailable);
452*6777b538SAndroid Build Coastguard Worker return;
453*6777b538SAndroid Build Coastguard Worker }
454*6777b538SAndroid Build Coastguard Worker
455*6777b538SAndroid Build Coastguard Worker ComPtr<IKeyCredentialManagerStatics> factory;
456*6777b538SAndroid Build Coastguard Worker HRESULT hr = base::win::GetActivationFactory<
457*6777b538SAndroid Build Coastguard Worker IKeyCredentialManagerStatics,
458*6777b538SAndroid Build Coastguard Worker RuntimeClass_Windows_Security_Credentials_KeyCredentialManager>(&factory);
459*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) {
460*6777b538SAndroid Build Coastguard Worker // Don't cache API call failures, allowing the possibility of trying again
461*6777b538SAndroid Build Coastguard Worker // if this was a one-time failure.
462*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(false);
463*6777b538SAndroid Build Coastguard Worker return;
464*6777b538SAndroid Build Coastguard Worker }
465*6777b538SAndroid Build Coastguard Worker
466*6777b538SAndroid Build Coastguard Worker ComPtr<IAsyncOperation<bool>> is_supported_operation;
467*6777b538SAndroid Build Coastguard Worker hr = factory->IsSupportedAsync(&is_supported_operation);
468*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) {
469*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(false);
470*6777b538SAndroid Build Coastguard Worker return;
471*6777b538SAndroid Build Coastguard Worker }
472*6777b538SAndroid Build Coastguard Worker
473*6777b538SAndroid Build Coastguard Worker auto callback_splits = SplitOnceCallbackIntoThree(std::move(callback));
474*6777b538SAndroid Build Coastguard Worker hr = base::win::PostAsyncHandlers(
475*6777b538SAndroid Build Coastguard Worker is_supported_operation.Get(),
476*6777b538SAndroid Build Coastguard Worker base::BindOnce(
477*6777b538SAndroid Build Coastguard Worker [](base::OnceCallback<void(bool)> callback,
478*6777b538SAndroid Build Coastguard Worker std::atomic<KeyCredentialManagerAvailability>& availability,
479*6777b538SAndroid Build Coastguard Worker boolean result) {
480*6777b538SAndroid Build Coastguard Worker availability = result
481*6777b538SAndroid Build Coastguard Worker ? KeyCredentialManagerAvailability::kAvailable
482*6777b538SAndroid Build Coastguard Worker : KeyCredentialManagerAvailability::kUnavailable;
483*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(result);
484*6777b538SAndroid Build Coastguard Worker },
485*6777b538SAndroid Build Coastguard Worker std::move(std::get<0>(callback_splits)), std::ref(availability)),
486*6777b538SAndroid Build Coastguard Worker base::BindOnce([](base::OnceCallback<void(bool)> callback,
487*6777b538SAndroid Build Coastguard Worker HRESULT) { std::move(callback).Run(false); },
488*6777b538SAndroid Build Coastguard Worker std::move(std::get<1>(callback_splits))));
489*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) {
490*6777b538SAndroid Build Coastguard Worker std::move(std::get<2>(callback_splits)).Run(false);
491*6777b538SAndroid Build Coastguard Worker return;
492*6777b538SAndroid Build Coastguard Worker }
493*6777b538SAndroid Build Coastguard Worker }
494*6777b538SAndroid Build Coastguard Worker
495*6777b538SAndroid Build Coastguard Worker } // namespace
496*6777b538SAndroid Build Coastguard Worker
GetUserVerifyingKeyProviderWin()497*6777b538SAndroid Build Coastguard Worker std::unique_ptr<UserVerifyingKeyProvider> GetUserVerifyingKeyProviderWin() {
498*6777b538SAndroid Build Coastguard Worker return std::make_unique<UserVerifyingKeyProviderWin>();
499*6777b538SAndroid Build Coastguard Worker }
500*6777b538SAndroid Build Coastguard Worker
IsKeyCredentialManagerAvailable(base::OnceCallback<void (bool)> callback)501*6777b538SAndroid Build Coastguard Worker void IsKeyCredentialManagerAvailable(base::OnceCallback<void(bool)> callback) {
502*6777b538SAndroid Build Coastguard Worker scoped_refptr<base::SequencedTaskRunner> task_runner =
503*6777b538SAndroid Build Coastguard Worker base::ThreadPool::CreateSequencedTaskRunner(
504*6777b538SAndroid Build Coastguard Worker {base::MayBlock(), base::TaskPriority::USER_BLOCKING});
505*6777b538SAndroid Build Coastguard Worker task_runner->PostTask(
506*6777b538SAndroid Build Coastguard Worker FROM_HERE,
507*6777b538SAndroid Build Coastguard Worker base::BindOnce(&IsKeyCredentialManagerAvailableInternal,
508*6777b538SAndroid Build Coastguard Worker base::BindPostTaskToCurrentDefault(std::move(callback))));
509*6777b538SAndroid Build Coastguard Worker }
510*6777b538SAndroid Build Coastguard Worker
511*6777b538SAndroid Build Coastguard Worker } // namespace crypto
512