Revision 28d63f19babbd14a18a0219acf21362fc5d52dbc authored by Henrik Skupin on 28 March 2018, 18:49:31 UTC, committed by moz-wptsync-bot on 28 March 2018, 18:49:31 UTC
To retrieve links via "link text" or "partial link text" the rendered
content of the element has to be used. This can be the case for CSS
transformations like "uppercase".
bugzilla-url: https://bugzilla.mozilla.org/show_bug.cgi?id=1381519
gecko-commit: 3e204686f1b10441f48435890241dff6706d04dd
gecko-integration-branch: central
gecko-reviewers: ato
1 parent f5b48cf
Raw File
failures.js
function run_test(algorithmNames) {
    var subtle = crypto.subtle; // Change to test prefixed implementations

    setup({explicit_timeout: true});

// These tests check that generateKey throws an error, and that
// the error is of the right type, for a wide set of incorrect parameters.
//
// Error testing occurs by setting the parameter that should trigger the
// error to an invalid value, then combining that with all valid
// parameters that should be checked earlier by generateKey, and all
// valid and invalid parameters that should be checked later by
// generateKey.
//
// There are a lot of combinations of possible parameters for both
// success and failure modes, resulting in a very large number of tests
// performed.


// Setup: define the correct behaviors that should be sought, and create
// helper functions that generate all possible test parameters for
// different situations.

    var allTestVectors = [ // Parameters that should work for generateKey
        {name: "AES-CTR",  resultType: CryptoKey, usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], mandatoryUsages: []},
        {name: "AES-CBC",  resultType: CryptoKey, usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], mandatoryUsages: []},
        {name: "AES-GCM",  resultType: CryptoKey, usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], mandatoryUsages: []},
        {name: "AES-KW",   resultType: CryptoKey, usages: ["wrapKey", "unwrapKey"], mandatoryUsages: []},
        {name: "HMAC",     resultType: CryptoKey, usages: ["sign", "verify"], mandatoryUsages: []},
        {name: "RSASSA-PKCS1-v1_5", resultType: "CryptoKeyPair", usages: ["sign", "verify"], mandatoryUsages: ["sign"]},
        {name: "RSA-PSS",  resultType: "CryptoKeyPair", usages: ["sign", "verify"], mandatoryUsages: ["sign"]},
        {name: "RSA-OAEP", resultType: "CryptoKeyPair", usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], mandatoryUsages: ["decrypt", "unwrapKey"]},
        {name: "ECDSA",    resultType: "CryptoKeyPair", usages: ["sign", "verify"], mandatoryUsages: ["sign"]},
        {name: "ECDH",     resultType: "CryptoKeyPair", usages: ["deriveKey", "deriveBits"], mandatoryUsages: ["deriveKey", "deriveBits"]}
    ];

    var testVectors = [];
    if (algorithmNames && !Array.isArray(algorithmNames)) {
        algorithmNames = [algorithmNames];
    };
    allTestVectors.forEach(function(vector) {
        if (!algorithmNames || algorithmNames.includes(vector.name)) {
            testVectors.push(vector);
        }
    });


    function parameterString(algorithm, extractable, usages) {
        if (typeof algorithm !== "object" && typeof algorithm !== "string") {
            alert(algorithm);
        }

        var result = "(" +
                        objectToString(algorithm) + ", " +
                        objectToString(extractable) + ", " +
                        objectToString(usages) +
                     ")";

        return result;
    }

    // Test that a given combination of parameters results in an error,
    // AND that it is the correct kind of error.
    //
    // Expected error is either a number, tested against the error code,
    // or a string, tested against the error name.
    function testError(algorithm, extractable, usages, expectedError, testTag) {
        promise_test(function(test) {
            return crypto.subtle.generateKey(algorithm, extractable, usages)
            .then(function(result) {
                assert_unreached("Operation succeeded, but should not have");
            }, function(err) {
                if (typeof expectedError === "number") {
                    assert_equals(err.code, expectedError, testTag + " not supported");
                } else {
                    assert_equals(err.name, expectedError, testTag + " not supported");
                }
            });
        }, testTag + ": generateKey" + parameterString(algorithm, extractable, usages));
    }


    // Given an algorithm name, create several invalid parameters.
    function badAlgorithmPropertySpecifiersFor(algorithmName) {
        var results = [];

        if (algorithmName.toUpperCase().substring(0, 3) === "AES") {
            // Specifier properties are name and length
            [64, 127, 129, 255, 257, 512].forEach(function(length) {
                results.push({name: algorithmName, length: length});
            });
        } else if (algorithmName.toUpperCase().substring(0, 3) === "RSA") {
            [new Uint8Array([1]), new Uint8Array([1,0,0])].forEach(function(publicExponent) {
                results.push({name: algorithmName, hash: "SHA-256", modulusLength: 1024, publicExponent: publicExponent});
            });
        } else if (algorithmName.toUpperCase().substring(0, 2) === "EC") {
            ["P-512", "Curve25519"].forEach(function(curveName) {
                results.push({name: algorithmName, namedCurve: curveName});
            });
        }

        return results;
    }


    // Don't create an exhaustive list of all invalid usages,
    // because there would usually be nearly 2**8 of them,
    // way too many to test. Instead, create every singleton
    // of an illegal usage, and "poison" every valid usage
    // with an illegal one.
    function invalidUsages(validUsages, mandatoryUsages) {
        var results = [];

        var illegalUsages = [];
        ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey", "deriveKey", "deriveBits"].forEach(function(usage) {
            if (!validUsages.includes(usage)) {
                illegalUsages.push(usage);
            }
        });

        var goodUsageCombinations = allValidUsages(validUsages, false, mandatoryUsages);

        illegalUsages.forEach(function(illegalUsage) {
            results.push([illegalUsage]);
            goodUsageCombinations.forEach(function(usageCombination) {
                results.push(usageCombination.concat([illegalUsage]));
            });
        });

        return results;
    }


