Bug 1265211 - Fix intermittent U2F Test r?mgoodwin
- The u2futil.js script's verifySignature method was causing an intermittent
in test_frame_register_sign.html due to incomplete ASN.1 decoding. Since
we're calready pulling in an ASN.1 parsing library, this changes that code to
do a complete parse and santizize, which should cover all cases.
MozReview-Commit-ID: 9kDWT2KUFdq
--- a/dom/u2f/tests/test_util_methods.html
+++ b/dom/u2f/tests/test_util_methods.html
@@ -1,14 +1,18 @@
<!DOCTYPE html>
<meta charset=utf-8>
<head>
<title>Test for Utility Methods for other FIDO Universal Second Factor tests</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/dom/u2f/tests/u2futil.js"></script>
+ <script type="text/javascript" src="pkijs/common.js"></script>
+ <script type="text/javascript" src="pkijs/asn1.js"></script>
+ <script type="text/javascript" src="pkijs/x509_schema.js"></script>
+ <script type="text/javascript" src="pkijs/x509_simpl.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1231681">Mozilla Bug 1231681</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
--- a/dom/u2f/tests/u2futil.js
+++ b/dom/u2f/tests/u2futil.js
@@ -125,34 +125,38 @@ function assembleRegistrationSignedData(
signedData[0] = 0x00;
appParam.map((x, i) => signedData[1 + i] = x);
challengeParam.map((x, i) => signedData[33 + i] = x);
keyHandle.map((x, i) => signedData[65 + i] = x);
pubKey.map((x, i) => signedData[65 + keyHandle.length + i] = x);
return signedData;
}
-function verifySignature(key, data, derSig) {
- if (derSig.byteLength < 70) {
- console.log("bad sig: " + hexEncode(derSig))
- throw "Invalid signature length: " + derSig.byteLength;
+function sanitizeSigArray(arr) {
+ // ECDSA signature fields into WebCrypto must be exactly 32 bytes long, so
+ // this method strips leading padding bytes, if added, and also appends
+ // padding zeros, if needed.
+ if (arr.length > 32) {
+ arr = arr.slice(arr.length - 32)
}
+ var ret = new Uint8Array(32);
+ ret.set(arr, ret.length - arr.length);
+ return ret;
+}
- // Poor man's ASN.1 decode
- // R and S are always 32 bytes. If ether has a DER
- // length > 32, it's just zeros we can chop off.
- var lenR = derSig[3];
- var lenS = derSig[3 + lenR + 2];
- var padR = lenR - 32;
- var padS = lenS - 32;
- var sig = new Uint8Array(64);
- derSig.slice(4 + padR, 4 + lenR).map((x, i) => sig[i] = x);
- derSig.slice(4 + lenR + 2 + padS, 4 + lenR + 2 + lenS).map(
- (x, i) => sig[32 + i] = x
- );
+function verifySignature(key, data, derSig) {
+ var sigAsn1 = org.pkijs.fromBER(derSig.buffer);
+ var sigR = new Uint8Array(sigAsn1.result.value_block.value[0].value_block.value_hex);
+ var sigS = new Uint8Array(sigAsn1.result.value_block.value[1].value_block.value_hex);
- console.log("data: " + hexEncode(data));
- console.log("der: " + hexEncode(derSig));
- console.log("raw: " + hexEncode(sig));
+ // The resulting R and S values from the ASN.1 Sequence must be fit into 32
+ // bytes. Sometimes they have leading zeros, sometimes they're too short, it
+ // all depends on what lib generated the signature.
+ var R = sanitizeSigArray(sigR);
+ var S = sanitizeSigArray(sigS);
+
+ var sigData = new Uint8Array(R.length + S.length);
+ sigData.set(R);
+ sigData.set(S, R.length);
var alg = {name: "ECDSA", hash: "SHA-256"};
- return crypto.subtle.verify(alg, key, sig, data);
+ return crypto.subtle.verify(alg, key, sigData, data);
}