wolfSSL / wolfssl

The wolfSSL library is a small, fast, portable implementation of TLS/SSL for embedded devices to the cloud. wolfSSL supports up to TLS 1.3 and DTLS 1.3!
https://www.wolfssl.com
GNU General Public License v2.0
2.33k stars 827 forks source link

mingw compile problems #356

Closed jay closed 8 years ago

jay commented 8 years ago

I had a few problems compiling wolfSSL in mingw32, most warnings as errors that were caused by -Werror. Rather than -Wno-error which would be fine I guess I went through each of them.


The m4/visibility.m4 detection incorrectly detects mingw gcc as supporting __visibility__ likely because there's no function definition to actually test the visibility. If I add one then the visibility test will properly fail, for example:

extern __attribute__((__visibility__("hidden"))) int hiddenvar;
extern __attribute__((__visibility__("default"))) int exportedvar;
extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void);
extern __attribute__((__visibility__("default"))) int exportedfunc (void);
void dummyfunc (void) {}

int hiddenfunc (void) { return 0; }
int main(){ return hiddenfunc(); }
$ gcc -fvisibility=hidden -o vis vis.c
vis.c: In function 'hiddenfunc':
vis.c:7:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]

However I'm not sure whether it would cause other warnings that could make the visibility test fail incorrectly on other platforms. For now I can workaround by passing -Wno-attributes to C_EXTRA_FLAGS before configure.

Related cyassl/ctaocrypt/visibility.h does not define dllexport or dllimport unless msvc.


I am using configure switch --enable-alpn but it requires a safe strtok as defined in wolfcrypt/types.h which mingw does not have. As a workaround I used a public domain version found at http://stackoverflow.com/a/12979321.


Both src/asn.c and src/dsa.c have unsigned / signed comparisons. As a workaround I casted both sizeofs to (int).


Unused variable warnings on assert. If a variable is only used for assert there is a warning, like this

testsuite/testsuite.c: In function 'join_thread':
testsuite/testsuite.c:331:9: error: variable 'res' set but not used [-Werror=unused-but-set-variable]

The two or three of these I saw looked superfluous so my workaround was passing -Wno-unused-but-set-variable to C_EXTRA_FLAGS before configure.


I had problems running the tests as well:

MD5      test passed!
SHA      test passed!
SHA-256  test passed!
SHA-384  test passed!
SHA-512  test passed!
RIPEMD   test passed!
HMAC-MD5 test passed!
HMAC-SHA test passed!
HMAC-SHA256 test passed!
HMAC-SHA384 test passed!
HMAC-SHA512 test passed!
GMAC     test passed!
Chacha   test passed!
POLY1305 test passed!
ChaCha20-Poly1305 AEAD test passed!
DES      test passed!
DES3     test passed!
AES      test passed!
AES-GCM  test passed!
RANDOM   test passed!
RSA      test passed!
DH       test passed!
DSA      test passed!
PWDBASED test passed!
OPENSSL  test passed!
ECC      test passed!
error = -341, record layer length error
wolfSSL error: SSL_accept failed
FAIL: testsuite/testsuite.test.exe
starting unit tests...
 Begin API Tests
   wolfSSL_Init(): passed

ERROR - tests/api.c line 278 failed with:
    expected: wolfSSL_CTX_load_verify_locations(ctx, bogusFile, 0) is false
    result:   wolfSSL_CTX_load_verify_locations(ctx, bogusFile, 0) => TRUE

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
FAIL: tests/unit.test.exe
-1
ready file /x/j/curl/mingw/wolfssl_mingw/wolfssl_resume_ready6776

Starting example server for resume test...

waiting for ready file...
wolfSSL error: port number cannot be 0
waiting for ready file...
waiting for ready file...
waiting for ready file...
waiting for ready file...
waiting for ready file...
waiting for ready file...
waiting for ready file...
waiting for ready file...
waiting for ready file...
waiting for ready file...
waiting for ready file...
waiting for ready file...
waiting for ready file...
waiting for ready file...
waiting for ready file...
waiting for ready file...
waiting for ready file...
waiting for ready file...
waiting for ready file...
NO ready file ending test...
in cleanup
killing server
./scripts/resume.test: line 33: kill: (216) - No such process
FAIL: scripts/resume.test
WOLFSSL_EXTERNAL_TEST NOT set, won't run
PASS: scripts/external.test
Bad option -c.

Usage: ping [-t] [-a] [-n count] [-l size] [-f] [-i TTL] [-v TOS]
            [-r count] [-s count] [[-j host-list] | [-k host-list]]
            [-w timeout] [-R] [-S srcaddr] [-4] [-6] target_name

