diff options
Diffstat (limited to 'dom/crypto/test/test_WebCrypto_Wrap_Unwrap.html')
-rw-r--r-- | dom/crypto/test/test_WebCrypto_Wrap_Unwrap.html | 443 |
1 files changed, 443 insertions, 0 deletions
diff --git a/dom/crypto/test/test_WebCrypto_Wrap_Unwrap.html b/dom/crypto/test/test_WebCrypto_Wrap_Unwrap.html new file mode 100644 index 0000000000..dcd040643d --- /dev/null +++ b/dom/crypto/test/test_WebCrypto_Wrap_Unwrap.html @@ -0,0 +1,443 @@ +<!DOCTYPE html> +<html> + +<head> +<title>WebCrypto Test Suite</title> +<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> +<link rel="stylesheet" href="./test_WebCrypto.css"/> +<script src="/tests/SimpleTest/SimpleTest.js"></script> + +<!-- Utilities for manipulating ABVs --> +<script src="util.js"></script> + +<!-- A simple wrapper around IndexedDB --> +<script src="simpledb.js"></script> + +<!-- Test vectors drawn from the literature --> +<script src="./test-vectors.js"></script> + +<!-- General testing framework --> +<script src="./test-array.js"></script> + +<script>/* <![CDATA[*/ +"use strict"; + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "Key wrap known answer, using AES-GCM", + function() { + var that = this; + var alg = { + name: "AES-GCM", + iv: tv.key_wrap_known_answer.wrapping_iv, + tagLength: 128, + }; + var key, wrappingKey; + + function doImport(k) { + wrappingKey = k; + return crypto.subtle.importKey("raw", tv.key_wrap_known_answer.key, + alg, true, ["encrypt", "decrypt"]); + } + function doWrap(k) { + key = k; + return crypto.subtle.wrapKey("raw", key, wrappingKey, alg); + } + + crypto.subtle.importKey("raw", tv.key_wrap_known_answer.wrapping_key, + alg, false, ["wrapKey"]) + .then(doImport, error(that)) + .then(doWrap, error(that)) + .then( + memcmp_complete(that, tv.key_wrap_known_answer.wrapped_key), + error(that) + ); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "Key wrap failing on non-extractable key", + function() { + var that = this; + var alg = { + name: "AES-GCM", + iv: tv.key_wrap_known_answer.wrapping_iv, + tagLength: 128, + }; + var key, wrappingKey; + + function doImport(k) { + wrappingKey = k; + return crypto.subtle.importKey("raw", tv.key_wrap_known_answer.key, + alg, false, ["encrypt", "decrypt"]); + } + function doWrap(k) { + key = k; + return crypto.subtle.wrapKey("raw", key, wrappingKey, alg); + } + + crypto.subtle.importKey("raw", tv.key_wrap_known_answer.wrapping_key, + alg, false, ["wrapKey"]) + .then(doImport, error(that)) + .then(doWrap, error(that)) + .then( + error(that), + complete(that) + ); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "Key unwrap known answer, using AES-GCM", + function() { + var that = this; + var alg = { + name: "AES-GCM", + iv: tv.key_wrap_known_answer.wrapping_iv, + tagLength: 128, + }; + var wrappingKey; + + function doUnwrap(k) { + wrappingKey = k; + return crypto.subtle.unwrapKey( + "raw", tv.key_wrap_known_answer.wrapped_key, + wrappingKey, alg, + "AES-GCM", true, ["encrypt", "decrypt"] + ); + } + function doExport(k) { + return crypto.subtle.exportKey("raw", k); + } + + crypto.subtle.importKey("raw", tv.key_wrap_known_answer.wrapping_key, + alg, false, ["unwrapKey"]) + .then(doUnwrap, error(that)) + .then(doExport, error(that)) + .then( + memcmp_complete(that, tv.key_wrap_known_answer.key), + error(that) + ); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "Key wrap/unwrap round-trip, using RSA-OAEP", + function() { + var that = this; + var oaep = { + name: "RSA-OAEP", + hash: "SHA-256", + }; + var gcm = { + name: "AES-GCM", + iv: tv.aes_gcm_enc.iv, + additionalData: tv.aes_gcm_enc.adata, + tagLength: 128, + }; + var unwrapKey; + + function doWrap(keys) { + var originalKey = keys[0]; + var wrapKey = keys[1]; + unwrapKey = keys[2]; + return crypto.subtle.wrapKey("raw", originalKey, wrapKey, oaep); + } + function doUnwrap(wrappedKey) { + return crypto.subtle.unwrapKey("raw", wrappedKey, unwrapKey, oaep, + gcm, false, ["encrypt"]); + } + function doEncrypt(aesKey) { + return crypto.subtle.encrypt(gcm, aesKey, tv.aes_gcm_enc.data); + } + + // 1.Import: + // -> HMAC key + // -> OAEP wrap key (public) + // -> OAEP unwrap key (private) + // 2. Wrap the HMAC key + // 3. Unwrap it + // 4. Compute HMAC + // 5. Check HMAC value + Promise.all([ + crypto.subtle.importKey("raw", tv.aes_gcm_enc.key, gcm, true, ["encrypt"]), + crypto.subtle.importKey("spki", tv.rsaoaep.spki, oaep, true, ["wrapKey"]), + crypto.subtle.importKey("pkcs8", tv.rsaoaep.pkcs8, oaep, false, ["unwrapKey"]), + ]) + .then(doWrap, error(that)) + .then(doUnwrap, error(that)) + .then(doEncrypt, error(that)) + .then( + memcmp_complete(that, tv.aes_gcm_enc.result), + error(that) + ); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "HMAC JWK wrap/unwrap round-trip, with AES-GCM", + function() { + var that = this; + var genAlg = { name: "HMAC", hash: "SHA-384", length: 512 }; + var wrapAlg = { name: "AES-GCM", iv: tv.aes_gcm_enc.iv }; + var wrapKey, originalKey, originalKeyJwk; + + function doExport(k) { + return crypto.subtle.exportKey("jwk", k); + } + function doWrap() { + return crypto.subtle.wrapKey("jwk", originalKey, wrapKey, wrapAlg); + } + function doUnwrap(wrappedKey) { + return crypto.subtle.unwrapKey("jwk", wrappedKey, wrapKey, wrapAlg, + { name: "HMAC", hash: "SHA-384"}, + true, ["sign", "verify"]); + } + + Promise.all([ + crypto.subtle.importKey("jwk", tv.aes_gcm_enc.key_jwk, + "AES-GCM", false, ["wrapKey", "unwrapKey"]) + .then(function(x) { wrapKey = x; }), + crypto.subtle.generateKey(genAlg, true, ["sign", "verify"]) + .then(function(x) { originalKey = x; return x; }) + .then(doExport) + .then(function(x) { originalKeyJwk = x; }), + ]) + .then(doWrap) + .then(doUnwrap) + .then(doExport) + .then( + complete(that, function(x) { + return exists(x.k) && x.k == originalKeyJwk.k; + }), + error(that) + ); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "ECDSA private JWK wrap/unwrap round-trip, with AES-GCM", + function() { + var that = this; + var genAlg = { name: "ECDSA", namedCurve: "P-256" }; + var wrapAlg = { name: "AES-GCM", iv: tv.aes_gcm_enc.iv }; + var wrapKey, originalKey, originalKeyJwk; + + function doExport(k) { + return crypto.subtle.exportKey("jwk", k); + } + function doWrap() { + return crypto.subtle.wrapKey("jwk", originalKey, wrapKey, wrapAlg); + } + function doUnwrap(wrappedKey) { + return crypto.subtle.unwrapKey("jwk", wrappedKey, wrapKey, wrapAlg, + genAlg, true, ["sign"]); + } + + Promise.all([ + crypto.subtle.importKey("jwk", tv.aes_gcm_enc.key_jwk, + "AES-GCM", false, ["wrapKey", "unwrapKey"]) + .then(function(x) { wrapKey = x; }), + crypto.subtle.generateKey(genAlg, true, ["sign", "verify"]) + .then(function(x) { originalKey = x.privateKey; return x.privateKey; }) + .then(doExport) + .then(function(x) { originalKeyJwk = x; }), + ]) + .then(doWrap) + .then(doUnwrap) + .then(doExport) + .then( + complete(that, function(x) { + return (x.kty == originalKeyJwk.kty) && + (x.crv == originalKeyJwk.crv) && + (x.d == originalKeyJwk.d) && + (x.x == originalKeyJwk.x) && + (x.y == originalKeyJwk.y); + }), + error(that) + ); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "AES-KW known answer", + function() { + var that = this; + + function doWrap(keys) { + var wrapKey = keys[0]; + var originalKey = keys[1]; + return crypto.subtle.wrapKey("raw", originalKey, wrapKey, "AES-KW"); + } + + Promise.all([ + crypto.subtle.importKey("jwk", tv.aes_kw.wrapping_key, + "AES-KW", false, ["wrapKey"]), + crypto.subtle.importKey("jwk", tv.aes_kw.key, + "AES-GCM", true, ["encrypt"]), + ]) + .then(doWrap) + .then( + memcmp_complete(that, tv.aes_kw.wrapped_key), + error(that) + ); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "AES-KW unwrap failure on tampered key data", + function() { + var that = this; + var tamperedWrappedKey = new Uint8Array(tv.aes_kw.wrapped_key); + tamperedWrappedKey[5] ^= 0xFF; + + function doUnwrap(wrapKey) { + return crypto.subtle.unwrapKey("raw", tamperedWrappedKey, wrapKey, + "AES-KW", "AES-GCM", + true, ["encrypt", "decrypt"]); + } + + crypto.subtle.importKey("jwk", tv.aes_kw.wrapping_key, + "AES-KW", false, ["unwrapKey"]) + .then(doUnwrap) + .then(error(that), complete(that)); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "AES-KW unwrap AES-KW key data", + function() { + var that = this; + var wrappedKey = new Uint8Array(tv.aes_kw.wrapped_key); + + function doUnwrap(wrapKey) { + return crypto.subtle.unwrapKey("raw", wrappedKey, wrapKey, + "AES-KW", "AES-KW", + true, ["wrapKey", "unwrapKey"]); + } + + crypto.subtle.importKey("jwk", tv.aes_kw.wrapping_key, + "AES-KW", false, ["unwrapKey"]) + .then(doUnwrap) + .then( + memcmp_complete(that, tv.aes_kw.key), + error(that) + ); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "AES-KW wrap/unwrap round-trip", + function() { + var that = this; + var genAlg = { name: "HMAC", hash: "SHA-384", length: 512 }; + var wrapKey, originalKey, originalKeyJwk; + + function doExport(k) { + return crypto.subtle.exportKey("jwk", k); + } + function doWrap() { + return crypto.subtle.wrapKey("raw", originalKey, wrapKey, "AES-KW"); + } + function doUnwrap(wrappedKey) { + return crypto.subtle.unwrapKey("raw", wrappedKey, wrapKey, + "AES-KW", { name: "HMAC", hash: "SHA-384"}, + true, ["sign", "verify"]); + } + + Promise.all([ + crypto.subtle.importKey("jwk", tv.aes_kw.wrapping_key, + "AES-KW", false, ["wrapKey", "unwrapKey"]) + .then(function(x) { wrapKey = x; }), + crypto.subtle.generateKey(genAlg, true, ["sign"]) + .then(function(x) { originalKey = x; return x; }) + .then(doExport) + .then(function(x) { originalKeyJwk = x; }), + ]) + .then(doWrap) + .then(doUnwrap) + .then(doExport) + .then( + complete(that, function(x) { + return exists(x.k) && x.k == originalKeyJwk.k; + }), + error(that) + ); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( + "JWK unwrap attempt on bogus data should error out", + function() { + // Largely cribbed from the "JWK wrap/unwrap round-trip, with AES-GCM" test + var that = this; + var wrapAlg = { name: "AES-GCM", iv: tv.aes_gcm_enc.iv }; + var wrapKey; + + function doBogusWrap() { + var abv = new TextEncoder().encode("I am so not JSON"); + return crypto.subtle.encrypt(wrapAlg, wrapKey, abv); + } + function doUnwrap(wrappedKey) { + return crypto.subtle.unwrapKey("jwk", wrappedKey, wrapKey, wrapAlg, + {name: "HMAC", hash: "SHA-384"}, + true, ["sign", "verify"]); + } + + crypto.subtle.importKey("jwk", tv.aes_gcm_enc.key_jwk, + "AES-GCM", false, ["encrypt", "unwrapKey"]) + .then(function(x) { wrapKey = x; }) + .then(doBogusWrap, error(that)) + .then(doUnwrap, error(that)) + .then( + error(that), + complete(that) + ); + } +); + +/* ]]>*/</script> +</head> + +<body> + +<div id="content"> + <div id="head"> + <b>Web</b>Crypto<br> + </div> + + <div id="start" onclick="start();">RUN ALL</div> + + <div id="resultDiv" class="content"> + Summary: + <span class="pass"><span id="passN">0</span> passed, </span> + <span class="fail"><span id="failN">0</span> failed, </span> + <span class="pending"><span id="pendingN">0</span> pending.</span> + <br/> + <br/> + + <table id="results"> + <tr> + <th>Test</th> + <th>Result</th> + <th>Time</th> + </tr> + </table> + + </div> + + <div id="foot"></div> +</div> + +</body> +</html> |