Bug 1241757 - Permit export of JWK with empty key_ops field, r=rbarnes
authorMartin Thomson <martin.thomson@gmail.com>
Fri, 22 Jan 2016 18:07:39 +1100
changeset 320552 b9799dc98199
parent 320551 14b934e83447
child 320553 ea39d4a6232c
child 320607 ab454c4469b7
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrbarnes
bugs1241757
milestone47.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 1241757 - Permit export of JWK with empty key_ops field, r=rbarnes
dom/crypto/WebCryptoTask.cpp
dom/crypto/test/test_WebCrypto_JWK.html
--- a/dom/crypto/WebCryptoTask.cpp
+++ b/dom/crypto/WebCryptoTask.cpp
@@ -2165,21 +2165,19 @@ private:
       }
 
       if (!mAlg.IsEmpty()) {
         mJwk.mAlg.Construct(mAlg);
       }
 
       mJwk.mExt.Construct(mExtractable);
 
-      if (!mKeyUsages.IsEmpty()) {
-        mJwk.mKey_ops.Construct();
-        if (!mJwk.mKey_ops.Value().AppendElements(mKeyUsages, fallible)) {
-          return NS_ERROR_OUT_OF_MEMORY;
-        }
+      mJwk.mKey_ops.Construct();
+      if (!mJwk.mKey_ops.Value().AppendElements(mKeyUsages, fallible)) {
+        return NS_ERROR_OUT_OF_MEMORY;
       }
 
       return NS_OK;
     }
 
     return NS_ERROR_DOM_SYNTAX_ERR;
   }
 
--- a/dom/crypto/test/test_WebCrypto_JWK.html
+++ b/dom/crypto/test/test_WebCrypto_JWK.html
@@ -245,16 +245,68 @@ TestArray.addTest(
                  shallowArrayEquals(x.key_ops, ['verify']) &&
                  x.n  == jwk.n  &&
                  x.e  == jwk.e;
           }),
         error(that)
       );
   }
 );
+
+// --------
+TestArray.addTest(
+  "Check JWK parameters on generated ECDSA key pair",
+  function() {
+    crypto.subtle.generateKey({name: 'ECDSA', namedCurve: 'P-256'}, true, ['sign', 'verify'])
+      .then(pair => Promise.all([
+         crypto.subtle.exportKey('jwk', pair.privateKey),
+         crypto.subtle.exportKey('jwk', pair.publicKey)
+      ]))
+      .then(
+        complete(this, function(x) {
+          var priv = x[0];
+          var pub = x[1];
+          var pubIsSubsetOfPriv = Object.keys(pub)
+            .filter(k => k !== 'key_ops') // key_ops is the only complex attr
+            .reduce((all, k) => all && pub[k] === priv[k], true);
+          // Can't use hasBaseJwkFields() because EC keys don't get "alg":
+          // "alg" matches curve to hash, but WebCrypto keys are more flexible.
+          return hasFields(pub, ['kty', 'crv', 'key_ops', 'ext']) &&
+            pub.kty === 'EC' &&
+            pub.crv === 'P-256' &&
+            pub.ext &&
+            typeof(pub.x) === 'string' &&
+            typeof(pub.y) === 'string' &&
+            shallowArrayEquals(pub.key_ops, ['verify']) &&
+            pubIsSubsetOfPriv &&
+            shallowArrayEquals(priv.key_ops, ['sign']) &&
+            typeof(priv.d) === 'string';
+        }),
+        error(this));
+  }
+);
+
+// --------
+TestArray.addTest(
+  "Check key_ops parameter on an unusable RSA public key",
+  function() {
+    var parameters = {
+      name: 'RSASSA-PKCS1-v1_5',
+      modulusLength: 1024,
+      publicExponent: new Uint8Array([1, 0, 1]),
+      hash: 'SHA-256'
+    };
+    // The public key generated here will have no usages and will therefore
+    // have an empty key_ops list.
+    crypto.subtle.generateKey(parameters, true, ['sign'])
+      .then(pair => crypto.subtle.exportKey('jwk', pair.publicKey))
+      .then(complete(this, x => x.key_ops.length === 0),
+            error(this));
+  }
+);
 /*]]>*/</script>
 </head>
 
 <body>
 
 <div id="content">
 	<div id="head">
 		<b>Web</b>Crypto<br>