Browse Source

ocsp: don't error out if we can't verify our certificate

We can omit either the CeritificateStatus message or the appropriate extension when we can not provide the OCSP staple that the peer is asking for. Let peer decide if it requires stapling and error out if we don't send it.
Juliusz Sosinowicz 4 months ago
parent
commit
51ba745214
4 changed files with 135 additions and 23 deletions
  1. 6 4
      scripts/ocsp-stapling.test
  2. 27 18
      src/internal.c
  3. 5 1
      src/tls.c
  4. 97 0
      tests/api.c

+ 6 - 4
scripts/ocsp-stapling.test

@@ -243,16 +243,18 @@ else
     OPENSSL_RESULT=$?
     echo "$OPENSSL_OUTPUT"
     fgrep -q 'self signed certificate in certificate chain' <<< "$OPENSSL_OUTPUT"
-    FGREP_RESULT=$?
-    if [ $OPENSSL_RESULT -eq 0 -a $FGREP_RESULT -ne 0 ]; then
+    FGREP1_RESULT=$?
+    fgrep -q 'self-signed certificate in certificate chain' <<< "$OPENSSL_OUTPUT"
+    FGREP2_RESULT=$?
+    if [ $OPENSSL_RESULT -eq 0 -a $FGREP1_RESULT -ne 0 -a $FGREP2_RESULT -ne 0 ]; then
         printf '%s\n' "Expected verification error from s_client is missing."
         remove_single_rF "$ready_file"
         exit 1
     fi
     remove_single_rF "$ready_file"
     wait $wolf_pid
-    if [ $? -ne 1 ]; then
-        printf '%s\n' "wolfSSL server unexpected fail value"
+    if [ $? -ne 0 ]; then
+        printf '%s\n' "wolfSSL server unexpected fail"
         exit 1
     fi
 fi

+ 27 - 18
src/internal.c

