Skip to content

Commit

Permalink
Bug 1816519 - implement getAuthenticatorData for AuthenticatorAttesta…
Browse files Browse the repository at this point in the history
…tionResponse. r=keeler,webidl,emilio,smaug

Depends on D186806

Differential Revision: https://phabricator.services.mozilla.com/D186374
  • Loading branch information
jschanck committed Aug 31, 2023
1 parent a0a8349 commit 7438e57
Show file tree
Hide file tree
Showing 25 changed files with 167 additions and 802 deletions.
1 change: 0 additions & 1 deletion .clang-format-ignore
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ dom/media/webspeech/recognition/energy_endpointer.cc
dom/media/webspeech/recognition/energy_endpointer.h
dom/media/webspeech/recognition/energy_endpointer_params.cc
dom/media/webspeech/recognition/energy_endpointer_params.h
dom/webauthn/cbor-cpp/.*
dom/webauthn/winwebauthn/webauthn.h
editor/libeditor/tests/browserscope/lib/richtext/.*
editor/libeditor/tests/browserscope/lib/richtext2/.*
Expand Down
2 changes: 0 additions & 2 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -1299,8 +1299,6 @@ dom/tests/mochitest/ajax/
dom/tests/mochitest/dom-level1-core/
dom/tests/mochitest/dom-level2-core/
dom/tests/mochitest/dom-level2-html/
dom/u2f/tests/pkijs/
dom/webauthn/cbor-cpp/
dom/webauthn/tests/pkijs/
dom/webgpu/tests/cts/checkout/
editor/libeditor/tests/browserscope/lib/richtext/
Expand Down
38 changes: 35 additions & 3 deletions dom/webauthn/AuthenticatorAttestationResponse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* 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/dom/WebAuthenticationBinding.h"
#include "mozilla/dom/AuthenticatorAttestationResponse.h"

