micropython-wolfssl
is a collection of user modules for micropython that enable wolfSSL to be used for TLS and cryptographic operations. It is an API-compatible replacement for the built-in implementations provided by MicroPython's ussl
, ucryptolib
and uhashlib
modules.
The wolfSSL embedded TLS library is a lightweight, portable, C-language-based SSL/TLS library targeted at IoT, embedded, and RTOS environments primarily because of its size, speed, and feature set. It works seamlessly in desktop, enterprise, and cloud environments as well. wolfSSL supports industry standards up to the current TLS 1.3 and DTLS 1.3, is up to 20 times smaller than OpenSSL, offers a simple API, an OpenSSL compatibility layer, OCSP and CRL support, and is backed by the robust wolfCrypt cryptography library. wolfCrypt has obtained two FIPS 140-2 Certificates, and is certified in a wide variety of operating environments. wolfCrypt is also listed on the CMVP Modules in Process List for FIPS 140-3.
wolfSSL is dual licensed under both the GPLv2 as well as standard commercial licensing. More info on licensing here.
micropython-wolfssl
provides three modules: wolfssl
, wolfcryptolib
, and uhashlib
. These modules implement the same API as MicroPython's built-in implementations of of SSL/TLS (ussl
), encryption (ucryptolib
), and hashing (uhashlib
). This means that python code utilizing these modules should not need to be changed (other than the name of the imported modules) when micropython-wolfssl
is used, and all MicroPython documentation for these modules can be followed. The only changes in behavior are different SSL error codes returned on failure. WolfSSL has much more comprehensive error codes than most other SSL libraries, and are detailed in appendix F of the wolfSSL manual.
micropython-wolfssl/
├── micropython.mk <-- makefile fragment parsed by MicroPython
├── moducryptolib_wolfssl.c <-- implementation of ucryptolib
├── moduhashlib_wolfssl.c <-- implemenation of uhashlib
├── modussl_wolfssl.c <-- implementation of ussl
├── ports <-- directory containing port-specific configuration and code
├── README.md
├── tests
└── wolfssl <-- wolfSSL submodule
micropython-wolfssl
supports a subset of the official ports included in MicroPython. The names of the ports are the same, and you must specify the port you are targeting when building MicroPython using the makefile variable WOLFSSL_PORT
(more on this in the steps below). Valid values for WOLFSSL_PORT
are: unix
and stm32
. If left unspecified, the default port is the unix
port. Each port supported by micropython-wolfssl
can be found in its own directory under micropython-wolfssl/ports
. Each port contains a user_settings.h
file, and optionally, a wolfssl_port.c
file.
wolfSSL can be customized for a specific target application or platform using a user_settings.h
file. This module provides a default user_settings.h
file for each port located in the ports
directory. If you wish you further customise wolfSSL, you can create your own user_settings.h
and pass it to the build system through the WOLFSSL_USER_SETTINGS_FILE
variable. This will override the default one located in the ports/$(WOLFSSL_PORT)
directory. The directory containing this file will be added to the compiler include path, so it is recommended you create a new directory holding this file with nothing else in it. Information on the various build options that can tailor wolfSSL to your application can be found in chapter 2 of the wolfSSL manual.
Some ports also contain a wolfssl_port.c
file containing implementations of certain functions required to enable wolfSSL to work on a specific hardware platform. These port files can be found in ports/
directory, where each subdirectory corresponds to the specific MicroPython port. Information on porting wolfSSL to a new platform can be found in Chapter 5: Portability and Appendix H: Porting Guide in the wolfSSL manual.
- Familiarize yourself with the MicroPython documentation for user modules, specifically for how user modules are included in the build
- Create a directory for user modules, if you haven't already (in this example, we use
micropython-modules
as the directory name - Clone this repository in the user module directory, and initialize submodules
cd /path/to/micropython-modules
git clone https://github.com/bigbrett/micropython-wolfssl.git
git submodule update --init --recursive
- OPTIONAL but recommended: In main MicroPython repository, disable support for the
ussl
,ucryptolib
anduhashlib
modules in your port by ensuring the following C macros are defined to 0 at compile time
#define MICROPY_PY_USSL 0
#define MICROPY_PY_UCRYPTOLIB 0
#define MICROPY_PY_UHASHLIB 0
NOTE: See port-specific-macros section below for instructions on the best way to do this for your port.
- Ensure the C macro
MICROPY_TRACKED_ALLOC
is defined to1
for your port at build-time. This is also detailed in the port-specific-macros section below. - Run
make clean
for your port (for some ports you need to include theBOARD
orVARIANT
argument to make) - Build your MicroPython port, providing
make
with two important command line variables: The path to your user module directory in theUSER_C_MODULES
variable, and the target port for wolfSSL in theWOLFSSL_PORT
variable:
make USER_C_MODULES=/path/to/micropython-modules WOLFSSL_PORT=unix
If you want to use a custom user_settings.h
for your port, pass it to make through the WOLFSSL_USER_SETTINGS_FILE
variable:
make USER_C_MODULES=/path/to/micropython-modules WOLFSSL_PORT=unix \
WOLFSSL_USER_SETTINGS_FILE=/path/to/user_settings.h
When using micropython-wolfssl
, most users will want to disable the built-in implementations of TLS, crypto, and hashing in order to reduce code size (including two TLS stacks in MicroPython will result in a very large binary). This requires setting a few important C macros in your port's build configuration to prevent the default implementations from being compiled. These macros are:
#define MICROPY_PY_USSL 0 // turns off built-in ussl module
#define MICROPY_PY_UCRYPTOLIB 0 // turns off built-in ucryptolib module
#define MICROPY_PY_UHASHLIB 0 // turns off built-in uhashlib module
Additionally, the C macro MICROPY_TRACKED_ALLOC
must be defined to 1, which not all ports do by default.
Unfortunately, there is little consistency between the makefiles/cmake files for each each MicroPython port with regards to these macros. As such, each port might define these macros in a different location, might optionally define them based on a different macro, or might not define them at all, relying on a default value instead. Therefore it might take a little bit of hunting through the source code to find out the best way to disable these macros in your port. The following steps show
how to disable these modules for various ports. It is possible these instructions could become out of date if MicroPython makes changes to their build system. If the following steps don't work (if you get errors about multiple definitions for uhashlib
and ucryptolib
fucntions or types) then it is possible the build system has changed and you need to find another way to ensure the MICROPY_PY_USSL
, MICROPY_PY_UCRYPTOLIB
and MICROPY_PY_UHASHLIB
C macros are all defined to zero at build time. grep
will be your friend here...
For the unix port, the three C macros above can be easily disabled by setting the MICROPY_PY_USSL=0
makefile variable in ports/unix/mpconfigport.mk
. This should automatically ensure the MICROPY_PY_USSL
C macro is not set, as well as prevent the MICROPY_PY_UCRYPTOLIB
and MICROPY_PY_UHASHLIB
C macros from later being defined to 1 in port/unix/variants/mpconfigvariant_common.h
. MICROPY_TRACKED_ALLOC
should be set to 1 by default and no further action is needed.
- If your board config makefile (
ports/stm32/board/$(BOARD)/mpconfigboard.mk
) contains the makefile variable "MICROPY_PY_USSL=1
", then change the assignment to set this variable to 0. - If your board config makefile contains the makefile variable "
MICROPY_SSL_MBEDTLS=1
" then change the assignment to set this variable to 0 - Modify
ports/stm32/mpconfigport.h
such that theMICROPY_PY_UCRYPTOLIB
C macro is never defined - Modify
ports/stm32/mpconfigport.h
such that theMICROPY_TRACKED_ALLOC
C macro is EXPLICITLY defined to 1, and not set to the value of another macro
You can now directly import the three modules (wolfssl
, wolfcryptolib
, wolfhashlib
) provided by micropython-wolfssl
using python's import
statement. Because micropython-wolfssl
is API compatible with the default implementations, you can simply alias the micropython-wolfssl
modules to the name of the internal module you were using before and no further modification to your code should be needed. For example, to set up a TLS connection:
# alias wolfssl to ussl on import
import wolfssl as ussl
# existing code is unchanged
ss = ussl.wrap_socket(...)
Features of the micropython-wolfssl
modules can also be configured using the existing configuration macros, so these can be left unchanged in your port's build. Please see the micropython documentation for more details. The existing macros used to configure the modules include:
MICROPY_PY_USSL_FINALISER // includes MicroPython "finalizer" for SSL module
MICROPY_PY_UHASHLIB_SHA256 // includes SHA256 algorithm
MICROPY_PY_UHASHLIB_SHA1 // includes SHA1 algorithm
MICROPY_PY_UHASHLIB_MD5 // includes MD5 algorithm
MICROPY_PY_UCRYPTOLIB_CTR // includes AES counter mode
MICROPY_PY_UCRYPTOLIB_CONSTS // includes AES ECB and CBC mode ROM constants