Welcome

https://travis-ci.org/wolfSSL/wolfssl-py.svg?branch=master

wolfSSL Python, a.k.a. wolfssl is a Python module that encapsulates wolfSSL’s SSL/TLS library.

wolfSSL’s SSL/TLS library is a lightweight, portable, C-language-based 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.

Installation

We provide Python wheels (prebuilt binaries) for OSX 64 bits and Linux 64 bits:

$ pip install wolfssl

Basic Usage

The SSL/TLS protocol works securing an underlying TCP connection, this module adds the secure layer around the Python standard library socket module.

There are three different paths to secure a socket in this module:

  • Using the top level function wolfssl.wrap_socket();
  • Using the method wrap_socket() from a SSLContext instance;
  • Creating an SSLSocket object from the scratch.
Note 1:
It is possible to use the same SSLContext for multiple SSLSockets to save time and resources.
Note 2:
Each path provides its own options for fine-tuning the securint parameters. Check them out in the API documentation.

Using the top level function wolfssl.wrap_socket()

>>> import socket
>>> import wolfssl
>>>
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
>>>
>>> secure_socket = wolfssl.wrap_socket(sock)
>>>
>>> secure_socket.connect(("www.python.org", 443))
>>>
>>> secure_socket.write(b"GET / HTTP/1.1\n\n")
>>>
>>> print(secure_socket.read())
b'HTTP/1.1 500 Domain Not Found\r\nServer: Varnish\r\nRetry-After: 0\r\ncontent-type: text/html\r\nCache-Control: private, no-cache\r\nconnection: keep-alive\r\nContent-Length: 179\r\nAccept-Ranges: bytes\r\nDate: Sun, 05 Feb 2017 21:26:48 GMT\r\nVia: 1.1 varnish\r\nConnection: keep-alive\r\n\r\n\n<html>\n<head>\n<title>Fastly error: unknown domain </title>\n</head>\n<body>\nFastly error: unknown domain: . Please check that this domain has been added to a service.</body></html>'
>>>
>>> secure_socket.close()

Using the method wrap_socket() from a SSLContext instance

>>> import socket
>>> import wolfssl
>>>
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
>>>
>>> context = wolfssl.SSLContext(wolfssl.PROTOCOL_TLSv1_2)
>>>
>>> secure_socket = context.wrap_socket(sock)
>>>
>>> secure_socket.connect(("www.python.org", 443))
>>>
>>> secure_socket.write(b"GET / HTTP/1.1\n\n")
>>>
>>> print(secure_socket.read())
b'HTTP/1.1 500 Domain Not Found\r\nServer: Varnish\r\nRetry-After: 0\r\ncontent-type: text/html\r\nCache-Control: private, no-cache\r\nconnection: keep-alive\r\nContent-Length: 179\r\nAccept-Ranges: bytes\r\nDate: Sun, 05 Feb 2017 21:26:48 GMT\r\nVia: 1.1 varnish\r\nConnection: keep-alive\r\n\r\n\n<html>\n<head>\n<title>Fastly error: unknown domain </title>\n</head>\n<body>\nFastly error: unknown domain: . Please check that this domain has been added to a service.</body></html>'
>>>
>>> secure_socket.close()

Creating an SSLSocket object from the scratch

>>> import socket
>>> import wolfssl
>>>
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
>>>
>>> secure_socket = wolfssl.SSLSocket(sock)
>>>
>>> secure_socket.connect(("www.python.org", 443))
>>>
>>> secure_socket.write(b"GET / HTTP/1.1\n\n")
>>>
>>> print(secure_socket.read())
b'HTTP/1.1 500 Domain Not Found\r\nServer: Varnish\r\nRetry-After: 0\r\ncontent-type: text/html\r\nCache-Control: private, no-cache\r\nconnection: keep-alive\r\nContent-Length: 179\r\nAccept-Ranges: bytes\r\nDate: Sun, 05 Feb 2017 21:26:48 GMT\r\nVia: 1.1 varnish\r\nConnection: keep-alive\r\n\r\n\n<html>\n<head>\n<title>Fastly error: unknown domain </title>\n</head>\n<body>\nFastly error: unknown domain: . Please check that this domain has been added to a service.</body></html>'
>>>
>>> secure_socket.close()

API Documentation

wrap_socket

wolfssl.wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=0, ssl_version=1, ca_certs=None, do_handshake_on_connect=True, suppress_ragged_eofs=True, ciphers=None)

