// META: title=WebCryptoAPI: Properties discard the context in algorithm normalization let nextTest = 0; let tests = {}; function closeChild(testId) { if (tests[testId]) { let {child, t} = tests[testId]; delete tests[testId]; document.body.removeChild(child); t.done(); } } function runInChild(t, childScript) { let testId = nextTest++; const preamble = ` let testId = ${testId}; function closeChildOnAccess(obj, key) { const oldValue = obj[key]; Object.defineProperty(obj, key, {get: () => { top.closeChild(testId); return oldValue; }}); } `; childScript = preamble + childScript; let child = document.createElement("iframe"); tests[testId] = {t, child}; document.body.appendChild(child); let script = document.createElement("script"); script.textContent = childScript; child.contentDocument.body.appendChild(script); } async_test((t) => { const childScript = ` let algorithm = {name: "AES-GCM", length: 128}; closeChildOnAccess(algorithm, "name"); crypto.subtle.generateKey(algorithm, true, ["encrypt", "decrypt"]);`; runInChild(t, childScript); }, "Context is discarded in generateKey"); async_test((t) => { const childScript = ` let algorithm = {name: "AES-GCM"}; closeChildOnAccess(algorithm, "name"); crypto.subtle.importKey("raw", new Uint8Array(16), algorithm, true, ["encrypt", "decrypt"]);`; runInChild(t, childScript); }, "Context is discarded in importKey"); async_test((t) => { const childScript = ` (async () => { let key = await crypto.subtle.generateKey( {name: "AES-GCM", length: 128}, true, ["encrypt", "decrypt"]); let algorithm = {name: "AES-GCM", iv: new Uint8Array(12)}; closeChildOnAccess(algorithm, "name"); crypto.subtle.encrypt(algorithm, key, new Uint8Array()); })();`; runInChild(t, childScript); }, "Context is discarded in encrypt"); async_test((t) => { const childScript = ` (async () => { let key = await crypto.subtle.generateKey( {name: "AES-GCM", length: 128}, true, ["encrypt", "decrypt"]); let algorithm = {name: "AES-GCM", iv: new Uint8Array(12)}; let encrypted = await crypto.subtle.encrypt(algorithm, key, new Uint8Array()); closeChildOnAccess(algorithm, "name"); crypto.subtle.decrypt(algorithm, key, encrypted); })();`; runInChild(t, childScript); }, "Context is discarded in decrypt"); async_test((t) => { const childScript = ` let algorithm = {name: "SHA-256"}; closeChildOnAccess(algorithm, "name"); crypto.subtle.digest(algorithm, new Uint8Array());`; runInChild(t, childScript); }, "Context is discarded in digest"); async_test((t) => { const childScript = ` (async () => { let key = await crypto.subtle.generateKey( {name: "ECDSA", namedCurve: "P-256"}, true, ["sign", "verify"]); let algorithm = {name: "ECDSA", hash: "SHA-256"}; closeChildOnAccess(algorithm, "name"); crypto.subtle.sign(algorithm, key.privateKey, new Uint8Array()); })();`; runInChild(t, childScript); }, "Context is discarded in sign"); async_test((t) => { const childScript = ` (async () => { let key = await crypto.subtle.generateKey( {name: "ECDSA", namedCurve: "P-256"}, true, ["sign", "verify"]); let algorithm = {name: "ECDSA", hash: "SHA-256"}; let data = new Uint8Array(); let signature = await crypto.subtle.sign(algorithm, key.privateKey, data); closeChildOnAccess(algorithm, "name"); crypto.subtle.verify(algorithm, key.publicKey, signature, data); })();`; runInChild(t, childScript); }, "Context is discarded in verify"); async_test((t) => { const childScript = ` (async () => { let key = await crypto.subtle.importKey( "raw", new Uint8Array(16), "HKDF", false, ["deriveBits"]); let algorithm = { name: "HKDF", hash: "SHA-256", salt: new Uint8Array(), info: new Uint8Array(), }; closeChildOnAccess(algorithm, "name"); crypto.subtle.deriveBits(algorithm, key, 16); })();`; runInChild(t, childScript); }, "Context is discarded in deriveBits"); async_test((t) => { const childScript = ` (async () => { let key = await crypto.subtle.importKey( "raw", new Uint8Array(16), "HKDF", false, ["deriveKey"]); let algorithm = { name: "HKDF", hash: "SHA-256", salt: new Uint8Array(), info: new Uint8Array(), }; let derivedAlgorithm = {name: "AES-GCM", length: 128}; closeChildOnAccess(algorithm, "name"); crypto.subtle.deriveKey(algorithm, key, derivedAlgorithm, true, ["encrypt", "decrypt"]); })();`; runInChild(t, childScript); }, "Context is discarded in deriveKey"); async_test((t) => { const childScript = ` (async () => { let key = await crypto.subtle.importKey( "raw", new Uint8Array(16), "HKDF", false, ["deriveKey"]); let algorithm = { name: "HKDF", hash: "SHA-256", salt: new Uint8Array(), info: new Uint8Array(), }; let derivedAlgorithm = {name: "AES-GCM", length: 128}; closeChildOnAccess(derivedAlgorithm, "name"); crypto.subtle.deriveKey(algorithm, key, derivedAlgorithm, true, ["encrypt", "decrypt"]); })();`; runInChild(t, childScript); }, "Context is discarded in deriveKey (2)"); async_test((t) => { const childScript = ` (async () => { let wrapKey = await crypto.subtle.generateKey( {name: "AES-GCM", length: 128}, true, ["wrapKey", "unwrapKey"]); let key = await crypto.subtle.generateKey( {name: "AES-GCM", length: 128}, true, ["encrypt", "decrypt"]); let wrapAlgorithm = {name: "AES-GCM", iv: new Uint8Array(12)}; closeChildOnAccess(wrapAlgorithm, "name"); crypto.subtle.wrapKey("raw", key, wrapKey, wrapAlgorithm); })();`; runInChild(t, childScript); }, "Context is discarded in wrapKey"); async_test((t) => { const childScript = ` (async () => { let wrapKey = await crypto.subtle.generateKey( {name: "AES-GCM", length: 128}, true, ["wrapKey", "unwrapKey"]); let keyAlgorithm = {name: "AES-GCM", length: 128}; let keyUsages = ["encrypt", "decrypt"]; let key = await crypto.subtle.generateKey(keyAlgorithm, true, keyUsages); let wrapAlgorithm = {name: "AES-GCM", iv: new Uint8Array(12)}; let wrapped = await crypto.subtle.wrapKey("raw", key, wrapKey, wrapAlgorithm); closeChildOnAccess(wrapAlgorithm, "name"); crypto.subtle.unwrapKey( "raw", wrapped, wrapKey, wrapAlgorithm, keyAlgorithm, true, keyUsages); })();`; runInChild(t, childScript); }, "Context is discarded in unwrapKey"); async_test((t) => { const childScript = ` (async () => { let wrapKey = await crypto.subtle.generateKey( {name: "AES-GCM", length: 128}, true, ["wrapKey", "unwrapKey"]); let keyAlgorithm = {name: "AES-GCM", length: 128}; let keyUsages = ["encrypt", "decrypt"]; let key = await crypto.subtle.generateKey(keyAlgorithm, true, keyUsages); let wrapAlgorithm = {name: "AES-GCM", iv: new Uint8Array(12)}; let wrapped = await crypto.subtle.wrapKey("raw", key, wrapKey, wrapAlgorithm); closeChildOnAccess(keyAlgorithm, "name"); crypto.subtle.unwrapKey( "raw", wrapped, wrapKey, wrapAlgorithm, keyAlgorithm, true, keyUsages); })();`; runInChild(t, childScript); }, "Context is discarded in unwrapKey (2)");