Use wolfSSL for TLS connections

The Azure Sphere SDK includes a subset of the wolfSSL library for transport layer security (TLS), which high-level applications can use to create secure TLS connections.

The wolfSSL API reference provides thorough documentation of the wolfSSL API, along with many examples. Azure Sphere supports a subset of the API that ensures binary compatibility.

Requirements for applications that use the wolfSSL library

Applications that use the wolfSSL library must include the necessary header files and build configuration.

The wolfSSL TLS API doesn't require capabilities in the application manifest. However, if the application connects to an internet endpoint, the application manifest must include information about the connection. See Connect to web services for more details on enabling connectivity.

Header files

Applications that use the wolfSSL API must include the ssl.h header file, and may require one or more additional header files, depending on the wolfSSL features in use:

#include <wolfssl/wolfcrypt/ecc.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/random.h>
#include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/ssl.h>

See the wolfSSL documentation to determine which header files your application requires.

Build configuration

To build an application with wolfSSL TLS API support, edit the CMakePresets.json and CMakeLists.txt files to specify the target API set and to link the wolfSSL library, respectively.

  1. Set the TARGET_API_SET in CMakePresets.json to 6 or greater.

    "AZURE_SPHERE_TARGET_API_SET": "6"
    
  2. Add wolfssl to the list of target_link_libraries in CMakeLists.txt to link the wolfSSL library into the project:

    target_link_libraries(${PROJECT_NAME} applibs pthread gcc_s c wolfssl)
    

Supported features

The Azure Sphere SDK supports client-side wolfSSL TLS using a Microsoft provided client certificate or a certificate or your choice. The Azure Sphere SDK supports server-side wolfSSL TLS using only a certificate of your choice. Notable unsupported scenarios include:

  • Only wolfSSL client-side TLS connections are supported with the Microsoft-provided client certificate. Server-side TLS connections cannot use the Microsoft-provided client certificate.

  • An application can either use the built-in wolfSSL TLS support or use and link in another wolfSSL library implementation. However, mixed use of the built-in support with another wolfSSL library is not supported.

Use wolfSSL in Azure Sphere

High-level Azure Sphere applications can use wolfSSL to create and communicate over a TLS connection. Applications typically must use a combination of the techniques to create and communicate over these connections.

Note

For enhanced security, applications should use wolfSSL_CTX_set_verify() to validate the host. See the wolfSSL documentation for more information.

Initialize wolfSSL for client TLS connections

To create a TLS connection with wolfSSL, the application first must initialize the library and the SSL context (CTX), as in the following code snippet:

    // Configure the wolfSSL library

    if (wolfSSL_Init() != WOLFSSL_SUCCESS) {
        Log_Debug("Error initializing wolfSSL library.\n");
        goto cleanupLabel;
    }

    // Configure wolfSSL CTX functionality

    WOLFSSL_METHOD *wolfSslMethod = wolfTLSv1_3_client_method();
    if (wolfSslMethod == NULL) {
        Log_Debug("Unable to allocate TLS v1.3 method.\n");
        goto cleanupLabel;
    }

    WOLFSSL_CTX *wolfSslCtx = wolfSSL_CTX_new(wolfSslMethod);
    if (wolfSslCtx == NULL) {
        Log_Debug("Unable get create SSL context.\n");
        goto cleanupLabel;
    }

Load the certificate

After wolfSSL is initialized, it can load a certificate for use with the TLS connection. You can include the certificate in the application image package, as described in Add CA certificates to the image package.

