Thursday, April 10, 2014

Building OpenSSL 1.0.1g on 64-bit Windows Pro 8.1 with Windows SDK 7.1

This, actually, turned out to be surprisingly straightforward.

I admit, nothing is really straightforward when it comes to OpenSSL, but as such things go, this simply involved:

  1. Download the latest source distribution
  2. Open up a SDK command prompt
  3. Optionally, get zlib, build DLL
  4. Get nasm and build executable
  5. If you did ask for zlib, add directories to INCLUDE and LIB:

    C:\…\openssl-1.0.1g> set INCLUDE=%INCLUDE%;C:\…\zlib-1.2.8
    C:\…\openssl-1.0.1g> set LIB=%LIB%;C:\…\zlib-1.2.8
  6. Run C:\…\openssl-1.0.1g> perl Configure VC-WIN64A zlib-dynamic --openssldir=C:\opt\OpenSSL
  7. Run C:\…\openssl-1.0.1g> ms\do_win64a
  8. Run C:\…\openssl-1.0.1g> nmake -f ms\ntdll.mak
  9. Wait … well, at least on my machine ;-)
  10. cd to out32dll, and run ..\ms\test
  11. Make sure all tests pass:

  12. Install by doing:

    C:\…\openssl-1.0.1g\out32dll> cd ..
    C:\…\openssl-1.0.1g> nmake -f ms\ntdll.mak install

Now, if you want to compile and link against OpenSSL, you will need to make sure C:\opt\OpenSSL\include and C:\opt\OpenSSL\lib are added to the INCLUDE and LIB paths, respectively. To run code linked against this OpenSSL build, you will also need to make sure programs built against it can located the DLLs. I put the files from both in a common location, say, C:\opt\bin which is then added to my %PATH%.

I want that extra bit of protection for C:\opt\bin, so it is only writable by an admin user. So, fire up an admin command window, and do:

C:\…> xcopy C:\opt\OpenSSL\bin\* C:\opt\bin
 C:\opt\OpenSSL\bin\libeay32.dll
 C:\opt\OpenSSL\bin\openssl.exe
 C:\opt\OpenSSL\bin\ssleay32.dll
 3 File(s) copied

and

C:\…> xcopy \users\sinan\src\zlib-1.2.8\zlib1.dll c:\opt\bin

How can we test this actually worked?

Well, let's try building Crypt::SSLeay:

C:\…\src> git clone https://github.com/nanis/Crypt-SSLeay.git

C:\…\src> cd Crypt-SSLeay

C:\…\Crypt-SSLeay> perl Makefile.PL --libpath=C:\opt\OpenSSL\lib --incpath=C:\opt\OpenSSL\include --live-tests --no-verbose

C:\…\Crypt-SSLeay> nmake test

which should yield:

t/00-basic.t .... ok
t/01-connect.t .. ok
t/02-live.t ..... # Reading configuration from 'test.config' on MSWin32
# network_tests : 1
t/02-live.t ..... 5/? # [RT #73755] Cheat by disabling LWP::UserAgent host verification
t/02-live.t ..... ok
All tests successful.
Files=3, Tests=29,  6 wallclock secs ( 0.06 usr +  0.02 sys =  0.08 CPU)
Result: PASS

Now, do an nmake install. Then, switch to a new, non-SDK command window to make sure that things work outside of the development environment as well. Try running the following script:

use strict;
use warnings;
use Test::More;

# Make sure LWP uses Crypt::SSLeay, not IO::Socket::SSL
# IO::Socket::SSL is better, but this is testing Crypt::SSLeay
use Net::HTTPS;
$Net::HTTPS::SSL_SOCKET_CLASS = 'Net::SSL';

use HTTP::Request;
use LWP::UserAgent;

my $method = 'HEAD';
my $uri = 'https://example.com/';

my $ua = LWP::UserAgent->new(
    ssl_opts => { verify_hostname => 0 },
);

my $req = HTTP::Request->new;

$req->method($method);
$req->uri($uri);

my $test_name = "$method '$uri'";

my $res = $ua->request($req);

if ($res->is_success) {
    my $socket_class = $res->header('Client-SSL-Socket-Class');
    # Make sure *WE* succeded ;-)
    if ( isa_ok($socket_class, 'Net::SSL') ) {
        pass $test_name;
    }
    else {
        fail $test_name;
        diag "Request succeded but UA used '$socket_class'";
    }
}
else {
    fail $test_name;
    diag "HTTP status = ", $res->status_line ;
}

done_testing;

Which produces:

C:\…\Temp> perl check-example.pl
ok 1 - The class (or class-like) 'Net::SSL' isa 'Net::SSL'
ok 2 - HEAD 'https://example.com/'
1..2

