Build and Debug Master Branch of OpenSSL on Ubuntu 16.04

A brief review of cloning, building, and debugging the master branch of the OpenSSL project along with stepping into the crypto library with GDB. More to come...

Overview

OpenSSL is the defacto, open source command line tool and libraries for cryptography. It has cutting edge support of cryptographic algorithms and an experienced team of developers. However, there seems to be a dearth of recent documentation and examples regarding developing with OpenSSL, especially with the latest API. Therefore, this article is a brief summary on getting started with OpenSSL development and will be expanded throughout 2018.

The openssl executable itself is a command line tool that can also be used interactively. A simple example using the openssl executable supplied with Ubuntu 16.04:

$ openssl
OpenSSL> version
OpenSSL 1.0.2g  1 Mar 2016
OpenSSL> quit

openssl relies on two important libraries that are part of the OpenSSL project:

  • libssl provides the client and server-side implementations for SSLv3 and TLS.
  • libcrypto provides general cryptographic and X.509 support needed by SSL/TLS but not logically part of it

We have found that the best way to learn how to work with the OpenSSL libraries is to look at how the openssl application makes use of them itself, and this is shown by example below.

Related Links

Build Master Branch on Ubuntu 16.04

Below we show steps to clone, build, and use the master branch of the OpenSSL repository without actually installing it (overwriting or interfering with the default installation).

$ cd /build/  # /build is where we build our code

$ git clone https://github.com/openssl/openssl.git
$ cd /build/openssl

$ git checkout master; git pull

$ find . -name tls1.h | xargs grep TLS1_3_VERSION_DRAFT_TXT
# define TLS1_3_VERSION_DRAFT_TXT        "TLS 1.3 (draft 22)"

$ mkdir build; cd /build/openssl/build

$../config --prefix=/opt/openssl --openssldir=$HOME/openssl no-deprecated enable-tls1_3 --debug

Operating system: x86_64-whatever-linux2
Using implicit seed configuration
Configuring OpenSSL version 1.1.1-dev (0x10101000L)
for linux-x86_64
    no-aria         [default]  OPENSSL_NO_ARIA (skip dir)
    no-asan         [default]  OPENSSL_NO_ASAN
    no-crypto-mdebug [default]  OPENSSL_NO_CRYPTO_MDEBUG
    no-crypto-mdebug-backtrace [default]  OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
    no-deprecated   [option]   OPENSSL_NO_DEPRECATED
    no-devcryptoeng [default]  OPENSSL_NO_DEVCRYPTOENG
    no-ec_nistp_64_gcc_128 [default]  OPENSSL_NO_EC_NISTP_64_GCC_128
    no-egd          [default]  OPENSSL_NO_EGD
    no-external-tests [default]  OPENSSL_NO_EXTERNAL_TESTS
    no-fuzz-afl     [default]  OPENSSL_NO_FUZZ_AFL
    no-fuzz-libfuzzer [default]  OPENSSL_NO_FUZZ_LIBFUZZER
    no-heartbeats   [default]  OPENSSL_NO_HEARTBEATS
    no-md2          [default]  OPENSSL_NO_MD2 (skip dir)
    no-msan         [default]  OPENSSL_NO_MSAN
    no-rc5          [default]  OPENSSL_NO_RC5 (skip dir)
    no-sctp         [default]  OPENSSL_NO_SCTP
    no-ssl-trace    [default]  OPENSSL_NO_SSL_TRACE
    no-ssl3         [default]  OPENSSL_NO_SSL3
    no-ssl3-method  [default]  OPENSSL_NO_SSL3_METHOD
    no-tls13downgrade [default]  OPENSSL_NO_TLS13DOWNGRADE
    no-ubsan        [default]  OPENSSL_NO_UBSAN
    no-unit-test    [default]  OPENSSL_NO_UNIT_TEST
    no-weak-ssl-ciphers [default]  OPENSSL_NO_WEAK_SSL_CIPHERS
    no-zlib         [default] 
    no-zlib-dynamic [default] 