Takes an instance sock of socket.socket, and returns an instance of wolfssl.SSLSocket, wraping the underlying socket in an SSL context.

The sock parameter must be a SOCK_STREAM socket; other socket types are unsupported.

The keyfile and certfile parameters specify optional files whith proper key and the certificates used to identify the local side of the connection.

The parameter server_side is a boolean which identifies whether server-side or client-side behavior is desired from this socket.

The parameter cert_reqs specifies whether a certificate is required from the other side of the connection, and whether it will be validated if provided. It must be one of the three values:

  • CERT_NONE (certificates ignored)
  • CERT_OPTIONAL (not required, but validated if provided)
  • CERT_REQUIRED (required and validated)

If the value of this parameter is not CERT_NONE, then the ca_certs parameter must point to a file of CA certificates.

The ca_certs file contains a set of concatenated “certification authority” certificates, which are used to validate certificates passed from the other end of the connection.

The parameter ssl_version specifies which version of the SSL protocol to use. Typically, the server chooses a particular protocol version, and the client must adapt to the server’s choice. Most of the versions are not interoperable with the other versions. If not specified, the default is PROTOCOL_TLS; it provides the most compatibility with other versions.

Here’s a table showing which versions in a client (down the side) can connect to which versions in a server (along the top):

client server SSLv3 TLS TLSv1 TLSv1.1 TLSv1.2
SSLv3 yes yes no no no
TLS (SSLv23) yes yes yes yes yes
TLSv1 no yes yes no no
TLSv1.1 no yes no yes no
TLSv1.2 no yes no no yes
Note:
Which connections succeed will vary depending on the versions of the ssl providers on both sides of the communication.
Note 2:
For TLS 1.3 connections use PROTOCOL_TLS as there is no dedicated PROTOCOL constant for just TLS 1.3.

The ciphers parameter sets the available ciphers for this SSL object. It should be a string in the wolfSSL cipher list format.

The parameter do_handshake_on_connect specifies whether to do the SSL handshake automatically after doing a socket.connect(), or whether the application program will call it explicitly, by invoking the SSLSocket.do_handshake() method. Calling SSLSocket.do_handshake() explicitly gives the program control over the blocking behavior of the socket I/O involved in the handshake.

The parameter suppress_ragged_eofs is not supported yet.

SSL/TLS Context

class wolfssl.SSLContext(protocol, server_side=False)

An SSLContext holds various SSL-related configuration options and data, such as certificates and possibly a private key.

verify_mode

Whether to try to verify other peers’ certificates and how to behave if verification fails. This attribute must be one of CERT_NONE, CERT_OPTIONAL or CERT_REQUIRED.

wrap_socket(sock, server_side=False, do_handshake_on_connect=True, suppress_ragged_eofs=True)

Wrap an existing Python socket sock and return an SSLSocket object. sock must be a SOCK_STREAM socket; other socket types are unsupported.

The returned SSL socket is tied to the context, its settings and certificates. The parameters server_side, do_handshake_on_connect and suppress_ragged_eofs have the same meaning as in the top-level wrap_socket() function.

set_ciphers(ciphers)

Set the available ciphers for sockets created with this context. It should be a string in the wolfSSL cipher list format. If no cipher can be selected (because compile-time options or other configuration forbids use of all the specified ciphers), an SSLError will be raised.

load_cert_chain(certfile, keyfile=None, password=None)

Load a private key and the corresponding certificate. The certfile string must be the path to a single file in PEM format containing the certificate as well as any number of CA certificates needed to establish the certificate’s authenticity.

The keyfile string, if present, must point to a file containing the private key in.

The password parameter is not supported yet.

load_verify_locations(cafile=None, capath=None, cadata=None)

Load a set of “certification authority” (CA) certificates used to validate other peers’ certificates when verify_mode is other than CERT_NONE. At least one of cafile or capath must be specified.

The cafile string, if present, is the path to a file of concatenated CA certificates in PEM format.

The capath string, if present, is the path to a directory containing several CA certificates in PEM format.

SSL/TLS Socket

class wolfssl.SSLSocket(sock=None, keyfile=None, certfile=None, server_side=False, cert_reqs=0, ssl_version=1, ca_certs=None, do_handshake_on_connect=True, family=<AddressFamily.AF_INET: 2>, sock_type=<SocketKind.SOCK_STREAM: 1>, proto=0, fileno=None, suppress_ragged_eofs=True, ciphers=None, _context=None)

