Static constants defining the possible errors encountered.
-
If SSLClient encounters an error, it will generally output logs into the serial monitor. If you need a way of programmatically checking the errors, you can do so with SSLClient::getWriteError(), which will return one of these values.
+
If SSLClient encounters an error, it will generally output logs into the serial monitor. If you need a way of programmatically checking the errors, you can do so with SSLClient::getWriteError(), which will return one of these values.
-
Enumerator
SSL_OK
+
Enumerator
SSL_OK
+
SSL_CLIENT_CONNECT_FAIL
The underlying client failed to connect, probably not an issue with SSL
-
SSL_CLIENT_CONNECT_FAIL
-
The underlying client failed to connect, probably not an issue with SSL
+
SSL_BR_CONNECT_FAIL
BearSSL failed to complete the SSL handshake, check logs for bear ssl error output
-
SSL_BR_CONNECT_FAIL
-
BearSSL failed to complete the SSL handshake, check logs for bear ssl error output
+
SSL_CLIENT_WRTIE_ERROR
The underlying client failed to write a payload, probably not an issue with SSL
-
SSL_CLIENT_WRTIE_ERROR
-
The underlying client failed to write a payload, probably not an issue with SSL
+
SSL_BR_WRITE_ERROR
An internal error occurred with BearSSL, check logs for diagnosis.
-
SSL_BR_WRITE_ERROR
-
An internal error occurred with BearSSL, check logs for diagnosis.
+
SSL_INTERNAL_ERROR
An internal error occurred with SSLClient, and you probably need to submit an issue on Github.
-
SSL_INTERNAL_ERROR
-
An internal error occurred with SSLClient, and you probably need to submit an issue on Github.
-
-
SSL_OUT_OF_MEMORY
-
SSLClient detected that there was not enough memory (>8000 bytes) to continue.
+
SSL_OUT_OF_MEMORY
SSLClient detected that there was not enough memory (>8000 bytes) to continue.
Initialize SSLClient with all of the prerequisites needed.
+
Initialize SSLClient with all of the prerequisites needed.
Precondition
You will need to generate an array of trust_anchors (root certificates) based off of the domains you want to make SSL connections to. Check out the TrustAnchors.md file for more info.
The analog_pin should be set to input.
Parameters
-
client
The base network device to create an SSL socket on. This object will be copied and the copy will be stored in SSLClient.
+
client
The base network device to create an SSL socket on. This object will be copied and the copy will be stored in SSLClient.
trust_anchors
Trust anchors used in the verification of the SSL server certificate. Check out TrustAnchors.md for more info.
trust_anchors_num
The number of objects in the trust_anchors array.
analog_pin
An analog pin to pull random bytes from, used in seeding the RNG.
@@ -369,7 +336,9 @@ The analog_pin should be set to input.
@@ -391,14 +360,73 @@ The analog_pin should be set to input.
Returns the number of bytes available to read from the data that has been received and decrypted.
-
This function updates the state of the SSL engine (including writing any data, see SSLClient::write) and as a result should be called periodically when expecting data. Additionally, since if there are no bytes and if SSLClient::connected is false this function returns zero (this same behavior is found in EthernetClient), it is prudent to ensure in your own code that the preconditions are met before checking this function to prevent an ambiguous result.
+
This function updates the state of the SSL engine (including writing any data, see SSLClient::write) and as a result should be called periodically when expecting data. Additionally, since if there are no bytes and if SSLClient::connected is false this function returns zero (this same behavior is found in EthernetClient), it is prudent to ensure in your own code that the preconditions are met before checking this function to prevent an ambiguous result.
The implementation for this function can be found in SSLClientImpl::available
Connect over SSL to a host specified by a hostname.
+
This function initializes the socket by calling m_client::connect(const char*, uint16_t) with the parameters supplied, then once the socket is open, uses BearSSL to complete a SSL handshake. This function runs until the SSL handshake succeeds or fails.
+
SSL requires the client to generate some random bits (to be later combined with some random bits from the server), so SSLClient uses the least significant bits from the analog pin supplied in the constructor. The random bits are generated from 16 consecutive analogReads, and given to BearSSL before the handshake starts.
+
This function will usually take around 4-10 seconds. If possible, this function also attempts to resume the SSL session if one is present matching the hostname string, which will reduce connection time to 100-500ms. To read more about this functionality, check out Session Caching in the README.
+
The implementation for this function can be found in SSLClientImpl::connect_impl(const char*, uint16_t)
+
Precondition
The underlying client object (passed in through the constructor) is in a non- error state, and must be able to access the IP.
+
+SSLClient can only have one connection at a time, so the client object must not already be connected.
+
+There must be sufficient memory available on the device to verify the certificate (if the free memory drops below 8000 bytes during certain points in the connection, SSLClient will fail).
+
+There must be a trust anchor given to the constructor that corresponds to the certificate provided by the IP address being connected to. For more information check out TrustAnchors.md .
+
Parameters
+
+
host
The hostname as a null-terminated c-string ("www.google.com")
+
port
The port to connect to on the host (443 for HTTPS)
@@ -433,13 +461,13 @@ The analog_pin should be set to input.
Connect over SSL to a host specified by an IP address.
SSLClient::connect(host, port) should be preferred over this function, as verifying the domain name is a step in ensuring the certificate is legitimate, which is important to the security of the device. Additionally, SSL sessions cannot be resumed when using this function, which can drastically increase initial connect time.
This function initializes the socket by calling m_client::connect(IPAddress, uint16_t) with the parameters supplied, then once the socket is open, uses BearSSL to to complete a SSL handshake. Due to the design of the SSL standard, this function will probably take an extended period (1-4sec) to negotiate the handshake and finish the connection. This function runs until the SSL handshake succeeds or fails.
-
SSL requires the client to generate some random bits (to be later combined with some random bits from the server), so SSLClient uses the least significant bits from the analog pin supplied in the constructor. The random bits are generated from 16 consecutive analogReads, and given to BearSSL before the handshake starts.
+
SSL requires the client to generate some random bits (to be later combined with some random bits from the server), so SSLClient uses the least significant bits from the analog pin supplied in the constructor. The random bits are generated from 16 consecutive analogReads, and given to BearSSL before the handshake starts.
The implementation for this function can be found in SSLClientImpl::connect_impl(IPAddress, uint16_t).
Precondition
The underlying client object (passed in through the constructor) is in a non- error state, and must be able to access the IP.
-SSLClient can only have one connection at a time, so the client object must not already be connected.
+SSLClient can only have one connection at a time, so the client object must not already be connected.
-There must be sufficient memory available on the device to verify the certificate (if the free memory drops below 8000 bytes during certain points in the connection, SSLClient will fail).
+There must be sufficient memory available on the device to verify the certificate (if the free memory drops below 8000 bytes during certain points in the connection, SSLClient will fail).
There must be a trust anchor given to the constructor that corresponds to the certificate provided by the IP address being connected to. For more information check out TrustAnchors.md .
Parameters
@@ -453,62 +481,9 @@ There must be a trust anchor given to the constructor that corresponds to the ce
-
-
Connect over SSL to a host specified by a hostname.
-
This function initializes the socket by calling m_client::connect(const char*, uint16_t) with the parameters supplied, then once the socket is open, uses BearSSL to complete a SSL handshake. This function runs until the SSL handshake succeeds or fails.
-
SSL requires the client to generate some random bits (to be later combined with some random bits from the server), so SSLClient uses the least significant bits from the analog pin supplied in the constructor. The random bits are generated from 16 consecutive analogReads, and given to BearSSL before the handshake starts.
-
This function will usually take around 4-10 seconds. If possible, this function also attempts to resume the SSL session if one is present matching the hostname string, which will reduce connection time to 100-500ms. To read more about this functionality, check out Session Caching in the README.
-
The implementation for this function can be found in SSLClientImpl::connect_impl(const char*, uint16_t)
-
Precondition
The underlying client object (passed in through the constructor) is in a non- error state, and must be able to access the IP.
-
-SSLClient can only have one connection at a time, so the client object must not already be connected.
-
-There must be sufficient memory available on the device to verify the certificate (if the free memory drops below 8000 bytes during certain points in the connection, SSLClient will fail).
-
-There must be a trust anchor given to the constructor that corresponds to the certificate provided by the IP address being connected to. For more information check out TrustAnchors.md .
-
Parameters
-
-
host
The hostname as a null-terminated c-string ("www.google.com")
-
port
The port to connect to on the host (443 for HTTPS)
-
-
-
-
Returns
1 of success, 0 if failure
-
-
-
-
@@ -530,13 +505,15 @@ There must be a trust anchor given to the constructor that corresponds to the ce
Check if the device is connected.
-
Use this function to determine if SSLClient is still connected and a SSL connection is active. It should be noted that this function should be called before SSLClient::available– both functions send and receive data with the SSLClient::m_client device, however SSLClient::available has some delays built in to protect SSLClient::m_client from being polled too frequently, and SSLClient::connected contains logic to ensure that if the socket is dropped SSLClient will react accordingly.
+
Use this function to determine if SSLClient is still connected and a SSL connection is active. It should be noted that this function should be called before SSLClient::available– both functions send and receive data with the SSLClient::m_client device, however SSLClient::available has some delays built in to protect SSLClient::m_client from being polled too frequently, and SSLClient::connected contains logic to ensure that if the socket is dropped SSLClient will react accordingly.
The implementation for this function can be found in SSLClientImpl::connected_impl.
@@ -557,12 +534,14 @@ There must be a trust anchor given to the constructor that corresponds to the ce
-
Force writing the buffered bytes from SSLClient::write to the network.
-
This function is blocking until all bytes from the buffer are written. For an explanation of how writing with SSLClient works, please see SSLClient::write. The implementation for this function can be found in SSLClientImpl::flush.
+
Force writing the buffered bytes from SSLClient::write to the network.
+
This function is blocking until all bytes from the buffer are written. For an explanation of how writing with SSLClient works, please see SSLClient::write. The implementation for this function can be found in SSLClientImpl::flush.
@@ -753,10 +772,10 @@ There must be a trust anchor given to the constructor that corresponds to the ce
Read size bytes from the SSL client buffer, copying them into *buf, and return the number of bytes read.
-
This function checks if bytes are ready to be read by calling SSLClient::available, and if so copies size number of bytes from the IO buffer into the buf pointer. Data read using this function will not include any SSL or socket commands, as the Client and BearSSL will capture those and process them separately.
-
If you find that you are having a lot of timeout errors, SSLClient may be experiencing a buffer overflow. Checkout README.md for more information.
+
This function checks if bytes are ready to be read by calling SSLClient::available, and if so copies size number of bytes from the IO buffer into the buf pointer. Data read using this function will not include any SSL or socket commands, as the Client and BearSSL will capture those and process them separately.
+
If you find that you are having a lot of timeout errors, SSLClient may be experiencing a buffer overflow. Checkout README.md for more information.
The implementation for this function can be found in SSLClientImpl::read_impl(uint8_t*, size_t)
@@ -967,9 +972,9 @@ There must be a trust anchor given to the constructor that corresponds to the ce
Write some bytes to the SSL connection.
-
Assuming all preconditions are met, this function writes data to the BearSSL IO buffer, BUT does not initially send the data. Instead, you must call SSLClient::available or SSLClient::flush, which will detect that the buffer is ready for writing, and will write the data to the network. Alternatively, if this function is requested to write a larger amount of data than SSLClientImpl::m_iobuf can handle, data will be written to the network in pages the size of SSLClientImpl::m_iobuf until all the data in buf is sent–attempting to keep all writes to the network grouped together. For information on why this is the case check out README.md .
+
Assuming all preconditions are met, this function writes data to the BearSSL IO buffer, BUT does not initially send the data. Instead, you must call SSLClient::available or SSLClient::flush, which will detect that the buffer is ready for writing, and will write the data to the network. Alternatively, if this function is requested to write a larger amount of data than SSLClientImpl::m_iobuf can handle, data will be written to the network in pages the size of SSLClientImpl::m_iobuf until all the data in buf is sent–attempting to keep all writes to the network grouped together. For information on why this is the case check out README.md .
The implementation for this function can be found in SSLClientImpl::write_impl(const uint8_t*, size_t)
-
Precondition
The socket and SSL layer must be connected, meaning SSLClient::connected must be true.
+
Precondition
The socket and SSL layer must be connected, meaning SSLClient::connected must be true.
BearSSL must not be waiting for the recipt of user data (if it is, there is probably an error with how the protocol in implemented in your code).
Parameters
@@ -983,7 +988,9 @@ BearSSL must not be waiting for the recipt of user data (if it is, there is prob
This file contains a simple utility class to store parameters about an SSL Session for reuse later. TLS mutual authentication is a process in which both the server and client perform cryptographic operations to verify the authenticity of eachother, for more information check out this article: https://medium.com/sitewards/the-magic-of-tls-x509-and-mutual-authentication-explained-b2162dec4401 . If this struct is provided to SSLClient::SSLClient via SSLClient::setMutualAuthParams, SSLClient will automatically send a client certificate if one is requested by the server. This will happen for all SSLClient connections, and may cause issues for websites that do not need mutual authentication—as a result, please only turn on mutual authentication if you are sure it is neccesary.
-
SSLClientParameters supports both ECC and RSA client certificates. I recommend using ECC certificates if possible, as SSLClientParameters will make a copy of both the certificate and the private key in memory, and ECC keys tend to be smaller than RSA ones.
+
This file contains a simple utility class to store parameters about an SSL Session for reuse later.
+
TLS mutual authentication is a process in which both the server and client perform cryptographic operations to verify the authenticity of eachother, for more information check out this article: https://medium.com/sitewards/the-magic-of-tls-x509-and-mutual-authentication-explained-b2162dec4401 . If this struct is provided to SSLClient::SSLClient via SSLClient::setMutualAuthParams, SSLClient will automatically send a client certificate if one is requested by the server. This will happen for all SSLClient connections, and may cause issues for websites that do not need mutual authentication—as a result, please only turn on mutual authentication if you are sure it is neccesary.
+
SSLClientParameters supports both ECC and RSA client certificates. I recommend using ECC certificates if possible, as SSLClientParameters will make a copy of both the certificate and the private key in memory, and ECC keys tend to be smaller than RSA ones.
Create mutual authentication parameters from a DER certificate and private key.
-
Use this function to create a mutual tls context from a DER client certificate and DER private key. This function will copy the certificate and private key, extract the needed information from the private key, and store both that information and the copied cert into a SSLClientParameters object. Given the key parsed correctly, you can then use SSLClient::setMutualAuthParams at the begining of your sketch to enable mTLS with SSLClient. This function supports both ECC and RSA certificate/private keys (use EC keys wherever possible, as they are signifigantly smaller and faster), however SSLClient only supports the p256, p384, and p512 curves for ECC.
-
Because SSLClientParameters creates a copy of both the certificate and key, you do not need to ensure that the data pointed to by cert_der or key_der is accessible after this function (i.e. you can free them afterwards).
-
Please note that if the private key is incorrect, this function will not report an error, and instead SSLClient will fall back to regular TLS when making a connection.
+
Use this function to create a mutual tls context from a DER client certificate and DER private key. This function will copy the certificate and private key, extract the needed information from the private key, and store both that information and the copied cert into a SSLClientParameters object. Given the key parsed correctly, you can then use SSLClient::setMutualAuthParams at the begining of your sketch to enable mTLS with SSLClient. This function supports both ECC and RSA certificate/private keys (use EC keys wherever possible, as they are signifigantly smaller and faster), however SSLClient only supports the p256, p384, and p512 curves for ECC.
+
Because SSLClientParameters creates a copy of both the certificate and key, you do not need to ensure that the data pointed to by cert_der or key_der is accessible after this function (i.e. you can free them afterwards).
+
Please note that if the private key is incorrect, this function will not report an error, and instead SSLClient will fall back to regular TLS when making a connection.
Create mutual authentication parameters from a PEM certificate and private key.
-
Use this function to create a mutual tls context from a PEM client certificate and PEM private key. This function will convert the PEM certificates into DER format (creating a copy in the process), extract the needed information from the private key, and store that information into a SSLClientParameters object. Given the certifiate and key parsed correctly, you can then use SSLClient::setMutualAuthParams at the begining of your sketch to enable mTLS with SSLClient. This function supports both ECC and RSA certificate/private keys (use EC keys wherever possible, as they are signifigantly smaller and faster), however SSLClient only supports the p256, p384, and p512 curves for ECC.
-
Because SSLClientParameters creates a copy of both the certificate and key, you do not need to ensure that the data pointed to by cert_pem or key_pem is accessible after this function (i.e. you can free them afterwards).
-
Please note that if the certificate or private key are incorrect, this function will not report an error, and instead SSLClient will fall back to regular TLS when making a connection.
+
Use this function to create a mutual tls context from a PEM client certificate and PEM private key. This function will convert the PEM certificates into DER format (creating a copy in the process), extract the needed information from the private key, and store that information into a SSLClientParameters object. Given the certifiate and key parsed correctly, you can then use SSLClient::setMutualAuthParams at the begining of your sketch to enable mTLS with SSLClient. This function supports both ECC and RSA certificate/private keys (use EC keys wherever possible, as they are signifigantly smaller and faster), however SSLClient only supports the p256, p384, and p512 curves for ECC.
+
Because SSLClientParameters creates a copy of both the certificate and key, you do not need to ensure that the data pointed to by cert_pem or key_pem is accessible after this function (i.e. you can free them afterwards).
+
Please note that if the certificate or private key are incorrect, this function will not report an error, and instead SSLClient will fall back to regular TLS when making a connection.
Parameters
cert_pem
A PEM formatted certificate, including the "BEGIN" and "END" header/footers. Can be ECC or RSA. cert_pem supports both LF and CRLF for endlines, but all other constraints on a valid PEM file apply.
This file contains a simple utility class to store parameters about an SSL Session for reuse later. This class was created to extend the values stored in br_ssl_session_parameters, which allow BearSSL to resume an SSL session. When testing BearSSL's session resumption feature, it was observed that BearSSL can only resume a session that was was started with the same server. This becomes an issue when using repeated requests to a domain name which can resolve to multiple IP addresses ("api.github.com"), as the device will switch between two or three servers. Since BearSSL only stores one session at a time, this results in session resumption being few and far between.
-
To remedy this problem, an SSLSession stores the IPAddress and hostname, along with the parameters in br_ssl_session_parameters struct. Using this data, SSLClient is able to remember which IPAddress is associated with which session, allowing it to reconnect to the last IPAddress, as opposed to any associated with the domain.
+
This file contains a simple utility class to store parameters about an SSL Session for reuse later.
+
This class was created to extend the values stored in br_ssl_session_parameters, which allow BearSSL to resume an SSL session. When testing BearSSL's session resumption feature, it was observed that BearSSL can only resume a session that was was started with the same server. This becomes an issue when using repeated requests to a domain name which can resolve to multiple IP addresses ("api.github.com"), as the device will switch between two or three servers. Since BearSSL only stores one session at a time, this results in session resumption being few and far between.
+
To remedy this problem, an SSLSession stores the IPAddress and hostname, along with the parameters in br_ssl_session_parameters struct. Using this data, SSLClient is able to remember which IPAddress is associated with which session, allowing it to reconnect to the last IPAddress, as opposed to any associated with the domain.
SSLClient adds TLS 1.2 functionality to any network library implementing the Arduino Client interface, including the Arduino EthernetClient and WiFiClient classes. SSLClient was created to integrate TLS seamlessly with the Arduino infrastructure using BearSSL as an underlying TLS engine. Unlike ArduinoBearSSL, SSLClient is completly self-contained, and does not require any additional hardware (other than a network connection).
-
SSLClient officially supports SAMD21, SAM3X, ESP32, TIVA C, STM32, and Teensy 4.x; but it should work on any board with at least 110kb flash and 7kb RAM. SSClient does not currently support ESP8266 (see this issue) or AVR due to memory constraints on both platforms.
+
+
SSLClient adds TLS 1.2 functionality to any network library implementing the Arduino Client interface, including the Arduino EthernetClient and WiFiClient classes. SSLClient was created to integrate TLS seamlessly with the Arduino infrastructure using BearSSL as an underlying TLS engine. Unlike ArduinoBearSSL, SSLClient is completly self-contained, and does not require any additional hardware (other than a network connection).
+
SSLClient officially supports SAMD21, SAM3X, ESP32, TIVA C, STM32, and Teensy 4.x; but it should work on any board with at least 110kb flash and 7kb RAM. SSClient does not currently support ESP8266 (see this issue) or AVR due to memory constraints on both platforms.
Using SSLClient is similar to using any other Arduino-based Client class, as this library was developed around compatibility with EthernetClient. There are a few extra things, however, that you will need to get started:
+
Overview
+
Using SSLClient is similar to using any other Arduino-based Client class, as this library was developed around compatibility with EthernetClient. There are a few extra things, however, that you will need to get started:
Board and Network Peripheral - Your board should have a lot of resources (>110kb flash and >7kb RAM), and your network peripheral should have a large internal buffer (>7kb). This library was tested with the Adafruit Feather M0 (256K flash, 32K RAM) and the Adafruit Ethernet Featherwing (16kb Buffer), and we still had to modify the Arduino Ethernet library to support larger internal buffers per socket (see the Implementation Gotchas).
Trust Anchors - You will need a header containing array of trust anchors (example), which are used to verify the SSL connection later on. This file must generated for every project. Check out TrustAnchors.md on how to generate this file for your project, and for more information about what a trust anchor is.
Network Peripheral Driver Implementing Client - Examples include EthernetClient, WiFiClient, and so on—SSLClient will run on top of any network driver exposing the Client interface.
Analog Pin - Used for generating random data at the start of the connection (see the Implementation Gotchas).
-
Once all those are ready, you can create an SSLClient object like this:
1 {C++}
2 BaseClientType baseClientInstance;
3 SSLClient client(baseClientInstance, TAs, (size_t)TAs_NUM, AnalogPin);
Where:
+
Once all those are ready, you can create an SSLClient object like this:
{C++}
+
BaseClientType baseClientInstance;
+
SSLClient client(baseClientInstance, TAs, (size_t)TAs_NUM, AnalogPin);
+
Where:
BaseClientType - The type of baseClientInstance
-
BaseClientInstance - An instance of the class you are using for SSLClient (the class associated with the network interface, from step 3). It is important that this instance be stored outside the SSLClient declaration (for instance, SSLClient(BaseClientType() ...) wouldn't work).
+
BaseClientInstance - An instance of the class you are using for SSLClient (the class associated with the network interface, from step 3). It is important that this instance be stored outside the SSLClient declaration (for instance, SSLClient(BaseClientType() ...) wouldn't work).
TAs - The name of the trust anchor array created in step 2. If you generated a header using the tutorial this will probably be TAs.
TAs_NUM - The number of trust anchors in TAs. If you generated a header using the tutorial this will probably be TAs_NUM.
AnalogPin - The analog pin to pull random data from (step 4).
-
For example, if I am using EthernetClient, a generated array of 2 trust anchors, and the analog pin A7, I would declare an SSLClient instance using:
1 {C++}
2 EthernetClient baseClient;
3 SSLClient client(baseClient, TAs, 2, A7);
Given this client, simply use SSLClient as you would the base client class:
1 {C++}
2 // connect to ardiuino.cc over ssl (port 443 for websites)
Note: client.connect("www.arduino.cc", 443) can take 5-15 seconds to finish on some low-power devices. This an unavoidable consequence of the SSL protocol, and is detailed more in Implementation Gotchas.
-
+
For example, if I am using EthernetClient, a generated array of 2 trust anchors, and the analog pin A7, I would declare an SSLClient instance using:
SSLClient also allows for changing the debugging level by adding an additional parameter to the constructor:
1 {C++}
2 EthernetClient baseClient;
3 SSLClient client(baseClient, TAs, (size_t)2, A7, 1, SSLClient::SSL_INFO);
Logging is always outputted through the Arduino Serial interface, so you'll need to setup Serial before you can view the SSL logs. Log levels are enumerated in ::DebugLevel. The log level is set to SSL_WARN by default.
-
Errors
-
When SSLClient encounters an error, it will attempt to terminate the SSL session gracefully if possible, and then close the socket. Simple error information can be found from SSLClient::getWriteError, which will return a value from the ::Error enum. For more detailed diagnostics, you can look at the serial logs, which will be displayed if the log level is at SSL_ERROR or lower.
-
Write Buffering
-
As you may have noticed in the documentation for SSLClient::write, calling this function does not actually write to the network. Instead, you must call SSLClient::available or SSLClient::flush, which will detect that the buffer is ready and write to the network (see SSLClient::write for details).
-
This was implemented as a buffered function because examples in Arduino libraries will often write to the network like so:
1 {C++}
2 EthernetClient client;
3 // ...
4 // connect to ardiuino.cc over ssl (port 443 for websites)
Notice that every single write() call immediately writes to the network, which is fine with most network clients. With SSL, however, if we are encrypting and writing to the network every write() call, this will result in a lot of small encryption tasks. Encryption takes a lot of time and code, so to reduce the overhead of an SSL connection, SSLClient::write implicitly buffers until the developer states that they are waiting for data to be received with SSLClient::available. A simple example can be found below:
-
1 {C++}
2 EthernetClient baseClient;
3 SSLClient client(baseClient, TAs, (size_t)2, A7);
4 // ...
5 // connect to ardiuino.cc over ssl (port 443 for websites)
12 // write the bytes to the network, then wait for response
13 while (!client.available()) { /* ... */ }
14 // ...
If you would like to trigger a network write manually without using the SSLClient::available, you can also call SSLClient::flush, which will write all data and return when finished.
-
Session Caching
+
Given this client, simply use SSLClient as you would the base client class:
{C++}
+
// connect to ardiuino.cc over ssl (port 443 for websites)
Note: client.connect("www.arduino.cc", 443) can take 5-15 seconds to finish on some low-power devices. This an unavoidable consequence of the SSL protocol, and is detailed more in Implementation Gotchas.
SSLClient also allows for changing the debugging level by adding an additional parameter to the constructor:
{C++}
+
EthernetClient baseClient;
+
SSLClient client(baseClient, TAs, (size_t)2, A7, 1, SSLClient::SSL_INFO);
+
Logging is always outputted through the Arduino Serial interface, so you'll need to setup Serial before you can view the SSL logs. Log levels are enumerated in ::DebugLevel. The log level is set to SSL_WARN by default.
+
Errors
+
When SSLClient encounters an error, it will attempt to terminate the SSL session gracefully if possible, and then close the socket. Simple error information can be found from SSLClient::getWriteError, which will return a value from the ::Error enum. For more detailed diagnostics, you can look at the serial logs, which will be displayed if the log level is at SSL_ERROR or lower.
+
Write Buffering
+
As you may have noticed in the documentation for SSLClient::write, calling this function does not actually write to the network. Instead, you must call SSLClient::available or SSLClient::flush, which will detect that the buffer is ready and write to the network (see SSLClient::write for details).
+
This was implemented as a buffered function because examples in Arduino libraries will often write to the network like so:
{C++}
+
EthernetClient client;
+
// ...
+
// connect to ardiuino.cc over ssl (port 443 for websites)
+
client.connect("www.arduino.cc", 443);
+
// ...
+
// write an http request to the network
+
client.write("GET /asciilogo.txt HTTP/1.1\r\n");
+
client.write("Host: arduino.cc\r\n");
+
client.write("Connection: close\r\n");
+
// wait for response
+
while (!client.available()) { /* ... */ }
+
// ...
+
Notice that every single write() call immediately writes to the network, which is fine with most network clients. With SSL, however, if we are encrypting and writing to the network every write() call, this will result in a lot of small encryption tasks. Encryption takes a lot of time and code, so to reduce the overhead of an SSL connection, SSLClient::write implicitly buffers until the developer states that they are waiting for data to be received with SSLClient::available. A simple example can be found below:
+
{C++}
+
EthernetClient baseClient;
+
SSLClient client(baseClient, TAs, (size_t)2, A7);
+
// ...
+
// connect to ardiuino.cc over ssl (port 443 for websites)
+
client.connect("www.arduino.cc", 443);
+
// ...
+
// add http request to the buffer
+
client.write("GET /asciilogo.txt HTTP/1.1\r\n");
+
client.write("Host: arduino.cc\r\n");
+
client.write("Connection: close\r\n");
+
// write the bytes to the network, then wait for response
+
while (!client.available()) { /* ... */ }
+
// ...
+
If you would like to trigger a network write manually without using the SSLClient::available, you can also call SSLClient::flush, which will write all data and return when finished.
+
Session Caching
As detailed in the resources section, SSL handshakes take an extended period (1-4sec) to negotiate. To remedy this problem, BearSSL is able to keep a SSL session cache of the clients it has connected to. If BearSSL successfully resumes an SSL session, it can reduce connection time to 100-500ms.
In order to use SSL session resumption:
The website you are connecting to must support it. Support is widespread, but you can verify easily using the SSLLabs tool.
-
You must reuse the same SSLClient object (SSL Sessions are stored in the object itself).
+
You must reuse the same SSLClient object (SSL Sessions are stored in the object itself).
You must reconnect to the exact same server.
-
SSLClient automatically stores an IP address and hostname in each session, ensuring that if you call connect("www.google.com")SSLClient will use the SSL session with that hostname. However, because some websites have multiple servers on a single IP address (github.com being an example), you may find that even if you are connecting to the same host the connection does not resume. This is a flaw in the SSL session protocol — though it has been resolved in TLS 1.3, the lack of widespread adoption of the new protocol prevents it from being used here. SSL sessions can also expire based on server criteria, which will result in a standard 4-10 second connection.
+
SSLClient automatically stores an IP address and hostname in each session, ensuring that if you call connect("www.google.com")SSLClient will use the SSL session with that hostname. However, because some websites have multiple servers on a single IP address (github.com being an example), you may find that even if you are connecting to the same host the connection does not resume. This is a flaw in the SSL session protocol — though it has been resolved in TLS 1.3, the lack of widespread adoption of the new protocol prevents it from being used here. SSL sessions can also expire based on server criteria, which will result in a standard 4-10 second connection.
You can test whether or not a website can resume SSL Sessions using the Session Example included with this library. Because of all the confounding factors of SSL Sessions, it is generally prudent while programming to assume the session will always fail to resume.
-
SSL sessions take a lot of memory to store, so by default SSLClient will only store one at a time. You can change this behavior by adding the following to your SSLClient declaration:
1 {C++}
2 EthernetClient baseClient;
3 SSLClient client(baseClient, TAs, (size_t)2, A7, SomeNumber);
Where SomeNumber is the number of sessions you would like to store. For example this declaration can store 3 sessions:
1 {C++}
2 EthernetClient baseClient;
3 SSLClient client(baseClient, TAs, (size_t)2, A7, 3);
Sessions are managed internally using the SSLSession::getSession function. This function will cycle through sessions in a rotating order, allowing the session cache to continually overwrite old sessions. In general, it is a good idea to use a SessionCache size equal to the number of domains you plan on connecting to.
+
SSL sessions take a lot of memory to store, so by default SSLClient will only store one at a time. You can change this behavior by adding the following to your SSLClient declaration:
{C++}
+
EthernetClient baseClient;
+
SSLClient client(baseClient, TAs, (size_t)2, A7, SomeNumber);
+
Where SomeNumber is the number of sessions you would like to store. For example this declaration can store 3 sessions:
{C++}
+
EthernetClient baseClient;
+
SSLClient client(baseClient, TAs, (size_t)2, A7, 3);
+
Sessions are managed internally using the SSLSession::getSession function. This function will cycle through sessions in a rotating order, allowing the session cache to continually overwrite old sessions. In general, it is a good idea to use a SessionCache size equal to the number of domains you plan on connecting to.
If you need to clear a session, you can do so using the SSLSession::removeSession function.
-
mTLS
-
As of v1.6.0, SSLClient supports mutual TLS authentication. mTLS is a varient of TLS that verifys both the server and device identities before a connection, and is commonly used in IoT protocols as a secure layer (MQTT over TLS, HTTPS over TLS, etc.).
-
To use mTLS with SSLClient you will need to a client certificate and client private key associated with the server you are attempting to connect to. Depending on your use case, you will either generate these yourself (ex. Mosquito MQTT setup), or have them generated for you (ex. AWS IoT Certificate Generation). Given this cryptographic information, you can modify the standard SSLClient connection sketch to enable mTLS authentication:
1 {C++}
2 ...
3 /* Somewhere above setup() */
4
5 // The client certificate, can be PEM or DER format
6 // DER format will be an array of raw bytes, and PEM format will be a string
The client certificate must be formatted correctly (according to BearSSL's specification) in order for mTLS to work. If the certificate is improperly formatted, SSLClient will attempt to make a regular TLS connection instead of an mTLS one, and fail to connect as a result. Because of this, if you are seeing errors similar to "peer did not send certificate chain" on your server, check that your certificate and key are formatted correctly (see https://github.com/OPEnSLab-OSU/SSLClient/issues/7#issuecomment-593704969). For more information on SSLClient's mTLS functionality, please see the SSLClientParameters documentation.
-
Note that both the above client certificate information as well as the correct trust anchors associated with the server are needed for the connection to succeed. Trust anchors will typically be generated from the CA used to generate the server certificate. More information on generating trust anchors can be found in ./TrustAnchors.md "TrustAnchors.md".
-
Implementation Gotchas
+
mTLS
+
As of v1.6.0, SSLClient supports mutual TLS authentication. mTLS is a varient of TLS that verifys both the server and device identities before a connection, and is commonly used in IoT protocols as a secure layer (MQTT over TLS, HTTPS over TLS, etc.).
+
To use mTLS with SSLClient you will need to a client certificate and client private key associated with the server you are attempting to connect to. Depending on your use case, you will either generate these yourself (ex. Mosquito MQTT setup), or have them generated for you (ex. AWS IoT Certificate Generation). Given this cryptographic information, you can modify the standard SSLClient connection sketch to enable mTLS authentication:
{C++}
+
...
+
/* Somewhere above setup() */
+
+
// The client certificate, can be PEM or DER format
+
// DER format will be an array of raw bytes, and PEM format will be a string
The client certificate must be formatted correctly (according to BearSSL's specification) in order for mTLS to work. If the certificate is improperly formatted, SSLClient will attempt to make a regular TLS connection instead of an mTLS one, and fail to connect as a result. Because of this, if you are seeing errors similar to "peer did not send certificate chain" on your server, check that your certificate and key are formatted correctly (see https://github.com/OPEnSLab-OSU/SSLClient/issues/7#issuecomment-593704969). For more information on SSLClient's mTLS functionality, please see the SSLClientParameters documentation.
+
Note that both the above client certificate information as well as the correct trust anchors associated with the server are needed for the connection to succeed. Trust anchors will typically be generated from the CA used to generate the server certificate. More information on generating trust anchors can be found in TrustAnchors.md.
+
Implementation Gotchas
Some ideas that didn't quite fit in the API documentation.
If you are using the Arduino Ethernet library, you will need to modify the library to support the large buffer sizes required by SSL (detailed in resources). You can either modify the library yourself, or use this fork of the Ethernet library with the modification. To use the fork, simply install the library using the "add a .zip library" button in Arduino, and replace #include "Ethernet.h" with #include "EthernetLarge.h" in your sketch. Alternatively if for some reason this solution does not work, you can apply the modification using the instructions below.
-
Manual Modification
-
First find the location of the library in the directory where Arduino is installed (C:\Program Files (x86)\Arduino on Windows). Inside of this directory, navigate to libraries\Ethernet\src (C:\Program Files (x86)\Arduino\libraries\Ethernet\src on Windows). Modify Ethernet.h to replace these lines:
1 {C++}
2 ...
3 // Configure the maximum number of sockets to support. W5100 chips can have
4 // up to 4 sockets. W5200 & W5500 can have up to 8 sockets. Several bytes
5 // of RAM are used for each socket. Reducing the maximum can save RAM, but
6 // you are limited to fewer simultaneous connections.
13 // By default, each socket uses 2K buffers inside the Wiznet chip. If
14 // MAX_SOCK_NUM is set to fewer than the chip's maximum, uncommenting
15 // this will use larger buffers within the Wiznet chip. Large buffers
16 // can really help with UDP protocols like Artnet. In theory larger
17 // buffers should allow faster TCP over high-latency links, but this
18 // does not always seem to work in practice (maybe Wiznet bugs?)
19 //#define ETHERNET_LARGE_BUFFERS
20 ...
With this:
1 {C++}
2 ...
3 // Configure the maximum number of sockets to support. W5100 chips can have
4 // up to 4 sockets. W5200 & W5500 can have up to 8 sockets. Several bytes
5 // of RAM are used for each socket. Reducing the maximum can save RAM, but
6 // you are limited to fewer simultaneous connections.
7 #define MAX_SOCK_NUM 2
8
9 // By default, each socket uses 2K buffers inside the Wiznet chip. If
10 // MAX_SOCK_NUM is set to fewer than the chip's maximum, uncommenting
11 // this will use larger buffers within the Wiznet chip. Large buffers
12 // can really help with UDP protocols like Artnet. In theory larger
13 // buffers should allow faster TCP over high-latency links, but this
14 // does not always seem to work in practice (maybe Wiznet bugs?)
15 #define ETHERNET_LARGE_BUFFERS
16 ...
You may need to use sudo or administrator permissions to make this modification. We change MAX_SOCK_NUM and ETHERNET_LARGE_BUFFERS so the Ethernet hardware can allocate a larger space for SSLClient, however a downside of this modification is we are now only able to have two sockets concurrently. As most microprocessors barely have enough memory for one SSL connection, this limitation will rarely be encountered in practice.
-
Seeding Random Data
-
The SSL protocol requires that SSLClient generate some random bits before connecting with a server. BearSSL provides a random number generator but requires a some entropy for a seed. Normally this seed is generated by taking the microsecond time using the internal clock, however since most microcontrollers are not build with this feature another source must be found. As a simple solution, SSLClient uses a floating analog pin as an external source of random data, passed through to the constructor in the analog_pin argument. Before every connection, SSLClient will take the bottom byte from 16 analog reads on analog_pin, and combine these bytes into a 16 byte random number, which is used as a seed for BearSSL. To ensure the most random data, it is recommended that this analog pin be either floating or connected to a location not modifiable by the microcontroller (i.e. a battery voltage readout).
-
Certificate Verification
-
SSLClient uses BearSSL's minimal x509 verification engine to verify the certificate of an SSL connection. This engine requires the developer create a trust anchor array using values stored in trusted root certificates. Check out ./TrustAnchors.md "this document" for more details on this component of SSLClient.
+
Manual Modification
+
First find the location of the library in the directory where Arduino is installed (C:\Program Files (x86)\Arduino on Windows). Inside of this directory, navigate to libraries\Ethernet\src (C:\Program Files (x86)\Arduino\libraries\Ethernet\src on Windows). Modify Ethernet.h to replace these lines:
{C++}
+
...
+
// Configure the maximum number of sockets to support. W5100 chips can have
+
// up to 4 sockets. W5200 & W5500 can have up to 8 sockets. Several bytes
+
// of RAM are used for each socket. Reducing the maximum can save RAM, but
+
// you are limited to fewer simultaneous connections.
// By default, each socket uses 2K buffers inside the Wiznet chip. If
+
// MAX_SOCK_NUM is set to fewer than the chip's maximum, uncommenting
+
// this will use larger buffers within the Wiznet chip. Large buffers
+
// can really help with UDP protocols like Artnet. In theory larger
+
// buffers should allow faster TCP over high-latency links, but this
+
// does not always seem to work in practice (maybe Wiznet bugs?)
+
//#define ETHERNET_LARGE_BUFFERS
+
...
+
With this:
{C++}
+
...
+
// Configure the maximum number of sockets to support. W5100 chips can have
+
// up to 4 sockets. W5200 & W5500 can have up to 8 sockets. Several bytes
+
// of RAM are used for each socket. Reducing the maximum can save RAM, but
+
// you are limited to fewer simultaneous connections.
+
#define MAX_SOCK_NUM 2
+
+
// By default, each socket uses 2K buffers inside the Wiznet chip. If
+
// MAX_SOCK_NUM is set to fewer than the chip's maximum, uncommenting
+
// this will use larger buffers within the Wiznet chip. Large buffers
+
// can really help with UDP protocols like Artnet. In theory larger
+
// buffers should allow faster TCP over high-latency links, but this
+
// does not always seem to work in practice (maybe Wiznet bugs?)
+
#define ETHERNET_LARGE_BUFFERS
+
...
+
You may need to use sudo or administrator permissions to make this modification. We change MAX_SOCK_NUM and ETHERNET_LARGE_BUFFERS so the Ethernet hardware can allocate a larger space for SSLClient, however a downside of this modification is we are now only able to have two sockets concurrently. As most microprocessors barely have enough memory for one SSL connection, this limitation will rarely be encountered in practice.
+
Seeding Random Data
+
The SSL protocol requires that SSLClient generate some random bits before connecting with a server. BearSSL provides a random number generator but requires a some entropy for a seed. Normally this seed is generated by taking the microsecond time using the internal clock, however since most microcontrollers are not build with this feature another source must be found. As a simple solution, SSLClient uses a floating analog pin as an external source of random data, passed through to the constructor in the analog_pin argument. Before every connection, SSLClient will take the bottom byte from 16 analog reads on analog_pin, and combine these bytes into a 16 byte random number, which is used as a seed for BearSSL. To ensure the most random data, it is recommended that this analog pin be either floating or connected to a location not modifiable by the microcontroller (i.e. a battery voltage readout).
+
Certificate Verification
+
SSLClient uses BearSSL's minimal x509 verification engine to verify the certificate of an SSL connection. This engine requires the developer create a trust anchor array using values stored in trusted root certificates. Check out this document for more details on this component of SSLClient.
BearSSL also features a known certificate validation engine, which only allows for a single domain in exchange for a significantly reduced resource usage (flash and CPU time). This functionality is planned to be implemented in the future.
-
Time
-
The minimal x509 verification engine requires an accurate source of time to properly verify the creation and expiration dates of a certificate. As most embedded devices do not have a reliable source of time, by default SSLClient opts to use the compilation timestamp (__DATE__ and __TIME__) as the "current time" during the verification process. While this approach reduces the complexity of using SSLClient, it is inherently insecure, and can cause errors if certificates are redeployed (see #27): to accommodate these edge cases, SSLClient::setVerificationTime can be used to update the timestamp before connecting, resolving the above issues.
-
Resources
+
Time
+
The minimal x509 verification engine requires an accurate source of time to properly verify the creation and expiration dates of a certificate. As most embedded devices do not have a reliable source of time, by default SSLClient opts to use the compilation timestamp (__DATE__ and __TIME__) as the "current time" during the verification process. While this approach reduces the complexity of using SSLClient, it is inherently insecure, and can cause errors if certificates are redeployed (see #27): to accommodate these edge cases, SSLClient::setVerificationTime can be used to update the timestamp before connecting, resolving the above issues.
+
Resources
The SSL protocol recommends a device support many different encryption algorithms, as well as protocols for SSL itself. The complexity of both of those components results in many medium sized components forming an extremely large whole. Additionally, most embedded processors lack the sophisticated math hardware commonly found in a modern CPU, and as a result require more instructions to create the encryption algorithms SSL requires. This not only increases size but makes the algorithms slow and memory intensive.
To illustrate this, I will run some tests on various domains below. I haven't yet, but I will.
If flash footprint is becoming a problem, there are numerous debugging strings (~3kb estimated) that can be removed from SSLClient.h, SSLClientImpl.h, and SSLClientImpl.cpp. I have not figured out a way to configure compilation of these strings, so you will need to modify the library to remove them yourself.
-
Read Buffer Overflow
-
SSL is a buffered protocol, and since most microcontrollers have limited resources (see Resources), SSLClient is limited in the size of its buffers. A common problem I encountered with SSL connections is buffer overflow, caused by the server sending too much data at once. This problem is caused by the microcontroller being unable to copy and decrypt data faster than it is being received, forcing some data to be discarded. This usually puts BearSSL in an unrecoverable state, forcing SSLClient to close the connection with a write error. If you are experiencing frequent timeout problems, this could be the reason why.
+
Read Buffer Overflow
+
SSL is a buffered protocol, and since most microcontrollers have limited resources (see Resources), SSLClient is limited in the size of its buffers. A common problem I encountered with SSL connections is buffer overflow, caused by the server sending too much data at once. This problem is caused by the microcontroller being unable to copy and decrypt data faster than it is being received, forcing some data to be discarded. This usually puts BearSSL in an unrecoverable state, forcing SSLClient to close the connection with a write error. If you are experiencing frequent timeout problems, this could be the reason why.
In order to remedy this problem, the device must be able to read the data faster than it is being received, or alternatively have a cache large enough to store the entire payload. Since SSL's encryption forces the device to read slowly, this means we must increase the cache size. Depending on your platform, there are a number of ways this can be done:
Sometimes your communication shield will have an internal buffer, which can be expanded through the driver code. This is the case with the Arduino Ethernet library (in the form of the MAX_SOCK_NUM and ETHERNET_LARGE_BUFFERS macros), however the library must be modified for the change to take effect.
-
SSLClient has an internal buffer SSLClient::m_iobuf, which can be expanded. BearSSL limits the amount of data that can be processed based on the stage in the SSL handshake, and so this will change will have limited usefulness.
-
In some cases, a website will send so much data that even with the above solutions, SSLClient will be unable to keep up (a website with a lot of HTML is an example). In these cases you will have to find another method of retrieving the data you need.
+
SSLClient has an internal buffer SSLClient::m_iobuf, which can be expanded. BearSSL limits the amount of data that can be processed based on the stage in the SSL handshake, and so this will change will have limited usefulness.
+
In some cases, a website will send so much data that even with the above solutions, SSLClient will be unable to keep up (a website with a lot of HTML is an example). In these cases you will have to find another method of retrieving the data you need.
If none of the above are viable, it is possible to implement your own Client class which has an internal buffer much larger than both the driver and BearSSL. This would require in-depth knowledge of programming and the communication shield you are working with, as well as a microcontroller with a significant amount of RAM.
-
Cipher Support
-
By default, SSLClient supports only TLS1.2 and the ciphers listed in this file under suites[], and the list is relatively small to keep the connection secure and the flash footprint down. These ciphers should work for most applications, however if for some reason you would like to use an older version of TLS or a different cipher, you can change the BearSSL profile being used by SSLClient to an alternate one with support for older protocols. To do this, edit SSLClientImpl::SSLClientImpl to change these lines:
If for some unfortunate reason you need SSL 3.0 or SSL 2.0, you will need to modify the BearSSL profile to enable support. Check out the BearSSL profiles documentation and I wish you the best of luck.
-
Security
-
Unlike BearSSL, SSLClient is not rigorously vetted to be secure. If your project has security requirements, I recommend you utilize BearSSL directly.
-
Known Issues
+
Cipher Support
+
By default, SSLClient supports only TLS1.2 and the ciphers listed in this file under suites[], and the list is relatively small to keep the connection secure and the flash footprint down. These ciphers should work for most applications, however if for some reason you would like to use an older version of TLS or a different cipher, you can change the BearSSL profile being used by SSLClient to an alternate one with support for older protocols. To do this, edit SSLClientImpl::SSLClientImpl to change these lines:
If for some unfortunate reason you need SSL 3.0 or SSL 2.0, you will need to modify the BearSSL profile to enable support. Check out the BearSSL profiles documentation and I wish you the best of luck.
+
Security
+
Unlike BearSSL, SSLClient is not rigorously vetted to be secure. If your project has security requirements, I recommend you utilize BearSSL directly.
+
Known Issues
-
In some drivers (Ethernet), calls to Client::flush will hang if internet is available but there is no route to the destination. Unfortunately SSLClient cannot correct for this without modifying the driver itself, and as a result the recommended solution is ensuring you choose a driver with built-in timeouts to prevent freezing. More information here.
+
In some drivers (Ethernet), calls to Client::flush will hang if internet is available but there is no route to the destination. Unfortunately SSLClient cannot correct for this without modifying the driver itself, and as a result the recommended solution is ensuring you choose a driver with built-in timeouts to prevent freezing. More information here.
When using PubSubClient on the ESP32, a stack overflow will occur if the user does not flush the buffer immediately after writing. The cause of this issue is under active investigation. More information in issue https://github.com/OPEnSLab-OSU/SSLClient/issues/9.
Previous to SSLClient v1.6.6, calls to SSLClient::connect would fail if the driver indicated that a socket was already opened (Client::connected returned true). This behavior created unintentional permanent failures when Client::stop would fail to close the socket, and as a result was downgraded to a warning in v1.6.6.
-
Previous to SSLClient v1.6.3, calling SSLClient::write with more than 2Kb of total data before flushing the write buffer would cause a buffer overflow.
Previous to SSLClient v1.6.6, calls to SSLClient::connect would fail if the driver indicated that a socket was already opened (Client::connected returned true). This behavior created unintentional permanent failures when Client::stop would fail to close the socket, and as a result was downgraded to a warning in v1.6.6.
+
Previous to SSLClient v1.6.3, calling SSLClient::write with more than 2Kb of total data before flushing the write buffer would cause a buffer overflow.
SSLClient uses BearSSL's minimal x509 verification engine to verify the certificate of an SSL connection. This engine requires the developer create a trust anchor array using values stored in trusted root certificates. In short, these trust anchor arrays allow BearSSL to verify that the server being connected to is who they say they are, and not someone malicious. You can read more about certificates and why they are important here.
-
SSLClient stores trust anchors in hardcoded constant variables, passed into SSLClient::SSLClient during setup. These constants are generally stored in their own header file as found in the BearSSL docs. This header file will look something like:
Typically a trust anchor header file is generated using brssl, a command-line utility included in BearSSL. As it is a fairly involded process to get brssl working, SSLClient provides a number of alternative tools to make the generation process a bit easier.
-
Note: When working with certificates (particularly in complicated mTLS setups), it can easily become confusing which certificate does what. If you aren't sure what certificate to put into the Trust Anchor tool, remember that Trust Anchors only care about the verifying the server: in other words, the certificate that goes into a Trust Anchor generation tool should be the certificate used to generate the server's certificate (usually a CA). Trust Anchors will never contain any information about client certificates, which should be passed into SSLClientParams instead.
-
HTTPS
-
For HTTPS, there a couple of tools you can use. Ordered from easiest to hardest:
pycert_bearssl, a command line utility based on a pycert. You will need to install Python 3, and follow the instructions in the pycert_bearssl.py file. You'll want to use the pycert_bearssl.py download command once the utility is set up.
-
The brssl command line utility, included in the BearSSL source. You will need to compile this file yourself.
-
-
Other Connections
-
For other kinds of SSL connections, you will need to find the root certificate being used by your host. You can check out this StackExchange post for numerous methods of acquiring this certificate from a server. If these methods are not sufficient, you may need to request this certificate from your network administrator. Once you have the certificate, convert it to PEM format if needed (I use this website), and use the pycert_bearssl.py convert --no-search command to convert the certificate into a trust anchor header.
-
Using Trust Anchors
-
Once you've generated a trust anchor array, add it to your Arduino sketch using the Sketch->Add File button in the Arduino IDE, and link it to your SSLClient like so:
1 {C++}
2 #include "yourtrustanchorfile.h"
3 // ...
4 SSLClient client(SomeClient, TAs, (size_t)TAs_NUM, SomePin);
5 // ...
Where yourtrustanchorfile.h contains a generated trust anchor array names TAs, with length TAs_NUM. BearSSL will now automatically use these trust anchors when SSLClient::connect is called.
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
-
Our Standards
+
Our Standards
Examples of behavior that contributes to creating a positive environment include:
Publishing others' private information, such as a physical or electronic address, without explicit permission
Other conduct which could reasonably be considered inappropriate in a professional setting
-
Our Responsibilities
+
Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
-
Scope
+
Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
-
Enforcement
+
Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at open..nosp@m.sens.nosp@m.ing@o.nosp@m.rego.nosp@m.nstat.nosp@m.e.ed.nosp@m.u. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
SSLClient uses BearSSL's minimal x509 verification engine to verify the certificate of an SSL connection. This engine requires the developer create a trust anchor array using values stored in trusted root certificates. In short, these trust anchor arrays allow BearSSL to verify that the server being connected to is who they say they are, and not someone malicious. You can read more about certificates and why they are important here.
+
SSLClient stores trust anchors in hardcoded constant variables, passed into SSLClient::SSLClient during setup. These constants are generally stored in their own header file as found in the BearSSL docs. This header file will look something like:
Typically a trust anchor header file is generated using brssl, a command-line utility included in BearSSL. As it is a fairly involded process to get brssl working, SSLClient provides a number of alternative tools to make the generation process a bit easier.
+
Note: When working with certificates (particularly in complicated mTLS setups), it can easily become confusing which certificate does what. If you aren't sure what certificate to put into the Trust Anchor tool, remember that Trust Anchors only care about the verifying the server: in other words, the certificate that goes into a Trust Anchor generation tool should be the certificate used to generate the server's certificate (usually a CA). Trust Anchors will never contain any information about client certificates, which should be passed into SSLClientParams instead.
+
HTTPS
+
For HTTPS, there a couple of tools you can use. Ordered from easiest to hardest:
pycert_bearssl, a command line utility based on a pycert. You will need to install Python 3, and follow the instructions in the pycert_bearssl.py file. You'll want to use the pycert_bearssl.py download command once the utility is set up.
+
The brssl command line utility, included in the BearSSL source. You will need to compile this file yourself.
+
+
Other Connections
+
For other kinds of SSL connections, you will need to find the root certificate being used by your host. You can check out this StackExchange post for numerous methods of acquiring this certificate from a server. If these methods are not sufficient, you may need to request this certificate from your network administrator. Once you have the certificate, convert it to PEM format if needed (I use this website), and use the pycert_bearssl.py convert --no-search command to convert the certificate into a trust anchor header.
+
Using Trust Anchors
+
Once you've generated a trust anchor array, add it to your Arduino sketch using the Sketch->Add File button in the Arduino IDE, and link it to your SSLClient like so:
{C++}
+
#include "yourtrustanchorfile.h"
+
// ...
+
SSLClient client(SomeClient, TAs, (size_t)TAs_NUM, SomePin);
+
// ...
+
Where yourtrustanchorfile.h contains a generated trust anchor array names TAs, with length TAs_NUM. BearSSL will now automatically use these trust anchors when SSLClient::connect is called.
+
+
+
+
+
+
+
Generated by 1.8.20
+
+
+
+
diff --git a/menu.js b/menu.js
new file mode 100644
index 0000000..2fe2214
--- /dev/null
+++ b/menu.js
@@ -0,0 +1,51 @@
+/*
+ @licstart The following is the entire license notice for the JavaScript code in this file.
+
+ The MIT License (MIT)
+
+ Copyright (C) 1997-2020 by Dimitri van Heesch
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ and associated documentation files (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ @licend The above is the entire license notice for the JavaScript code in this file
+ */
+function initMenu(relPath,searchEnabled,serverSide,searchPage,search) {
+ function makeTree(data,relPath) {
+ var result='';
+ if ('children' in data) {
+ result+='
');
+ }
+ }
+ $('#main-menu').smartmenus();
+}
+/* @license-end */
diff --git a/menudata.js b/menudata.js
new file mode 100644
index 0000000..736b513
--- /dev/null
+++ b/menudata.js
@@ -0,0 +1,71 @@
+/*
+ @licstart The following is the entire license notice for the JavaScript code in this file.
+
+ The MIT License (MIT)
+
+ Copyright (C) 1997-2020 by Dimitri van Heesch
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ and associated documentation files (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ @licend The above is the entire license notice for the JavaScript code in this file
+*/
+var menudata={children:[
+{text:"Main Page",url:"index.html"},
+{text:"Related Pages",url:"pages.html"},
+{text:"Namespaces",url:"namespaces.html",children:[
+{text:"Namespace List",url:"namespaces.html"},
+{text:"Namespace Members",url:"namespacemembers.html",children:[
+{text:"All",url:"namespacemembers.html"},
+{text:"Functions",url:"namespacemembers_func.html"}]}]},
+{text:"Classes",url:"annotated.html",children:[
+{text:"Class List",url:"annotated.html"},
+{text:"Class Index",url:"classes.html"},
+{text:"Class Hierarchy",url:"hierarchy.html"},
+{text:"Class Members",url:"functions.html",children:[
+{text:"All",url:"functions.html",children:[
+{text:"a",url:"functions.html#index_a"},
+{text:"c",url:"functions.html#index_c"},
+{text:"d",url:"functions.html#index_d"},
+{text:"e",url:"functions.html#index_e"},
+{text:"f",url:"functions.html#index_f"},
+{text:"g",url:"functions.html#index_g"},
+{text:"i",url:"functions.html#index_i"},
+{text:"o",url:"functions.html#index_o"},
+{text:"p",url:"functions.html#index_p"},
+{text:"r",url:"functions.html#index_r"},
+{text:"s",url:"functions.html#index_s"},
+{text:"t",url:"functions.html#index_t"},
+{text:"v",url:"functions.html#index_v"},
+{text:"w",url:"functions.html#index_w"}]},
+{text:"Functions",url:"functions_func.html",children:[
+{text:"a",url:"functions_func.html#index_a"},
+{text:"c",url:"functions_func.html#index_c"},
+{text:"f",url:"functions_func.html#index_f"},
+{text:"g",url:"functions_func.html#index_g"},
+{text:"o",url:"functions_func.html#index_o"},
+{text:"p",url:"functions_func.html#index_p"},
+{text:"r",url:"functions_func.html#index_r"},
+{text:"s",url:"functions_func.html#index_s"},
+{text:"t",url:"functions_func.html#index_t"},
+{text:"w",url:"functions_func.html#index_w"}]},
+{text:"Variables",url:"functions_vars.html"},
+{text:"Enumerations",url:"functions_enum.html"},
+{text:"Enumerator",url:"functions_eval.html"}]}]},
+{text:"Files",url:"files.html",children:[
+{text:"File List",url:"files.html"},
+{text:"File Members",url:"globals.html",children:[
+{text:"All",url:"globals.html"},
+{text:"Macros",url:"globals_defs.html"}]}]}]}
diff --git a/namespacemembers.html b/namespacemembers.html
index 6782b58..0fb6f33 100644
--- a/namespacemembers.html
+++ b/namespacemembers.html
@@ -1,9 +1,10 @@
-
+
-
+
+
SSLClient: Namespace Members
@@ -12,16 +13,9 @@
-
-
@@ -40,47 +34,22 @@
diff --git a/navtree.css b/navtree.css
index 1a868b3..33341a6 100644
--- a/navtree.css
+++ b/navtree.css
@@ -94,8 +94,11 @@
}
.ui-resizable-e {
- background:url("splitbar.png") repeat scroll right center transparent;
- cursor:e-resize;
+ background-image:url("splitbar.png");
+ background-size:100%;
+ background-repeat:repeat-y;
+ background-attachment: scroll;
+ cursor:ew-resize;
height:100%;
right:0;
top:0;
diff --git a/navtree.js b/navtree.js
index 9df45a7..1e272d3 100644
--- a/navtree.js
+++ b/navtree.js
@@ -1,4 +1,30 @@
+/*
+ @licstart The following is the entire license notice for the JavaScript code in this file.
+
+ The MIT License (MIT)
+
+ Copyright (C) 1997-2020 by Dimitri van Heesch
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ and associated documentation files (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ @licend The above is the entire license notice for the JavaScript code in this file
+ */
var navTreeSubIndices = new Array();
+var arrowDown = '▼';
+var arrowRight = '►';
function getData(varName)
{
@@ -45,7 +71,6 @@ function localStorageSupported()
}
}
-
function storeLink(link)
{
if (!$("#nav-sync").hasClass('sync') && localStorageSupported()) {
@@ -71,21 +96,13 @@ function cachedLink()
function getScript(scriptName,func,show)
{
- var head = document.getElementsByTagName("head")[0];
+ var head = document.getElementsByTagName("head")[0];
var script = document.createElement('script');
script.id = scriptName;
script.type = 'text/javascript';
- script.onload = func;
- script.src = scriptName+'.js';
- if ($.browser.msie && $.browser.version<=8) {
- // script.onload does not work with older versions of IE
- script.onreadystatechange = function() {
- if (script.readyState=='complete' || script.readyState=='loaded') {
- func(); if (show) showRoot();
- }
- }
- }
- head.appendChild(script);
+ script.onload = func;
+ script.src = scriptName+'.js';
+ head.appendChild(script);
}
function createIndent(o,domNode,node,level)
@@ -94,18 +111,17 @@ function createIndent(o,domNode,node,level)
var n = node;
while (n.parentNode) { level++; n=n.parentNode; }
if (node.childrenData) {
- var imgNode = document.createElement("img");
+ var imgNode = document.createElement("span");
+ imgNode.className = 'arrow';
imgNode.style.paddingLeft=(16*level).toString()+'px';
- imgNode.width = 16;
- imgNode.height = 22;
- imgNode.border = 0;
+ imgNode.innerHTML=arrowRight;
node.plus_img = imgNode;
node.expandToggle = document.createElement("a");
node.expandToggle.href = "javascript:void(0)";
node.expandToggle.onclick = function() {
if (node.expanded) {
$(node.getChildrenUL()).slideUp("fast");
- node.plus_img.src = node.relpath+"arrowright.png";
+ node.plus_img.innerHTML=arrowRight;
node.expanded = false;
} else {
expandNode(o, node, false, false);
@@ -113,15 +129,13 @@ function createIndent(o,domNode,node,level)
}
node.expandToggle.appendChild(imgNode);
domNode.appendChild(node.expandToggle);
- imgNode.src = node.relpath+"arrowright.png";
} else {
var span = document.createElement("span");
- span.style.display = 'inline-block';
+ span.className = 'arrow';
span.style.width = 16*(level+1)+'px';
- span.style.height = '22px';
span.innerHTML = ' ';
domNode.appendChild(span);
- }
+ }
}
var animationInProgress = false;
@@ -131,6 +145,7 @@ function gotoAnchor(anchor,aname,updateLocation)
var pos, docContent = $('#doc-content');
var ancParent = $(anchor.parent());
if (ancParent.hasClass('memItemLeft') ||
+ ancParent.hasClass('memtitle') ||
ancParent.hasClass('fieldname') ||
ancParent.hasClass('fieldtype') ||
ancParent.is(':header'))
@@ -195,7 +210,7 @@ function newNode(o, po, text, link, childrenData, lastNode)
var aname = '#'+link.split('#')[1];
var srcPage = stripPath(pathName());
var targetPage = stripPath(link.split('#')[0]);
- a.href = srcPage!=targetPage ? url : "javascript:void(0)";
+ a.href = srcPage!=targetPage ? url : "javascript:void(0)";
a.onclick = function(){
storeLink(link);
if (!$(a).parent().parent().hasClass('selected'))
@@ -213,7 +228,7 @@ function newNode(o, po, text, link, childrenData, lastNode)
a.onclick = function() { storeLink(link); }
}
} else {
- if (childrenData != null)
+ if (childrenData != null)
{
a.className = "nolink";
a.href = "javascript:void(0)";
@@ -243,7 +258,7 @@ function showRoot()
(function (){ // retry until we can scroll to the selected item
try {
var navtree=$('#nav-tree');
- navtree.scrollTo('#selected',0,{offset:-windowHeight/2});
+ navtree.scrollTo('#selected',100,{offset:-windowHeight/2});
} catch (err) {
setTimeout(arguments.callee, 0);
}
@@ -262,17 +277,9 @@ function expandNode(o, node, imm, showRoot)
} else {
if (!node.childrenVisited) {
getNode(o, node);
- } if (imm || ($.browser.msie && $.browser.version>8)) {
- // somehow slideDown jumps to the start of tree for IE9 :-(
- $(node.getChildrenUL()).show();
- } else {
- $(node.getChildrenUL()).slideDown("fast");
- }
- if (node.isLast) {
- node.plus_img.src = node.relpath+"arrowdown.png";
- } else {
- node.plus_img.src = node.relpath+"arrowdown.png";
}
+ $(node.getChildrenUL()).slideDown("fast");
+ node.plus_img.innerHTML = arrowDown;
node.expanded = true;
}
}
@@ -301,7 +308,6 @@ function highlightAnchor()
} else {
glowEffect(anchor.next(),1000); // normal member
}
- gotoAnchor(anchor,aname,false);
}
function selectAndHighlight(hash,n)
@@ -341,7 +347,7 @@ function showNode(o, node, index, hash)
getNode(o, node);
}
$(node.getChildrenUL()).css({'display':'block'});
- node.plus_img.src = node.relpath+"arrowdown.png";
+ node.plus_img.innerHTML = arrowDown;
node.expanded = true;
var n = node.children[o.breadcrumbs[index]];
if (index+11){
@@ -520,4 +543,4 @@ function initNavTree(toroot,relpath)
}
})
}
-
+/* @license-end */
diff --git a/navtreedata.js b/navtreedata.js
index 0afccae..6b896ca 100644
--- a/navtreedata.js
+++ b/navtreedata.js
@@ -1,11 +1,35 @@
+/*
+ @licstart The following is the entire license notice for the JavaScript code in this file.
+
+ The MIT License (MIT)
+
+ Copyright (C) 1997-2020 by Dimitri van Heesch
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ and associated documentation files (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ @licend The above is the entire license notice for the JavaScript code in this file
+*/
var NAVTREE =
[
[ "SSLClient", "index.html", [
- [ "Contributor Covenant Code of Conduct", "md_CODE_OF_CONDUCT.html", null ],
- [ "Contributing", "md_CONTRIBUTING.html", null ],
- [ "Trust Anchors", "md_TrustAnchors.html", null ],
- [ "Namespaces", null, [
- [ "Namespace List", "namespaces.html", "namespaces" ],
+ [ "Contributor Covenant Code of Conduct", "md__c_o_d_e__o_f__c_o_n_d_u_c_t.html", null ],
+ [ "Contributing", "md__c_o_n_t_r_i_b_u_t_i_n_g.html", null ],
+ [ "Trust Anchors", "md__trust_anchors.html", null ],
+ [ "Namespaces", "namespaces.html", [
+ [ "Namespace List", "namespaces.html", "namespaces_dup" ],
[ "Namespace Members", "namespacemembers.html", [
[ "All", "namespacemembers.html", null ],
[ "Functions", "namespacemembers_func.html", null ]
@@ -23,8 +47,8 @@ var NAVTREE =
[ "Enumerator", "functions_eval.html", null ]
] ]
] ],
- [ "Files", null, [
- [ "File List", "files.html", "files" ],
+ [ "Files", "files.html", [
+ [ "File List", "files.html", "files_dup" ],
[ "File Members", "globals.html", [
[ "All", "globals.html", null ],
[ "Macros", "globals_defs.html", null ]
diff --git a/navtreeindex0.js b/navtreeindex0.js
index 09024f6..ffb0847 100644
--- a/navtreeindex0.js
+++ b/navtreeindex0.js
@@ -12,10 +12,10 @@ var NAVTREEINDEX0 =
"annotated.html":[4,0],
"class_s_s_l_client.html":[4,0,1],
"class_s_s_l_client.html#a03c7926938acd57cfc3b982edf725a86":[4,0,1,21],
-"class_s_s_l_client.html#a08f05da0fca82c3470be4c1da8cf80a3":[4,0,1,11],
"class_s_s_l_client.html#a0c0b6f2ad25701d1e45adb613d072d86":[4,0,1,13],
"class_s_s_l_client.html#a0e775669b4a040fbd3f281dcbcd2de78":[4,0,1,3],
-"class_s_s_l_client.html#a248a5152cc3c3e7666bf5443bfd57c90":[4,0,1,5],
+"class_s_s_l_client.html#a248a5152cc3c3e7666bf5443bfd57c90":[4,0,1,4],
+"class_s_s_l_client.html#a2a178251978e0622f7e241da702ae498":[4,0,1,11],
"class_s_s_l_client.html#a2bd012ef6f01df9694ba9fd0a3c227c3":[4,0,1,9],
"class_s_s_l_client.html#a4192ee3562c4806d4a6829356ca2636b":[4,0,1,12],
"class_s_s_l_client.html#a48239f60f1b4318cc112706fc40c6cea":[4,0,1,1],
@@ -26,8 +26,7 @@ var NAVTREEINDEX0 =
"class_s_s_l_client.html#a48239f60f1b4318cc112706fc40c6ceaa7510402478ffbecd6e1aa3811b175cfd":[4,0,1,1,1],
"class_s_s_l_client.html#a48239f60f1b4318cc112706fc40c6ceaab8581e1172fbf15067d435706d3a03a8":[4,0,1,1,3],
"class_s_s_l_client.html#a48239f60f1b4318cc112706fc40c6ceaaf66f8d5f6601f9e7607b78bf7a07fc84":[4,0,1,1,5],
-"class_s_s_l_client.html#a4c5420541a06213133ae308a3bca1c95":[4,0,1,14],
-"class_s_s_l_client.html#a51dd3097cf5a3a8bf7644517026954b5":[4,0,1,10],
+"class_s_s_l_client.html#a4c5420541a06213133ae308a3bca1c95":[4,0,1,15],
"class_s_s_l_client.html#a5488f01ccfddfd9e41f54dfbda48bcae":[4,0,1,6],
"class_s_s_l_client.html#a68f026a625ca1ccd1aba87bb6e670376":[4,0,1,2],
"class_s_s_l_client.html#a7343a58457b4659f83b61cac1f442c3d":[4,0,1,22],
@@ -35,11 +34,12 @@ var NAVTREEINDEX0 =
"class_s_s_l_client.html#a9a4e9c9877ab73cf7e82d6942cc7db21":[4,0,1,8],
"class_s_s_l_client.html#aaf2192a6621fdf2f89cc26a9a1584f8c":[4,0,1,7],
"class_s_s_l_client.html#ab285c2f5a03124558ef7f74b9f3d12ad":[4,0,1,19],
-"class_s_s_l_client.html#ab97c0745f65a6c6009ac938b3b9912c3":[4,0,1,4],
+"class_s_s_l_client.html#ab97c0745f65a6c6009ac938b3b9912c3":[4,0,1,5],
"class_s_s_l_client.html#ad5d9d8a4187a3f8918bf66af83e733c4":[4,0,1,16],
"class_s_s_l_client.html#ad8ed697371748e31e01c3f697bc36cbe":[4,0,1,20],
+"class_s_s_l_client.html#ae3f9e6f8e8a50e520c936239abecfd22":[4,0,1,10],
"class_s_s_l_client.html#aeee217b5558dfb0724f2319888a77256":[4,0,1,17],
-"class_s_s_l_client.html#aef1b52f4ad9633126cb68739175920eb":[4,0,1,15],
+"class_s_s_l_client.html#aef1b52f4ad9633126cb68739175920eb":[4,0,1,14],
"class_s_s_l_client.html#af632625f8d247f3885c81e1f05043ad1":[4,0,1,0],
"class_s_s_l_client.html#af632625f8d247f3885c81e1f05043ad1a199742ec5c99c72d9cede1fda0f125c5":[4,0,1,0,1],
"class_s_s_l_client.html#af632625f8d247f3885c81e1f05043ad1a24122d1e1bb724237f305a0b4a21ff75":[4,0,1,0,0],
@@ -47,14 +47,14 @@ var NAVTREEINDEX0 =
"class_s_s_l_client.html#af632625f8d247f3885c81e1f05043ad1a8d5f7561f9cc0a2f3e5f362b02f4a5b2":[4,0,1,0,3],
"class_s_s_l_client.html#af632625f8d247f3885c81e1f05043ad1ad1cf0d4d876daa655edb8331bfe2ce39":[4,0,1,0,4],
"class_s_s_l_client_parameters.html":[4,0,2],
-"class_s_s_l_client_parameters.html#a8d0294703c37b7f46eddc7914d6eb7c5":[4,0,2,3],
-"class_s_s_l_client_parameters.html#a92e6fcaf9a4d001cb3df91f3e7b8b5e2":[4,0,2,4],
+"class_s_s_l_client_parameters.html#a82c21b0ae4690a6b7842a0d74b12f67f":[4,0,2,4],
+"class_s_s_l_client_parameters.html#a90d581703308881714d64d1ada785ad2":[4,0,2,2],
"class_s_s_l_client_parameters.html#a97213b5554e90908fbf284669b5f22f3":[4,0,2,0],
-"class_s_s_l_client_parameters.html#ab00a35434fb94451b78b6dd502f53921":[4,0,2,1],
-"class_s_s_l_client_parameters.html#ab48cdb94c7dedcc922b8b4fa84ca03b5":[4,0,2,2],
+"class_s_s_l_client_parameters.html#ad9beb80ce98ed9aa34db28783f0264c5":[4,0,2,3],
+"class_s_s_l_client_parameters.html#af5686b2c601812f55477a7089b3b2c2d":[4,0,2,1],
"class_s_s_l_session.html":[4,0,3],
"class_s_s_l_session.html#a0c8e01b0944c1f4b0ec6d4c423c95b74":[4,0,3,0],
-"class_s_s_l_session.html#a42aa22e9b6ef3a6d859cdbc21fef90e0":[4,0,3,1],
+"class_s_s_l_session.html#a825373c5ba1aa6c45e74dc8a72b21820":[4,0,3,1],
"class_s_s_l_session.html#acbe6549b55d50541d09a16f770e65afc":[4,0,3,2],
"classes.html":[4,1],
"dir_68267d1309a1af8e8297ef4c3efbcdba.html":[5,0,0],
@@ -68,9 +68,9 @@ var NAVTREEINDEX0 =
"globals_defs.html":[5,1,1],
"hierarchy.html":[4,2],
"index.html":[],
-"md_CODE_OF_CONDUCT.html":[0],
-"md_CONTRIBUTING.html":[1],
-"md_TrustAnchors.html":[2],
+"md__c_o_d_e__o_f__c_o_n_d_u_c_t.html":[0],
+"md__c_o_n_t_r_i_b_u_t_i_n_g.html":[1],
+"md__trust_anchors.html":[2],
"namespacemembers.html":[3,1,0],
"namespacemembers_func.html":[3,1,1],
"namespaces.html":[3,0],
diff --git a/pages.html b/pages.html
index f474d8b..8b2982f 100644
--- a/pages.html
+++ b/pages.html
@@ -1,9 +1,10 @@
-
+
-
+
+
SSLClient: Related Pages
@@ -12,16 +13,9 @@
-
-
@@ -40,35 +34,22 @@
diff --git a/resize.js b/resize.js
index 2b86c36..e1ad0fe 100644
--- a/resize.js
+++ b/resize.js
@@ -1,73 +1,131 @@
-var cookie_namespace = 'doxygen';
-var sidenav,navtree,content,header;
+/*
+ @licstart The following is the entire license notice for the JavaScript code in this file.
-function readCookie(cookie)
-{
- var myCookie = cookie_namespace+"_"+cookie+"=";
- if (document.cookie)
- {
- var index = document.cookie.indexOf(myCookie);
- if (index != -1)
- {
- var valStart = index + myCookie.length;
- var valEnd = document.cookie.indexOf(";", valStart);
- if (valEnd == -1)
- {
- valEnd = document.cookie.length;
- }
- var val = document.cookie.substring(valStart, valEnd);
- return val;
- }
- }
- return 0;
-}
+ The MIT License (MIT)
-function writeCookie(cookie, val, expiration)
-{
- if (val==undefined) return;
- if (expiration == null)
- {
- var date = new Date();
- date.setTime(date.getTime()+(10*365*24*60*60*1000)); // default expiration is one week
- expiration = date.toGMTString();
- }
- document.cookie = cookie_namespace + "_" + cookie + "=" + val + "; expires=" + expiration+"; path=/";
-}
-
-function resizeWidth()
-{
- var windowWidth = $(window).width() + "px";
- var sidenavWidth = $(sidenav).outerWidth();
- content.css({marginLeft:parseInt(sidenavWidth)+"px"});
- writeCookie('width',sidenavWidth, null);
-}
+ Copyright (C) 1997-2020 by Dimitri van Heesch
-function restoreWidth(navWidth)
-{
- var windowWidth = $(window).width() + "px";
- content.css({marginLeft:parseInt(navWidth)+6+"px"});
- sidenav.css({width:navWidth + "px"});
-}
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ and associated documentation files (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
-function resizeHeight()
-{
- var headerHeight = header.outerHeight();
- var footerHeight = footer.outerHeight();
- var windowHeight = $(window).height() - headerHeight - footerHeight;
- content.css({height:windowHeight + "px"});
- navtree.css({height:windowHeight + "px"});
- sidenav.css({height:windowHeight + "px"});
-}
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ @licend The above is the entire license notice for the JavaScript code in this file
+ */
function initResizable()
{
+ var cookie_namespace = 'doxygen';
+ var sidenav,navtree,content,header,collapsed,collapsedWidth=0,barWidth=6,desktop_vp=768,titleHeight;
+
+ function readCookie(cookie)
+ {
+ var myCookie = cookie_namespace+"_"+cookie+"=";
+ if (document.cookie) {
+ var index = document.cookie.indexOf(myCookie);
+ if (index != -1) {
+ var valStart = index + myCookie.length;
+ var valEnd = document.cookie.indexOf(";", valStart);
+ if (valEnd == -1) {
+ valEnd = document.cookie.length;
+ }
+ var val = document.cookie.substring(valStart, valEnd);
+ return val;
+ }
+ }
+ return 0;
+ }
+
+ function writeCookie(cookie, val, expiration)
+ {
+ if (val==undefined) return;
+ if (expiration == null) {
+ var date = new Date();
+ date.setTime(date.getTime()+(10*365*24*60*60*1000)); // default expiration is one week
+ expiration = date.toGMTString();
+ }
+ document.cookie = cookie_namespace + "_" + cookie + "=" + val + "; expires=" + expiration+"; path=/";
+ }
+
+ function resizeWidth()
+ {
+ var windowWidth = $(window).width() + "px";
+ var sidenavWidth = $(sidenav).outerWidth();
+ content.css({marginLeft:parseInt(sidenavWidth)+"px"});
+ writeCookie('width',sidenavWidth-barWidth, null);
+ }
+
+ function restoreWidth(navWidth)
+ {
+ var windowWidth = $(window).width() + "px";
+ content.css({marginLeft:parseInt(navWidth)+barWidth+"px"});
+ sidenav.css({width:navWidth + "px"});
+ }
+
+ function resizeHeight()
+ {
+ var headerHeight = header.outerHeight();
+ var footerHeight = footer.outerHeight();
+ var windowHeight = $(window).height() - headerHeight - footerHeight;
+ content.css({height:windowHeight + "px"});
+ navtree.css({height:windowHeight + "px"});
+ sidenav.css({height:windowHeight + "px"});
+ var width=$(window).width();
+ if (width!=collapsedWidth) {
+ if (width=desktop_vp) {
+ if (!collapsed) {
+ collapseExpand();
+ }
+ } else if (width>desktop_vp && collapsedWidth0) {
+ restoreWidth(0);
+ collapsed=true;
+ }
+ else {
+ var width = readCookie('width');
+ if (width>200 && width<$(window).width()) { restoreWidth(width); } else { restoreWidth(200); }
+ collapsed=false;
+ }
+ }
+
header = $("#top");
sidenav = $("#side-nav");
content = $("#doc-content");
navtree = $("#nav-tree");
footer = $("#nav-path");
$(".side-nav-resizable").resizable({resize: function(e, ui) { resizeWidth(); } });
+ $(sidenav).resizable({ minWidth: 0 });
$(window).resize(function() { resizeHeight(); });
+ var device = navigator.userAgent.toLowerCase();
+ var touch_device = device.match(/(iphone|ipod|ipad|android)/);
+ if (touch_device) { /* wider split bar for touch only devices */
+ $(sidenav).css({ paddingRight:'20px' });
+ $('.ui-resizable-e').css({ width:'20px' });
+ $('#nav-sync').css({ right:'34px' });
+ barWidth=20;
+ }
var width = readCookie('width');
if (width) { restoreWidth(width); } else { resizeWidth(); }
resizeHeight();
@@ -76,22 +134,7 @@ function initResizable()
if (i>=0) window.location.hash=url.substr(i);
var _preventDefault = function(evt) { evt.preventDefault(); };
$("#splitbar").bind("dragstart", _preventDefault).bind("selectstart", _preventDefault);
- $(document).bind('touchmove',function(e){
- var device = navigator.userAgent.toLowerCase();
- var ios = device.match(/(iphone|ipod|ipad)/);
- if (ios) {
- try {
- var target = e.target;
- while (target) {
- if ($(target).css('-webkit-overflow-scrolling')=='touch') return;
- target = target.parentNode;
- }
- e.preventDefault();
- } catch(err) {
- e.preventDefault();
- }
- }
- });
+ $(".ui-resizable-handle").dblclick(collapseExpand);
+ $(window).on('load',resizeHeight);
}
-
-
+/* @license-end */
diff --git a/search/all_0.html b/search/all_0.html
index d54e0bd..a34319f 100644
--- a/search/all_0.html
+++ b/search/all_0.html
@@ -1,7 +1,7 @@
-
+
-
+
@@ -11,15 +11,25 @@
object is the parent of the search bar */
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 36px;
+ margin-right: 1em;
+}
+
/*---------------- Search filter selection */
#MSearchSelectWindow {
@@ -102,7 +85,7 @@
left: 0; top: 0;
border: 1px solid #90A5CE;
background-color: #F9FAFC;
- z-index: 1;
+ z-index: 10001;
padding-top: 4px;
padding-bottom: 4px;
-moz-border-radius: 4px;
@@ -165,6 +148,7 @@ iframe#MSearchResults {
left: 0; top: 0;
border: 1px solid #000;
background-color: #EEF1F7;
+ z-index:10000;
}
/* ----------------------------------- */
diff --git a/search/search.js b/search/search.js
index dedce3b..92b6094 100644
--- a/search/search.js
+++ b/search/search.js
@@ -1,3 +1,27 @@
+/*
+ @licstart The following is the entire license notice for the JavaScript code in this file.
+
+ The MIT License (MIT)
+
+ Copyright (C) 1997-2020 by Dimitri van Heesch
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ and associated documentation files (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ @licend The above is the entire license notice for the JavaScript code in this file
+ */
function convertToId(search)
{
var result = '';
@@ -177,10 +201,9 @@ function SearchBox(name, resultsPath, inFrame, label)
}
return;
}
- else if (window.frames.MSearchResults.searchResults)
+ else
{
- var elem = window.frames.MSearchResults.searchResults.NavNext(0);
- if (elem) elem.focus();
+ window.frames.MSearchResults.postMessage("take_focus", "*");
}
}
else if (e.keyCode==27) // Escape out of the search field
@@ -341,7 +364,7 @@ function SearchBox(name, resultsPath, inFrame, label)
if (domPopupSearchResultsWindow.style.display!='block')
{
var domSearchBox = this.DOMSearchBox();
- this.DOMSearchClose().style.display = 'inline';
+ this.DOMSearchClose().style.display = 'inline-block';
if (this.insideFrame)
{
var domPopupSearchResults = this.DOMPopupSearchResults();
@@ -788,4 +811,4 @@ function init_search()
}
searchBox.OnSelectItem(0);
}
-
+/* @license-end */
diff --git a/search/search_l.png b/search/search_l.png
index c872f4d..fd5f7da 100644
Binary files a/search/search_l.png and b/search/search_l.png differ
diff --git a/search/search_r.png b/search/search_r.png
index 97ee8b4..1af5d21 100644
Binary files a/search/search_r.png and b/search/search_r.png differ
diff --git a/search/variables_0.html b/search/variables_0.html
index 3835278..2edd111 100644
--- a/search/variables_0.html
+++ b/search/variables_0.html
@@ -1,7 +1,7 @@
-
+
-
+
@@ -11,15 +11,25 @@
14 * UNIX_TIMESTAMP gives the UNIX timestamp (unsigned long integer of seconds since 1st Jan 1970) of compilation from macros using the compiler defined __TIME__ macro.
15 * This should include Gregorian calendar leap days, in particular the 29ths of February, 100 and 400 years modulo leaps.
16 *
17 * Careful: __TIME__ is the local time of the computer, NOT the UTC time in general!
14 * UNIX_TIMESTAMP gives the UNIX timestamp (unsigned long integer of seconds since 1st Jan 1970) of compilation from macros using the compiler defined __TIME__ macro.
+
15 * This should include Gregorian calendar leap days, in particular the 29ths of February, 100 and 400 years modulo leaps.
+
16 *
+
17 * Careful: __TIME__ is the local time of the computer, NOT the UTC time in general!