Commit a237529b authored by ap@apple.com's avatar ap@apple.com

Implement key generation and JWK import for RSASSA-PKCS1-v1_5

https://bugs.webkit.org/show_bug.cgi?id=124236

Reviewed by Sam Weinig.

Source/WebCore:

Tests: crypto/subtle/rsassa-pkcs1-v1_5-generate-key.html
       crypto/subtle/rsassa-pkcs1-v1_5-import-jwk.html

* WebCore.xcodeproj/project.pbxproj: Added new files.

* bindings/js/JSCryptoAlgorithmBuilder.cpp:
(WebCore::JSCryptoAlgorithmBuilder::add):
* bindings/js/JSCryptoAlgorithmBuilder.h:
* crypto/CryptoAlgorithmDescriptionBuilder.h:
Added a way to add an Uint8Array, as needed for RSA key.algorithm.publicExponent.

* bindings/js/JSCryptoAlgorithmDictionary.cpp:
(WebCore::createAesCbcParams): Removed unneeded JSC prefixes.
(WebCore::createAesKeyGenParams): Ditto.
(WebCore::createHmacParams): Ditto.
(WebCore::createHmacKeyParams): Ditto.
(WebCore::createRsaKeyGenParams): Added.
(WebCore::createRsaSsaKeyParams): Added. WebCrypto currently doesn't specify any
parameters for importKey, so the structure remains blank (unlike with JWK).
(WebCore::createRsaSsaParams): Added (currently unused, will be sued for sign/verify soon).
(WebCore::JSCryptoAlgorithmDictionary::createParametersForEncrypt): Removed unneeded JSC prefixes.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForDecrypt): Ditto.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForSign): Added support for RSAES_PKCS1_v1_5.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForVerify): Ditto.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForDigest): Removed unneeded JSC prefixes.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForGenerateKey): Ditto.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForDeriveKey): Ditto.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForDeriveBits): Ditto.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForImportKey): Added support for RSAES_PKCS1_v1_5.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForExportKey): Removed unneeded JSC prefixes.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForWrapKey): Ditto.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForUnwrapKey): Ditto.

* bindings/js/JSCryptoKeySerializationJWK.h:
* bindings/js/JSCryptoKeySerializationJWK.cpp:
(WebCore::getJSArrayFromJSON): Added.
(WebCore::getBigIntegerVectorFromJSON): Added.
(WebCore::createRSASSAKeyParameters): Create parameters for key import. The key
will remember which algorithm it's allowed to be used with.
(WebCore::JSCryptoKeySerializationJWK::reconcileAlgorithm): Added support for
RS256...RS512 (tha is, RSAES_PKCS1_v1_5 with SHA-256...SHA-512).
(WebCore::JSCryptoKeySerializationJWK::keyDataOctetSequence): Split out of keyData().
(WebCore::JSCryptoKeySerializationJWK::keyDataRSAComponents): Added code to read
RSA key components from JWK.
(WebCore::JSCryptoKeySerializationJWK::keyData): Call one of the above functions.

* crypto/CryptoAlgorithmRSASSA_PKCS1_v1_5Mac.cpp: Added.
(WebCore::CryptoAlgorithmRSASSA_PKCS1_v1_5::sign):
(WebCore::CryptoAlgorithmRSASSA_PKCS1_v1_5::verify):
Placeholders.

* crypto/CryptoKey.h: (WebCore::CryptoKeyClass): Added RSA key class for poor man's RTTI.

* crypto/CryptoKeyData.h: (WebCore::CryptoKeyData::FormatRSAComponents): Added RSAComponents
for poor man's RTTI.

* crypto/algorithms/CryptoAlgorithmAES_CBC.cpp: (WebCore::CryptoAlgorithmAES_CBC::importKey):
* crypto/algorithms/CryptoAlgorithmHMAC.cpp: (WebCore::CryptoAlgorithmHMAC::importKey):
* crypto/keys/CryptoKeyAES.h:
(WebCore::isCryptoKeyAES):
(WebCore::toCryptoKeyAES):
* crypto/keys/CryptoKeyDataOctetSequence.h:
(WebCore::toCryptoKeyDataOctetSequence):
* crypto/keys/CryptoKeyHMAC.h:
(WebCore::isCryptoKeyHMAC):
(WebCore::toCryptoKeyHMAC):
* crypto/mac/CryptoAlgorithmAES_CBCMac.cpp:
(WebCore::CryptoAlgorithmAES_CBC::encrypt):
(WebCore::CryptoAlgorithmAES_CBC::decrypt):
* crypto/mac/CryptoAlgorithmHMACMac.cpp:
(WebCore::CryptoAlgorithmHMAC::sign):
(WebCore::CryptoAlgorithmHMAC::verify):
Switched from "as" functions to "is" and "to" ones, as that's more idiomatic.