Expand Down Expand Up @@ -53,7 +54,8 @@ JSObject* AuthenticatorAttestationResponse::WrapObject(
void AuthenticatorAttestationResponse::GetAttestationObject(
JSContext* aCx, JS::MutableHandle<JSObject*> aValue, ErrorResult& aRv) {
if (!mAttestationObjectCachedObj) {
mAttestationObjectCachedObj = mAttestationObject.ToArrayBuffer(aCx);
mAttestationObjectCachedObj = ArrayBuffer::Create(
aCx, mAttestationObject.Length(), mAttestationObject.Elements());
if (!mAttestationObjectCachedObj) {
aRv.NoteJSContextException(aCx);
return;
Expand All @@ -63,11 +65,41 @@ void AuthenticatorAttestationResponse::GetAttestationObject(
}

nsresult AuthenticatorAttestationResponse::SetAttestationObject(
CryptoBuffer& aBuffer) {
if (NS_WARN_IF(!mAttestationObject.Assign(aBuffer))) {
const nsTArray<uint8_t>& aBuffer) {
if (!mAttestationObject.Assign(aBuffer, mozilla::fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}

return NS_OK;
}

void AuthenticatorAttestationResponse::GetAuthenticatorData(
JSContext* aCx, JS::MutableHandle<JSObject*> aValue, ErrorResult& aRv) {
if (!mAttestationObjectParsed) {
nsresult rv = authrs_webauthn_att_obj_constructor(
mAttestationObject, /* anonymize */ false,
getter_AddRefs(mAttestationObjectParsed));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return;
}
}

nsTArray<uint8_t> authenticatorData;
nsresult rv =
mAttestationObjectParsed->GetAuthenticatorData(authenticatorData);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return;
}

JS::Heap<JSObject*> buffer(ArrayBuffer::Create(
aCx, authenticatorData.Length(), authenticatorData.Elements()));
if (!buffer) {
aRv.NoteJSContextException(aCx);
return;
}
aValue.set(buffer);
}

} // namespace mozilla::dom
10 changes: 7 additions & 3 deletions dom/webauthn/AuthenticatorAttestationResponse.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
#include "mozilla/Attributes.h"
#include "mozilla/dom/AuthenticatorResponse.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/CryptoBuffer.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIWebAuthnController.h"
#include "nsWrapperCache.h"

namespace mozilla::dom {
Expand All @@ -35,10 +35,14 @@ class AuthenticatorAttestationResponse final : public AuthenticatorResponse {
void GetAttestationObject(JSContext* aCx, JS::MutableHandle<JSObject*> aValue,
ErrorResult& aRv);

nsresult SetAttestationObject(CryptoBuffer& aBuffer);
nsresult SetAttestationObject(const nsTArray<uint8_t>& aBuffer);

void GetAuthenticatorData(JSContext* aCx, JS::MutableHandle<JSObject*> aValue,
ErrorResult& aRv);

private:
CryptoBuffer mAttestationObject;
nsTArray<uint8_t> mAttestationObject;
nsCOMPtr<nsIWebAuthnAttObj> mAttestationObjectParsed;
JS::Heap<JSObject*> mAttestationObjectCachedObj;
};

Expand Down
25 changes: 25 additions & 0 deletions dom/webauthn/AuthrsBridge_ffi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* 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/. */

#ifndef mozilla_dom_AuthrsBridge_ffi_h
#define mozilla_dom_AuthrsBridge_ffi_h

// TODO(Bug 1850592): Autogenerate this with cbindgen.

#include "nsTArray.h"

class nsIWebAuthnAttObj;
class nsIWebAuthnTransport;

extern "C" {

nsresult authrs_transport_constructor(nsIWebAuthnTransport** result);

nsresult authrs_webauthn_att_obj_constructor(
const nsTArray<uint8_t>& attestation, bool anonymize,
nsIWebAuthnAttObj** result);

} // extern "C"

#endif // mozilla_dom_AuthrsBridge_ffi_h
10 changes: 1 addition & 9 deletions dom/webauthn/AuthrsTransport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "AuthrsTransport.h"
#include "AuthrsBridge_ffi.h"
#include "nsIWebAuthnController.h"
#include "nsCOMPtr.h"

namespace {
extern "C" {

// Implemented in Rust
nsresult authrs_transport_constructor(nsIWebAuthnTransport** result);

} // extern "C"
} // namespace

namespace mozilla::dom {

already_AddRefed<nsIWebAuthnTransport> NewAuthrsTransport() {
Expand Down
45 changes: 0 additions & 45 deletions dom/webauthn/WebAuthnCBORUtil.cpp

This file was deleted.

22 changes: 0 additions & 22 deletions dom/webauthn/WebAuthnCBORUtil.h

This file was deleted.

24 changes: 0 additions & 24 deletions dom/webauthn/WebAuthnUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "mozilla/dom/WebAuthnUtil.h"
#include "mozilla/dom/WebAuthnCBORUtil.h"
#include "nsComponentManagerUtils.h"
#include "nsICryptoHash.h"
#include "nsIEffectiveTLDService.h"
Expand Down Expand Up @@ -108,29 +107,6 @@ bool EvaluateAppID(nsPIDOMWindowInner* aParent, const nsString& aOrigin,
return false;
}

nsresult ReadToCryptoBuffer(pkix::Reader& aSrc, /* out */ CryptoBuffer& aDest,
uint32_t aLen) {
if (aSrc.EnsureLength(aLen) != pkix::Success) {
return NS_ERROR_DOM_UNKNOWN_ERR;
}

if (!aDest.SetCapacity(aLen, mozilla::fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}

for (uint32_t offset = 0; offset < aLen; ++offset) {
uint8_t b;
if (aSrc.Read(b) != pkix::Success) {
return NS_ERROR_DOM_UNKNOWN_ERR;
}
if (!aDest.AppendElement(b, mozilla::fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
}

return NS_OK;
}

static nsresult HashCString(nsICryptoHash* aHashService, const nsACString& aIn,
/* out */ CryptoBuffer& aOut) {
MOZ_ASSERT(aHashService);
Expand Down
40 changes: 25 additions & 15 deletions dom/webauthn/WinWebAuthnManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@

#include "mozilla/Assertions.h"
#include "mozilla/dom/PWebAuthnTransactionParent.h"
#include "mozilla/dom/WebAuthnCBORUtil.h"
#include "mozilla/MozPromise.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/dom/CryptoBuffer.h"
#include "mozilla/Unused.h"
#include "nsIWebAuthnController.h"
#include "nsTextFormatter.h"
#include "nsWindowsHelpers.h"
#include "AuthrsBridge_ffi.h"
#include "WebAuthnEnumStrings.h"
#include "WebAuthnTransportIdentifiers.h"
#include "winwebauthn/webauthn.h"
Expand Down Expand Up @@ -426,21 +427,30 @@ void WinWebAuthnManager::Register(
pWebAuthNCredentialAttestation->cbAuthenticatorData);

nsTArray<uint8_t> attObject;
attObject.AppendElements(
pWebAuthNCredentialAttestation->pbAttestationObject,
pWebAuthNCredentialAttestation->cbAttestationObject);

if (winAttestation == WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_NONE) {
// Zero AAGuid
const uint8_t zeroGuid[16] = {0};
authenticatorData.ReplaceElementsAt(32 + 1 + 4 /*AAGuid offset*/, 16,
zeroGuid, 16);

CryptoBuffer authData;
authData.Assign(authenticatorData);
CryptoBuffer noneAttObj;
CBOREncodeNoneAttestationObj(authData, noneAttObj);
attObject.AppendElements(noneAttObj);
} else {
attObject.AppendElements(
pWebAuthNCredentialAttestation->pbAttestationObject,
pWebAuthNCredentialAttestation->cbAttestationObject);
// The anonymize flag in the nsIWebAuthnAttObj constructor causes the
// attestation statement to be removed during deserialization. It also
// causes the AAGUID to be zeroed out. If we can't deserialize the
// existing attestation, then we can't ensure that it is anonymized, so we
// act as though the user denied consent and we return NotAllowed.
nsCOMPtr<nsIWebAuthnAttObj> anonymizedAttObj;
nsresult rv = authrs_webauthn_att_obj_constructor(
attObject,
/* anonymize */ true, getter_AddRefs(anonymizedAttObj));
if (NS_FAILED(rv)) {
MaybeAbortRegister(aTransactionId, NS_ERROR_DOM_NOT_ALLOWED_ERR);
return;
}
attObject.Clear();
rv = anonymizedAttObj->GetAttestationObject(attObject);
if (NS_FAILED(rv)) {
MaybeAbortRegister(aTransactionId, NS_ERROR_DOM_NOT_ALLOWED_ERR);
return;
}
}

nsTArray<WebAuthnExtensionResult> extensions;
Expand Down
Loading

0 comments on commit 7438e57

Please sign in to comment.