test_webauthn_attestation_conveyance.html (4122B)
1 <!DOCTYPE html> 2 <meta charset=utf-8> 3 <head> 4 <title>W3C Web Authentication - Attestation Conveyance</title> 5 <script src="/tests/SimpleTest/SimpleTest.js"></script> 6 <script type="text/javascript" src="u2futil.js"></script> 7 <script type="text/javascript" src="pkijs/common.js"></script> 8 <script type="text/javascript" src="pkijs/asn1.js"></script> 9 <script type="text/javascript" src="pkijs/x509_schema.js"></script> 10 <script type="text/javascript" src="pkijs/x509_simpl.js"></script> 11 <script type="text/javascript" src="cbor.js"></script> 12 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 13 </head> 14 <body> 15 16 <h1>W3C Web Authentication - Attestation Conveyance</h1> 17 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1428916">Mozilla Bug 1428916</a> 18 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1416056">Mozilla Bug 1416056</a> 19 20 <script class="testbody" type="text/javascript"> 21 "use strict"; 22 23 add_task(async () => { 24 await SpecialPowers.pushPrefEnv({"set": [ 25 ["security.webauthn.always_allow_direct_attestation", true], 26 ]}); 27 await addVirtualAuthenticator(); 28 }); 29 30 function verifyAnonymizedCertificate(aResult) { 31 return webAuthnDecodeCBORAttestation(aResult.response.attestationObject) 32 .then(({fmt, attStmt}) => { 33 is(fmt, "none", "Is a None Attestation"); 34 is(typeof(attStmt), "object", "attStmt is a map"); 35 is(Object.keys(attStmt).length, 0, "attStmt is empty"); 36 }); 37 } 38 39 async function verifyDirectCertificate(aResult) { 40 let clientDataHash = await crypto.subtle.digest("SHA-256", aResult.response.clientDataJSON) 41 .then(digest => new Uint8Array(digest)); 42 let {fmt, attStmt, authData, authDataObj} = await webAuthnDecodeCBORAttestation(aResult.response.attestationObject); 43 is(fmt, "packed", "Is a Packed Attestation"); 44 let signedData = new Uint8Array(authData.length + clientDataHash.length); 45 signedData.set(authData); 46 signedData.set(clientDataHash, authData.length); 47 let valid = await verifySignature(authDataObj.publicKeyHandle, signedData, new Uint8Array(attStmt.sig)); 48 ok(valid, "Signature is valid."); 49 } 50 51 function arrivingHereIsBad(aResult) { 52 ok(false, "Bad result! Received a: " + aResult); 53 } 54 55 function expectTypeError(aResult) { 56 ok(aResult.toString().startsWith("TypeError"), "Expecting a TypeError, got " + aResult); 57 } 58 59 // Start a new MakeCredential() request. 60 function requestMakeCredential(attestation) { 61 let publicKey = { 62 rp: {id: document.domain, name: "none"}, 63 user: {id: new Uint8Array(), name: "none", displayName: "none"}, 64 challenge: crypto.getRandomValues(new Uint8Array(16)), 65 timeout: 5000, // the minimum timeout is actually 15 seconds 66 pubKeyCredParams: [{type: "public-key", alg: cose_alg_ECDSA_w_SHA256}], 67 attestation, 68 }; 69 70 return navigator.credentials.create({publicKey}); 71 } 72 73 // Test success cases for make credential. 74 add_task(async function test_make_credential_success () { 75 // No selection criteria should be equal to none, which means anonymized 76 await requestMakeCredential() 77 .then(verifyAnonymizedCertificate) 78 .catch(arrivingHereIsBad); 79 80 // Request an unknown attestation type. This should be treated as "none". 81 await requestMakeCredential("unknown") 82 .then(verifyAnonymizedCertificate) 83 .catch(arrivingHereIsBad); 84 85 // Request no attestation. 86 await requestMakeCredential("none") 87 .then(verifyAnonymizedCertificate) 88 .catch(arrivingHereIsBad); 89 90 // Request indirect attestation, which is the same as direct. 91 await requestMakeCredential("indirect") 92 .then(verifyDirectCertificate) 93 .catch(arrivingHereIsBad); 94 95 // Request direct attestation, which will prompt for user intervention. 96 await requestMakeCredential("direct") 97 .then(verifyDirectCertificate) 98 .catch(arrivingHereIsBad); 99 }); 100 </script> 101 102 </body> 103 </html>