summaryrefslogtreecommitdiffstats
path: root/dom/webauthn/AuthenticatorAttestationResponse.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /dom/webauthn/AuthenticatorAttestationResponse.cpp
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/webauthn/AuthenticatorAttestationResponse.cpp')
-rw-r--r--dom/webauthn/AuthenticatorAttestationResponse.cpp241
1 files changed, 241 insertions, 0 deletions
diff --git a/dom/webauthn/AuthenticatorAttestationResponse.cpp b/dom/webauthn/AuthenticatorAttestationResponse.cpp
new file mode 100644
index 0000000000..7fe493dae3
--- /dev/null
+++ b/dom/webauthn/AuthenticatorAttestationResponse.cpp
@@ -0,0 +1,241 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "AuthrsBridge_ffi.h"
+#include "mozilla/Base64.h"
+#include "mozilla/HoldDropJSObjects.h"
+#include "mozilla/dom/AuthenticatorAttestationResponse.h"
+#include "mozilla/dom/WebAuthenticationBinding.h"
+
+namespace mozilla::dom {
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(AuthenticatorAttestationResponse)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(
+ AuthenticatorAttestationResponse, AuthenticatorResponse)
+ tmp->mAttestationObjectCachedObj = nullptr;
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(AuthenticatorAttestationResponse,
+ AuthenticatorResponse)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+ NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mAttestationObjectCachedObj)
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(
+ AuthenticatorAttestationResponse, AuthenticatorResponse)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_ADDREF_INHERITED(AuthenticatorAttestationResponse,
+ AuthenticatorResponse)
+NS_IMPL_RELEASE_INHERITED(AuthenticatorAttestationResponse,
+ AuthenticatorResponse)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AuthenticatorAttestationResponse)
+NS_INTERFACE_MAP_END_INHERITING(AuthenticatorResponse)
+
+AuthenticatorAttestationResponse::AuthenticatorAttestationResponse(
+ nsPIDOMWindowInner* aParent)
+ : AuthenticatorResponse(aParent), mAttestationObjectCachedObj(nullptr) {
+ mozilla::HoldJSObjects(this);
+}
+
+AuthenticatorAttestationResponse::~AuthenticatorAttestationResponse() {
+ mozilla::DropJSObjects(this);
+}
+
+JSObject* AuthenticatorAttestationResponse::WrapObject(
+ JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
+ return AuthenticatorAttestationResponse_Binding::Wrap(aCx, this, aGivenProto);
+}
+
+void AuthenticatorAttestationResponse::GetAttestationObject(
+ JSContext* aCx, JS::MutableHandle<JSObject*> aValue, ErrorResult& aRv) {
+ if (!mAttestationObjectCachedObj) {
+ mAttestationObjectCachedObj =
+ ArrayBuffer::Create(aCx, mAttestationObject, aRv);
+ if (aRv.Failed()) {
+ return;
+ }
+ }
+ aValue.set(mAttestationObjectCachedObj);
+}
+
+void AuthenticatorAttestationResponse::SetAttestationObject(
+ const nsTArray<uint8_t>& aBuffer) {
+ mAttestationObject.Assign(aBuffer);
+}
+
+void AuthenticatorAttestationResponse::GetTransports(
+ nsTArray<nsString>& aTransports) {
+ aTransports.Assign(mTransports);
+}
+
+void AuthenticatorAttestationResponse::SetTransports(
+ const nsTArray<nsString>& aTransports) {
+ mTransports.Assign(aTransports);
+}
+
+nsresult AuthenticatorAttestationResponse::GetAuthenticatorDataBytes(
+ nsTArray<uint8_t>& aAuthenticatorData) {
+ if (!mAttestationObjectParsed) {
+ nsresult rv = authrs_webauthn_att_obj_constructor(
+ mAttestationObject, /* anonymize */ false,
+ getter_AddRefs(mAttestationObjectParsed));
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ }
+ nsresult rv =
+ mAttestationObjectParsed->GetAuthenticatorData(aAuthenticatorData);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ return NS_OK;
+}
+
+void AuthenticatorAttestationResponse::GetAuthenticatorData(
+ JSContext* aCx, JS::MutableHandle<JSObject*> aValue, ErrorResult& aRv) {
+ nsTArray<uint8_t> authenticatorData;
+ nsresult rv = GetAuthenticatorDataBytes(authenticatorData);
+ if (NS_FAILED(rv)) {
+ aRv.Throw(rv);
+ return;
+ }
+
+ JS::Heap<JSObject*> buffer(ArrayBuffer::Create(aCx, authenticatorData, aRv));
+ if (aRv.Failed()) {
+ return;
+ }
+ aValue.set(buffer);
+}
+
+nsresult AuthenticatorAttestationResponse::GetPublicKeyBytes(
+ nsTArray<uint8_t>& aPublicKeyBytes) {
+ if (!mAttestationObjectParsed) {
+ nsresult rv = authrs_webauthn_att_obj_constructor(
+ mAttestationObject, /* anonymize */ false,
+ getter_AddRefs(mAttestationObjectParsed));
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ }
+ nsresult rv = mAttestationObjectParsed->GetPublicKey(aPublicKeyBytes);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ return NS_OK;
+}
+
+void AuthenticatorAttestationResponse::GetPublicKey(
+ JSContext* aCx, JS::MutableHandle<JSObject*> aValue, ErrorResult& aRv) {
+ nsTArray<uint8_t> publicKey;
+ nsresult rv = GetPublicKeyBytes(publicKey);
+ if (NS_FAILED(rv)) {
+ if (rv == NS_ERROR_NOT_AVAILABLE) {
+ aValue.set(nullptr);
+ } else {
+ aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+ }
+ return;
+ }
+
+ JS::Heap<JSObject*> buffer(ArrayBuffer::Create(aCx, publicKey, aRv));
+ if (aRv.Failed()) {
+ return;
+ }
+ aValue.set(buffer);
+}
+
+COSEAlgorithmIdentifier AuthenticatorAttestationResponse::GetPublicKeyAlgorithm(
+ ErrorResult& aRv) {
+ if (!mAttestationObjectParsed) {
+ nsresult rv = authrs_webauthn_att_obj_constructor(
+ mAttestationObject, false, getter_AddRefs(mAttestationObjectParsed));
+ if (NS_FAILED(rv)) {
+ aRv.Throw(rv);
+ return 0;
+ }
+ }
+
+ COSEAlgorithmIdentifier alg;
+ mAttestationObjectParsed->GetPublicKeyAlgorithm(&alg);
+ return alg;
+}
+
+void AuthenticatorAttestationResponse::ToJSON(
+ AuthenticatorAttestationResponseJSON& aJSON, ErrorResult& aError) {
+ nsAutoCString clientDataJSONBase64;
+ nsresult rv = Base64URLEncode(
+ mClientDataJSON.Length(),
+ reinterpret_cast<const uint8_t*>(mClientDataJSON.get()),
+ mozilla::Base64URLEncodePaddingPolicy::Omit, clientDataJSONBase64);
+ // This will only fail if the length is so long that it overflows 32-bits
+ // when calculating the encoded size.
+ if (NS_FAILED(rv)) {
+ aError.ThrowDataError("clientDataJSON too long");
+ return;
+ }
+ aJSON.mClientDataJSON.Assign(NS_ConvertUTF8toUTF16(clientDataJSONBase64));
+
+ nsTArray<uint8_t> authenticatorData;
+ rv = GetAuthenticatorDataBytes(authenticatorData);
+ if (NS_FAILED(rv)) {
+ aError.ThrowUnknownError("could not get authenticatorData");
+ return;
+ }
+ nsAutoCString authenticatorDataBase64;
+ rv = Base64URLEncode(authenticatorData.Length(), authenticatorData.Elements(),
+ mozilla::Base64URLEncodePaddingPolicy::Omit,
+ authenticatorDataBase64);
+ if (NS_FAILED(rv)) {
+ aError.ThrowDataError("authenticatorData too long");
+ return;
+ }
+ aJSON.mAuthenticatorData.Assign(
+ NS_ConvertUTF8toUTF16(authenticatorDataBase64));
+
+ if (!aJSON.mTransports.Assign(mTransports, mozilla::fallible)) {
+ aError.Throw(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+
+ nsTArray<uint8_t> publicKeyBytes;
+ rv = GetPublicKeyBytes(publicKeyBytes);
+ if (NS_SUCCEEDED(rv)) {
+ nsAutoCString publicKeyBytesBase64;
+ rv = Base64URLEncode(publicKeyBytes.Length(), publicKeyBytes.Elements(),
+ mozilla::Base64URLEncodePaddingPolicy::Omit,
+ publicKeyBytesBase64);
+ if (NS_FAILED(rv)) {
+ aError.ThrowDataError("publicKey too long");
+ return;
+ }
+ aJSON.mPublicKey.Construct(NS_ConvertUTF8toUTF16(publicKeyBytesBase64));
+ } else if (rv != NS_ERROR_NOT_AVAILABLE) {
+ aError.ThrowUnknownError("could not get publicKey");
+ return;
+ }
+
+ COSEAlgorithmIdentifier publicKeyAlgorithm = GetPublicKeyAlgorithm(aError);
+ if (aError.Failed()) {
+ aError.ThrowUnknownError("could not get publicKeyAlgorithm");
+ return;
+ }
+ aJSON.mPublicKeyAlgorithm = publicKeyAlgorithm;
+
+ nsAutoCString attestationObjectBase64;
+ rv = Base64URLEncode(
+ mAttestationObject.Length(), mAttestationObject.Elements(),
+ mozilla::Base64URLEncodePaddingPolicy::Omit, attestationObjectBase64);
+ if (NS_FAILED(rv)) {
+ aError.ThrowDataError("attestationObject too long");
+ return;
+ }
+ aJSON.mAttestationObject.Assign(
+ NS_ConvertUTF8toUTF16(attestationObjectBase64));
+}
+
+} // namespace mozilla::dom