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

A. Sinan Unur

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.