Bug 1861467 - [wpt-sync] Update web-platform-tests to eedf737ce39c512d0ca3471f988972e...
[gecko.git] / dom / webauthn / AuthenticatorAttestationResponse.cpp
blob43f928f6566ec5df6814423e42bd5186297459d9
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/. */
7 #include "AuthrsBridge_ffi.h"
8 #include "mozilla/Base64.h"
9 #include "mozilla/HoldDropJSObjects.h"
10 #include "mozilla/dom/AuthenticatorAttestationResponse.h"
11 #include "mozilla/dom/WebAuthenticationBinding.h"
13 namespace mozilla::dom {
15 NS_IMPL_CYCLE_COLLECTION_CLASS(AuthenticatorAttestationResponse)
16 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(
17 AuthenticatorAttestationResponse, AuthenticatorResponse)
18 tmp->mAttestationObjectCachedObj = nullptr;
19 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
21 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(AuthenticatorAttestationResponse,
22 AuthenticatorResponse)
23 NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
24 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mAttestationObjectCachedObj)
25 NS_IMPL_CYCLE_COLLECTION_TRACE_END
27 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(
28 AuthenticatorAttestationResponse, AuthenticatorResponse)
29 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
31 NS_IMPL_ADDREF_INHERITED(AuthenticatorAttestationResponse,
32 AuthenticatorResponse)
33 NS_IMPL_RELEASE_INHERITED(AuthenticatorAttestationResponse,
34 AuthenticatorResponse)
36 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AuthenticatorAttestationResponse)
37 NS_INTERFACE_MAP_END_INHERITING(AuthenticatorResponse)
39 AuthenticatorAttestationResponse::AuthenticatorAttestationResponse(
40 nsPIDOMWindowInner* aParent)
41 : AuthenticatorResponse(aParent), mAttestationObjectCachedObj(nullptr) {
42 mozilla::HoldJSObjects(this);
45 AuthenticatorAttestationResponse::~AuthenticatorAttestationResponse() {
46 mozilla::DropJSObjects(this);
49 JSObject* AuthenticatorAttestationResponse::WrapObject(
50 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
51 return AuthenticatorAttestationResponse_Binding::Wrap(aCx, this, aGivenProto);
54 void AuthenticatorAttestationResponse::GetAttestationObject(
55 JSContext* aCx, JS::MutableHandle<JSObject*> aValue, ErrorResult& aRv) {
56 if (!mAttestationObjectCachedObj) {
57 mAttestationObjectCachedObj = ArrayBuffer::Create(
58 aCx, mAttestationObject.Length(), mAttestationObject.Elements());
59 if (!mAttestationObjectCachedObj) {
60 aRv.NoteJSContextException(aCx);
61 return;
64 aValue.set(mAttestationObjectCachedObj);
67 void AuthenticatorAttestationResponse::SetAttestationObject(
68 const nsTArray<uint8_t>& aBuffer) {
69 mAttestationObject.Assign(aBuffer);
72 void AuthenticatorAttestationResponse::GetTransports(
73 nsTArray<nsString>& aTransports) {
74 aTransports.Assign(mTransports);
77 void AuthenticatorAttestationResponse::SetTransports(
78 const nsTArray<nsString>& aTransports) {
79 mTransports.Assign(aTransports);
82 nsresult AuthenticatorAttestationResponse::GetAuthenticatorDataBytes(
83 nsTArray<uint8_t>& aAuthenticatorData) {
84 if (!mAttestationObjectParsed) {
85 nsresult rv = authrs_webauthn_att_obj_constructor(
86 mAttestationObject, /* anonymize */ false,
87 getter_AddRefs(mAttestationObjectParsed));
88 if (NS_FAILED(rv)) {
89 return rv;
92 nsresult rv =
93 mAttestationObjectParsed->GetAuthenticatorData(aAuthenticatorData);
94 if (NS_FAILED(rv)) {
95 return rv;
97 return NS_OK;
100 void AuthenticatorAttestationResponse::GetAuthenticatorData(
101 JSContext* aCx, JS::MutableHandle<JSObject*> aValue, ErrorResult& aRv) {
102 nsTArray<uint8_t> authenticatorData;
103 nsresult rv = GetAuthenticatorDataBytes(authenticatorData);
104 if (NS_FAILED(rv)) {
105 aRv.Throw(rv);
106 return;
109 JS::Heap<JSObject*> buffer(ArrayBuffer::Create(
110 aCx, authenticatorData.Length(), authenticatorData.Elements()));
111 if (!buffer) {
112 aRv.NoteJSContextException(aCx);
113 return;
115 aValue.set(buffer);
118 nsresult AuthenticatorAttestationResponse::GetPublicKeyBytes(
119 nsTArray<uint8_t>& aPublicKeyBytes) {
120 if (!mAttestationObjectParsed) {
121 nsresult rv = authrs_webauthn_att_obj_constructor(
122 mAttestationObject, /* anonymize */ false,
123 getter_AddRefs(mAttestationObjectParsed));
124 if (NS_FAILED(rv)) {
125 return rv;
128 nsresult rv = mAttestationObjectParsed->GetPublicKey(aPublicKeyBytes);
129 if (NS_FAILED(rv)) {
130 return rv;
132 return NS_OK;
135 void AuthenticatorAttestationResponse::GetPublicKey(
136 JSContext* aCx, JS::MutableHandle<JSObject*> aValue, ErrorResult& aRv) {
137 nsTArray<uint8_t> publicKey;
138 nsresult rv = GetPublicKeyBytes(publicKey);
139 if (NS_FAILED(rv)) {
140 if (rv == NS_ERROR_NOT_AVAILABLE) {
141 aValue.set(nullptr);
142 } else {
143 aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
145 return;
148 JS::Heap<JSObject*> buffer(
149 ArrayBuffer::Create(aCx, publicKey.Length(), publicKey.Elements()));
150 if (!buffer) {
151 aRv.NoteJSContextException(aCx);
152 return;
154 aValue.set(buffer);
157 COSEAlgorithmIdentifier AuthenticatorAttestationResponse::GetPublicKeyAlgorithm(
158 ErrorResult& aRv) {
159 if (!mAttestationObjectParsed) {
160 nsresult rv = authrs_webauthn_att_obj_constructor(
161 mAttestationObject, false, getter_AddRefs(mAttestationObjectParsed));
162 if (NS_FAILED(rv)) {
163 aRv.Throw(rv);
164 return 0;
168 COSEAlgorithmIdentifier alg;
169 mAttestationObjectParsed->GetPublicKeyAlgorithm(&alg);
170 return alg;
173 void AuthenticatorAttestationResponse::ToJSON(
174 AuthenticatorAttestationResponseJSON& aJSON, ErrorResult& aError) {
175 nsAutoCString clientDataJSONBase64;
176 nsresult rv = Base64URLEncode(
177 mClientDataJSON.Length(),
178 reinterpret_cast<const uint8_t*>(mClientDataJSON.get()),
179 mozilla::Base64URLEncodePaddingPolicy::Omit, clientDataJSONBase64);
180 // This will only fail if the length is so long that it overflows 32-bits
181 // when calculating the encoded size.
182 if (NS_FAILED(rv)) {
183 aError.ThrowDataError("clientDataJSON too long");
184 return;
186 aJSON.mClientDataJSON.Assign(NS_ConvertUTF8toUTF16(clientDataJSONBase64));
188 nsTArray<uint8_t> authenticatorData;
189 rv = GetAuthenticatorDataBytes(authenticatorData);
190 if (NS_FAILED(rv)) {
191 aError.ThrowUnknownError("could not get authenticatorData");
192 return;
194 nsAutoCString authenticatorDataBase64;
195 rv = Base64URLEncode(authenticatorData.Length(), authenticatorData.Elements(),
196 mozilla::Base64URLEncodePaddingPolicy::Omit,
197 authenticatorDataBase64);
198 if (NS_FAILED(rv)) {
199 aError.ThrowDataError("authenticatorData too long");
200 return;
202 aJSON.mAuthenticatorData.Assign(
203 NS_ConvertUTF8toUTF16(authenticatorDataBase64));
205 if (!aJSON.mTransports.Assign(mTransports, mozilla::fallible)) {
206 aError.Throw(NS_ERROR_OUT_OF_MEMORY);
207 return;
210 nsTArray<uint8_t> publicKeyBytes;
211 rv = GetPublicKeyBytes(publicKeyBytes);
212 if (NS_SUCCEEDED(rv)) {
213 nsAutoCString publicKeyBytesBase64;
214 rv = Base64URLEncode(publicKeyBytes.Length(), publicKeyBytes.Elements(),
215 mozilla::Base64URLEncodePaddingPolicy::Omit,
216 publicKeyBytesBase64);
217 if (NS_FAILED(rv)) {
218 aError.ThrowDataError("publicKey too long");
219 return;
221 aJSON.mPublicKey.Construct(NS_ConvertUTF8toUTF16(publicKeyBytesBase64));
222 } else if (rv != NS_ERROR_NOT_AVAILABLE) {
223 aError.ThrowUnknownError("could not get publicKey");
224 return;
227 COSEAlgorithmIdentifier publicKeyAlgorithm = GetPublicKeyAlgorithm(aError);
228 if (aError.Failed()) {
229 aError.ThrowUnknownError("could not get publicKeyAlgorithm");
230 return;
232 aJSON.mPublicKeyAlgorithm = publicKeyAlgorithm;
234 nsAutoCString attestationObjectBase64;
235 rv = Base64URLEncode(
236 mAttestationObject.Length(), mAttestationObject.Elements(),
237 mozilla::Base64URLEncodePaddingPolicy::Omit, attestationObjectBase64);
238 if (NS_FAILED(rv)) {
239 aError.ThrowDataError("attestationObject too long");
240 return;
242 aJSON.mAttestationObject.Assign(
243 NS_ConvertUTF8toUTF16(attestationObjectBase64));
246 } // namespace mozilla::dom