diff --git a/README.md b/README.md index c172b38..8cb8650 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ For more information on SSLClient, check out the [examples](./examples), [API do SSLClient was created to integrate SSL seamlessly with the Arduino infrastructure, and so it does just that: implementing the brilliant [BearSSL](https://bearssl.org/) as a proxy in front of any Arduino socket library. BearSSL is designed with low flash footprint in mind, and as a result does little verification of improper programming, relying on the developer to ensure the code is correct. Since SSLClient is built specifically for the Arduino ecosystem, most of the code adds those programming checks back in, making debugging a fast and simple process. The rest manages the state of BearSSL, and ensures a manageable memory footprint. -Additionally, the bulk of SSLClient is split into two components: a template class [SSLClient](./src/SSLClient.h), and an implementation class [SSLClientImpl](./src/SSLClientImpl.h). The template class serves to abstract some functions not implemented in the Arduino Client interface (such as `EthernetClient::remoteIP`), and the implementation class is the rest of the SSLClient library. +Additionally, the bulk of SSLClient is split into two components: a template class [SSLClient](./src/SSLClient.h), and an implementation class [SSLClientImpl](./src/SSLClientImpl.h). The template class serves to abstract some functions not implemented in the Arduino Client interface (such as EthernetClient::remoteIP), and the implementation class is the rest of the SSLClient library. ## Other Features @@ -60,13 +60,13 @@ SSLClient also allows for changing the debugging level by adding an additional p ```C++ SSLClient client(EthernetClient(), TAs, (size_t)2, A7, SSL_INFO); ``` -Logging is always outputted through the [Arduino Serial interface](https://www.arduino.cc/reference/en/language/functions/communication/serial/), so you'll need to setup Serial before you can view the SSL logs. Log levels are enumerated in [Error](./src/SSLClientImpl.h). The log level is set to `SSL_WARN` by default. +Logging is always outputted through the [Arduino Serial interface](https://www.arduino.cc/reference/en/language/functions/communication/serial/), 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 [this enumeration](link-me). 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. +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](link-me), calling this function does not actually write to the network. Instead, you must call [SSLClient::available](link-me) or [SSLClient::flush](link-me), which will detect that the buffer is ready and write to the network (see [SSLClient::write](link-me) for details). +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++ @@ -112,14 +112,25 @@ In order to use SSL session resumption: SSLClient automatically stores an IP address and hostname in each session, ensuring that if you call `connect("www.google.com")` SSLClient will use a IP address that recognizes the SSL session instead of another IP address associated with `"www.google.com"`. 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](./examples/Session_Example/Session_Example.ino) 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. +You can test whether or not a website can resume SSL Sessions using the [Session Example](./examples/Session_Example/Session_Example.ino) 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: +```C++ +SSLClient client(EthernetClient(), TAs, 2, A7); +``` +Where `SomeNumber` is the number of sessions you would like to store. For example this declaration can store 3 sessions: +```C++ +SSLClient client(EthernetClient(), TAs, 2, A7); +``` +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. ## Implementation Gotchas Some ideas that didn't quite fit in the API documentation. ### Certificate Verification - SSLClient uses BearSSL's [minimal x509 verification engine](https://bearssl.org/x509.html#the-minimal-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](./TrustAnchors.md) for more details on this component of SSLClient. BearSSL also features a [known certificate validation engine](https://bearssl.org/x509.html#the-known-key-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. @@ -141,7 +152,7 @@ In order to remedy this problem, the device must be able to read the data faster * 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](./src/TLS12_only_profile) 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](./src/bearssl/src/ssl). To do this, edit `SSLClientImpl::SSLClientImpl` to change these lines: +By default, SSLClient supports only TLS1.2 and the ciphers listed in [this file](./src/TLS12_only_profile.c) 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](./src/bearssl/src/ssl). To do this, edit `SSLClientImpl::SSLClientImpl` to change these lines: ```C++ br_client_init_TLS12_only(&m_sslctx, &m_x509ctx, m_trust_anchors, m_trust_anchors_num); // comment the above line and uncomment the line below if you're having trouble connecting over SSL diff --git a/docs/html/_s_s_l_client_8h.html b/docs/html/_s_s_l_client_8h.html index 8112e78..17512cf 100644 --- a/docs/html/_s_s_l_client_8h.html +++ b/docs/html/_s_s_l_client_8h.html @@ -104,7 +104,7 @@ $(document).ready(function(){initNavTree('_s_s_l_client_8h.html','');});

Classes

class  SSLClient< C, SessionCache > - The main SSLClient class Check out README.md for more info. More...
+ The main SSLClient class. Check out README.md for more info. More...
  - +

diff --git a/docs/html/_s_s_l_client_8h_source.html b/docs/html/_s_s_l_client_8h_source.html index 3788ec1..b5a6df8 100644 --- a/docs/html/_s_s_l_client_8h_source.html +++ b/docs/html/_s_s_l_client_8h_source.html @@ -91,50 +91,50 @@ $(document).ready(function(){initNavTree('_s_s_l_client_8h_source.html','');});
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
+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 
247  virtual int peek() { return peek_impl(); }
248 
256  virtual void flush() { return flush_impl(); }
257 
266  virtual void stop() { return stop_impl(); }
267 
280  virtual uint8_t connected() { return connected_impl(); }
281 
282  //========================================
283  //= Functions Not in the Client Interface
284  //========================================
285 
300  virtual SSLSession& getSession(const char* host, const IPAddress& addr) { return get_session_impl(host, addr); }
301 
310  virtual void removeSession(const char* host, const IPAddress& addr) { return remove_session_impl(host, addr); }
311 
317  virtual size_t getSessionCount() const { return SessionCache; }
318 
324  virtual operator bool() { return connected() > 0; }
326  virtual bool operator==(const bool value) { return bool() == value; }
328  virtual bool operator!=(const bool value) { return bool() != value; }
330  virtual bool operator==(const C& rhs) { return m_client == rhs; }
332  virtual bool operator!=(const C& rhs) { return m_client != rhs; }
334  virtual uint16_t localPort() {
335  if (std::is_member_function_pointer<decltype(&C::localPort)>::value) return m_client.localPort();
336  else {
337  m_warn("Client class has no localPort function, so localPort() will always return 0", __func__);
338  return 0;
339  }
340  }
342  virtual IPAddress remoteIP() {
343  if (std::is_member_function_pointer<decltype(&C::remoteIP)>::value) return m_client.remoteIP();
344  else {
345  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__);
346  return INADDR_NONE;
347  }
348  }
350  virtual uint16_t remotePort() {
351  if (std::is_member_function_pointer<decltype(&C::remotePort)>::value) return m_client.remotePort();
352  else {
353  m_warn("Client class has no remotePort function, so remotePort() will always return 0", __func__);
354  return 0;
355  }
356  }
357 
359  C& getClient() { return m_client; }
360 
361 protected:
363  virtual Client& get_arduino_client() { return m_client; }
364  virtual const Client& get_arduino_client() const { return m_client; }
366  virtual SSLSession* get_session_array() { return m_sessions; }
367  virtual const SSLSession* get_session_array() const { return m_sessions; }
368 
369 private:
370  // create a copy of the client
371  C m_client;
372  // also store an array of SSLSessions, so we can resume communication with multiple websites
373  SSLSession m_sessions[SessionCache];
374 };
375 
376 #endif
virtual uint8_t connected()
Check if the device is connected.
Definition: SSLClient.h:280
+
virtual bool operator!=(const bool value)
Definition: SSLClient.h:328
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
+
virtual const SSLSession * get_session_array() const
Definition: SSLClient.h:367
+
virtual uint16_t remotePort()
Returns the remote port, if C::remotePort exists. Else return 0.
Definition: SSLClient.h:350
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
+
virtual int available()
Returns the number of bytes available to read from the data that has been received and decrypted.
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
+
virtual uint16_t localPort()
Returns the local port, C::localPort exists. Else return 0.
Definition: SSLClient.h:334
+
virtual IPAddress remoteIP()
Returns the remote IP, if C::remoteIP exists. Else return INADDR_NONE.
Definition: SSLClient.h:342
+
C & getClient()
Returns a reference to the client object stored in this class. Take care not to break it.
Definition: SSLClient.h:359
+
virtual int peek()
View the first byte of the buffer, without removing it from the SSLClient Buffer.
Definition: SSLClient.h:247
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 SSLSession & getSession(const char *host, const IPAddress &addr)
Gets a session reference corresponding to a host and IP, or a reference to a empty session if none ex...
Definition: SSLClient.h:300
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
+
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
+
virtual void stop()
Close the connection.
Definition: SSLClient.h:266
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 size_t getSessionCount() const
Get the maximum number of SSL sessions that can be stored at once.
Definition: SSLClient.h:317
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 bool operator==(const bool value)
Definition: SSLClient.h:326
+
virtual void flush()
Force writing the buffered bytes from SSLClient::write to the network.
Definition: SSLClient.h:256
+
virtual const Client & get_arduino_client() const
Definition: SSLClient.h:364
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 SSLSession * get_session_array()
Returns an instance of the session array that is on the stack.
Definition: SSLClient.h:366
-
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 bool operator!=(const C &rhs)
Returns whether or not two SSLClient objects do not have the same underlying client object.
Definition: SSLClient.h:332
+
virtual void removeSession(const char *host, const IPAddress &addr)
Clear the session corresponding to a host and IP.
Definition: SSLClient.h:310
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
+
virtual int read(uint8_t *buf, size_t size)
Read size bytes from the SSL client 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:330
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
+
virtual Client & get_arduino_client()
Returns an instance of m_client that is polymorphic and can be used by SSLClientImpl.
Definition: SSLClient.h:363
DebugLevel
Level of verbosity used in logging for SSLClient.
Definition: SSLClientImpl.h:59
diff --git a/docs/html/_s_s_l_client_impl_8h.html b/docs/html/_s_s_l_client_impl_8h.html index c98b0d7..505dabd 100644 --- a/docs/html/_s_s_l_client_impl_8h.html +++ b/docs/html/_s_s_l_client_impl_8h.html @@ -104,7 +104,7 @@ $(document).ready(function(){initNavTree('_s_s_l_client_impl_8h.html','');});

