Title: [219064] trunk
Revision
219064
Author
[email protected]
Date
2017-07-03 00:46:09 -0700 (Mon, 03 Jul 2017)

Log Message

[GCrypt] Implement CryptoKeyEC SPKI exports
https://bugs.webkit.org/show_bug.cgi?id=173646

Reviewed by Jiewen Tan.

Source/WebCore:

No new tests -- affected tests are now passing and are unskipped.

Implement libgcrypt-based support for SPKI exports of EC keys.

Initially, the ECParameters structure is created so that it will be later embedded
into the SubjectPublicKeyInfo structure. First the root element of this structure
is written into, specifying namedCurve as the chosen member (even if other choices
are not really available). We then write out the object identifier into this
namedCurve member that properly represents this key's curve type.

The SubjectPublicKeyInfo structure is created next. We write out id-ecPublicKey
identifier as the chosen algorithm identifier. Web Crypto specification demands
that the id-ecDH identifier is used in case of ECDH keys, but no existing test in
the W3C test suite expects this, so this should be revisited later. Data of the
previously-constructed ECParameters structure is written out into the
AlgorithmIdentifier's parameters member.

The `q` MPI data is then retrieved. Its size is validated, as well as the first
byte of data in order to ensure the MPI represents an uncompressed EC point.
The data is then written into the subjectPublicKey member.

Finally the encoded SubjectPublicKeyInfo structure data is extracted and returned
from the platformExportSpki() function, completion the export operation.

* crypto/gcrypt/CryptoKeyECGCrypt.cpp:
(WebCore::curveIdentifier):
(WebCore::CryptoKeyEC::platformExportSpki):

Source/WebCore/PAL:

No new tests -- covered by existing Web Crypto tests.

Add three new libtasn1 utility functions.

createStructure() is a simple wrapper around asn1_create_element(), creating a new
ASN.1 structure for the specified definition that's listed in WebCrypto.asn. The
existing decodeStructure() is modified to use this new addition.

encodedData() retrieves the ASN.1-encoded data of the specified element that's
located in the passed-in asn1_node. This is used when retrieving SPKI or PKCS#8
data from filled-out ASN.1 structures.

writeElement() writes the provided data to the given asn1_node object under the
specified element, using the given size. True is returned if this operation was
successful.

* pal/crypto/tasn1/Utilities.cpp:
(PAL::TASN1::createStructure):
(PAL::TASN1::decodeStructure):
(PAL::TASN1::encodedData):
(PAL::TASN1::writeElement):
* pal/crypto/tasn1/Utilities.h:

LayoutTests:

* platform/gtk/TestExpectations:
Unskip tests that cover SPKI exports of EC keys.

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (219063 => 219064)


--- trunk/LayoutTests/ChangeLog	2017-07-03 05:51:58 UTC (rev 219063)
+++ trunk/LayoutTests/ChangeLog	2017-07-03 07:46:09 UTC (rev 219064)
@@ -1,3 +1,13 @@
+2017-07-03  Zan Dobersek  <[email protected]>
+
+        [GCrypt] Implement CryptoKeyEC SPKI exports
+        https://bugs.webkit.org/show_bug.cgi?id=173646
+
+        Reviewed by Jiewen Tan.
+
+        * platform/gtk/TestExpectations:
+        Unskip tests that cover SPKI exports of EC keys.
+
 2017-07-02  Sam Weinig  <[email protected]>
 
         [WebIDL] Remove special casing for RegExp which is no longer required by the spec

Modified: trunk/LayoutTests/platform/gtk/TestExpectations (219063 => 219064)


--- trunk/LayoutTests/platform/gtk/TestExpectations	2017-07-03 05:51:58 UTC (rev 219063)
+++ trunk/LayoutTests/platform/gtk/TestExpectations	2017-07-03 07:46:09 UTC (rev 219064)
@@ -754,21 +754,14 @@
 webkit.org/b/133122 crypto/subtle/ecdh-derive-bits-malformed-parametrs.html [ Skip ]
 webkit.org/b/133122 crypto/subtle/ecdh-generate-export-key-pkcs8-p256.html [ Skip ]
 webkit.org/b/133122 crypto/subtle/ecdh-generate-export-key-pkcs8-p384.html [ Skip ]
-webkit.org/b/133122 crypto/subtle/ecdh-generate-export-key-spki-p256.html [ Skip ]
-webkit.org/b/133122 crypto/subtle/ecdh-generate-export-key-spki-p384.html [ Skip ]
 webkit.org/b/133122 crypto/subtle/ecdh-import-pkcs8-key-p256.html [ Skip ]
 webkit.org/b/133122 crypto/subtle/ecdh-import-pkcs8-key-p384.html [ Skip ]
 webkit.org/b/133122 crypto/subtle/ecdsa-generate-export-key-pkcs8.html [ Skip ]
