[Curl] implement CertificateInfo::summaryInfo
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 5 Aug 2019 07:34:23 +0000 (07:34 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 5 Aug 2019 07:34:23 +0000 (07:34 +0000)
https://bugs.webkit.org/show_bug.cgi?id=191498

Patch by Takashi Komori <Takashi.Komori@sony.com> on 2019-08-05
Reviewed by Alex Christensen.

Source/WebCore:

Implement CertificaeInfo::SummaryInfo.
This patch makes WebInspector show summary of certificates.

Tests: http/tests/inspector/network/resource-security-certificate.html
       http/tests/inspector/network/getSerializedCertificate.html

* platform/Curl.cmake:
* platform/network/curl/CertificateInfo.h:
(WTF::Persistence::Coder<WebCore::CertificateInfo>::encode):
(WTF::Persistence::Coder<WebCore::CertificateInfo>::decode):
(WebCore::CertificateInfo::summaryInfo const): Deleted.
* platform/network/curl/CertificateInfoCurl.cpp:
(WebCore::CertificateInfo::summaryInfo const):
* platform/network/curl/CurlSSLVerifier.cpp:
(WebCore::CurlSSLVerifier::collectInfo):
(WebCore::CurlSSLVerifier::verifyCallback):
(WebCore::StackOfX509::StackOfX509): Deleted.
(WebCore::StackOfX509::~StackOfX509): Deleted.
(WebCore::StackOfX509::count): Deleted.
(WebCore::StackOfX509::item): Deleted.
(): Deleted.
(WebCore::BIOHolder::BIOHolder): Deleted.
(WebCore::BIOHolder::~BIOHolder): Deleted.
(WebCore::BIOHolder::write): Deleted.
(WebCore::BIOHolder::asCertificate): Deleted.
(WebCore::pemDataFromCtx): Deleted.
* platform/network/curl/CurlSSLVerifier.h:
* platform/network/curl/OpenSSLHelper.cpp: Added.
(OpenSSL::deleter<X509>::operator()):
(OpenSSL::StackOfGeneralName::StackOfGeneralName):
(OpenSSL::StackOfGeneralName::~StackOfGeneralName):
(OpenSSL::StackOfGeneralName::operator bool):
(OpenSSL::StackOfGeneralName::count):
(OpenSSL::StackOfGeneralName::item):
(OpenSSL::StackOfX509::StackOfX509):
(OpenSSL::StackOfX509::~StackOfX509):
(OpenSSL::StackOfX509::count):
(OpenSSL::StackOfX509::item):
(OpenSSL::BIO::BIO):
(OpenSSL::BIO::~BIO):
(OpenSSL::BIO::getDataAsVector const):
(OpenSSL::BIO::getDataAsString const):
(OpenSSL::BIO::readX509):
(OpenSSL::BIO::get):
(OpenSSL::pemDataFromCtx):
(OpenSSL::createCertificateInfo):
(OpenSSL::toString):
(OpenSSL::getCommonName):
(OpenSSL::getSubjectName):
(OpenSSL::convertASN1TimeToSeconds):
(OpenSSL::getSubjectAltName):
(OpenSSL::createSummaryInfo):
* platform/network/curl/OpenSSLHelper.h: Copied from Source/WebCore/platform/network/curl/CertificateInfoCurl.cpp.

Source/WTF:

Fixed function template for encoding vector.

* wtf/persistence/PersistentCoders.h:

LayoutTests:

* platform/wincairo-wk1/TestExpectations:
* platform/wincairo/TestExpectations:

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

13 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/wincairo-wk1/TestExpectations
LayoutTests/platform/wincairo/TestExpectations
Source/WTF/ChangeLog
Source/WTF/wtf/persistence/PersistentCoders.h
Source/WebCore/ChangeLog
Source/WebCore/platform/Curl.cmake
Source/WebCore/platform/network/curl/CertificateInfo.h
Source/WebCore/platform/network/curl/CertificateInfoCurl.cpp
Source/WebCore/platform/network/curl/CurlSSLVerifier.cpp
Source/WebCore/platform/network/curl/CurlSSLVerifier.h
Source/WebCore/platform/network/curl/OpenSSLHelper.cpp [new file with mode: 0644]
Source/WebCore/platform/network/curl/OpenSSLHelper.h [new file with mode: 0644]

index 9275dfe..64a4e41 100644 (file)
@@ -1,3 +1,13 @@
+2019-08-05  Takashi Komori  <Takashi.Komori@sony.com>
+
+        [Curl] implement CertificateInfo::summaryInfo
+        https://bugs.webkit.org/show_bug.cgi?id=191498
+
+        Reviewed by Alex Christensen.
+
+        * platform/wincairo-wk1/TestExpectations:
+        * platform/wincairo/TestExpectations:
+
 2019-08-04  Youenn Fablet  <youenn@apple.com>
 
         WebRTC: got incorrect `this` in negotiationneeded event
index 2b71cd6..915d763 100644 (file)
@@ -331,3 +331,7 @@ fast/css/transition-color-unspecified.html [ Skip ]
 fast/filter-image/filter-image-animation.html [ Skip ]
 resize-observer/modify-frametree-in-callback.html [ Skip ]
 resize-observer/multi-frames.html [ Skip ]
+
+# WinCairo wk1 doesn't support inspector tests.
+webkit.org/b/191498 http/tests/inspector/network/resource-security-certificate.html [ Skip ]
+webkit.org/b/191498 http/tests/inspector/network/getSerializedCertificate.html [ Skip ]
index 7bec062..e290e08 100644 (file)
@@ -1018,8 +1018,8 @@ http/tests/xmlhttprequest/xmlhttprequest-overridemimetype-content-type-header.ht
 http/tests/xmlviewer [ Skip ]
 
 webkit.org/b/192406 http/tests/inspector/network/resource-security-connection.html [ Skip ]
-webkit.org/b/191498 http/tests/inspector/network/resource-security-certificate.html [ Skip ]
-webkit.org/b/191498 http/tests/inspector/network/getSerializedCertificate.html [ Skip ]
+webkit.org/b/191498 http/tests/inspector/network/resource-security-certificate.html [ Pass ]
+webkit.org/b/191498 http/tests/inspector/network/getSerializedCertificate.html [ Pass ]
 
 #///////////////////////////////////////////////////////////////////////////////
 # Issue categories below are shared with other platforms (primarily AppleWin)
index 3365a22..1ac7f9b 100644 (file)
@@ -1,3 +1,14 @@
+2019-08-05  Takashi Komori  <Takashi.Komori@sony.com>
+
+        [Curl] implement CertificateInfo::summaryInfo
+        https://bugs.webkit.org/show_bug.cgi?id=191498
+
+        Reviewed by Alex Christensen.
+
+        Fixed function template for encoding vector.
+
+        * wtf/persistence/PersistentCoders.h:
+
 2019-08-02  Mark Lam  <mark.lam@apple.com>
 
         [ARM64E] Harden the diversity of the DOMJIT::Signature::unsafeFunction pointer.
index 909532d..faaa9f4 100644 (file)
@@ -150,7 +150,7 @@ template<typename T, size_t inlineCapacity> struct VectorCoder<true, T, inlineCa
     static void encode(Encoder& encoder, const Vector<T, inlineCapacity>& vector)
     {
         encoder << static_cast<uint64_t>(vector.size());
-        encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(vector.data()), vector.size() * sizeof(T), alignof(T));
+        encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(vector.data()), vector.size() * sizeof(T));
     }
     
     static bool decode(Decoder& decoder, Vector<T, inlineCapacity>& vector)