Options:
    -t             Ping the specified host until stopped.
                   To see statistics and continue - type Control-Break;
                   To stop - type Control-C.
    -a             Resolve addresses to hostnames.
    -n count       Number of echo requests to send.
    -l size        Send buffer size.
    -f             Set Don't Fragment flag in packet (IPv4-only).
    -i TTL         Time To Live.
    -v TOS         Type Of Service (IPv4-only. This setting has been deprecated
                   and has no effect on the type of service field in the IP Head
er).
    -r count       Record route for count hops (IPv4-only).
    -s count       Timestamp for count hops (IPv4-only).
    -j host-list   Loose source route along host-list (IPv4-only).
    -k host-list   Strict source route along host-list (IPv4-only).
    -w timeout     Timeout in milliseconds to wait for each reply.
    -R             Use routing header to test reverse route also (IPv6-only).
    -S srcaddr     Source address to use.
    -4             Force using IPv4.
    -6             Force using IPv6.

Couldn't find www.google.com, skipping
PASS: scripts/google.test
==========================================================
3 of 5 tests failed
Please report to https://github.com/wolfssl/wolfssl/issues
==========================================================
make[2]: *** [check-TESTS] Error 1
make[2]: Leaving directory `/x/j/curl/mingw/wolfssl_mingw'
make[1]: *** [check-am] Error 2
make[1]: Leaving directory `/x/j/curl/mingw/wolfssl_mingw'
make: *** [check] Error 2

The testsuite fail wasn't reproducible. In the background for an hour I've run while true; do testsuite/testsuite.test.exe 2>&1 | grep error; done but I haven't seen it again. (Edit: after I posted this I saw error = -308, error state on socket but that's not the same as record layer length error.)

The other two fails are reproducible. in unit.test:

ERROR - tests/api.c line 278 failed with:
    expected: wolfSSL_CTX_load_verify_locations(ctx, bogusFile, 0) is false
    result:   wolfSSL_CTX_load_verify_locations(ctx, bogusFile, 0) => TRUE

bogusFile is /dev/null and it fails because it's able to open it? I didn't look into that one too close.

in resume.test port number is 0 and I guess that isn't allowed for mingw

wolfSSL error: port number cannot be 0

another thing is the ping commands you're using ping -c but that's not universal on windows it should be ping -n. In cygwin you may need to test which is appropriate. The ping package that comes with cygwin doesn't use either and doesn't work properly so you could probably get away with something like -n for windows even if cygwin and -c elsewhere, unless someone on windows built ping manually.

jay commented 8 years ago

the /dev/null thing looks like it happens because although /dev/null is fine in mingw shell you're using the windows api so it needs NUL instead, probably something like this:

diff --git a/tests/api.c b/tests/api.c
index 36189ef..11d9c1b 100644
--- a/tests/api.c
+++ b/tests/api.c
@@ -58,8 +58,12 @@ static const char* passed = "passed";
 static const char* failed = "failed";

 #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
+#ifdef _WIN32
+static const char* bogusFile  = "NUL";
+#else
 static const char* bogusFile  = "/dev/null";
 #endif
