SSLClient  1.0
Add TLS 1.2 functionality to any network library.
SSLClient.h
Go to the documentation of this file.
1 /* Copyright 2019 OSU OPEnS Lab
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy of this
4  * software and associated documentation files (the "Software"), to deal in the Software
5  * without restriction, including without limitation the rights to use, copy, modify,
6  * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
7  * permit persons to whom the Software is furnished to do so, subject to the following
8  * conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in all
11  * copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
15  * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
16  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
18  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19  */
20 
21 #include <type_traits>
22 #include "Client.h"
23 #include "SSLClientImpl.h"
24 #include "SSLSession.h"
25 
26 #ifndef SSLClient_H_
27 #define SSLClient_H_
28 
34 template <class C, size_t SessionCache = 1>
35 class SSLClient : public SSLClientImpl {
36 /*
37  * static checks
38  * I'm a java developer, so I want to ensure that my inheritance is safe.
39  * These checks ensure that all the functions we use on class C are
40  * actually present on class C. It does this by checking that the
41  * class inherits from Client.
42  *
43  * Additionally, I ran into a lot of memory issues with large sessions caches.
44  * Since each session contains at max 352 bytes of memory, they eat of the
45  * stack quite quickly and can cause overflows. As a result, I have added a
46  * warning here to discourage the use of more than 3 sessions at a time. Any
47  * amount past that will require special modification of this library, and
48  * assumes you know what you are doing.
49  */
50 static_assert(std::is_base_of<Client, C>::value, "SSLClient can only accept a type with base class Client!");
51 static_assert(SessionCache > 0 && SessionCache < 255, "There can be no less than one and no more than 255 sessions in the cache!");
52 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.");
53 
54 public:
71  explicit SSLClient(const C& client, const br_x509_trust_anchor *trust_anchors, const size_t trust_anchors_num, const int analog_pin, const DebugLevel debug = SSL_WARN)
72  : SSLClientImpl(trust_anchors, trust_anchors_num, analog_pin, debug)
73  , m_client(client)
74  , m_sessions{SSLSession()}
75  {
76  // set the timeout to a reasonable number (it can always be changes later)
77  // SSL Connections take a really long time so we don't want to time out a legitimate thing
78  setTimeout(10 * 1000);
79  }
80 
81  //========================================
82  //= Functions implemented in SSLClientImpl
83  //========================================
84 
124  virtual int connect(IPAddress ip, uint16_t port) { return connect_impl(ip, port); }
125 
162  virtual int connect(const char *host, uint16_t port) { return connect_impl(host, port); }
163 
165  virtual size_t write(uint8_t b) { return write_impl(&b, 1); }
189  virtual size_t write(const uint8_t *buf, size_t size) { return write_impl(buf, size); }
190 
209  virtual int available() { return available_impl(); }
210 
215  virtual int read() { uint8_t read_val; return read(&read_val, 1) > 0 ? read_val : -1; };
237  virtual int read(uint8_t *buf, size_t size) { return read_impl(buf, size); }
238 
246  virtual int peek() { return peek_impl(); }
247 
254  virtual void flush() { return flush_impl(); }
255 
263  virtual void stop() { return stop_impl(); }
264 
276  virtual uint8_t connected() { return connected_impl(); }
277 
278  //========================================
279  //= Functions Not in the Client Interface
280  //========================================
281 
296  virtual SSLSession& getSession(const char* host, const IPAddress& addr) { return get_session_impl(host, addr); }
297 
306  virtual void removeSession(const char* host, const IPAddress& addr) { return remove_session_impl(host, addr); }
307 
312  virtual size_t getSessionCount() const { return SessionCache; }
313 
318  virtual operator bool() { return connected() > 0; }
320  virtual bool operator==(const bool value) { return bool() == value; }
322  virtual bool operator!=(const bool value) { return bool() != value; }
324  virtual bool operator==(const C& rhs) { return m_client == rhs; }
326  virtual bool operator!=(const C& rhs) { return m_client != rhs; }
328  virtual uint16_t localPort() {
329  if (std::is_member_function_pointer<decltype(&C::localPort)>::value) return m_client.localPort();
330  else {
331  m_warn("Client class has no localPort function, so localPort() will always return 0", __func__);
332  return 0;
333  }
334  }
336  virtual IPAddress remoteIP() {
337  if (std::is_member_function_pointer<decltype(&C::remoteIP)>::value) return m_client.remoteIP();
338  else {
339  m_warn("Client class has no remoteIP function, so remoteIP() will always return INADDR_NONE. This means that sessions caching will always be disabled.", __func__);
340  return INADDR_NONE;
341  }
342  }
344  virtual uint16_t remotePort() {
345  if (std::is_member_function_pointer<decltype(&C::remotePort)>::value) return m_client.remotePort();
346  else {
347  m_warn("Client class has no remotePort function, so remotePort() will always return 0", __func__);
348  return 0;
349  }
350  }
351 
353  C& getClient() { return m_client; }
354 
355 protected:
357  virtual Client& get_arduino_client() { return m_client; }
358  virtual const Client& get_arduino_client() const { return m_client; }
360  virtual SSLSession* get_session_array() { return m_sessions; }
361  virtual const SSLSession* get_session_array() const { return m_sessions; }
362 
363 private:
364  // create a copy of the client
365  C m_client;
366  // also store an array of SSLSessions, so we can resume communication with multiple websites
367  SSLSession m_sessions[SessionCache];
368 };
369 
370 #endif
virtual uint8_t connected()
Check if the device is connected. Use this function to determine if SSLClient is still connected and ...
Definition: SSLClient.h:276
virtual bool operator!=(const bool value)
Definition: SSLClient.h:322
size_t write_impl(const uint8_t *buf, size_t size)
Definition: SSLClientImpl.cpp:130
virtual const SSLSession * get_session_array() const
Definition: SSLClient.h:361
virtual uint16_t remotePort()
Returns the remote port, if C::remotePort exists. Else return 0.
Definition: SSLClient.h:344
Definition: SSLClientImpl.h:65
SSLSession & get_session_impl(const char *host, const IPAddress &addr)
Definition: SSLClientImpl.cpp:276
virtual int available()
Returns the number of bytes availible to read from the SSL Socket.
Definition: SSLClient.h:209
This class stores values which allow SSLClient to save and resume SSL sessions.
Definition: SSLSession.h:52
virtual uint16_t localPort()
Returns the local port, C::localPort exists. Else return 0.
Definition: SSLClient.h:328
virtual IPAddress remoteIP()
Returns the remote IP, if C::remoteIP exists. Else return INADDR_NONE.
Definition: SSLClient.h:336
C & getClient()
returns a reference to the client object stored in this class. Take care not to break it.
Definition: SSLClient.h:353
virtual int peek()
view the first byte of the buffer, without removing it from the SSLClient Buffer The implementation f...
Definition: SSLClient.h:246
int peek_impl()
Definition: SSLClientImpl.cpp:209
virtual SSLSession & getSession(const char *host, const IPAddress &addr)
Get a session reference corresponding to a host and IP, or a reference to a empty session if none exi...
Definition: SSLClient.h:296
virtual size_t write(const uint8_t *buf, size_t size)
Write some bytes to the SSL connection.
Definition: SSLClient.h:189
The main SSLClient class Check out README.md for more info.
Definition: SSLClient.h:35
SSLClient(const C &client, const br_x509_trust_anchor *trust_anchors, const size_t trust_anchors_num, const int analog_pin, const DebugLevel debug=SSL_WARN)
Initialize SSLClient with all of the prerequisites needed.
Definition: SSLClient.h:71
virtual void stop()
Close the connection If the SSL session is still active, all incoming data is discarded and BearSSL w...
Definition: SSLClient.h:263
int available_impl()
Definition: SSLClientImpl.cpp:173
int read_impl(uint8_t *buf, size_t size)
Definition: SSLClientImpl.cpp:194
void remove_session_impl(const char *host, const IPAddress &addr)
Definition: SSLClientImpl.cpp:295
virtual size_t getSessionCount() const
Get the maximum number of SSL sessions that can be stored at once.
Definition: SSLClient.h:312
virtual int read()
Read a single byte, or -1 if none is available.
Definition: SSLClient.h:215
virtual size_t write(uint8_t b)
Definition: SSLClient.h:165
void m_warn(const T str, const char *func_name) const
Definition: SSLClientImpl.h:153
virtual bool operator==(const bool value)
Definition: SSLClient.h:320
virtual void flush()
Force writing the buffered bytes from SSLClient::write to the network. This function is blocking unti...
Definition: SSLClient.h:254
virtual const Client & get_arduino_client() const
Definition: SSLClient.h:358
virtual int connect(const char *host, uint16_t port)
Connect over SSL to a host specified by a hostname.
Definition: SSLClient.h:162
virtual SSLSession * get_session_array()
return an instance of the session array that is on the stack
Definition: SSLClient.h:360
virtual bool operator!=(const C &rhs)
Returns whether or not two SSLClient objects do not have the same underlying client object.
Definition: SSLClient.h:326
virtual void removeSession(const char *host, const IPAddress &addr)
Clear the session corresponding to a host and IP.
Definition: SSLClient.h:306
virtual int connect(IPAddress ip, uint16_t port)
Connect over SSL to a host specified by an IP address.
Definition: SSLClient.h:124
int connect_impl(IPAddress ip, uint16_t port)
Definition: SSLClientImpl.cpp:74
void stop_impl()
Definition: SSLClientImpl.cpp:229
void flush_impl()
Definition: SSLClientImpl.cpp:221
Implementation code to be inherited by SSLClient.
Definition: SSLClientImpl.h:71
virtual int read(uint8_t *buf, size_t size)
Read size bytes from the SSL socket buffer, copying them into *buf, and return the number of bytes re...
Definition: SSLClient.h:237
virtual bool operator==(const C &rhs)
Returns whether or not two SSLClient objects have the same underlying client object.
Definition: SSLClient.h:324
uint8_t connected_impl()
Definition: SSLClientImpl.cpp:250
virtual Client & get_arduino_client()
return an instance of m_client that is polymorphic and can be used by SSLClientImpl
Definition: SSLClient.h:357
DebugLevel
Level of verbosity used in logging for SSLClient.
Definition: SSLClientImpl.h:59