-webkit.org/b/133122 crypto/subtle/ecdsa-generate-export-key-spki.html [ Skip ]
 webkit.org/b/133122 crypto/subtle/ecdsa-import-pkcs8-key.html [ Skip ]
 webkit.org/b/133122 crypto/subtle/ec-import-jwk-key-export-pkcs8-key.html [ Skip ]
-webkit.org/b/133122 crypto/subtle/ec-import-jwk-key-export-spki-key.html [ Skip ]
-webkit.org/b/133122 crypto/subtle/ec-import-raw-key-export-spki-key.html [ Skip ]
 webkit.org/b/133122 crypto/subtle/ec-import-pkcs8-key-export-jwk-key.html [ Skip ]
 webkit.org/b/133122 crypto/subtle/ec-import-pkcs8-key-export-pkcs8-key-p256.html [ Skip ]
 webkit.org/b/133122 crypto/subtle/ec-import-pkcs8-key-export-pkcs8-key-p384.html [ Skip ]
-webkit.org/b/133122 crypto/subtle/ec-import-spki-key-export-spki-key-p256.html [ Skip ]
-webkit.org/b/133122 crypto/subtle/ec-import-spki-key-export-spki-key-p384.html [ Skip ]
 webkit.org/b/133122 crypto/subtle/rsa-export-key-malformed-parameters.html [ Skip ]
 webkit.org/b/133122 crypto/subtle/rsa-import-jwk-key-export-pkcs8-key.html [ Skip ]
 webkit.org/b/133122 crypto/subtle/rsa-import-jwk-key-export-spki-key.html [ Skip ]
@@ -804,7 +797,6 @@
 webkit.org/b/133122 crypto/workers/subtle/aes-cfb-import-key-wrap-key.html [ Skip ]
 webkit.org/b/133122 crypto/workers/subtle/aes-postMessage-worker.html [ Skip ]
 webkit.org/b/133122 crypto/workers/subtle/ec-generate-export-pkcs8-key.html [ Skip ]
-webkit.org/b/133122 crypto/workers/subtle/ec-generate-export-spki-key.html [ Skip ]
 webkit.org/b/133122 crypto/workers/subtle/ec-import-pkcs8-key.html [ Skip ]
 webkit.org/b/133122 crypto/workers/subtle/ec-postMessage-worker.html [ Skip ]
 webkit.org/b/133122 crypto/workers/subtle/hmac-postMessage-worker.html [ Skip ]

Modified: trunk/Source/WebCore/ChangeLog (219063 => 219064)


--- trunk/Source/WebCore/ChangeLog	2017-07-03 05:51:58 UTC (rev 219063)
+++ trunk/Source/WebCore/ChangeLog	2017-07-03 07:46:09 UTC (rev 219064)
@@ -1,3 +1,38 @@
+2017-07-03  Zan Dobersek  <[email protected]>
+
+        [GCrypt] Implement CryptoKeyEC SPKI exports
+        https://bugs.webkit.org/show_bug.cgi?id=173646
+
+        Reviewed by Jiewen Tan.
+
+        No new tests -- affected tests are now passing and are unskipped.
+
+        Implement libgcrypt-based support for SPKI exports of EC keys.
+
+        Initially, the ECParameters structure is created so that it will be later embedded
+        into the SubjectPublicKeyInfo structure. First the root element of this structure
+        is written into, specifying namedCurve as the chosen member (even if other choices
+        are not really available). We then write out the object identifier into this
+        namedCurve member that properly represents this key's curve type.
+
+        The SubjectPublicKeyInfo structure is created next. We write out id-ecPublicKey
+        identifier as the chosen algorithm identifier. Web Crypto specification demands
+        that the id-ecDH identifier is used in case of ECDH keys, but no existing test in
+        the W3C test suite expects this, so this should be revisited later. Data of the
+        previously-constructed ECParameters structure is written out into the
+        AlgorithmIdentifier's parameters member.
+
+        The `q` MPI data is then retrieved. Its size is validated, as well as the first
+        byte of data in order to ensure the MPI represents an uncompressed EC point.
+        The data is then written into the subjectPublicKey member.
+
+        Finally the encoded SubjectPublicKeyInfo structure data is extracted and returned
+        from the platformExportSpki() function, completion the export operation.
+
+        * crypto/gcrypt/CryptoKeyECGCrypt.cpp:
+        (WebCore::curveIdentifier):
+        (WebCore::CryptoKeyEC::platformExportSpki):
+
 2017-07-02  Sam Weinig  <[email protected]>
 
         [WebIDL] Remove special casing for RegExp which is no longer required by the spec

