| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 69e4fab commit cc19107
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,6 +1,3 @@ | |||
| 1 | - function run_test(algorithmNames) { | ||
| 2 | - var subtle = crypto.subtle; // Change to test prefixed implementations | ||
| 3 | - | ||
| 4 | 1 | // These tests check that generateKey throws an error, and that | |
| 5 | 2 | // the error is of the right type, for a wide set of incorrect parameters. | |
| 6 | 3 | // | |
@@ -19,42 +16,83 @@ function run_test(algorithmNames) { | |||
| 19 | 16 | // helper functions that generate all possible test parameters for | |
| 20 | 17 | // different situations. | |
| 21 | 18 | ||
| 22 | - var testVectors = getGenerateKeyTestVectors(algorithmNames); | ||
| 19 | + function parameterString(algorithm, extractable, usages) { | ||
| 20 | + if (typeof algorithm !== "object" && typeof algorithm !== "string") { | ||
| 21 | + alert(algorithm); | ||
| 22 | + } | ||
| 23 | 23 | ||
| 24 | + var result = "(" + | ||
| 25 | + objectToString(algorithm) + ", " + | ||
| 26 | + objectToString(extractable) + ", " + | ||
| 27 | + objectToString(usages) + | ||
| 28 | + ")"; | ||
| 24 | 29 | ||
| 25 | - function parameterString(algorithm, extractable, usages) { | ||
| 26 | - if (typeof algorithm !== "object" && typeof algorithm !== "string") { | ||
| 27 | - alert(algorithm); | ||
| 28 | - } | ||
| 30 | + return result; | ||
| 31 | + } | ||
| 29 | 32 | ||
| 30 | - var result = "(" + | ||
| 31 | - objectToString(algorithm) + ", " + | ||
| 32 | - objectToString(extractable) + ", " + | ||
| 33 | - objectToString(usages) + | ||
| 34 | - ")"; | ||
| 33 | + // Test that a given combination of parameters results in an error, | ||
| 34 | + // AND that it is the correct kind of error. | ||
| 35 | + // | ||
| 36 | + // Expected error is either a number, tested against the error code, | ||
| 37 | + // or a string, tested against the error name. | ||
| 38 | + function testError(algorithm, extractable, usages, expectedError, testTag) { | ||
| 39 | + promise_test(function(test) { | ||
| 40 | + return crypto.subtle.generateKey(algorithm, extractable, usages) | ||
| 41 | + .then(function(result) { | ||
| 42 | + assert_unreached("Operation succeeded, but should not have"); | ||
| 43 | + }, function(err) { | ||
| 44 | + if (typeof expectedError === "number") { | ||
| 45 | + assert_equals(err.code, expectedError, testTag + " not supported"); | ||
| 46 | + } else { | ||
| 47 | + assert_equals(err.name, expectedError, testTag + " not supported"); | ||
| 48 | + } | ||
| 49 | + }); | ||
| 50 | + }, testTag + ": generateKey" + parameterString(algorithm, extractable, usages)); | ||
| 51 | + } | ||
| 35 | 52 | ||
| 36 | - return result; | ||
| 37 | - } | ||
| 38 | 53 | ||
| 39 | - // Test that a given combination of parameters results in an error, | ||
| 40 | - // AND that it is the correct kind of error. | ||
| 41 | - // | ||
| 42 | - // Expected error is either a number, tested against the error code, | ||
| 43 | - // or a string, tested against the error name. | ||
| 44 | - function testError(algorithm, extractable, usages, expectedError, testTag) { | ||
| 45 | - promise_test(function(test) { | ||
| 46 | - return crypto.subtle.generateKey(algorithm, extractable, usages) | ||
| 47 | - .then(function(result) { | ||
| 48 | - assert_unreached("Operation succeeded, but should not have"); | ||
| 49 | - }, function(err) { | ||
| 50 | - if (typeof expectedError === "number") { | ||
| 51 | - assert_equals(err.code, expectedError, testTag + " not supported"); | ||
| 52 | - } else { | ||
| 53 | - assert_equals(err.name, expectedError, testTag + " not supported"); | ||
| 54 | - } | ||
| 54 | + // Algorithm normalization happens before generateKey looks at any other | ||
| 55 | + // argument, so these cases are independent of the algorithm under test and | ||
| 56 | + // only need to run once for the whole suite. | ||
| 57 | + function run_bad_algorithm_test() { | ||
| 58 | + // Algorithm normalization should fail with "Not supported" | ||
| 59 | + var badAlgorithmNames = [ | ||
| 60 | + "AES", | ||
| 61 | + {name: "AES"}, | ||
| 62 | + {name: "AES", length: 128}, | ||
| 63 | + {name: "AES-CMAC", length: 128}, // Removed after CR | ||
| 64 | + {name: "AES-CFB", length: 128}, // Removed after CR | ||
| 65 | + {name: "HMAC", hash: "MD5"}, | ||
| 66 | + {name: "RSA", hash: "SHA-256", modulusLength: 2048, publicExponent: new Uint8Array([1,0,1])}, | ||
| 67 | + {name: "RSA-PSS", hash: "SHA", modulusLength: 2048, publicExponent: new Uint8Array([1,0,1])}, | ||
| 68 | + {name: "EC", namedCurve: "P521"} | ||
| 69 | + ]; | ||
| 70 | + | ||
| 71 | + | ||
| 72 | + // Algorithm normalization failures should be found first | ||
| 73 | + // - all other parameters can be good or bad, should fail | ||
| 74 | + // due to NotSupportedError. | ||
| 75 | + badAlgorithmNames.forEach(function(algorithm) { | ||
| 76 | + allValidUsages(["decrypt", "sign", "deriveBits"], true, []) // Small search space, shouldn't matter because should fail before used | ||
| 77 | + .forEach(function(usages) { | ||
| 78 | + [false, true, "RED", 7].forEach(function(extractable){ | ||
| 79 | + testError(algorithm, extractable, usages, "NotSupportedError", "Bad algorithm"); | ||
| 55 | 80 | }); | |
| 56 | - }, testTag + ": generateKey" + parameterString(algorithm, extractable, usages)); | ||
| 57 | - } | ||
| 81 | + }); | ||
| 82 | + }); | ||
| 83 | + | ||
| 84 | + // Empty algorithm should fail with TypeError | ||
| 85 | + allValidUsages(["decrypt", "sign", "deriveBits"], true, []) // Small search space, shouldn't matter because should fail before used | ||
| 86 | + .forEach(function(usages) { | ||
| 87 | + [false, true, "RED", 7].forEach(function(extractable){ | ||
| 88 | + testError({}, extractable, usages, "TypeError", "Empty algorithm"); | ||
| 89 | + }); | ||
| 90 | + }); | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + | ||
| 94 | + function run_test(algorithmNames) { | ||
| 95 | + var testVectors = getGenerateKeyTestVectors(algorithmNames); | ||
| 58 | 96 | ||
| 59 | 97 | ||
| 60 | 98 | // Given an algorithm name, create several invalid parameters. | |
@@ -108,45 +146,9 @@ function run_test(algorithmNames) { | |||
| 108 | 146 | ||
| 109 | 147 | ||
| 110 | 148 | // Now test for properly handling errors | |
| 111 | - // - Unsupported algorithm | ||
| 112 | 149 | // - Bad usages for algorithm | |
| 113 | 150 | // - Bad key lengths | |
| 114 | 151 | ||
| 115 | - // Algorithm normalization should fail with "Not supported" | ||
| 116 | - var badAlgorithmNames = [ | ||
| 117 | - "AES", | ||
| 118 | - {name: "AES"}, | ||
| 119 | - {name: "AES", length: 128}, | ||
| 120 | - {name: "AES-CMAC", length: 128}, // Removed after CR | ||
| 121 | - {name: "AES-CFB", length: 128}, // Removed after CR | ||
| 122 | - {name: "HMAC", hash: "MD5"}, | ||
| 123 | - {name: "RSA", hash: "SHA-256", modulusLength: 2048, publicExponent: new Uint8Array([1,0,1])}, | ||
| 124 | - {name: "RSA-PSS", hash: "SHA", modulusLength: 2048, publicExponent: new Uint8Array([1,0,1])}, | ||
| 125 | - {name: "EC", namedCurve: "P521"} | ||
| 126 | - ]; | ||
| 127 | - | ||
| 128 | - | ||
| 129 | - // Algorithm normalization failures should be found first | ||
| 130 | - // - all other parameters can be good or bad, should fail | ||
| 131 | - // due to NotSupportedError. | ||
| 132 | - badAlgorithmNames.forEach(function(algorithm) { | ||
| 133 | - allValidUsages(["decrypt", "sign", "deriveBits"], true, []) // Small search space, shouldn't matter because should fail before used | ||
| 134 | - .forEach(function(usages) { | ||
| 135 | - [false, true, "RED", 7].forEach(function(extractable){ | ||
| 136 | - testError(algorithm, extractable, usages, "NotSupportedError", "Bad algorithm"); | ||
| 137 | - }); | ||
| 138 | - }); | ||
| 139 | - }); | ||
| 140 | - | ||
| 141 | - // Empty algorithm should fail with TypeError | ||
| 142 | - allValidUsages(["decrypt", "sign", "deriveBits"], true, []) // Small search space, shouldn't matter because should fail before used | ||
| 143 | - .forEach(function(usages) { | ||
| 144 | - [false, true, "RED", 7].forEach(function(extractable){ | ||
| 145 | - testError({}, extractable, usages, "TypeError", "Empty algorithm"); | ||
| 146 | - }); | ||
| 147 | - }); | ||
| 148 | - | ||
| 149 | - | ||
| 150 | 152 | // Algorithms normalize okay, but usages bad (though not empty). | |
| 151 | 153 | // It shouldn't matter what other extractable is. Should fail | |
| 152 | 154 | // due to SyntaxError | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,5 @@ | |||
| 1 | + // META: title=WebCryptoAPI: generateKey() for Failures | ||
| 2 | + // META: timeout=long | ||
| 3 | + // META: script=../util/helpers.js | ||
| 4 | + // META: script=failures.js | ||
| 5 | + run_bad_algorithm_test(); | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -110,6 +110,27 @@ function run_test(algorithmNames, slowTest) { | |||
| 110 | 110 | assert_unreached("exportKey threw an unexpected error: " + err.toString()); | |
| 111 | 111 | }) | |
| 112 | 112 | }, testTag + ": generateKey" + parameterString(algorithm, extractable, usages)); | |
| 113 | + | ||
| 114 | + // Special case for ECDH and ECDSA: check that the generated key length is consistent. | ||
| 115 | + // Particularly for P-521, there is a high risk of the generated key being one byte short | ||
| 116 | + // if the implementation isn't careful. | ||
| 117 | + if (algorithm.namedCurve && extractable) { | ||
| 118 | + promise_test(async function(test) { | ||
| 119 | + // We run about 20 variants of this test, times 10 key generations below, | ||
| 120 | + // so this should have a decent chance of catching issues. | ||
| 121 | + await Promise.all(Array.from({ length: 10 }).map(async () => { | ||
| 122 | + const { privateKey, publicKey } = await subtle.generateKey(algorithm, extractable, usages); | ||
| 123 | + const [jwkPub, jwkPriv] = await Promise.all([ | ||
| 124 | + subtle.exportKey('jwk', publicKey), | ||
| 125 | + subtle.exportKey('jwk', privateKey), | ||
| 126 | + ]); | ||
| 127 | + const expectedLength = Math.ceil(Math.ceil(parseInt(algorithm.namedCurve.substring(2)) / 8) * 4/3); | ||
| 128 | + assert_equals(jwkPub.x.length, expectedLength, "Public key value x has correct length"); | ||
| 129 | + assert_equals(jwkPub.y.length, expectedLength, "Public key value y has correct length"); | ||
| 130 | + assert_equals(jwkPriv.d.length, expectedLength, "Private key value d has correct length"); | ||
| 131 | + })); | ||
| 132 | + }, testTag + ": generateKey" + parameterString(algorithm, extractable, usages) + " produces consistent length key"); | ||
| 133 | + } | ||
| 113 | 134 | } | |
| 114 | 135 | ||
| 115 | 136 | // Test all valid sets of parameters for successful | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -96,7 +96,7 @@ | |||
| 96 | 96 | "path": "web-locks" | |
| 97 | 97 | }, | |
| 98 | 98 | "WebCryptoAPI": { | |
| 99 | - "commit": "82c3d9069cf2e93e5528a1f428fa122bd9af651d", | ||
| 99 | + "commit": "4c2fd05ed5d0b90a9e1fcdcb35f6671bd461de0d", | ||
| 100 | 100 | "path": "WebCryptoAPI" | |
| 101 | 101 | }, | |
| 102 | 102 | "webidl": { | |
| Back | FazBrowse Home | New Git URL |
0 commit comments