Skip to content

Commit a2e5126

Browse files
panvadanielleadams
authored andcommitted
test,crypto: update WebCryptoAPI WPT
PR-URL: #45569 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de>
1 parent b999983 commit a2e5126

13 files changed

+847
-30
lines changed

test/fixtures/wpt/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Last update:
3131
- user-timing: https://github.com/web-platform-tests/wpt/tree/df24fb604e/user-timing
3232
- wasm/jsapi: https://github.com/web-platform-tests/wpt/tree/d8dbe6990b/wasm/jsapi
3333
- wasm/webapi: https://github.com/web-platform-tests/wpt/tree/fd1b23eeaa/wasm/webapi
34-
- WebCryptoAPI: https://github.com/web-platform-tests/wpt/tree/0042d42ee6/WebCryptoAPI
34+
- WebCryptoAPI: https://github.com/web-platform-tests/wpt/tree/21ccdcd814/WebCryptoAPI
3535
- webidl/ecmascript-binding/es-exceptions: https://github.com/web-platform-tests/wpt/tree/a370aad338/webidl/ecmascript-binding/es-exceptions
3636

3737
[Web Platform Tests]: https://github.com/web-platform-tests/wpt
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
function run_test(algorithmNames) {
2+
var subtle = crypto.subtle; // Change to test prefixed implementations
3+
4+
setup({explicit_timeout: true});
5+
6+
// These tests check that importKey and exportKey throw an error, and that
7+
// the error is of the right type, for a wide set of incorrect parameters.
8+
9+
// Error testing occurs by setting the parameter that should trigger the
10+
// error to an invalid value, then combining that with all valid
11+
// parameters that should be checked earlier by importKey, and all
12+
// valid and invalid parameters that should be checked later by
13+
// importKey.
14+
//
15+
// There are a lot of combinations of possible parameters for both
16+
// success and failure modes, resulting in a very large number of tests
17+
// performed.
18+
19+
20+
var allTestVectors = [ // Parameters that should work for importKey / exportKey
21+
{name: "Ed25519", privateUsages: ["sign"], publicUsages: ["verify"]},
22+
{name: "Ed448", privateUsages: ["sign"], publicUsages: ["verify"]},
23+
{name: "X25519", privateUsages: ["deriveKey", "deriveBits"], publicUsages: []},
24+
{name: "X448", privateUsages: ["deriveKey", "deriveBits"], publicUsages: []},
25+
];
26+
27+
var testVectors = [];
28+
if (algorithmNames && !Array.isArray(algorithmNames)) {
29+
algorithmNames = [algorithmNames];
30+
};
31+
allTestVectors.forEach(function(vector) {
32+
if (!algorithmNames || algorithmNames.includes(vector.name)) {
33+
testVectors.push(vector);
34+
}
35+
});
36+
37+
function parameterString(format, algorithm, extractable, usages, data) {
38+
if (typeof algorithm !== "object" && typeof algorithm !== "string") {
39+
alert(algorithm);
40+
}
41+
42+
var jwk_label = "";
43+
if (format === "jwk")
44+
jwk_label = data.d === undefined ? " (public) " : "(private)";
45+
46+
var result = "(" +
47+
objectToString(format) + jwk_label + ", " +
48+
objectToString(algorithm) + ", " +
49+
objectToString(extractable) + ", " +
50+
objectToString(usages) +
51+
")";
52+
53+
return result;
54+
}
55+
56+
// Test that a given combination of parameters results in an error,
57+
// AND that it is the correct kind of error.
58+
//
59+
// Expected error is either a number, tested against the error code,
60+
// or a string, tested against the error name.
61+
function testError(format, algorithm, keyData, keySize, usages, extractable, expectedError, testTag) {
62+
promise_test(async() => {
63+
let key;
64+
try {
65+
key = await subtle.importKey(format, keyData, algorithm, extractable, usages);
66+
} catch(err) {
67+
let actualError = typeof expectedError === "number" ? err.code : err.name;
68+
assert_equals(actualError, expectedError, testTag + " not supported.");
69+
}
70+
assert_equals(key, undefined, "Operation succeeded, but should not have.");
71+
}, testTag + ": importKey" + parameterString(format, algorithm, extractable, usages, keyData));
72+
}
73+
74+
// Don't create an exhaustive list of all invalid usages,
75+
// because there would usually be nearly 2**8 of them,
76+
// way too many to test. Instead, create every singleton
77+
// of an illegal usage, and "poison" every valid usage
78+
// with an illegal one.
79+
function invalidUsages(validUsages, mandatoryUsages) {
80+
var results = [];
81+
82+
var illegalUsages = [];
83+
["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey", "deriveKey", "deriveBits"].forEach(function(usage) {
84+
if (!validUsages.includes(usage)) {
85+
illegalUsages.push(usage);
86+
}
87+
});
88+
89+
var goodUsageCombinations = validUsages.length === 0 ? [] : allValidUsages(validUsages, false, mandatoryUsages);
90+
91+
illegalUsages.forEach(function(illegalUsage) {
92+
results.push([illegalUsage]);
93+
goodUsageCombinations.forEach(function(usageCombination) {
94+
results.push(usageCombination.concat([illegalUsage]));
95+
});
96+
});
97+
98+
return results;
99+
}
100+
101+
function validUsages(usages, format, data) {
102+
if (format === 'spki') return usages.publicUsages
103+
if (format === 'pkcs8') return usages.privateUsages
104+
if (format === 'jwk') {
105+
if (data === undefined)
106+
return [];
107+
return data.d === undefined ? usages.publicUsages : usages.privateUsages;
108+
}
109+
return [];
110+
}
111+
112+
// Now test for properly handling errors
113+
// - Unsupported algorithm
114+
// - Bad usages for algorithm
115+
// - Bad key lengths
116+
// - Lack of a mandatory format field
117+
// - Incompatible keys pair
118+
119+
// Algorithms normalize okay, but usages bad (though not empty).
120+
// It shouldn't matter what other extractable is. Should fail
121+
// due to SyntaxError
122+
testVectors.forEach(function(vector) {
123+
var name = vector.name;
124+
validKeyData.forEach(function(test) {
125+
allAlgorithmSpecifiersFor(name).forEach(function(algorithm) {
126+
invalidUsages(validUsages(vector, test.format, test.data)).forEach(function(usages) {
127+
[true, false].forEach(function(extractable) {
128+
testError(test.format, algorithm, test.data, name, usages, extractable, "SyntaxError", "Bad usages");
129+
});
130+
});
131+
});
132+
});
133+
});
134+
135+
// Algorithms normalize okay, usages ok. The length of the key must thouw a DataError exception.
136+
testVectors.forEach(function(vector) {
137+
var name = vector.name;
138+
badKeyLengthData.forEach(function(test) {
139+
allAlgorithmSpecifiersFor(name).forEach(function(algorithm) {
140+
allValidUsages(validUsages(vector, test.format, test.data)).forEach(function(usages) {
141+
[true, false].forEach(function(extractable) {
142+
testError(test.format, algorithm, test.data, name, usages, extractable, "DataError", "Bad key length");
143+
});
144+
});
145+
});
146+
});
147+
});
148+
149+
// Algorithms normalize okay, usages ok and valid key. The lack of the mandatory JWK parameter must throw a syntax error.
150+
testVectors.forEach(function(vector) {
151+
var name = vector.name;
152+
missingJWKFieldKeyData.forEach(function(test) {
153+
allAlgorithmSpecifiersFor(name).forEach(function(algorithm) {
154+
allValidUsages(validUsages(vector, 'jwk', test.data)).forEach(function(usages) {
155+
[true, false].forEach(function(extractable) {
156+
testError('jwk', algorithm, test.data, name, usages, extractable, "DataError", "Missing JWK '" + test.param + "' parameter");
157+
});
158+
});
159+
});
160+
});
161+
});
162+
163+
// Algorithms normalize okay, usages ok and valid key. The public key is not compatible with the private key.
164+
testVectors.forEach(function(vector) {
165+
var name = vector.name;
166+
invalidJWKKeyData.forEach(function(data) {
167+
allAlgorithmSpecifiersFor(name).forEach(function(algorithm) {
168+
allValidUsages(vector.privateUsages).forEach(function(usages) {
169+
[true].forEach(function(extractable) {
170+
testError('jwk', algorithm, data, name, usages, extractable, "DataError", "Invalid key pair");
171+
});
172+
});
173+
});
174+
});
175+
});
176+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// META: title=WebCryptoAPI: importKey() for Failures
2+
// META: timeout=long
3+
// META: script=../util/helpers.js
4+
// META: script=okp_importKey_failures.js
5+
6+
// Setup: define the correct behaviors that should be sought, and create
7+
// helper functions that generate all possible test parameters for
8+
// different situations.
9+
var validKeyData = [
10+
{
11+
format: "spki",
12+
data: new Uint8Array([48, 42, 48, 5, 6, 3, 43, 101, 112, 3, 33, 0, 216, 225, 137, 99, 216, 9, 212, 135, 217, 84, 154, 204, 174, 198, 116, 46, 126, 235, 162, 77, 138, 13, 59, 20, 183, 227, 202, 234, 6, 137, 61, 204])
13+
},
14+
{
15+
format: "pkcs8",
16+
data: new Uint8Array([48, 46, 2, 1, 0, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32, 243, 200, 244, 196, 141, 248, 120, 20, 110, 140, 211, 191, 109, 244, 229, 14, 56, 155, 167, 7, 78, 21, 194, 53, 45, 205, 93, 48, 141, 76, 168, 31])
17+
},
18+
{
19+
format: "jwk",
20+
data: {
21+
crv: "Ed25519",
22+
d: "88j0xI34eBRujNO_bfTlDjibpwdOFcI1Lc1dMI1MqB8",
23+
x: "2OGJY9gJ1IfZVJrMrsZ0Ln7rok2KDTsUt-PK6gaJPcw",
24+
kty: "OKP"
25+
},
26+
},
27+
{
28+
format: "jwk",
29+
data: {
30+
crv: "Ed25519",
31+
x: "2OGJY9gJ1IfZVJrMrsZ0Ln7rok2KDTsUt-PK6gaJPcw",
32+
kty: "OKP"
33+
},
34+
},
35+
];
36+
37+
// Removed just the last byte.
38+
var badKeyLengthData = [
39+
{
40+
format: "spki",
41+
data: new Uint8Array([48, 42, 48, 5, 6, 3, 43, 101, 112, 3, 33, 0, 216, 225, 137, 99, 216, 9, 212, 135, 217, 84, 154, 204, 174, 198, 116, 46, 126, 235, 162, 77, 138, 13, 59, 20, 183, 227, 202, 234, 6, 137, 61])
42+
},
43+
{
44+
format: "pkcs8",
45+
data: new Uint8Array([48, 46, 2, 1, 0, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32, 243, 200, 244, 196, 141, 248, 120, 20, 110, 140, 211, 191, 109, 244, 229, 14, 56, 155, 167, 7, 78, 21, 194, 53, 45, 205, 93, 48, 141, 76, 168])
46+
},
47+
{
48+
format: "jwk",
49+
data: {
50+
crv: "Ed25519",
51+
d: "88j0xI34eBRujNO_bfTlDjibpwdOFcI1Lc1dMI1MqB",
52+
x: "2OGJY9gJ1IfZVJrMrsZ0Ln7rok2KDTsUt-PK6gaJPcw",
53+
kty: "OKP"
54+
}
55+
},
56+
{
57+
format: "jwk",
58+
data: {
59+
crv: "Ed25519",
60+
x: "2OGJY9gJ1IfZVJrMrsZ0Ln7rok2KDTsUt-PK6gaJPc",
61+
kty: "OKP"
62+
}
63+
},
64+
];
65+
66+
var missingJWKFieldKeyData = [
67+
{
68+
param: "x",
69+
data: {
70+
crv: "Ed25519",
71+
d: "88j0xI34eBRujNO_bfTlDjibpwdOFcI1Lc1dMI1MqB8",
72+
kty: "OKP"
73+
},
74+
},
75+
{
76+
param: "kty",
77+
data: {
78+
crv: "Ed25519",
79+
x: "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo",
80+
d: "88j0xI34eBRujNO_bfTlDjibpwdOFcI1Lc1dMI1MqB8",
81+
},
82+
},
83+
{
84+
param: "crv",
85+
data: {
86+
x: "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo",
87+
kty: "OKP"
88+
},
89+
}
90+
];
91+
92+
// The public key doesn't match the private key.
93+
var invalidJWKKeyData = [
94+
{
95+
crv: "Ed25519",
96+
d: "88j0xI34eBRujNO_bfTlDjibpwdOFcI1Lc1dMI1MqB8",
97+
x: "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo",
98+
kty: "OKP"
99+
},
100+
];
101+
102+
run_test(["Ed25519"]);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// META: title=WebCryptoAPI: importKey() for Failures
2+
// META: timeout=long
3+
// META: script=../util/helpers.js
4+
// META: script=okp_importKey_failures.js
5+
6+
// Setup: define the correct behaviors that should be sought, and create
7+
// helper functions that generate all possible test parameters for
8+
// different situations.
9+
var validKeyData = [
10+
{
11+
format: "spki",
12+
data: new Uint8Array([48, 67, 48, 5, 6, 3, 43, 101, 113, 3, 58, 0, 171, 75, 184, 133, 253, 125, 44, 90, 242, 78, 131, 113, 12, 255, 160, 199, 74, 87, 226, 116, 128, 29, 178, 5, 123, 11, 220, 94, 160, 50, 182, 254, 107, 199, 139, 128, 69, 54, 90, 235, 38, 232, 110, 31, 20, 253, 52, 157, 7, 196, 132, 149, 245, 164, 106, 90, 128]),
13+
},
14+
{
15+
format: "pkcs8",
16+
data: new Uint8Array([48, 71, 2, 1, 0, 48, 5, 6, 3, 43, 101, 113, 4, 59, 4, 57, 14, 255, 3, 69, 140, 40, 224, 23, 156, 82, 29, 227, 18, 201, 105, 183, 131, 67, 72, 236, 171, 153, 26, 96, 227, 178, 233, 167, 158, 76, 217, 228, 128, 239, 41, 23, 18, 210, 200, 61, 4, 114, 114, 213, 201, 244, 40, 102, 79, 105, 109, 38, 112, 69, 143, 29, 46]),
17+
},
18+
{
19+
format: "jwk",
20+
data: {
21+
crv: "Ed448",
22+
d: "Dv8DRYwo4BecUh3jEslpt4NDSOyrmRpg47Lpp55M2eSA7ykXEtLIPQRyctXJ9ChmT2ltJnBFjx0u",
23+
x: "q0u4hf19LFryToNxDP-gx0pX4nSAHbIFewvcXqAytv5rx4uARTZa6ybobh8U_TSdB8SElfWkalqA",
24+
kty: "OKP"
25+
},
26+
},
27+
{
28+
format: "jwk",
29+
data: {
30+
crv: "Ed448",
31+
x: "q0u4hf19LFryToNxDP-gx0pX4nSAHbIFewvcXqAytv5rx4uARTZa6ybobh8U_TSdB8SElfWkalqA",
32+
kty: "OKP"
33+
},
34+
},
35+
];
36+
37+
// Removed just the last byte.
38+
var badKeyLengthData = [
39+
{
40+
format: "spki",
41+
data: new Uint8Array([48, 67, 48, 5, 6, 3, 43, 101, 113, 3, 58, 0, 171, 75, 184, 133, 253, 125, 44, 90, 242, 78, 131, 113, 12, 255, 160, 199, 74, 87, 226, 116, 128, 29, 178, 5, 123, 11, 220, 94, 160, 50, 182, 254, 107, 199, 139, 128, 69, 54, 90, 235, 38, 232, 110, 31, 20, 253, 52, 157, 7, 196, 132, 149, 245, 164, 106, 90]),
42+
},
43+
{
44+
format: "pkcs8",
45+
data: new Uint8Array([48, 71, 2, 1, 0, 48, 5, 6, 3, 43, 101, 113, 4, 59, 4, 57, 14, 255, 3, 69, 140, 40, 224, 23, 156, 82, 29, 227, 18, 201, 105, 183, 131, 67, 72, 236, 171, 153, 26, 96, 227, 178, 233, 167, 158, 76, 217, 228, 128, 239, 41, 23, 18, 210, 200, 61, 4, 114, 114, 213, 201, 244, 40, 102, 79, 105, 109, 38, 112, 69, 143, 29]),
46+
},
47+
{
48+
format: "jwk",
49+
data: {
50+
crv: "Ed448",
51+
d: "Dv8DRYwo4BecUh3jEslpt4NDSOyrmRpg47Lpp55M2eSA7ykXEtLIPQRyctXJ9ChmT2ltJnBFjx0",
52+
x: "q0u4hf19LFryToNxDP-gx0pX4nSAHbIFewvcXqAytv5rx4uARTZa6ybobh8U_TSdB8SElfWkalqA",
53+
kty: "OKP"
54+
},
55+
},
56+
{
57+
format: "jwk",
58+
data: {
59+
crv: "Ed448",
60+
x: "q0u4hf19LFryToNxDP-gx0pX4nSAHbIFewvcXqAytv5rx4uARTZa6ybobh8U_TSdB8SElfWkalq",
61+
kty: "OKP"
62+
},
63+
},
64+
];
65+
66+
var missingJWKFieldKeyData = [
67+
{
68+
param: "x",
69+
data: {
70+
crv: "Ed448",
71+
d: "Dv8DRYwo4BecUh3jEslpt4NDSOyrmRpg47Lpp55M2eSA7ykXEtLIPQRyctXJ9ChmT2ltJnBFjx0u",
72+
kty: "OKP"
73+
}
74+
},
75+
{
76+
param: "kty",
77+
data: {
78+
crv: "Ed448",
79+
d: "Dv8DRYwo4BecUh3jEslpt4NDSOyrmRpg47Lpp55M2eSA7ykXEtLIPQRyctXJ9ChmT2ltJnBFjx0u",
80+
x: "q0u4hf19LFryToNxDP-gx0pX4nSAHbIFewvcXqAytv5rx4uARTZa6ybobh8U_TSdB8SElfWkalqA",
81+
}
82+
},
83+
{
84+
param: "crv",
85+
data: {
86+
d: "Dv8DRYwo4BecUh3jEslpt4NDSOyrmRpg47Lpp55M2eSA7ykXEtLIPQRyctXJ9ChmT2ltJnBFjx0u",
87+
x: "q0u4hf19LFryToNxDP-gx0pX4nSAHbIFewvcXqAytv5rx4uARTZa6ybobh8U_TSdB8SElfWkalqA",
88+
kty: "OKP"
89+
}
90+
}
91+
];
92+
93+
// The public key doesn't match the private key.
94+
var invalidJWKKeyData = [
95+
{
96+
crv: "Ed448",
97+
d: "Dv8DRYwo4BecUh3jEslpt4NDSOyrmRpg47Lpp55M2eSA7ykXEtLIPQRyctXJ9ChmT2ltJnBFjx0u",
98+
x: "X9dEm1m0Yf0s54fsYWrUah2hNCSFpw4fig6nXYDpZ3jt8SR2m0bHBhvWeD3x5Q9s0foavq_oJWGA",
99+
kty: "OKP"
100+
},
101+
];
102+
103+
run_test(["Ed448"]);

0 commit comments

Comments
 (0)