Master The Pico WiFi: Simplest HTTPS Client
Written by Harry Fairhead & Mike James   
Monday, 01 May 2023
Article Index
Master The Pico WiFi: Simplest HTTPS Client
A Simple TLS Client


A very common use of certificates is in TLS, Transport Security Layer. This is used in HTTPS to transport data between client and server, but it is also used in email and other types of server. TLS evolved out of SSL, Secure Sockets Layer which is still used to refer to it. SSL was designed to be used to convert a standard non-encrypted socket-based connection to an encrypted socket-based connection with minimal change to the program. As the Pico, without the help of Free RTOS, doesn’t make use of lwIP’s socket API you might think that SSL wasn’t relevant, but TLS/SSL can convert a callback-based program into an encrypted connection with very little extra work, as long as you have used the ALTCP introduced in Chapter 2, which provides the same versatility as sockets.

That is:

  • TLS/SSL is a way to add encryption and authentication to existing protocols.

  • SSL is now obsolete but you will still find that TLS libraries and facilities have SSL in their name even though they support TLS, e.g. the OPENSSL library.

  • TLS is generally added to a socket-based implementation of a protocol and, on the Pico, lwIP doesn’t support sockets unless you also use Free RTOS.

  • As long as you have used ALTCP to implement your program, you can add TLS with very few changes.

There have been a number of revisions of the TLS/SSL protocol over time. The first three versions were SSL 1 to 3 and these are all deprecated. TLS 1.0 was issued in 1999 and deprecated in 2021. TLS 1.1 was also deprecated in 2021. The two supported versions are TLS 1.2, introduced in 2008, and TLS 1.3, introduced in 2018.

At the time of writing TLS 1.2 is supported by 99% of all servers and TLS 1.3 by 54.2%. A server can support multiple versions of TLS and roughly 40% still support TLS 1.0 and 1.1.

All latest web browsers support TLS 1.0, 1.1 and 1.2 by default. TLS 1.3 is thought to be secure in all its possible configurations, but TLS 1.2 has vulnerabilities if you select a weak configuration. Currently the mbedTLS library that the Pico uses supports TLS 1.2.

Every TLS connection starts out unencrypted. The client then requests that the server sets up a TLS connection. Usually this happens if the client attempts to connect using port 443, but it can also use a protocol-specific STARTTLS request to the server; this is often used with email servers.

The next step is that a handshaking procedure starts using public keys. The handshake establishes what encryption and hash methods the client and server support. The server picks a method that they both support. Next the server sends the client its certificate and the client checks it for validity. The client can also provide a certificate to the server for it to check. Finally a shared secret is constructed by the client and passed to the server.

From this point on everything is encrypted using the agreed method and key. The higher-level protocol, HTTPS in this case, submits its data packets to be transferred and they are automatically encrypted on transmission and decrypted on reception. In this way the program can work as if encryption wasn’t being used.

In practice, the server and client often have to have more than one attempt at making the connection work and this can result in empty packets being transmitted and received. HTTPS can be messy.


As we already know, the Pico SDK uses lwIP to implement network functions. As long as you have used the altcp module then it is very easy to change the way that the network functions run at run time. The idea is that you can provide a custom module that maps standard functions like altcp_write to a custom implementation. This is a very general method of adding a feature to an existing TCP program.

To make TLS easy to use, lwIP provides an application module, altcp_tls which maps the standard network functions to TLS functions. To make use of this module all you have to do is include altcp_tls.h and set LWIP_ALTCP_TLS to 1 in the lwipopts.h file. However, the altcp_tls module doesn’t actually do any cryptography. Instead it passes all of the cryptography tasks on to the mbedtls library.

The mbedtls library is a lightweight cryptographic library aimed at hardware with limited memory and processor power. To make everything work you also need to compile mbedtls and allow altcp_tls to make use of it. This sounds easy, but there are a great many options and customizations needed to make it work as the mbedtls library isn’t targeted at any particular hardware.

To customize mbedtls you need to add defines to an additional configuration file, mbedtls_config.h, which is stored in your project folder. The big problem with this configuration file is the huge number of options and the lack of guidance on how to use them. What is worse is that many of the options have to be selected to make anything work at all and options are interlinked and depend on one another. All this makes getting started with mbedtls difficult.

You can include the full mbedtls library in your program using:

target_link_libraries(. . . pico_mbedtls)

i.e. by adding pico_mbedtls to the list of target_link_libraries.



Last Updated ( Tuesday, 02 May 2023 )