@@ -15972,43 +15972,44 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
                 WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
                 return OUT_OF_ORDER_E;
             }
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
+                                     defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
             if (ssl->msgsReceived.got_certificate_status == 0) {
+                int csrRet = 0;
 #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
-                if (ssl->status_request) {
-                    int ret;
-
+                if (csrRet == 0 && ssl->status_request) {
                     WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange");
-                    if ((ret = TLSX_CSR_ForceRequest(ssl)) != 0)
-                        return ret;
+                    csrRet = TLSX_CSR_ForceRequest(ssl);
                 }
 #endif
 #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
-                if (ssl->status_request_v2) {
-                    int ret;
-
+                if (csrRet == 0 && ssl->status_request_v2) {
                     WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange");
-                    if ((ret = TLSX_CSR2_ForceRequest(ssl)) != 0)
-                        return ret;
+                    csrRet = TLSX_CSR2_ForceRequest(ssl);
                 }
 #endif
-#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
-                                     defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+                if (csrRet != 0) {
+                    /* Error out if OCSP lookups are enabled and failed or if
+                     * the user requires stapling. */
+                    if (SSL_CM(ssl)->ocspEnabled || SSL_CM(ssl)->ocspMustStaple)
+                        return csrRet;
+                }
                 /* Check that a status request extension was seen as the
                  * CertificateStatus wasn't when an OCSP staple is required.
                  */
                 if (
-    #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
                      !ssl->status_request &&
-    #endif
-    #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+#endif
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
                      !ssl->status_request_v2 &&
-    #endif
+#endif
                                                  SSL_CM(ssl)->ocspMustStaple) {
                     WOLFSSL_ERROR_VERBOSE(OCSP_CERT_UNKNOWN);
                     return OCSP_CERT_UNKNOWN;
                 }
-                #endif
             }
+#endif
 
             break;
 #endif
@@ -23298,8 +23299,12 @@ int SendCertificateStatus(WOLFSSL* ssl)
 
             if (ret == 0 && response.buffer) {
                 ret = BuildCertificateStatus(ssl, status_type, &response, 1);
-
             }
+
+            /* Let's not error out the connection if we can't verify our cert */
+            if (ret == ASN_SELF_SIGNED_E || ret == ASN_NO_SIGNER_E)
+                ret = 0;
+
             if (response.buffer) {
                 XFREE(response.buffer, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
                 response.buffer = NULL;
@@ -23428,6 +23433,10 @@ int SendCertificateStatus(WOLFSSL* ssl)
                 }
             }
 
+            /* Let's not error out the connection if we can't verify our cert */
+            if (ret == ASN_SELF_SIGNED_E || ret == ASN_NO_SIGNER_E)
+                ret = 0;
+
             break;
         }
     #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */

+ 5 - 1
src/tls.c

@@ -3307,9 +3307,13 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, const byte* input, word16 length,
             InitDecodedCert(cert, ssl->buffers.certificate->buffer,
                             ssl->buffers.certificate->length, ssl->heap);
             ret = ParseCert(cert, CERT_TYPE, 1, SSL_CM(ssl));
-            if (ret != 0 ) {
+            if (ret != 0) {
                 FreeDecodedCert(cert);
                 XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
+                /* Let's not error out the connection if we can't verify our
+                 * cert */
+                if (ret == ASN_SELF_SIGNED_E || ret == ASN_NO_SIGNER_E)
+                    ret = 0;
                 return ret;
             }
             ret = TLSX_CSR_InitRequest(ssl->extensions, cert, ssl->heap);

+ 97 - 0
tests/api.c

@@ -68693,6 +68693,102 @@ static int test_dtls13_early_data(void)
     return EXPECT_RESULT();
 }
 
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+static int test_self_signed_stapling_client_v1_ctx_ready(WOLFSSL_CTX* ctx)
+{
+    EXPECT_DECLS;
+    ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx), 1);
+    ExpectIntEQ(wolfSSL_CTX_UseOCSPStapling(ctx, WOLFSSL_CSR_OCSP,
+            WOLFSSL_CSR_OCSP_USE_NONCE), 1);
+    return EXPECT_RESULT();
+}
+#endif
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+static int test_self_signed_stapling_client_v2_ctx_ready(WOLFSSL_CTX* ctx)
+{
+    EXPECT_DECLS;
+    ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx), 1);
+    ExpectIntEQ(wolfSSL_CTX_UseOCSPStaplingV2(ctx, WOLFSSL_CSR2_OCSP,
+            WOLFSSL_CSR2_OCSP_USE_NONCE), 1);
+    return EXPECT_RESULT();
+}
+
+static int test_self_signed_stapling_client_v2_multi_ctx_ready(WOLFSSL_CTX* ctx)
+{
+    EXPECT_DECLS;
+    ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx), 1);
+    ExpectIntEQ(wolfSSL_CTX_UseOCSPStaplingV2(ctx, WOLFSSL_CSR2_OCSP_MULTI,
+            0), 1);
+    return EXPECT_RESULT();
+}
+#endif
+
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+static int test_self_signed_stapling_server_ctx_ready(WOLFSSL_CTX* ctx)
+{
+    EXPECT_DECLS;
+    ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx), 1);
+    return EXPECT_RESULT();
+}
+#endif
+
+static int test_self_signed_stapling(void)
+{
+    EXPECT_DECLS;
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+    test_ssl_cbf client_cbf;
+    test_ssl_cbf server_cbf;
+    size_t i;
+    struct {
+        method_provider client_meth;
+        method_provider server_meth;
+        ctx_cb client_ctx;
+        const char* tls_version;
+    } params[] = {
+#if defined(WOLFSSL_TLS13) && defined(HAVE_CERTIFICATE_STATUS_REQUEST)
+        { wolfTLSv1_3_client_method, wolfTLSv1_3_server_method,
+            test_self_signed_stapling_client_v1_ctx_ready, "TLSv1_3 v1" },
+#endif
+#ifndef WOLFSSL_NO_TLS12
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+        { wolfTLSv1_2_client_method, wolfTLSv1_2_server_method,
+            test_self_signed_stapling_client_v1_ctx_ready, "TLSv1_2 v1" },
+#endif
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+        { wolfTLSv1_2_client_method, wolfTLSv1_2_server_method,
+            test_self_signed_stapling_client_v2_ctx_ready, "TLSv1_2 v2" },
+        { wolfTLSv1_2_client_method, wolfTLSv1_2_server_method,
+            test_self_signed_stapling_client_v2_multi_ctx_ready,
+            "TLSv1_2 v2 multi" },
+#endif
+#endif
+    };
+
+    for (i = 0; i < sizeof(params)/sizeof(*params) && !EXPECT_FAIL(); i++) {
+        XMEMSET(&client_cbf, 0, sizeof(client_cbf));
+        XMEMSET(&server_cbf, 0, sizeof(server_cbf));
+
+        printf("\nTesting self-signed cert with status request: %s\n",
+                params[i].tls_version);
+
+        client_cbf.method = params[i].client_meth;
+        client_cbf.ctx_ready = params[i].client_ctx;
+
+        server_cbf.method = params[i].server_meth;
+        server_cbf.certPemFile = "certs/ca-cert.pem";
+        server_cbf.keyPemFile  = "certs/ca-key.pem";
+        server_cbf.ctx_ready = test_self_signed_stapling_server_ctx_ready;
+
+        ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbf,
+            &server_cbf, NULL), TEST_SUCCESS);
+    }
+#endif
+    return EXPECT_RESULT();
+}
+
 /*----------------------------------------------------------------------------*
  | Main
  *----------------------------------------------------------------------------*/
@@ -69886,6 +69982,7 @@ TEST_CASE testCases[] = {
     /* OCSP Stapling */
     TEST_DECL(test_wolfSSL_UseOCSPStapling),
     TEST_DECL(test_wolfSSL_UseOCSPStaplingV2),
+    TEST_DECL(test_self_signed_stapling),
 
     /* Multicast */
     TEST_DECL(test_wolfSSL_mcast),