Modified: trunk/Source/WebCore/PAL/ChangeLog (219063 => 219064)


--- trunk/Source/WebCore/PAL/ChangeLog	2017-07-03 05:51:58 UTC (rev 219063)
+++ trunk/Source/WebCore/PAL/ChangeLog	2017-07-03 07:46:09 UTC (rev 219064)
@@ -1,3 +1,33 @@
+2017-07-03  Zan Dobersek  <[email protected]>
+
+        [GCrypt] Implement CryptoKeyEC SPKI exports
+        https://bugs.webkit.org/show_bug.cgi?id=173646
+
+        Reviewed by Jiewen Tan.
+
+        No new tests -- covered by existing Web Crypto tests.
+
+        Add three new libtasn1 utility functions.
+
+        createStructure() is a simple wrapper around asn1_create_element(), creating a new
+        ASN.1 structure for the specified definition that's listed in WebCrypto.asn. The
+        existing decodeStructure() is modified to use this new addition.
+
+        encodedData() retrieves the ASN.1-encoded data of the specified element that's
+        located in the passed-in asn1_node. This is used when retrieving SPKI or PKCS#8
+        data from filled-out ASN.1 structures.
+
+        writeElement() writes the provided data to the given asn1_node object under the
+        specified element, using the given size. True is returned if this operation was
+        successful.
+
+        * pal/crypto/tasn1/Utilities.cpp:
+        (PAL::TASN1::createStructure):
+        (PAL::TASN1::decodeStructure):
+        (PAL::TASN1::encodedData):
+        (PAL::TASN1::writeElement):
+        * pal/crypto/tasn1/Utilities.h:
+
 2017-07-01  Dan Bernstein  <[email protected]>
 
         [iOS] Remove code only needed when building for iOS 9.x

Modified: trunk/Source/WebCore/PAL/pal/crypto/tasn1/Utilities.cpp (219063 => 219064)


--- trunk/Source/WebCore/PAL/pal/crypto/tasn1/Utilities.cpp	2017-07-03 05:51:58 UTC (rev 219063)
+++ trunk/Source/WebCore/PAL/pal/crypto/tasn1/Utilities.cpp	2017-07-03 07:46:09 UTC (rev 219064)
@@ -102,14 +102,19 @@
     return s_definitions;
 }
 
+bool createStructure(const char* elementName, asn1_node* root)
+{
+    int ret = asn1_create_element(asn1Definitions(), elementName, root);
+    return ret == ASN1_SUCCESS;
+}
+
 bool decodeStructure(asn1_node* root, const char* elementName, const Vector<uint8_t>& data)
 {
-    int ret = asn1_create_element(asn1Definitions(), elementName, root);
-    if (ret != ASN1_SUCCESS)
+    if (!createStructure(elementName, root))
         return false;
 
     int dataSize = data.size();
-    ret = asn1_der_decoding2(root, data.data(), &dataSize, ASN1_DECODE_FLAG_STRICT_DER, nullptr);
+    int ret = asn1_der_decoding2(root, data.data(), &dataSize, ASN1_DECODE_FLAG_STRICT_DER, nullptr);
     return ret == ASN1_SUCCESS;
 }
 
@@ -135,5 +140,26 @@
     return data;
 }
 
+std::optional<Vector<uint8_t>> encodedData(asn1_node root, const char* elementName)
+{
+    int length = 0;
+    int ret = asn1_der_coding(root, elementName, nullptr, &length, nullptr);
+    if (ret != ASN1_MEM_ERROR)
+        return std::nullopt;
+
+    Vector<uint8_t> data(length);
+    ret = asn1_der_coding(root, elementName, data.data(), &length, nullptr);
+    if (ret != ASN1_SUCCESS)
+        return std::nullopt;
+
+    return data;
+}
+
+bool writeElement(asn1_node root, const char* elementName, const void* data, size_t dataSize)
+{
+    int ret = asn1_write_value(root, elementName, data, dataSize);
+    return ret == ASN1_SUCCESS;
+}
+
 } // namespace TASN1
 } // namespace PAL

Modified: trunk/Source/WebCore/PAL/pal/crypto/tasn1/Utilities.h (219063 => 219064)


--- trunk/Source/WebCore/PAL/pal/crypto/tasn1/Utilities.h	2017-07-03 05:51:58 UTC (rev 219063)
+++ trunk/Source/WebCore/PAL/pal/crypto/tasn1/Utilities.h	2017-07-03 07:46:09 UTC (rev 219064)
@@ -55,8 +55,11 @@
     asn1_node m_structure { nullptr };
 };
 
