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 */
|
||||
void SSLClient::setMutualAuthParams(const SSLClientParameters* params) {
|
||||
void SSLClient::setMutualAuthParams(const SSLClientParameters& params) {
|
||||
// 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,
|
||||
params->client_cert_chain,
|
||||
params->chain_len,
|
||||
¶ms->ec_key,
|
||||
params.getCertChain(),
|
||||
1,
|
||||
params.getECKey(),
|
||||
BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
|
||||
BR_KEYTYPE_EC,
|
||||
br_ssl_engine_get_ec(&m_sslctx.eng),
|
||||
&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) {
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "Client.h"
|
||||
#include "SSLSession.h"
|
||||
#include "SSLClientParameters.h"
|
||||
#include "SSLObj.h"
|
||||
#include <vector>
|
||||
|
||||
#ifndef SSLClient_H_
|
||||
|
@ -313,7 +312,7 @@ public:
|
|||
*
|
||||
* @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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "SSLObj.h"
|
||||
#include "SSLClientParameters.h"
|
||||
|
||||
// fix for non-exception arduino platforms
|
||||
#ifdef ADAFRUIT_FEATHER_M0
|
||||
|
@ -8,24 +8,24 @@ namespace std {
|
|||
#endif
|
||||
|
||||
struct ssl_pem_decode_state {
|
||||
std::vector<unsigned char>* vect;
|
||||
std::vector<char>* vect;
|
||||
size_t index = 0;
|
||||
};
|
||||
|
||||
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);
|
||||
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
|
||||
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 {};
|
||||
// initialize the bearssl PEM context
|
||||
br_pem_decoder_context pctx;
|
||||
br_pem_decoder_init(&pctx);
|
||||
// create a temporary vector
|
||||
std::vector<unsigned char> temp;
|
||||
std::vector<char> temp;
|
||||
// initialize the DER storage context
|
||||
ssl_pem_decode_state state;
|
||||
state.vect = &temp;
|
||||
|
@ -53,3 +53,15 @@ const std::vector<unsigned char> SSLObj::make_vector_pem(const char* data, const
|
|||
// else we're good!
|
||||
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"
|
||||
#undef min
|
||||
#undef max
|
||||
#include <vector>
|
||||
|
||||
#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.
|
||||
* \brief This class 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
|
||||
|
@ -49,18 +47,28 @@
|
|||
* 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;
|
||||
class SSLClientParameters {
|
||||
public:
|
||||
|
||||
/*
|
||||
static SSLClientParameters fromECCPEM(const char* cert_pem, const char* key_pem);
|
||||
static SSLClientParameters fromECCDER(const char* cert_der, const char* key_der);
|
||||
static SSLClientParameters fromRSAPEM(const char* cert_pem, const char* key_pem);
|
||||
static SSLClientParameters fromRSADER(const char* cert_der, const char* key_der);
|
||||
*/
|
||||
|
||||
const br_x509_certificate* getCertChain() const { return &m_cert_struct; }
|
||||
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
|
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