WOLFSSL MANUAL: CHAPTER 3

Download wolfSSL Manual (PDF)

Chapter 3 : Getting Started

 

3.1 General Description

 

wolfSSL is about 10 times smaller than yaSSL and up to 20 times smaller than OpenSSL when using the compile options described in Chapter 2. User benchmarking and feedback also reports dramatically better performance from wolfSSL vs. OpenSSL in the vast majority of standard SSL operations.

 

For instructions on the build process please see Chapter 2.

 

3.2 Testsuite

 

The testsuite program is designed to test the ability of wolfSSL and its cryptography library, wolfCrypt, to run on the system.  

 

wolfSSL needs all examples and tests to be run from the wolfSSL home directory.  This is because it finds certs and keys from ./certs.  To run testsuite, execute:

 

./testsuite/testsuite.test

 

or

 

make test    (when using autoconf)

 

On *nix or Windows the examples and testsuite will check to see if the current directory is the source directory and if so, attempt to change to the wolfSSL home directory.  This should work in most setup cases, if not, just use the first method above and specify the full path.

 

On a successful run you should see output like this, with additional output for unit tests and cipher suite tests:

 

MD5      test passed!

SHA      test passed!

SHA-224  test passed!

SHA-256  test passed!

SHA-384  test passed!

SHA-512  test passed!

HMAC-MD5 test passed!

HMAC-SHA test passed!

HMAC-SHA224 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!

AES      test passed!

AES-GCM  test passed!

RANDOM   test passed!

RSA      test passed!

DH       test passed!

ECC      test passed!

SSL version is TLSv1.2

SSL cipher suite is TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

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!

sending server shutdown command: quit!

client sent quit command: shutting down!

ciphers = DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305-OLD:ECDHE-ECDSA-CHACHA20-POLY1305-OLD:DHE-RSA-CHACHA20-POLY1305-OLD

33bc1a4570f4f1abccd5c48aace529b01a42ab51293954a297796e90d20970f0  input

33bc1a4570f4f1abccd5c48aace529b01a42ab51293954a297796e90d20970f0  /tmp/output-7Iyhbo

 

All tests passed!

 

This indicates that everything is configured and built correctly. If any of the tests fail, make sure the build system was set up correctly. Likely culprits include having the wrong endianness or not properly setting the 64-bit type. If you've set anything to the non-default settings try removing those, rebuilding wolfSSL, and then re-testing.

 

3.3 Client Example

 

You can use the client example found in examples/client to test wolfSSL against any SSL server. To see a list of available command line runtime options, run the client with the --help argument:

 

./examples/client/client --help

client 3.9.10 NOTE: All files relative to wolfSSL home dir

-?          Help, print this usage

-h <host>   Host to connect to, default 127.0.0.1

-p <num>    Port to connect on, not 0, default 11111

-v <num>    SSL version [0-3], SSLv3(0) - TLS1.2(3)), default 3

-V          Prints valid ssl version numbers, SSLv3(0) - TLS1.2(3)

-l <str>    Cipher suite list (: delimited)

-c <file>   Certificate file,           default ./certs/client-cert.pem

-k <file>   Key file,                   default ./certs/client-key.pem

-A <file>   Certificate Authority file, default ./certs/ca-cert.pem

-Z <num>    Minimum DH key bits,        default 1024

-b <num>    Benchmark <num> connections and print stats

-B <num>    Benchmark throughput using <num> bytes and print stats

-s          Use pre Shared keys

-t          Track wolfSSL memory use

-d          Disable peer checks

-D          Override Date Errors example

-e          List Every cipher suite available,

-g          Send server HTTP GET

-u          Use UDP DTLS, add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)

-m          Match domain name in cert

-N          Use Non-blocking sockets

-r          Resume session

-w          Wait for bidirectional shutdown

-M <prot>   Use STARTTLS, using <prot> protocol (smtp)

-f          Fewer packets/group messages

-x          Disable client cert/key loading