Classes

class  SSLClientImpl
 Implementation code to be inherited by SSLClient. More...
 Implementation code to be inherited by SSLClient. More...
 
SSL_WARN = 2, SSL_INFO = 3 } - +

@@ -127,7 +127,7 @@ Enumerations

 Level of verbosity used in logging for SSLClient. More...
 Level of verbosity used in logging for SSLClient. More...
 

Enumeration Type Documentation

@@ -143,8 +143,8 @@ Enumerations
-

Level of verbosity used in logging for SSLClient.

-

Use these values when initializing SSLClient to set how many logs you would like to see in the Serial monitor.

+

Level of verbosity used in logging for SSLClient.

+

Use these values when initializing SSLClient to set how many logs you would like to see in the Serial monitor.

@@ -171,7 +171,7 @@ Enumerations

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_NONE 

No logging output

- -
Enumerator
SSL_OK 
SSL_CLIENT_CONNECT_FAIL 

The underlying client failed to connect, probably not an issue with SSL

@@ -182,9 +182,9 @@ Enumerations
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.

diff --git a/docs/html/_s_s_l_session_8h.html b/docs/html/_s_s_l_session_8h.html index 4382701..9f37a1c 100644 --- a/docs/html/_s_s_l_session_8h.html +++ b/docs/html/_s_s_l_session_8h.html @@ -102,7 +102,7 @@ $(document).ready(function(){initNavTree('_s_s_l_session_8h.html','');});

Classes

class  SSLSession - This class stores values which allow SSLClient to save and resume SSL sessions. More...
+ This class stores values which allow SSLClient to save and resume SSL sessions. More...
 
