Changeset 219064 in webkit


Ignore:
Timestamp:
Jul 3, 2017 12:46:09 AM (7 years ago)
Author:
zandobersek@gmail.com
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.

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r219061 r219064  
     12017-07-03  Zan Dobersek  <zdobersek@igalia.com>
     2
     3        [GCrypt] Implement CryptoKeyEC SPKI exports
     4        https://bugs.webkit.org/show_bug.cgi?id=173646
     5
     6        Reviewed by Jiewen Tan.
     7
     8        * platform/gtk/TestExpectations:
     9        Unskip tests that cover SPKI exports of EC keys.
     10
    1112017-07-02  Sam Weinig  <sam@webkit.org>
    212
  • trunk/LayoutTests/platform/gtk/TestExpectations

    r218874 r219064  
    755755webkit.org/b/133122 crypto/subtle/ecdh-generate-export-key-pkcs8-p256.html [ Skip ]
    756756webkit.org/b/133122 crypto/subtle/ecdh-generate-export-key-pkcs8-p384.html [ Skip ]
    757 webkit.org/b/133122 crypto/subtle/ecdh-generate-export-key-spki-p256.html [ Skip ]
    758 webkit.org/b/133122 crypto/subtle/ecdh-generate-export-key-spki-p384.html [ Skip ]
    759757webkit.org/b/133122 crypto/subtle/ecdh-import-pkcs8-key-p256.html [ Skip ]
    760758webkit.org/b/133122 crypto/subtle/ecdh-import-pkcs8-key-p384.html [ Skip ]
    761759webkit.org/b/133122 crypto/subtle/ecdsa-generate-export-key-pkcs8.html [ Skip ]
    762 webkit.org/b/133122 crypto/subtle/ecdsa-generate-export-key-spki.html [ Skip ]
    763760webkit.org/b/133122 crypto/subtle/ecdsa-import-pkcs8-key.html [ Skip ]
    764761webkit.org/b/133122 crypto/subtle/ec-import-jwk-key-export-pkcs8-key.html [ Skip ]
    765 webkit.org/b/133122 crypto/subtle/ec-import-jwk-key-export-spki-key.html [ Skip ]
    766 webkit.org/b/133122 crypto/subtle/ec-import-raw-key-export-spki-key.html [ Skip ]
    767762webkit.org/b/133122 crypto/subtle/ec-import-pkcs8-key-export-jwk-key.html [ Skip ]
    768763webkit.org/b/133122 crypto/subtle/ec-import-pkcs8-key-export-pkcs8-key-p256.html [ Skip ]
    769764webkit.org/b/133122 crypto/subtle/ec-import-pkcs8-key-export-pkcs8-key-p384.html [ Skip ]
    770 webkit.org/b/133122 crypto/subtle/ec-import-spki-key-export-spki-key-p256.html [ Skip ]
    771 webkit.org/b/133122 crypto/subtle/ec-import-spki-key-export-spki-key-p384.html [ Skip ]
    772765webkit.org/b/133122 crypto/subtle/rsa-export-key-malformed-parameters.html [ Skip ]
    773766webkit.org/b/133122 crypto/subtle/rsa-import-jwk-key-export-pkcs8-key.html [ Skip ]
     
    805798webkit.org/b/133122 crypto/workers/subtle/aes-postMessage-worker.html [ Skip ]
    806799webkit.org/b/133122 crypto/workers/subtle/ec-generate-export-pkcs8-key.html [ Skip ]
    807 webkit.org/b/133122 crypto/workers/subtle/ec-generate-export-spki-key.html [ Skip ]
    808800webkit.org/b/133122 crypto/workers/subtle/ec-import-pkcs8-key.html [ Skip ]
    809801webkit.org/b/133122 crypto/workers/subtle/ec-postMessage-worker.html [ Skip ]
  • trunk/Source/WebCore/ChangeLog

    r219061 r219064  
     12017-07-03  Zan Dobersek  <zdobersek@igalia.com>
     2
     3        [GCrypt] Implement CryptoKeyEC SPKI exports
     4        https://bugs.webkit.org/show_bug.cgi?id=173646
     5
     6        Reviewed by Jiewen Tan.
     7
     8        No new tests -- affected tests are now passing and are unskipped.
     9
     10        Implement libgcrypt-based support for SPKI exports of EC keys.
     11
     12        Initially, the ECParameters structure is created so that it will be later embedded
     13        into the SubjectPublicKeyInfo structure. First the root element of this structure
     14        is written into, specifying namedCurve as the chosen member (even if other choices
     15        are not really available). We then write out the object identifier into this
     16        namedCurve member that properly represents this key's curve type.
     17
     18        The SubjectPublicKeyInfo structure is created next. We write out id-ecPublicKey
     19        identifier as the chosen algorithm identifier. Web Crypto specification demands
     20        that the id-ecDH identifier is used in case of ECDH keys, but no existing test in
     21        the W3C test suite expects this, so this should be revisited later. Data of the
     22        previously-constructed ECParameters structure is written out into the
     23        AlgorithmIdentifier's parameters member.
     24
     25        The `q` MPI data is then retrieved. Its size is validated, as well as the first
     26        byte of data in order to ensure the MPI represents an uncompressed EC point.
     27        The data is then written into the subjectPublicKey member.
     28
     29        Finally the encoded SubjectPublicKeyInfo structure data is extracted and returned
     30        from the platformExportSpki() function, completion the export operation.
     31
     32        * crypto/gcrypt/CryptoKeyECGCrypt.cpp:
     33        (WebCore::curveIdentifier):
     34        (WebCore::CryptoKeyEC::platformExportSpki):
     35
    1362017-07-02  Sam Weinig  <sam@webkit.org>
    237
  • trunk/Source/WebCore/PAL/ChangeLog

    r219055 r219064  
     12017-07-03  Zan Dobersek  <zdobersek@igalia.com>
     2
     3        [GCrypt] Implement CryptoKeyEC SPKI exports
     4        https://bugs.webkit.org/show_bug.cgi?id=173646
     5
     6        Reviewed by Jiewen Tan.
     7
     8        No new tests -- covered by existing Web Crypto tests.
     9
     10        Add three new libtasn1 utility functions.
     11
     12        createStructure() is a simple wrapper around asn1_create_element(), creating a new
     13        ASN.1 structure for the specified definition that's listed in WebCrypto.asn. The
     14        existing decodeStructure() is modified to use this new addition.
     15
     16        encodedData() retrieves the ASN.1-encoded data of the specified element that's
     17        located in the passed-in asn1_node. This is used when retrieving SPKI or PKCS#8
     18        data from filled-out ASN.1 structures.
     19
     20        writeElement() writes the provided data to the given asn1_node object under the
     21        specified element, using the given size. True is returned if this operation was
     22        successful.
     23
     24        * pal/crypto/tasn1/Utilities.cpp:
     25        (PAL::TASN1::createStructure):
     26        (PAL::TASN1::decodeStructure):
     27        (PAL::TASN1::encodedData):
     28        (PAL::TASN1::writeElement):
     29        * pal/crypto/tasn1/Utilities.h:
     30
    1312017-07-01  Dan Bernstein  <mitz@apple.com>
    232
  • trunk/Source/WebCore/PAL/pal/crypto/tasn1/Utilities.cpp

    r218626 r219064  
    103103}
    104104
     105bool createStructure(const char* elementName, asn1_node* root)
     106{
     107    int ret = asn1_create_element(asn1Definitions(), elementName, root);
     108    return ret == ASN1_SUCCESS;
     109}
     110
    105111bool decodeStructure(asn1_node* root, const char* elementName, const Vector<uint8_t>& data)
    106112{
    107     int ret = asn1_create_element(asn1Definitions(), elementName, root);
    108     if (ret != ASN1_SUCCESS)
     113    if (!createStructure(elementName, root))
    109114        return false;
    110115
    111116    int dataSize = data.size();
    112     ret = asn1_der_decoding2(root, data.data(), &dataSize, ASN1_DECODE_FLAG_STRICT_DER, nullptr);
     117    int ret = asn1_der_decoding2(root, data.data(), &dataSize, ASN1_DECODE_FLAG_STRICT_DER, nullptr);
    113118    return ret == ASN1_SUCCESS;
    114119}
     
    136141}
    137142
     143std::optional<Vector<uint8_t>> encodedData(asn1_node root, const char* elementName)
     144{
     145    int length = 0;
     146    int ret = asn1_der_coding(root, elementName, nullptr, &length, nullptr);
     147    if (ret != ASN1_MEM_ERROR)
     148        return std::nullopt;
     149
     150    Vector<uint8_t> data(length);
     151    ret = asn1_der_coding(root, elementName, data.data(), &length, nullptr);
     152    if (ret != ASN1_SUCCESS)
     153        return std::nullopt;
     154
     155    return data;
     156}
     157
     158bool writeElement(asn1_node root, const char* elementName, const void* data, size_t dataSize)
     159{
     160    int ret = asn1_write_value(root, elementName, data, dataSize);
     161    return ret == ASN1_SUCCESS;
     162}
     163
    138164} // namespace TASN1
    139165} // namespace PAL
  • trunk/Source/WebCore/PAL/pal/crypto/tasn1/Utilities.h

    r218626 r219064  
    5656};
    5757
     58bool createStructure(const char* elementName, asn1_node* root);
    5859bool decodeStructure(asn1_node* root, const char* elementName, const Vector<uint8_t>& data);
    5960std::optional<Vector<uint8_t>> elementData(asn1_node root, const char* elementName);
     61std::optional<Vector<uint8_t>> encodedData(asn1_node root, const char* elementName);
     62bool writeElement(asn1_node root, const char* elementName, const void* data, size_t dataSize);
    6063
    6164} // namespace TASN1
  • trunk/Source/WebCore/crypto/gcrypt/CryptoKeyECGCrypt.cpp

    r218840 r219064  
    6767}
    6868
     69static const char* curveIdentifier(CryptoKeyEC::NamedCurve curve)
     70{
     71    switch (curve) {
     72    case CryptoKeyEC::NamedCurve::P256:
     73        return "1.2.840.10045.3.1.7";
     74    case CryptoKeyEC::NamedCurve::P384:
     75        return "1.3.132.0.34";
     76    }
     77
     78    ASSERT_NOT_REACHED();
     79    return nullptr;
     80}
     81
    6982static unsigned uncompressedPointSizeForCurve(CryptoKeyEC::NamedCurve curve)
    7083{
     
    403416Vector<uint8_t> CryptoKeyEC::platformExportSpki() const
    404417{
     418    PAL::TASN1::Structure ecParameters;
     419    {
     420        // Create the `ECParameters` structure.
     421        if (!PAL::TASN1::createStructure("WebCrypto.ECParameters", &ecParameters))
     422            return { };
     423
     424        // Select the `namedCurve` object identifier as the target `ECParameters` choice.
     425        if (!PAL::TASN1::writeElement(ecParameters, "", "namedCurve", 1))
     426            return { };
     427
     428        // Write out the EC curve identifier under `namedCurve`.
     429        if (!PAL::TASN1::writeElement(ecParameters, "namedCurve", curveIdentifier(m_curve), 1))
     430            return { };
     431    }
     432
     433    PAL::TASN1::Structure spki;
     434    {
     435        // Create the `SubjectPublicKeyInfo` structure.
     436        if (!PAL::TASN1::createStructure("WebCrypto.SubjectPublicKeyInfo", &spki))
     437            return { };
     438
     439        // Write out the id-ecPublicKey identifier under `algorithm.algorithm`.
     440        // FIXME: Per specification this should write out id-ecDH when the ECDH algorithm
     441        // is specified for this CryptoKeyEC object, but not even the W3C tests expect that.
     442        if (!PAL::TASN1::writeElement(spki, "algorithm.algorithm", "1.2.840.10045.2.1", 1))
     443            return { };
     444
     445        // Write out the `ECParameters` data under `algorithm.parameters`.
     446        {
     447            auto data = PAL::TASN1::encodedData(ecParameters, "");
     448            if (!data || !PAL::TASN1::writeElement(spki, "algorithm.parameters", data->data(), data->size()))
     449                return { };
     450        }
     451
     452        // Retrieve the `q` s-expression, which should contain the public key data.
     453        PAL::GCrypt::Handle<gcry_sexp_t> qSexp(gcry_sexp_find_token(m_platformKey, "q", 0));
     454        if (!qSexp)
     455            return { };
     456
     457        // Retrieve the `q` data, which should be in the uncompressed point format.
     458        // Validate the data size and the first byte (which should be 0x04).
     459        auto qData = mpiData(qSexp);
     460        if (!qData || qData->size() != uncompressedPointSizeForCurve(m_curve) || qData->at(0) != 0x04)
     461            return { };
     462
     463        // Write out the public key data under `subjectPublicKey`. Because this is a
     464        // bit string parameter, the data size has to be multiplied by 8.
     465        if (!PAL::TASN1::writeElement(spki, "subjectPublicKey", qData->data(), qData->size() * 8))
     466            return { };
     467    }
     468
     469    // Retrieve the encoded `SubjectPublicKeyInfo` data and return it.
     470    auto result = PAL::TASN1::encodedData(spki, "");
     471    if (!result)
     472        return { };
     473
     474    return WTFMove(result.value());
     475}
     476
     477Vector<uint8_t> CryptoKeyEC::platformExportPkcs8() const
     478{
    405479    notImplemented();
    406480
     
    408482}
    409483
    410 Vector<uint8_t> CryptoKeyEC::platformExportPkcs8() const
    411 {
    412     notImplemented();
    413 
    414     return { };
    415 }
    416 
    417484} // namespace WebCore
    418485
Note: See TracChangeset for help on using the changeset viewer.