Bug 1420763 - encode webauthn keys as a COSE key; r?jcj draft
authorAdam Langley <agl@chromium.org>
Sun, 31 Dec 2017 19:46:20 -0800
changeset 715108 a41d7fd211873e4d0dbe2427b822bd2c49003e97
parent 715097 ab6752aa7e63279dd8da7959be39e0bf4b4d66a8
child 744700 668e37941bf2b0e7f408fd708fb4a31cec020848
push id94059
push userbmo:agl@chromium.org
push dateMon, 01 Jan 2018 03:46:37 +0000
reviewersjcj
bugs1420763
milestone58.0
Bug 1420763 - encode webauthn keys as a COSE key; r?jcj webauthn says[1] that public keys are encoded as COSE keys. I find the COSE RFC quite circuitous in many respects and so any reviews should check whether they agree with my understanding of what should be in a COSE key. The webauthn spec says that the key: “MUST contain the "alg" parameter and MUST NOT contain any other optional parameters.” I don't believe that any of the parameters included are optional but, again, I don't think the RFC is completely clear. [1] https://www.w3.org/TR/webauthn/#sec-attested-credential-data MozReview-Commit-ID: 9cXTv5zGl9v
dom/webauthn/WebAuthnCBORUtil.cpp
--- a/dom/webauthn/WebAuthnCBORUtil.cpp
+++ b/dom/webauthn/WebAuthnCBORUtil.cpp
@@ -16,36 +16,32 @@ CBOREncodePublicKeyObj(const CryptoBuffe
                        /* out */ CryptoBuffer& aPubKeyObj)
 {
   mozilla::dom::CryptoBuffer xBuf, yBuf;
   nsresult rv = U2FDecomposeECKey(aPubKeyBuf, xBuf, yBuf);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
-  /*
-  Public Key Object, encoded in CBOR (description is CDDL)
-
-  pubKey = $pubKeyFmt
-
-  pubKeyFmt /= eccPubKey
-  eccPubKey = { alg: eccAlgName, x: biguint, y: biguint }
-  eccAlgName = "ES256" / "ES384" / "ES512"
-  */
+  // COSE_Key object. See https://tools.ietf.org/html/rfc8152#section-7
   cbor::output_dynamic cborPubKeyOut;
   cbor::encoder encoder(cborPubKeyOut);
-  encoder.write_map(3);
+  encoder.write_map(5);
   {
-    encoder.write_string("alg");
-    encoder.write_string(JWK_ALG_ECDSA_P_256); // Always ES256 for U2F
+    encoder.write_int(1);   // kty
+    encoder.write_int(2);   // EC2
+    encoder.write_int(3);   // alg
+    encoder.write_int(-7);  // ES256
 
-    encoder.write_string("x");
+    // See https://tools.ietf.org/html/rfc8152#section-13.1
+    encoder.write_int(-1);  // crv
+    encoder.write_int(1);   // P-256
+    encoder.write_int(-2);  // x
     encoder.write_bytes(xBuf.Elements(), xBuf.Length());
-
-    encoder.write_string("y");
+    encoder.write_int(-3);  // y
     encoder.write_bytes(yBuf.Elements(), yBuf.Length());
   }
 
   if (!aPubKeyObj.Assign(cborPubKeyOut.data(), cborPubKeyOut.size())) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
   return NS_OK;
 }