+#endif

 /*----------------------------------------------------------------------------*
  | Setup

even with that fixed unit still fails though,

starting unit tests...
 Begin API Tests
   wolfSSL_Init(): passed
SUCCESS4
wolfSSL error: tcp connect failed
FAIL: tests/unit.test.exe
dgarske commented 8 years ago

Hey Jay, thanks for filing this issue and the excellent detail! I'll review and address each of these in our repo.

To confirm... you using are using the MinGW MSYS terminal with ./configure and make? Also can you confirm the MinGW version you are using?

Let me know if you find anything else. I'll update you when our internal pull request is issued.

jay commented 8 years ago

MinGW is a series of packages so there's no specific version afaict. Yes, I'm using the MSYS terminal and ./configure and make. The versions are gcc 4.7.0 and make 3.81 but this should apply to gcc 4.9.3 (the latest mingw package). To test this I installed mingw from scratch in a clean vm. I had some problems but as I noted in that report I believe the hanging is an msys problem and not with your code. Aside from that I still had the same issues building wolfSSL.

dgarske commented 8 years ago

Sorry, closed on accident. Working on this now.

dgarske commented 8 years ago

The MinGW hang is due to it trying to run multiple make's at the same time "-j2". To workaround this use "make -j1" to disable the job server. This is a MinGW / MSYS bug.

There are fixes on our side that I'll be making to resolve some of the warnings/errors you reported. That will result in a pull request later today. I'll post additional information soon. Thanks.

dgarske commented 8 years ago

Hey Jay,

I've resolved the visibility issue, build warnings and bogusFile check.

On the strtok_s we'd like to avoid implementing libc/string functions in our library. Its fine for you to add an implementation in your application that works. In fact you could wrap it in an "#ifdef MINGW32" check.

I'm still working on a solution for the port 0 error. With POSIX API's the listen can accept port 0 and will auto-assign one. Not sure if there is a good solution on that for Windows.

For now those fixes have been posted to https://github.com/dgarske/wolfssl/tree/mingwfixes.

Also I was wrong about the make -j1. The proper way to do that is "./configure --disable-jobserver".

Thanks, David Garske, wolfSSL

jay commented 8 years ago

Thanks David. I can confirm wolfSSL now builds fine with the exception of the missing strtok_s. While I realize you may not want to add such a function, I think it could be helpful to users who are building using mingw.

I did not test the jobserver fix since I'm using the old msys and at the moment I don't have time to try to build again in a clean VM. However I did add your information to the bug I filed.

Another thing I see is that the exported functions in the mingw built DLL contains internal functions. I'm pretty sure that's because WOLFSSL_DLL is not defined during build, and also because __declspec(dllexport) isn't used, for example this is how visibility.h should look I think

diff --git a/wolfssl/wolfcrypt/visibility.h b/wolfssl/wolfcrypt/visibility.h
index 82f110f..67741a2 100644
--- a/wolfssl/wolfcrypt/visibility.h
+++ b/wolfssl/wolfcrypt/visibility.h
@@ -46,7 +46,7 @@
     #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
         #define WOLFSSL_API   __global
         #define WOLFSSL_LOCAL __hidden
-    #elif defined(_MSC_VER)
+    #elif defined(_MSC_VER) || defined(__MINGW32__)
         #ifdef WOLFSSL_DLL
             #define WOLFSSL_API __declspec(dllexport)
         #else
@@ -58,7 +58,7 @@
         #define WOLFSSL_LOCAL
     #endif /* HAVE_VISIBILITY */
 #else /* BUILDING_WOLFSSL */
-    #if defined(_MSC_VER)
+    #if defined(_MSC_VER) || defined(__MINGW32__)
         #ifdef WOLFSSL_DLL
             #define WOLFSSL_API __declspec(dllimport)
         #else
dgarske commented 8 years ago

Pushed fixes for both the visibility and port 0 issues. Pull request 372 has been submitted for these: https://github.com/wolfSSL/wolfssl/pull/372

jay commented 8 years ago

WOLFSSL_DLL still needs to be defined, and another thing I noticed is the cyassl/options.h is read-only and permission is denied editing it. That would occur if the configure script is run more than once and is likely because the sed that comes with mingw changes the permissions on an in-place modification file to read only. I read on stackoverflow this is a problem with cygwin as well apparently. My suggestion is define WOLFSSL_DLL for mingw and chmod u+w cyassl/options.h after sed modifies it. These fixes may or may not be needed for cygwin I don't know. cygwin may need dll export in visibility also.

diff --git a/configure.ac b/configure.ac
index 9a84505..57eef23 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2606,6 +2606,15 @@ case $host_os in
         LDFLAGS="$LDFLAGS -lws2_32" ;;
 esac

+# We need WOLFSSL_DLL for Windows
+if test "$enable_shared" = "yes"
+then
+    case $host in
+        *-*-cygwin* | *-*-msys* | *-*-mingw*)
+            AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DLL" ;;
+    esac
+fi
+
 # add user C_EXTRA_FLAGS back
 CFLAGS="$CFLAGS $USER_C_EXTRA_FLAGS"
 OPTION_FLAGS="$USER_CFLAGS $USER_C_EXTRA_FLAGS $AM_CFLAGS"
@@ -2679,7 +2688,16 @@ for option in $OPTION_FLAGS; do
         noequalsign=`echo $defonly | sed 's/=/ /'`
         if test "$noequalsign" = "NDEBUG" || test "$noequalsign" = "DEBUG"
         then
-            echo "not outputing (N)DEBUG to $OPTION_FILE"
+            echo "not outputting (N)DEBUG to $OPTION_FILE"
+            continue
+        fi
+
+        # The user could use the options file with a static build or a shared
+        # build therefore it's up to them to define WOLFSSL_DLL when they are
+        # using wolfSSL DLL in their program.
+        if test "$noequalsign" = "WOLFSSL_DLL"
+        then
+            echo "not outputting WOLFSSL_DLL to $OPTION_FILE"
             continue
         fi

@@ -2729,6 +2747,8 @@ done < $OPTION_FILE

 # switch ifdef protection in cyassl/option.h to CYASSL_OPTONS_H, remove bak
 sed -i.bak 's/WOLFSSL_OPTIONS_H/CYASSL_OPTIONS_H/g' cyassl/options.h
+# mingw and cygwin sed change the permission to read only, for some reason.
+chmod u+w cyassl/options.h
 rm cyassl/options.h.bak

 # output config summary

