AuthenticatorAssertionResponse.cpp (5954B)
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 #include "mozilla/dom/AuthenticatorAssertionResponse.h" 8 9 #include "mozilla/Base64.h" 10 #include "mozilla/HoldDropJSObjects.h" 11 #include "mozilla/dom/WebAuthenticationBinding.h" 12 13 namespace mozilla::dom { 14 15 NS_IMPL_CYCLE_COLLECTION_CLASS(AuthenticatorAssertionResponse) 16 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(AuthenticatorAssertionResponse, 17 AuthenticatorResponse) 18 tmp->mAuthenticatorDataCachedObj = nullptr; 19 tmp->mSignatureCachedObj = nullptr; 20 tmp->mUserHandleCachedObj = nullptr; 21 NS_IMPL_CYCLE_COLLECTION_UNLINK_END 22 23 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(AuthenticatorAssertionResponse, 24 AuthenticatorResponse) 25 NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER 26 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mAuthenticatorDataCachedObj) 27 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mSignatureCachedObj) 28 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mUserHandleCachedObj) 29 NS_IMPL_CYCLE_COLLECTION_TRACE_END 30 31 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED( 32 AuthenticatorAssertionResponse, AuthenticatorResponse) 33 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 34 35 NS_IMPL_ADDREF_INHERITED(AuthenticatorAssertionResponse, AuthenticatorResponse) 36 NS_IMPL_RELEASE_INHERITED(AuthenticatorAssertionResponse, AuthenticatorResponse) 37 38 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AuthenticatorAssertionResponse) 39 NS_INTERFACE_MAP_END_INHERITING(AuthenticatorResponse) 40 41 AuthenticatorAssertionResponse::AuthenticatorAssertionResponse( 42 nsPIDOMWindowInner* aParent) 43 : AuthenticatorResponse(aParent), 44 mAuthenticatorDataCachedObj(nullptr), 45 mSignatureCachedObj(nullptr), 46 mUserHandleCachedObj(nullptr) { 47 mozilla::HoldJSObjects(this); 48 } 49 50 AuthenticatorAssertionResponse::~AuthenticatorAssertionResponse() { 51 mozilla::DropJSObjects(this); 52 } 53 54 JSObject* AuthenticatorAssertionResponse::WrapObject( 55 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { 56 return AuthenticatorAssertionResponse_Binding::Wrap(aCx, this, aGivenProto); 57 } 58 59 void AuthenticatorAssertionResponse::GetAuthenticatorData( 60 JSContext* aCx, JS::MutableHandle<JSObject*> aValue, ErrorResult& aRv) { 61 if (!mAuthenticatorDataCachedObj) { 62 mAuthenticatorDataCachedObj = 63 ArrayBuffer::Create(aCx, mAuthenticatorData, aRv); 64 if (aRv.Failed()) { 65 return; 66 } 67 } 68 aValue.set(mAuthenticatorDataCachedObj); 69 } 70 71 void AuthenticatorAssertionResponse::SetAuthenticatorData( 72 const nsTArray<uint8_t>& aBuffer) { 73 mAuthenticatorData.Assign(aBuffer); 74 } 75 76 void AuthenticatorAssertionResponse::GetSignature( 77 JSContext* aCx, JS::MutableHandle<JSObject*> aValue, ErrorResult& aRv) { 78 if (!mSignatureCachedObj) { 79 mSignatureCachedObj = ArrayBuffer::Create(aCx, mSignature, aRv); 80 if (aRv.Failed()) { 81 return; 82 } 83 } 84 aValue.set(mSignatureCachedObj); 85 } 86 87 void AuthenticatorAssertionResponse::SetSignature( 88 const nsTArray<uint8_t>& aBuffer) { 89 mSignature.Assign(aBuffer); 90 } 91 92 void AuthenticatorAssertionResponse::GetUserHandle( 93 JSContext* aCx, JS::MutableHandle<JSObject*> aValue, ErrorResult& aRv) { 94 // Per 95 // https://w3c.github.io/webauthn/#ref-for-dom-authenticatorassertionresponse-userhandle%E2%91%A0 96 // this should return null if the handle is unset. 97 if (mUserHandle.IsEmpty()) { 98 aValue.set(nullptr); 99 } else { 100 if (!mUserHandleCachedObj) { 101 mUserHandleCachedObj = ArrayBuffer::Create(aCx, mUserHandle, aRv); 102 if (aRv.Failed()) { 103 return; 104 } 105 } 106 aValue.set(mUserHandleCachedObj); 107 } 108 } 109 110 void AuthenticatorAssertionResponse::SetUserHandle( 111 const nsTArray<uint8_t>& aBuffer) { 112 mUserHandle.Assign(aBuffer); 113 } 114 115 void AuthenticatorAssertionResponse::ToJSON( 116 AuthenticatorAssertionResponseJSON& aJSON, ErrorResult& aError) { 117 nsAutoCString clientDataJSONBase64; 118 nsresult rv = Base64URLEncode( 119 mClientDataJSON.Length(), 120 reinterpret_cast<const uint8_t*>(mClientDataJSON.get()), 121 mozilla::Base64URLEncodePaddingPolicy::Omit, clientDataJSONBase64); 122 // This will only fail if the length is so long that it overflows 32-bits 123 // when calculating the encoded size. 124 if (NS_FAILED(rv)) { 125 aError.ThrowDataError("clientDataJSON too long"); 126 return; 127 } 128 aJSON.mClientDataJSON.Assign(NS_ConvertUTF8toUTF16(clientDataJSONBase64)); 129 130 nsAutoCString authenticatorDataBase64; 131 rv = Base64URLEncode( 132 mAuthenticatorData.Length(), mAuthenticatorData.Elements(), 133 mozilla::Base64URLEncodePaddingPolicy::Omit, authenticatorDataBase64); 134 if (NS_FAILED(rv)) { 135 aError.ThrowDataError("authenticatorData too long"); 136 return; 137 } 138 aJSON.mAuthenticatorData.Assign( 139 NS_ConvertUTF8toUTF16(authenticatorDataBase64)); 140 141 nsAutoCString signatureBase64; 142 rv = Base64URLEncode(mSignature.Length(), mSignature.Elements(), 143 mozilla::Base64URLEncodePaddingPolicy::Omit, 144 signatureBase64); 145 if (NS_FAILED(rv)) { 146 aError.ThrowDataError("signature too long"); 147 return; 148 } 149 aJSON.mSignature.Assign(NS_ConvertUTF8toUTF16(signatureBase64)); 150 151 if (!mUserHandle.IsEmpty()) { 152 nsAutoCString userHandleBase64; 153 rv = Base64URLEncode(mUserHandle.Length(), mUserHandle.Elements(), 154 mozilla::Base64URLEncodePaddingPolicy::Omit, 155 userHandleBase64); 156 if (NS_FAILED(rv)) { 157 aError.ThrowDataError("userHandle too long"); 158 return; 159 } 160 aJSON.mUserHandle.Construct(NS_ConvertUTF8toUTF16(userHandleBase64)); 161 } 162 163 // attestationObject is not currently supported on assertion responses 164 } 165 166 } // namespace mozilla::dom