diff --git a/docs/html/_s_s_l_session_8h_source.html b/docs/html/_s_s_l_session_8h_source.html index 1bd7bf5..9cee101 100644 --- a/docs/html/_s_s_l_session_8h_source.html +++ b/docs/html/_s_s_l_session_8h_source.html @@ -91,10 +91,10 @@ $(document).ready(function(){initNavTree('_s_s_l_session_8h_source.html','');});
SSLSession.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 
28 #include "bearssl.h"
29 #include "Arduino.h"
30 #include "IPAddress.h"
31 
32 #ifndef SSLSession_H_
33 #define SSLSession_H_
34 
52 class SSLSession : public br_ssl_session_parameters {
53 
54 public:
60  explicit SSLSession()
61  : m_valid_session(false)
62  , m_hostname()
63  , m_ip(INADDR_NONE) {}
64 
66  SSLSession& operator=(const SSLSession&) = delete;
67 
76  const String& get_hostname() const { return m_hostname; }
77 
86  const IPAddress& get_ip() const { return m_ip; }
87 
88  bool is_valid_session() const { return m_valid_session; }
89 
109  void set_parameters(const IPAddress& ip, const char* hostname = NULL);
110 
117  void clear_parameters();
118 
120  br_ssl_session_parameters* to_br_session() { return (br_ssl_session_parameters *)this; }
121 
122 private:
123  bool m_valid_session;
124  // aparently a hostname has a max length of 256 chars. Go figure.
125  String m_hostname;
126  // store the IP Address we connected to
127  IPAddress m_ip;
128 };
129 
130 
131 
132 #endif /* SSLSession_H_ */
This class stores values which allow SSLClient to save and resume SSL sessions.
Definition: SSLSession.h:52
-
br_ssl_session_parameters * to_br_session()
returns a pointer to the ::br_ssl_session_parameters component of this class
Definition: SSLSession.h:120
+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 
28 #include "bearssl.h"
29 #include "Arduino.h"
30 #include "IPAddress.h"
31 
32 #ifndef SSLSession_H_
33 #define SSLSession_H_
34 
52 class SSLSession : public br_ssl_session_parameters {
53 
54 public:
60  explicit SSLSession()
61  : m_valid_session(false)
62  , m_hostname()
63  , m_ip(INADDR_NONE) {}
64 
66  SSLSession& operator=(const SSLSession&) = delete;
67 
76  const String& get_hostname() const { return m_hostname; }
77 
86  const IPAddress& get_ip() const { return m_ip; }
87 
88  bool is_valid_session() const { return m_valid_session; }
89 
109  void set_parameters(const IPAddress& ip, const char* hostname = NULL);
110 
118  void clear_parameters();
119 
121  br_ssl_session_parameters* to_br_session() { return (br_ssl_session_parameters *)this; }
122 
123 private:
124  bool m_valid_session;
125  // aparently a hostname has a max length of 256 chars. Go figure.
126  String m_hostname;
127  // store the IP Address we connected to
128  IPAddress m_ip;
129 };
130 
131 
132 
133 #endif /* SSLSession_H_ */
This class stores values which allow SSLClient to save and resume SSL sessions.
Definition: SSLSession.h:52
+
br_ssl_session_parameters * to_br_session()
Returns a pointer to the ::br_ssl_session_parameters component of this class.
Definition: SSLSession.h:121
void set_parameters(const IPAddress &ip, const char *hostname=NULL)
Set the ip address and hostname of the session.
Definition: SSLSession.cpp:4
-
void clear_parameters()
delete the parameters and invalidate the session Roughly equivalent to this_session = SSLSession(),...
Definition: SSLSession.cpp:19
+
void clear_parameters()
Delete the parameters and invalidate the session.
Definition: SSLSession.cpp:19
bool is_valid_session() const
Definition: SSLSession.h:88
SSLSession & operator=(const SSLSession &)=delete
use clear_parameters or set_parameters instead
const IPAddress & get_ip() const
Get ::IPAddress associated with this session.
Definition: SSLSession.h:86
diff --git a/docs/html/annotated.html b/docs/html/annotated.html index 45f5447..5f354c0 100644 --- a/docs/html/annotated.html +++ b/docs/html/annotated.html @@ -93,9 +93,9 @@ $(document).ready(function(){initNavTree('annotated.html','');});
Here are the classes, structs, unions and interfaces with brief descriptions:
- - - + + +
 CSSLClientThe main SSLClient class Check out README.md for more info
 CSSLClientImplImplementation code to be inherited by SSLClient
 CSSLSessionThis class stores values which allow SSLClient to save and resume SSL sessions
 CSSLClientThe main SSLClient class. Check out README.md for more info
 CSSLClientImplImplementation code to be inherited by SSLClient
 CSSLSessionThis class stores values which allow SSLClient to save and resume SSL sessions
diff --git a/docs/html/class_s_s_l_client.html b/docs/html/class_s_s_l_client.html index abed69b..eadc3cf 100644 --- a/docs/html/class_s_s_l_client.html +++ b/docs/html/class_s_s_l_client.html @@ -96,7 +96,7 @@ $(document).ready(function(){initNavTree('class_s_s_l_client.html','');});
-

The main SSLClient class Check out README.md for more info. +

The main SSLClient class. Check out README.md for more info. More...

#include <SSLClient.h>

@@ -113,7 +113,7 @@ Inheritance diagram for SSLClient< C, SessionCache >:

Public Member Functions

 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. More...
+ Initialize SSLClient with all of the prerequisites needed. More...
  virtual int connect (IPAddress ip, uint16_t port)  Connect over SSL to a host specified by an IP address. More...
@@ -127,28 +127,28 @@ Public Member Functions  Write some bytes to the SSL connection. More...
  virtual int available () - Returns the number of bytes availible to read from the SSL Socket. More...
+ Returns the number of bytes available to read from the data that has been received and decrypted. More...
  virtual int read ()  Read a single byte, or -1 if none is available. More...
  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 read. More...
+ Read size bytes from the SSL client buffer, copying them into *buf, and return the number of bytes read. More...
  virtual int peek () - view the first byte of the buffer, without removing it from the SSLClient Buffer The implementation for this function can be found in SSLClientImpl::peek More...
+ View the first byte of the buffer, without removing it from the SSLClient Buffer. More...
  virtual void 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. More...
+ Force writing the buffered bytes from SSLClient::write to the network. More...
  virtual void stop () - Close the connection If the SSL session is still active, all incoming data is discarded and BearSSL will attempt to close the session gracefully (will write to the network), and then call m_client::stop. If the session is not active or an error was encountered previously, this function will simply call m_client::stop. The implementation for this function can be found in SSLClientImpl::peek. More...
+ Close the connection. More...
  virtual uint8_t connected () - 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 SSLClient::available should be preferred over this function for rapid polling–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. More...