Also the unit test is still failing,

starting unit tests...
 Begin API Tests
   wolfSSL_Init(): passed
SUCCESS4
wolfSSL error: tcp connect failed
FAIL: tests/unit.test.exe

The failure looks to be in test_client_nofail, it is attempting to connect to 127.0.0.1 port 0.

And ping -c doesn't work as I mentioned, that could be fixed by doing something like

diff --git a/scripts/external.test b/scripts/external.test
index f2ba8d1..7948306 100755
--- a/scripts/external.test
+++ b/scripts/external.test
@@ -15,8 +15,14 @@ else
     exit 0
 fi

+OS="`uname`"
+case $OS in
+  MINGW* | MSYS* | CYGWIN*) PINGSW=-n ;;
+  *) PINGSW=-c ;;
+esac
+
 # is our desired server there?
-ping -c 2 $server
+ping $PINGSW 2 $server
 RESULT=$?
 [ $RESULT -ne 0 ] && echo -e "\n\nCouldn't find $server, skipping" && exit 0

diff --git a/scripts/google.test b/scripts/google.test
index 8a3ca37..d12ac13 100755

 [ ! -x ./examples/client/client ] && echo -e "\n\nClient doesn't exist" && exit
 @ -6,8 +6,14 @@ server=www.google.com
+OS="`uname`"
+case $OS in
+  MINGW* | MSYS* | CYGWIN*) PINGSW=-n ;;
+  *) PINGSW=-c ;;
+esac
+
 # is our desired server there?
-ping -c 2 $server
+ping $PINGSW 2 $server
 RESULT=$?
 [ $RESULT -ne 0 ] && echo -e "\n\nCouldn't find $server, skipping" && exit 0

diff --git a/scripts/ocsp.test b/scripts/ocsp.test
index 66d4488..f698935 100755
--- a/scripts/ocsp.test
+++ b/scripts/ocsp.test
@@ -7,8 +7,14 @@ ca=certs/external/ca-globalsign-root-r2.pem

 [ ! -x ./examples/client/client ] && echo -e "\n\nClient doesn't exist" && exit

+OS="`uname`"
+case $OS in
+  MINGW* | MSYS* | CYGWIN*) PINGSW=-n ;;
+  *) PINGSW=-c ;;
+esac
+
 # is our desired server there?
-ping -c 2 $server
+ping $PINGSW 2 $server
 RESULT=$?
 [ $RESULT -ne 0 ] && echo -e "\n\nCouldn't find $server, skipping" && exit 0
dgarske commented 8 years ago

Hey Jay,

Thanks for the excellent follow up on this!

WOLFSSL_DLL: I had to define this as well to prevent all functions from being exported. Seems reasonable to define this for MinGW/MSys/Cygwin, but need to make sure it won't break anything on Windows.

cyassl/options.h is read-only: I also saw the permission error on the cyassl/options.h.

I didn't see the issues with the unit.test or the ping -c, but I will look into those and make appropriate fixes.

Thanks! Re-opening issue. David Garske

dgarske commented 8 years ago

Hey Jay,

I've pushed fixes for the WOLFSSL_DLL, cyassl/options.h permission issue, ping and port 0 on tests/unit. https://github.com/wolfSSL/wolfssl/pull/372

Let me know if there is anything else. David G.

jay commented 8 years ago

Note if both shared and static builds are being built then the options file will contain both WOLFSSL_SHARED and WOLFSSL_STATIC. If a user includes the options file in their program then both of those will be defined in their program.

Also two tests are failing. The first failed connect is 127.0.0.1:11111, the second is 127.0.0.1:0.

SSL version is TLSv1.2
SSL cipher suite is TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
Client message: hello wolfssl!
Server response: I hear you fa shizzle!
wolfSSL error: tcp connect failed
FAIL: testsuite/testsuite.test.exe
starting unit tests...
 Begin API Tests
   wolfSSL_Init(): passed
SUCCESS4
wolfSSL error: tcp connect failed
FAIL: tests/unit.test.exe
dgarske commented 8 years ago

Hey Jay, can you send me your ./configure options for reproducing this tcp connect failed? david@wolfssl.com. Thanks.

jay commented 8 years ago

You can find them here, however I tried with no options and the result is the same. From your branch mingwfixes (ac9df1a):

make distclean
./autogen.sh
./configure
make V=1
make test
dgarske commented 8 years ago

Hey Jay, sorry I was out on paternity leave, but am back now. The MinGW fixes were merged into master today. I haven't had a chance to try and reproduce the tcp connect failed error, but will do so this week and let you know if I can find a fix and if so will post a pull request. Also please send me an email at david@wolfssl.com so I can correspond with you directly. Thanks!