[GCrypt] Implement CryptoKeyEC::keySizeInBits(), ::platformGeneratePair()
authorzandobersek@gmail.com <zandobersek@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 3 Apr 2017 18:40:54 +0000 (18:40 +0000)
committerzandobersek@gmail.com <zandobersek@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 3 Apr 2017 18:40:54 +0000 (18:40 +0000)
https://bugs.webkit.org/show_bug.cgi?id=170345

Reviewed by Michael Catanzaro.

Source/WebCore:

Start implementing the libgcrypt-based platform bits of CryptoKeyEC.

Implement keySizeInBits() by returning the appropriate size for this
object's curve type. An assertion is added to ensure that this size
matches the one that's returned by gcry_pk_get_nbits() for this
object's EC key as represented by the m_platformKey gcry_sexp_t object.

Implement platformGeneratePair() by constructing a genkey s-expression
that requests a generation of an EC key for the specified curve type.
The s-expression is then passed to gcry_pk_genkey(), and the public
and private key data is then retrieved from the returned s-expression
upon success and used to create the public and private CryptoKeyEC
objects.

The PlatformECKey type alias is changed to match gcry_sexp_t. The
CryptoKeyEC destructor releases the gcry_sexp_t object through
a PAL::GCrypt::HandleDeleter<gcry_sexp_t> instance.

The method definitions in the CryptoKeyECGCrypt.cpp file are also
sorted to match the declaration order in the header.

No new tests -- current ones cover this sufficiently, but are not yet
enabled due to other missing platform-specific SUBTLE_CRYPTO
implementations.

* crypto/gcrypt/CryptoKeyECGCrypt.cpp:
(WebCore::curveSize):
(WebCore::curveName):
(WebCore::CryptoKeyEC::~CryptoKeyEC):
(WebCore::CryptoKeyEC::keySizeInBits):
(WebCore::CryptoKeyEC::platformGeneratePair):
(WebCore::CryptoKeyEC::platformImportSpki):
(WebCore::CryptoKeyEC::platformImportPkcs8):
(WebCore::CryptoKeyEC::platformExportRaw):
(WebCore::CryptoKeyEC::platformAddFieldElements):
(WebCore::CryptoKeyEC::platformExportSpki):
* crypto/keys/CryptoKeyEC.h:

Source/WebCore/PAL:

* pal/crypto/gcrypt/Handle.h:
(PAL::GCrypt::HandleDeleter<gcry_sexp_t>::operator()): Add a HandleDeleter
specialization for the gcry_sexp_t type.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214825 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/PAL/ChangeLog
Source/WebCore/PAL/pal/crypto/gcrypt/Handle.h
Source/WebCore/crypto/gcrypt/CryptoKeyECGCrypt.cpp
Source/WebCore/crypto/keys/CryptoKeyEC.h

index d0b961c..f2cea27 100644 (file)
@@ -1,5 +1,50 @@
 2017-04-03  Zan Dobersek  <zdobersek@igalia.com>
 
+        [GCrypt] Implement CryptoKeyEC::keySizeInBits(), ::platformGeneratePair()
+        https://bugs.webkit.org/show_bug.cgi?id=170345
+
+        Reviewed by Michael Catanzaro.
+
+        Start implementing the libgcrypt-based platform bits of CryptoKeyEC.
+
+        Implement keySizeInBits() by returning the appropriate size for this
+        object's curve type. An assertion is added to ensure that this size
+        matches the one that's returned by gcry_pk_get_nbits() for this
+        object's EC key as represented by the m_platformKey gcry_sexp_t object.
+
+        Implement platformGeneratePair() by constructing a genkey s-expression
+        that requests a generation of an EC key for the specified curve type.
+        The s-expression is then passed to gcry_pk_genkey(), and the public
+        and private key data is then retrieved from the returned s-expression
+        upon success and used to create the public and private CryptoKeyEC
+        objects.
+
+        The PlatformECKey type alias is changed to match gcry_sexp_t. The
+        CryptoKeyEC destructor releases the gcry_sexp_t object through
+        a PAL::GCrypt::HandleDeleter<gcry_sexp_t> instance.
+
+        The method definitions in the CryptoKeyECGCrypt.cpp file are also
+        sorted to match the declaration order in the header.
+
+        No new tests -- current ones cover this sufficiently, but are not yet
+        enabled due to other missing platform-specific SUBTLE_CRYPTO
+        implementations.
+
+        * crypto/gcrypt/CryptoKeyECGCrypt.cpp:
+        (WebCore::curveSize):
+        (WebCore::curveName):
+        (WebCore::CryptoKeyEC::~CryptoKeyEC):
+        (WebCore::CryptoKeyEC::keySizeInBits):
+        (WebCore::CryptoKeyEC::platformGeneratePair):
+        (WebCore::CryptoKeyEC::platformImportSpki):
+        (WebCore::CryptoKeyEC::platformImportPkcs8):
+        (WebCore::CryptoKeyEC::platformExportRaw):
+        (WebCore::CryptoKeyEC::platformAddFieldElements):
+        (WebCore::CryptoKeyEC::platformExportSpki):
+        * crypto/keys/CryptoKeyEC.h:
+
+2017-04-03  Zan Dobersek  <zdobersek@igalia.com>
+
         [GCrypt] Implement AES_KW support
         https://bugs.webkit.org/show_bug.cgi?id=170274
 
