[WebCrypto] Support SPKI/PKCS8 for Elliptic Curve
https://bugs.webkit.org/show_bug.cgi?id=169318
<rdar://problem/31081956>

Reviewed by Brent Fulgham.

LayoutTests/imported/w3c:

* web-platform-tests/WebCryptoAPI/import_export/ec_importKey.worker-expected.txt:
* web-platform-tests/WebCryptoAPI/import_export/test_ec_importKey-expected.txt:

Source/WebCore:

This patch adds SPKI/PKCS8 support for Elliptic Curve cryptos. We can now import/export
SPKI/PKCS8 Elliptic Curve keys after this change. Few things to note: 1) This patch
implements a loose DER encoder/decoder for hacking the underlying CommonCrypto library.
2) It only permits id-ecPublicKey as the AlgorithmIdentifier following OpenSSL/Chrome(BoringSSL).
3) It follows OpenSSL/Chrome(BoringSSL) to replace ECParameters in ECPrivateKey with custom
tags. Hence, we should fully comply with OpenSSL/Chrome(BoringSSL).

Tests: crypto/subtle/ec-import-jwk-key-export-pkcs8-key.html
       crypto/subtle/ec-import-jwk-key-export-spki-key.html
       crypto/subtle/ec-import-pkcs8-key-export-jwk-key.html
       crypto/subtle/ec-import-pkcs8-key-export-pkcs8-key-p256.html
       crypto/subtle/ec-import-pkcs8-key-export-pkcs8-key-p384.html
       crypto/subtle/ec-import-raw-key-export-spki-key.html
       crypto/subtle/ec-import-spki-key-export-jwk-key.html
       crypto/subtle/ec-import-spki-key-export-raw-key.html
       crypto/subtle/ec-import-spki-key-export-spki-key-p256.html
       crypto/subtle/ec-import-spki-key-export-spki-key-p384.html
       crypto/subtle/ecdh-generate-export-key-spki-p256.html
       crypto/subtle/ecdh-generate-export-key-spki-p384.html
       crypto/subtle/ecdh-generate-export-pkcs8-p256.html
       crypto/subtle/ecdh-generate-export-pkcs8-p384.html
       crypto/subtle/ecdh-import-pkcs8-key-p256.html
       crypto/subtle/ecdh-import-pkcs8-key-p384.html
       crypto/subtle/ecdh-import-spki-key-p256.html
       crypto/subtle/ecdh-import-spki-key-p384.html
       crypto/workers/subtle/ec-generate-export-pkcs8-key.html
       crypto/workers/subtle/ec-generate-export-spki-key.html
       crypto/workers/subtle/ec-import-pkcs8-key.html
       crypto/workers/subtle/ec-import-spki-key.html

