blob: c867fd469131cdf74412e081145f8debaca699ef [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<script src="../fast/js/resources/js-test-pre.js"></script>
<script src="resources/common.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>
<script>
description("Tests algorithm normalization.");
jsTestIsAsync = true;
// FIXME: Rename this to crypto-operation.html, since it tests the basic
// construction of CryptoOperations.
// -------------------------------
// Helpers to return a normalized algorithm identifier.
// -------------------------------
aesCbcKey = null;
hmacSha1Key = null;
rsaSsaKey = null;
function normalizeDigest(algorithmIdentifier)
{
return crypto.subtle.digest(algorithmIdentifier).algorithm;
}
function normalizeEncrypt(algorithmIdentifier, key)
{
return crypto.subtle.encrypt(algorithmIdentifier, key).algorithm;
}
function normalizeSign(algorithmIdentifier, key)
{
return crypto.subtle.sign(algorithmIdentifier, key).algorithm;
}
function runTests()
{
// -------------------------------
// Case insensitivity of "name"
// -------------------------------
algorithm = normalizeDigest({name: "SHA-1"});
shouldBe("algorithm.name", "'SHA-1'");
algorithm = normalizeDigest({name: "sHa-256"});
shouldBe("algorithm.name", "'SHA-256'");
// -------------------------------
// Failures if "name" is invalid
// -------------------------------
shouldThrow("normalizeDigest({})");
shouldThrow("normalizeDigest({name: null})");
shouldThrow("normalizeDigest({name: -1})");
shouldThrow("normalizeDigest({name: ''})");
shouldThrow("normalizeDigest({name: 'nosuchalgorithm'})");
shouldThrow("normalizeDigest({name: '\\u0189'})");
// -------------------------------
// Failures if the algorithm identifier is not an object
// -------------------------------
shouldThrow("normalizeDigest(null)");
shouldThrow("normalizeDigest(0)");
shouldThrow("normalizeDigest(undefined)");
shouldThrow("normalizeDigest('')");
// -------------------------------
// Skip unrecognized parameters.
// -------------------------------
algorithm = normalizeDigest({name: "sHa-1", noSuchParam: 3});
shouldBeUndefined("algorithm.noSuchParam");
// -------------------------------
// Normalized algorithm COPIES all data
// -------------------------------
originalIv = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
algorithm = normalizeEncrypt({ name: "aes-cbc", iv: originalIv }, aesCbcKey);
// Make sure it constructed the normalized result.
shouldBe("algorithm.name", "'AES-CBC'");
shouldBe("algorithm.iv.length", "16");
shouldBe("algorithm.iv[3]", "3");
// Mutate the original (un-normalized) algorithm. Verify that this doesn't affect the normalized output.
originalIv[3] = 0;
shouldBe("algorithm.iv[3]", "3");
// -------------------------------
// AES-CBC normalization failures
// -------------------------------
// The "iv" MUST be 16 bytes long.
rawAlgorithm = {
name: "AES-CBC",
iv: new Uint8Array([1, 2, 3])
};
shouldThrow("normalizeEncrypt(rawAlgorithm, aesCbcKey)");
// -------------------------------
// Normalize a normalized algorithm (SHA-384)
// -------------------------------
algorithm = normalizeDigest({name: "sHa-384"});
shouldBe("algorithm.name", "'SHA-384'");
algorithm = normalizeDigest(algorithm);
shouldBe("algorithm.name", "'SHA-384'");
// -------------------------------
// Normalize a normalized algorithm (AES-CBC, encrypt)
// -------------------------------
algorithm = normalizeEncrypt({ name: "aEs-cbc", iv: originalIv }, aesCbcKey);
// Make sure it constructed the normalized result.
shouldBe("algorithm.name", "'AES-CBC'");
shouldBe("algorithm.iv.length", "16");
shouldBe("algorithm.iv[1]", "1");
algorithm = normalizeEncrypt(algorithm, aesCbcKey);
shouldBe("algorithm.name", "'AES-CBC'");
shouldBe("algorithm.iv.length", "16");
shouldBe("algorithm.iv[1]", "1");
// -------------------------------
// Unsupported operation on algorithm
// -------------------------------
shouldThrow("normalizeEncrypt({ name: 'SHA-1' }, aesCbcKey)");
shouldThrow("normalizeDigest({ name: 'AES-CBC', iv: originalIv })");
// -------------------------------
// Normalize HMAC
// -------------------------------
shouldThrow("normalizeSign({name: 'hmac'}, hmacSha1Key)"); // Missing "hash"
shouldThrow("normalizeSign({name: 'hmac', hash: 'foo'}, hmacSha1Key)"); // Not a valid "hash"
shouldThrow("normalizeSign({name: 'hmac', hash: { name: 'AES-CBC', iv: originalIv }}, hmacSha1Key)"); // Not a valid "hash"
validHmacSha1 = {name: 'hmac', hash: {name: 'Sha-1'}};
algorithm = normalizeSign(validHmacSha1, hmacSha1Key);
shouldBe("algorithm.name", "'HMAC'");
shouldBe("algorithm.hash.name", "'SHA-1'");
shouldThrow("normalizeEncrypt(validHmacSha1, hmacSha1Key)"); // Not defined for encrypt()
// -------------------------------
// Normalize RSASSA-PKCS1-v1_5
// -------------------------------
shouldThrow("normalizeSign({name: 'RSASSA-PKCS1-v1_5'}, rsaSsaKey)"); // Missing "hash"
shouldThrow("normalizeSign({name: 'RSASSA-PKCS1-v1_5', hash: 'foo'}, rsaSsaKey)"); // Not a valid "hash"
shouldThrow("normalizeSign({name: 'RSASSA-PKCS1-v1_5', hash: { name: 'AES-CBC', iv: originalIv }}, rsaSsaKey)"); // Not a valid "hash"
validRsaSsa = {name: 'RsaSsa-PKCS1-v1_5', hash: {name: 'Sha-256'}};
algorithm = normalizeSign(validRsaSsa, rsaSsaKey);
shouldBe("algorithm.name", "'RSASSA-PKCS1-v1_5'");
shouldBe("algorithm.hash.name", "'SHA-256'");
shouldThrow("normalizeEncrypt(validRsaSsa, rsaSsaKey)"); // Not defined for encrypt()
// FIXME: Test the normalization of RsaSsaKeyGen parameters.
// -------------------------------
// Try using a key for an unsupported operation.
// -------------------------------
algorithmIdentifier = { name: "aes-cbc", iv: originalIv };
shouldThrow("crypto.subtle.encrypt(algorithmIdentifier, aesCbcKeyNoEncrypt)");
// -------------------------------
// Try using an HMAC-SHA1 key for encrypting AES-CBC
// -------------------------------
algorithmIdentifier = { name: "aes-cbc", iv: originalIv };
shouldThrow("crypto.subtle.encrypt(algorithmIdentifier, hmacSha1Key)");
// -------------------------------
// Try using an HMAC-SHA1 key for signing HMAC-SHA256
// -------------------------------
algorithmIdentifier = {name: 'hmac', hash: {name: 'sha-256'}};
shouldThrow("crypto.subtle.sign(algorithmIdentifier, hmacSha1Key)");
}
function importAesCbcKey(keyUsages)
{
var keyFormat = "spki";
var data = new Uint8Array([]);
var algorithm = {name: "aes-cbc"};
var extractable = false;
return crypto.subtle.importKey(keyFormat, data, algorithm, extractable, keyUsages);
}
function importRsaSsaKey()
{
var keyFormat = "spki";
var data = new Uint8Array([]);
var algorithm = {name: "RSASSA-PKCS1-v1_5"};
var extractable = false;
var keyUsages = ["encrypt", "decrypt", "verify", "sign"];
return crypto.subtle.importKey(keyFormat, data, algorithm, extractable, keyUsages);
}
function failedKeyImport(value)
{
debug("Failed importing key: " + value);
finishJSTest();
}
// Import two keys before starting the tests: one for AES-CBC, and one for
// HMAC SHA1.
Promise.every(importAesCbcKey(['encrypt', 'decrypt', 'sign', 'verify']), importAesCbcKey(['decrypt', 'sign', 'verify']), importHmacSha1Key(), importRsaSsaKey()).then(function(keys)
{
aesCbcKey = keys[0];
aesCbcKeyNoEncrypt = keys[1];
hmacSha1Key = keys[2];
rsaSsaKey = keys[3];
runTests();
finishJSTest();
}, failedKeyImport);
</script>
<script src="../fast/js/resources/js-test-post.js"></script>
</body>
</html>