implemented IP-based session caching
This commit is contained in:
parent
d59faf1f7d
commit
ac03dc943a
3 changed files with 43 additions and 22 deletions
|
@ -108,20 +108,18 @@ public:
|
||||||
set_client(&m_client);
|
set_client(&m_client);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* The special functions most clients have are below
|
* The special functions most clients have are below
|
||||||
* Most of them smply pass through
|
* Most of them smply pass through
|
||||||
*/
|
*/
|
||||||
virtual int availableForWrite(void) { return m_client.availableForWrite(); }
|
|
||||||
virtual operator bool() { return connected() > 0; }
|
virtual operator bool() { return connected() > 0; }
|
||||||
virtual bool operator==(const bool value) { return bool() == value; }
|
virtual bool operator==(const bool value) { return bool() == value; }
|
||||||
virtual bool operator!=(const bool value) { return bool() != value; }
|
virtual bool operator!=(const bool value) { return bool() != value; }
|
||||||
virtual bool operator==(const C& rhs) { return m_client == rhs; }
|
virtual bool operator==(const C& rhs) { return m_client == rhs; }
|
||||||
virtual bool operator!=(const C& rhs) { return m_client != rhs; }
|
virtual bool operator!=(const C& rhs) { return m_client != rhs; }
|
||||||
virtual uint16_t localPort() { return m_client.localPort(); }
|
virtual uint16_t localPort() { return std::is_member_function_pointer<decltype(&C::localPort)>::value ? m_client.localPort() : 0; }
|
||||||
virtual IPAddress remoteIP() { return m_client.remoteIP(); }
|
virtual IPAddress remoteIP() { return std::is_member_function_pointer<decltype(&C::remoteIP)>::value ? m_client.remoteIP() : INADDR_NONE; }
|
||||||
virtual uint16_t remotePort() { return m_client.remotePort(); }
|
virtual uint16_t remotePort() { return std::is_member_function_pointer<decltype(&C::remotePort)>::value ? m_client.remotePort() : 0; }
|
||||||
virtual void setConnectionTimeout(uint16_t timeout) { m_client.setConnectionTimeout(timeout); }
|
|
||||||
|
|
||||||
//! get the client object
|
//! get the client object
|
||||||
C& getClient() { return m_client; }
|
C& getClient() { return m_client; }
|
||||||
|
|
|
@ -21,18 +21,18 @@
|
||||||
#include "SSLClient.h"
|
#include "SSLClient.h"
|
||||||
|
|
||||||
/** see SSLClientImpl.h */
|
/** see SSLClientImpl.h */
|
||||||
SSLClientImpl::SSLClientImpl(Client* client, const br_x509_trust_anchor *trust_anchors, const size_t trust_anchors_num, const int analog_pin, const bool debug)
|
SSLClientImpl::SSLClientImpl(Client *client, const br_x509_trust_anchor *trust_anchors,
|
||||||
|
const size_t trust_anchors_num, const int analog_pin, const bool debug)
|
||||||
: m_client(client)
|
: m_client(client)
|
||||||
, m_trust_anchors(trust_anchors)
|
, m_trust_anchors(trust_anchors)
|
||||||
, m_trust_anchors_num(trust_anchors_num)
|
, m_trust_anchors_num(trust_anchors_num)
|
||||||
, m_analog_pin(analog_pin)
|
, m_analog_pin(analog_pin)
|
||||||
, m_debug(debug)
|
, m_debug(debug)
|
||||||
, m_write_idx(0) {
|
, m_write_idx(0)
|
||||||
|
, m_session() {
|
||||||
|
|
||||||
// zero the iobuf just in case it's still garbage
|
// zero the iobuf just in case it's still garbage
|
||||||
memset(m_iobuf, 0, sizeof m_iobuf);
|
memset(m_iobuf, 0, sizeof m_iobuf);
|
||||||
// zero the session parameters for similar reason
|
|
||||||
memset(&m_ses_param, 0, sizeof m_ses_param);
|
|
||||||
// initlalize the various bearssl libraries so they're ready to go when we connect
|
// initlalize the various bearssl libraries so they're ready to go when we connect
|
||||||
br_client_init_TLS12_only(&m_sslctx, &m_x509ctx, m_trust_anchors, m_trust_anchors_num);
|
br_client_init_TLS12_only(&m_sslctx, &m_x509ctx, m_trust_anchors, m_trust_anchors_num);
|
||||||
// br_ssl_client_init_full(&m_sslctx, &m_x509ctx, m_trust_anchors, m_trust_anchors_num);
|
// br_ssl_client_init_full(&m_sslctx, &m_x509ctx, m_trust_anchors, m_trust_anchors_num);
|
||||||
|
@ -62,16 +62,25 @@ int SSLClientImpl::connect(IPAddress ip, uint16_t port) {
|
||||||
int SSLClientImpl::connect(const char *host, uint16_t port) {
|
int SSLClientImpl::connect(const char *host, uint16_t port) {
|
||||||
// reset indexs for saftey
|
// reset indexs for saftey
|
||||||
m_write_idx = 0;
|
m_write_idx = 0;
|
||||||
|
// first, if we have a session, check if we're trying to resolve the same host
|
||||||
|
// as before
|
||||||
|
bool connect_ok;
|
||||||
|
if (m_session.is_valid_session()
|
||||||
|
&& strcmp(m_session.get_hostname(), host) == 0) {
|
||||||
|
// if so, then connect using the stored session
|
||||||
|
m_print("Connecting using a cached IP");
|
||||||
|
connect_ok = m_client->connect(m_session.get_ip(), port);
|
||||||
|
}
|
||||||
|
// else connect with the provided hostname
|
||||||
|
else connect_ok = m_client->connect(host, port);
|
||||||
// first we need our hidden client member to negotiate the socket for us,
|
// first we need our hidden client member to negotiate the socket for us,
|
||||||
// since most times socket functionality is implemented in hardeware.
|
// since most times socket functionality is implemented in hardeware.
|
||||||
if (!m_client->connect(host, port)) {
|
if (!connect_ok) {
|
||||||
m_print("Error: Failed to connect using m_client");
|
m_print("Error: Failed to connect using m_client");
|
||||||
setWriteError(SSL_CLIENT_CONNECT_FAIL);
|
setWriteError(SSL_CLIENT_CONNECT_FAIL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
m_print("Base ethernet client connected!");
|
m_print("Base ethernet client connected!");
|
||||||
// clear the write error
|
|
||||||
setWriteError(SSL_OK);
|
|
||||||
// start ssl!
|
// start ssl!
|
||||||
return m_start_ssl(host);
|
return m_start_ssl(host);
|
||||||
}
|
}
|
||||||
|
@ -221,6 +230,8 @@ uint8_t SSLClientImpl::connected() {
|
||||||
|
|
||||||
/** see SSLClientImpl.h */
|
/** see SSLClientImpl.h */
|
||||||
int SSLClientImpl::m_start_ssl(const char* host) {
|
int SSLClientImpl::m_start_ssl(const char* host) {
|
||||||
|
// clear the write error
|
||||||
|
setWriteError(SSL_OK);
|
||||||
// get some random data by reading the analog pin we've been handed
|
// get some random data by reading the analog pin we've been handed
|
||||||
// we want 128 bits to be safe, as recommended by the bearssl docs
|
// we want 128 bits to be safe, as recommended by the bearssl docs
|
||||||
uint8_t rng_seeds[16];
|
uint8_t rng_seeds[16];
|
||||||
|
@ -228,9 +239,9 @@ int SSLClientImpl::m_start_ssl(const char* host) {
|
||||||
for (uint8_t i = 0; i < sizeof rng_seeds; i++) rng_seeds[i] = static_cast<uint8_t>(analogRead(m_analog_pin));
|
for (uint8_t i = 0; i < sizeof rng_seeds; i++) rng_seeds[i] = static_cast<uint8_t>(analogRead(m_analog_pin));
|
||||||
br_ssl_engine_inject_entropy(&m_sslctx.eng, rng_seeds, sizeof rng_seeds);
|
br_ssl_engine_inject_entropy(&m_sslctx.eng, rng_seeds, sizeof rng_seeds);
|
||||||
// inject session parameters for faster reconnection, if we have any
|
// inject session parameters for faster reconnection, if we have any
|
||||||
if(m_ses_param.session_id_len > 0) {
|
if(m_session.is_valid_session()) {
|
||||||
|
br_ssl_engine_set_session_parameters(&m_sslctx.eng, m_session.to_br_session());
|
||||||
m_print("Set session!");
|
m_print("Set session!");
|
||||||
br_ssl_engine_set_session_parameters(&m_sslctx.eng, &m_ses_param);
|
|
||||||
}
|
}
|
||||||
// reset the engine, but make sure that it reset successfully
|
// reset the engine, but make sure that it reset successfully
|
||||||
int ret = br_ssl_client_reset(&m_sslctx, host, 1);
|
int ret = br_ssl_client_reset(&m_sslctx, host, 1);
|
||||||
|
@ -249,14 +260,16 @@ int SSLClientImpl::m_start_ssl(const char* host) {
|
||||||
}
|
}
|
||||||
// all good to go! the SSL socket should be up and running
|
// all good to go! the SSL socket should be up and running
|
||||||
// debug print the session parameters to see if they exist
|
// debug print the session parameters to see if they exist
|
||||||
br_ssl_engine_get_session_parameters(&m_sslctx.eng, &m_ses_param);
|
br_ssl_engine_get_session_parameters(&m_sslctx.eng, m_session.to_br_session());
|
||||||
|
// set the hostname and ip in the session as well
|
||||||
|
m_session.set_parameters(remoteIP(), host);
|
||||||
m_print("Session:");
|
m_print("Session:");
|
||||||
for (uint8_t i = 0; i < m_ses_param.session_id_len; i++) {
|
for (uint8_t i = 0; i < m_session.session_id_len; i++) {
|
||||||
Serial.print(", 0x");
|
Serial.print(", 0x");
|
||||||
Serial.print(m_ses_param.session_id[i], HEX);
|
Serial.print(m_session.session_id[i], HEX);
|
||||||
}
|
}
|
||||||
Serial.println();
|
Serial.println();
|
||||||
Serial.println(m_ses_param.cipher_suite, HEX);
|
Serial.println(m_session.cipher_suite, HEX);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "bearssl.h"
|
#include "bearssl.h"
|
||||||
#include "Client.h"
|
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
|
#include "Client.h"
|
||||||
|
#include "SSLSession.h"
|
||||||
|
|
||||||
#ifndef SSLClientImpl_H_
|
#ifndef SSLClientImpl_H_
|
||||||
#define SSLClientImpl_H_
|
#define SSLClientImpl_H_
|
||||||
|
@ -44,9 +45,13 @@ public:
|
||||||
* line utility. For more information see the samples or bearssl.org
|
* line utility. For more information see the samples or bearssl.org
|
||||||
* @param trust_anchors_num The number of trust anchors stored
|
* @param trust_anchors_num The number of trust anchors stored
|
||||||
* @param analog_pin An analog pin to pull random bytes from, used in seeding the RNG
|
* @param analog_pin An analog pin to pull random bytes from, used in seeding the RNG
|
||||||
|
* @param get_remote_ip Function pointer to get the remote ip from the client. We
|
||||||
|
* need this value since the Client abstract class has no remoteIP() function,
|
||||||
|
* however most of the arduino internet client implementations do.
|
||||||
* @param debug whether to enable or disable debug logging, must be constexpr
|
* @param debug whether to enable or disable debug logging, must be constexpr
|
||||||
*/
|
*/
|
||||||
explicit SSLClientImpl(Client* client, const br_x509_trust_anchor *trust_anchors, const size_t trust_anchors_num, const int analog_pin, const bool debug = true);
|
explicit SSLClientImpl(Client* client, const br_x509_trust_anchor *trust_anchors,
|
||||||
|
const size_t trust_anchors_num, const int analog_pin, const bool debug = true);
|
||||||
/** Dtor is implicit since unique_ptr handles it fine */
|
/** Dtor is implicit since unique_ptr handles it fine */
|
||||||
|
|
||||||
/** functions specific to the EthernetClient which I'll have to override */
|
/** functions specific to the EthernetClient which I'll have to override */
|
||||||
|
@ -111,6 +116,10 @@ public:
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
virtual uint8_t connected();
|
virtual uint8_t connected();
|
||||||
|
|
||||||
|
// stub virtual functions to get things from the client
|
||||||
|
virtual uint16_t localPort() = 0;
|
||||||
|
virtual IPAddress remoteIP() = 0;
|
||||||
|
virtual uint16_t remotePort() = 0;
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* @brief set the pointer to the Client class that we wil use
|
* @brief set the pointer to the Client class that we wil use
|
||||||
|
@ -120,6 +129,7 @@ protected:
|
||||||
* is critical that this function is called before anything else
|
* is critical that this function is called before anything else
|
||||||
*/
|
*/
|
||||||
void set_client(Client* c) { m_client = c; }
|
void set_client(Client* c) { m_client = c; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/** @brief debugging print function, only prints if m_debug is true */
|
/** @brief debugging print function, only prints if m_debug is true */
|
||||||
|
@ -174,7 +184,7 @@ private:
|
||||||
// weird timing issues
|
// weird timing issues
|
||||||
size_t m_write_idx;
|
size_t m_write_idx;
|
||||||
// store the last SSL session, so reconnection later is speedy fast
|
// store the last SSL session, so reconnection later is speedy fast
|
||||||
br_ssl_session_parameters m_ses_param;
|
SSLSession m_session;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SSLClientImpl_H_ */
|
#endif /* SSLClientImpl_H_ */
|
Loading…
Reference in a new issue