OpenSSL for Windows

In earlier articles, we have looked at how to create a gcc build environment on Windows, and also how to compile binaries for Windows on Linux, using the MinGW-w64 suite to be able to support native 64-bit Windows builds.

But in order to build useful applications in these environments, we often need some common libraries. In this article, we will have a look at how to compile the OpenSSL library and make a small application that uses it. Compiled OpenSSL libraries are available for download (see the link at the bottom), in case you don’t want to do the compilation yourself.

 

Prerequisites

We will be cross-compiling from Linux. If you want to use Windows only, please consider downloading the compiled OpenSSL binaries near the bottom of the page, or adjust the paths accordingly when building the library.

I have my 64-bit Windows build environment installed in /opt/mingw64, and the cross-compiler prefix is x86_64-w64-mingw32. I will target (build binaries for) 64-bit Windows in this article. Please adjust these variables according to your own build environment. i686-w64-mingw32 is the prefix for the 32-bit Windows cross-compiler.

 

Compiling OpenSSL

  1. Follow the simple instructions on how to set up a Windows build environment on Linux. It is also possible to do this on Windows, but it is simpler and faster using Linux. Please leave a comment if you would like me to describe how to build on Windows.
  2. Grab the desired OpenSSL source tarball. Use OpenSSL version 1.0.0 or newer; OpenSSL versions older than v1.0.0 are a bit harder to build on Windows, but let me know if you want to see how to do this.  I’ll use OpenSSL version 1.0.0e in the following, but the steps should be identical for any version newer than 1.0.0.
  3. Put your tarball in a temporary directory, e.g. /tmp and unpack it:
    $ tar zxvf openssl-1.0.0e.tar.gz
  4. Run the configure script to use the 64-bit Windows compiler.
    $ cd openssl-1.0.0e
    $ CROSS_COMPILE="x86_64-w64-mingw32-" ./Configure mingw64 no-asm shared --prefix=/opt/mingw64


    Configured for mingw64.
  5. Compile. Make sure the the cross-compiler is in your path, or add it explicitly as show below.
    $ PATH=$PATH:/opt/mingw64/bin make
  6. Install it.
    $ sudo PATH=$PATH:/opt/mingw64/bin make install

We now have the OpenSSL libraries and headers for 64-bit Windows installed. Repeat the steps above with CROSS_COMPILE="i686-w64-mingw32-" and prefix /opt/mingw32 to build and install the 32-bit libraries for Windows.

 

A simple application

To confirm OpenSSL is working correctly, let’s create  a small C application that generates a SHA-256 digest of a character string. It reads a string given as the argument, generates the digest and shows the computed digest. The digest-generating code is shown below, while the complete code is available for download.

void SHA256Hash(unsigned char digest[EVP_MAX_MD_SIZE], char *stringToHash)
{
OpenSSL_add_all_digests();

const EVP_MD *md = EVP_get_digestbyname(“sha256″);

EVP_MD_CTX context;
EVP_MD_CTX_init(&context);
EVP_DigestInit_ex(&context, md, NULL);
EVP_DigestUpdate(&context, (unsigned char *)stringToHash, strlen(stringToHash));

unsigned int digestSz;
EVP_DigestFinal_ex(&context, digest, &digestSz);
EVP_MD_CTX_cleanup(&context);

EVP_cleanup();
}

  1. Save the file sha256.c in a working directory.
  2. Compile it.
    $ /opt/mingw64/bin/x86_64-w64-mingw32-gcc -I/opt/mingw64/include -L/opt/mingw64/lib -Wall sha256.c -lcrypto -o sha256.exe
  3. Check that the executable has the correct binary format (PE32+ is 64-bit).
    $ file sha256.exe
    sha256.exe: PE32+ executable for MS Windows (console) Mono/.Net assembly
  4. Copy our new program to a 64-bit Windows machine, and run it in the Windows Command Prompt.
    > sha256.exe 12345