index 7671ddc..271038f 100644 (file)
@@ -1,5 +1,16 @@
 2017-04-03  Zan Dobersek  <zdobersek@igalia.com>
 
+        [GCrypt] Implement CryptoKeyEC::keySizeInBits(), ::platformGeneratePair()
+        https://bugs.webkit.org/show_bug.cgi?id=170345
+
+        Reviewed by Michael Catanzaro.
+
+        * pal/crypto/gcrypt/Handle.h:
+        (PAL::GCrypt::HandleDeleter<gcry_sexp_t>::operator()): Add a HandleDeleter
+        specialization for the gcry_sexp_t type.
+
+2017-04-03  Zan Dobersek  <zdobersek@igalia.com>
+
         [GCrypt] Implement AES_GCM support
         https://bugs.webkit.org/show_bug.cgi?id=170271
 
index a15b099..0d667f3 100644 (file)
@@ -98,5 +98,13 @@ struct HandleDeleter<gcry_mac_hd_t> {
     }
 };
 
+template<>
+struct HandleDeleter<gcry_sexp_t> {
+    void operator()(gcry_sexp_t handle)
+    {
+        gcry_sexp_release(handle);
+    }
+};
+
 } // namespace GCrypt
 } // namespace PAL
index 55d6d14..c11125d 100644 (file)
 
 #include "CryptoKeyPair.h"
 #include "NotImplemented.h"
