Ignored Trust-Chain related errors when validating certificate

Currently, bmcweb is generating self signed certificate when uploaded
certificate is not in trust-chain while validating that certificate.

As per design direction, bmcweb and Certificate Manager should ignore
trust chain related errors and same feature addressed in certificate
manager.

Reference change id from Certificate Manager:
https://gerrit.openbmc-project.xyz/c/openbmc/phosphor-certificate-manager/+/13875

With this change, the user can upload self signed CA certificate
without Root CA-Certificate in certificate store and bmcweb won't generate
self signed certificate when uploaded certificate is not in
trust-chain.

Trust chain error info:
    X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
    X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
    X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
    X509_V_ERR_CERT_UNTRUSTED
    X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE

Change-Id: Ieedd602541d6d5284be3e22ffd5db3ee875065fe
Signed-off-by: Ramesh Iyyar <rameshi1@in.ibm.com>
diff --git a/include/ssl_key_handler.hpp b/include/ssl_key_handler.hpp
index 7aa1c53..ce6d9fa 100644
--- a/include/ssl_key_handler.hpp
+++ b/include/ssl_key_handler.hpp
@@ -22,6 +22,85 @@
 static EVP_PKEY *createEcKey();
 static void handleOpensslError();
 
+// Trust chain related errors.`
+inline bool isTrustChainError(int errnum)
+{
+    if ((errnum == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ||
+        (errnum == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) ||
+        (errnum == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) ||
+        (errnum == X509_V_ERR_CERT_UNTRUSTED) ||
+        (errnum == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE))
+    {
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+inline bool validateCertificate(X509 *const cert)
+{
+    // Create an empty X509_STORE structure for certificate validation.
+    X509_STORE *x509Store = X509_STORE_new();
+    if (!x509Store)
+    {
+        BMCWEB_LOG_ERROR << "Error occured during X509_STORE_new call";
+        return false;
+    }
+
+    // Load Certificate file into the X509 structure.
+    X509_STORE_CTX *storeCtx = X509_STORE_CTX_new();
+    if (!storeCtx)
+    {
+        BMCWEB_LOG_ERROR << "Error occured during X509_STORE_CTX_new call";
+        X509_STORE_free(x509Store);
+        return false;
+    }
+
+    int errCode = X509_STORE_CTX_init(storeCtx, x509Store, cert, NULL);
+    if (errCode != 1)
+    {
+        BMCWEB_LOG_ERROR << "Error occured during X509_STORE_CTX_init call";
+        X509_STORE_CTX_free(storeCtx);
+        X509_STORE_free(x509Store);
+        return false;
+    }
+
+    errCode = X509_verify_cert(storeCtx);
+    if (errCode == 1)
+    {
+        BMCWEB_LOG_INFO << "Certificate verification is success";
+        X509_STORE_CTX_free(storeCtx);
+        X509_STORE_free(x509Store);
+        return true;
+    }
+    if (errCode == 0)
+    {
+        errCode = X509_STORE_CTX_get_error(storeCtx);
+        X509_STORE_CTX_free(storeCtx);
+        X509_STORE_free(x509Store);
+        if (isTrustChainError(errCode))
+        {
+            BMCWEB_LOG_DEBUG << "Ignoring Trust Chain error. Reason: "
+                             << X509_verify_cert_error_string(errCode);
+            return true;
+        }
+        else
+        {
+            BMCWEB_LOG_ERROR << "Certificate verification failed. Reason: "
+                             << X509_verify_cert_error_string(errCode);
+            return false;
+        }
+    }
+
+    BMCWEB_LOG_ERROR
+        << "Error occured during X509_verify_cert call. ErrorCode: " << errCode;
+    X509_STORE_CTX_free(storeCtx);
+    X509_STORE_free(x509Store);
+    return false;
+}
+
 inline bool verifyOpensslKeyCert(const std::string &filepath)
 {
     bool privateKeyValid = false;
@@ -86,16 +165,8 @@
                 }
                 else
                 {
-                    rc = X509_verify(x509, pkey);
-                    if (rc == 1)
-                    {
-                        certValid = true;
-                    }
-                    else
-                    {
-                        std::cerr << "Error in verifying private key signature "
-                                  << ERR_get_error() << "\n";
-                    }
+                    certValid = validateCertificate(x509);
+                    X509_free(x509);
                 }
             }