* WebCore.xcodeproj/project.pbxproj:
* crypto/algorithms/CryptoAlgorithmECDH.cpp:
(WebCore::CryptoAlgorithmECDH::importKey):
(WebCore::CryptoAlgorithmECDH::exportKey):
* crypto/gnutls/CryptoKeyECGnuTLS.cpp:
(WebCore::CryptoKeyEC::platformExportRaw):
(WebCore::CryptoKeyEC::platformImportSpki):
(WebCore::CryptoKeyEC::platformExportSpki):
(WebCore::CryptoKeyEC::platformImportPkcs8):
(WebCore::CryptoKeyEC::platformExportPkcs8):
(WebCore::CryptoKeyEC::exportRaw): Deleted.
* crypto/keys/CryptoKeyEC.cpp:
(WebCore::CryptoKeyEC::importSpki):
(WebCore::CryptoKeyEC::importPkcs8):
(WebCore::CryptoKeyEC::exportRaw):
(WebCore::CryptoKeyEC::exportSpki):
(WebCore::CryptoKeyEC::exportPkcs8):
* crypto/keys/CryptoKeyEC.h:
* crypto/mac/CommonCryptoDERUtilities.h: Added.
(WebCore::bytesUsedToEncodedLength):
(WebCore::extraBytesNeededForEncodedLength):
(WebCore::addEncodedASN1Length):
(WebCore::bytesNeededForEncodedLength):
* crypto/mac/CryptoKeyECMac.cpp:
(WebCore::compareBytes):
(WebCore::CryptoKeyEC::platformExportRaw):
(WebCore::CryptoKeyEC::platformImportJWKPrivate):
(WebCore::getOID):
(WebCore::CryptoKeyEC::platformImportSpki):
(WebCore::CryptoKeyEC::platformExportSpki):
(WebCore::CryptoKeyEC::platformImportPkcs8):
(WebCore::CryptoKeyEC::platformExportPkcs8):
(WebCore::CryptoKeyEC::exportRaw): Deleted.
Enlarge the robust of exportRaw.
* crypto/mac/CryptoKeyRSAMac.cpp:
(WebCore::CryptoKeyRSA::exportSpki):
(WebCore::CryptoKeyRSA::exportPkcs8):
Enhance the implementation.
(WebCore::bytesUsedToEncodedLength): Deleted.
(WebCore::bytesNeededForEncodedLength): Deleted.
(WebCore::addEncodedASN1Length): Deleted.
Moved to CommonCryptoDERUtilities.h.

LayoutTests:

