refactored a bit, need to refactor more to merge SSLClientImpl with SSLClient to cut down flash footprint and code footprint
This commit is contained in:
parent
bd890ae834
commit
843d19bf6c
4 changed files with 45 additions and 43 deletions
|
@ -59,6 +59,9 @@ Some ideas that didn't quite fit in the API documentation.
|
||||||
|
|
||||||
SSLClient uses BearSSL's [minimal x509 verification engine](link-me) 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](./TrustAnchors.md) for more details on this component of SSLClient.
|
SSLClient uses BearSSL's [minimal x509 verification engine](link-me) 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](./TrustAnchors.md) for more details on this component of SSLClient.
|
||||||
|
|
||||||
|
### Session Caching
|
||||||
|
|
||||||
|
|
||||||
### Cipher Support
|
### Cipher Support
|
||||||
|
|
||||||
SSLClient supports only TLS1.2 and the ciphers listed in [this file under `suites[]`](./src/TLS12_only_profile) by default, 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](./src/bearssl/src/ssl). To do this, edit `SSLClientImpl::SSLClientImpl` to change these lines:
|
SSLClient supports only TLS1.2 and the ciphers listed in [this file under `suites[]`](./src/TLS12_only_profile) by default, 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](./src/bearssl/src/ssl). To do this, edit `SSLClientImpl::SSLClientImpl` to change these lines:
|
||||||
|
|
|
@ -75,7 +75,7 @@ class SSLClient : public SSLClientImpl {
|
||||||
* amount past that will require special modification of this library, and
|
* amount past that will require special modification of this library, and
|
||||||
* assumes you know what you are doing.
|
* assumes you know what you are doing.
|
||||||
*/
|
*/
|
||||||
static_assert(std::is_base_of<Client, C>::value, "C must be a Client Class!");
|
static_assert(std::is_base_of<Client, C>::value, "SSLClient can only accept a type with base class Client!");
|
||||||
static_assert(SessionCache > 0 && SessionCache < 255, "There can be no less than one and no more than 255 sessions in the cache!");
|
static_assert(SessionCache > 0 && SessionCache < 255, "There can be no less than one and no more than 255 sessions in the cache!");
|
||||||
static_assert(SessionCache <= 3, "You need to decrease the size of m_iobuf in order to have more than 3 sessions at once, otherwise memory issues will occur.");
|
static_assert(SessionCache <= 3, "You need to decrease the size of m_iobuf in order to have more than 3 sessions at once, otherwise memory issues will occur.");
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ public:
|
||||||
* the handshake and finish the connection. This function runs until the SSL
|
* the handshake and finish the connection. This function runs until the SSL
|
||||||
* handshake succeeds or fails, as found in most Arduino libraries.
|
* handshake succeeds or fails, as found in most Arduino libraries.
|
||||||
*
|
*
|
||||||
* The implementation for this function can be found in SSLClientImpl::connect(IPAddress, uint16_t)
|
* The implementation for this function can be found in SSLClientImpl::connect_impl(IPAddress, uint16_t)
|
||||||
*
|
*
|
||||||
* @pre The underlying client object (passed in through the ctor) in a non-
|
* @pre The underlying client object (passed in through the ctor) in a non-
|
||||||
* error state, and must be able to access the server being connected to.
|
* error state, and must be able to access the server being connected to.
|
||||||
|
@ -151,7 +151,7 @@ public:
|
||||||
* @param port the port to connect to
|
* @param port the port to connect to
|
||||||
* @returns 1 if success, 0 if failure (as found in EthernetClient)
|
* @returns 1 if success, 0 if failure (as found in EthernetClient)
|
||||||
*/
|
*/
|
||||||
// virtual int connect(IPAddress ip, uint16_t port) = 0;
|
virtual int connect(IPAddress ip, uint16_t port) { return connect_impl(ip, port); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Connect over SSL using connect(ip, port), using a DNS lookup to
|
* @brief Connect over SSL using connect(ip, port), using a DNS lookup to
|
||||||
|
@ -186,7 +186,7 @@ public:
|
||||||
* Because of all these factors, it is generally prudent to assume the
|
* Because of all these factors, it is generally prudent to assume the
|
||||||
* connection will not be resumed, and go from there.
|
* connection will not be resumed, and go from there.
|
||||||
*
|
*
|
||||||
* The implementation for this function can be found in SSLClientImpl::connect(const char*, uint16_t)
|
* The implementation for this function can be found in SSLClientImpl::connect_impl(const char*, uint16_t)
|
||||||
*
|
*
|
||||||
* @pre The underlying client object (passed in through the ctor) in a non-
|
* @pre The underlying client object (passed in through the ctor) in a non-
|
||||||
* error state, and must be able to access the server being connected to.
|
* error state, and must be able to access the server being connected to.
|
||||||
|
@ -205,10 +205,10 @@ public:
|
||||||
* @param port the port to connect to (443)
|
* @param port the port to connect to (443)
|
||||||
* @returns 1 of success, 0 if failure (as found in EthernetClient).
|
* @returns 1 of success, 0 if failure (as found in EthernetClient).
|
||||||
*/
|
*/
|
||||||
// virtual int connect(const char *host, uint16_t port) = 0;
|
virtual int connect(const char *host, uint16_t port) { return connect_impl(host, port); }
|
||||||
|
|
||||||
/** @see SSLClient::write(uint8_t*, size_t) */
|
/** @see SSLClient::write(uint8_t*, size_t) */
|
||||||
// virtual size_t write(uint8_t b) = 0;
|
virtual size_t write(uint8_t b) { return write_impl(&b, 1); }
|
||||||
/**
|
/**
|
||||||
* @brief Write some bytes to the SSL connection
|
* @brief Write some bytes to the SSL connection
|
||||||
*
|
*
|
||||||
|
@ -243,7 +243,7 @@ public:
|
||||||
* If you would like to trigger a network write manually without using the SSLClient::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.
|
* you can also call SSLClient::flush, which will write all data and return when finished.
|
||||||
*
|
*
|
||||||
* The implementation for this function can be found in SSLClientImpl::write(const uint8_t*, size_t)
|
* The implementation for this function can be found in SSLClientImpl::write_impl(const uint8_t*, size_t)
|
||||||
*
|
*
|
||||||
* @pre The socket and SSL layer must be connected, meaning SSLClient::connected must be true.
|
* @pre The socket and SSL layer must be connected, meaning SSLClient::connected must be true.
|
||||||
* @pre BearSSL must not be waiting for the recipt of user data (if it is, there is
|
* @pre BearSSL must not be waiting for the recipt of user data (if it is, there is
|
||||||
|
@ -254,7 +254,7 @@ public:
|
||||||
* @returns The number of bytes copied to the buffer (size), or zero if the BearSSL engine
|
* @returns The number of bytes copied to the buffer (size), or zero if the BearSSL engine
|
||||||
* fails to become ready for writing data.
|
* fails to become ready for writing data.
|
||||||
*/
|
*/
|
||||||
// virtual size_t write(const uint8_t *buf, size_t size) = 0;
|
virtual size_t write(const uint8_t *buf, size_t size) { return write_impl(buf, size); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the number of bytes availible to read from the SSL Socket
|
* @brief Returns the number of bytes availible to read from the SSL Socket
|
||||||
|
@ -274,10 +274,13 @@ public:
|
||||||
* @returns The number of bytes availible (can be zero), or zero if any of the pre
|
* @returns The number of bytes availible (can be zero), or zero if any of the pre
|
||||||
* conditions aren't satisfied.
|
* conditions aren't satisfied.
|
||||||
*/
|
*/
|
||||||
//virtual int available() = 0;
|
virtual int available() { return available_impl(); }
|
||||||
|
|
||||||
/** @see SSLClient::read(uint8_t*, size_t) */
|
/**
|
||||||
//virtual int read() = 0;
|
* @brief Read a single byte, or -1 if none is available.
|
||||||
|
* @see SSLClient::read(uint8_t*, size_t)
|
||||||
|
*/
|
||||||
|
virtual int read() { uint8_t read_val; return read(&read_val, 1) > 0 ? read_val : -1; };
|
||||||
/**
|
/**
|
||||||
* @brief Read size bytes from the SSL socket buffer, copying them into *buf, and return the number of bytes read.
|
* @brief Read size bytes from the SSL socket buffer, copying them into *buf, and return the number of bytes read.
|
||||||
*
|
*
|
||||||
|
@ -314,7 +317,7 @@ public:
|
||||||
* Often times there are other ways to get data that we need that do the same thing,
|
* Often times there are other ways to get data that we need that do the same thing,
|
||||||
* and these other ways may offer smaller and more managable response payloads.
|
* and these other ways may offer smaller and more managable response payloads.
|
||||||
*
|
*
|
||||||
* The implementation for this function can be found in SSLClientImpl::read(uint8_t*, size_t)
|
* The implementation for this function can be found in SSLClientImpl::read_impl(uint8_t*, size_t)
|
||||||
*
|
*
|
||||||
* @pre SSLClient::available must be >0
|
* @pre SSLClient::available must be >0
|
||||||
*
|
*
|
||||||
|
@ -323,7 +326,7 @@ public:
|
||||||
*
|
*
|
||||||
* @returns The number of bytes copied (<= size), or -1 if the preconditions are not satisfied.
|
* @returns The number of bytes copied (<= size), or -1 if the preconditions are not satisfied.
|
||||||
*/
|
*/
|
||||||
//virtual int read(uint8_t *buf, size_t size) = 0;
|
virtual int read(uint8_t *buf, size_t size) { return read_impl(buf, size); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief view the first byte of the buffer, without removing it from the SSLClient Buffer
|
* @brief view the first byte of the buffer, without removing it from the SSLClient Buffer
|
||||||
|
@ -332,7 +335,7 @@ public:
|
||||||
* @returns The first byte recieved, or -1 if the preconditions are not satisfied (warning:
|
* @returns The first byte recieved, or -1 if the preconditions are not satisfied (warning:
|
||||||
* do not use if your data may be -1, as the return value is ambigious)
|
* do not use if your data may be -1, as the return value is ambigious)
|
||||||
*/
|
*/
|
||||||
//virtual int peek() = 0;
|
virtual int peek() { return peek_impl(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Force writing the buffered bytes from SSLClient::write to the network.
|
* @brief Force writing the buffered bytes from SSLClient::write to the network.
|
||||||
|
@ -340,7 +343,7 @@ public:
|
||||||
* an explanation of how writing with SSLClient works, please see SSLCLient::write.
|
* an explanation of how writing with SSLClient works, please see SSLCLient::write.
|
||||||
* The implementation for this function can be found in SSLClientImpl::flush.
|
* The implementation for this function can be found in SSLClientImpl::flush.
|
||||||
*/
|
*/
|
||||||
//virtual void flush() = 0;
|
virtual void flush() { return flush_impl(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Close the connection
|
* @brief Close the connection
|
||||||
|
@ -349,7 +352,7 @@ public:
|
||||||
* error was encountered previously, this function will simply call m_client::stop.
|
* error was encountered previously, this function will simply call m_client::stop.
|
||||||
* The implementation for this function can be found in SSLClientImpl::peek.
|
* The implementation for this function can be found in SSLClientImpl::peek.
|
||||||
*/
|
*/
|
||||||
//virtual void stop() = 0;
|
virtual void stop() { return stop_impl(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if the device is connected.
|
* @brief Check if the device is connected.
|
||||||
|
@ -358,11 +361,11 @@ public:
|
||||||
* polling--both functions send and recieve data to the Client device, however SSLClient::availible
|
* polling--both functions send and recieve data to the Client device, however SSLClient::availible
|
||||||
* has some delays built in to protect the Client device from being polled too frequently.
|
* has some delays built in to protect the Client device from being polled too frequently.
|
||||||
*
|
*
|
||||||
* The implementation for this function can be found in SSLClientImpl::connected.
|
* The implementation for this function can be found in SSLClientImpl::connected_impl.
|
||||||
*
|
*
|
||||||
* @returns 1 if connected, 0 if not
|
* @returns 1 if connected, 0 if not
|
||||||
*/
|
*/
|
||||||
//virtual uint8_t connected() = 0;
|
virtual uint8_t connected() { return connected_impl(); }
|
||||||
|
|
||||||
//========================================
|
//========================================
|
||||||
//= Functions Not in the Client Interface
|
//= Functions Not in the Client Interface
|
||||||
|
@ -456,7 +459,7 @@ SSLSession& SSLClient<C, SessionCache>::getSession(const char* host, const IPAdd
|
||||||
if (temp_index == m_index && ++m_index >= SessionCache) m_index = 0;
|
if (temp_index == m_index && ++m_index >= SessionCache) m_index = 0;
|
||||||
// return the pointed to value
|
// return the pointed to value
|
||||||
m_info("Using session index: ", func_name);
|
m_info("Using session index: ", func_name);
|
||||||
Serial.println(temp_index);
|
m_info(temp_index, func_name);
|
||||||
return m_sessions[temp_index];
|
return m_sessions[temp_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ SSLClientImpl::SSLClientImpl(Client *client, const br_x509_trust_anchor *trust_a
|
||||||
}
|
}
|
||||||
|
|
||||||
/* see SSLClientImpl.h*/
|
/* see SSLClientImpl.h*/
|
||||||
int SSLClientImpl::connect(IPAddress ip, uint16_t port) {
|
int SSLClientImpl::connect_impl(IPAddress ip, uint16_t port) {
|
||||||
const char* func_name = __func__;
|
const char* func_name = __func__;
|
||||||
// connection check
|
// connection check
|
||||||
if (m_client->connected()) {
|
if (m_client->connected()) {
|
||||||
|
@ -94,7 +94,7 @@ int SSLClientImpl::connect(IPAddress ip, uint16_t port) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* see SSLClientImpl.h*/
|
/* see SSLClientImpl.h*/
|
||||||
int SSLClientImpl::connect(const char *host, uint16_t port) {
|
int SSLClientImpl::connect_impl(const char *host, uint16_t port) {
|
||||||
const char* func_name = __func__;
|
const char* func_name = __func__;
|
||||||
// connection check
|
// connection check
|
||||||
if (m_client->connected()) {
|
if (m_client->connected()) {
|
||||||
|
@ -127,7 +127,7 @@ int SSLClientImpl::connect(const char *host, uint16_t port) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** see SSLClientImpl.h*/
|
/** see SSLClientImpl.h*/
|
||||||
size_t SSLClientImpl::write(const uint8_t *buf, size_t size) {
|
size_t SSLClientImpl::write_impl(const uint8_t *buf, size_t size) {
|
||||||
const char* func_name = __func__;
|
const char* func_name = __func__;
|
||||||
// check if the socket is still open and such
|
// check if the socket is still open and such
|
||||||
if (!m_soft_connected(func_name)) return 0;
|
if (!m_soft_connected(func_name)) return 0;
|
||||||
|
@ -164,7 +164,7 @@ size_t SSLClientImpl::write(const uint8_t *buf, size_t size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** see SSLClientImpl.h*/
|
/** see SSLClientImpl.h*/
|
||||||
int SSLClientImpl::available() {
|
int SSLClientImpl::available_impl() {
|
||||||
const char* func_name = __func__;
|
const char* func_name = __func__;
|
||||||
// connection check
|
// connection check
|
||||||
if (!m_soft_connected(func_name)) return 0;
|
if (!m_soft_connected(func_name)) return 0;
|
||||||
|
@ -185,7 +185,7 @@ int SSLClientImpl::available() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** see SSLClientImpl.h */
|
/** see SSLClientImpl.h */
|
||||||
int SSLClientImpl::read(uint8_t *buf, size_t size) {
|
int SSLClientImpl::read_impl(uint8_t *buf, size_t size) {
|
||||||
// check that the engine is ready to read
|
// check that the engine is ready to read
|
||||||
if (available() <= 0) return -1;
|
if (available() <= 0) return -1;
|
||||||
// read the buffer, send the ack, and return the bytes read
|
// read the buffer, send the ack, and return the bytes read
|
||||||
|
@ -200,7 +200,7 @@ int SSLClientImpl::read(uint8_t *buf, size_t size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** see SSLClientImpl.h */
|
/** see SSLClientImpl.h */
|
||||||
int SSLClientImpl::peek() {
|
int SSLClientImpl::peek_impl() {
|
||||||
// check that the engine is ready to read
|
// check that the engine is ready to read
|
||||||
if (available() <= 0) return -1;
|
if (available() <= 0) return -1;
|
||||||
// read the buffer, send the ack, and return the bytes read
|
// read the buffer, send the ack, and return the bytes read
|
||||||
|
@ -212,7 +212,7 @@ int SSLClientImpl::peek() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** see SSLClientImpl.h*/
|
/** see SSLClientImpl.h*/
|
||||||
void SSLClientImpl::flush() {
|
void SSLClientImpl::flush_impl() {
|
||||||
// trigger a flush, incase there's any leftover data
|
// trigger a flush, incase there's any leftover data
|
||||||
br_ssl_engine_flush(&m_sslctx.eng, 0);
|
br_ssl_engine_flush(&m_sslctx.eng, 0);
|
||||||
// run until application data is ready for pickup
|
// run until application data is ready for pickup
|
||||||
|
@ -220,7 +220,7 @@ void SSLClientImpl::flush() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** see SSLClientImpl.h*/
|
/** see SSLClientImpl.h*/
|
||||||
void SSLClientImpl::stop() {
|
void SSLClientImpl::stop_impl() {
|
||||||
// tell the SSL connection to gracefully close
|
// tell the SSL connection to gracefully close
|
||||||
br_ssl_engine_close(&m_sslctx.eng);
|
br_ssl_engine_close(&m_sslctx.eng);
|
||||||
// if the engine isn't closed, and the socket is still open
|
// if the engine isn't closed, and the socket is still open
|
||||||
|
@ -240,7 +240,7 @@ void SSLClientImpl::stop() {
|
||||||
m_client->stop();
|
m_client->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t SSLClientImpl::connected() {
|
uint8_t SSLClientImpl::connected_impl() {
|
||||||
const char* func_name = __func__;
|
const char* func_name = __func__;
|
||||||
// check all of the error cases
|
// check all of the error cases
|
||||||
const auto c_con = m_client->connected();
|
const auto c_con = m_client->connected();
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
*
|
*
|
||||||
* If SSLClient encounters an error, it will generally output
|
* If SSLClient encounters an error, it will generally output
|
||||||
* logs into the serial moniter. If you need a way of programmatically
|
* logs into the serial moniter. If you need a way of programmatically
|
||||||
* checking the errors, you can do so with SSLCLient.getWriteError(),
|
* checking the errors, you can do so with SSLClient::getWriteError(),
|
||||||
* which will return one of these values.
|
* which will return one of these values.
|
||||||
*/
|
*/
|
||||||
enum Error {
|
enum Error {
|
||||||
|
@ -71,7 +71,7 @@ enum DebugLevel {
|
||||||
* On error, any function in this class will terminate the socket.
|
* On error, any function in this class will terminate the socket.
|
||||||
* TODO: Write what this is */
|
* TODO: Write what this is */
|
||||||
|
|
||||||
class SSLClientImpl : public Client {
|
class SSLClientImpl: public Client {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief initializes SSL contexts for bearSSL
|
* @brief initializes SSL contexts for bearSSL
|
||||||
|
@ -102,27 +102,23 @@ public:
|
||||||
//============================================
|
//============================================
|
||||||
|
|
||||||
/** @see SSLClient::connect(IPAddress, uint16_t) */
|
/** @see SSLClient::connect(IPAddress, uint16_t) */
|
||||||
virtual int connect(IPAddress ip, uint16_t port);
|
int connect_impl(IPAddress ip, uint16_t port);
|
||||||
/** @see SSLClient::connect(const char*, uint16_t) */
|
/** @see SSLClient::connect(const char*, uint16_t) */
|
||||||
virtual int connect(const char *host, uint16_t port);
|
int connect_impl(const char *host, uint16_t port);
|
||||||
/** @see SSLClient::write(const uint8_t*, size_t) */
|
/** @see SSLClient::write(const uint8_t*, size_t) */
|
||||||
virtual size_t write(uint8_t b) { return write(&b, 1); }
|
size_t write_impl(const uint8_t *buf, size_t size);
|
||||||
/** @see SSLClient::write(const uint8_t*, size_t) */
|
|
||||||
virtual size_t write(const uint8_t *buf, size_t size);
|
|
||||||
/** @see SSLClient::available */
|
/** @see SSLClient::available */
|
||||||
virtual int available();
|
int available_impl();
|
||||||
/** @see SSLClient::read(uint8_t*, size_t) */
|
/** @see SSLClient::read(uint8_t*, size_t) */
|
||||||
virtual int read() { uint8_t read_val; return read(&read_val, 1) > 0 ? read_val : -1; }
|
int read_impl(uint8_t *buf, size_t size);
|
||||||
/** @see SSLClient::read(uint8_t*, size_t) */
|
|
||||||
virtual int read(uint8_t *buf, size_t size);
|
|
||||||
/** @see SSLClient::peek */
|
/** @see SSLClient::peek */
|
||||||
virtual int peek();
|
int peek_impl();
|
||||||
/** @see SSLClient::flush */
|
/** @see SSLClient::flush */
|
||||||
virtual void flush();
|
void flush_impl();
|
||||||
/** @see SSLClient::stop */
|
/** @see SSLClient::stop */
|
||||||
virtual void stop();
|
void stop_impl();
|
||||||
/** @see SSLClient::connected */
|
/** @see SSLClient::connected */
|
||||||
virtual uint8_t connected();
|
uint8_t connected_impl();
|
||||||
|
|
||||||
//============================================
|
//============================================
|
||||||
//= Functions implemented in SSLClient.h
|
//= Functions implemented in SSLClient.h
|
||||||
|
|
Loading…
Reference in a new issue