// Now test for properly handling errors
// - Unsupported algorithm
// - Bad usages for algorithm
// - Bad key lengths

    // Algorithm normalization should fail with "Not supported"
    var badAlgorithmNames = [
        "AES",
        {name: "AES"},
        {name: "AES", length: 128},
        {name: "AES-CMAC", length: 128},    // Removed after CR
        {name: "AES-CFB", length: 128},      // Removed after CR
        {name: "HMAC", hash: "MD5"},
        {name: "RSA", hash: "SHA-256", modulusLength: 2048, publicExponent: new Uint8Array([1,0,1])},
        {name: "RSA-PSS", hash: "SHA", modulusLength: 2048, publicExponent: new Uint8Array([1,0,1])},
        {name: "EC", namedCurve: "P521"}
    ];


    // Algorithm normalization failures should be found first
    // - all other parameters can be good or bad, should fail
    //   due to NotSupportedError.
    badAlgorithmNames.forEach(function(algorithm) {
        allValidUsages(["decrypt", "sign", "deriveBits"], true, []) // Small search space, shouldn't matter because should fail before used
        .forEach(function(usages) {
            [false, true, "RED", 7].forEach(function(extractable){
                testError(algorithm, extractable, usages, "NotSupportedError", "Bad algorithm");
            });
        });
    });


    // Algorithms normalize okay, but usages bad (though not empty).
    // It shouldn't matter what other extractable is. Should fail
    // due to SyntaxError
    testVectors.forEach(function(vector) {
        var name = vector.name;

        allAlgorithmSpecifiersFor(name).forEach(function(algorithm) {
            invalidUsages(vector.usages, vector.mandatoryUsages).forEach(function(usages) {
                [true].forEach(function(extractable) {
                    testError(algorithm, extractable, usages, "SyntaxError", "Bad usages");
                });
            });
        });
    });


    // Other algorithm properties should be checked next, so try good
    // algorithm names and usages, but bad algorithm properties next.
    // - Special case: normally bad usage [] isn't checked until after properties,
    //   so it's included in this test case. It should NOT cause an error.
    testVectors.forEach(function(vector) {
        var name = vector.name;
        badAlgorithmPropertySpecifiersFor(name).forEach(function(algorithm) {
            allValidUsages(vector.usages, true, vector.mandatoryUsages)
            .forEach(function(usages) {
                [false, true].forEach(function(extractable) {
                    if (name.substring(0,2) === "EC") {
                        testError(algorithm, extractable, usages, "NotSupportedError", "Bad algorithm property");
                    } else {
                        testError(algorithm, extractable, usages, "OperationError", "Bad algorithm property");
                    }
                });
            });
        });
    });


    // The last thing that should be checked is an empty usages (for secret keys).
    testVectors.forEach(function(vector) {
        var name = vector.name;

        allAlgorithmSpecifiersFor(name).forEach(function(algorithm) {
            var usages = [];
            [false, true].forEach(function(extractable) {
                testError(algorithm, extractable, usages, "SyntaxError", "Empty usages");
            });
        });
    });


}
back to top