+ Check if the device is connected. More...
  virtual SSLSessiongetSession (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 exist. More...
+ Gets a session reference corresponding to a host and IP, or a reference to a empty session if none exist. More...
  virtual void removeSession (const char *host, const IPAddress &addr)  Clear the session corresponding to a host and IP. More...
@@ -157,17 +157,17 @@ Public Member Functions  Get the maximum number of SSL sessions that can be stored at once. More...
  virtual operator bool () - Equivalent to SSLClient::connected() > 0. More...
+ Equivalent to SSLClient::connected() > 0. More...
  virtual bool operator== (const bool value)   virtual bool operator!= (const bool value)   virtual bool operator== (const C &rhs) - Returns whether or not two SSLClient objects have the same underlying client object. More...
+ Returns whether or not two SSLClient objects have the same underlying client object. More...
  virtual bool operator!= (const C &rhs) - Returns whether or not two SSLClient objects do not have the same underlying client object. More...
+ Returns whether or not two SSLClient objects do not have the same underlying client object. More...
  virtual uint16_t localPort ()  Returns the local port, C::localPort exists. Else return 0. More...
@@ -179,7 +179,7 @@ Public Member Functions  Returns the remote port, if C::remotePort exists. Else return 0. More...
  C & getClient () - returns a reference to the client object stored in this class. Take care not to break it. More...
+ Returns a reference to the client object stored in this class. Take care not to break it. More...
  - Public Member Functions inherited from SSLClientImpl  SSLClientImpl (const br_x509_trust_anchor *trust_anchors, const size_t trust_anchors_num, const int analog_pin, const DebugLevel debug) @@ -210,12 +210,12 @@ Public Member Functions

Protected Member Functions

virtual Client & get_arduino_client () - return an instance of m_client that is polymorphic and can be used by SSLClientImpl More...
+ Returns an instance of m_client that is polymorphic and can be used by SSLClientImpl. More...
  virtual const Client & get_arduino_client () const   virtual SSLSessionget_session_array () - return an instance of the session array that is on the stack More...
+ Returns an instance of the session array that is on the stack. More...
  virtual const SSLSessionget_session_array () const   @@ -248,7 +248,7 @@ Protected Member Functions

template<class C, size_t SessionCache = 1>
class SSLClient< C, SessionCache >

-

The main SSLClient class Check out README.md for more info.

+

The main SSLClient class. Check out README.md for more info.

Constructor & Destructor Documentation

◆ SSLClient()

@@ -304,13 +304,13 @@ template<class C , size_t SessionCache = 1>
-

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
- + @@ -347,10 +347,10 @@ template<class C , size_t SessionCache = 1>
clientThe base network device to create an SSL socket on. This object will be copied and the copy will be stored in SSLClient.
clientThe base network device to create an SSL socket on. This object will be copied and the copy will be stored in SSLClient.
trust_anchorsTrust anchors used in the verification of the SSL server certificate. Check out TrustAnchors.md for more info.
trust_anchors_numThe number of objects in the trust_anchors array.
analog_pinAn analog pin to pull random bytes from, used in seeding the RNG.
-

Returns the number of bytes availible to read from the SSL Socket.

-

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.

+

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.

The implementation for this function can be found in SSLClientImpl::available

-
Precondition
SSLClient::connected must be true.
+
Precondition
SSLClient::connected must be true.
Returns
The number of bytes available (can be zero), or zero if any of the pre conditions aren't satisfied.
@@ -392,15 +392,15 @@ template<class C , size_t SessionCache = 1>

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, 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 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.

+

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.

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
@@ -451,15 +451,15 @@ template<class C , size_t SessionCache = 1>

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 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 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.
+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
@@ -498,7 +498,8 @@ template<class C , size_t SessionCache = 1>
-

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 SSLClient::available should be preferred over this function for rapid polling–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.

+

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 SSLClient::available should be preferred over this function for rapid polling–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.

The implementation for this function can be found in SSLClientImpl::connected_impl.

Returns
1 if connected, 0 if not
@@ -529,7 +530,8 @@ template<class C , size_t SessionCache = 1>
-

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.

@@ -558,7 +560,7 @@ template<class C , size_t SessionCache = 1>
-

return an instance of m_client that is polymorphic and can be used by SSLClientImpl

+

Returns an instance of m_client that is polymorphic and can be used by SSLClientImpl.

Implements SSLClientImpl.

@@ -618,7 +620,7 @@ template<class C , size_t SessionCache = 1>
-

return an instance of the session array that is on the stack

+

Returns an instance of the session array that is on the stack.

Implements SSLClientImpl.

@@ -678,7 +680,7 @@ template<class C , size_t SessionCache = 1>
-

returns a reference to the client object stored in this class. Take care not to break it.

+

Returns a reference to the client object stored in this class. Take care not to break it.

@@ -718,7 +720,7 @@ template<class C , size_t SessionCache = 1>
-

Get a session reference corresponding to a host and IP, or a reference to a empty session if none exist.

+

Gets a session reference corresponding to a host and IP, or a reference to a empty session if none exist.

If no session corresponding to the host and IP exist, then this function will cycle through sessions in a rotating order. This allows the session cache to continually store sessions, however it will also result in old sessions being cleared and returned. In general, it is a good idea to use a SessionCache size equal to the number of domains you plan on connecting to.

The implementation for this function can be found at SSLClientImpl::get_session_impl.

Parameters
@@ -820,7 +822,7 @@ template<class C , size_t SessionCache = 1>
-

Equivalent to SSLClient::connected() > 0.

+

Equivalent to SSLClient::connected() > 0.

Returns
true if connected, false if not
@@ -880,7 +882,7 @@ template<class C , size_t SessionCache = 1>
-

Returns whether or not two SSLClient objects do not have the same underlying client object.

+

Returns whether or not two SSLClient objects do not have the same underlying client object.

@@ -939,7 +941,7 @@ template<class C , size_t SessionCache = 1>
-

Returns whether or not two SSLClient objects have the same underlying client object.

+

Returns whether or not two SSLClient objects have the same underlying client object.

@@ -968,8 +970,8 @@ template<class C , size_t SessionCache = 1>
-

view the first byte of the buffer, without removing it from the SSLClient Buffer The implementation for this function can be found in SSLClientImpl::peek

-
Precondition
SSLClient::available must be >0
+

View the first byte of the buffer, without removing it from the SSLClient Buffer.

+

The implementation for this function can be found in SSLClientImpl::peek

Precondition
SSLClient::available must be >0
Returns
The first byte received, or -1 if the preconditions are not satisfied (warning: do not use if your data may be -1, as the return value is ambiguous)
@@ -1000,7 +1002,7 @@ template<class C , size_t SessionCache = 1>

Read a single byte, or -1 if none is available.

-
See also
SSLClient::read(uint8_t*, size_t)
+
See also
SSLClient::read(uint8_t*, size_t)
@@ -1040,11 +1042,11 @@ template<class C , size_t SessionCache = 1>
-

Read size bytes from the SSL socket 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.

+

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.

The implementation for this function can be found in SSLClientImpl::read_impl(uint8_t*, size_t)

-
Precondition
SSLClient::available must be >0
+
Precondition
SSLClient::available must be >0
Parameters
@@ -1191,7 +1193,8 @@ template<class C , size_t SessionCache = 1>
bufThe pointer to the buffer to put SSL application data into
-

Close the connection If the SSL session is still active, all incoming data is discarded and BearSSL will attempt to close the session gracefully (will write to the network), and then call m_client::stop. If the session is not active or an error was encountered previously, this function will simply call m_client::stop. The implementation for this function can be found in SSLClientImpl::peek.

+

Close the connection.

+

If the SSL session is still active, all incoming data is discarded and BearSSL will attempt to close the session gracefully (will write to the network), and then call m_client::stop. If the session is not active or an error was encountered previously, this function will simply call m_client::stop. The implementation for this function can be found in SSLClientImpl::peek.

@@ -1261,9 +1264,9 @@ template<class C , size_t SessionCache = 1>

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
diff --git a/docs/html/class_s_s_l_client_impl.html b/docs/html/class_s_s_l_client_impl.html index 7ecee39..7259c74 100644 --- a/docs/html/class_s_s_l_client_impl.html +++ b/docs/html/class_s_s_l_client_impl.html @@ -96,7 +96,7 @@ $(document).ready(function(){initNavTree('class_s_s_l_client_impl.html','');});
-

Implementation code to be inherited by SSLClient. +

Implementation code to be inherited by SSLClient. More...

#include <SSLClientImpl.h>

@@ -106,7 +106,7 @@ Inheritance diagram for SSLClientImpl:
-SSLClient< C, SessionCache > +SSLClient< C, SessionCache >
@@ -180,7 +180,7 @@ Protected Member Functions
 

Detailed Description

-

Implementation code to be inherited by SSLClient.

+

Implementation code to be inherited by SSLClient.

Constructor & Destructor Documentation

◆ SSLClientImpl()

@@ -227,7 +227,7 @@ Protected Member Functions
@@ -246,7 +246,7 @@ Protected Member Functions @@ -322,7 +322,7 @@ Protected Member Functions @@ -340,7 +340,7 @@ Protected Member Functions @@ -366,7 +366,7 @@ Protected Member Functions
-

See SSLClient::get_arduino_client

+
See also
SSLClient::get_arduino_client

Implemented in SSLClient< C, SessionCache >.

@@ -421,7 +421,7 @@ Protected Member Functions
-

See SSLClient::get_session_array

+
See also
SSLClient::get_session_array

Implemented in SSLClient< C, SessionCache >.

@@ -479,7 +479,7 @@ Protected Member Functions
@@ -505,7 +505,7 @@ Protected Member Functions
-

See SSLClient::getSessionCount

+
See also
SSLClient::getSessionCount

Implemented in SSLClient< C, SessionCache >.

@@ -533,7 +533,7 @@ Protected Member Functions
-

See SSLClient::localPort

+
See also
SSLClient::localPort

Implemented in SSLClient< C, SessionCache >.

@@ -829,7 +829,7 @@ template<typename T >
-
See also
SSLClient::peek
+
See also
SSLClient::peek
@@ -858,7 +858,7 @@ template<typename T > @@ -884,7 +884,7 @@ template<typename T >
-

See SSLClient::remoteIP

+
See also
SSLClient::remoteIP

Implemented in SSLClient< C, SessionCache >.

@@ -912,7 +912,7 @@ template<typename T >
-

See SSLClient::localPort

+
See also
SSLClient::localPort

Implemented in SSLClient< C, SessionCache >.

@@ -943,7 +943,7 @@ template<typename T >
@@ -961,7 +961,7 @@ template<typename T >
-
See also
SSLClient::stop
+
See also
SSLClient::stop
diff --git a/docs/html/class_s_s_l_session.html b/docs/html/class_s_s_l_session.html index 07d85e0..adb0e30 100644 --- a/docs/html/class_s_s_l_session.html +++ b/docs/html/class_s_s_l_session.html @@ -95,7 +95,7 @@ $(document).ready(function(){initNavTree('class_s_s_l_session.html','');});
-

This class stores values which allow SSLClient to save and resume SSL sessions. +

This class stores values which allow SSLClient to save and resume SSL sessions. More...

#include <SSLSession.h>

@@ -126,17 +126,17 @@ Public Member Functions  Set the ip address and hostname of the session. More...
  void clear_parameters () - delete the parameters and invalidate the session Roughly equivalent to this_session = SSLSession(), however this function preserves the String object, allowing it to better handle the dynamic memory needed. More...
+ Delete the parameters and invalidate the session. More...
  br_ssl_session_parameters * to_br_session () - returns a pointer to the ::br_ssl_session_parameters component of this class More...
+ Returns a pointer to the ::br_ssl_session_parameters component of this class. More...
 

Detailed Description

-

This class stores values which allow SSLClient to save and resume SSL sessions.

+

This class stores values which allow SSLClient to save and resume SSL sessions.

SSLSession.h

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.

+

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.

Constructor & Destructor Documentation

◆ SSLSession()

@@ -182,7 +182,8 @@ Public Member Functions
-

delete the parameters and invalidate the session Roughly equivalent to this_session = SSLSession(), however this function preserves the String object, allowing it to better handle the dynamic memory needed.

+

Delete the parameters and invalidate the session.

+

Roughly equivalent to this_session = SSLSession(), however this function preserves the String object, allowing it to better handle the dynamic memory needed.

@@ -211,7 +212,7 @@ Public Member Functions

Get the hostname string associated with this session.

Returns
A String object or "" if there is no hostname
-
Precondition
must check isValidSession before getting this value, as if this session in invalid this value is not guarented to be reset to "".
+
Precondition
must check isValidSession before getting this value, as if this session in invalid this value is not guarenteed to be reset to "".
@@ -240,7 +241,7 @@ Public Member Functions

Get ::IPAddress associated with this session.

Returns
A ::IPAddress object, #INADDR_NONE if there is no IP
-
Precondition
must check isValidSession before getting this value, as if this session in invalid this value is not guarented to be reset to #INADDR_NONE.
+
Precondition
must check isValidSession before getting this value, as if this session in invalid this value is not guarenteed to be reset to #INADDR_NONE.
@@ -325,7 +326,7 @@ Public Member Functions

Set the ip address and hostname of the session.

This function stores the ip Address object and hostname object into the session object. If hostname is not null or ip address is not blank, and the ::br_ssl_session_parameters values are non-zero it then validates the session.

-
Precondition
You must call ::br_ssl_engine_get_session_parameters with this session before calling this function. This is because there is no way to completly validate the ::br_ssl_session_parameters and the session may end up in a corrupted state if this is not observed.
+
Precondition
You must call ::br_ssl_engine_get_session_parameters with this session before calling this function. This is because there is no way to completely validate the ::br_ssl_session_parameters and the session may end up in a corrupted state if this is not observed.
Parameters
@@ -359,7 +360,7 @@ Public Member Functions
ipThe IP address of the host associated with the session
-

returns a pointer to the ::br_ssl_session_parameters component of this class

+

Returns a pointer to the ::br_ssl_session_parameters component of this class.

diff --git a/docs/html/functions_vars.html b/docs/html/functions_vars.html new file mode 100644 index 0000000..0b413ef --- /dev/null +++ b/docs/html/functions_vars.html @@ -0,0 +1,145 @@ + + + + + + + +SSLClient: Class Members - Variables + + + + + + + + + + + + + + +
+
+ + + + + + +
+
SSLClient +  1.0 +
+
Add TLS 1.2 functionality to any network library.
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
+ + + + diff --git a/docs/html/hierarchy.html b/docs/html/hierarchy.html index 85eafea..7ad10b4 100644 --- a/docs/html/hierarchy.html +++ b/docs/html/hierarchy.html @@ -94,10 +94,10 @@ $(document).ready(function(){initNavTree('hierarchy.html','');});
This inheritance list is sorted roughly, but not completely, alphabetically:
[detail level 123]
- + - - + +
 Cbr_ssl_session_parameters
 CSSLSessionThis class stores values which allow SSLClient to save and resume SSL sessions
 CSSLSessionThis class stores values which allow SSLClient to save and resume SSL sessions
 CClient
 CSSLClientImplImplementation code to be inherited by SSLClient
 CSSLClient< C, SessionCache >The main SSLClient class Check out README.md for more info
 CSSLClientImplImplementation code to be inherited by SSLClient
 CSSLClient< C, SessionCache >The main SSLClient class. Check out README.md for more info
diff --git a/docs/html/index.html b/docs/html/index.html index b209a0b..39317ee 100644 --- a/docs/html/index.html +++ b/docs/html/index.html @@ -5,7 +5,7 @@ -SSLClient: Main Page +SSLClient: SSLClient - Arduino Library For SSL @@ -86,11 +86,74 @@ $(document).ready(function(){initNavTree('index.html','');}); -
+
-
SSLClient Documentation
+
SSLClient - Arduino Library For SSL
+

SSLClient requires at least 110kb flash and 8kb RAM, and will not compile otherwise. This means that most Arduino boards are not supported. Check your board's specifications before attempting to use this library.

+

SSLClient is a simple library to add TLS 1.2 functionality to any network library implementing the Arduino Client interface, including the Arduino EthernetClient and WiFiClient classes (though it is better to prefer WiFClient.connectSSL if implemented). In other words, SSLClient implements encrypted communication through SSL on devices that do not otherwise support it.

+

Overview

+

Using SSLClient should be similar to using any other Arduino-based Client class, since this library was developed around compatibility with EthernetClient. There are a few extra things, however, that you will need to get started:

+
    +
  1. A board with a lot of resources (>110kb flash and >8kb RAM), and a network peripheral with a large internal buffer (>8kb). 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 Notes).
  2. +
  3. A header containing array of trust anchors, which will look like this file. These are used to verify the SSL connection later on, and without them you will be unable to use this library. Check out this document on how to generate this file for your project, and for more information about what a trust anchor is.
  4. +
  5. A Client class associated with a network interface. We tested this library using EthernetClient, however in theory it will work for any class implementing Client.
  6. +
  7. An analog pin, used for generating random data at the start of the connection (see the Implementation Notes).
  8. +
