halfway through rewrite of mTLS api, need to finish testing RSA support
This commit is contained in:
parent
801f81ec9b
commit
f5672e6884
5 changed files with 59 additions and 95 deletions
|
@ -272,17 +272,25 @@ void SSLClient::removeSession(const char* host) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* see SSLClient.h */
|
/* see SSLClient.h */
|
||||||
void SSLClient::setMutualAuthParams(const SSLClientParameters* params) {
|
void SSLClient::setMutualAuthParams(const SSLClientParameters& params) {
|
||||||
// if mutual authentication if needed, configure bearssl to support it.
|
// if mutual authentication if needed, configure bearssl to support it.
|
||||||
if (params != nullptr)
|
if (params.getECKey() != NULL) {
|
||||||
br_ssl_client_set_single_ec( &m_sslctx,
|
br_ssl_client_set_single_ec( &m_sslctx,
|
||||||
params->client_cert_chain,
|
params.getCertChain(),
|
||||||
params->chain_len,
|
1,
|
||||||
¶ms->ec_key,
|
params.getECKey(),
|
||||||
BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
|
BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
|
||||||
BR_KEYTYPE_EC,
|
BR_KEYTYPE_EC,
|
||||||
br_ssl_engine_get_ec(&m_sslctx.eng),
|
br_ssl_engine_get_ec(&m_sslctx.eng),
|
||||||
&br_ecdsa_i15_sign_asn1);
|
&br_ecdsa_i15_sign_asn1);
|
||||||
|
}
|
||||||
|
else if (params.getRSAKey() != NULL) {
|
||||||
|
br_ssl_client_set_single_rsa( &m_sslctx,
|
||||||
|
params.getCertChain(),
|
||||||
|
1,
|
||||||
|
params.getRSAKey(),
|
||||||
|
&br_rsa_i15_pkcs1_sign);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SSLClient::m_soft_connected(const char* func_name) {
|
bool SSLClient::m_soft_connected(const char* func_name) {
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include "Client.h"
|
#include "Client.h"
|
||||||
#include "SSLSession.h"
|
#include "SSLSession.h"
|
||||||
#include "SSLClientParameters.h"
|
#include "SSLClientParameters.h"
|
||||||
#include "SSLObj.h"
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#ifndef SSLClient_H_
|
#ifndef SSLClient_H_
|
||||||
|
@ -313,7 +312,7 @@ public:
|
||||||
*
|
*
|
||||||
* @pre SSLClient has not already started an SSL connection.
|
* @pre SSLClient has not already started an SSL connection.
|
||||||
*/
|
*/
|
||||||
void setMutualAuthParams(const SSLClientParameters* params);
|
void setMutualAuthParams(const SSLClientParameters& params);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets a session reference corresponding to a host and IP, or a reference to a empty session if none exist
|
* @brief Gets a session reference corresponding to a host and IP, or a reference to a empty session if none exist
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "SSLObj.h"
|
#include "SSLClientParameters.h"
|
||||||
|
|
||||||
// fix for non-exception arduino platforms
|
// fix for non-exception arduino platforms
|
||||||
#ifdef ADAFRUIT_FEATHER_M0
|
#ifdef ADAFRUIT_FEATHER_M0
|
||||||
|
@ -8,24 +8,24 @@ namespace std {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct ssl_pem_decode_state {
|
struct ssl_pem_decode_state {
|
||||||
std::vector<unsigned char>* vect;
|
std::vector<char>* vect;
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ssl_pem_decode_callback(void *dest_ctx, const void *src, size_t len) {
|
static void ssl_pem_decode_callback(void *dest_ctx, const void *src, size_t len) {
|
||||||
ssl_pem_decode_state* ctx = static_cast<ssl_pem_decode_state*>(dest_ctx);
|
ssl_pem_decode_state* ctx = static_cast<ssl_pem_decode_state*>(dest_ctx);
|
||||||
for (size_t i = 0; i < len; i++) ctx->vect->emplace_back(static_cast<const unsigned char*>(src)[i]);
|
for (size_t i = 0; i < len; i++) ctx->vect->emplace_back(static_cast<const char*>(src)[i]);
|
||||||
// update index
|
// update index
|
||||||
ctx->index += len;
|
ctx->index += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<unsigned char> SSLObj::make_vector_pem(const char* data, const size_t len) {
|
static const std::vector<char> make_vector_pem(const char* data, const size_t len) {
|
||||||
if (data == nullptr || len < 80) return {};
|
if (data == nullptr || len < 80) return {};
|
||||||
// initialize the bearssl PEM context
|
// initialize the bearssl PEM context
|
||||||
br_pem_decoder_context pctx;
|
br_pem_decoder_context pctx;
|
||||||
br_pem_decoder_init(&pctx);
|
br_pem_decoder_init(&pctx);
|
||||||
// create a temporary vector
|
// create a temporary vector
|
||||||
std::vector<unsigned char> temp;
|
std::vector<char> temp;
|
||||||
// initialize the DER storage context
|
// initialize the DER storage context
|
||||||
ssl_pem_decode_state state;
|
ssl_pem_decode_state state;
|
||||||
state.vect = &temp;
|
state.vect = &temp;
|
||||||
|
@ -52,4 +52,16 @@ const std::vector<unsigned char> SSLObj::make_vector_pem(const char* data, const
|
||||||
}
|
}
|
||||||
// else we're good!
|
// else we're good!
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static br_skey_decoder_context make_key_from_der(const std::vector<char>& der) {
|
||||||
|
br_skey_decoder_context out;
|
||||||
|
br_skey_decoder_init(&out);
|
||||||
|
br_skey_decoder_push(&out, der.data(), der.size());
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSLClientParameters::SSLClientParameters(const char* cert, const size_t cert_len, const char* key, const size_t key_len, bool is_der)
|
||||||
|
: m_cert(is_der ? std::vector<char>(cert, cert + cert_len) : make_vector_pem(cert, cert_len))
|
||||||
|
, m_cert_struct{ const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(m_cert.data())), m_cert.size() }
|
||||||
|
, m_key{ make_key_from_der(is_der ? std::vector<char>(key, key + key_len) : make_vector_pem(key, key_len)) } {}
|
|
@ -26,17 +26,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "bearssl.h"
|
#include "bearssl.h"
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#ifndef SSLClientParameters_H_
|
#ifndef SSLClientParameters_H_
|
||||||
#define SSLClientParameters_H_
|
#define SSLClientParameters_H_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This file contains a simple struct to package together all the data required to
|
* \brief This class stores data required for SSLClient to use mutual authentication.
|
||||||
* 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
|
* TLS mutual authentication is a process in which both the server and client
|
||||||
* perform cryptographic operations to verify the authenticity of eachother, for more
|
* perform cryptographic operations to verify the authenticity of eachother, for more
|
||||||
|
@ -49,18 +47,28 @@
|
||||||
* At the moment SSLClient only supports mutual authentication using ECC client certificates.
|
* At the moment SSLClient only supports mutual authentication using ECC client certificates.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct SSLClientParameters {
|
class SSLClientParameters {
|
||||||
/**
|
public:
|
||||||
* \brief Pointer to the client certificate chain.
|
|
||||||
*
|
/*
|
||||||
* Must be availible in memory AT ALL TIMES, should not be a local object.
|
static SSLClientParameters fromECCPEM(const char* cert_pem, const char* key_pem);
|
||||||
* Certificates must be ordered from Client->Intermediate->...->Root.
|
static SSLClientParameters fromECCDER(const char* cert_der, const char* key_der);
|
||||||
*/
|
static SSLClientParameters fromRSAPEM(const char* cert_pem, const char* key_pem);
|
||||||
const br_x509_certificate* client_cert_chain;
|
static SSLClientParameters fromRSADER(const char* cert_der, const char* key_der);
|
||||||
/** 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_x509_certificate* getCertChain() const { return &m_cert_struct; }
|
||||||
const br_ec_private_key ec_key;
|
int getCertType() const { return br_skey_decoder_key_type(&m_key); }
|
||||||
|
const br_ec_private_key* getECKey() const { return br_skey_decoder_get_ec(&m_key); }
|
||||||
|
const br_rsa_private_key* getRSAKey() const { return br_skey_decoder_get_rsa(&m_key); }
|
||||||
|
|
||||||
|
// protected:
|
||||||
|
SSLClientParameters(const char* cert, const size_t cert_len, const char* key, const size_t key_len, bool is_der = false);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::vector<char> m_cert;
|
||||||
|
const br_x509_certificate m_cert_struct;
|
||||||
|
const br_skey_decoder_context m_key;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
63
src/SSLObj.h
63
src/SSLObj.h
|
@ -1,63 +0,0 @@
|
||||||
/* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SSLObj.h
|
|
||||||
*
|
|
||||||
* This file contains a utility class to take PEM input and store it as a DER object
|
|
||||||
* for later use by BearSSL.
|
|
||||||
*/
|
|
||||||
#include <cstring>
|
|
||||||
#include "bearssl_pem.h"
|
|
||||||
|
|
||||||
#ifndef SSLObj_H_
|
|
||||||
#define SSLObj_H_
|
|
||||||
|
|
||||||
#undef min
|
|
||||||
#undef max
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief This namespace works with raw DER byte arrays for use later with TLS mutual auth.
|
|
||||||
*
|
|
||||||
* This namespace was created to store some of the values stored in ::SSLClientParameters,
|
|
||||||
* which allow BearSSL use client certificates when creating a TLS connection. Since
|
|
||||||
* most certificates are transmitted over the internet in PEM format, a certificate can
|
|
||||||
* be provided in PEM or DER format, and will be converted internally to DER format for
|
|
||||||
* later use.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace SSLObj {
|
|
||||||
/**
|
|
||||||
* @brief Convert a PEM buffer into a vector of raw DER bytes
|
|
||||||
*
|
|
||||||
* This function takes a PEM buffer (e.g. `----BEGIN CERTIFICATE...`) and converts
|
|
||||||
* it into a vector of raw bytes. The bytes given to this function must:
|
|
||||||
* * Contain both the `-----BEGIN XXX-----` and `-----END XXX-----` strings. These are
|
|
||||||
* removed during processing.
|
|
||||||
* * Have a base64 encoded body
|
|
||||||
* * Only contain a single object (certificate, private key, etc.).
|
|
||||||
*
|
|
||||||
* @returns The raw bytes decoded from the PEM file.
|
|
||||||
*/
|
|
||||||
const std::vector<unsigned char> make_vector_pem(const char* data, const size_t len);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in a new issue