Keep in mind that IO::Socket::SSL is the better module. If you have upgraded to LWP 6.xx and also installed LWP::Protocol::https, your LWP::UserAgent object is very likely using IO::Socket::SSL. Only force the use of Crypt::SSLeay if you have a specific need.

4 comments:

  1. Hi tried to update my openssl on strawberry perl to 1.0.1g using the the above instructions and everythings got ok until i run the following command:

    perl Makefile.PL --libpath=C:\opt\OpenSSL\lib --incpath=C:\opt\OpenSSL\include --live-tests --no-verbose

    i get the below message :
    live-tests --no-verbose
    Unknown option: libpath
    Unknown option: incpath
    Unknown option: no-verbose
    Warning (mostly harmless): No library found for -lssl
    Warning (mostly harmless): No library found for -lcrypto
    Writing Makefile for Crypt::SSLeay
    Writing MYMETA.yml and MYMETA.json

    Then i tried to install crypt::ssleay from cpan using o conf makepl_arg and lib and inc pointed to the openssl lib and inc dir but the build is failed and get the following error:
    SSLeay.o:SSLeay.c:(.text+0x2ed8): undefined reference to `SSL_CTX_set_verify'
    SSLeay.o:SSLeay.c:(.text+0x2f51): undefined reference to `OPENSSL_add_all_algorithms_noconf'
    SSLeay.o:SSLeay.c:(.text+0x2f56): undefined reference to `SSL_load_error_strings'
    SSLeay.o:SSLeay.c:(.text+0x2f5b): undefined reference to `ERR_load_crypto_strings'
    SSLeay.o:SSLeay.c:(.text+0x2f61): undefined reference to `SSL_library_init'
    SSLeay.o:SSLeay.c:(.text+0x2f75): undefined reference to `SSLv3_client_method'
    SSLeay.o:SSLeay.c:(.text+0x2f7d): undefined reference to `SSL_CTX_new'
    SSLeay.o:SSLeay.c:(.text+0x2f9b): undefined reference to `RAND_seed'
    SSLeay.o:SSLeay.c:(.text+0x2fa5): undefined reference to `SSLv23_client_method'
    SSLeay.o:SSLeay.c:(.text+0x2fb1): undefined reference to `SSL_CTX_new'
    SSLeay.o:SSLeay.c:(.text+0x3043): undefined reference to `ERR_get_error'
    SSLeay.o:SSLeay.c:(.text+0x30c7): undefined reference to `ERR_get_error'
    SSLeay.o:SSLeay.c:(.text+0x30e0): undefined reference to `ERR_error_string'
    c:/strawberry-perl-5.16.3.1-64bit-portable/c/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../x
    4-w64-mingw32/bin/ld.exe: SSLeay.o: bad reloc address 0x0 in section `.pdata'
    c:/strawberry-perl-5.16.3.1-64bit-portable/c/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../x
    4-w64-mingw32/bin/ld.exe: final link failed: Invalid operation
    collect2: ld returned 1 exit status
    dmake.EXE: Error code 129, while making 'blib\arch\auto\Crypt\SSLeay\SSLeay.dll'
    NANIS/Crypt-SSLeay-0.64.tar.gz
    C:\strawberry\c\bin\dmake.EXE -- NOT OK
    Running make test
    Can't test without successful make
    Running make install
    Make had returned bad status, install seems impossible
    Failed during this command:
    NANIS/Crypt-SSLeay-0.64.tar.gz : make NO

    do you have any idea what could be my mistake here ?

    ReplyDelete
    Replies
    1. I notice two possibilities: 1) You say you tried to "update my openssl", but all I see is output related to Crypt::SSLeay. To build a new version of OpenSSL libraries, please download the source from openssl.org. 2) My instructions for Crypt::SSLeay apply to the latest development version, available from GitHub or CPAN by manually checking out the source or downloading the development version.

      If you have Strawberry Perl, and if you had built OpenSSL from source, the library and header files would be under your Strawberry Perl installation, not under c:\opt\.

      So, please first build OpenSSL, then try the latest development version of Crypt::SSLeay and let me know if things improve. I am planning to release 0.66 in a few days and I would appreciate the input. Please report bugs/issues on RT bugtracker.

      Delete
  2. I'm getting a lot of: warning C4267: '=' : conversion from 'size_t' to 'int', possible loss of data Did you anything about addressing those warnings?

    ReplyDelete
    Replies
    1. I am not sure I would call that "a lot", but there are some. And, no, I haven't gotten around to looking at those yet.

      Delete