diff --git a/dom/u2f/tests/test_util_methods.html b/dom/u2f/tests/test_util_methods.html index 45c33d3331f8..4cccdd2c86f7 100644 --- a/dom/u2f/tests/test_util_methods.html +++ b/dom/u2f/tests/test_util_methods.html @@ -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> diff --git a/dom/u2f/tests/u2futil.js b/dom/u2f/tests/u2futil.js index 7e90b8f66cff..b415ff6c8103 100644 --- a/dom/u2f/tests/u2futil.js +++ b/dom/u2f/tests/u2futil.js @@ -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); }