From 6ea6b8659ffc2bdff325a3d71c67cc1cfb854c51 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Fri, 2 Mar 2018 16:38:49 -0800 Subject: Isolate TLS functions into separate tls.h header file. --- src/nng.h | 81 ---------------------- src/supplemental/http/http_api.h | 4 +- src/supplemental/http/http_client.c | 1 + src/supplemental/http/http_conn.c | 3 +- src/supplemental/http/http_public.c | 1 + src/supplemental/http/http_server.c | 1 + src/supplemental/tls/CMakeLists.txt | 5 +- src/supplemental/tls/mbedtls/tls.c | 4 +- src/supplemental/tls/none/tls.c | 3 +- src/supplemental/tls/tls.h | 130 +++++++++++++++++++++++++----------- src/supplemental/tls/tls_api.h | 53 +++++++++++++++ src/transport/tls/tls.c | 1 + src/transport/ws/websocket.c | 1 + tests/httpclient.c | 1 + tests/httpserver.c | 1 + tests/tls.c | 2 +- tests/wss.c | 1 + tests/wssfile.c | 2 + tools/nngcat/nngcat.c | 1 + 19 files changed, 171 insertions(+), 125 deletions(-) create mode 100644 src/supplemental/tls/tls_api.h diff --git a/src/nng.h b/src/nng.h index a4f4e5e0..e2cdb8fa 100644 --- a/src/nng.h +++ b/src/nng.h @@ -669,87 +669,6 @@ enum nng_sockaddr_family { NNG_AF_ZT = 5, // ZeroTier }; -// For some transports, we need TLS configuration, including certificates -// and so forth. Note that these symbols are only actually present at link -// time if TLS support is enabled in your build. A TLS configuration cannot -// be changed once it is in use. -typedef struct nng_tls_config nng_tls_config; - -typedef enum nng_tls_mode { - NNG_TLS_MODE_CLIENT = 0, - NNG_TLS_MODE_SERVER = 1, -} nng_tls_mode; - -typedef enum nng_tls_auth_mode { - NNG_TLS_AUTH_MODE_NONE = 0, // No verification is performed - NNG_TLS_AUTH_MODE_OPTIONAL = 1, // Verify cert if presented - NNG_TLS_AUTH_MODE_REQUIRED = 2, // Verify cert, close if invalid -} nng_tls_auth_mode; - -// nng_tls_config_alloc creates a TLS configuration using -// reasonable defaults. This configuration can be shared -// with multiple pipes or services/servers. -NNG_DECL int nng_tls_config_alloc(nng_tls_config **, nng_tls_mode); - -// nng_tls_config_free drops the reference count on the TLS -// configuration object, and if zero, deallocates it. -NNG_DECL void nng_tls_config_free(nng_tls_config *); - -// nng_tls_config_server_name sets the server name. This is -// called by clients to set the name that the server supplied -// certificate should be matched against. This can also cause -// the SNI to be sent to the server to tell it which cert to -// use if it supports more than one. -NNG_DECL int nng_tls_config_server_name(nng_tls_config *, const char *); - -// nng_tls_config_ca_cert configures one or more CAs used for validation -// of peer certificates. Multiple CAs (and their chains) may be configured -// by either calling this multiple times, or by specifying a list of -// certificates as concatenated data. The final argument is an optional CRL -// (revokation list) for the CA, also in PEM. Both PEM strings are ASCIIZ -// format (except that the CRL may be NULL). -NNG_DECL int nng_tls_config_ca_chain( - nng_tls_config *, const char *, const char *); - -// nng_tls_config_own_cert is used to load our own certificate and public -// key. For servers, this may be called more than once to configure multiple -// different keys, for example with different algorithms depending on what -// the peer supports. On the client, only a single option is available. -// The first two arguments are the cert (or validation chain) and the -// key as PEM format ASCIIZ strings. The final argument is an optional -// password and may be NULL. -NNG_DECL int nng_tls_config_own_cert( - nng_tls_config *, const char *, const char *, const char *); - -// nng_tls_config_key is used to pass our own private key. -NNG_DECL int nng_tls_config_key(nng_tls_config *, const uint8_t *, size_t); - -// nng_tls_config_pass is used to pass a password used to decrypt -// private keys that are encrypted. -NNG_DECL int nng_tls_config_pass(nng_tls_config *, const char *); - -// nng_tls_config_auth_mode is used to configure the authentication mode use. -// The default is that servers have this off (i.e. no client authentication) -// and clients have it on (they verify the server), which matches typical -// practice. -NNG_DECL int nng_tls_config_auth_mode(nng_tls_config *, nng_tls_auth_mode); - -// nng_tls_config_ca_file is used to pass a CA chain and optional CRL -// via the filesystem. If CRL data is present, it must be contained -// in the file, along with the CA certificate data. The format is PEM. -// The path name must be a legal file name. -NNG_DECL int nng_tls_config_ca_file(nng_tls_config *, const char *); - -// nng_tls_config_cert_key_file is used to pass our own certificate and -// private key data via the filesystem. Both the key and certificate -// must be present as PEM blocks in the same file. A password is used to -// decrypt the private key if it is encrypted and the password supplied is not -// NULL. This may be called multiple times on servers, but only once on a -// client. (Servers can support multiple different certificates and keys for -// different cryptographic algorithms. Clients only get one.) -NNG_DECL int nng_tls_config_cert_key_file( - nng_tls_config *, const char *, const char *); - // URL support. We frequently want to process a URL, and these methods // give us a convenient way of doing so. diff --git a/src/supplemental/http/http_api.h b/src/supplemental/http/http_api.h index 31c54146..8de859b4 100644 --- a/src/supplemental/http/http_api.h +++ b/src/supplemental/http/http_api.h @@ -12,6 +12,8 @@ #define NNG_SUPPLEMENTAL_HTTP_HTTP_API_H #include "core/nng_impl.h" +#include "supplemental/tls/tls.h" + #include "supplemental/http/http.h" // This represents the "internal" HTTP API. It should not be used @@ -115,7 +117,7 @@ extern void nni_http_write_full(nni_http_conn *, nni_aio *); extern int nni_http_sock_addr(nni_http_conn *, nni_sockaddr *); extern int nni_http_peer_addr(nni_http_conn *, nni_sockaddr *); -// nni_tls_http_verified returns true if the peer has been verified using TLS. +// nni_http_tls_verified returns true if the peer has been verified using TLS. extern bool nni_http_tls_verified(nni_http_conn *); // nni_http_server will look for an existing server with the same diff --git a/src/supplemental/http/http_client.c b/src/supplemental/http/http_client.c index 484a2e72..c62a3c56 100644 --- a/src/supplemental/http/http_client.c +++ b/src/supplemental/http/http_client.c @@ -15,6 +15,7 @@ #include "core/nng_impl.h" #include "supplemental/tls/tls.h" +#include "supplemental/tls/tls_api.h" #include "http_api.h" diff --git a/src/supplemental/http/http_conn.c b/src/supplemental/http/http_conn.c index cdfdbaa9..d37c9a2f 100644 --- a/src/supplemental/http/http_conn.c +++ b/src/supplemental/http/http_conn.c @@ -13,6 +13,7 @@ #include "core/nng_impl.h" #include "supplemental/tls/tls.h" +#include "supplemental/tls/tls_api.h" #include "http_api.h" @@ -760,4 +761,4 @@ nni_http_conn_init_tls(nni_http_conn **connp, nng_tls_config *cfg, void *tcp) nni_plat_tcp_pipe_fini(tcp); return (NNG_ENOTSUP); } -#endif // NNG_SUPP_TLS \ No newline at end of file +#endif // NNG_SUPP_TLS diff --git a/src/supplemental/http/http_public.c b/src/supplemental/http/http_public.c index b2007469..2d879807 100644 --- a/src/supplemental/http/http_public.c +++ b/src/supplemental/http/http_public.c @@ -9,6 +9,7 @@ // #include "core/nng_impl.h" +#include "supplemental/tls/tls.h" #include "http.h" #include "http_api.h" diff --git a/src/supplemental/http/http_server.c b/src/supplemental/http/http_server.c index f8b8c64b..503ab1dd 100644 --- a/src/supplemental/http/http_server.c +++ b/src/supplemental/http/http_server.c @@ -15,6 +15,7 @@ #include "core/nng_impl.h" #include "supplemental/tls/tls.h" +#include "supplemental/tls/tls_api.h" #include "http_api.h" diff --git a/src/supplemental/tls/CMakeLists.txt b/src/supplemental/tls/CMakeLists.txt index 3f77732d..a16745bd 100644 --- a/src/supplemental/tls/CMakeLists.txt +++ b/src/supplemental/tls/CMakeLists.txt @@ -10,9 +10,9 @@ if (NNG_SUPP_TLS) set(NNG_SUPP_TLS_MBEDTLS ON) - set(TLS_SOURCES supplemental/tls/tls.h) set(TLS_DEFINES -DNNG_SUPP_TLS) endif() +set(TLS_SOURCES supplemental/tls/tls.h) # For now we only support the ARM mbedTLS library. if (NNG_SUPP_TLS_MBEDTLS) @@ -38,5 +38,8 @@ else() set(TLS_SOURCES ${TLS_SOURCES} supplemental/tls/none/tls.c) endif() +set(TLS_HEADERS supplemental/tls/tls.h) + set(NNG_DEFINES ${NNG_DEFINES} ${TLS_DEFINES} PARENT_SCOPE) set(NNG_SOURCES ${NNG_SOURCES} ${TLS_SOURCES} PARENT_SCOPE) +set(NNG_HEADERS ${NNG_HEADERS} ${TLS_HEADERS} PARENT_SCOPE) diff --git a/src/supplemental/tls/mbedtls/tls.c b/src/supplemental/tls/mbedtls/tls.c index 1e008668..8faf4e46 100644 --- a/src/supplemental/tls/mbedtls/tls.c +++ b/src/supplemental/tls/mbedtls/tls.c @@ -13,6 +13,7 @@ #include #include + #include "mbedtls/version.h" // Must be first in order to pick up version #include "mbedtls/error.h" @@ -29,6 +30,7 @@ #include "core/nng_impl.h" #include "supplemental/tls/tls.h" +#include "supplemental/tls/tls_api.h" // Implementation note. This implementation buffers data between the TLS // encryption layer (mbedTLS) and the underlying TCP socket. As a result, @@ -980,4 +982,4 @@ void nng_tls_config_free(nng_tls_config *cfg) { nni_tls_config_fini(cfg); -} \ No newline at end of file +} diff --git a/src/supplemental/tls/none/tls.c b/src/supplemental/tls/none/tls.c index beaf322c..8177ff61 100644 --- a/src/supplemental/tls/none/tls.c +++ b/src/supplemental/tls/none/tls.c @@ -18,6 +18,7 @@ #include "core/nng_impl.h" #include "supplemental/tls/tls.h" +#include "supplemental/tls/tls_api.h" void nni_tls_config_fini(nng_tls_config *cfg) @@ -174,4 +175,4 @@ void nng_tls_config_free(nng_tls_config *cfg) { NNI_ARG_UNUSED(cfg); -} \ No newline at end of file +} diff --git a/src/supplemental/tls/tls.h b/src/supplemental/tls/tls.h index 4dd94290..62da9618 100644 --- a/src/supplemental/tls/tls.h +++ b/src/supplemental/tls/tls.h @@ -11,43 +11,97 @@ #ifndef NNG_SUPPLEMENTAL_TLS_TLS_H #define NNG_SUPPLEMENTAL_TLS_TLS_H -#include - -// nni_tls represents the context for a single TLS stream. -typedef struct nni_tls nni_tls; - -// nni_tls_config_init creates a new TLS configuration object. -// The object is created with a reference count of one. -extern int nni_tls_config_init(nng_tls_config **, nng_tls_mode); - -// nni_tls_config_fini drops the reference on the configuration -// object, deallocating if this was the last reference. -extern void nni_tls_config_fini(nng_tls_config *); - -// nni_tls_config_hold is used to get a hold on the config -// object, preventing it from being released inadvertently. -// The hold is released with a call to nng_tls_config_fini(). -// Note that a hold need not be acquired at creation, since -// the configuration object is created with a hold on it. -extern void nni_tls_config_hold(nng_tls_config *); - -extern int nni_tls_init(nni_tls **, nng_tls_config *, nni_plat_tcp_pipe *); -extern void nni_tls_close(nni_tls *); -extern void nni_tls_fini(nni_tls *); -extern void nni_tls_send(nni_tls *, nng_aio *); -extern void nni_tls_recv(nni_tls *, nng_aio *); -extern int nni_tls_sockname(nni_tls *, nni_sockaddr *); -extern int nni_tls_peername(nni_tls *, nni_sockaddr *); - -// nni_tls_verified returns true if the peer, or false if the peer did not -// verify. (During the handshake phase, the peer is not verified, so this -// might return false if executed too soon. The verification status will -// be accurate once the handshake is finished, however. -extern bool nni_tls_verified(nni_tls *); - -// nni_tls_ciphersuite_name returns the name of the ciphersuite in use. -extern const char *nni_tls_ciphersuite_name(nni_tls *); - -// TBD: getting additional peer certificate information... +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +// Note that TLS functions may be stubbed out if TLS is not enabled in +// the build. + +// For some transports, we need TLS configuration, including certificates +// and so forth. A TLS configuration cannot be changed once it is in use. +typedef struct nng_tls_config nng_tls_config; + +typedef enum nng_tls_mode { + NNG_TLS_MODE_CLIENT = 0, + NNG_TLS_MODE_SERVER = 1, +} nng_tls_mode; + +typedef enum nng_tls_auth_mode { + NNG_TLS_AUTH_MODE_NONE = 0, // No verification is performed + NNG_TLS_AUTH_MODE_OPTIONAL = 1, // Verify cert if presented + NNG_TLS_AUTH_MODE_REQUIRED = 2, // Verify cert, close if invalid +} nng_tls_auth_mode; + +// nng_tls_config_alloc creates a TLS configuration using +// reasonable defaults. This configuration can be shared +// with multiple pipes or services/servers. +NNG_DECL int nng_tls_config_alloc(nng_tls_config **, nng_tls_mode); + +// nng_tls_config_free drops the reference count on the TLS +// configuration object, and if zero, deallocates it. +NNG_DECL void nng_tls_config_free(nng_tls_config *); + +// nng_tls_config_server_name sets the server name. This is +// called by clients to set the name that the server supplied +// certificate should be matched against. This can also cause +// the SNI to be sent to the server to tell it which cert to +// use if it supports more than one. +NNG_DECL int nng_tls_config_server_name(nng_tls_config *, const char *); + +// nng_tls_config_ca_cert configures one or more CAs used for validation +// of peer certificates. Multiple CAs (and their chains) may be configured +// by either calling this multiple times, or by specifying a list of +// certificates as concatenated data. The final argument is an optional CRL +// (revokation list) for the CA, also in PEM. Both PEM strings are ASCIIZ +// format (except that the CRL may be NULL). +NNG_DECL int nng_tls_config_ca_chain( + nng_tls_config *, const char *, const char *); + +// nng_tls_config_own_cert is used to load our own certificate and public +// key. For servers, this may be called more than once to configure multiple +// different keys, for example with different algorithms depending on what +// the peer supports. On the client, only a single option is available. +// The first two arguments are the cert (or validation chain) and the +// key as PEM format ASCIIZ strings. The final argument is an optional +// password and may be NULL. +NNG_DECL int nng_tls_config_own_cert( + nng_tls_config *, const char *, const char *, const char *); + +// nng_tls_config_key is used to pass our own private key. +NNG_DECL int nng_tls_config_key(nng_tls_config *, const uint8_t *, size_t); + +// nng_tls_config_pass is used to pass a password used to decrypt +// private keys that are encrypted. +NNG_DECL int nng_tls_config_pass(nng_tls_config *, const char *); + +// nng_tls_config_auth_mode is used to configure the authentication mode use. +// The default is that servers have this off (i.e. no client authentication) +// and clients have it on (they verify the server), which matches typical +// practice. +NNG_DECL int nng_tls_config_auth_mode(nng_tls_config *, nng_tls_auth_mode); + +// nng_tls_config_ca_file is used to pass a CA chain and optional CRL +// via the filesystem. If CRL data is present, it must be contained +// in the file, along with the CA certificate data. The format is PEM. +// The path name must be a legal file name. +NNG_DECL int nng_tls_config_ca_file(nng_tls_config *, const char *); + +// nng_tls_config_cert_key_file is used to pass our own certificate and +// private key data via the filesystem. Both the key and certificate +// must be present as PEM blocks in the same file. A password is used to +// decrypt the private key if it is encrypted and the password supplied is not +// NULL. This may be called multiple times on servers, but only once on a +// client. (Servers can support multiple different certificates and keys for +// different cryptographic algorithms. Clients only get one.) +NNG_DECL int nng_tls_config_cert_key_file( + nng_tls_config *, const char *, const char *); + +#ifdef __cplusplus +} +#endif #endif // NNG_SUPPLEMENTAL_TLS_TLS_H diff --git a/src/supplemental/tls/tls_api.h b/src/supplemental/tls/tls_api.h new file mode 100644 index 00000000..24d8e578 --- /dev/null +++ b/src/supplemental/tls/tls_api.h @@ -0,0 +1,53 @@ +// +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_SUPPLEMENTAL_TLS_TLS_API_H +#define NNG_SUPPLEMENTAL_TLS_TLS_API_H + +#include + +// nni_tls represents the context for a single TLS stream. +typedef struct nni_tls nni_tls; + +// nni_tls_config_init creates a new TLS configuration object. +// The object is created with a reference count of one. +extern int nni_tls_config_init(nng_tls_config **, nng_tls_mode); + +// nni_tls_config_fini drops the reference on the configuration +// object, deallocating if this was the last reference. +extern void nni_tls_config_fini(nng_tls_config *); + +// nni_tls_config_hold is used to get a hold on the config +// object, preventing it from being released inadvertently. +// The hold is released with a call to nng_tls_config_fini(). +// Note that a hold need not be acquired at creation, since +// the configuration object is created with a hold on it. +extern void nni_tls_config_hold(nng_tls_config *); + +extern int nni_tls_init(nni_tls **, nng_tls_config *, nni_plat_tcp_pipe *); +extern void nni_tls_close(nni_tls *); +extern void nni_tls_fini(nni_tls *); +extern void nni_tls_send(nni_tls *, nng_aio *); +extern void nni_tls_recv(nni_tls *, nng_aio *); +extern int nni_tls_sockname(nni_tls *, nni_sockaddr *); +extern int nni_tls_peername(nni_tls *, nni_sockaddr *); + +// nni_tls_verified returns true if the peer, or false if the peer did not +// verify. (During the handshake phase, the peer is not verified, so this +// might return false if executed too soon. The verification status will +// be accurate once the handshake is finished, however. +extern bool nni_tls_verified(nni_tls *); + +// nni_tls_ciphersuite_name returns the name of the ciphersuite in use. +extern const char *nni_tls_ciphersuite_name(nni_tls *); + +// TBD: getting additional peer certificate information... + +#endif // NNG_SUPPLEMENTAL_TLS_TLS_API_H diff --git a/src/transport/tls/tls.c b/src/transport/tls/tls.c index fc993501..f9de3367 100644 --- a/src/transport/tls/tls.c +++ b/src/transport/tls/tls.c @@ -15,6 +15,7 @@ #include "core/nng_impl.h" #include "supplemental/tls/tls.h" +#include "supplemental/tls/tls_api.h" #include "tls.h" // TLS over TCP transport. Platform specific TCP operations must be diff --git a/src/transport/ws/websocket.c b/src/transport/ws/websocket.c index 191f44fb..a8cdcbb0 100644 --- a/src/transport/ws/websocket.c +++ b/src/transport/ws/websocket.c @@ -16,6 +16,7 @@ #include "core/nng_impl.h" #include "supplemental/http/http_api.h" #include "supplemental/tls/tls.h" +#include "supplemental/tls/tls_api.h" #include "supplemental/websocket/websocket.h" #include "websocket.h" diff --git a/tests/httpclient.c b/tests/httpclient.c index 7a38ed8d..db107f74 100644 --- a/tests/httpclient.c +++ b/tests/httpclient.c @@ -17,6 +17,7 @@ // Basic HTTP client tests. #include "core/nng_impl.h" +#include "supplemental/tls/tls.h" #include "supplemental/http/http.h" #include "supplemental/sha1/sha1.h" diff --git a/tests/httpserver.c b/tests/httpserver.c index e24c081f..acbe237a 100644 --- a/tests/httpserver.c +++ b/tests/httpserver.c @@ -17,6 +17,7 @@ // Basic HTTP server tests. #include "core/nng_impl.h" +#include "supplemental/tls/tls.h" #include "supplemental/http/http.h" const char *doc1 = "Someone is home!"; diff --git a/tests/tls.c b/tests/tls.c index 02a89f97..31041fa5 100644 --- a/tests/tls.c +++ b/tests/tls.c @@ -11,7 +11,7 @@ #include "convey.h" #include "nng.h" #include "protocol/pair1/pair.h" - +#include "supplemental/tls/tls.h" #include "transport/tls/tls.h" #include "trantest.h" diff --git a/tests/wss.c b/tests/wss.c index ebb2e310..96dc9bd9 100644 --- a/tests/wss.c +++ b/tests/wss.c @@ -11,6 +11,7 @@ #include "convey.h" #include "nng.h" #include "protocol/pair1/pair.h" +#include "supplemental/tls/tls.h" #include "transport/ws/websocket.h" #include "trantest.h" diff --git a/tests/wssfile.c b/tests/wssfile.c index 82c519e1..8b5b0126 100644 --- a/tests/wssfile.c +++ b/tests/wssfile.c @@ -12,6 +12,8 @@ #include "nng.h" #include "protocol/pair1/pair.h" #include "transport/ws/websocket.h" +#include "supplemental/tls/tls.h" + #include "trantest.h" #include "stubs.h" diff --git a/tools/nngcat/nngcat.c b/tools/nngcat/nngcat.c index 04afe919..2f5ef563 100644 --- a/tools/nngcat/nngcat.c +++ b/tools/nngcat/nngcat.c @@ -28,6 +28,7 @@ #include "protocol/reqrep0/req.h" #include "protocol/survey0/respond.h" #include "protocol/survey0/survey.h" +#include "supplemental/tls/tls.h" #include "supplemental/util/options.h" #include "supplemental/util/platform.h" -- cgit v1.2.3-70-g09d2