CKM: Check certificate validity before test 32/169832/1
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Fri, 9 Feb 2018 12:18:53 +0000 (13:18 +0100)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Fri, 9 Feb 2018 13:11:33 +0000 (14:11 +0100)
When a certificate expires or a systemd date is incorrectly set the certificate
chain tests fail suggesting key-manager failure.

This commit adds a simple certificate validity check before the certificate is
used. If the certificate is not valid the test fails and a clear message is
delivered to the user. Each certificate is validated only once.

Change-Id: I4de5549e49b761472c224f6bb672d512386d398d

src/ckm/test-certs.cpp

index 6dddb7a..a844cf5 100644 (file)
  */
 
 #include <map>
+#include <memory>
+#include <openssl/pem.h>
+#include <openssl/bio.h>
+#include <openssl/x509.h>
 #include <test-certs.h>
 #include <dpl/test/test_runner.h>
 #include <dpl/test/test_runner_child.h>
@@ -50,7 +54,23 @@ enum RawCertificateID {
     NO_CERT
 };
 
-typedef map<RawCertificateID, pair<string, CKM::CertificateShPtr>> CertMap;
+
+struct TestCert {
+    enum Validity {
+        UNKNOWN,
+        VALID,
+        NOT_YET_VALID,
+        EXPIRED
+    };
+
+    TestCert() : valid(UNKNOWN) {}
+
+    string raw_base64;
+    CKM::CertificateShPtr certPtr;
+    Validity valid;
+};
+
+typedef map<RawCertificateID, TestCert> CertMap;
 
 CKM::CertificateShPtr createCert(const string& cert) {
     CKM::RawBuffer buffer_cert(cert.begin(), cert.end());
@@ -106,8 +126,8 @@ CertMap initializeTestCerts()
             "qMn7nf7taidDKLO2T4bhujztnTYOhhaXKgPy7AtZ28N2wvX96VyAPB/vrchGmyBK\n"
             "kOg11TpPdNDkhb1J4ZCh2gupDg==\n"
             "-----END CERTIFICATE-----\n");
-        cm[RawCertificateID::TEST_ROOT_CA] =
-            std::make_pair(raw_base64, createCert(raw_base64));
+        cm[RawCertificateID::TEST_ROOT_CA].raw_base64 = raw_base64;
+        cm[RawCertificateID::TEST_ROOT_CA].certPtr = createCert(raw_base64);
     }
 
     // TEST_IM_CA, signed by TEST_ROOT_CA, expires 2035
@@ -135,8 +155,8 @@ CertMap initializeTestCerts()
             "SLoHQ9s1i7Zyb7HU6UAaqMOz15LBkyAqtNyJcO2p7Q/p5YK0xfD4xisI5qXucqVm\n"
             "F2obL5qJSTN/RQ==\n"
             "-----END CERTIFICATE-----\n");
-        cm[RawCertificateID::TEST_IM_CA] =
-            std::make_pair(raw_base64, createCert(raw_base64));
+        cm[RawCertificateID::TEST_IM_CA].raw_base64 = raw_base64;
+        cm[RawCertificateID::TEST_IM_CA].certPtr = createCert(raw_base64);
     }
 
     // TEST_LEAF, signed by TEST_IM_CA, expires 2035
@@ -162,8 +182,8 @@ CertMap initializeTestCerts()
             "Zj/T1JkYXKkEwZU6nAR2jdZp3EP9xj3o15V/tyFcXHx6l8NTxn4cJb+Xe4VquQJz\n"
             "6ON7PVe0ABN/AlwVQiFE\n"
             "-----END CERTIFICATE-----\n");
-        cm[RawCertificateID::TEST_LEAF] =
-            std::make_pair(raw_base64, createCert(raw_base64));
+        cm[RawCertificateID::TEST_LEAF].raw_base64 = raw_base64;
+        cm[RawCertificateID::TEST_LEAF].certPtr = createCert(raw_base64);
     }
 
     // BING.COM, signed by MICROSOFT_IM_CA, expires 10 Jul 2019
@@ -236,8 +256,8 @@ CertMap initializeTestCerts()
             "AfqkzSUxhqHXuThe7KIoX9/0zv4AA1WZFis1QvAG7dpl9eio6vCdC/73HvBAlqRL\n"
             "+7Mb1uu0\n"
             "-----END CERTIFICATE-----\n");
-        cm[RawCertificateID::BING_COM] =
-            std::make_pair(raw_base64, createCert(raw_base64));
+        cm[RawCertificateID::BING_COM].raw_base64 = raw_base64;
+        cm[RawCertificateID::BING_COM].certPtr = createCert(raw_base64);
 
     }
 
@@ -277,8 +297,8 @@ CertMap initializeTestCerts()
             "TlHk/R4RFsyeANmXGpfjZceGNRtTdr4y0SxBSUujPpMMW3dXBzA8NYuM0WmiJ/pV\n"
             "6KudEB7RF9+6bInTyVvXC5SIqdi0ldeO\n"
             "-----END CERTIFICATE-----\n");
-        cm[RawCertificateID::MICROSOFT_IM_CA] =
-            std::make_pair(raw_base64, createCert(raw_base64));
+        cm[RawCertificateID::MICROSOFT_IM_CA].raw_base64 = raw_base64;
+        cm[RawCertificateID::MICROSOFT_IM_CA].certPtr = createCert(raw_base64);
 
     }
 