index cfeebcf..19bf6bb 100644 (file)
@@ -1,3 +1,64 @@
+2019-08-05  Takashi Komori  <Takashi.Komori@sony.com>
+
+        [Curl] implement CertificateInfo::summaryInfo
+        https://bugs.webkit.org/show_bug.cgi?id=191498
+
+        Reviewed by Alex Christensen.
+
+        Implement CertificaeInfo::SummaryInfo.
+        This patch makes WebInspector show summary of certificates.
+
+        Tests: http/tests/inspector/network/resource-security-certificate.html
+               http/tests/inspector/network/getSerializedCertificate.html
+
+        * platform/Curl.cmake:
+        * platform/network/curl/CertificateInfo.h:
+        (WTF::Persistence::Coder<WebCore::CertificateInfo>::encode):
+        (WTF::Persistence::Coder<WebCore::CertificateInfo>::decode):
+        (WebCore::CertificateInfo::summaryInfo const): Deleted.
+        * platform/network/curl/CertificateInfoCurl.cpp:
+        (WebCore::CertificateInfo::summaryInfo const):
+        * platform/network/curl/CurlSSLVerifier.cpp:
+        (WebCore::CurlSSLVerifier::collectInfo):
+        (WebCore::CurlSSLVerifier::verifyCallback):
+        (WebCore::StackOfX509::StackOfX509): Deleted.
+        (WebCore::StackOfX509::~StackOfX509): Deleted.
+        (WebCore::StackOfX509::count): Deleted.
+        (WebCore::StackOfX509::item): Deleted.
+        (): Deleted.
+        (WebCore::BIOHolder::BIOHolder): Deleted.
+        (WebCore::BIOHolder::~BIOHolder): Deleted.
+        (WebCore::BIOHolder::write): Deleted.
+        (WebCore::BIOHolder::asCertificate): Deleted.
+        (WebCore::pemDataFromCtx): Deleted.
+        * platform/network/curl/CurlSSLVerifier.h:
+        * platform/network/curl/OpenSSLHelper.cpp: Added.
+        (OpenSSL::deleter<X509>::operator()):
+        (OpenSSL::StackOfGeneralName::StackOfGeneralName):
+        (OpenSSL::StackOfGeneralName::~StackOfGeneralName):
+        (OpenSSL::StackOfGeneralName::operator bool):
+        (OpenSSL::StackOfGeneralName::count):
+        (OpenSSL::StackOfGeneralName::item):
+        (OpenSSL::StackOfX509::StackOfX509):
+        (OpenSSL::StackOfX509::~StackOfX509):
+        (OpenSSL::StackOfX509::count):
+        (OpenSSL::StackOfX509::item):
+        (OpenSSL::BIO::BIO):
+        (OpenSSL::BIO::~BIO):
+        (OpenSSL::BIO::getDataAsVector const):
+        (OpenSSL::BIO::getDataAsString const):
+        (OpenSSL::BIO::readX509):
+        (OpenSSL::BIO::get):
+        (OpenSSL::pemDataFromCtx):
+        (OpenSSL::createCertificateInfo):
+        (OpenSSL::toString):
+        (OpenSSL::getCommonName):
+        (OpenSSL::getSubjectName):
+        (OpenSSL::convertASN1TimeToSeconds):
+        (OpenSSL::getSubjectAltName):
+        (OpenSSL::createSummaryInfo):
+        * platform/network/curl/OpenSSLHelper.h: Copied from Source/WebCore/platform/network/curl/CertificateInfoCurl.cpp.
+
 2019-08-04  Youenn Fablet  <youenn@apple.com>
 
         WebRTC: got incorrect `this` in negotiationneeded event