-X          Driven by eXternal test case

-n          Disable Extended Master Secret

 

To test against example.com:443 try the following.  This is using wolfSSL compiled with the --enable-opensslextra --enable-supportedcurves build options:

 

./examples/client/client -h example.com -p 443 -d -g

peer's cert info:

 issuer : /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA

 subject: /C=US/ST=California/L=Los Angeles/O=Internet Corporation for Assigned Names and Numbers/OU=Technology/CN=www.example.org

 altname = www.example.net

 altname = www.example.edu

 altname = www.example.com

 altname = example.org

 altname = example.net

 altname = example.edu

 altname = example.com

 altname = www.example.org

 serial number:0e:64:c5:fb:c2:36:ad:e1:4b:17:2a:eb:41:c7:8c:b0

SSL version is TLSv1.2

SSL cipher suite is TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

Client Random : 83083A1D84404E66C86D7560A2C6ACEEEB0C35F94FDD5E07BC7507CD4E273B19

SSL connect ok, sending GET...

Server response: HTTP/1.0 200 OK

Accept-Ranges: bytes

Content-Type: text/html

Date: Tue, 20 D

ec 2016 22:52:00 GMT

Last-Modified: Tue, 20 Dec 2016 22:33:12 GMT

Server: ECS

 (pae/378A)

Content-Length: 94

Connection: close

 

<html><head><title>edgecastcdn.net</title></head>

<body><h1>edgecastcdn.net</h1></body></html>

 

This tells the client to connect to (-h) example.com on the HTTPS port (-p) of 443 and sends a generic (-g) GET request. The (-d) option tells the client not to verify the server. The rest is the initial output from the server that fits into the read buffer.

 

If no command line arguments are given, then the client attempts to connect to the localhost on the wolfSSL default port of 11111.  It also loads the client certificate in case the server wants to perform client authentication.

 

The client is able to benchmark a connection when using the “-b <num>” argument. When used, the client attempts to connect to the specified server/port the argument number of times and gives the average time in milliseconds that it took to perform SSL_connect().  For example,

 

./examples/client/client -b 100

SSL_connect avg took: 0.653 milliseconds

 

If you'd like to change the default host from localhost, or the default port from 11111, you can change these settings in /wolfssl/test.h. The variables wolfSSLIP and wolfSSLPort control these settings. Re-build all of the examples including testsuite when changing these settings otherwise the test programs won't be able to connect to each other.

 

By default, the wolfSSL example client tries to connect to the specified server using TLS 1.2.  The user is able to change the SSL/TLS version which the client uses by using the “-v” command line option.  The following values are available for this option:

 

-v 0  =  SSL 3.0 (disabled by default)

-v 1  =  TLS 1.0

-v 2  =  TLS 1.1

-v 3  =  TLS 1.2

 

A common error users see when using the example client is -155:

 

 err = -155, ASN sig error, confirm failure

 

This is typically caused by the wolfSSL client not being able to verify the certificate of the server it is connecting to.  By default, the wolfSSL client loads the yaSSL test CA certificate as a trusted root certificate.  This test CA certificate will not be able to verify an external server certificate which was signed by a different CA.  As such, to solve this problem, users either need to turn off verification of the peer (server), using the “-d” option:

 

./examples/client/client -h myhost.com -p 443 -d

 

Or load the correct CA certificate into the wolfSSL client using the “-A” command line option:

 

./examples/client/client -h myhost.com -p 443 -A serverCA.pem

 

3.4 Server Example

 

The server example demonstrates a simple SSL server that optionally performs client authentication. Only one client connection is accepted and then the server quits. The client example in normal mode (no command line arguments) will work just fine against the example server, but if you specify command line arguments for the client example, then a client certificate isn't loaded and the wolfSSL_connect() will fail (unless client cert check is disabled using the “-d” option). The server will report an error "-245, peer didn't send cert".  Like the example client, the server can be used with several command line arguments as well:

 