PERL          =/usr/bin/perl
PERLVERSION   =5.22.1 for x86_64-linux-gnu-thread-multi
HASHBANGPERL  =/usr/bin/env perl
CC            =gcc
CFLAG         =-Wall -O0 -g -pthread -m64 -DL_ENDIAN  -Wa,--noexecstack
CXX           =g++
CXXFLAG       =-Wall -O0 -g -pthread -m64 -DL_ENDIAN  -Wa,--noexecstack
DEFINES       =DSO_DLFCN HAVE_DLFCN_H OPENSSL_THREADS OPENSSL_NO_STATIC_ENGINE OPENSSL_PIC OPENSSL_IA32_SSE2 OPENSSL_BN_ASM_MONT OPENSSL_BN_ASM_MONT5 OPENSSL_BN_ASM_GF2m SHA1_ASM SHA256_ASM SHA512_ASM RC4_ASM MD5_ASM AES_ASM VPAES_ASM BSAES_ASM GHASH_ASM ECP_NISTZ256_ASM PADLOCK_ASM POLY1305_ASM OPENSSL_API_COMPAT=0x10100000L
EX_LIBS       =-ldl

$ make

config options used (see INSTALL for extensive list of supported options):

  • --prefix: top of the installation directory tree
  • --openssldir: directory for OpenSSL configuration files, and also the default certificate and key store.
  • no-deprecated: removes support of all deprecated APIs in 1.1.0 and below
  • --debug: build with debugging symbols

After building openssl in our local /build/openssl/build directory, let's determine where to find the openssl executable & crypto libraries and setup executing openssl without installing it:

$ ls *.so
libcrypto.so  libssl.so

$ ./apps/openssl 
./apps/openssl: error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory
envy:build$ ldd ./apps/openssl
	linux-vdso.so.1 =>  (0x00007ffc1cffe000)
	libssl.so.1.1 => not found
	libcrypto.so.1.1 => not found
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f53c4117000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f53c3d4d000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f53c4334000)
	
$ export LD_LIBRARY_PATH=/build/openssl/build
envy:build$ ldd ./apps/openssl
	linux-vdso.so.1 =>  (0x00007fff45cbb000)
	libssl.so.1.1 => /build/openssl/build/libssl.so.1.1 (0x00007f3bd27d5000)
	libcrypto.so.1.1 => /build/openssl/build/libcrypto.so.1.1 (0x00007f3bd22c9000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f3bd20ac000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3bd1ce2000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f3bd1ade000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f3bd2a80000)
	
$ ./apps/openssl 
OpenSSL> version
OpenSSL 1.1.1-dev  xx XXX xxxx
OpenSSL> 

Debugging genrsa

Generating an RSA private key is a common and interesting function for the openssl application. Below we'll set up a breakpoint in an RSA crypto library function, which will be called when we invoke genrasa:

$ gdb -v
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1

$ gdb ./app/openssl
...
Reading symbols from ./apps/openssl...done.
(gdb) break main
Breakpoint 1 at 0x43a457: file ../apps/openssl.c, line 119.

(gdb) run
...
Breakpoint 1, main (argc=1, argv=0x7fffffffe4a8) at ../apps/openssl.c:119
119	{

(gdb) break rsa_builtin_keygen
Breakpoint 2 at 0x7ffff77fc056: file ../crypto/rsa/rsa_gen.c, line 66.

(gdb) cont
Continuing.
OpenSSL> genrsa
Generating RSA private key, 2048 bit long modulus (2 primes)

Breakpoint 2, rsa_builtin_keygen (rsa=0x6cfda0, bits=2048, primes=2, e_value=Reading in symbols for ../crypto/bn/bn_x931p.c...done.
0x6cfcc0, cb=0x6cfca0) at ../crypto/rsa/rsa_gen.c:66

(gdb) backtrace 
Reading in symbols for ../apps/genrsa.c...done.
#0  rsa_builtin_keygen (rsa=0x6cfda0, bits=2048, primes=2, e_value=0x6cfcc0, cb=0x6cfca0) at ../crypto/rsa/rsa_gen.c:66
#1  0x00007ffff77fc028 in RSA_generate_multi_prime_key (rsa=0x6cfda0, bits=2048, primes=2, e_value=0x6cfcc0, cb=0x6cfca0)
    at ../crypto/rsa/rsa_gen.c:61
#2  0x0000000000436559 in genrsa_main (argc=0, argv=0x6cfbf8) at ../apps/genrsa.c:147
#3  0x000000000043b1e1 in do_cmd (prog=0x6c3150, argc=1, argv=0x6cfbf0) at ../apps/openssl.c:552
#4  0x000000000043a840 in main (argc=1, argv=0x7fffffffe4b8) at ../apps/openssl.c:241
(gdb)

Now at this point, you can step through the RSA key generation routine, print variables, dump memory, etc. If you need help with GDB, then consult its documentation page. We'll also be adding some GDB development articles in the near future.

more to come...

Please help us improve this article by adding your comment or question:

email addresses are neither displayed nor shared