+bool createStructure(const char* elementName, asn1_node* root);
 bool decodeStructure(asn1_node* root, const char* elementName, const Vector<uint8_t>& data);
 std::optional<Vector<uint8_t>> elementData(asn1_node root, const char* elementName);
+std::optional<Vector<uint8_t>> encodedData(asn1_node root, const char* elementName);
+bool writeElement(asn1_node root, const char* elementName, const void* data, size_t dataSize);
 
 } // namespace TASN1
 } // namespace PAL

Modified: trunk/Source/WebCore/crypto/gcrypt/CryptoKeyECGCrypt.cpp (219063 => 219064)


--- trunk/Source/WebCore/crypto/gcrypt/CryptoKeyECGCrypt.cpp	2017-07-03 05:51:58 UTC (rev 219063)
+++ trunk/Source/WebCore/crypto/gcrypt/CryptoKeyECGCrypt.cpp	2017-07-03 07:46:09 UTC (rev 219064)
@@ -66,6 +66,19 @@
     return nullptr;
 }
 
+static const char* curveIdentifier(CryptoKeyEC::NamedCurve curve)
+{
+    switch (curve) {
+    case CryptoKeyEC::NamedCurve::P256:
+        return "1.2.840.10045.3.1.7";
+    case CryptoKeyEC::NamedCurve::P384:
+        return "1.3.132.0.34";
+    }
+
+    ASSERT_NOT_REACHED();
+    return nullptr;
+}
+
 static unsigned uncompressedPointSizeForCurve(CryptoKeyEC::NamedCurve curve)
 {
     switch (curve) {
@@ -402,9 +415,63 @@
 
 Vector<uint8_t> CryptoKeyEC::platformExportSpki() const
 {
-    notImplemented();
+    PAL::TASN1::Structure ecParameters;
+    {
+        // Create the `ECParameters` structure.
+        if (!PAL::TASN1::createStructure("WebCrypto.ECParameters", &ecParameters))
+            return { };
 
-    return { };
+        // Select the `namedCurve` object identifier as the target `ECParameters` choice.
+        if (!PAL::TASN1::writeElement(ecParameters, "", "namedCurve", 1))
+            return { };
+
+        // Write out the EC curve identifier under `namedCurve`.
+        if (!PAL::TASN1::writeElement(ecParameters, "namedCurve", curveIdentifier(m_curve), 1))
+            return { };
+    }
+
+    PAL::TASN1::Structure spki;
+    {
+        // Create the `SubjectPublicKeyInfo` structure.
+        if (!PAL::TASN1::createStructure("WebCrypto.SubjectPublicKeyInfo", &spki))
+            return { };
+
+        // Write out the id-ecPublicKey identifier under `algorithm.algorithm`.
+        // FIXME: Per specification this should write out id-ecDH when the ECDH algorithm
+        // is specified for this CryptoKeyEC object, but not even the W3C tests expect that.
+        if (!PAL::TASN1::writeElement(spki, "algorithm.algorithm", "1.2.840.10045.2.1", 1))
+            return { };
+
+        // Write out the `ECParameters` data under `algorithm.parameters`.
+        {
+            auto data = "" "");
+            if (!data || !PAL::TASN1::writeElement(spki, "algorithm.parameters", data->data(), data->size()))
+                return { };
+        }
+
+        // Retrieve the `q` s-_expression_, which should contain the public key data.
+        PAL::GCrypt::Handle<gcry_sexp_t> qSexp(gcry_sexp_find_token(m_platformKey, "q", 0));
+        if (!qSexp)
+            return { };
+
+        // Retrieve the `q` data, which should be in the uncompressed point format.
+        // Validate the data size and the first byte (which should be 0x04).
+        auto qData = mpiData(qSexp);
+        if (!qData || qData->size() != uncompressedPointSizeForCurve(m_curve) || qData->at(0) != 0x04)
+            return { };
+
+        // Write out the public key data under `subjectPublicKey`. Because this is a
+        // bit string parameter, the data size has to be multiplied by 8.
+        if (!PAL::TASN1::writeElement(spki, "subjectPublicKey", qData->data(), qData->size() * 8))
+            return { };
+    }
+
+    // Retrieve the encoded `SubjectPublicKeyInfo` data and return it.
+    auto result = PAL::TASN1::encodedData(spki, "");
+    if (!result)
+        return { };
+
+    return WTFMove(result.value());
 }
 
 Vector<uint8_t> CryptoKeyEC::platformExportPkcs8() const
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to