./examples/server/server --help

server 3.9.10 NOTE: All files relative to wolfSSL home dir

-?          Help, print this usage

-p <num>    Port to listen on, not 0, default 11111

-v <num>    SSL version [0-3], SSLv3(0) - TLS1.2(3)), default 3

-l <str>    Cipher suite list (: delimited)

-c <file>   Certificate file,           default ./certs/server-cert.pem

-k <file>   Key file,                   default ./certs/server-key.pem

-A <file>   Certificate Authority file, default ./certs/client-cert.pem

-R <file>   Create Ready file for external monitor default none

-D <file>   Diffie-Hellman Params file, default ./certs/dh2048.pem

-Z <num>    Minimum DH key bits,        default 1024

-d          Disable client cert check

-b          Bind to any interface instead of localhost only

-s          Use pre Shared keys

-t          Track wolfSSL memory use

-u          Use UDP DTLS, add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)

-f          Fewer packets/group messages

-r          Allow one client Resumption

-N          Use Non-blocking sockets

-S <str>    Use Host Name Indication

-w          Wait for bidirectional shutdown

-i          Loop indefinitely (allow repeated connections)

-e          Echo data mode (return raw bytes received)

-B <num>    Benchmark throughput using <num> bytes and print stats

 

3.5 EchoServer Example

 

The echoserver example sits in an endless loop waiting for an unlimited number of client connections. Whatever the client sends the echoserver echoes back. Client authentication isn't performed so the example client can be used against the echoserver in all 3 modes. Four special commands aren't echoed back and instruct the echoserver to take a different action.

 

  1. "quit"  If the echoserver receives the string "quit" it will shutdown.

 

  1. "break"  If the echoserver receives the string "break" it will stop the current session but continue handling requests. This is particularly useful for DTLS testing.

 

  1. "printstats" If the echoserver receives the string "printstats" it will print out statistics for the session cache.

 

  1. "GET"  If the echoserver receives the string "GET" it will handle it as an http get and send back a simple page with the message "greeting from wolfSSL".  This allows testing of various TLS/SSL clients like Safari, IE, Firefox, gnutls, and the like against the echoserver example.

 

The output of the echoserver is echoed to stdout unless NO_MAIN_DRIVER is defined.  You can redirect output through the shell or through the first command line argument. To create a file named output.txt with the output from the echoserver run:

 

./examples/echoserver/echoserver output.txt

 

3.6 EchoClient Example

 

The echoclient example can be run in interactive mode or batch mode with files. To run in interactive mode and write 3 strings "hello", "wolfssl", and "quit" results in:

 

./examples/echoclient/echoclient

hello

hello

wolfssl

wolfssl

quit

sending server shutdown command: quit!

 

To use an input file, specify the filename on the command line as the first argument. To echo the contents of the file input.txt issue:

 

./examples/echoclient/echoclient input.txt

 

If you want the result to be written out to a file, you can specify the output file name as an additional command line argument. The following command will echo the contents of file input.txt and write the result from the server to output.txt:

 

./examples/echoclient/echoclient input.txt output.txt

 

The testsuite program does just that, but hashes the input and output files to make sure that the client and server were getting/sending the correct and expected results.

 

3.7 Benchmark

 

Many users are curious about how the wolfSSL embedded SSL library will perform on a specific hardware device or in a specific environment.  Because of the wide variety of different platforms and compilers used today in embedded, enterprise, and cloud-based environments, it is hard to give generic performance calculations across the board.

 

To help wolfSSL users and customers in determining SSL performance for wolfSSL / wolfCrypt, a benchmark application is provided which is bundled with wolfSSL.  wolfSSL uses the wolfCrypt cryptography library for all crypto operations by default.  Because the underlying crypto is a very performance-critical aspect of SSL/TLS, our benchmark application runs performance tests on wolfCrypt’s algorithms.

 

