Part 3: Sample Application: Integrating wolfSSL with a RISC-V

Are you interested in FIPS 140-3 RISC-V Certification? Check out our RISC-V Announcement:

wolfSSL Embraces RISC-V; FIPS 140-3 Certifications Now Available

The important thing to know: there are no special requirements for wolfSSL to run on your RISC-V device. There are no external dependencies. We can run a TLS stack in the smallest memory footprint. Although not a RISC-V device, [gojimmypi] was able to get a TLS stack working in less than 24KB on the Arduino Nano 33 IoT device with total 32KB RAM + 256KB Flash. Most targets will of course have considerably more memory resources.

There are examples to help you get started. There are also examples for different specific environments and IDE platforms.

One of the important things to remember, particularly on embedded devices, is that a reasonably accurate clock is needed. Otherwise certificate validation will fail if the device time is not within the begin and end dates for the certificates.

This particular example is extracted from the Espressif wolfssl_client example, but applies to all platforms:

For embedded systems, copy or install wolfSSL as needed for your particular environment.

For command-line systems:

  ./configure LDFLAGS="-L/path/to/wolfssl" CPPFLAGS="-I/path/to/includes"

For using a custom user_settings.h file, for instance with CMake, define WOLFSSL_USER_SETTINGS:

    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_USER_SETTINGS")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWOLFSSL_USER_SETTINGS")

Include a couple of wolfSSL files.

    /* wolfSSL */
    #include 
    #include 

Note that the settings.h file must be included before any other wolfSSL file, in every source file that uses wolfSSL. Never explicitly include the user_settings.h file, as it is preprocessed and included by the settings.h file.

Create and initialize wolfSSL ctx (context object)

    ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); /* SSL 3.0 - TLS 1.3. */
    /*   options:   */
    /* ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());      only TLS 1.2 */
    /* ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());      only TLS 1.3 */

Open a socket:

    sockfd = socket(AF_INET, SOCK_STREAM, 0)

Optionally set a cipher suite:

    ret = wolfSSL_CTX_set_cipher_list(ctx, WOLFSSL_ESP32_CIPHER_SUITE);

Set client certificate:

    ret = wolfSSL_CTX_use_certificate_chain_buffer_format(ctx,
                                     CTX_CLIENT_CERT,
                                     CTX_CLIENT_CERT_SIZE,
                                     CTX_CLIENT_CERT_TYPE);

Load CA Certificate

        ret = wolfSSL_CTX_load_verify_buffer(ctx,
                                     CTX_CA_CERT,
                                     CTX_CA_CERT_SIZE,
                                     CTX_CA_CERT_TYPE);

Load private key:

    ret_i = wolfSSL_CTX_use_PrivateKey_buffer(ctx,
                                     CTX_CLIENT_KEY,
                                     CTX_CLIENT_KEY_SIZE,
                                     CTX_CLIENT_KEY_TYPE);

Create a wolfSSL secure socket layer connection:

    ssl = wolfSSL_new(ctx)

Tell wolfSSL to verify the peer, and no callback:

    wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, 0);

Connect

    ret = connect(sockfd,
                 (struct sockaddr *)&servAddr,
                 sizeof(servAddr))

Once your application is connected, send a message with wolfSSL_write()

        /* Send the message to the server */
        do {
            err = 0; /* reset error */
            ret_i = wolfSSL_write(ssl, buff, len);
            if (ret_i <= 0) {
                err = wolfSSL_get_error(ssl, 0);
            }
        } while (err == WOLFSSL_ERROR_WANT_WRITE ||
                 err == WOLFSSL_ERROR_WANT_READ);

And receive a message with wolfSSL_read()

        do {
            err = 0; /* reset error */
            ret_i = wolfSSL_read(ssl, buff, sizeof(buff));
            if (ret_i <= 0) {
                err = wolfSSL_get_error(ssl, 0);
            }
        } while ((err == WOLFSSL_ERROR_WANT_READ) ||
                 (err == WOLFSSL_ERROR_WANT_WRITE) );

A build command would look something like this:

gcc -o simple_tls_client simple_tls_client.c \
    -I/usr/local/include -L/usr/local/lib -lwolfssl

Have any questions on using wolfSSL in your project? We’d love to help!

Common questions are answered over on our forums.

If you have a project that you don’t want to share publicly, please email us at support@wolfSSL.com.

We want to hear how you want to use wolfSSL. Please contact us at facts@wolfSSL.com, +1 425 245 8247, or open an issue on GitHUb.

Catch up on ‘Part 1: Ready for Integration: wolfSSL and RISC-V‘ and ‘Part 2: Installing and Configuring wolfSSL on RISC-V.’

Download wolfSSL Now