[Openvpn-devel] Unit tests: add test for SSL_CTX_use_Cryptoapi_certificate()

Message ID 20230318144325.1316320-1-selva.nair@gmail.com
State Accepted
Headers show
Series [Openvpn-devel] Unit tests: add test for SSL_CTX_use_Cryptoapi_certificate() | expand

Commit Message

Selva Nair March 18, 2023, 2:43 p.m. UTC
From: Selva Nair <selva.nair@gmail.com>

- This is the only remaining function in cryptoapi.c that has no
  direct or indirect test.

  This test confirms that an SSL_CTX context gets a certificate and
  private key loaded into it and the public key in the certificate
  matches the private key. As signing with certificate/key pairs
  fetched from the store is independently tested by the 'cryptoapi_sign'
  test, signing is not re-tested here.

  The functions "setup_/teardown_cryptoapi_sign()" are renamed to
  "setup_/teardown_xkey_provider()" to better reflect their purpose.
  These are also reused for the new test.

  While touching this context, also fix a memory leak in
  test_cryptoapi_sign: X509_get_pubkey() -> X509_get0_pubkey()

Signed-off-by: Selva Nair <selva.nair@gmail.com>
---
 tests/unit_tests/openvpn/test_cryptoapi.c | 51 ++++++++++++++++++++---
 1 file changed, 46 insertions(+), 5 deletions(-)

Comments

Gert Doering March 20, 2023, 5:34 p.m. UTC | #1
Acked-by: Gert Doering <gert@greenie.muc.de>

Unit tests are goood!!!! :-)

Stare-at-code looks good, and Github is happy with the result... (both
32 and 64 bit)

    [==========] Running 7 test(s).
    [ RUN      ] test_parse_hexstring
    [       OK ] test_parse_hexstring
    [ RUN      ] import_certs
    [       OK ] import_certs
    [ RUN      ] test_find_cert_bythumb
    [       OK ] test_find_cert_bythumb
    [ RUN      ] test_find_cert_byname
    [       OK ] test_find_cert_byname
    [ RUN      ] test_find_cert_byissuer
    [       OK ] test_find_cert_byissuer
    [ RUN      ] test_cryptoapi_sign
    [       OK ] test_cryptoapi_sign
    [ RUN      ] test_ssl_ctx_use_cryptoapicert
    [       OK ] test_ssl_ctx_use_cryptoapicert
    [==========] 7 test(s) run.
    [  PASSED  ] 7 test(s).

Your patch has been applied to the master and release/2.6 branch.

commit 85da9de524f34db3f6bd4ebc110b25c6bcbc273d (master)
commit 973083746727cb797248262de56fb0a707bcdb90 (release/2.6)
Author: Selva Nair
Date:   Sat Mar 18 10:43:25 2023 -0400

     Unit tests: add test for SSL_CTX_use_Cryptoapi_certificate()

     Signed-off-by: Selva Nair <selva.nair@gmail.com>
     Acked-by: Gert Doering <gert@greenie.muc.de>
     Message-Id: <20230318144325.1316320-1-selva.nair@gmail.com>
     URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg26438.html
     Signed-off-by: Gert Doering <gert@greenie.muc.de>


--
kind regards,

Gert Doering

Patch

diff --git a/tests/unit_tests/openvpn/test_cryptoapi.c b/tests/unit_tests/openvpn/test_cryptoapi.c
index b07e8935..e64a1de3 100644
--- a/tests/unit_tests/openvpn/test_cryptoapi.c
+++ b/tests/unit_tests/openvpn/test_cryptoapi.c
@@ -343,7 +343,7 @@  test_find_cert_byissuer(void **state)
 }
 
 static int
-setup_cryptoapi_sign(void **state)
+setup_xkey_provider(void **state)
 {
     (void) state;
     /* Initialize providers in a way matching what OpenVPN core does */
@@ -358,7 +358,7 @@  setup_cryptoapi_sign(void **state)
 }
 
 static int
-teardown_cryptoapi_sign(void **state)
+teardown_xkey_provider(void **state)
 {
     (void) state;
     for (size_t i = 0; i < _countof(prov); i++)
@@ -493,13 +493,52 @@  test_cryptoapi_sign(void **state)
             fail_msg("Load_CryptoAPI_certificate failed: <%s>", c->friendly_name);
             return;
         }
-        EVP_PKEY *pubkey = X509_get_pubkey(x509);
+        EVP_PKEY *pubkey = X509_get0_pubkey(x509);
+        assert_non_null(pubkey);
         assert_int_equal(digest_sign_verify(privkey, pubkey), 1);
         X509_free(x509);
         EVP_PKEY_free(privkey);
     }
 }
 
+/* Test that SSL_CTX_use_Cryptoapi_certificate() sets a matching certificate
+ * and key in ssl_ctx.
+ */
+void
+test_ssl_ctx_use_cryptoapicert(void **state)
+{
+    (void) state;
+    char select_string[64];
+
+    import_certs(state); /* a no-op if already imported */
+    assert_true(certs_loaded);
+
+    for (struct test_cert *c = certs; c->cert; c++)
+    {
+        if (c->valid == 0)
+        {
+            continue;
+        }
+        SSL_CTX *ssl_ctx = SSL_CTX_new_ex(tls_libctx, NULL, SSLv23_client_method());
+        assert_non_null(ssl_ctx);
+
+        openvpn_snprintf(select_string, sizeof(select_string), "THUMB:%s", c->hash);
+        if (!SSL_CTX_use_CryptoAPI_certificate(ssl_ctx, select_string))
+        {
+            fail_msg("SSL_CTX_use_CryptoAPI_certificate failed: <%s>", c->friendly_name);
+            return;
+        }
+        /* Use OpenSSL to check that the cert and private key in ssl_ctx "match" */
+        if (!SSL_CTX_check_private_key(ssl_ctx))
+        {
+            fail_msg("Certificate and private key in ssl_ctx do not match for <%s>", c->friendly_name);
+            return;
+        }
+
+        SSL_CTX_free(ssl_ctx);
+    }
+}
+
 static void
 test_parse_hexstring(void **state)
 {
@@ -530,8 +569,10 @@  main(void)
         cmocka_unit_test(test_find_cert_bythumb),
         cmocka_unit_test(test_find_cert_byname),
         cmocka_unit_test(test_find_cert_byissuer),
-        cmocka_unit_test_setup_teardown(test_cryptoapi_sign, setup_cryptoapi_sign,
-                                        teardown_cryptoapi_sign),
+        cmocka_unit_test_setup_teardown(test_cryptoapi_sign, setup_xkey_provider,
+                                        teardown_xkey_provider),
+        cmocka_unit_test_setup_teardown(test_ssl_ctx_use_cryptoapicert, setup_xkey_provider,
+                                        teardown_xkey_provider),
     };
 
     int ret = cmocka_run_group_tests_name("cryptoapi tests", tests, NULL, cleanup);