[Openvpn-devel,v2,3/3] Add a unit test for functions in cryptoapi.c

Message ID 20230204064010.257925-2-selva.nair@gmail.com
State Superseded
Headers show
Series None | expand

Commit Message

Selva Nair Feb. 4, 2023, 6:40 a.m. UTC
From: Selva Nair <selva.nair@gmail.com>

- Though named cryptoapi_testdriver, right now this only tests
  parsing of thumbprint specified as a selector for --cryptioapicert
  option. More tests coming..

v2: a line that belongs here was mistakenly included in the previous
commit. Corrected.

Signed-off-by: Selva Nair <selva.nair@gmail.com>
---
 tests/unit_tests/openvpn/Makefile.am      |  16 +++
 tests/unit_tests/openvpn/test_cryptoapi.c | 126 ++++++++++++++++++++++
 2 files changed, 142 insertions(+)
 create mode 100644 tests/unit_tests/openvpn/test_cryptoapi.c

Comments

Arne Schwabe Feb. 8, 2023, 12:18 a.m. UTC | #1
Am 04.02.23 um 07:40 schrieb selva.nair@gmail.com:
> From: Selva Nair <selva.nair@gmail.com>
> 
> - Though named cryptoapi_testdriver, right now this only tests
>    parsing of thumbprint specified as a selector for --cryptioapicert
>    option. More tests coming..
> 
> v2: a line that belongs here was mistakenly included in the previous
> commit. Corrected.
> 
> Signed-off-by: Selva Nair <selva.nair@gmail.com>

While a good step, this still has problems. With OpenSSL 1.1.1 it still 
tries to run the check-engine.sh script and unsurprisingly fails:

---- begin log.txt ----
./check_engine_keys.sh: 25: ../../../src/openvpn/openvpn: not found
--- end log.txt ---
Key mismatch not detected
FAIL: check_engine_keys.sh

This can be fixed by:

--- a/tests/unit_tests/engine-key/Makefile.am
+++ b/tests/unit_tests/engine-key/Makefile.am
@@ -12,7 +12,9 @@ TESTS_ENVIRONMENT = srcdir="$(abs_srcdir)"; \
         top_srcdir="$(top_srcdir)"; \
         export srcdir builddir top_builddir top_srcdir;

+if !CROSS_COMPILING
  TESTS = check_engine_keys.sh
+endif
  check_engine_keys.sh: $(conffiles)

  CLEANFILES = \


I have working github actions for this running which was a real pain to 
get working. I will send this after we get a v3 of the patch with that 
patch above included.


Then my mingw seems to be more pendantic then every other compiler. I 
will send a separate patch for that on the mailing list.

Also libtool is utterly broken on my mingw cross building on the mac:

libtool:   error: Could not determine the host path corresponding to
libtool:   error: 
'/Users/arne/ovpn/mingw64/lib:/Users/arne/ovpn/mingw64/bin:/Users/arne/ovpn/deps-mingw64/lib:/Users/arne/ovpn/deps-mingw64/bin'
libtool:   error: Continuing, but uninstalled executables may not work.
./.libs/lt-provider_testdriver.c:41:5: warning: '_putenv' redeclared 
without dllimport attribute: previous dllimport ignored [-Wattributes]
    41 | int _putenv (const char *);
       |     ^~~~~~~