* crypto/subtle/ec-export-key-malformed-parameters-expected.txt:
* crypto/subtle/ec-export-key-malformed-parameters.html:
* crypto/subtle/ec-import-jwk-key-export-jwk-key-private-expected.txt:
* crypto/subtle/ec-import-jwk-key-export-jwk-key-private.html:
* crypto/subtle/ec-import-jwk-key-export-pkcs8-key-expected.txt: Added.
* crypto/subtle/ec-import-jwk-key-export-pkcs8-key.html: Added.
* crypto/subtle/ec-import-jwk-key-export-spki-key-expected.txt: Added.
* crypto/subtle/ec-import-jwk-key-export-spki-key.html: Added.
* crypto/subtle/ec-import-key-malformed-parameters-expected.txt:
* crypto/subtle/ec-import-key-malformed-parameters.html:
* crypto/subtle/ec-import-pkcs8-key-export-jwk-key-expected.txt: Added.
* crypto/subtle/ec-import-pkcs8-key-export-jwk-key.html: Added.
* crypto/subtle/ec-import-pkcs8-key-export-pkcs8-key-p256-expected.txt: Added.
* crypto/subtle/ec-import-pkcs8-key-export-pkcs8-key-p256.html: Added.
* crypto/subtle/ec-import-pkcs8-key-export-pkcs8-key-p384-expected.txt: Added.
* crypto/subtle/ec-import-pkcs8-key-export-pkcs8-key-p384.html: Added.
* crypto/subtle/ec-import-raw-key-export-spki-key-expected.txt: Added.
* crypto/subtle/ec-import-raw-key-export-spki-key.html: Added.
* crypto/subtle/ec-import-spki-key-export-jwk-key-expected.txt: Added.
* crypto/subtle/ec-import-spki-key-export-jwk-key.html: Added.
* crypto/subtle/ec-import-spki-key-export-raw-key-expected.txt: Added.
* crypto/subtle/ec-import-spki-key-export-raw-key.html: Added.
* crypto/subtle/ec-import-spki-key-export-spki-key-p256-expected.txt: Added.
* crypto/subtle/ec-import-spki-key-export-spki-key-p256.html: Added.
* crypto/subtle/ec-import-spki-key-export-spki-key-p384-expected.txt: Added.
* crypto/subtle/ec-import-spki-key-export-spki-key-p384.html: Added.
* crypto/subtle/ecdh-generate-export-key-spki-p256-expected.txt: Added.
* crypto/subtle/ecdh-generate-export-key-spki-p256.html: Added.
* crypto/subtle/ecdh-generate-export-key-spki-p384-expected.txt: Added.
* crypto/subtle/ecdh-generate-export-key-spki-p384.html: Added.
* crypto/subtle/ecdh-generate-export-pkcs8-p256-expected.txt: Added.
* crypto/subtle/ecdh-generate-export-pkcs8-p256.html: Added.
* crypto/subtle/ecdh-generate-export-pkcs8-p384-expected.txt: Added.
* crypto/subtle/ecdh-generate-export-pkcs8-p384.html: Added.
* crypto/subtle/ecdh-import-pkcs8-key-p256-expected.txt: Added.
* crypto/subtle/ecdh-import-pkcs8-key-p256.html: Added.
* crypto/subtle/ecdh-import-pkcs8-key-p384-expected.txt: Added.
* crypto/subtle/ecdh-import-pkcs8-key-p384.html: Added.
* crypto/subtle/ecdh-import-spki-key-p256-expected.txt: Added.
* crypto/subtle/ecdh-import-spki-key-p256.html: Added.
* crypto/subtle/ecdh-import-spki-key-p384-expected.txt: Added.
* crypto/subtle/ecdh-import-spki-key-p384.html: Added.
* crypto/workers/subtle/ec-generate-export-pkcs8-key-expected.txt: Added.
* crypto/workers/subtle/ec-generate-export-pkcs8-key.html: Added.
* crypto/workers/subtle/ec-generate-export-spki-key-expected.txt: Added.
* crypto/workers/subtle/ec-generate-export-spki-key.html: Added.
* crypto/workers/subtle/ec-import-pkcs8-key-expected.txt: Added.
* crypto/workers/subtle/ec-import-pkcs8-key.html: Added.
* crypto/workers/subtle/ec-import-spki-key-expected.txt: Added.
* crypto/workers/subtle/ec-import-spki-key.html: Added.
* crypto/workers/subtle/resources/ec-generate-export-pkcs8-key.js: Added.
* crypto/workers/subtle/resources/ec-generate-export-spki-key.js: Added.
* crypto/workers/subtle/resources/ec-import-pkcs8-key.js: Added.
* crypto/workers/subtle/resources/ec-import-spki-key.js: Added.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@214074 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/crypto/subtle/ec-import-jwk-key-export-spki-key.html b/LayoutTests/crypto/subtle/ec-import-jwk-key-export-spki-key.html
new file mode 100644
index 0000000..c35ca2e
--- /dev/null
+++ b/LayoutTests/crypto/subtle/ec-import-jwk-key-export-spki-key.html
@@ -0,0 +1,40 @@
+<!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 a JWK ECDH public key and export it in SPKI format");
+
+jsTestIsAsync = true;
+
+var jwkKey = {
+    kty: "EC",
+    crv: "P-256",
+    x: "1FSVWieTvikFkG1NOyhkUCaMbdQhxwH6aCu4Ez-sRtA",
+    y: "9jmNTLqM4cjBhdAnHcNI9YQV3O8LFmo-EdZWk8ntAaI",
+};
+var expectedSpkiKey = "3059301306072a8648ce3d020106082a8648ce3d03010703420004d454955a2793be2905906d4d3b286450268c6dd421c701fa682bb8133fac46d0f6398d4cba8ce1c8c185d0271dc348f58415dcef0b166a3e11d65693c9ed01a2";
+var extractable = true;
+
+debug("Importing a key...");
+crypto.subtle.importKey("jwk", jwkKey, { name: "ECDH", namedCurve: "P-256" }, extractable, [ ]).then(function(key) {
+    return crypto.subtle.exportKey("spki", key);
+}).then(function(result) {
+    publicKey = result;
+
+    shouldBe("bytesToHexString(publicKey)", "expectedSpkiKey");
+
+    finishJSTest();
+});
+
+</script>
+
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>