The following example shows how an app can use Storage_GetAbsolutePathInImagePackage to get the path to a client certificate that is part of the application image package, and then call wolfSSL_CTX_load_verify_locations to load the certificate into wolfSSL. Note that the app must include the storage.h header file to use Storage_GetAbsolutePathInImagePackage.

   #include <applibs/storage.h>
   ...

    // Get the full path to the certificate file used to authenticate the HTTPS server identity.
    // The .pem file is the certificate that is used to verify the
    // server identity.

    certificatePath = Storage_GetAbsolutePathInImagePackage("certs/YourDesiredCert.pem");
    if (certificatePath == NULL) {
        Log_Debug("The certificate path could not be resolved: errno=%d (%s)\n", errno,
                  strerror(errno));
        goto cleanupLabel;
    }

    // Load the client certificate into wolfSSL
    if (wolfSSL_CTX_load_verify_locations(ctx, certificatePath, NULL) != WOLFSSL_SUCCESS) {
        Log_Debug("Error loading certificate.\n");
        goto cleanupLabel;
    }

Create a client-side connection

After loading the certificate, the app can establish the TLS connection. This step involves creating an SSL object, associating it with a socket descriptor, and then creating the connection, as in this example:

    // Create the SSL object
    if ((ssl = wolfSSL_new(ctx)) == NULL) {
        Log_Debug("Error creating final SSL object.\n");
        goto cleanupLabel;
    }

    // Attach the socket file descriptor to wolfSSL
    if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) {
        Log_Debug("Error attaching socket fd to wolfSSL.\n");
        goto cleanupLabel;
    }

    // Call Connect for incoming connections
    if (wolfSSL_connect(ssl) != WOLFSSL_SUCCESS) {
        Log_Debug("Error establishing TLS connection to host.\n");
        goto cleanupLabel;
    }

Read and write data from the connection

To write and read data from the connection, the application can use wolfSSL_write and wolfSSL_read, respectively, as the following example shows. In this example, the write to the server contains a standard HTTP/1.1 request to retrieve the content of the page. The documentation at HTTP/1.1: Request (w3.org) provides a good overview of this structure. However, note that this document has been superseded and you can find more details on request structure in its replacement RFC 9110: HTTP Semantics (rfc-editor.org).

    sprintf(buffer, "GET / HTTP/1.1\r\nHost: example.com\r\nAccept: */*\r\n\r\n");
    ret = wolfSSL_write(ssl, buffer, (int)strlen(buffer));
    if (ret != strlen(buffer)) {
        Log_Debug("Error writing GET command to server.\n");
        goto cleanupLabel;
    }

    // Read the data back
    ret = wolfSSL_read(ssl, buffer, BUFFER_SIZE);
    if (ret == -1) {
        Log_Debug("Error reading from host.\n");
        goto cleanupLabel;
    }

    Log_Debug("Received %d bytes from host.\n", ret);
    Log_Debug("%s\n", buffer);

Initialize wolfSSL for server-side connections

To create a TLS server with wolfSSL, the application must first initialize the library and the SSL context (CTX), as in the following code snippet:

// Configure wolfSSL CTX functionality
    WOLFSSL_METHOD *wolfSslMethod = wolfTLSv1_3_server_method();
    if (wolfSslMethod) == NULL) {
        Log_Debug("Unable to allocate TLS v1.3 method\n");
        goto cleanupLabel;
    }

    WOLFSSL_CTX *wolfSslCtx = wolfSSL_CTX_new(wolfSslMethod);
    if (wolfSslCtx == NULL) {
        Log_Debug("Unable to create SSL context.\n");
        goto cleanupLabel;
    }

Accept incoming connections using wolfSSL TLS server

Accept incoming connections from a client to the Azure Sphere server.

    // Call Accept for incoming connections
    if (wolfSSL_accept(ssl) != WOLFSSL_SUCCESS) {
        Log_Debug("Error establishing TLS connection to host.\n");
        goto cleanupLabel;
    }

Cleanup

When the application is done using the connection, it should free the related resources.

    free(certificatePath);

    if (ssl) {
        wolfSSL_free(ssl);
    }
    if (ctx) {
        wolfSSL_CTX_free(ctx);
        wolfSSL_Cleanup();
    }

Sample

For a sample of the WolfSSL functionality on the Azure Sphere platform, see WolfSSL_HighLevelApp.