The last step should generate the following dialog box, which contains the SHA-256 digest of the string “12345″.

sha256.exe sample run

 

OpenSSL Windows binaries

In case you don’t want to compile the OpenSSL library yourself, I have compiled version 1.0.0e and made it available for download below.

Just unpack each tarball to your respective MinGW-w64 installation directory. They should work both if you are running the gcc compiler on Windows, as well as cross-compiling for Windows like we have done above.

Please leave a comment if you found this interesting or have suggestions for improvements!

This entry was posted in GCC Windows and tagged , , , , . Bookmark the permalink.

23 Responses to OpenSSL for Windows

  1. Pingback: Compile for Windows on Linux | BlogCompiler

  2. Pingback: gcc for Windows | BlogCompiler

  3. Steven Penny says:

    > Please leave a comment if you would like me to describe how to build on Windows.

    Yes!

    • author says:

      Hi Steven,

      Were you interested in using MinGW to build on Windows, or a different environment (e.g. Visual Studio).

      Thanks.

    • Alberto says:

      Hi Steven
      I would like to know the steps in windows, now I’m using Eclipse with MinGW (in Windows 8, C/C++ language), thank you, Best Regards

  4. John says:

    When i try to run ‘make’, this happens after compiling:

    Creating library file: libcrypto.dll.a
    Cannot export OPENSSL_cleanse: symbol not defined
    Cannot export OPENSSL_cpuid_setup: symbol not defined
    libcrypto.a(cryptlib.o):cryptlib.c:(.text+0x431): undefined reference to `_OPENSSL_cpuid_setup'
    libcrypto.a(mem.o):mem.c:(.text+0xabe): undefined reference to `_OPENSSL_cleanse'

    It happened both on Linux (cross-compiling) and Windows on several different OpenSSL versions.

    I’m using i686-w64-mingw32 on Linux.

    • author says:

      Hi John,

      Which versions of OpenSSL did you try? I just successfully compiled 1.0.1c with the above steps. Also, which version of the MinGW w-64 toolchain are you using? I use the sezero one from 2011-10-05.

  5. John says:

    I tried OpenSSL 1.0.1c, 1.0.1b and 1.0.0h.
    I also tried the newest MinGW (20120531) on Windows, and both the sezero one (linked at http://www.blogcompiler.com/2010/07/11/compile-for-windows-on-linux/) and the version available on my package manager (don’t know the number).

    It seems weird that the compilation fails at the same step on both OS’s. Perhaps I’m missing something?
    Did you edit the Configure file in any way before running make?

    • author says:

      John,

      I did not change the Configure or do anything else than what is described in the steps above. However, I did manage to reproduce linking issues when manually removing libcrypto.* from the source directory. A couple of things to try:

      1. Run “make clean” before running “make”.

      2. Run “make clean”, “make depend” and then “make”.

      3. Disable shared libraries. Run “make clean”, then configure with “CROSS_COMPILE=”i686-w64-mingw32-” ./Configure mingw64 no-asm no-shared –prefix=/opt/mingw32″, and then run “make”.

      You can also try to remove the source directory and unpack again in case “make clean” does not do its job properly.

      Let me know how it works out for you.

  6. John says:

    Do you know where the implementation of function BIO_read is?
    I found the header definition in “include/ssl/bio.h”, but where could the implementation be?

  7. Jon says:

    In case someone else runs in to this problem, as I had a bit of trouble with -lcrypto I tried some other SSL libraries, and it turns out that -leay32 worked for me. And just that. I should note I have both the .a and .dll files on my machine (mingw32, the tdm compiler, windows 7 64-bit).

    • Jon says:

      I may also mention the best compilation tips I’ve come across are from rfc2324. They’re simple, but effective. They’re actually meant for cross-compiling, but whatever. Compiling OpenSSL on MinGW with the mingw.bat file is aggravating but enticing, so the site just gives you some help here and there.

  8. vijay says:

    Can you please post steps on how to compile OpenSSL for Windows 64 from Visual Studio.

    vijay

  9. snorkel says:

    Hi,
    Any chance you could update the binary builds to the 1.0.1e version?

  10. Luke says:

    This is great, thanks so much for sharing this!

    I was wondering:
    1. How do you work out which .exe and .dll etc files have been built by make, so that they can be packaged for Windows distribution?
    2. When I run openssl.exe from the version you compiled above, I get the message “WARNING: can’t open config file: /opt/mingw645/ssl/openssl.cnf”. It doesn’t seem to stop openssl.exe from working, but do you have any ideas how to resolve that, and maybe let openssl.exe read openssl.cnf from the directory the .exe runs from?
    3. Would you consider doing a similar post on compiling OpenSSH for Windows?

    • author says:

      Hi Luke,

      Thanks for your feedback.

      1. I have simply tried to run them on a Windows machine and put in new dlls one by one until Windows runs the executable. Windows will try to load dlls from the directory of the executable automatically, so you can simply put them in there. A more advanced option may be to run the mingw version of ldd against the executable, but I have not tried this myself.

      2. Sorry, I have not seen this issue before.

      3. Yes, thanks for the tip. I will put it on the backlog and see if I can get it going soon. It’s time to write a new post anyway. :)

      Have a nice day.

      • Luke says:

        Thanks for the answers. That’d be awesome if you could cover OpenSSH—looking forward to your next post, whatever it’s about (no pressure)!

  11. mpb says:

    It might be worth pointing out that Ubuntu (and Debian?) have packages that provide the MinGW cross compiler. Just run “sudo apt-get install mingw32″.

    Also, after running CROSS_COMPILE=”x86_64-w64-mingw32-” ./Configure … (as you suggested), make would fail (during linking?) with a bunch of undefined reference errors.

    However, when I followed the instructions nestled in the INSTALL.W32 file, make finished successfully, and it appears the resulting openssl.exe actually runs successfully!!

    The INSTALL.W32 instructions say to:
    ./Configure –cross-compile-prefix=i386-mingw32- mingw …

    Note that on Ubuntu 13.04, the cross compile prefix is: “i586-mingw32msvc-”, as that is the prefix of the compiler and build tools installed by the mingw32 package.

  12. Johnson says:

    First of all I want to thank you for the howto. I’ve been struggling with this compile for a week now and have made the most headway once I found your tutorial. I’m using ‘openssl-1.0.0l’ and I can compile it and create the sha256.exe file using the dynamic libraries, but I have to mv the libeay32.dll into the same directory as the sha256.exe file in order for it to run. When I add the ‘-static’ tag i get a compile error:
    $ /opt/mingw64/bin/x86_64-w64-mingw32-gcc -static -I/opt/mingw64/include -L/opt/mingw64/lib -Wall sha256.c -lcrypto -o sha256.exe
    /opt/mingw64/lib/libcrypto.a(rand_win.o):rand_win.c:(.text+0xd26): undefined reference to `__imp_CreateDCW’
    /opt/mingw64/lib/libcrypto.a(rand_win.o):rand_win.c:(.text+0xd32): undefined reference to `__imp_CreateCompatibleDC’
    ………..
    /opt/mingw64/lib/gcc/x86_64-w64-mingw32/4.8.3/../../../../x86_64-w64-mingw32/bin/ld: /opt/mingw64/lib/libcrypto.a(rand_win.o): bad reloc address 0×0 in section `.pdata’
    collect2: error: ld returned 1 exit status
    Any ideas for a remedy for this?

  13. HangLe says:

    I’m using CEGCC on Ubuntu. Could you please show me how to cross compile openssl with CEGCC?

    • author says:

      Hi HangLe,

      Unfortunately, I do not have any experience with cegcc, although I assume that the abstract method is the same.

      Perhpas some of the other readers know?

Leave a Reply

Your email address will not be published. Required fields are marked *


− eight = 1

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>