* crypto/algorithms/CryptoAlgorithmRSASSA_PKCS1_v1_5.cpp: Added.
* crypto/algorithms/CryptoAlgorithmRSASSA_PKCS1_v1_5.h: Added.
Glue code for importKey/generateKey for now.

* crypto/keys/CryptoKeyDataRSAComponents.cpp: Added.
(WebCore::CryptoKeyDataRSAComponents::CryptoKeyDataRSAComponents):
(WebCore::CryptoKeyDataRSAComponents::~CryptoKeyDataRSAComponents):
* crypto/keys/CryptoKeyDataRSAComponents.h: Added.
(WebCore::toCryptoKeyDataRSAComponents):
Added a structure to hold RSA key components, extracted from JWK or another format.

* crypto/keys/CryptoKeyRSA.h: Added.
* crypto/mac/CryptoKeyRSAMac.cpp: Added.

* crypto/mac/CryptoAlgorithmRegistryMac.cpp:
(WebCore::CryptoAlgorithmRegistry::platformRegisterAlgorithms):
Register RSASSA_PKCS1_v1_5.

* crypto/parameters/CryptoAlgorithmHmacKeyParams.h: Added a constructor to make
sure that hasLength is never left uninitialized, even when reading formats that
don't contain a length.

* crypto/parameters/CryptoAlgorithmRsaKeyGenParams.h: Added.
* crypto/parameters/CryptoAlgorithmRsaSsaKeyParams.h: Added.
* crypto/parameters/CryptoAlgorithmRsaSsaParams.h: Added.
Added parameter structures that are needed for RSASSA_PKCS1_v1_5.

LayoutTests:

* crypto/subtle/resources/common.js:
(hexToArrayBuffer): Fixed a typo
(Base64URL.stringify):
(Base64URL.parse):
Added helpers to deal with Base64URL, as needed for JWK.