+

Once all those are ready, you can create a simple SSLClient object like this:

{C++}
SSLClient<BaseClientType> 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)
  • +
  • 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:

    {C++}
    SSLClient<EthernetClient> client(EthernetClient(), TAs, 2, A7);

    Once that is setup, simply use SSLClient as you would the base client class:

    {C++}
    // connect to ardiuino.cc over ssl (port 443 for websites)
    client.connect("www.arduino.cc", 443);
    // Make a HTTP request
    client.println("GET /asciilogo.txt HTTP/1.1");
    client.println("User-Agent: AdafruitFeatherM0WiFi");
    client.print("Host: ");
    client.println(server);
    client.println("Connection: close");
    client.println();
    client.flush();
    // read and print the data
    ...

    Note: client.connect("www.arduino.cc", 443) can take 5-15 seconds to finish. This an unavoidable consequence of the SSL protocol, and is detailed in Implementation Notes.

    +
  • +
+

For more information on SSLClient, check out the examples, API documentation, or the rest of this README.

+

How It Works

+

SSLClient was created to integrate SSL seamlessly with the Arduino infrastructure, and so it does just that: implementing the brilliant BearSSL as a proxy in front of any Arduino socket library. BearSSL is designed with low flash footprint in mind, and as a result does little verification of improper programming, relying on the developer to ensure the code is correct. Since SSLClient is built specifically for the Arduino ecosystem, most of the code adds those programming checks back in, making debugging a fast and simple process. The rest manages the state of BearSSL, and ensures a manageable memory footprint.

