Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
* License, v. 2.0. If a copy of the MPL was not distributed with this
5
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef mozilla_dom_U2FHIDTokenManager_h
8
#define mozilla_dom_U2FHIDTokenManager_h
9
10
#include "mozilla/dom/U2FTokenTransport.h"
11
#include "authenticator/src/u2fhid-capi.h"
12
13
/*
14
* U2FHIDTokenManager is a Rust implementation of a secure token manager
15
* for the U2F and WebAuthn APIs, talking to HIDs.
16
*/
17
18
namespace mozilla {
19
namespace dom {
20
21
class U2FAppIds {
22
public:
23
explicit U2FAppIds(const nsTArray<nsTArray<uint8_t>>& aApplications) {
24
mAppIds = rust_u2f_app_ids_new();
25
26
for (auto& app_id : aApplications) {
27
rust_u2f_app_ids_add(mAppIds, app_id.Elements(), app_id.Length());
28
}
29
}
30
31
rust_u2f_app_ids* Get() { return mAppIds; }
32
33
~U2FAppIds() { rust_u2f_app_ids_free(mAppIds); }
34
35
private:
36
rust_u2f_app_ids* mAppIds;
37
};
38
39
class U2FKeyHandles {
40
public:
41
explicit U2FKeyHandles(
42
const nsTArray<WebAuthnScopedCredential>& aCredentials) {
43
mKeyHandles = rust_u2f_khs_new();
44
45
for (auto& cred : aCredentials) {
46
rust_u2f_khs_add(mKeyHandles, cred.id().Elements(), cred.id().Length(),
47
cred.transports());
48
}
49
}
50
51
rust_u2f_key_handles* Get() { return mKeyHandles; }
52
53
~U2FKeyHandles() { rust_u2f_khs_free(mKeyHandles); }
54
55
private:
56
rust_u2f_key_handles* mKeyHandles;
57
};
58
59
class U2FResult {
60
public:
61
explicit U2FResult(uint64_t aTransactionId, rust_u2f_result* aResult)
62
: mTransactionId(aTransactionId), mResult(aResult) {
63
MOZ_ASSERT(mResult);
64
}
65
66
~U2FResult() { rust_u2f_res_free(mResult); }
67
68
uint64_t GetTransactionId() { return mTransactionId; }
69
70
bool IsError() { return NS_FAILED(GetError()); }
71
72
nsresult GetError() {
73
switch (rust_u2f_result_error(mResult)) {
74
case U2F_ERROR_UKNOWN:
75
case U2F_ERROR_CONSTRAINT:
76
return NS_ERROR_DOM_UNKNOWN_ERR;
77
case U2F_ERROR_NOT_SUPPORTED:
78
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
79
case U2F_ERROR_INVALID_STATE:
80
return NS_ERROR_DOM_INVALID_STATE_ERR;
81
case U2F_ERROR_NOT_ALLOWED:
82
return NS_ERROR_DOM_NOT_ALLOWED_ERR;
83
default:
84
return NS_OK;
85
}
86
}
87
88
bool CopyRegistration(nsTArray<uint8_t>& aBuffer) {
89
return CopyBuffer(U2F_RESBUF_ID_REGISTRATION, aBuffer);
90
}
91
92
bool CopyKeyHandle(nsTArray<uint8_t>& aBuffer) {
93
return CopyBuffer(U2F_RESBUF_ID_KEYHANDLE, aBuffer);
94
}
95
96
bool CopySignature(nsTArray<uint8_t>& aBuffer) {
97
return CopyBuffer(U2F_RESBUF_ID_SIGNATURE, aBuffer);
98
}
99
100
bool CopyAppId(nsTArray<uint8_t>& aBuffer) {
101
return CopyBuffer(U2F_RESBUF_ID_APPID, aBuffer);
102
}
103
104
private:
105
bool CopyBuffer(uint8_t aResBufID, nsTArray<uint8_t>& aBuffer) {
106
size_t len;
107
if (!rust_u2f_resbuf_length(mResult, aResBufID, &len)) {
108
return false;
109
}
110
111
if (!aBuffer.SetLength(len, fallible)) {
112
return false;
113
}
114
115
return rust_u2f_resbuf_copy(mResult, aResBufID, aBuffer.Elements());
116
}
117
118
uint64_t mTransactionId;
119
rust_u2f_result* mResult;
120
};
121
122
class U2FHIDTokenManager final : public U2FTokenTransport {
123
public:
124
explicit U2FHIDTokenManager();
125
126
RefPtr<U2FRegisterPromise> Register(const WebAuthnMakeCredentialInfo& aInfo,
127
bool aForceNoneAttestation) override;
128
129
RefPtr<U2FSignPromise> Sign(const WebAuthnGetAssertionInfo& aInfo) override;
130
131
void Cancel() override;
132
void Drop() override;
133
134
void HandleRegisterResult(UniquePtr<U2FResult>&& aResult);
135
void HandleSignResult(UniquePtr<U2FResult>&& aResult);
136
137
private:
138
~U2FHIDTokenManager() {}
139
140
void ClearPromises() {
141
mRegisterPromise.RejectIfExists(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
142
mSignPromise.RejectIfExists(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
143
}
144
145
class Transaction {
146
public:
147
Transaction(uint64_t aId, const nsTArray<uint8_t>& aRpIdHash,
148
const nsCString& aClientDataJSON,
149
bool aForceNoneAttestation = false)
150
: mId(aId),
151
mRpIdHash(aRpIdHash),
152
mClientDataJSON(aClientDataJSON),
153
mForceNoneAttestation(aForceNoneAttestation) {}
154
155
// The transaction ID.
156
uint64_t mId;
157
158
// The RP ID hash.
159
nsTArray<uint8_t> mRpIdHash;
160
161
// The clientData JSON.
162
nsCString mClientDataJSON;
163
164
// Whether we'll force "none" attestation.
165
bool mForceNoneAttestation;
166
};
167
168
rust_u2f_manager* mU2FManager;
169
Maybe<Transaction> mTransaction;
170
MozPromiseHolder<U2FRegisterPromise> mRegisterPromise;
171
MozPromiseHolder<U2FSignPromise> mSignPromise;
172
};
173
174
} // namespace dom
175
} // namespace mozilla
176
177
#endif // mozilla_dom_U2FHIDTokenManager_h