The benchmark utility located in wolfcrypt/benchmark (./wolfcrypt/benchmark/benchmark) may be used to benchmark the cryptographic functionality of wolfCrypt. Typical output may look like the following (in this output, several optional algorithms/ciphers were enabled including HC-128, RABBIT, ECC, SHA-256, SHA-512, AES-GCM, AES-CCM, and Camellia):

 

./wolfcrypt/benchmark/benchmark

 

RNG      50 megs took 0.516 seconds,   96.975 MB/s Cycles per byte =  22.57

AES enc  50 megs took 0.278 seconds,  179.737 MB/s Cycles per byte =  12.18

AES dec  50 megs took 0.260 seconds,  192.029 MB/s Cycles per byte =  11.40

AES-GCM  50 megs took 0.840 seconds,   59.552 MB/s Cycles per byte =  36.75

AES-CCM  50 megs took 0.534 seconds,   93.548 MB/s Cycles per byte =  23.39

Camellia 50 megs took 0.376 seconds,  132.928 MB/s Cycles per byte =  16.46

HC128    50 megs took 0.032 seconds, 1550.586 MB/s Cycles per byte =   1.41

RABBIT   50 megs took 0.109 seconds,  459.559 MB/s Cycles per byte =   4.76

CHACHA   50 megs took 0.144 seconds,  347.427 MB/s Cycles per byte =   6.30

CHA-POLY 50 megs took 0.190 seconds,  262.978 MB/s Cycles per byte =   8.32

IDEA     50 megs took 0.807 seconds,   61.982 MB/s Cycles per byte =  35.31

 

MD5      50 megs took 0.111 seconds,  452.121 MB/s Cycles per byte =   4.84

POLY1305 50 megs took 0.039 seconds, 1281.392 MB/s Cycles per byte =   1.71

SHA      50 megs took 0.118 seconds,  424.747 MB/s Cycles per byte =   5.15

SHA-224  50 megs took 0.242 seconds,  206.789 MB/s Cycles per byte =  10.58

SHA-256  50 megs took 0.243 seconds,  206.022 MB/s Cycles per byte =  10.62

SHA-384  50 megs took 0.172 seconds,  290.787 MB/s Cycles per byte =   7.53

SHA-512  50 megs took 0.175 seconds,  286.117 MB/s Cycles per byte =   7.65

 

scrypt   39.698 milliseconds, avg over 10 iterations

 

RSA 2048 public           0.358 milliseconds, avg over 100 iterations

RSA 2048 private          4.537 milliseconds, avg over 100 iterations

DH  2048 key generation   1.391 milliseconds, avg over 100 iterations

DH  2048 key agreement    1.422 milliseconds, avg over 100 iterations

 

ECC  256 key generation   0.885 milliseconds, avg over 100 iterations

EC-DHE   key agreement    0.874 milliseconds, avg over 100 iterations

EC-DSA   sign   time      0.929 milliseconds, avg over 100 iterations

EC-DSA   verify time      0.602 milliseconds, avg over 100 iterations

 

This is especially useful for comparing the public key speed before and after changing the math library. You can test the results using the normal math library (./configure), the fastmath library (./configure --enable-fastmath), and the fasthugemath library (./configure --enable-fasthugemath).

 

For more details and benchmark results, please refer to the wolfSSL Benchmarks page: https://www.wolfssl.com/docs/benchmarks/

 

3.7.1 Relative Performance

Although the performance of individual ciphers and algorithms will depend on the host platform, the following graph shows relative performance between wolfCrypt’s ciphers.  These tests were conducted on a Macbook Pro (OS X 10.6.8) running a 2.2 GHz Intel Core i7.

 

 

If you want to use only a subset of ciphers, you can customize which specific cipher suites and/or ciphers wolfSSL uses when making an SSL/TLS connection.  For example, to force 128-bit AES, add the following line after the call to wolfSSL_CTX_new (SSL_CTX_new):

 

wolfSSL_CTX_set_cipher_list(ctx, “AES128-SHA”);

 

