tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

WebAuthnResult.h (13338B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #ifndef mozilla_dom_WebAuthnResult_h_
      6 #define mozilla_dom_WebAuthnResult_h_
      7 
      8 #include "mozilla/Maybe.h"
      9 #include "nsIWebAuthnResult.h"
     10 #include "nsString.h"
     11 #include "nsTArray.h"
     12 
     13 #ifdef MOZ_WIDGET_ANDROID
     14 #  include "JavaBuiltins.h"
     15 #  include "mozilla/java/WebAuthnUtilsNatives.h"
     16 #endif
     17 
     18 #ifdef XP_WIN
     19 #  include <windows.h>
     20 
     21 #  include "mozilla/dom/PWebAuthnTransactionParent.h"
     22 #  include "winwebauthn/webauthn.h"
     23 #endif
     24 
     25 namespace mozilla::dom {
     26 
     27 class WebAuthnRegisterResult final : public nsIWebAuthnRegisterResult {
     28 public:
     29  NS_DECL_THREADSAFE_ISUPPORTS
     30  NS_DECL_NSIWEBAUTHNREGISTERRESULT
     31 
     32  WebAuthnRegisterResult(const nsTArray<uint8_t>& aAttestationObject,
     33                         const Maybe<nsCString>& aClientDataJSON,
     34                         const nsTArray<uint8_t>& aCredentialId,
     35                         const nsTArray<nsString>& aTransports,
     36                         const Maybe<nsString>& aAuthenticatorAttachment,
     37                         const Maybe<bool>& aLargeBlobSupported,
     38                         const Maybe<bool>& aPrfSupported,
     39                         const Maybe<nsTArray<uint8_t>>& aPrfFirst,
     40                         const Maybe<nsTArray<uint8_t>>& aPrfSecond)
     41      : mAttestationConsentPromptShown(false),
     42        mClientDataJSON(aClientDataJSON),
     43        mCredPropsRk(Nothing()),
     44        mAuthenticatorAttachment(aAuthenticatorAttachment),
     45        mLargeBlobSupported(aLargeBlobSupported),
     46        mPrfSupported(aPrfSupported) {
     47    mAttestationObject.AppendElements(aAttestationObject);
     48    mCredentialId.AppendElements(aCredentialId);
     49    mTransports.AppendElements(aTransports);
     50    if (aPrfFirst.isSome()) {
     51      mPrfFirst.emplace(aPrfFirst->Length());
     52      mPrfFirst->Assign(aPrfFirst.ref());
     53    }
     54    if (aPrfSecond.isSome()) {
     55      mPrfSecond.emplace(aPrfSecond->Length());
     56      mPrfSecond->Assign(aPrfSecond.ref());
     57    }
     58  }
     59 
     60 #ifdef MOZ_WIDGET_ANDROID
     61  explicit WebAuthnRegisterResult(
     62      const java::WebAuthnUtils::MakeCredentialResponse::LocalRef& aResponse) {
     63    mAttestationObject.AppendElements(
     64        reinterpret_cast<uint8_t*>(
     65            aResponse->AttestationObject()->GetElements().Elements()),
     66        aResponse->AttestationObject()->Length());
     67    mAttestationConsentPromptShown = false;
     68    if (aResponse->ClientDataJson()) {
     69      mClientDataJSON = Some(nsAutoCString(
     70          reinterpret_cast<const char*>(
     71              aResponse->ClientDataJson()->GetElements().Elements()),
     72          aResponse->ClientDataJson()->Length()));
     73    }
     74    mCredentialId.AppendElements(
     75        reinterpret_cast<uint8_t*>(
     76            aResponse->KeyHandle()->GetElements().Elements()),
     77        aResponse->KeyHandle()->Length());
     78    auto transports = aResponse->Transports();
     79    for (size_t i = 0; i < transports->Length(); i++) {
     80      mTransports.AppendElement(
     81          jni::String::LocalRef(transports->GetElement(i))->ToString());
     82    }
     83    mAuthenticatorAttachment =
     84        Some(aResponse->AuthenticatorAttachment()->ToString());
     85    if (aResponse->CredProps()) {
     86      mCredPropsRk = Some(java::sdk::Boolean::Ref::From(aResponse->CredProps())
     87                              ->BooleanValue());
     88    }
     89  }
     90 #endif
     91 
     92 #ifdef XP_WIN
     93  WebAuthnRegisterResult(nsCString& aClientDataJSON,
     94                         PCWEBAUTHN_CREDENTIAL_ATTESTATION aResponse)
     95      : mClientDataJSON(Some(aClientDataJSON)) {
     96    mCredentialId.AppendElements(aResponse->pbCredentialId,
     97                                 aResponse->cbCredentialId);
     98 
     99    mAttestationObject.AppendElements(aResponse->pbAttestationObject,
    100                                      aResponse->cbAttestationObject);
    101    mAttestationConsentPromptShown = true;
    102 
    103    nsTArray<WebAuthnExtensionResult> extensions;
    104    if (aResponse->dwVersion >= WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_2) {
    105      PCWEBAUTHN_EXTENSIONS pExtensionList = &aResponse->Extensions;
    106      if (pExtensionList->cExtensions != 0 &&
    107          pExtensionList->pExtensions != NULL) {
    108        for (DWORD dwIndex = 0; dwIndex < pExtensionList->cExtensions;
    109             dwIndex++) {
    110          PWEBAUTHN_EXTENSION pExtension =
    111              &pExtensionList->pExtensions[dwIndex];
    112          if (pExtension->pwszExtensionIdentifier &&
    113              (0 == _wcsicmp(pExtension->pwszExtensionIdentifier,
    114                             WEBAUTHN_EXTENSIONS_IDENTIFIER_HMAC_SECRET)) &&
    115              pExtension->cbExtension == sizeof(BOOL)) {
    116            BOOL* pCredentialCreatedWithHmacSecret =
    117                (BOOL*)pExtension->pvExtension;
    118            if (*pCredentialCreatedWithHmacSecret) {
    119              mHmacCreateSecret = Some(true);
    120              mPrfSupported = Some(true);
    121            }
    122          }
    123        }
    124      }
    125    }
    126 
    127    if (aResponse->dwVersion >= WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_7) {
    128      if (aResponse->pHmacSecret) {
    129        if (aResponse->pHmacSecret->cbFirst > 0) {
    130          mPrfFirst.emplace();
    131          mPrfFirst->AppendElements(aResponse->pHmacSecret->pbFirst,
    132                                    aResponse->pHmacSecret->cbFirst);
    133        }
    134        if (aResponse->pHmacSecret->cbSecond > 0) {
    135          mPrfSecond.emplace();
    136          mPrfSecond->AppendElements(aResponse->pHmacSecret->pbSecond,
    137                                     aResponse->pHmacSecret->cbSecond);
    138        }
    139      }
    140    }
    141 
    142    DWORD transports = 0;
    143    if (aResponse->dwVersion >= WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_8) {
    144      // The dwTransports field added in version 8 lists all supported
    145      // transports, whereas the dwUsedTransport available since version 3 only
    146      // returns the transport that was used.
    147      transports = aResponse->dwTransports;
    148    } else if (aResponse->dwVersion >=
    149               WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_3) {
    150      transports = aResponse->dwUsedTransport;
    151    }
    152 
    153    if (transports & WEBAUTHN_CTAP_TRANSPORT_USB) {
    154      mTransports.AppendElement(u"usb"_ns);
    155    }
    156    if (transports & WEBAUTHN_CTAP_TRANSPORT_NFC) {
    157      mTransports.AppendElement(u"nfc"_ns);
    158    }
    159    if (transports & WEBAUTHN_CTAP_TRANSPORT_BLE) {
    160      mTransports.AppendElement(u"ble"_ns);
    161    }
    162    if (transports & WEBAUTHN_CTAP_TRANSPORT_INTERNAL) {
    163      mTransports.AppendElement(u"internal"_ns);
    164    }
    165    // WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_5 corresponds to
    166    // WEBAUTHN_API_VERSION_6 which is where WEBAUTHN_CTAP_TRANSPORT_HYBRID was
    167    // defined.
    168    if (aResponse->dwVersion >= WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_5) {
    169      if (transports & WEBAUTHN_CTAP_TRANSPORT_HYBRID) {
    170        mTransports.AppendElement(u"hybrid"_ns);
    171      }
    172    }
    173 
    174    if (aResponse->dwVersion >= WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_3) {
    175      if (aResponse->dwUsedTransport & WEBAUTHN_CTAP_TRANSPORT_INTERNAL) {
    176        mAuthenticatorAttachment = Some(u"platform"_ns);
    177      } else {
    178        mAuthenticatorAttachment = Some(u"cross-platform"_ns);
    179      }
    180    }
    181 
    182    if (aResponse->dwVersion >= WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_4) {
    183      if (aResponse->bLargeBlobSupported) {
    184        mLargeBlobSupported = Some(true);
    185      }
    186    }
    187 
    188    if (aResponse->dwVersion >= WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_5) {
    189      if (aResponse->bPrfEnabled) {
    190        mPrfSupported = Some(true);
    191      }
    192    }
    193  }
    194 #endif
    195 
    196 private:
    197  ~WebAuthnRegisterResult() = default;
    198 
    199  nsTArray<uint8_t> mAttestationObject;
    200  bool mAttestationConsentPromptShown;
    201  nsTArray<uint8_t> mCredentialId;
    202  nsTArray<nsString> mTransports;
    203  Maybe<nsCString> mClientDataJSON;
    204  Maybe<bool> mCredPropsRk;
    205  Maybe<bool> mHmacCreateSecret;
    206  Maybe<nsString> mAuthenticatorAttachment;
    207  Maybe<bool> mLargeBlobSupported;
    208  Maybe<bool> mPrfSupported;
    209  Maybe<nsTArray<uint8_t>> mPrfFirst;
    210  Maybe<nsTArray<uint8_t>> mPrfSecond;
    211 };
    212 
    213 class WebAuthnSignResult final : public nsIWebAuthnSignResult {
    214 public:
    215  NS_DECL_THREADSAFE_ISUPPORTS
    216  NS_DECL_NSIWEBAUTHNSIGNRESULT
    217 
    218  WebAuthnSignResult(const nsTArray<uint8_t>& aAuthenticatorData,
    219                     const Maybe<nsCString>& aClientDataJSON,
    220                     const nsTArray<uint8_t>& aCredentialId,
    221                     const nsTArray<uint8_t>& aSignature,
    222                     const nsTArray<uint8_t>& aUserHandle,
    223                     const Maybe<nsString>& aAuthenticatorAttachment,
    224                     const Maybe<bool>& aUsedAppId,
    225                     const Maybe<nsTArray<uint8_t>>& aLargeBlobValue,
    226                     const Maybe<bool>& aLargeBlobWritten,
    227                     const Maybe<nsTArray<uint8_t>>& aPrfFirst,
    228                     const Maybe<nsTArray<uint8_t>>& aPrfSecond)
    229      : mClientDataJSON(aClientDataJSON),
    230        mAuthenticatorAttachment(aAuthenticatorAttachment),
    231        mUsedAppId(aUsedAppId),
    232        mLargeBlobWritten(aLargeBlobWritten) {
    233    mAuthenticatorData.AppendElements(aAuthenticatorData);
    234    mCredentialId.AppendElements(aCredentialId);
    235    mSignature.AppendElements(aSignature);
    236    mUserHandle.AppendElements(aUserHandle);
    237    if (aLargeBlobValue.isSome()) {
    238      mLargeBlobValue.emplace(aLargeBlobValue->Length());
    239      mLargeBlobValue->Assign(aLargeBlobValue.ref());
    240    }
    241    if (aPrfFirst.isSome()) {
    242      mPrfFirst.emplace(aPrfFirst.ref().Length());
    243      mPrfFirst->Assign(aPrfFirst.ref());
    244    }
    245    if (aPrfSecond.isSome()) {
    246      mPrfSecond.emplace(aPrfSecond.ref().Length());
    247      mPrfSecond->Assign(aPrfSecond.ref());
    248    }
    249  }
    250 
    251 #ifdef MOZ_WIDGET_ANDROID
    252  explicit WebAuthnSignResult(
    253      const java::WebAuthnUtils::GetAssertionResponse::LocalRef& aResponse) {
    254    mAuthenticatorData.AppendElements(
    255        reinterpret_cast<uint8_t*>(
    256            aResponse->AuthData()->GetElements().Elements()),
    257        aResponse->AuthData()->Length());
    258    if (aResponse->ClientDataJson()) {
    259      mClientDataJSON = Some(nsAutoCString(
    260          reinterpret_cast<const char*>(
    261              aResponse->ClientDataJson()->GetElements().Elements()),
    262          aResponse->ClientDataJson()->Length()));
    263    }
    264    mCredentialId.AppendElements(
    265        reinterpret_cast<uint8_t*>(
    266            aResponse->KeyHandle()->GetElements().Elements()),
    267        aResponse->KeyHandle()->Length());
    268    mSignature.AppendElements(
    269        reinterpret_cast<uint8_t*>(
    270            aResponse->Signature()->GetElements().Elements()),
    271        aResponse->Signature()->Length());
    272    mUserHandle.AppendElements(
    273        reinterpret_cast<uint8_t*>(
    274            aResponse->UserHandle()->GetElements().Elements()),
    275        aResponse->UserHandle()->Length());
    276    mAuthenticatorAttachment =
    277        Some(aResponse->AuthenticatorAttachment()->ToString());
    278  }
    279 #endif
    280 
    281 #ifdef XP_WIN
    282  WebAuthnSignResult(nsCString& aClientDataJSON, DWORD aCredLargeBlobOperation,
    283                     PCWEBAUTHN_ASSERTION aResponse)
    284      : mClientDataJSON(Some(aClientDataJSON)) {
    285    mSignature.AppendElements(aResponse->pbSignature, aResponse->cbSignature);
    286 
    287    mCredentialId.AppendElements(aResponse->Credential.pbId,
    288                                 aResponse->Credential.cbId);
    289 
    290    mUserHandle.AppendElements(aResponse->pbUserId, aResponse->cbUserId);
    291 
    292    mAuthenticatorData.AppendElements(aResponse->pbAuthenticatorData,
    293                                      aResponse->cbAuthenticatorData);
    294 
    295    mAuthenticatorAttachment = Nothing();  // not available
    296 
    297    if (aCredLargeBlobOperation == WEBAUTHN_CRED_LARGE_BLOB_OPERATION_GET) {
    298      if (aResponse->dwVersion >= WEBAUTHN_ASSERTION_VERSION_2 &&
    299          aResponse->dwCredLargeBlobStatus ==
    300              WEBAUTHN_CRED_LARGE_BLOB_STATUS_SUCCESS) {
    301        mLargeBlobValue.emplace();
    302        mLargeBlobValue->AppendElements(aResponse->pbCredLargeBlob,
    303                                        aResponse->cbCredLargeBlob);
    304      }
    305    } else if (aCredLargeBlobOperation ==
    306               WEBAUTHN_CRED_LARGE_BLOB_OPERATION_SET) {
    307      if (aResponse->dwVersion >= WEBAUTHN_ASSERTION_VERSION_2 &&
    308          aResponse->dwCredLargeBlobStatus ==
    309              WEBAUTHN_CRED_LARGE_BLOB_STATUS_SUCCESS) {
    310        mLargeBlobWritten.emplace(true);
    311      } else {
    312        mLargeBlobWritten.emplace(false);
    313      }
    314    }
    315 
    316    if (aResponse->dwVersion >= WEBAUTHN_ASSERTION_VERSION_3) {
    317      if (aResponse->pHmacSecret) {
    318        if (aResponse->pHmacSecret->cbFirst > 0) {
    319          mPrfFirst.emplace();
    320          mPrfFirst->AppendElements(aResponse->pHmacSecret->pbFirst,
    321                                    aResponse->pHmacSecret->cbFirst);
    322        }
    323        if (aResponse->pHmacSecret->cbSecond > 0) {
    324          mPrfSecond.emplace();
    325          mPrfSecond->AppendElements(aResponse->pHmacSecret->pbSecond,
    326                                     aResponse->pHmacSecret->cbSecond);
    327        }
    328      }
    329    }
    330  }
    331 #endif
    332 
    333 private:
    334  ~WebAuthnSignResult() = default;
    335 
    336  nsTArray<uint8_t> mAuthenticatorData;
    337  Maybe<nsCString> mClientDataJSON;
    338  nsTArray<uint8_t> mCredentialId;
    339  nsTArray<uint8_t> mSignature;
    340  nsTArray<uint8_t> mUserHandle;
    341  Maybe<nsString> mAuthenticatorAttachment;
    342  Maybe<bool> mUsedAppId;
    343  Maybe<nsTArray<uint8_t>> mLargeBlobValue;
    344  Maybe<bool> mLargeBlobWritten;
    345  Maybe<nsTArray<uint8_t>> mPrfFirst;
    346  Maybe<nsTArray<uint8_t>> mPrfSecond;
    347 };
    348 
    349 }  // namespace mozilla::dom
    350 #endif  // mozilla_dom_WebAuthnResult_h