* crypto/subtle/rsassa-pkcs1-v1_5-generate-key-expected.txt: Added.
* crypto/subtle/rsassa-pkcs1-v1_5-generate-key.html: Added.
* crypto/subtle/rsassa-pkcs1-v1_5-import-jwk-expected.txt: Added.
* crypto/subtle/rsassa-pkcs1-v1_5-import-jwk.html: Added.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@159180 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent bb221000
2013-11-13 Alexey Proskuryakov <ap@apple.com>
Implement key generation and JWK import for RSASSA-PKCS1-v1_5
https://bugs.webkit.org/show_bug.cgi?id=124236
Reviewed by Sam Weinig.
* crypto/subtle/resources/common.js:
(hexToArrayBuffer): Fixed a typo
(Base64URL.stringify):
(Base64URL.parse):
Added helpers to deal with Base64URL, as needed for JWK.
* crypto/subtle/rsassa-pkcs1-v1_5-generate-key-expected.txt: Added.
* crypto/subtle/rsassa-pkcs1-v1_5-generate-key.html: Added.
* crypto/subtle/rsassa-pkcs1-v1_5-import-jwk-expected.txt: Added.
* crypto/subtle/rsassa-pkcs1-v1_5-import-jwk.html: Added.
2013-11-12 Alexey Proskuryakov <ap@apple.com>
Disable WebCrypto on Mountain Lion
......
......@@ -48,13 +48,24 @@ function asciiToArrayBuffer(str)
function hexToArrayBuffer(str)
{
if (str.length % 2)
throw "Hex string lenght must be even";
throw "Hex string length must be even";
var chars = [];
for (var i = 0; i < str.length; i += 2)
chars.push(parseInt(str.substr(i, 2), 16));
return new Uint8Array(chars);
}
var Base64URL = {
stringify: function (a) {
var base64string = btoa(String.fromCharCode.apply(0, a));
return base64string.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
},
parse: function (s) {
s = s.replace(/-/g, "+").replace(/_/g, "/").replace(/\s/g, '');
return new Uint8Array(Array.prototype.map.call(atob(s), function (c) { return c.charCodeAt(0) }));
}
};
function printRejectedResult(value)
{
debug(" rejected with value of " + value);
......
Test generating an RSA key pair for RSASSA-PKCS1-v1_5.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
Generating a key pair...
PASS keyPair.toString() is '[object KeyPair]'
PASS keyPair.publicKey.type is 'public'
PASS keyPair.publicKey.algorithm.name is 'rsassa-pkcs1-v1_5'
PASS keyPair.publicKey.algorithm.modulusLength is 2048
PASS byteArrayToHexString(keyPair.publicKey.algorithm.publicExponent) is '[01 00 01]'
PASS keyPair.publicKey.algorithm.hash is undefined.
PASS keyPair.privateKey.type is 'private'
PASS keyPair.privateKey.algorithm.name is 'rsassa-pkcs1-v1_5'
PASS keyPair.privateKey.algorithm.modulusLength is 2048
PASS byteArrayToHexString(keyPair.privateKey.algorithm.publicExponent) is '[01 00 01]'
PASS keyPair.privateKey.algorithm.hash is undefined.
Testing that custom attributes on keys survive garbage collection...
PASS keyPair.publicKey.foo is 'bar'
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE html>
<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
<script src="resources/common.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>
<script>
description("Test generating an RSA key pair for RSASSA-PKCS1-v1_5.");
jsTestIsAsync = true;
if (!window.subtle)
window.crypto.subtle = window.crypto.webkitSubtle;
var algorithmKeyGen = {
name: "RSASSA-PKCS1-v1_5",
// RsaKeyGenParams
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]), // Equivalent to 65537
};
var extractable = true;
debug("Generating a key pair...");
crypto.subtle.generateKey(algorithmKeyGen, extractable, ["sign", "verify"]).then(function(result) {
keyPair = result;
shouldBe("keyPair.toString()", "'[object KeyPair]'");
shouldBe("keyPair.publicKey.type", "'public'");
shouldBe("keyPair.publicKey.algorithm.name", "'rsassa-pkcs1-v1_5'");
shouldBe("keyPair.publicKey.algorithm.modulusLength", "2048");
shouldBe("byteArrayToHexString(keyPair.publicKey.algorithm.publicExponent)", "'[01 00 01]'");
shouldBeUndefined("keyPair.publicKey.algorithm.hash");
shouldBe("keyPair.privateKey.type", "'private'");
shouldBe("keyPair.privateKey.algorithm.name", "'rsassa-pkcs1-v1_5'");
shouldBe("keyPair.privateKey.algorithm.modulusLength", "2048");
shouldBe("byteArrayToHexString(keyPair.privateKey.algorithm.publicExponent)", "'[01 00 01]'");
shouldBeUndefined("keyPair.privateKey.algorithm.hash");
debug("\nTesting that custom attributes on keys survive garbage collection...");
keyPair.publicKey.foo = "bar";
gc();
setTimeout(function() {
gc();
setTimeout(function() {
shouldBe("keyPair.publicKey.foo", "'bar'");
finishJSTest();
}, 0);
}, 0);
});
</script>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>
Test importing an RSA key for RSASSA-PKCS1-v1_5.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
Importing a public key...
PASS publicKey.toString() is '[object Key]'
PASS publicKey.type is 'public'
PASS publicKey.usages is ['sign','verify']
PASS publicKey.algorithm.name is 'rsassa-pkcs1-v1_5'
PASS publicKey.algorithm.modulusLength is 2048
PASS byteArrayToHexString(publicKey.algorithm.publicExponent) is '[01 00 01]'
PASS publicKey.algorithm.hash.name is 'sha-256'
Importing a private key...
PASS privateKey.toString() is '[object Key]'
PASS privateKey.type is 'private'
PASS privateKey.usages is ['sign','verify']
PASS privateKey.algorithm.name is 'rsassa-pkcs1-v1_5'
PASS privateKey.algorithm.modulusLength is 2048
PASS byteArrayToHexString(privateKey.algorithm.publicExponent) is '[01 00 01]'
PASS privateKey.algorithm.hash.name is 'sha-256'
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE html>
<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
<script src="resources/common.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>
<script>
description("Test importing an RSA key for RSASSA-PKCS1-v1_5.");
jsTestIsAsync = true;
if (!window.subtle)
window.crypto.subtle = window.crypto.webkitSubtle;
var extractable = true;
var publicKeyJSON = {
kty: "RSA",
alg: "RS256",
n: "rcCUCv7Oc1HVam1DIhCzqknThWawOp8QLk8Ziy2p10ByjQFCajoFiyuAWl-R1WXZaf4xitLRracT9agpzIzc-MbLSHIGgWQGO21lGiImy5ftZ-D8bHAqRz2y15pzD4c4CEou7XSSLDoRnR0QG5MsDhD6s2gV9mwHkrtkCxtMWdBi-77as8wGmlNRldcOSgZDLK8UnCSgA1OguZ989bFyc8tOOEIb0xUSfPSz3LPSCnyYz68aDjmKVeNH-ig857OScyWbGyEy3Biw64qun3juUlNWsJ3zngkOdteYWytx5Qr4XKNs6R-Myyq72KUp02mJDZiiyiglxML_i3-_CeecCw",
e: "AQAB"
};
var privateKeyJSON = {
kty: "RSA",
alg: "RS256",
n: "rcCUCv7Oc1HVam1DIhCzqknThWawOp8QLk8Ziy2p10ByjQFCajoFiyuAWl-R1WXZaf4xitLRracT9agpzIzc-MbLSHIGgWQGO21lGiImy5ftZ-D8bHAqRz2y15pzD4c4CEou7XSSLDoRnR0QG5MsDhD6s2gV9mwHkrtkCxtMWdBi-77as8wGmlNRldcOSgZDLK8UnCSgA1OguZ989bFyc8tOOEIb0xUSfPSz3LPSCnyYz68aDjmKVeNH-ig857OScyWbGyEy3Biw64qun3juUlNWsJ3zngkOdteYWytx5Qr4XKNs6R-Myyq72KUp02mJDZiiyiglxML_i3-_CeecCw",
e: "AQAB",
d: "eNLS37aCz7RXSNPD_DtLBJ6j5T8cSxdzRBCjPaI6WcGqJp16lq3UTwuoDLAqlA9oGYm238dsIWpuucP_lQtbWe-7SpxoI6_vmYGf7YVUHv1-DF9qiOmSrMmdxMnVOzYXY8RaT6thPjn_J5cfLV2xI_LwsrMtmpdSyNlgX0zTUhwtuahgAKMEChYjH2EnjHdHw6sY2-wApdcQI7ULE0oo5RzbQZpmuhcN9hiBc0L3hhF0qo50mbl02_65_GQ7DpVkXBxNgRBLzlPabmzzG2oAhfefLgYmSC1opaCkXE6vRWQNWNL45RZNZFYM3uoJghOMqGeocM0BpjdChHrPOlFvSQ",
p: "4miTuAjKMeH5uJ5KB397QUwhbkYEgSbcA2mifmSkvE2018gb55qkBHK1eVryf1_m43LNlc6O_ak6gfzdZIZvS5NCGjPl0q09plUpu8qFOSspBwA67qGH76lFlZLn_d4yglS7wfLru4_5Ys8qLLs-DqVLviwposOnyyWqwM5AXp0",
q: "xHYrzkivtmnz_sGchnWGc0q-pDOkKicptRpv2pMFIIXxnFX5aMeEXIZjVujXtwUy1UlFIN2GZJSvy5KJ79mu_XyNnFHMzedH-A3ee3u8h1UUrZF-vUu1_e4U_x67NN1dedzUSKynN7pFl3OkuShMBWGV-cwzOPdcVAfVuZlxUMc",
dp: "fBzDzYDUBmBQGop7Hn0dvf_T27V6RqpctWo074CQZcFbP2atFVtKSj3viWT3xid2VHzcgiDHdfpM3nEVlEO1wwIonGCSvdjGEOZiiFVOjrZAOVxA8guOjyyFvqbXke06VwPIIVvfKeSU2zuhbP__1tt6F_fxow4Kb2xonGT0GGk",
dq: "jmE2DiIPdhwDgLXAQpIaBqQ81bO3XfVT_LRULAwwwwlPuQV148H04zlh9TJ6Y2GZHYokV1U0eOBpJxfkb7dLYtpJpuiBjRf4yIUEoGlkkI_QlJnFSFr-YjGRdfNHqWBkxlSMZL770R9mIATndGkH7z5x-r9KwBZFC4FCG2hg_zE",
qi: "YCX_pLwbMBA1ThVH0WcwmnytqNcrMCEwTm7ByA2eU6nWbQrULvf7m9_kzfLUcjsnpAVlBQG5JMXMy0Sq4ptwbywsa5-G8KAOOOR2L3v4hC-Eys9ftgFM_3i0o40eeQH4b3haPbntrIeMg8IzlOuVYKf9-2QuKDoWeRdd7NsdxTk"
};
debug("Importing a public key...");
crypto.subtle.importKey("jwk", asciiToArrayBuffer(JSON.stringify(publicKeyJSON)), null, extractable, ["sign", "verify"]).then(function(result) {
publicKey = result;
shouldBe("publicKey.toString()", "'[object Key]'");
shouldBe("publicKey.type", "'public'");
shouldBe("publicKey.usages", "['sign','verify']");
shouldBe("publicKey.algorithm.name", "'rsassa-pkcs1-v1_5'");
shouldBe("publicKey.algorithm.modulusLength", "2048");
shouldBe("byteArrayToHexString(publicKey.algorithm.publicExponent)", "'[01 00 01]'");
shouldBe("publicKey.algorithm.hash.name", "'sha-256'");
debug("\nImporting a private key...");
return crypto.subtle.importKey("jwk", asciiToArrayBuffer(JSON.stringify(privateKeyJSON)), null, extractable, ["sign", "verify"]);
}).then(function(result) {
privateKey = result;
shouldBe("privateKey.toString()", "'[object Key]'");
shouldBe("privateKey.type", "'private'");
shouldBe("privateKey.usages", "['sign','verify']");
shouldBe("privateKey.algorithm.name", "'rsassa-pkcs1-v1_5'");
shouldBe("privateKey.algorithm.modulusLength", "2048");
shouldBe("byteArrayToHexString(privateKey.algorithm.publicExponent)", "'[01 00 01]'");
shouldBe("privateKey.algorithm.hash.name", "'sha-256'");
finishJSTest();
});
</script>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>
2013-11-13 Alexey Proskuryakov <ap@apple.com>
Implement key generation and JWK import for RSASSA-PKCS1-v1_5
https://bugs.webkit.org/show_bug.cgi?id=124236
Reviewed by Sam Weinig.
Tests: crypto/subtle/rsassa-pkcs1-v1_5-generate-key.html
crypto/subtle/rsassa-pkcs1-v1_5-import-jwk.html
* WebCore.xcodeproj/project.pbxproj: Added new files.
* bindings/js/JSCryptoAlgorithmBuilder.cpp:
(WebCore::JSCryptoAlgorithmBuilder::add):
* bindings/js/JSCryptoAlgorithmBuilder.h:
* crypto/CryptoAlgorithmDescriptionBuilder.h:
Added a way to add an Uint8Array, as needed for RSA key.algorithm.publicExponent.
* bindings/js/JSCryptoAlgorithmDictionary.cpp:
(WebCore::createAesCbcParams): Removed unneeded JSC prefixes.
(WebCore::createAesKeyGenParams): Ditto.
(WebCore::createHmacParams): Ditto.
(WebCore::createHmacKeyParams): Ditto.
(WebCore::createRsaKeyGenParams): Added.
(WebCore::createRsaSsaKeyParams): Added. WebCrypto currently doesn't specify any
parameters for importKey, so the structure remains blank (unlike with JWK).
(WebCore::createRsaSsaParams): Added (currently unused, will be sued for sign/verify soon).
(WebCore::JSCryptoAlgorithmDictionary::createParametersForEncrypt): Removed unneeded JSC prefixes.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForDecrypt): Ditto.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForSign): Added support for RSAES_PKCS1_v1_5.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForVerify): Ditto.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForDigest): Removed unneeded JSC prefixes.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForGenerateKey): Ditto.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForDeriveKey): Ditto.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForDeriveBits): Ditto.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForImportKey): Added support for RSAES_PKCS1_v1_5.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForExportKey): Removed unneeded JSC prefixes.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForWrapKey): Ditto.
(WebCore::JSCryptoAlgorithmDictionary::createParametersForUnwrapKey): Ditto.
* bindings/js/JSCryptoKeySerializationJWK.h:
* bindings/js/JSCryptoKeySerializationJWK.cpp:
(WebCore::getJSArrayFromJSON): Added.
(WebCore::getBigIntegerVectorFromJSON): Added.
(WebCore::createRSASSAKeyParameters): Create parameters for key import. The key
will remember which algorithm it's allowed to be used with.
(WebCore::JSCryptoKeySerializationJWK::reconcileAlgorithm): Added support for
RS256...RS512 (tha is, RSAES_PKCS1_v1_5 with SHA-256...SHA-512).
(WebCore::JSCryptoKeySerializationJWK::keyDataOctetSequence): Split out of keyData().
(WebCore::JSCryptoKeySerializationJWK::keyDataRSAComponents): Added code to read
RSA key components from JWK.
(WebCore::JSCryptoKeySerializationJWK::keyData): Call one of the above functions.
* crypto/CryptoAlgorithmRSASSA_PKCS1_v1_5Mac.cpp: Added.
(WebCore::CryptoAlgorithmRSASSA_PKCS1_v1_5::sign):
(WebCore::CryptoAlgorithmRSASSA_PKCS1_v1_5::verify):
Placeholders.
* crypto/CryptoKey.h: (WebCore::CryptoKeyClass): Added RSA key class for poor man's RTTI.
* crypto/CryptoKeyData.h: (WebCore::CryptoKeyData::FormatRSAComponents): Added RSAComponents
for poor man's RTTI.
* crypto/algorithms/CryptoAlgorithmAES_CBC.cpp: (WebCore::CryptoAlgorithmAES_CBC::importKey):
* crypto/algorithms/CryptoAlgorithmHMAC.cpp: (WebCore::CryptoAlgorithmHMAC::importKey):
* crypto/keys/CryptoKeyAES.h:
(WebCore::isCryptoKeyAES):
(WebCore::toCryptoKeyAES):
* crypto/keys/CryptoKeyDataOctetSequence.h:
(WebCore::toCryptoKeyDataOctetSequence):
* crypto/keys/CryptoKeyHMAC.h:
(WebCore::isCryptoKeyHMAC):
(WebCore::toCryptoKeyHMAC):
* crypto/mac/CryptoAlgorithmAES_CBCMac.cpp:
(WebCore::CryptoAlgorithmAES_CBC::encrypt):
(WebCore::CryptoAlgorithmAES_CBC::decrypt):
* crypto/mac/CryptoAlgorithmHMACMac.cpp:
(WebCore::CryptoAlgorithmHMAC::sign):
(WebCore::CryptoAlgorithmHMAC::verify):
Switched from "as" functions to "is" and "to" ones, as that's more idiomatic.
* crypto/algorithms/CryptoAlgorithmRSASSA_PKCS1_v1_5.cpp: Added.
* crypto/algorithms/CryptoAlgorithmRSASSA_PKCS1_v1_5.h: Added.
Glue code for importKey/generateKey for now.
* crypto/keys/CryptoKeyDataRSAComponents.cpp: Added.
(WebCore::CryptoKeyDataRSAComponents::CryptoKeyDataRSAComponents):
(WebCore::CryptoKeyDataRSAComponents::~CryptoKeyDataRSAComponents):
* crypto/keys/CryptoKeyDataRSAComponents.h: Added.
(WebCore::toCryptoKeyDataRSAComponents):
Added a structure to hold RSA key components, extracted from JWK or another format.
* crypto/keys/CryptoKeyRSA.h: Added.
* crypto/mac/CryptoKeyRSAMac.cpp: Added.
* crypto/mac/CryptoAlgorithmRegistryMac.cpp:
(WebCore::CryptoAlgorithmRegistry::platformRegisterAlgorithms):
Register RSASSA_PKCS1_v1_5.
* crypto/parameters/CryptoAlgorithmHmacKeyParams.h: Added a constructor to make
sure that hasLength is never left uninitialized, even when reading formats that
don't contain a length.
* crypto/parameters/CryptoAlgorithmRsaKeyGenParams.h: Added.
* crypto/parameters/CryptoAlgorithmRsaSsaKeyParams.h: Added.
* crypto/parameters/CryptoAlgorithmRsaSsaParams.h: Added.
Added parameter structures that are needed for RSASSA_PKCS1_v1_5.
2013-11-12 Alexey Proskuryakov <ap@apple.com>
Disable WebCrypto on Mountain Lion
......
......@@ -30,6 +30,8 @@
#include <runtime/ObjectConstructor.h>
#include <runtime/Operations.h>
#include <runtime/TypedArrays.h>
#include <runtime/TypedArrayInlines.h>
using namespace JSC;
......@@ -64,6 +66,14 @@ void JSCryptoAlgorithmBuilder::add(const char* key, const String& value)
m_dictionary->putDirect(vm, identifier, jsString(m_exec, value));
}
void JSCryptoAlgorithmBuilder::add(const char* key, const Vector<uint8_t>& buffer)
{
VM& vm = m_exec->vm();
Identifier identifier(&vm, key);
RefPtr<Uint8Array> arrayView = Uint8Array::create(buffer.data(), buffer.size());
m_dictionary->putDirect(vm, identifier, arrayView->wrap(m_exec, vm.dynamicGlobalObject));
}
void JSCryptoAlgorithmBuilder::add(const char* key, const CryptoAlgorithmDescriptionBuilder& nestedBuilder)
{
VM& vm = m_exec->vm();
......
......@@ -48,6 +48,7 @@ public:
virtual void add(const char*, unsigned) OVERRIDE;
virtual void add(const char*, const String&) OVERRIDE;
virtual void add(const char*, const Vector<uint8_t>&) OVERRIDE;
virtual void add(const char*, const CryptoAlgorithmDescriptionBuilder&) OVERRIDE;
private:
......
......@@ -63,6 +63,8 @@ private:
JSCryptoKeySerializationJWK(JSC::ExecState*, const String&);
bool keySizeIsValid(size_t sizeInBits) const;
std::unique_ptr<CryptoKeyData> keyDataOctetSequence() const;
std::unique_ptr<CryptoKeyData> keyDataRSAComponents() const;
JSC::ExecState* m_exec;
JSC::Strong<JSC::JSObject> m_json;
......
......@@ -28,6 +28,7 @@
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
#include <wtf/Vector.h>
#if ENABLE(SUBTLE_CRYPTO)
......@@ -43,6 +44,7 @@ public:
virtual void add(const char*, unsigned) = 0;
virtual void add(const char*, const String&) = 0;
virtual void add(const char*, const Vector<uint8_t>&) = 0;
virtual void add(const char*, const CryptoAlgorithmDescriptionBuilder&) = 0;
};
......
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "CryptoAlgorithmRSASSA_PKCS1_v1_5.h"
#if ENABLE(SUBTLE_CRYPTO)
#include "ExceptionCode.h"
namespace WebCore {
void CryptoAlgorithmRSASSA_PKCS1_v1_5::sign(const CryptoAlgorithmParameters&, const CryptoKey&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode& ec)
{
ec = NOT_SUPPORTED_ERR;
}
void CryptoAlgorithmRSASSA_PKCS1_v1_5::verify(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData& /*signature*/, const Vector<CryptoOperationData>& /*data*/, std::unique_ptr<PromiseWrapper>, ExceptionCode& ec)
{
ec = NOT_SUPPORTED_ERR;
}
} // namespace WebCore
#endif // ENABLE(SUBTLE_CRYPTO)
......@@ -41,7 +41,8 @@ class CryptoAlgorithmDescriptionBuilder;
ENUM_CLASS(CryptoKeyClass) {
HMAC,
AES
AES,
RSA
};
class CryptoKey : public RefCounted<CryptoKey> {
......
......@@ -36,7 +36,8 @@ class CryptoKeyData {
WTF_MAKE_NONCOPYABLE(CryptoKeyData);
public:
ENUM_CLASS(Format) {
OctetSequence
OctetSequence,
RSAComponents
};
CryptoKeyData(Format format)
......
......@@ -75,7 +75,7 @@ void CryptoAlgorithmAES_CBC::importKey(const CryptoAlgorithmParameters&, const C
ec = NOT_SUPPORTED_ERR;
return;
}
const CryptoKeyDataOctetSequence& keyDataOctetSequence = asCryptoKeyDataOctetSequence(keyData);
const CryptoKeyDataOctetSequence& keyDataOctetSequence = toCryptoKeyDataOctetSequence(keyData);
RefPtr<CryptoKeyAES> result = CryptoKeyAES::create(CryptoAlgorithmIdentifier::AES_CBC, keyDataOctetSequence.octetSequence(), extractable, usage);
promise->fulfill(result.release());
}
......
......@@ -76,7 +76,7 @@ void CryptoAlgorithmHMAC::importKey(const CryptoAlgorithmParameters& parameters,
ec = NOT_SUPPORTED_ERR;
return;
}
const CryptoKeyDataOctetSequence& keyDataOctetSequence = asCryptoKeyDataOctetSequence(keyData);
const CryptoKeyDataOctetSequence& keyDataOctetSequence = toCryptoKeyDataOctetSequence(keyData);
const CryptoAlgorithmHmacParams& hmacParameters = static_cast<const CryptoAlgorithmHmacParams&>(parameters);
......
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "CryptoAlgorithmRSASSA_PKCS1_v1_5.h"
#if ENABLE(SUBTLE_CRYPTO)
#include "CryptoAlgorithmRsaKeyGenParams.h"
#include "CryptoAlgorithmRsaSsaKeyParams.h"
#include "CryptoKeyDataRSAComponents.h"
#include "CryptoKeyRSA.h"
#include "JSDOMPromise.h"
namespace WebCore {
const char* const CryptoAlgorithmRSASSA_PKCS1_v1_5::s_name = "rsassa-pkcs1-v1_5";
CryptoAlgorithmRSASSA_PKCS1_v1_5::CryptoAlgorithmRSASSA_PKCS1_v1_5()
{
}
CryptoAlgorithmRSASSA_PKCS1_v1_5::~CryptoAlgorithmRSASSA_PKCS1_v1_5()
{
}
std::unique_ptr<CryptoAlgorithm> CryptoAlgorithmRSASSA_PKCS1_v1_5::create()
{
return std::unique_ptr<CryptoAlgorithm>(new CryptoAlgorithmRSASSA_PKCS1_v1_5);
}
CryptoAlgorithmIdentifier CryptoAlgorithmRSASSA_PKCS1_v1_5::identifier() const
{
return s_identifier;
}
void CryptoAlgorithmRSASSA_PKCS1_v1_5::importKey(const CryptoAlgorithmParameters& parameters, const CryptoKeyData& keyData, bool extractable, CryptoKeyUsage usage, std::unique_ptr<PromiseWrapper> promise, ExceptionCode&)
{
const CryptoAlgorithmRsaSsaKeyParams& rsaSSAParameters = static_cast<const CryptoAlgorithmRsaSsaKeyParams&>(parameters);
const CryptoKeyDataRSAComponents& rsaComponents = toCryptoKeyDataRSAComponents(keyData);
RefPtr<CryptoKeyRSA> result = CryptoKeyRSA::create(CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5, rsaComponents, extractable, usage);
if (!result) {
promise->reject(nullptr);
return;
}
if (rsaSSAParameters.hasHash)
result->restrictToHash(rsaSSAParameters.hash);
promise->fulfill(result.release());
}
void CryptoAlgorithmRSASSA_PKCS1_v1_5::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsage usages, std::unique_ptr<PromiseWrapper> promise, ExceptionCode&)
{
const CryptoAlgorithmRsaKeyGenParams& rsaParameters = static_cast<const CryptoAlgorithmRsaKeyGenParams&>(parameters);
CryptoKeyRSA::generatePair(CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5, rsaParameters.modulusLength, rsaParameters.publicExponent, extractable, usages, std::move(promise));
}
}
#endif // ENABLE(SUBTLE_CRYPTO)
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CryptoAlgorithmRSASSA_PKCS1_v1_5_h
#define CryptoAlgorithmRSASSA_PKCS1_v1_5_h
#include "CryptoAlgorithm.h"
#if ENABLE(SUBTLE_CRYPTO)
namespace WebCore {
class CryptoAlgorithmRSASSA_PKCS1_v1_5 FINAL : public CryptoAlgorithm {
public:
static const char* const s_name;
static const CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5;
static std::unique_ptr<CryptoAlgorithm> create();
virtual CryptoAlgorithmIdentifier identifier() const OVERRIDE;
virtual void sign(const CryptoAlgorithmParameters&, const CryptoKey&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
virtual void verify(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData& signature, const Vector<CryptoOperationData>& data, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
virtual void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsage, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
virtual void importKey(const CryptoAlgorithmParameters&, const CryptoKeyData&, bool extractable, CryptoKeyUsage, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
private:
CryptoAlgorithmRSASSA_PKCS1_v1_5();
virtual ~CryptoAlgorithmRSASSA_PKCS1_v1_5();
};
}
#endif // ENABLE(SUBTLE_CRYPTO)
#endif // CryptoAlgorithmRSASSA_PKCS1_v1_5_h
......@@ -56,18 +56,21 @@ private:
Vector<char> m_key;
};
inline const CryptoKeyAES* asCryptoKeyAES(const CryptoKey& key)
inline bool isCryptoKeyAES(const CryptoKey& key)
{
if (key.keyClass() != CryptoKeyClass::AES)
return nullptr;
return static_cast<const CryptoKeyAES*>(&key);
return key.keyClass() == CryptoKeyClass::AES;
}
inline CryptoKeyAES* asCryptoKeyAES(CryptoKey& key)
inline const CryptoKeyAES& toCryptoKeyAES(const CryptoKey& key)
{
if (key.keyClass() != CryptoKeyClass::AES)
return nullptr;
return static_cast<CryptoKeyAES*>(&key);
ASSERT_WITH_SECURITY_IMPLICATION(isCryptoKeyAES(key));
return static_cast<const CryptoKeyAES&>(key);
}
inline CryptoKeyAES& toCryptoKeyAES(CryptoKey& key)
{
ASSERT_WITH_SECURITY_IMPLICATION(isCryptoKeyAES(key));
return static_cast<CryptoKeyAES&>(key);
}
} // namespace WebCore
......
......@@ -49,7 +49,7 @@ private:
Vector<char> m_keyData;
};
inline const CryptoKeyDataOctetSequence& asCryptoKeyDataOctetSequence(const CryptoKeyData& data)
inline const CryptoKeyDataOctetSequence& toCryptoKeyDataOctetSequence(const CryptoKeyData& data)