3.7.2 Benchmarking Notes

 

  1. The processors native register size (32 vs 64-bit) can make a big difference when doing 1000+ bit public key operations.
  2. keygen (--enable-keygen) will allow you to also benchmark key generation speeds when running the benchmark utility.
  3. fastmath (--enable-fastmath) reduces dynamic memory usage and speeds up public key operations. If you are having trouble building on 32-bit platform with fastmath, disable shared libraries so that PIC isn’t hogging a register (also see notes in the README)

    ./configure --enable-fastmath --disable-shared
    make clean
    make

    *Note: doing a “make clean” is good practice with wolfSSL when switching configure options.

  4. By default, fastmath tries to use assembly optimizations if possible. If assembly optimizations don’t work, you can still use fastmath without them by adding TFM_NO_ASM to CFLAGS when building wolfSSL:

    ./configure --enable-fastmath C_EXTRA_FLAGS=”-DTFM_NO_ASM”

  5. Using fasthugemath can try to push fastmath even more for users who are not running on embedded platforms:

    ./configure --enable-fasthugemath

  6. With the default wolfSSL build, we have tried to find a good balance between memory usage and performance. If you are more concerned about one of the two, please refer back to Chapter 2 for additional wolfSSL configuration options.
  7. Bulk Transfers: wolfSSL by default uses 128 byte I/O buffers since about 80% of SSL traffic falls within this size and to limit dynamic memory use. It can be configured to use 16K buffers (the maximum SSL size) if bulk transfers are required.

 

3.7.3 Benchmarking on Embedded Systems

 

There are several build options available to make building the benchmark application on an embedded system easier.  These include:

 

BENCH_EMBEDDED - enabling this define will switch the benchmark application from using Megabytes to using Kilobytes, therefore reducing the memory usage.  By default, when using this define, ciphers and algorithms will be benchmarked with 25kB.  Public key algorithms will only be benchmarked over 1 iteration (as public key operations on some embedded processors can be fairly slow).  These can be adjusted in benchmark.c by altering the variables “numBlocks” and “times” located inside the BENCH_EMBEDDED define.

 

USE_CERT_BUFFERS_1024 - enabling this define will switch the benchmark application from loading test keys and certificates from the file system and instead use 1024-bit key and certificate buffers located in <wolfssl_root>/wolfssl/certs_test.h.  It is useful to use this define when an embedded platform has no filesystem (used with NO_FILESYSTEM) and a slow processor where 2048-bit public key operations may not be reasonable.

 

USE_CERT_BUFFERS_2048 - enabling this define is similar to USE_CERT_BUFFERS_1024 accept that 2048-bit key and certificate buffers are used instead of 1024-bit ones.  This define is useful when the processor is fast enough to do 2048-bit public key operations but when there is no filesystem available to load keys and certificates from files.

 

3.8 Changing a Client Application to Use wolfSSL

 

This section will explain the basic steps needed to add wolfSSL to a client application, using the wolfSSL native API. For a server explanation, please see Section 3.9.  A more complete walk-through with example code is located in the SSL Tutorial in Chapter 11.  If you want more information about the OpenSSL compatibility layer, please see Chapter 13.

 

  1. Include the wolfSSL header

 

#include <wolfssl/ssl.h>

 

  1. Change all calls from read() (or recv()) to wolfSSL_read() so

 

result = read(fd, buffer, bytes);

 

becomes

 

result = wolfSSL_read(ssl, buffer, bytes);

 

  1. Change all calls from write (or send) to wolfSSL_write() so

 

result = write(fd, buffer, bytes);

 

becomes

 

result = wolfSSL_write(ssl, buffer, bytes);

 

  1. You can manually call wolfSSL_connect() but that's not even necessary; the first call to wolfSSL_read() or wolfSSL_write() will initiate the wolfSSL_connect() if it hasn't taken place yet.

 

  1. Initialize wolfSSL and the WOLFSSL_CTX. You can use one WOLFSSL_CTX no matter how many WOLFSSL objects you end up creating. Basically you'll just need to load CA certificates to verify the server you are connecting to. Basic initialization looks like:

 