+

Additionally, the bulk of SSLClient is split into two components: a template class SSLClient, and an implementation class SSLClientImpl. The template class serves to abstract some functions not implemented in the Arduino Client interface (such as EthernetClient::remoteIP), and the implementation class is the rest of the SSLClient library.

+

Other Features

+

Logging

+

SSLClient also allows for changing the debugging level by adding an additional parameter to the constructor:

{C++}
SSLClient<EthernetClient> client(EthernetClient(), TAs, (size_t)2, A7, 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++}
SSLClient<EthernetClient> client(EthernetClient(), TAs, 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 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 a IP address that recognizes the SSL session instead of another IP address associated with "www.google.com". 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:

{C++}
SSLClient<EthernetClient, SomeNumber> client(EthernetClient(), TAs, 2, A7);

Where SomeNumber is the number of sessions you would like to store. For example this declaration can store 3 sessions:

{C++}
SSLClient<EthernetClient, 3> client(EthernetClient(), TAs, 2, A7);

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.

+

Implementation Gotchas

+

Some ideas that didn't quite fit in the API documentation.

+

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.

+

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.

+

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 SSLClientImpl::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:

{C++}
br_client_init_TLS12_only(&m_sslctx, &m_x509ctx, m_trust_anchors, m_trust_anchors_num);
// comment the above line and uncomment the line below if you're having trouble connecting over SSL
// br_ssl_client_init_full(&m_sslctx, &m_x509ctx, m_trust_anchors, m_trust_anchors_num);

to this:

{C++}
// br_client_init_TLS12_only(&m_sslctx, &m_x509ctx, m_trust_anchors, m_trust_anchors_num);
// comment the above line and uncomment the line below if you're having trouble connecting over SSL
br_ssl_client_init_full(&m_sslctx, &m_x509ctx, m_trust_anchors, m_trust_anchors_num);

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.

+
diff --git a/docs/html/md__c_1__users__noah__documents__arduino_libraries__s_s_l_client__trust_anchors.html b/docs/html/md__c_1__users__noah__documents__arduino_libraries__s_s_l_client__trust_anchors.html index ae62f75..01d98af 100644 --- a/docs/html/md__c_1__users__noah__documents__arduino_libraries__s_s_l_client__trust_anchors.html +++ b/docs/html/md__c_1__users__noah__documents__arduino_libraries__s_s_l_client__trust_anchors.html @@ -91,11 +91,11 @@ $(document).ready(function(){initNavTree('md__c_1__users__noah__documents__ardui
Trust Anchors
-

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:

{C++}
#define TAs_NUM 1
static const unsigned char TA_DN0[] = {
// lots of raw bytes here
// ...
};
static const unsigned char TA_RSA_N0[] = {
// lots of raw bytes here
//...
};
static const unsigned char TA_RSA_E0[] = {
// 1-3 bytes here
};
static const br_x509_trust_anchor TAs[] = {
{
{ (unsigned char *)TA_DN0, sizeof TA_DN0 },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA_RSA_N0, sizeof TA_RSA_N0,
(unsigned char *)TA_RSA_E0, sizeof TA_RSA_E0,
} }
}
},
};

A full example of a trust anchor header can be found in this file. Full documentation for the format of these variables can be found in the BearSSL documentation for br_x509_trust_anchor.

+

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:

{C++}
#define TAs_NUM 1
static const unsigned char TA_DN0[] = {
// lots of raw bytes here
// ...
};
static const unsigned char TA_RSA_N0[] = {
// lots of raw bytes here
//...
};
static const unsigned char TA_RSA_E0[] = {
// 1-3 bytes here
};
static const br_x509_trust_anchor TAs[] = {
{
{ (unsigned char *)TA_DN0, sizeof TA_DN0 },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA_RSA_N0, sizeof TA_RSA_N0,
(unsigned char *)TA_RSA_E0, sizeof TA_RSA_E0,
} }
}
},
};