This class implements a subtype of socket.socket that wraps the underlying OS socket in an SSL/TLS connection, providing secure read and write methods over that channel.

context

Returns the context used by this object.

dup() → socket object

Duplicate the socket. Return a new socket object connected to the same system resource. The new socket is non-inheritable.

write(data)

Write DATA to the underlying secure channel. Returns number of bytes of DATA actually transmitted.

send(data[, flags]) → count

Send a data string to the socket. For the optional flags argument, see the Unix manual. Return the number of bytes sent; this may be less than len(data) if the network is busy.

sendall(data[, flags])

Send a data string to the socket. For the optional flags argument, see the Unix manual. This calls send() repeatedly until all data is sent. If an error occurs, it’s impossible to tell how much data has been sent.

sendto(data, [flags, ]address) → count

Like send(data, flags) but allows specifying the destination address. For IP sockets, the address is a pair (hostaddr, port).

sendmsg(buffers[, ancdata[, flags[, address]]]) → count

Send normal and ancillary data to the socket, gathering the non-ancillary data from a series of buffers and concatenating it into a single message. The buffers argument specifies the non-ancillary data as an iterable of bytes-like objects (e.g. bytes objects). The ancdata argument specifies the ancillary data (control messages) as an iterable of zero or more tuples (cmsg_level, cmsg_type, cmsg_data), where cmsg_level and cmsg_type are integers specifying the protocol level and protocol-specific type respectively, and cmsg_data is a bytes-like object holding the associated data. The flags argument defaults to 0 and has the same meaning as for send(). If address is supplied and not None, it sets a destination address for the message. The return value is the number of bytes of non-ancillary data sent.

sendfile(file[, offset[, count]]) → sent

Send a file until EOF is reached by using high-performance os.sendfile() and return the total number of bytes which were sent. file must be a regular file object opened in binary mode. If os.sendfile() is not available (e.g. Windows) or file is not a regular file socket.send() will be used instead. offset tells from where to start reading the file. If specified, count is the total number of bytes to transmit as opposed to sending the file until EOF is reached. File position is updated on return or also in case of error in which case file.tell() can be used to figure out the number of bytes which were sent. The socket must be of SOCK_STREAM type. Non-blocking sockets are not supported.

read(length=1024, buffer=None)

Read up to LENGTH bytes and return them. Return zero-length string on EOF.

recv(buffersize[, flags]) → data

Receive up to buffersize bytes from the socket. For the optional flags argument, see the Unix manual. When no data is available, block until at least one byte is available or until the remote end is closed. When the remote end is closed and all data is read, return the empty string.

recv_into(buffer[, nbytes[, flags]]) → nbytes_read

A version of recv() that stores its data into a buffer rather than creating a new string. Receive up to buffersize bytes from the socket. If buffersize is not specified (or 0), receive up to the size available in the given buffer.

See recv() for documentation about the flags.

recvfrom(buffersize[, flags]) -> (data, address info)

Like recv(buffersize, flags) but also return the sender’s address info.

recvfrom_into(buffer[, nbytes[, flags]]) -> (nbytes, address info)

Like recv_into(buffer[, nbytes[, flags]]) but also return the sender’s address info.

recvmsg(bufsize[, ancbufsize[, flags]]) -> (data, ancdata, msg_flags, address)

Receive normal data (up to bufsize bytes) and ancillary data from the socket. The ancbufsize argument sets the size in bytes of the internal buffer used to receive the ancillary data; it defaults to 0, meaning that no ancillary data will be received. Appropriate buffer sizes for ancillary data can be calculated using CMSG_SPACE() or CMSG_LEN(), and items which do not fit into the buffer might be truncated or discarded. The flags argument defaults to 0 and has the same meaning as for recv().

The return value is a 4-tuple: (data, ancdata, msg_flags, address). The data item is a bytes object holding the non-ancillary data received. The ancdata item is a list of zero or more tuples (cmsg_level, cmsg_type, cmsg_data) representing the ancillary data (control messages) received: cmsg_level and cmsg_type are integers specifying the protocol level and protocol-specific type respectively, and cmsg_data is a bytes object holding the associated data. The msg_flags item is the bitwise OR of various flags indicating conditions on the received message; see your system documentation for details. If the receiving socket is unconnected, address is the address of the sending socket, if available; otherwise, its value is unspecified.

