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

--HG--
extra : transplant_source : %A9CD%CD%E7E%11s%0A%82ls%5B%7B%80jQ%FC%FE%0B
This commit is contained in:
J.C. Jones 2016-04-19 08:49:13 -07:00
parent 5d60c22c60
commit fa14e077d5
2 changed files with 28 additions and 20 deletions

View File

@ -4,6 +4,10 @@
<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>

View File

@ -130,29 +130,33 @@ function assembleRegistrationSignedData(appParam, challengeParam, keyHandle, pub
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);
}