+#include <pal/crypto/gcrypt/Handle.h>
+#include <pal/crypto/gcrypt/Utilities.h>
 
 namespace WebCore {
 
-struct _PlatformECKeyGnuTLS {
-};
-
-CryptoKeyEC::~CryptoKeyEC()
+static size_t curveSize(CryptoKeyEC::NamedCurve curve)
 {
-    notImplemented();
+    switch (curve) {
+    case CryptoKeyEC::NamedCurve::P256:
+        return 256;
+    case CryptoKeyEC::NamedCurve::P384:
+        return 384;
+    }
 }
 
-size_t CryptoKeyEC::keySizeInBits() const
+static const char* curveName(CryptoKeyEC::NamedCurve curve)
 {
-    notImplemented();
-
-    return 0;
+    switch (curve) {
+    case CryptoKeyEC::NamedCurve::P256:
+        return "NIST P-256";
+    case CryptoKeyEC::NamedCurve::P384:
+        return "NIST P-384";
+    }
 }
 
-Vector<uint8_t> CryptoKeyEC::platformExportRaw() const
+CryptoKeyEC::~CryptoKeyEC()
 {
-    notImplemented();
-
-    return { };
+    if (m_platformKey)
+        PAL::GCrypt::HandleDeleter<gcry_sexp_t>()(m_platformKey);
 }
 
-std::optional<CryptoKeyPair> CryptoKeyEC::platformGeneratePair(CryptoAlgorithmIdentifier, NamedCurve, bool, CryptoKeyUsageBitmap)
+size_t CryptoKeyEC::keySizeInBits() const
 {
-    notImplemented();
+    size_t size = curveSize(m_curve);
+    ASSERT(size == gcry_pk_get_nbits(m_platformKey));
+    return size;
+}
 
-    return std::nullopt;
+std::optional<CryptoKeyPair> CryptoKeyEC::platformGeneratePair(CryptoAlgorithmIdentifier identifier, NamedCurve curve, bool extractable, CryptoKeyUsageBitmap usages)
+{
+    PAL::GCrypt::Handle<gcry_sexp_t> genkeySexp;
+    gcry_error_t error = gcry_sexp_build(&genkeySexp, nullptr, "(genkey(ecc(curve %s)))", curveName(curve));
+    if (error != GPG_ERR_NO_ERROR) {
+        PAL::GCrypt::logError(error);
+        return std::nullopt;
+    }
+
+    PAL::GCrypt::Handle<gcry_sexp_t> keyPairSexp;
+    error = gcry_pk_genkey(&keyPairSexp, genkeySexp);
+    if (error != GPG_ERR_NO_ERROR) {
+        PAL::GCrypt::logError(error);
+        return std::nullopt;
+    }
+
+    PAL::GCrypt::Handle<gcry_sexp_t> publicKeySexp(gcry_sexp_find_token(keyPairSexp, "public-key", 0));
+    PAL::GCrypt::Handle<gcry_sexp_t> privateKeySexp(gcry_sexp_find_token(keyPairSexp, "private-key", 0));
+    if (!publicKeySexp || !privateKeySexp)
+        return std::nullopt;
+
+    auto publicKey = CryptoKeyEC::create(identifier, curve, CryptoKeyType::Public, publicKeySexp.release(), true, usages);
+    auto privateKey = CryptoKeyEC::create(identifier, curve, CryptoKeyType::Private, privateKeySexp.release(), extractable, usages);
+    return CryptoKeyPair { WTFMove(publicKey), WTFMove(privateKey) };
 }
 
 RefPtr<CryptoKeyEC> CryptoKeyEC::platformImportRaw(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&&, bool, CryptoKeyUsageBitmap)
@@ -83,30 +115,37 @@ RefPtr<CryptoKeyEC> CryptoKeyEC::platformImportJWKPrivate(CryptoAlgorithmIdentif
     return nullptr;
 }
 
-void CryptoKeyEC::platformAddFieldElements(JsonWebKey&) const
+RefPtr<CryptoKeyEC> CryptoKeyEC::platformImportSpki(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&&, bool, CryptoKeyUsageBitmap)
 {
     notImplemented();
+
+    return nullptr;
 }
 
-RefPtr<CryptoKeyEC> CryptoKeyEC::platformImportSpki(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&&, bool, CryptoKeyUsageBitmap)
+RefPtr<CryptoKeyEC> CryptoKeyEC::platformImportPkcs8(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&&, bool, CryptoKeyUsageBitmap)
 {
     notImplemented();
 
     return nullptr;
 }
 
-Vector<uint8_t> CryptoKeyEC::platformExportSpki() const
+Vector<uint8_t> CryptoKeyEC::platformExportRaw() const
 {
     notImplemented();
 
     return { };
 }
 
-RefPtr<CryptoKeyEC> CryptoKeyEC::platformImportPkcs8(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&&, bool, CryptoKeyUsageBitmap)
+void CryptoKeyEC::platformAddFieldElements(JsonWebKey&) const
 {
     notImplemented();
+}
 
-    return nullptr;
+Vector<uint8_t> CryptoKeyEC::platformExportSpki() const
+{
+    notImplemented();
+
+    return { };
 }
 
 Vector<uint8_t> CryptoKeyEC::platformExportPkcs8() const
index f18d414..443a682 100644 (file)
@@ -37,8 +37,9 @@ typedef CCECCryptorRef PlatformECKey;
 #endif
 
 #if PLATFORM(GTK)
-typedef struct _PlatformECKeyGnuTLS PlatformECKeyGnuTLS;
-typedef PlatformECKeyGnuTLS *PlatformECKey;
+// gcry_sexp* equates gcry_sexp_t.
+struct gcry_sexp;
+typedef gcry_sexp* PlatformECKey;
 #endif