Bug 1522145 - Web Authentication - Support additional Windows Hello Algorithms r=keeler
authorAkshay Kumar <akshay.sonu@gmail.com>
Thu, 24 Jan 2019 18:38:49 +0000
changeset 515320 6b7bc40023111979a4755dfeca82629c9c022cd5
parent 515319 242c2992fd17bc2452c9bb0465c195b04f7454da
child 515321 145d739c4139f2767cb7e1475e17ab7d600dead4
child 515349 b55ddb97722a51b3365f1a72bdb416f028fd2073
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskeeler
bugs1522145
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1522145 - Web Authentication - Support additional Windows Hello Algorithms r=keeler Support Main Algorithms Differential Revision: https://phabricator.services.mozilla.com/D17363
dom/webauthn/U2FHIDTokenManager.cpp
dom/webauthn/U2FSoftTokenManager.cpp
dom/webauthn/WebAuthnCoseIdentifiers.h
dom/webauthn/WebAuthnManager.cpp
--- a/dom/webauthn/U2FHIDTokenManager.cpp
+++ b/dom/webauthn/U2FHIDTokenManager.cpp
@@ -1,14 +1,15 @@
 /* -*- 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 "WebAuthnCoseIdentifiers.h"
 #include "mozilla/dom/U2FHIDTokenManager.h"
 #include "mozilla/dom/WebAuthnUtil.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/StaticMutex.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -135,16 +136,41 @@ RefPtr<U2FRegisterPromise> U2FHIDTokenMa
       registerFlags |= U2F_FLAG_REQUIRE_RESIDENT_KEY;
     }
     if (requireUserVerification) {
       registerFlags |= U2F_FLAG_REQUIRE_USER_VERIFICATION;
     }
     if (requirePlatformAttachment) {
       registerFlags |= U2F_FLAG_REQUIRE_PLATFORM_ATTACHMENT;
     }
+
+    nsTArray<CoseAlg> coseAlgos;
+    for (const auto& coseAlg : extra.coseAlgs()) {
+      switch (static_cast<CoseAlgorithmIdentifier>(coseAlg.alg())) {
+        case CoseAlgorithmIdentifier::ES256:
+          coseAlgos.AppendElement(coseAlg);
+          break;
+        default:
+          continue;
+      }
+    }
+
+    // Only if no algorithms were specified, default to the only CTAP 1 / U2F
+    // protocol-supported algorithm. Ultimately this logic must move into
+    // u2f-hid-rs in a fashion that doesn't break the tests.
+    if (extra.coseAlgs().IsEmpty()) {
+      coseAlgos.AppendElement(
+          static_cast<int32_t>(CoseAlgorithmIdentifier::ES256));
+    }
+
+    // If there are no acceptable/supported algorithms, reject the promise.
+    if (coseAlgos.IsEmpty()) {
+      return U2FRegisterPromise::CreateAndReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
+                                                 __func__);
+    }
   }
 
   CryptoBuffer rpIdHash, clientDataHash;
   NS_ConvertUTF16toUTF8 rpId(aInfo.RpId());
   nsresult rv = BuildTransactionHashes(rpId, aInfo.ClientDataJSON(), rpIdHash,
                                        clientDataHash);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return U2FRegisterPromise::CreateAndReject(NS_ERROR_DOM_UNKNOWN_ERR,
--- a/dom/webauthn/U2FSoftTokenManager.cpp
+++ b/dom/webauthn/U2FSoftTokenManager.cpp
@@ -1,14 +1,15 @@
 /* -*- 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 "WebAuthnCoseIdentifiers.h"
 #include "mozilla/dom/U2FSoftTokenManager.h"
 #include "CryptoBuffer.h"
 #include "mozilla/Base64.h"
 #include "mozilla/Casting.h"
 #include "nsNSSComponent.h"
 #include "nsThreadUtils.h"
 #include "pk11pub.h"
 #include "prerror.h"
@@ -597,16 +598,40 @@ RefPtr<U2FRegisterPromise> U2FSoftTokenM
 
     // The U2F softtoken neither supports resident keys or
     // user verification, nor is it a platform authenticator.
     if (sel.requireResidentKey() || requireUserVerification ||
         requirePlatformAttachment) {
       return U2FRegisterPromise::CreateAndReject(NS_ERROR_DOM_NOT_ALLOWED_ERR,
                                                  __func__);
     }
+
+    nsTArray<CoseAlg> coseAlgos;
+    for (const auto& coseAlg : extra.coseAlgs()) {
+      switch (static_cast<CoseAlgorithmIdentifier>(coseAlg.alg())) {
+        case CoseAlgorithmIdentifier::ES256:
+          coseAlgos.AppendElement(coseAlg);
+          break;
+        default:
+          continue;
+      }
+    }
+
+    // Only if no algorithms were specified, default to the one the soft token
+    // supports.
+    if (extra.coseAlgs().IsEmpty()) {
+      coseAlgos.AppendElement(
+          static_cast<int32_t>(CoseAlgorithmIdentifier::ES256));
+    }
+
+    // If there are no acceptable/supported algorithms, reject the promise.
+    if (coseAlgos.IsEmpty()) {
+      return U2FRegisterPromise::CreateAndReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
+                                                 __func__);
+    }
   }
 
   CryptoBuffer rpIdHash, clientDataHash;
   NS_ConvertUTF16toUTF8 rpId(aInfo.RpId());
   nsresult rv = BuildTransactionHashes(rpId, aInfo.ClientDataJSON(), rpIdHash,
                                        clientDataHash);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return U2FRegisterPromise::CreateAndReject(NS_ERROR_DOM_UNKNOWN_ERR,
--- a/dom/webauthn/WebAuthnCoseIdentifiers.h
+++ b/dom/webauthn/WebAuthnCoseIdentifiers.h
@@ -10,24 +10,12 @@
 #include "mozilla/dom/WebCryptoCommon.h"
 
 namespace mozilla {
 namespace dom {
 
 // From https://www.iana.org/assignments/cose/cose.xhtml#algorithms
 enum class CoseAlgorithmIdentifier : int32_t { ES256 = -7 };
 
-static nsresult CoseAlgorithmToWebCryptoId(const int32_t& aId,
-                                           /* out */ nsString& aName) {
-  switch (static_cast<CoseAlgorithmIdentifier>(aId)) {
-    case CoseAlgorithmIdentifier::ES256:
-      aName.AssignLiteral(JWK_ALG_ECDSA_P_256);
-      break;
-    default:
-      return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
-  }
-  return NS_OK;
-}
-
 }  // namespace dom
 }  // namespace mozilla
 
 #endif  // mozilla_dom_WebAuthnCoseIdentifiers_h
