From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- dom/webauthn/AuthenticatorAttestationResponse.cpp | 241 ++++++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 dom/webauthn/AuthenticatorAttestationResponse.cpp (limited to 'dom/webauthn/AuthenticatorAttestationResponse.cpp') 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 aGivenProto) { + return AuthenticatorAttestationResponse_Binding::Wrap(aCx, this, aGivenProto); +} + +void AuthenticatorAttestationResponse::GetAttestationObject( + JSContext* aCx, JS::MutableHandle aValue, ErrorResult& aRv) { + if (!mAttestationObjectCachedObj) { + mAttestationObjectCachedObj = + ArrayBuffer::Create(aCx, mAttestationObject, aRv); + if (aRv.Failed()) { + return; + } + } + aValue.set(mAttestationObjectCachedObj); +} + +void AuthenticatorAttestationResponse::SetAttestationObject( + const nsTArray& aBuffer) { + mAttestationObject.Assign(aBuffer); +} + +void AuthenticatorAttestationResponse::GetTransports( + nsTArray& aTransports) { + aTransports.Assign(mTransports); +} + +void AuthenticatorAttestationResponse::SetTransports( + const nsTArray& aTransports) { + mTransports.Assign(aTransports); +} + +nsresult AuthenticatorAttestationResponse::GetAuthenticatorDataBytes( + nsTArray& 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 aValue, ErrorResult& aRv) { + nsTArray authenticatorData; + nsresult rv = GetAuthenticatorDataBytes(authenticatorData); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return; + } + + JS::Heap buffer(ArrayBuffer::Create(aCx, authenticatorData, aRv)); + if (aRv.Failed()) { + return; + } + aValue.set(buffer); +} + +nsresult AuthenticatorAttestationResponse::GetPublicKeyBytes( + nsTArray& 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 aValue, ErrorResult& aRv) { + nsTArray 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 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(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 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 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 -- cgit v1.2.3