-
Notifications
You must be signed in to change notification settings - Fork 126
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added TLS API, and an mbedTLS-based implementation
- Loading branch information
Showing
5 changed files
with
1,095 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/** | ||
* @file mbedtls_socket.h | ||
* | ||
* TLS (SSL) socket implementation using mbedTLS. | ||
* | ||
* @author Jens Alfke | ||
* @author Couchbase, Inc. | ||
* @author www.couchbase.com | ||
* | ||
* @date August 2019 | ||
*/ | ||
|
||
// -------------------------------------------------------------------------- | ||
// This file is part of the "sockpp" C++ socket library. | ||
// | ||
// Copyright (c) 2014-2019 Frank Pagliughi | ||
// All rights reserved. | ||
// | ||
// Redistribution and use in source and binary forms, with or without | ||
// modification, are permitted provided that the following conditions are | ||
// met: | ||
// | ||
// 1. Redistributions of source code must retain the above copyright notice, | ||
// this list of conditions and the following disclaimer. | ||
// | ||
// 2. Redistributions in binary form must reproduce the above copyright | ||
// notice, this list of conditions and the following disclaimer in the | ||
// documentation and/or other materials provided with the distribution. | ||
// | ||
// 3. Neither the name of the copyright holder nor the names of its | ||
// contributors may be used to endorse or promote products derived from this | ||
// software without specific prior written permission. | ||
// | ||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR | ||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
// -------------------------------------------------------------------------- | ||
|
||
#ifndef __sockpp_mbedtls_socket_h | ||
#define __sockpp_mbedtls_socket_h | ||
|
||
#include "sockpp/tls_context.h" | ||
#include "sockpp/tls_socket.h" | ||
#include <memory> | ||
#include <string> | ||
|
||
struct mbedtls_pk_context; | ||
struct mbedtls_ssl_config; | ||
struct mbedtls_x509_crt; | ||
|
||
namespace sockpp { | ||
|
||
/** | ||
* A concrete implementation of \ref tls_context, using the mbedTLS library. | ||
* You probably don't want to use this class directly, unless you want to instantiate a | ||
* custom context so you can have different contexts for different sockets. | ||
*/ | ||
class mbedtls_context : public tls_context { | ||
public: | ||
mbedtls_context(role_t = CLIENT); | ||
~mbedtls_context() override; | ||
|
||
void set_root_certs(const std::string &certData) override; | ||
void allow_invalid_peer_certs(bool) override; | ||
void allow_only_certificate(const std::string &certData) override; | ||
|
||
void allow_only_certificate(mbedtls_x509_crt *certificate); | ||
|
||
/** | ||
* Sets the identity certificate and private key using mbedTLS objects. | ||
*/ | ||
void set_identity(mbedtls_x509_crt *certificate, mbedtls_pk_context *private_key); | ||
|
||
void set_identity(const std::string &certificate_data, | ||
const std::string &private_key_data) override; | ||
|
||
void set_identity_files(const std::string &certificate_file, | ||
const std::string &private_key_file, | ||
const std::string &private_key_password) override; | ||
|
||
std::unique_ptr<tls_socket> wrap_socket(std::unique_ptr<stream_socket> socket, | ||
role_t, | ||
const std::string &peer_name) override; | ||
|
||
role_t role(); | ||
|
||
static mbedtls_x509_crt* get_system_root_certs(); | ||
|
||
private: | ||
struct cert; | ||
|
||
int verify_callback(mbedtls_x509_crt *crt, int depth, uint32_t *flags); | ||
static std::unique_ptr<cert> parse_cert(const std::string &cert_data); | ||
|
||
std::unique_ptr<mbedtls_ssl_config> ssl_config_; | ||
std::unique_ptr<cert> root_certs_; | ||
std::unique_ptr<cert> pinned_cert_; | ||
|
||
static cert *s_system_root_certs; | ||
|
||
friend class mbedtls_socket; | ||
}; | ||
|
||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
/** | ||
* @file tls_context.h | ||
* | ||
* Context object for TLS (SSL) sockets. | ||
* | ||
* @author Jens Alfke | ||
* @author Couchbase, Inc. | ||
* @author www.couchbase.com | ||
* | ||
* @date August 2019 | ||
*/ | ||
|
||
// -------------------------------------------------------------------------- | ||
// This file is part of the "sockpp" C++ socket library. | ||
// | ||
// Copyright (c) 2014-2019 Frank Pagliughi | ||
// All rights reserved. | ||
// | ||
// Redistribution and use in source and binary forms, with or without | ||
// modification, are permitted provided that the following conditions are | ||
// met: | ||
// | ||
// 1. Redistributions of source code must retain the above copyright notice, | ||
// this list of conditions and the following disclaimer. | ||
// | ||
// 2. Redistributions in binary form must reproduce the above copyright | ||
// notice, this list of conditions and the following disclaimer in the | ||
// documentation and/or other materials provided with the distribution. | ||
// | ||
// 3. Neither the name of the copyright holder nor the names of its | ||
// contributors may be used to endorse or promote products derived from this | ||
// software without specific prior written permission. | ||
// | ||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR | ||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
// -------------------------------------------------------------------------- | ||
|
||
#ifndef __sockpp_tls_context_h | ||
#define __sockpp_tls_context_h | ||
|
||
#include "sockpp/platform.h" | ||
#include <memory> | ||
#include <string> | ||
|
||
namespace sockpp { | ||
class connector; | ||
class stream_socket; | ||
class tls_socket; | ||
|
||
/** | ||
* Context / configuration for TLS (SSL) connections; also acts as a factory for | ||
* \ref tls_socket objects. | ||
* | ||
* A single context can be shared by any number of \ref tls_socket instances. | ||
* A context must remain in scope as long as any socket using it remains in scope. | ||
*/ | ||
class tls_context | ||
{ | ||
public: | ||
enum role_t { | ||
CLIENT = 0, | ||
SERVER = 1 | ||
}; | ||
/** | ||
* A singleton context that can be used if you don't need any per-connection | ||
* configuration. | ||
*/ | ||
static tls_context& default_context(); | ||
|
||
virtual ~tls_context() =default; | ||
|
||
/** | ||
* Tells whether the context is initialized and valid. Check this after constructing | ||
* an instance and do not use if not valid. | ||
* @return Zero if valid, a nonzero error code if initialization failed. | ||
* The code may be a POSIX code, or one specific to the TLS library. | ||
*/ | ||
int status() const { | ||
return status_; | ||
} | ||
|
||
operator bool() const { | ||
return status_ == 0; | ||
} | ||
|
||
/** | ||
* Overrides the set of trusted root certificates used for validation. | ||
*/ | ||
virtual void set_root_certs(const std::string &certData) =0; | ||
|
||
/** | ||
* Allows connections to peers whose X.509 certificates are not valid. | ||
* **If enabled, you take responsibility for validating the certificate yourself!** | ||
* @param allow Pass true to allow invalid certs to be used, false to disallow | ||
* (default is false.) | ||
*/ | ||
virtual void allow_invalid_peer_certs(bool allow) =0; | ||
|
||
/** | ||
* Requires that the peer have the exact certificate given. | ||
* This is known as "cert-pinning". It's more secure, but requires that the client | ||
* update its copy of the certificate whenever the server updates it. | ||
* @param certData The X.509 certificate in DER or PEM form; or an empty string for | ||
* no pinning (the default). | ||
*/ | ||
virtual void allow_only_certificate(const std::string &certData) =0; | ||
|
||
virtual void set_identity(const std::string &certificate_data, | ||
const std::string &private_key_data) =0; | ||
|
||
virtual void set_identity_files(const std::string &certificate_file, | ||
const std::string &private_key_file, | ||
const std::string &private_key_password) =0; | ||
|
||
/** | ||
* Creates a new \ref tls_socket instance that wraps the given connector socket. | ||
* The \ref tls_socket takes ownership of the base socket and will close it when | ||
* it's closed. | ||
* When this method returns, the TLS handshake will already have completed; | ||
* be sure to check the stream's status, since the handshake may have failed. | ||
* @param socket The underlying connector socket that TLS will use for I/O. | ||
* @param role CLIENT or SERVER mode. | ||
* @param peer_name The peer's canonical hostname, or other distinguished name, | ||
* to be used for certificate validation. | ||
* @return A new \ref tls_socket to use for secure I/O. | ||
*/ | ||
virtual std::unique_ptr<tls_socket> wrap_socket(std::unique_ptr<stream_socket> socket, | ||
role_t role, | ||
const std::string &peer_name) =0; | ||
|
||
protected: | ||
tls_context() =default; | ||
|
||
/** | ||
* Sets the error status of the context. Call this if initialization fails. | ||
*/ | ||
void set_status(int s) const { | ||
status_ = s; | ||
} | ||
|
||
private: | ||
tls_context(const tls_context&) =delete; | ||
|
||
mutable int status_ =0; | ||
}; | ||
|
||
} | ||
|
||
#endif |
Oops, something went wrong.