A full example of a trust anchor header can be found in this file. Full documentation for the format of these variables can be found in the BearSSL documentation for br_x509_trust_anchor.

Generating Trust Anchors

HTTPS

-

For HTTPS, there a couple of tools you can use. Ordered from easy to hard:

    +

    For HTTPS, there a couple of tools you can use. Ordered from easiest to hardest:

    • This website, written to simplify the creation of trust anchor headers. Simply plug and play.
    • 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.
    • @@ -103,7 +103,7 @@ $(document).ready(function(){initNavTree('md__c_1__users__noah__documents__ardui

      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 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<SomeClientType> 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.

      +

      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<SomeClientType> 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.

diff --git a/docs/html/navtreedata.js b/docs/html/navtreedata.js index 2de0edc..6bb2dc3 100644 --- a/docs/html/navtreedata.js +++ b/docs/html/navtreedata.js @@ -24,7 +24,7 @@ for the JavaScript code in this file var NAVTREE = [ [ "SSLClient", "index.html", [ - [ "SSLClient - Arduino Library For SSL", "md__c_1__users__noah__documents__arduino_libraries__s_s_l_client__r_e_a_d_m_e.html", null ], + [ "SSLClient - Arduino Library For SSL", "index.html", null ], [ "Trust Anchors", "md__c_1__users__noah__documents__arduino_libraries__s_s_l_client__trust_anchors.html", null ], [ "Classes", "annotated.html", [ [ "Class List", "annotated.html", "annotated_dup" ], diff --git a/docs/html/navtreeindex0.js b/docs/html/navtreeindex0.js index 00bd01c..97904f6 100644 --- a/docs/html/navtreeindex0.js +++ b/docs/html/navtreeindex0.js @@ -108,8 +108,8 @@ var NAVTREEINDEX0 = "globals_func.html":[3,1,1], "globals_vars.html":[3,1,2], "hierarchy.html":[2,2], +"index.html":[0], "index.html":[], -"md__c_1__users__noah__documents__arduino_libraries__s_s_l_client__r_e_a_d_m_e.html":[0], "md__c_1__users__noah__documents__arduino_libraries__s_s_l_client__trust_anchors.html":[1], "pages.html":[], "time__macros_8h.html":[3,0,1,5], diff --git a/docs/html/pages.html b/docs/html/pages.html index 5f7f3f9..c715a5c 100644 --- a/docs/html/pages.html +++ b/docs/html/pages.html @@ -93,8 +93,7 @@ $(document).ready(function(){initNavTree('pages.html','');});
Here is a list of all related documentation pages:
diff --git a/docs/html/search/all_e.js b/docs/html/search/all_e.js index 2ae3e87..84c4068 100644 --- a/docs/html/search/all_e.js +++ b/docs/html/search/all_e.js @@ -1,6 +1,6 @@ var searchData= [ - ['sslclient_20_2d_20arduino_20library_20for_20ssl',['SSLClient - Arduino Library For SSL',['../md__c_1__users__noah__documents__arduino_libraries__s_s_l_client__r_e_a_d_m_e.html',1,'']]], + ['sslclient_20_2d_20arduino_20library_20for_20ssl',['SSLClient - Arduino Library For SSL',['../index.html',1,'']]], ['sec_5fper_5fday',['SEC_PER_DAY',['../time__macros_8h.html#a3aaee30ddedb3f6675aac341a66e39e2',1,'time_macros.h']]], ['sec_5fper_5fhour',['SEC_PER_HOUR',['../time__macros_8h.html#a2d540510d5860d7f190d13124956bc57',1,'time_macros.h']]], ['sec_5fper_5fmin',['SEC_PER_MIN',['../time__macros_8h.html#ac47b302f1b8d2a7a9c035c417247be76',1,'time_macros.h']]], diff --git a/docs/html/search/pages_0.js b/docs/html/search/pages_0.js index c416cfc..54d5ef5 100644 --- a/docs/html/search/pages_0.js +++ b/docs/html/search/pages_0.js @@ -1,4 +1,4 @@ var searchData= [ - ['sslclient_20_2d_20arduino_20library_20for_20ssl',['SSLClient - Arduino Library For SSL',['../md__c_1__users__noah__documents__arduino_libraries__s_s_l_client__r_e_a_d_m_e.html',1,'']]] + ['sslclient_20_2d_20arduino_20library_20for_20ssl',['SSLClient - Arduino Library For SSL',['../index.html',1,'']]] ]; diff --git a/docs/html/search/variables_1.html b/docs/html/search/variables_1.html new file mode 100644 index 0000000..b784017 --- /dev/null +++ b/docs/html/search/variables_1.html @@ -0,0 +1,30 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/docs/html/search/variables_1.js b/docs/html/search/variables_1.js new file mode 100644 index 0000000..89036bd --- /dev/null +++ b/docs/html/search/variables_1.js @@ -0,0 +1,17 @@ +var searchData= +[ + ['m_5fanalog_5fpin',['m_analog_pin',['../class_s_s_l_client_impl.html#a9fd03216e71ec0d250b3ed2874f08350',1,'SSLClientImpl']]], + ['m_5fclient',['m_client',['../class_s_s_l_client.html#a3fa6f4acf8149d76dd4fa443df4a2202',1,'SSLClient']]], + ['m_5fdebug',['m_debug',['../class_s_s_l_client_impl.html#a918195d260b3399056bd0477e5249321',1,'SSLClientImpl']]], + ['m_5fhostname',['m_hostname',['../class_s_s_l_session.html#ab5611a1eb7633019a9bfaa7cc86a1645',1,'SSLSession']]], + ['m_5fiobuf',['m_iobuf',['../class_s_s_l_client_impl.html#a6b8064ac811810e00b339f15fbe522c3',1,'SSLClientImpl']]], + ['m_5fip',['m_ip',['../class_s_s_l_session.html#ab080fda0553cff3be60ef134b68ad029',1,'SSLSession']]], + ['m_5fsession_5findex',['m_session_index',['../class_s_s_l_client_impl.html#a7cc5de19274e5ec689017cbb84aa008a',1,'SSLClientImpl']]], + ['m_5fsessions',['m_sessions',['../class_s_s_l_client.html#a680fa57f70d2f3164dd4b117bba8f001',1,'SSLClient']]], + ['m_5fsslctx',['m_sslctx',['../class_s_s_l_client_impl.html#ab6e5219b2edeb01bd949fbb51749adee',1,'SSLClientImpl']]], + ['m_5ftrust_5fanchors',['m_trust_anchors',['../class_s_s_l_client_impl.html#ac84af4c6b35f59642b6814c52cfde5db',1,'SSLClientImpl']]], + ['m_5ftrust_5fanchors_5fnum',['m_trust_anchors_num',['../class_s_s_l_client_impl.html#a4b86754cee9e04742728ca14e1b0db7f',1,'SSLClientImpl']]], + ['m_5fvalid_5fsession',['m_valid_session',['../class_s_s_l_session.html#abfe44b78c7c7d0f83919d6031d1d1857',1,'SSLSession']]], + ['m_5fwrite_5fidx',['m_write_idx',['../class_s_s_l_client_impl.html#a4bdc048774d8be220da7175e1369513f',1,'SSLClientImpl']]], + ['m_5fx509ctx',['m_x509ctx',['../class_s_s_l_client_impl.html#a942c7bd3ebbb03db249096c8bb591b8c',1,'SSLClientImpl']]] +]; diff --git a/src/SSLClient.h b/src/SSLClient.h index 0a08d34..3e69bd9 100644 --- a/src/SSLClient.h +++ b/src/SSLClient.h @@ -27,7 +27,7 @@ #define SSLClient_H_ /** - * @brief The main SSLClient class + * @brief The main SSLClient class. * Check out README.md for more info. */ diff --git a/src/SSLClientImpl.h b/src/SSLClientImpl.h index 5c570d0..a7dd03f 100644 --- a/src/SSLClientImpl.h +++ b/src/SSLClientImpl.h @@ -70,7 +70,7 @@ enum DebugLevel { /** @brief Implementation code to be inherited by SSLClient */ class SSLClientImpl : public Client { public: - /** See SSLClient::SSLClient */ + /** @see SSLClient::SSLClient */ explicit SSLClientImpl(const br_x509_trust_anchor *trust_anchors, const size_t trust_anchors_num, const int analog_pin, const DebugLevel debug); @@ -96,28 +96,28 @@ public: void stop_impl(); /** @see SSLClient::connected */ uint8_t connected_impl(); - /** See SSLClient::getSession */ + /** @see SSLClient::getSession */ SSLSession& get_session_impl(const char* host, const IPAddress& addr); - /** See SSLClient::removeSession */ + /** @see SSLClient::removeSession */ void remove_session_impl(const char* host, const IPAddress& addr); //============================================ //= Functions implemented in SSLClient.h //============================================ - /** See SSLClient::localPort */ + /** @see SSLClient::localPort */ virtual uint16_t localPort() = 0; - /** See SSLClient::remoteIP */ + /** @see SSLClient::remoteIP */ virtual IPAddress remoteIP() = 0; - /** See SSLClient::localPort */ + /** @see SSLClient::localPort */ virtual uint16_t remotePort() = 0; - /** See SSLClient::getSessionCount */ + /** @see SSLClient::getSessionCount */ virtual size_t getSessionCount() const = 0; protected: - /** See SSLClient::get_arduino_client */ + /** @see SSLClient::get_arduino_client */ virtual Client& get_arduino_client() = 0; virtual const Client& get_arduino_client() const = 0; - /** See SSLClient::get_session_array */ + /** @see SSLClient::get_session_array */ virtual SSLSession* get_session_array() = 0; virtual const SSLSession* get_session_array() const = 0;