wolfSSL_Init();

 

WOLFSSL_CTX* ctx;

 

if ( (ctx = wolfSSL_CTX_new(wolfTLSv1_client_method())) == NULL) {

    fprintf(stderr, "wolfSSL_CTX_new error.\n");

    exit(EXIT_FAILURE);

}

 

if (wolfSSL_CTX_load_verify_locations(ctx,"./ca-cert.pem",0) !=                                                                              

    SSL_SUCCESS) {

    fprintf(stderr, "Error loading ./ca-cert.pem,"

                    " please check the file.\n");

    exit(EXIT_FAILURE);

}

 

 

  1. Create the WOLFSSL object after each TCP connect and associate the file descriptor with the session:

 

/*after connecting to socket fd*/

 

WOLFSSL* ssl;

 

if ( (ssl = wolfSSL_new(ctx)) == NULL) {

    fprintf(stderr, "wolfSSL_new error.\n");

    exit(EXIT_FAILURE);

}

 

wolfSSL_set_fd(ssl, fd);

 

  1. Error checking. Each wolfSSL_read() and wolfSSL_write() call will return the number of bytes written upon success, 0 upon connection closure, and -1 for an error,  just like read() and write(). In the event of an error you can use two calls to get more information about the error:

 

char errorString[80];

int err = wolfSSL_get_error(ssl, 0);

wolfSSL_ERR_error_string(err, errorString);

 

If you are using non-blocking sockets, you can test for errno EAGAIN/EWOULDBLOCK or more correctly you can test the specific error code returned by wolfSSL_get_error() for SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE.

 

  1. Cleanup. After each WOLFSSL object is done being used you can free it up by calling:

 

wolfSSL_free(ssl);

 

When you are completely done using SSL/TLS altogether you can free the WOLFSSL_CTX object by calling:

 

wolfSSL_CTX_free(ctx);

wolfSSL_Cleanup();

 

For an example of a client application using wolfSSL, see the client example located in the <wolfssl_root>/examples/client.c file.

 

3.9 Changing a Server Application to Use wolfSSL

 

This section will explain the basic steps needed to add wolfSSL to a server application using the wolfSSL native API.  For a client explanation, please see section 3.8.  A more complete walk-through, with example code, is located in the SSL Tutorial in Chapter 11.

 

  1. Follow the instructions above for a client, except change the client method call in step 5 to a server one, so

 

wolfSSL_CTX_new(wolfTLSv1ls_client_method())

 

becomes

 

wolfSSL_CTX_new(wolfTLSv1_server_method())

 

or even

 

wolfSSL_CTX_new(wolfSSLv23_server_method())

 

To allow SSLv3 and TLSv1+ clients to connect to the server.

 

  1. Add the server's certificate and key file to the initialization in step 5 above:

 

if (wolfSSL_CTX_use_certificate_file(ctx,"./server-cert.pem",

    SSL_FILETYPE_PEM) != SSL_SUCCESS) {

    fprintf(stderr, "Error loading ./server-cert.pem,"

                    " please check the file.\n");

    exit(EXIT_FAILURE);

}

 

if (wolfSSL_CTX_use_PrivateKey_file(ctx,"./server-key.pem",

    SSL_FILETYPE_PEM) != SSL_SUCCESS) {

    fprintf(stderr, "Error loading ./server-key.pem,"

                    " please check the file.\n");

    exit(EXIT_FAILURE);

}

 

It is possible to load certificates and keys from buffers as well if there is no filesystem available.  In this case, see the wolfSSL_CTX_use_certificate_buffer() and wolfSSL_CTX_use_PrivateKey_buffer() API documentation, linked here, for more information.

 

For an example of a server application using wolfSSL, see the server example located in the <wolfssl_root>/examples/server.c file.