@@ -308,8 +328,8 @@ CertMap initializeTestCerts()
             "vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep\n"
             "+OkuE6N36B9K\n"
             "-----END CERTIFICATE-----\n");
-        cm[RawCertificateID::DIGICERT_ROOT_CA] =
-            std::make_pair(raw_base64, createCert(raw_base64));
+        cm[RawCertificateID::DIGICERT_ROOT_CA].raw_base64 = raw_base64;
+        cm[RawCertificateID::DIGICERT_ROOT_CA].certPtr = createCert(raw_base64);
     }
 
     // DIGICERT_IM_CA, signed by DIGICERT_ROOT_CA, expires 22 Oct 2028
@@ -343,8 +363,8 @@ CertMap initializeTestCerts()
             "0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvFwY+3sAzm2fTYS5yh+Rp/BIAV0Ae\n"
             "cPUeybQ=\n"
             "-----END CERTIFICATE-----\n");
-        cm[RawCertificateID::DIGICERT_IM_CA] =
-            std::make_pair(raw_base64, createCert(raw_base64));
+        cm[RawCertificateID::DIGICERT_IM_CA].raw_base64 = raw_base64;
+        cm[RawCertificateID::DIGICERT_IM_CA].certPtr = createCert(raw_base64);
     }
 
     // FACEBOOK_COM, *.facebook.com - signed by DIGICERT_IM_CA, expires 25 Jan 2018
@@ -395,8 +415,8 @@ CertMap initializeTestCerts()
             "EP0UhYknI1B6LBecJuj7jI26eXZdX35CYkpI/SZA9KK+OYKHh6vCxKqnRZ9ZQUOj\n"
             "XnIWKQeV5Hg=\n"
             "-----END CERTIFICATE-----\n");
-        cm[RawCertificateID::FACEBOOK_COM] =
-            std::make_pair(raw_base64, createCert(raw_base64));
+        cm[RawCertificateID::FACEBOOK_COM].raw_base64 = raw_base64;
+        cm[RawCertificateID::FACEBOOK_COM].certPtr = createCert(raw_base64);
     }
 
     return cm;
@@ -406,6 +426,44 @@ CertMap TEST_CERTS = initializeTestCerts();
 
 } // namespace TestData::anonymous
 
+void checkCertificateValidity(std::map<RawCertificateID, TestCert>::iterator& it)
+{
+    if (it->second.valid == TestCert::UNKNOWN)
+    {
+        auto buff = BIO_new(BIO_s_mem());
+        BIO_write(buff, it->second.raw_base64.c_str(), it->second.raw_base64.size());
+
+        X509* x509 = PEM_read_bio_X509(buff, nullptr, nullptr, nullptr);
+        BIO_free_all(buff);
+
+        RUNNER_ASSERT_MSG(x509 != NULL, "Test certificate " << it->first << " can't be parsed");
+
+        if (X509_cmp_current_time(X509_get_notBefore(x509)) > 0)
+            it->second.valid = TestCert::NOT_YET_VALID;
+        else if (X509_cmp_current_time(X509_get_notAfter(x509)) < 0)
+            it->second.valid = TestCert::EXPIRED;
+        else
+            it->second.valid = TestCert::VALID;
+
+        X509_free(x509);
+    }
+
+    switch (it->second.valid)
+    {
+    case TestCert::NOT_YET_VALID:
+        RUNNER_FAIL_MSG(
+                "Test certificate " << it->first <<
+                " is not yet valid. Check the certificate and the system date.");
+        break;
+    case TestCert::EXPIRED:
+        RUNNER_FAIL_MSG(
+                "Test certificate " << it->first <<
+                " has expired. Check the certificate and the system date.");
+        break;
+    default:
+        break;
+    }
+}
 
 std::string getTestCertificateBase64(certificateID id)
 {
@@ -413,10 +471,12 @@ std::string getTestCertificateBase64(certificateID id)
 
     RUNNER_ASSERT_MSG(cert != TEST_CERTS.end(), "Unknown certificate index!");
 
-    auto &certPair = cert->second;
-    RUNNER_ASSERT_MSG(certPair.first.size() > 0, "Certificate is empty!");
+    auto &certStruct = cert->second;
+    RUNNER_ASSERT_MSG(certStruct.raw_base64.size() > 0, "Certificate is empty!");
 
-    return certPair.first;
+    checkCertificateValidity(cert);
+
+    return certStruct.raw_base64;
 }
 
 CKM::CertificateShPtr getTestCertificate(certificateID id)
@@ -425,10 +485,12 @@ CKM::CertificateShPtr getTestCertificate(certificateID id)
 
     RUNNER_ASSERT_MSG(cert != TEST_CERTS.end(), "Unknown certificate index!");
 
-    auto &certPair = cert->second;
-    RUNNER_ASSERT_MSG(certPair.second != nullptr, "Certificate is empty!");
+    auto &certStruct = cert->second;
+    RUNNER_ASSERT_MSG(certStruct.certPtr != nullptr, "Certificate is empty!");
+
+    checkCertificateValidity(cert);
 
-    return certPair.second;
+    return certStruct.certPtr;
 }
 
 } // namespace TestData