added mutual authentication, tweaked command line tool
This commit is contained in:
parent
0538c30081
commit
4b95e7d7a1
5 changed files with 132 additions and 18 deletions
|
@ -22,6 +22,7 @@
|
|||
#include "Client.h"
|
||||
#include "SSLClientImpl.h"
|
||||
#include "SSLSession.h"
|
||||
#include "SSLClientParameters.h"
|
||||
|
||||
#ifndef SSLClient_H_
|
||||
#define SSLClient_H_
|
||||
|
@ -67,11 +68,35 @@ public:
|
|||
* @param trust_anchors_num The number of objects in the trust_anchors array.
|
||||
* @param analog_pin An analog pin to pull random bytes from, used in seeding the RNG.
|
||||
* @param debug The level of debug logging (use the ::DebugLevel enum).
|
||||
* @param mutual_auth_params Configuration to use for mutual authentication, nullptr to disable mutual auth. (see ::SSLClientParameters).
|
||||
*/
|
||||
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)
|
||||
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)
|
||||
: SSLClientImpl(trust_anchors, trust_anchors_num, analog_pin, debug)
|
||||
, m_client(client)
|
||||
, m_sessions{SSLSession()}
|
||||
, m_sessions{}
|
||||
{
|
||||
// set the timeout to a reasonable number (it can always be changes later)
|
||||
// SSL Connections take a really long time so we don't want to time out a legitimate thing
|
||||
setTimeout(30 * 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as SSLClient::SSLClient(const C &, const br_x509_trust_anchor*, const size_t, const int, const DebugLevel),
|
||||
* but can compile support for mutual authentication.
|
||||
*/
|
||||
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,
|
||||
const SSLClientParameters* mutual_auth_params)
|
||||
: SSLClientImpl(trust_anchors, trust_anchors_num, analog_pin, debug, mutual_auth_params)
|
||||
, m_client(client)
|
||||
, m_sessions{}
|
||||
{
|
||||
// set the timeout to a reasonable number (it can always be changes later)
|
||||
// SSL Connections take a really long time so we don't want to time out a legitimate thing
|
||||
|
|
|
@ -52,9 +52,7 @@ static int freeMemory() {
|
|||
/* see SSLClientImpl.h */
|
||||
SSLClientImpl::SSLClientImpl(const br_x509_trust_anchor *trust_anchors,
|
||||
const size_t trust_anchors_num, const int analog_pin, const DebugLevel debug)
|
||||
: m_trust_anchors(trust_anchors)
|
||||
, m_trust_anchors_num(trust_anchors_num)
|
||||
, m_analog_pin(analog_pin)
|
||||
: m_analog_pin(analog_pin)
|
||||
, m_session_index(0)
|
||||
, m_debug(debug)
|
||||
, m_is_connected(false)
|
||||
|
@ -63,7 +61,7 @@ SSLClientImpl::SSLClientImpl(const br_x509_trust_anchor *trust_anchors,
|
|||
// zero the iobuf just in case it's still garbage
|
||||
memset(m_iobuf, 0, sizeof m_iobuf);
|
||||
// initlalize the various bearssl libraries so they're ready to go when we connect
|
||||
br_client_init_TLS12_only(&m_sslctx, &m_x509ctx, m_trust_anchors, m_trust_anchors_num);
|
||||
br_client_init_TLS12_only(&m_sslctx, &m_x509ctx, trust_anchors, 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);
|
||||
// check if the buffer size is half or full duplex
|
||||
|
@ -71,6 +69,23 @@ SSLClientImpl::SSLClientImpl(const br_x509_trust_anchor *trust_anchors,
|
|||
br_ssl_engine_set_buffer(&m_sslctx.eng, m_iobuf, sizeof m_iobuf, duplex);
|
||||
}
|
||||
|
||||
/* see SSLClientImpl.h */
|
||||
SSLClientImpl::SSLClientImpl(const br_x509_trust_anchor *trust_anchors,
|
||||
const size_t trust_anchors_num, const int analog_pin,
|
||||
const DebugLevel debug, const SSLClientParameters* mutual_auth_params)
|
||||
: SSLClientImpl(trust_anchors, trust_anchors_num, analog_pin, debug) {
|
||||
// if mutual authentication if needed, configure bearssl to support it.
|
||||
if (mutual_auth_params != nullptr)
|
||||
br_ssl_client_set_single_ec( &m_sslctx,
|
||||
mutual_auth_params->client_cert_chain,
|
||||
mutual_auth_params->chain_len,
|
||||
&mutual_auth_params->ec_key,
|
||||
BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
|
||||
BR_KEYTYPE_EC,
|
||||
br_ssl_engine_get_ec(&m_sslctx.eng),
|
||||
&br_ecdsa_i15_sign_asn1);
|
||||
}
|
||||
|
||||
/* see SSLClientImpl.h*/
|
||||
int SSLClientImpl::connect_impl(IPAddress ip, uint16_t port) {
|
||||
const char* func_name = __func__;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "Arduino.h"
|
||||
#include "Client.h"
|
||||
#include "SSLSession.h"
|
||||
#include "SSLClientParameters.h"
|
||||
|
||||
#ifndef SSLClientImpl_H_
|
||||
#define SSLClientImpl_H_
|
||||
|
@ -72,7 +73,13 @@ class SSLClientImpl : public Client {
|
|||
public:
|
||||
/** @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);
|
||||
const size_t trust_anchors_num, const int analog_pin,
|
||||
const DebugLevel debug);
|
||||
|
||||
/** @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, const SSLClientParameters* mutual_auth_params);
|
||||
|
||||
//============================================
|
||||
//= Functions implemented in SSLClientImpl.cpp
|
||||
|
@ -171,10 +178,6 @@ private:
|
|||
//= Data Members
|
||||
//============================================
|
||||
|
||||
// store pointers to the trust anchors
|
||||
// should not be computed at runtime
|
||||
const br_x509_trust_anchor *m_trust_anchors;
|
||||
const size_t m_trust_anchors_num;
|
||||
// store the pin to fetch an RNG see from
|
||||
const int m_analog_pin;
|
||||
// store an index of where a new session can be placed if we don't have any corresponding sessions
|
||||
|
|
66
src/SSLClientParameters.h
Normal file
66
src/SSLClientParameters.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
/* Copyright 2019 OSU OPEnS Lab
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
* software and associated documentation files (the "Software"), to deal in the Software
|
||||
* without restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SSLClientParameters.h
|
||||
*
|
||||
* This file contains a simple utility class to store parameters about an SSL Session
|
||||
* for reuse later.
|
||||
*/
|
||||
|
||||
#include "bearssl.h"
|
||||
|
||||
#ifndef SSLClientParameters_H_
|
||||
#define SSLClientParameters_H_
|
||||
|
||||
/**
|
||||
* This file contains a simple struct to package together all the data required to
|
||||
* use client certificate authentication with SSLClient.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief This struct stores data required for SSLClient to use mutual authentication.
|
||||
*
|
||||
* TLS mutual authentication is a process in which both the server and client
|
||||
* perform cryptographic operations to verify the authenticity of eachother, for more
|
||||
* information check out this article: https://medium.com/sitewards/the-magic-of-tls-x509-and-mutual-authentication-explained-b2162dec4401 .
|
||||
* If this struct is provided to SSLClient::SSLClient, SSLClient will automatically
|
||||
* send a client certificate if one is requested by the server. This will happen for all
|
||||
* SSLClient connections, and may cause issues for websites that do not need mutual authentication---
|
||||
* as a result, please only turn on mutual authentication if you are sure it is neccesary.
|
||||
*
|
||||
* At the moment SSLClient only supports mutual authentication using ECC client certificates.
|
||||
*/
|
||||
|
||||
struct SSLClientParameters {
|
||||
/**
|
||||
* \brief Pointer to the client certificate chain.
|
||||
*
|
||||
* Must be availible in memory AT ALL TIMES, should not be a local object.
|
||||
* Certificates must be ordered from Client->Intermediate->...->Root.
|
||||
*/
|
||||
const br_x509_certificate* client_cert_chain;
|
||||
/** The number of certificates in SSLClientParameters::client_cert_chain */
|
||||
const size_t chain_len;
|
||||
/** The private key corresponding to the first certificate in SSLClientParameters::client_cert_chain */
|
||||
const br_ec_private_key ec_key;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -100,8 +100,10 @@ def download(port, cert_var, cert_length_var, output, use_store, keep_dupes, dom
|
|||
help='the location of the .pem file containing a list of trusted root certificates (default: use certifi.where())')
|
||||
@click.option('--keep-dupes', '-d', is_flag=True, default=False,
|
||||
help='write all certs including any duplicates (default: remove duplicates)')
|
||||
@click.option('--no-verify', '-n', is_flag=True, default=False,
|
||||
help='Do not attempt to match a root certificate to the provided PEM files')
|
||||
@click.argument('cert', type=click.File('r'), nargs=-1)
|
||||
def convert(cert_var, cert_length_var, output, use_store, keep_dupes, cert):
|
||||
def convert(cert_var, cert_length_var, output, use_store, keep_dupes, no_verify, cert):
|
||||
"""Convert PEM certificates into a C header that can be imported into a
|
||||
sketch. Specify each certificate to encode as a separate argument (each
|
||||
must be in PEM format) and they will be merged into a single file.
|
||||
|
@ -132,6 +134,9 @@ def convert(cert_var, cert_length_var, output, use_store, keep_dupes, cert):
|
|||
cert_objs.append(cert_parsed)
|
||||
# find a root certificate for each
|
||||
root_certs = []
|
||||
if no_verify:
|
||||
root_certs = cert_objs
|
||||
else:
|
||||
for i, c in enumerate(cert_objs):
|
||||
cn_hash = c.get_issuer().hash()
|
||||
if cn_hash not in cert_dict:
|
||||
|
|
Loading…
Reference in a new issue