From f5672e6884504bec489911efab250dd20c993dbc Mon Sep 17 00:00:00 2001 From: Noah Laptop Date: Wed, 26 Feb 2020 11:54:18 -0800 Subject: [PATCH] halfway through rewrite of mTLS api, need to finish testing RSA support --- src/SSLClient.cpp | 20 +++++-- src/SSLClient.h | 3 +- src/{SSLObj.cpp => SSLClientParameters.cpp} | 24 ++++++-- src/SSLClientParameters.h | 44 ++++++++------ src/SSLObj.h | 63 --------------------- 5 files changed, 59 insertions(+), 95 deletions(-) rename src/{SSLObj.cpp => SSLClientParameters.cpp} (66%) delete mode 100644 src/SSLObj.h diff --git a/src/SSLClient.cpp b/src/SSLClient.cpp index 5153090..284e0f9 100644 --- a/src/SSLClient.cpp +++ b/src/SSLClient.cpp @@ -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) - br_ssl_client_set_single_ec( &m_sslctx, - params->client_cert_chain, - params->chain_len, - ¶ms->ec_key, + if (params.getECKey() != NULL) { + br_ssl_client_set_single_ec( &m_sslctx, + 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) { diff --git a/src/SSLClient.h b/src/SSLClient.h index 28fc932..db9796e 100644 --- a/src/SSLClient.h +++ b/src/SSLClient.h @@ -21,7 +21,6 @@ #include "Client.h" #include "SSLSession.h" #include "SSLClientParameters.h" -#include "SSLObj.h" #include #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 diff --git a/src/SSLObj.cpp b/src/SSLClientParameters.cpp similarity index 66% rename from src/SSLObj.cpp rename to src/SSLClientParameters.cpp index 05fee81..244d427 100644 --- a/src/SSLObj.cpp +++ b/src/SSLClientParameters.cpp @@ -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* vect; + std::vector* 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(dest_ctx); - for (size_t i = 0; i < len; i++) ctx->vect->emplace_back(static_cast(src)[i]); + for (size_t i = 0; i < len; i++) ctx->vect->emplace_back(static_cast(src)[i]); // update index ctx->index += len; } -const std::vector SSLObj::make_vector_pem(const char* data, const size_t len) { +static const std::vector 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 temp; + std::vector temp; // initialize the DER storage context ssl_pem_decode_state state; state.vect = &temp; @@ -52,4 +52,16 @@ const std::vector SSLObj::make_vector_pem(const char* data, const } // else we're good! return temp; -} \ No newline at end of file +} + +static br_skey_decoder_context make_key_from_der(const std::vector& 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(cert, cert + cert_len) : make_vector_pem(cert, cert_len)) + , m_cert_struct{ const_cast(reinterpret_cast(m_cert.data())), m_cert.size() } + , m_key{ make_key_from_der(is_der ? std::vector(key, key + key_len) : make_vector_pem(key, key_len)) } {} \ No newline at end of file diff --git a/src/SSLClientParameters.h b/src/SSLClientParameters.h index 10d478d..15f74cb 100644 --- a/src/SSLClientParameters.h +++ b/src/SSLClientParameters.h @@ -26,17 +26,15 @@ */ #include "bearssl.h" +#undef min +#undef max +#include #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 m_cert; + const br_x509_certificate m_cert_struct; + const br_skey_decoder_context m_key; }; #endif \ No newline at end of file diff --git a/src/SSLObj.h b/src/SSLObj.h deleted file mode 100644 index 8f70ac8..0000000 --- a/src/SSLObj.h +++ /dev/null @@ -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 -#include "bearssl_pem.h" - -#ifndef SSLObj_H_ -#define SSLObj_H_ - -#undef min -#undef max -#include - -/** - * \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 make_vector_pem(const char* data, const size_t len); -} - -#endif \ No newline at end of file