--- a/dom/webauthn/WebAuthnManager.cpp
+++ b/dom/webauthn/WebAuthnManager.cpp
@@ -263,52 +263,34 @@ already_AddRefed<Promise> WebAuthnManage
   }
 
   // <https://w3c.github.io/webauthn/#sctn-appid-extension>
   if (aOptions.mExtensions.mAppid.WasPassed()) {
     promise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
     return promise.forget();
   }
 
-  // TODO: Move this logic into U2FTokenManager in Bug 1409220.
-
   // Process each element of mPubKeyCredParams using the following steps, to
   // produce a new sequence coseAlgos.
-  nsTArray<PublicKeyCredentialParameters> acceptableParams;
   nsTArray<CoseAlg> coseAlgos;
   for (size_t a = 0; a < aOptions.mPubKeyCredParams.Length(); ++a) {
-    // Let current be the currently selected element of
-    // mPubKeyCredParams.
-
     // If current.type does not contain a PublicKeyCredentialType
     // supported by this implementation, then stop processing current and move
     // on to the next element in mPubKeyCredParams.
     if (aOptions.mPubKeyCredParams[a].mType !=
         PublicKeyCredentialType::Public_key) {
       continue;
     }
 
-    nsString algName;
-    if (NS_FAILED(CoseAlgorithmToWebCryptoId(aOptions.mPubKeyCredParams[a].mAlg,
-                                             algName))) {
-      continue;
-    }
-
-    if (!acceptableParams.AppendElement(aOptions.mPubKeyCredParams[a],
-                                        mozilla::fallible)) {
-      promise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
-      return promise.forget();
-    }
     coseAlgos.AppendElement(aOptions.mPubKeyCredParams[a].mAlg);
   }
 
-  // If acceptableParams is empty and mPubKeyCredParams was not empty, cancel
-  // the timer started in step 2, reject promise with a DOMException whose name
-  // is "NotSupportedError", and terminate this algorithm.
-  if (acceptableParams.IsEmpty() && !aOptions.mPubKeyCredParams.IsEmpty()) {
+  // If there are algorithms specified, but none are Public_key algorithms,
+  // reject the promise.
+  if (coseAlgos.IsEmpty() && !aOptions.mPubKeyCredParams.IsEmpty()) {
     promise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
     return promise.forget();
   }
 
   // If excludeList is undefined, set it to the empty list.
   //
   // If extensions was specified, process any extensions supported by this
   // client platform, to produce the extension data that needs to be sent to the