Skip to content

Commit

Permalink
test,crypto: update WebCryptoAPI WPT
Browse files Browse the repository at this point in the history
Refs: nodejs#54572
Refs: nodejs#54468
PR-URL: nodejs#54593
Refs: nodejs#54572
Refs: nodejs#54468
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
  • Loading branch information
panva authored and sendoru committed Sep 1, 2024
1 parent 0265883 commit 2b43487
Show file tree
Hide file tree
Showing 20 changed files with 568 additions and 493 deletions.
12 changes: 10 additions & 2 deletions test/common/wpt.js
Original file line number Diff line number Diff line change
Expand Up @@ -458,8 +458,16 @@ class StatusLoader {

load() {
const dir = path.join(__dirname, '..', 'wpt');
const statusFile = path.join(dir, 'status', `${this.path}.json`);
const result = JSON.parse(fs.readFileSync(statusFile, 'utf8'));
let statusFile = path.join(dir, 'status', `${this.path}.json`);
let result;

if (fs.existsSync(statusFile)) {
result = JSON.parse(fs.readFileSync(statusFile, 'utf8'));
} else {
statusFile = path.join(dir, 'status', `${this.path}.cjs`);
result = require(statusFile);
}

this.rules.addRules(result);

const subDir = fixtures.path('wpt', this.path);
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/wpt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Last update:
- user-timing: https://github.com/web-platform-tests/wpt/tree/5ae85bf826/user-timing
- wasm/jsapi: https://github.com/web-platform-tests/wpt/tree/cde25e7e3c/wasm/jsapi
- wasm/webapi: https://github.com/web-platform-tests/wpt/tree/fd1b23eeaa/wasm/webapi
- WebCryptoAPI: https://github.com/web-platform-tests/wpt/tree/5e042cbc4e/WebCryptoAPI
- WebCryptoAPI: https://github.com/web-platform-tests/wpt/tree/6748a0a246/WebCryptoAPI
- webidl/ecmascript-binding/es-exceptions: https://github.com/web-platform-tests/wpt/tree/a370aad338/webidl/ecmascript-binding/es-exceptions
- webmessaging/broadcastchannel: https://github.com/web-platform-tests/wpt/tree/e97fac4791/webmessaging/broadcastchannel
- webstorage: https://github.com/web-platform-tests/wpt/tree/9dafa89214/webstorage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ function define_tests() {
// Verify the derive functions perform checks against the all-zero value results,
// ensuring small-order points are rejected.
// https://www.rfc-editor.org/rfc/rfc7748#section-6.1
// TODO: The spec states that the check must be done on use, but there is discussion about doing it on import.
// https://github.com/WICG/webcrypto-secure-curves/pull/13
Object.keys(kSmallOrderPoint).forEach(function(algorithmName) {
kSmallOrderPoint[algorithmName].forEach(function(test) {
promise_test(async() => {
Expand All @@ -23,8 +21,8 @@ function define_tests() {
false, [])
derived = await subtle.deriveBits({name: algorithmName, public: publicKey}, privateKey, 8 * sizes[algorithmName]);
} catch (err) {
assert_false(privateKey === undefined, "Private key should be valid.");
assert_false(publicKey === undefined, "Public key should be valid.");
assert_true(privateKey !== undefined, "Private key should be valid.");
assert_true(publicKey !== undefined, "Public key should be valid.");
assert_equals(err.name, "OperationError", "Should throw correct error, not " + err.name + ": " + err.message + ".");
}
assert_equals(derived, undefined, "Operation succeeded, but should not have.");
Expand Down Expand Up @@ -59,25 +57,6 @@ function define_tests() {
});
}, algorithmName + " mixed case parameters");

// Null length
// "Null" is not valid per the current spec
// - https://github.com/w3c/webcrypto/issues/322
// - https://github.com/w3c/webcrypto/issues/329
//
// Proposal for a spec change:
// - https://github.com/w3c/webcrypto/pull/345
//
// This test case may be replaced by these new tests:
// - https://github.com/web-platform-tests/wpt/pull/43400
promise_test(function(test) {
return subtle.deriveBits({name: algorithmName, public: publicKeys[algorithmName]}, privateKeys[algorithmName], null)
.then(function(derivation) {
assert_true(equalBuffers(derivation, derivations[algorithmName]), "Derived correct bits");
}, function(err) {
assert_unreached("deriveBits failed with error " + err.name + ": " + err.message);
});
}, algorithmName + " with null length");

// Shorter than entire derivation per algorithm
promise_test(function(test) {
return subtle.deriveBits({name: algorithmName, public: publicKeys[algorithmName]}, privateKeys[algorithmName], 8 * sizes[algorithmName] - 32)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// META: title=WebCryptoAPI: deriveBits() tests for the 'length' parameter
// META: script=derived_bits_length.js
// META: script=derived_bits_length_vectors.js
// META: script=derived_bits_length_testcases.js

// Define subtests from a `promise_test` to ensure the harness does not
// complete before the subtests are available. `explicit_done` cannot be used
// for this purpose because the global `done` function is automatically invoked
// by the WPT infrastructure in dedicated worker tests defined using the
// "multi-global" pattern.
promise_test(define_tests, 'setup - define tests');
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
function define_tests() {
// May want to test prefixed implementations.
var subtle = self.crypto.subtle;

Object.keys(testCases).forEach(algorithm => {
let testData = algorithms[algorithm];
testCases[algorithm].forEach(testParam => {
promise_test(async() => {
let derivedBits, privateKey, publicKey;
try {
privateKey = await subtle.importKey(testData.privateKey.format, testData.privateKey.data, testData.importAlg, false, ["deriveBits"]);
if (testData.deriveAlg.public !== undefined) {
publicKey = await subtle.importKey(testData.publicKey.format, testData.publicKey.data, testData.importAlg, false, []);
testData.deriveAlg.public = publicKey;
}
if (testParam.length === "omitted")
derivedBits = await subtle.deriveBits(testData.deriveAlg, privateKey);
else
derivedBits = await subtle.deriveBits(testData.deriveAlg, privateKey, testParam.length);
if (testParam.expected === undefined) {
assert_unreached("deriveBits should have thrown an OperationError exception.");
}
assert_array_equals(new Uint8Array(derivedBits), testParam.expected, "Derived bits do not match the expected result.");
} catch (err) {
if (err instanceof AssertionError || testParam.expected !== undefined) {
throw err;
}
assert_true(privateKey !== undefined, "Key should be valid.");
assert_equals(err.name, "OperationError", "deriveBits correctly threw OperationError: " + err.message);
}
}, algorithm + " derivation with " + testParam.length + " as 'length' parameter");
});
});

return Promise.resolve("define_tests");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
var testCases = {
"HKDF": [
{length: 256, expected: algorithms["HKDF"].derivation},
{length: 0, expected: undefined}, // explicitly disallowed, so should throw
{length: null, expected: undefined }, // should throw an exception
{length: undefined, expected: undefined }, // should throw an exception
{length: "omitted", expected: undefined }, // default value is null, so should throw
],
"PBKDF2": [
{length: 256, expected: algorithms["PBKDF2"].derivation},
{length: 0, expected: undefined}, // explicitly disallowed, so should throw
{length: null, expected: undefined }, // should throw an exception
{length: undefined, expected: undefined }, // should throw an exception
{length: "omitted", expected: undefined }, // default value is null, so should throw
],
"ECDH": [
{length: 256, expected: algorithms["ECDH"].derivation},
{length: 0, expected: emptyArray},
{length: null, expected: algorithms["ECDH"].derivation},
{length: undefined, expected: algorithms["ECDH"].derivation},
{length: "omitted", expected: algorithms["ECDH"].derivation }, // default value is null
],
"X25519": [
{length: 256, expected: algorithms["X25519"].derivation},
{length: 0, expected: emptyArray},
{length: null, expected: algorithms["X25519"].derivation},
{length: undefined, expected: algorithms["X25519"].derivation},
{length: "omitted", expected: algorithms["X25519"].derivation }, // default value is null
],
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const emptyArray = new Uint8Array([]);
const rawKey = new Uint8Array([85, 115, 101, 114, 115, 32, 115, 104, 111, 117, 108, 100, 32, 112, 105, 99, 107, 32, 108, 111, 110, 103, 32, 112, 97, 115, 115, 112, 104, 114, 97, 115, 101, 115, 32, 40, 110, 111, 116, 32, 117, 115, 101, 32, 115, 104, 111, 114, 116, 32, 112, 97, 115, 115, 119, 111, 114, 100, 115, 41, 33]);
const salt = new Uint8Array([83, 111, 100, 105, 117, 109, 32, 67, 104, 108, 111, 114, 105, 100, 101, 32, 99, 111, 109, 112, 111, 117, 110, 100]);
const info = new Uint8Array([72, 75, 68, 70, 32, 101, 120, 116, 114, 97, 32, 105, 110, 102, 111]);

var algorithms = {
"HKDF": {
importAlg: {name: "HKDF"},
privateKey: {format: "raw", data: rawKey},
deriveAlg: {name: "HKDF", salt: salt, hash: "SHA-256", info: info},
derivation: new Uint8Array([49, 183, 214, 133, 48, 168, 99, 231, 23, 192, 129, 202, 105, 23, 182, 134, 80, 179, 221, 154, 41, 243, 6, 6, 226, 202, 209, 153, 190, 193, 77, 19]),
},
"PBKDF2": {
importAlg: {name: "PBKDF2"},
privateKey: {format: "raw", data: rawKey},
deriveAlg: {name: "PBKDF2", salt: salt, hash: "SHA-256", iterations: 100000},
derivation: new Uint8Array([17, 153, 45, 139, 129, 51, 17, 36, 76, 84, 75, 98, 41, 41, 69, 226, 8, 212, 3, 206, 189, 107, 149, 82, 161, 165, 98, 6, 93, 153, 88, 234]),
},
"ECDH": {
importAlg: {name: "ECDH", namedCurve: "P-256"},
privateKey: {format: "pkcs8", data: new Uint8Array([48, 129, 135, 2, 1, 0, 48, 19, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 134, 72, 206, 61, 3, 1, 7, 4, 109, 48, 107, 2, 1, 1, 4, 32, 15, 247, 79, 232, 241, 202, 175, 97, 92, 206, 241, 29, 217, 53, 114, 87, 98, 217, 216, 65, 236, 186, 185, 94, 170, 38, 68, 123, 52, 100, 245, 113, 161, 68, 3, 66, 0, 4, 140, 96, 11, 44, 102, 25, 45, 97, 158, 39, 210, 37, 107, 59, 151, 118, 178, 141, 30, 5, 246, 13, 234, 189, 98, 174, 123, 154, 211, 157, 224, 217, 59, 4, 102, 109, 199, 119, 14, 126, 207, 13, 211, 203, 203, 211, 110, 221, 107, 94, 220, 153, 81, 7, 55, 161, 237, 104, 46, 205, 112, 244, 10, 47])},
publicKey: {format: "spki", data: new Uint8Array([48, 89, 48, 19, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 134, 72, 206, 61, 3, 1, 7, 3, 66, 0, 4, 154, 116, 32, 120, 126, 95, 77, 105, 211, 232, 34, 114, 115, 1, 109, 56, 224, 71, 129, 133, 223, 127, 238, 156, 142, 103, 60, 202, 211, 79, 126, 128, 254, 49, 141, 182, 221, 107, 119, 218, 99, 32, 165, 246, 151, 89, 9, 68, 23, 177, 52, 239, 138, 139, 116, 193, 101, 4, 57, 198, 115, 0, 90, 61])},
deriveAlg: {name: "ECDH", public: new Uint8Array ([])},
derivation: new Uint8Array([14, 143, 60, 77, 177, 178, 162, 131, 115, 90, 0, 220, 87, 31, 26, 232, 151, 28, 227, 35, 250, 17, 131, 137, 203, 95, 65, 196, 59, 61, 181, 161]),
},
"X25519": {
importAlg: {name: "X25519"},
privateKey: {format: "pkcs8", data: new Uint8Array([48, 46, 2, 1, 0, 48, 5, 6, 3, 43, 101, 110, 4, 34, 4, 32, 200, 131, 142, 118, 208, 87, 223, 183, 216, 201, 90, 105, 225, 56, 22, 10, 221, 99, 115, 253, 113, 164, 210, 118, 187, 86, 227, 168, 27, 100, 255, 97])},
publicKey: {format: "spki", data: new Uint8Array([48, 42, 48, 5, 6, 3, 43, 101, 110, 3, 33, 0, 28, 242, 177, 230, 2, 46, 197, 55, 55, 30, 215, 245, 62, 84, 250, 17, 84, 216, 62, 152, 235, 100, 234, 81, 250, 229, 179, 48, 124, 254, 151, 6])},
deriveAlg: {name: "X25519", public: new Uint8Array ([])},
derivation: new Uint8Array([39, 104, 64, 157, 250, 185, 158, 194, 59, 140, 137, 185, 63, 245, 136, 2, 149, 247, 97, 118, 8, 143, 137, 228, 61, 254, 190, 126, 161, 149, 0, 8]),
}
};
19 changes: 0 additions & 19 deletions test/fixtures/wpt/WebCryptoAPI/derive_bits_keys/ecdh_bits.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,25 +55,6 @@ function define_tests() {
});
}, namedCurve + " mixed case parameters");

// Null length
// "Null" is not valid per the current spec
// - https://github.com/w3c/webcrypto/issues/322
// - https://github.com/w3c/webcrypto/issues/329
//
// Proposal for a spec change:
// - https://github.com/w3c/webcrypto/pull/345
//
// This test case may be replaced by these new tests:
// - https://github.com/web-platform-tests/wpt/pull/43400
promise_test(function(test) {
return subtle.deriveBits({name: "ECDH", public: publicKeys[namedCurve]}, privateKeys[namedCurve], null)
.then(function(derivation) {
assert_true(equalBuffers(derivation, derivations[namedCurve]), "Derived correct bits");
}, function(err) {
assert_unreached("deriveBits failed with error " + err.name + ": " + err.message);
});
}, namedCurve + " with null length");

// Shorter than entire derivation per algorithm
promise_test(function(test) {
return subtle.deriveBits({name: "ECDH", public: publicKeys[namedCurve]}, privateKeys[namedCurve], 8 * sizes[namedCurve] - 32)
Expand Down
19 changes: 0 additions & 19 deletions test/fixtures/wpt/WebCryptoAPI/derive_bits_keys/hkdf.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,25 +139,6 @@ function define_tests() {
});
}, testName + " with missing info");

// length null (OperationError)
// "Null" is not valid per the current spec
// - https://github.com/w3c/webcrypto/issues/322
// - https://github.com/w3c/webcrypto/issues/329
//
// Proposal for a spec change:
// - https://github.com/w3c/webcrypto/pull/345
//
// This test case may be replaced by these new tests:
// - https://github.com/web-platform-tests/wpt/pull/43400
subsetTest(promise_test, function(test) {
return subtle.deriveBits(algorithm, baseKeys[derivedKeySize], null)
.then(function(derivation) {
assert_unreached("null length should have thrown an OperationError");
}, function(err) {
assert_equals(err.name, "OperationError", "deriveBits with null length correctly threw OperationError: " + err.message);
});
}, testName + " with null length");

// length not multiple of 8 (OperationError)
subsetTest(promise_test, function(test) {
return subtle.deriveBits(algorithm, baseKeys[derivedKeySize], 44)
Expand Down
20 changes: 0 additions & 20 deletions test/fixtures/wpt/WebCryptoAPI/derive_bits_keys/pbkdf2.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,26 +103,6 @@ function define_tests() {

});

// Test various error conditions for deriveBits below:
// length null (OperationError)
// "Null" is not valid per the current spec
// - https://github.com/w3c/webcrypto/issues/322
// - https://github.com/w3c/webcrypto/issues/329
//
// Proposal for a spec change:
// - https://github.com/w3c/webcrypto/pull/345
//
// This test case may be replaced by these new tests:
// - https://github.com/web-platform-tests/wpt/pull/43400
subsetTest(promise_test, function(test) {
return subtle.deriveBits({name: "PBKDF2", salt: salts[saltSize], hash: hashName, iterations: parseInt(iterations)}, baseKeys[passwordSize], null)
.then(function(derivation) {
assert_unreached("null length should have thrown an OperationError");
}, function(err) {
assert_equals(err.name, "OperationError", "deriveBits with null length correctly threw OperationError: " + err.message);
});
}, testName + " with null length");

// 0 length (OperationError)
subsetTest(promise_test, function(test) {
return subtle.deriveBits({name: "PBKDF2", salt: salts[saltSize], hash: hashName, iterations: parseInt(iterations)}, baseKeys[passwordSize], 0)
Expand Down
17 changes: 17 additions & 0 deletions test/fixtures/wpt/WebCryptoAPI/getRandomValues.any.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
// Step 1.
test(function() {
assert_throws_dom("TypeMismatchError", function() {
self.crypto.getRandomValues(new Float16Array(6))
}, "Float16Array")

assert_throws_dom("TypeMismatchError", function() {
const len = 65536 / Float16Array.BYTES_PER_ELEMENT + 1;
self.crypto.getRandomValues(new Float16Array(len));
}, "Float16Array (too long)")
}, "Float16 arrays");

test(function() {
assert_throws_dom("TypeMismatchError", function() {
self.crypto.getRandomValues(new Float32Array(6))
Expand Down Expand Up @@ -57,4 +68,10 @@ for (const array of arrays) {
test(function() {
assert_true(self.crypto.getRandomValues(new ctor(0)).length == 0)
}, "Null arrays: " + array);

test(function() {
class Buffer extends ctor {}
// Must not throw for the test to pass
self.crypto.getRandomValues(new Buffer(256));
}, "Subclass of " + array);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// META: title=WebCryptoAPI: Assure promise returned by importKey is settled.
// META: timeout=long
// META: script=/common/gc.js

'use strict';

promise_test(async () => {
const jwkKey = {};
const extractable = true;
crypto.subtle.importKey("jwk", jwkKey, {name: "UNSUPPORTED", hash: "SHA-224"}, extractable, []).then(
() => { assert_unreached("Unsupported algorithm should cause promise rejection")},
(err) => {
assert_equals(err.name, "NotSupportedError");
});
await garbageCollect();
})

Loading

0 comments on commit 2b43487

Please sign in to comment.