./.libs/lt-provider_testdriver.c: In function 'lt_dump_script':
./.libs/lt-provider_testdriver.c:837:10: warning: missing terminating " 
character
   837 |   fputs ("# provider_testdriver - temporary wrapper script for 
.libs/provider_testdriver.
       |          ^
./.libs/lt-provider_testdriver.c:837:10: error: missing terminating " 
character
   837 |   fputs ("# provider_testdriver - temporary wrapper script for 
.libs/provider_testdriver.
       | 
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./.libs/lt-provider_testdriver.c:838:4: warning: missing terminating " 
character
   838 | exe", f);
       |    ^



 From the lt-provider_testdriver.c:

void lt_dump_script (FILE* f)
{
   fputs ("#! /bi", f);
   fputs ("", f);
   fputs ("# packet_id_testdriver - temporary wrapper script for 
.libs/packet_id_testdrive
r.exe", f);
   fputs ("r.exe", f);
   fputs ("# Ge", f);
   fputs ("#", f);
   fputs ("#", f);
   fputs ("# This wrapper script should ", f);
   fputs ("# If it is, it will ", f);
   fputs ("", f);
   fputs ("# Sed substitutio", f);
   fputs ("# metacharacters that are still active withi", f);
   fputs ("sed_quote_subst='s|", f);
   fputs ("", f);
   fputs ("# Be Bour", f);
   fputs ("if test -", f);
   fputs ("  emulate sh", f);
   fputs ("  NULLCMD=:", f);
   fputs ("  # Zsh 3.x a", f);
   fputs ("  # is co", f);


I have to say the autoconf/libtool/automake is pretty broken here and I 
absolutely no idea how to fix it. Any idea or help would be appricated.

Arne
Selva Nair Feb. 8, 2023, 1:05 a.m. UTC | #2
Hi,

On Tue, Feb 7, 2023 at 7:18 PM Arne Schwabe <arne@rfc2549.org> wrote:

> Am 04.02.23 um 07:40 schrieb selva.nair@gmail.com:
> > From: Selva Nair <selva.nair@gmail.com>
> >
> > - Though named cryptoapi_testdriver, right now this only tests
> >    parsing of thumbprint specified as a selector for --cryptioapicert
> >    option. More tests coming..
> >
> > v2: a line that belongs here was mistakenly included in the previous
> > commit. Corrected.
> >
> > Signed-off-by: Selva Nair <selva.nair@gmail.com>
>
> While a good step, this still has problems. With OpenSSL 1.1.1 it still
> tries to run the check-engine.sh script and unsurprisingly fails:
>
> ---- begin log.txt ----
> ./check_engine_keys.sh: 25: ../../../src/openvpn/openvpn: not found
> --- end log.txt ---
> Key mismatch not detected
> FAIL: check_engine_keys.sh
>
> This can be fixed by:
>
> --- a/tests/unit_tests/engine-key/Makefile.am
> +++ b/tests/unit_tests/engine-key/Makefile.am
> @@ -12,7 +12,9 @@ TESTS_ENVIRONMENT = srcdir="$(abs_srcdir)"; \
>          top_srcdir="$(top_srcdir)"; \
>          export srcdir builddir top_builddir top_srcdir;
>
> +if !CROSS_COMPILING
>   TESTS = check_engine_keys.sh
> +endif
>   check_engine_keys.sh: $(conffiles)
>
>   CLEANFILES = \
>

Thanks for this. I added this to 2/3 where it belongs and submitted it as
v3 2/3. With that, this patch should be okay as is.

For those not following closely, this patch  should be applied after the
cryptoapi patch set where the function being tested here is introduced.

Selva
Arne Schwabe Feb. 8, 2023, 11:16 a.m. UTC | #3
Am 08.02.23 um 02:05 schrieb Selva Nair:
> Hi,
> 
> On Tue, Feb 7, 2023 at 7:18 PM Arne Schwabe <arne@rfc2549.org 
> <mailto:arne@rfc2549.org>> wrote:
> 
>     Am 04.02.23 um 07:40 schrieb selva.nair@gmail.com
>     <mailto:selva.nair@gmail.com>:
>      > From: Selva Nair <selva.nair@gmail.com <mailto:selva.nair@gmail.com>>
>      >
>      > - Though named cryptoapi_testdriver, right now this only tests
>      >    parsing of thumbprint specified as a selector for --cryptioapicert
>      >    option. More tests coming..
>      >
>      > v2: a line that belongs here was mistakenly included in the previous
>      > commit. Corrected.
>      >
>      > Signed-off-by: Selva Nair <selva.nair@gmail.com
>     <mailto:selva.nair@gmail.com>>
> 
>     While a good step, this still has problems. With OpenSSL 1.1.1 it still
>     tries to run the check-engine.sh script and unsurprisingly fails:
> 
>     ---- begin log.txt ----
>     ./check_engine_keys.sh: 25: ../../../src/openvpn/openvpn: not found
>     --- end log.txt ---
>     Key mismatch not detected
>     FAIL: check_engine_keys.sh
> 
>     This can be fixed by:
> 
>     --- a/tests/unit_tests/engine-key/Makefile.am
>     +++ b/tests/unit_tests/engine-key/Makefile.am
>     @@ -12,7 +12,9 @@ TESTS_ENVIRONMENT = srcdir="$(abs_srcdir)"; \
>               top_srcdir="$(top_srcdir)"; \
>               export srcdir builddir top_builddir top_srcdir;
> 
>     +if !CROSS_COMPILING
>        TESTS = check_engine_keys.sh
>     +endif
>        check_engine_keys.sh: $(conffiles)
> 
>        CLEANFILES = \
> 
> 
> Thanks for this. I added this to 2/3 where it belongs and submitted it 
> as v3 2/3. With that, this patch should be okay as is.
> 
> For those not following closely, this patch  should be applied after the 
> cryptoapi patch set where the function being tested here is introduced.
> 
> Selva

No, I think this that is independent. This is about the engine keys 
support added by James Bottomley.  I needed and tested this patch 
without the cryptoapi patch.

Arne
Selva Nair Feb. 8, 2023, 3:43 p.m. UTC | #4
On Wed, Feb 8, 2023 at 6:16 AM Arne Schwabe <arne@rfc2549.org> wrote:

> Am 08.02.23 um 02:05 schrieb Selva Nair:
> > Hi,
> >
> > On Tue, Feb 7, 2023 at 7:18 PM Arne Schwabe <arne@rfc2549.org
> > <mailto:arne@rfc2549.org>> wrote:
> >
> >     Am 04.02.23 um 07:40 schrieb selva.nair@gmail.com
> >     <mailto:selva.nair@gmail.com>:
> >      > From: Selva Nair <selva.nair@gmail.com <mailto:
> selva.nair@gmail.com>>
> >      >
> >      > - Though named cryptoapi_testdriver, right now this only tests
> >      >    parsing of thumbprint specified as a selector for
> --cryptioapicert
> >      >    option. More tests coming..
> >      >
> >      > v2: a line that belongs here was mistakenly included in the
> previous
> >      > commit. Corrected.
> >      >
> >      > Signed-off-by: Selva Nair <selva.nair@gmail.com
> >     <mailto:selva.nair@gmail.com>>
> >
> >     While a good step, this still has problems. With OpenSSL 1.1.1 it
> still
> >     tries to run the check-engine.sh script and unsurprisingly fails:
> >
> >     ---- begin log.txt ----
> >     ./check_engine_keys.sh: 25: ../../../src/openvpn/openvpn: not found
> >     --- end log.txt ---
> >     Key mismatch not detected
> >     FAIL: check_engine_keys.sh
> >
> >     This can be fixed by:
> >
> >     --- a/tests/unit_tests/engine-key/Makefile.am
> >     +++ b/tests/unit_tests/engine-key/Makefile.am
> >     @@ -12,7 +12,9 @@ TESTS_ENVIRONMENT = srcdir="$(abs_srcdir)"; \
> >               top_srcdir="$(top_srcdir)"; \
> >               export srcdir builddir top_builddir top_srcdir;
> >
> >     +if !CROSS_COMPILING
> >        TESTS = check_engine_keys.sh
> >     +endif
> >        check_engine_keys.sh: $(conffiles)
> >
> >        CLEANFILES = \
> >
> >
> > Thanks for this. I added this to 2/3 where it belongs and submitted it
> > as v3 2/3. With that, this patch should be okay as is.
> >
> > For those not following closely, this patch  should be applied after the
> > cryptoapi patch set where the function being tested here is introduced.
> >
> > Selva
>
> No, I think this that is independent. This is about the engine keys
> support added by James Bottomley.  I needed and tested this patch
> without the cryptoapi patch.
>

Got that. I think gmail is messing up my thread view -- this email appear
for me as linked to my original 3/3 which is on the test for cryptoapi.
That's why I wrote "this patch should be okay as is."  Anyway...

Will look into your patches later today.

Selva
Gert Doering Feb. 14, 2023, 1:48 p.m. UTC | #5
Hi,

On Sat, Feb 04, 2023 at 01:40:10AM -0500, selva.nair@gmail.com wrote:
> From: Selva Nair <selva.nair@gmail.com>
> 
> - Though named cryptoapi_testdriver, right now this only tests
>   parsing of thumbprint specified as a selector for --cryptioapicert
>   option. More tests coming..
> 
> v2: a line that belongs here was mistakenly included in the previous
> commit. Corrected.

So, unit test are good, especially for the Windows bits that could
really use more testing - so thanks for that.

OTOH, having the test here without adding it to .github/workflows/build.yaml
means "it not run automatically".  How do we want to do that, do you want
to send a v3 with build.yaml extended, or shall I merge this as is, and
we do a separate patch "... and now run the unit test"?

gert

Patch

diff --git a/tests/unit_tests/openvpn/Makefile.am b/tests/unit_tests/openvpn/Makefile.am
index 8d2386e0..ee0a3d8a 100644
--- a/tests/unit_tests/openvpn/Makefile.am
+++ b/tests/unit_tests/openvpn/Makefile.am
@@ -17,6 +17,7 @@  endif
 test_binaries += provider_testdriver
 
 if WIN32
+test_binaries += cryptoapi_testdriver
 LDADD = -lws2_32
 endif
 
@@ -152,6 +153,21 @@  provider_testdriver_SOURCES = test_provider.c mock_msg.c \
 	$(openvpn_srcdir)/win32-util.c \
 	$(openvpn_srcdir)/platform.c
 
+if WIN32
+cryptoapi_testdriver_CFLAGS  = @TEST_CFLAGS@ \
+	-I$(openvpn_includedir) -I$(compat_srcdir) -I$(openvpn_srcdir) \
+	$(OPTIONAL_CRYPTO_CFLAGS)
+cryptoapi_testdriver_LDFLAGS = @TEST_LDFLAGS@ \
+	$(OPTIONAL_CRYPTO_LIBS) -lcrypt32 -lncrypt
+cryptoapi_testdriver_SOURCES = test_cryptoapi.c mock_msg.c \
+	$(openvpn_srcdir)/xkey_helper.c \
+	$(openvpn_srcdir)/buffer.c \
+	$(openvpn_srcdir)/base64.c \
+	$(openvpn_srcdir)/platform.c \
+	mock_get_random.c \
+	$(openvpn_srcdir)/win32-util.c
+endif
+
 auth_token_testdriver_CFLAGS  = @TEST_CFLAGS@ \
 	-I$(openvpn_includedir) -I$(compat_srcdir) -I$(openvpn_srcdir) \
 	$(OPTIONAL_CRYPTO_CFLAGS)
diff --git a/tests/unit_tests/openvpn/test_cryptoapi.c b/tests/unit_tests/openvpn/test_cryptoapi.c
new file mode 100644
index 00000000..2bea3f42
--- /dev/null
+++ b/tests/unit_tests/openvpn/test_cryptoapi.c
@@ -0,0 +1,126 @@ 
+/*
+ *  OpenVPN -- An application to securely tunnel IP networks
+ *             over a single UDP port, with support for SSL/TLS-based
+ *             session authentication and key exchange,
+ *             packet encryption, packet authentication, and
+ *             packet compression.
+ *
+ *  Copyright (C) 2023 Selva Nair <selva.nair@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation, either version 2 of the License,
+ *  or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#elif defined(_MSC_VER)
+#include "config-msvc.h"
+#endif
+
+#include "syshead.h"
+#include "manage.h"
+#include "integer.h"
+#include "xkey_common.h"
+
+#if defined(HAVE_XKEY_PROVIDER) && defined (ENABLE_CRYPTOAPI)
+#include <setjmp.h>
+#include <cmocka.h>
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/core_names.h>
+#include <openssl/evp.h>
+
+#include <cryptoapi.h>
+#include <cryptoapi.c> /* pull-in the whole file to test static functions */
+
+struct management *management; /* global */
+
+/* mock a management function that xkey_provider needs */
+char *
+management_query_pk_sig(struct management *man, const char *b64_data,
+                        const char *algorithm)
+{
+    (void) man;
+    (void) b64_data;
+    (void) algorithm;
+    return NULL;
+}
+
+/* tls_libctx is defined in ssl_openssl.c which we do not want to compile in */
+OSSL_LIB_CTX *tls_libctx;
+
+#ifndef _countof
+#define _countof(x) sizeof((x))/sizeof(*(x))
+#endif
+
+/* test data */
+static const uint8_t test_hash[] = {
+    0x77, 0x38, 0x65, 0x00, 0x1e, 0x96, 0x48, 0xc6, 0x57, 0x0b, 0xae,
+    0xc0, 0xb7, 0x96, 0xf9, 0x66, 0x4d, 0x5f, 0xd0, 0xb7
+};
+
+/* valid test strings to test with and without embedded and trailing spaces */
+static const char *valid_str[] = {
+    "773865001e9648c6570baec0b796f9664d5fd0b7",
+    " 77 386500 1e 96 48 c6570b aec0b7   96f9664d5f  d0 b7",
+    "   773865001e9648c6570baec0b796f9664d5fd0b7  ",
+};
+
+/* some invalid strings to test with and without embedded and trailing spaces */
+static const char *invalid_str[] = {
+    "773 865001e9648c6570baec0b796f9664d5fd012",  /* space within byte */
+    "77:38:65001e9648c6570baec0b796f9664d5fd0b7", /* invalid separator */
+    "7738x5001e9648c6570baec0b796f9664d5fd0b7",   /* non hex character */
+};
+
+static void
+test_parse_hexstring(void **state)
+{
+    unsigned char hash[255];
+    (void) state;
+
+    for (int i = 0; i < _countof(valid_str); i++)
+    {
+        int len = parse_hexstring(valid_str[i], hash, _countof(hash));
+        assert_int_equal(len, sizeof(test_hash));
+        assert_memory_equal(hash, test_hash, sizeof(test_hash));
+        memset(hash, 0, _countof(hash));
+    }
+
+    for (int i = 0; i < _countof(invalid_str); i++)
+    {
+        int len = parse_hexstring(invalid_str[i], hash, _countof(hash));
+        assert_int_equal(len, 0);
+    }
+}
+
+int
+main(void)
+{
+    const struct CMUnitTest tests[] = { cmocka_unit_test(test_parse_hexstring) };
+
+    int ret = cmocka_run_group_tests_name("cryptoapi tests", tests, NULL, NULL);
+
+    return ret;
+}
+
+#else  /* ifdef HAVE_XKEY_PROVIDER */
+
+int
+main(void)
+{
+    return 0;
+}
+
+#endif  /* ifdef HAVE_XKEY_PROVIDER */