index 0064adf..c171789 100644 (file)
@@ -24,6 +24,7 @@ list(APPEND WebCore_SOURCES
     platform/network/curl/CurlSSLVerifier.cpp
     platform/network/curl/DNSResolveQueueCurl.cpp
     platform/network/curl/NetworkStorageSessionCurl.cpp
+    platform/network/curl/OpenSSLHelper.cpp
     platform/network/curl/ProtectionSpaceCurl.cpp
     platform/network/curl/ProxyServerCurl.cpp
     platform/network/curl/PublicSuffixCurl.cpp
@@ -51,11 +52,15 @@ list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS
     platform/network/curl/CurlProxySettings.h
     platform/network/curl/CurlRequest.h
     platform/network/curl/CurlRequestClient.h
+    platform/network/curl/CurlRequestScheduler.h
     platform/network/curl/CurlRequestSchedulerClient.h
     platform/network/curl/CurlResourceHandleDelegate.h
     platform/network/curl/CurlResponse.h
     platform/network/curl/CurlSSLHandle.h
+    platform/network/curl/CurlSSLVerifier.h
+    platform/network/curl/DNSResolveQueueCurl.h
     platform/network/curl/DownloadBundle.h
+    platform/network/curl/OpenSSLHelper.h
     platform/network/curl/ProtectionSpaceCurl.h
     platform/network/curl/ResourceError.h
     platform/network/curl/ResourceRequest.h
index e57f3bd..2fb6fec 100644 (file)
@@ -49,7 +49,7 @@ public:
 
     bool containsNonRootSHA1SignedCertificate() const { notImplemented(); return false; }
 
-    Optional<SummaryInfo> summaryInfo() const { notImplemented(); return WTF::nullopt; }
+    Optional<SummaryInfo> summaryInfo() const;
 
     bool isEmpty() const { return m_certificateChain.isEmpty(); }
 
@@ -71,15 +71,37 @@ namespace WTF {
 namespace Persistence {
 
 template<> struct Coder<WebCore::CertificateInfo> {
-    static void encode(Encoder&, const WebCore::CertificateInfo&)
+    static void encode(Encoder& encoder, const WebCore::CertificateInfo& certificateInfo)
     {
-        notImplemented();
+        auto& certificateChain = certificateInfo.certificateChain();
+
+        encoder << certificateInfo.verificationError();
+        encoder << certificateChain.size();
+        for (auto& certificate : certificateChain)
+            encoder << certificate;
     }
 
-    static bool decode(Decoder&, WebCore::CertificateInfo&)
+    static bool decode(Decoder& decoder, WebCore::CertificateInfo& certificateInfo)
     {
-        notImplemented();
-        return false;
+        int verificationError;
+        if (!decoder.decode(verificationError))
+            return false;
+
+        size_t numOfCert = 0;
+        if (!decoder.decode(numOfCert))
+            return false;
+
+        WebCore::CertificateInfo::CertificateChain certificateChain;
+        for (size_t i = 0; i < numOfCert; i++) {
+            WebCore::CertificateInfo::Certificate certificate;
+            if (!decoder.decode(certificate))
+                return false;
+
+            certificateChain.append(WTFMove(certificate));
+        }
+
+        certificateInfo = WebCore::CertificateInfo(verificationError, WTFMove(certificateChain));
+        return true;
     }
 };
 
index 0a5339f..279b36c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Sony Interactive Entertainment Inc.
+ * Copyright (C) 2019 Sony Interactive Entertainment Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "CertificateInfo.h"
 
+#include "OpenSSLHelper.h"
 #include <wtf/CrossThreadCopier.h>
 
 #if USE(CURL)
@@ -50,6 +51,14 @@ CertificateInfo::Certificate CertificateInfo::makeCertificate(const uint8_t* buf
     return certificate;
 }
 
+Optional<CertificateInfo::SummaryInfo> CertificateInfo::summaryInfo() const
+{
+    if (!m_certificateChain.size())
+        return WTF::nullopt;
+
+    return OpenSSL::createSummaryInfo(m_certificateChain.at(0));
+}
+
 }
 
 #endif
index 8094b93..bf14b28 100644 (file)
 #if USE(CURL)
 #include "CurlContext.h"
 #include "CurlSSLHandle.h"
-#include <openssl/ssl.h>
 
 namespace WebCore {
 
-static Vector<CertificateInfo::Certificate> pemDataFromCtx(X509StoreCTX*);
 static CurlSSLVerifier::SSLCertificateFlags convertToSSLCertificateFlags(unsigned);
 
 CurlSSLVerifier::CurlSSLVerifier(void* sslCtx)
@@ -61,15 +59,16 @@ CurlSSLVerifier::CurlSSLVerifier(void* sslCtx)
         SSL_CTX_set1_curves_list(ctx, curvesList.utf8().data());
 }
 
-void CurlSSLVerifier::collectInfo(X509StoreCTX* ctx)
+void CurlSSLVerifier::collectInfo(X509_STORE_CTX* ctx)
 {
-    m_certificateInfo = CertificateInfo { X509_STORE_CTX_get_error(ctx), pemDataFromCtx(ctx) };
+    if (auto certificateInfo = OpenSSL::createCertificateInfo(ctx))
+        m_certificateInfo = WTFMove(*certificateInfo);
 
     if (auto error = m_certificateInfo.verificationError())
         m_sslErrors = static_cast<int>(convertToSSLCertificateFlags(error));
 }
 
-int CurlSSLVerifier::verifyCallback(int preverified, X509StoreCTX* ctx)
+int CurlSSLVerifier::verifyCallback(int preverified, X509_STORE_CTX* ctx)
 {
     auto ssl = static_cast<SSL*>(X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
     auto sslCtx = SSL_get_SSL_CTX(ssl);
@@ -80,75 +79,6 @@ int CurlSSLVerifier::verifyCallback(int preverified, X509StoreCTX* ctx)
     return preverified;
 }
 
-class StackOfX509 {
-public:
-    explicit StackOfX509(X509StoreCTX* ctx)
-        : m_certs { X509_STORE_CTX_get1_chain(ctx) }
-    {
-    }
-
-    ~StackOfX509()
-    {
-        if (m_certs)
-            sk_X509_pop_free(m_certs, X509_free);
-    }
-
-    unsigned count() { return sk_X509_num(m_certs); }
-    X509* item(unsigned i) { return sk_X509_value(m_certs, i); }
-
-private:
-    STACK_OF(X509)* m_certs { nullptr };
-};
-
-class BIOHolder {
-public:
-    BIOHolder()
-        : m_bio { BIO_new(BIO_s_mem()) }
-    {
-    }
-
-    ~BIOHolder()
-    {
-        if (m_bio)
-            BIO_free(m_bio);
-    }
-
-    bool write(X509* data) { return PEM_write_bio_X509(m_bio, data); }
-    CertificateInfo::Certificate asCertificate()
-    {
-        uint8_t* data;
-        long length = BIO_get_mem_data(m_bio, &data);
-        if (length < 0)
-            return CertificateInfo::Certificate();
-
-        auto cert = CertificateInfo::makeCertificate(data, length);
-        return cert;
-    }
-
-private:
-    BIO* m_bio { nullptr };
-};
-
-static Vector<CertificateInfo::Certificate> pemDataFromCtx(X509StoreCTX* ctx)
-{
-    Vector<CertificateInfo::Certificate> result;
-    StackOfX509 certs { ctx };
-    for (int i = 0; i < certs.count(); i++) {
-        BIOHolder bio;
-
-        if (!bio.write(certs.item(i)))
-            return Vector<CertificateInfo::Certificate> { };
-
-        auto certificate = bio.asCertificate();
-        if (certificate.isEmpty())
-            return Vector<CertificateInfo::Certificate> { };
-
-        result.append(WTFMove(certificate));
-    }
-
-    return result;
-}
-
 static CurlSSLVerifier::SSLCertificateFlags convertToSSLCertificateFlags(unsigned sslError)
 {
     switch (sslError) {
index 9e3b800..452f705 100644 (file)
 #pragma once
 
 #include "CertificateInfo.h"
+#include "OpenSSLHelper.h"
 #include <wtf/Noncopyable.h>
 #include <wtf/text/WTFString.h>
 
-struct x509_store_ctx_st;
-typedef struct x509_store_ctx_st X509StoreCTX;
-
 namespace WebCore {
 
-class CurlHandle;
-
 class CurlSSLVerifier {
     WTF_MAKE_NONCOPYABLE(CurlSSLVerifier);
 public:
@@ -56,12 +52,11 @@ public:
     const CertificateInfo& certificateInfo() const { return m_certificateInfo; }
 
 private:
-    static int verifyCallback(int, X509StoreCTX*);
+    static int verifyCallback(int, X509_STORE_CTX*);
+    void collectInfo(X509_STORE_CTX*);
 
     int m_sslErrors { 0 };
     CertificateInfo m_certificateInfo;
-
-    void collectInfo(X509StoreCTX*);
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/network/curl/OpenSSLHelper.cpp b/Source/WebCore/platform/network/curl/OpenSSLHelper.cpp
new file mode 100644 (file)
index 0000000..e5fc483
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2019 Sony Interactive Entertainment Inc.
+ *
+ * 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 "OpenSSLHelper.h"
+
+#include <openssl/x509v3.h>
+#include <wtf/DateMath.h>
+#include <wtf/HexNumber.h>
+#include <wtf/Seconds.h>
+#include <wtf/text/StringBuilder.h>
+
+namespace OpenSSL {
+
+template<typename> struct deleter;
+template<> struct deleter<X509> {
+    void operator()(X509* x509)
+    {
+        if (x509)
+            X509_free(x509);
+    }
+};
+
+class StackOfGeneralName {
+public:
+    StackOfGeneralName(const X509* x509, int nid)
+        : m_names { static_cast<STACK_OF(GENERAL_NAME)*>(X509_get_ext_d2i(x509, nid, nullptr, nullptr)) }
+    {
+    }
+
+    ~StackOfGeneralName()
+    {
+        if (m_names)
+            sk_GENERAL_NAME_pop_free(m_names, GENERAL_NAME_free);
+    }
+
+    operator bool() { return m_names; }
+
+    int count() { return sk_GENERAL_NAME_num(m_names); }
+    GENERAL_NAME* item(int i) { return sk_GENERAL_NAME_value(m_names, i); }
+
+private:
+    STACK_OF(GENERAL_NAME)* m_names { nullptr };
+};
+
+class StackOfX509 {
+public:
+    StackOfX509(X509_STORE_CTX* ctx)
+        : m_certs { X509_STORE_CTX_get1_chain(ctx) }
+    {
+    }
+
+    ~StackOfX509()
+    {
+        if (m_certs)
+            sk_X509_pop_free(m_certs, X509_free);
+    }
+
+    int count() { return sk_X509_num(m_certs); }
+    X509* item(int i) { return sk_X509_value(m_certs, i); }
+
+private:
+    STACK_OF(X509)* m_certs { nullptr };
+};
+
+class BIO {
+public:
+    BIO()
+        : m_bio { ::BIO_new(::BIO_s_mem()) }
+    {
+    }
+
+    BIO(X509* data)
+        : m_bio { ::BIO_new(::BIO_s_mem()) }
+    {
+        ::PEM_write_bio_X509(m_bio, data);
+    }
+
+    BIO(const Vector<uint8_t>& data)
+        : m_bio { ::BIO_new_mem_buf(data.data(), data.size()) }
+    {
+    }
+
+    ~BIO()
+    {
+        if (m_bio)
+            ::BIO_free(m_bio);
+    }
+
+    Optional<Vector<uint8_t>> getDataAsVector() const
+    {
+        uint8_t* data { nullptr };
+        auto length = ::BIO_get_mem_data(m_bio, &data);
+        if (length < 0)
+            return WTF::nullopt;
+
+        Vector<uint8_t> result;
+        result.append(data, length);
+        return result;
+    }
+
+    String getDataAsString() const
+    {
+        uint8_t* data { nullptr };
+        auto length = ::BIO_get_mem_data(m_bio, &data);
+        if (length < 0)
+            return String();
+
+        return String(data, length);
+    }
+
+    std::unique_ptr<X509, deleter<X509>> readX509()
+    {
+        return std::unique_ptr<X509, deleter<X509>>(::PEM_read_bio_X509(m_bio, nullptr, 0, nullptr));
+    }
+
+    ::BIO* get() { return m_bio; }
+
+private:
+    ::BIO* m_bio { nullptr };
+};
+
+
+static Vector<WebCore::CertificateInfo::Certificate> pemDataFromCtx(X509_STORE_CTX* ctx)
+{
+    Vector<WebCore::CertificateInfo::Certificate> result;
+    StackOfX509 certs { ctx };
+
+    for (int i = 0; i < certs.count(); i++) {
+        BIO bio(certs.item(i));
+
+        if (auto certificate = bio.getDataAsVector())
+            result.append(WTFMove(*certificate));
+        else
+            return { };
+    }
+
+    return result;
+}
+
+Optional<WebCore::CertificateInfo> createCertificateInfo(X509_STORE_CTX* ctx)
+{
+    if (!ctx)
+        return WTF::nullopt;
+
+    return WebCore::CertificateInfo(X509_STORE_CTX_get_error(ctx), pemDataFromCtx(ctx));
+}
+
+static String toString(const ASN1_STRING* name)
+{
+    unsigned char* data { nullptr };
+    auto length = ASN1_STRING_to_UTF8(&data, name);
+    if (length <= 0)
+        return String();
+
+    String result(data, length);
+    OPENSSL_free(data);
+    return result;
+}
+
+static String getCommonName(const X509* x509)
+{
+    auto subjectName = X509_get_subject_name(x509);
+    if (!subjectName)
+        return String();
+
+    auto index = X509_NAME_get_index_by_NID(subjectName, NID_commonName, -1);
+    if (index < 0)
+        return String();
+
+    auto commonNameEntry = X509_NAME_get_entry(subjectName, index);
+    if (!commonNameEntry)
+        return String();
+
+    auto commonNameEntryData = X509_NAME_ENTRY_get_data(commonNameEntry);
+    if (!commonNameEntryData)
+        return String();
+
+    return toString(commonNameEntryData);
+}
+
+static String getSubjectName(const X509* x509)
+{
+    static const unsigned long flags = (ASN1_STRFLGS_RFC2253 | ASN1_STRFLGS_ESC_QUOTE | XN_FLAG_SEP_CPLUS_SPC | XN_FLAG_DN_REV | XN_FLAG_FN_NONE | XN_FLAG_SPC_EQ) & ~ASN1_STRFLGS_ESC_MSB;
+
+    auto subjectName = X509_get_subject_name(x509);
+    if (!subjectName)
+        return String();
+
+    BIO bio;
+    auto length = X509_NAME_print_ex(bio.get(), subjectName, 0, flags);
+    if (length <= 0)
+        return String();
+
+    return bio.getDataAsString();
+}
+
+static Optional<Seconds> convertASN1TimeToSeconds(const ASN1_TIME* ans1Time)
+{
+    if (!ans1Time)
+        return WTF::nullopt;
+
+    if ((ans1Time->type != V_ASN1_UTCTIME && ans1Time->type != V_ASN1_GENERALIZEDTIME) || !ans1Time->data)
+        return WTF::nullopt;
+
+    // UTCTIME         : YYmmddHHMM[SS]
+    // GENERALIZEDTIME : YYYYmmddHHMM[SS]
+    int digitLength = ans1Time->type == V_ASN1_UTCTIME ? 10 : 12;
+    if (ans1Time->length < digitLength)
+        return WTF::nullopt;
+
+    auto data = ans1Time->data;
+    for (int i = 0; i < digitLength; i++) {
+        if (!isASCIIDigit(data[i]))
+            return WTF::nullopt;
+    }
+
+    struct tm time { };
+
+    if (ans1Time->type == V_ASN1_UTCTIME) {
+        time.tm_year = (data[0] - '0') * 10 + (data[1] - '0');
+        if (time.tm_year < 50)
+            time.tm_year += 100;
+    } else {
+        time.tm_year = (data[0] - '0') * 1000 + (data[1] - '0') * 100 + (data[2] - '0') * 10 + (data[3] - '0');
+        time.tm_year -= 1900;
+    }
+
+    data += ans1Time->type == V_ASN1_UTCTIME ? 2 : 4;
+
+    time.tm_mon = (data[0] - '0') * 10 + (data[1] - '0') - 1;
+    if (time.tm_mon < 0 || time.tm_mon > 11)
+        return WTF::nullopt;
+    time.tm_mday = (data[2] - '0') * 10 + (data[3] - '0');
+    time.tm_hour = (data[4] - '0') * 10 + (data[5] - '0');
+    time.tm_min = (data[6] - '0') * 10 + (data[7] - '0');
+
+    if ((ans1Time->length >= digitLength + 2) && isASCIIDigit(data[8]) && isASCIIDigit(data[9]))
+        time.tm_sec = (data[8] - '0') * 10 + (data[9] - '0');
+
+    auto gmtTime = mktime(&time);
+    auto localTimeOffset = calculateLocalTimeOffset(gmtTime * 1000.0);
+    return Seconds(gmtTime + (localTimeOffset.offset / 1000.0));
+}
+
+static void getSubjectAltName(const X509* x509, Vector<String>& dnsNames, Vector<String>& ipAddresses)
+{
+    StackOfGeneralName sanList(x509, NID_subject_alt_name);
+    if (!sanList)
+        return;
+
+    auto num = sanList.count();
+    for (auto i = 0; i < num; i++) {
+        auto* value = sanList.item(i);
+        if (!value)
+            continue;
+
+        if (value->type == GEN_DNS) {
+            auto dnsName = toString(value->d.dNSName);
+            if (!dnsName.isNull())
+                dnsNames.append(WTFMove(dnsName));
+        } else if (value->type == GEN_IPADD) {
+            auto data = value->d.iPAddress->data;
+            if (value->d.iPAddress->length == 4)
+                ipAddresses.append(makeString(data[0], ".", data[1], ".", data[2], ".", data[3]));
+            else if (value->d.iPAddress->length == 16) {
+                StringBuilder ipAddress;
+                for (int i = 0; i < 8; i++) {
+                    ipAddress.append(makeString(hex(data[0] << 8 | data[1], 4)));
+                    if (i != 7)
+                        ipAddress.append(":");
+                    data += 2;
+                }
+                ipAddresses.append(ipAddress.toString());
+            }
+        }
+    }
+}
+
+Optional<WebCore::CertificateInfo::SummaryInfo> createSummaryInfo(const Vector<uint8_t>& pem)
+{
+    BIO bio { pem };
+    auto x509 = bio.readX509();
+    if (!x509)
+        return WTF::nullopt;
+
+    WebCore::CertificateInfo::SummaryInfo summaryInfo;
+
+    summaryInfo.subject = getCommonName(x509.get());
+    if (summaryInfo.subject.isNull())
+        summaryInfo.subject = getSubjectName(x509.get());
+
+    if (auto notBefore = convertASN1TimeToSeconds(X509_get0_notBefore(x509.get())))
+        summaryInfo.validFrom = *notBefore;
+
+    if (auto notAfter = convertASN1TimeToSeconds(X509_get0_notAfter(x509.get())))
+        summaryInfo.validUntil = *notAfter;
+
+    getSubjectAltName(x509.get(), summaryInfo.dnsNames, summaryInfo.ipAddresses);
+
+    return summaryInfo;
+}
+
+}
diff --git a/Source/WebCore/platform/network/curl/OpenSSLHelper.h b/Source/WebCore/platform/network/curl/OpenSSLHelper.h
new file mode 100644 (file)
index 0000000..185daf5
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 Sony Interactive Entertainment Inc.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "CertificateInfo.h"
+#include <openssl/ssl.h>
+#include <wtf/Optional.h>
+#include <wtf/Vector.h>
+
+namespace OpenSSL {
+
+Optional<WebCore::CertificateInfo> createCertificateInfo(X509_STORE_CTX*);
+Optional<WebCore::CertificateInfo::SummaryInfo> createSummaryInfo(const Vector<uint8_t>& pem);
+
+} // namespace OpenSSL