If recvmsg() raises an exception after the system call returns, it will first attempt to close any file descriptors received via the SCM_RIGHTS mechanism.

recvmsg_into(buffers[, ancbufsize[, flags]]) -> (nbytes, ancdata, msg_flags, address)

Receive normal data and ancillary data from the socket, scattering the non-ancillary data into a series of buffers. The buffers argument must be an iterable of objects that export writable buffers (e.g. bytearray objects); these will be filled with successive chunks of the non-ancillary data until it has all been written or there are no more buffers. The ancbufsize argument sets the size in bytes of the internal buffer used to receive the ancillary data; it defaults to 0, meaning that no ancillary data will be received. Appropriate buffer sizes for ancillary data can be calculated using CMSG_SPACE() or CMSG_LEN(), and items which do not fit into the buffer might be truncated or discarded. The flags argument defaults to 0 and has the same meaning as for recv().

The return value is a 4-tuple: (nbytes, ancdata, msg_flags, address). The nbytes item is the total number of bytes of non-ancillary data written into the buffers. The ancdata item is a list of zero or more tuples (cmsg_level, cmsg_type, cmsg_data) representing the ancillary data (control messages) received: cmsg_level and cmsg_type are integers specifying the protocol level and protocol-specific type respectively, and cmsg_data is a bytes object holding the associated data. The msg_flags item is the bitwise OR of various flags indicating conditions on the received message; see your system documentation for details. If the receiving socket is unconnected, address is the address of the sending socket, if available; otherwise, its value is unspecified.

If recvmsg_into() raises an exception after the system call returns, it will first attempt to close any file descriptors received via the SCM_RIGHTS mechanism.

shutdown(flag)

Shut down the reading side of the socket (flag == SHUT_RD), the writing side of the socket (flag == SHUT_WR), or both ends (flag == SHUT_RDWR).

unwrap()

Unwraps the underlying OS socket from the SSL/TLS connection. Returns the wrapped OS socket.

do_handshake(block=False)

Perform a TLS/SSL handshake.

connect(addr)

Connects to remote ADDR, and then wraps the connection in a secure channel.

connect_ex(addr)

Connects to remote ADDR, and then wraps the connection in a secure channel.

accept()

Accepts a new connection from a remote client, and returns a tuple containing that new connection wrapped with a server-side secure channel, and the address of the remote client.

Client and Server Examples

SSL/TLS Client Example

import socket
import wolfssl

CA_DATA = \
"""
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
+OkuE6N36B9K
-----END CERTIFICATE-----
"""

bind_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)

context = wolfssl.SSLContext(wolfssl.PROTOCOL_TLSv1_2)

context.verify_mode = wolfssl.CERT_REQUIRED
context.load_verify_locations(cadata=CA_DATA)

secure_socket = context.wrap_socket(bind_socket)

secure_socket.connect(("www.python.org", 443))

secure_socket.write(b"GET / HTTP/1.1\n\n")

print(secure_socket.read())

secure_socket.close()

SSL/TLS Server Example

import socket
import wolfssl

bind_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)

bind_socket.bind(("", 4433))
bind_socket.listen(5)

context = wolfssl.SSLContext(wolfssl.PROTOCOL_TLSv1_2, server_side=True)

context.load_cert_chain("certs/server-cert.pem", "certs/server-key.pem")

while True:
    try:
        secure_socket = None

        new_socket, from_addr = bind_socket.accept()

        secure_socket = context.wrap_socket(new_socket)

        print("Connection received from", from_addr)

        print("\n", secure_socket.read(), "\n")
        secure_socket.write(b"I hear you fa shizzle!")

    except KeyboardInterrupt:
        print()
        break

    finally:
        if secure_socket:
            secure_socket.close()

bind_socket.close()

Licensing

wolfSSL’s software is available under two distinct licensing models: open source and standard commercial licensing. Please see the relevant section below for information on each type of license.

Open Source

wolfCrypt and wolfSSL software are free software downloads and may be modified to the needs of the user as long as the user adheres to version two of the GPL License. The GPLv2 license can be found on the gnu.org website.

Commercial Licensing

Businesses and enterprises who wish to incorporate wolfSSL products into proprietary appliances or other commercial software products for re-distribution must license commercial versions. Licenses are generally issued for one product and include unlimited royalty-free distribution. Custom licensing terms are also available at licensing@wolfssl.com.