WIP: Adds MbedTLS support to Cytoplasm #54

Draft
lda wants to merge 9 commits from lda/Cytoplasm:add-mbed into master
6 changed files with 390 additions and 0 deletions
Showing only changes of commit c1d59b2c6f - Show all commits

View file

@ -5,6 +5,20 @@ Cytoplasm. It is intended to be updated with every commit that makes a user-faci
change worth reporting in the change log. As such, it changes frequently between change worth reporting in the change log. As such, it changes frequently between
releases. Final change log entries are published as [Releases](releases). releases. Final change log entries are published as [Releases](releases).
## v0.5.0
**TO BE WRITTEN**
### Breaking Changes
- `ShaToHex` now requires what hash was used.
### New Features
- LMDB support is available with the `--with-lmdb` flag.
- MbedTLS summort is available with the `--with-mbed` flag. Please note that Cytoplasm
programs using it must be used with the `CYTO_TLS_CA` environment defined to map to a
valid CA file, and that the `CYTO_TLS_SEED` flag can be set to use a seedfile, increasing
entropy on systems where it is unavailable.
## v0.4.1 ## v0.4.1
Cytoplasm is now a C99 library! Upgrading from C89 to C99 makes Cytoplasm more portable Cytoplasm is now a C99 library! Upgrading from C89 to C99 makes Cytoplasm more portable

4
configure vendored
View file

@ -76,6 +76,10 @@ for arg in $SCRIPT_ARGS; do
TLS_IMPL="TLS_LIBRESSL" TLS_IMPL="TLS_LIBRESSL"
TLS_LIBS="-ltls -lcrypto -lssl" TLS_LIBS="-ltls -lcrypto -lssl"
;; ;;
--with-mbed)
TLS_IMPL="TLS_MBEDTLS"
TLS_LIBS="-lmbedtls"
;;
--disable-tls) --disable-tls)
TLS_IMPL="" TLS_IMPL=""
TLS_LIBS="" TLS_LIBS=""

View file

@ -50,6 +50,7 @@
#define TLS_LIBRESSL 2 #define TLS_LIBRESSL 2
#define TLS_OPENSSL 3 #define TLS_OPENSSL 3
#define TLS_MBEDTLS 4
/** /**
* Create a new TLS client stream using the given file descriptor and * Create a new TLS client stream using the given file descriptor and

View file

@ -29,6 +29,7 @@
#include <limits.h> #include <limits.h>
/* TODO: Verify LibreSSL support later */ /* TODO: Verify LibreSSL support later */
#include <Tls.h>
#if defined(TLS_IMPL) && (TLS_IMPL == TLS_OPENSSL) #if defined(TLS_IMPL) && (TLS_IMPL == TLS_OPENSSL)
#include <openssl/sha.h> #include <openssl/sha.h>

View file

@ -31,6 +31,7 @@
/* TODO: Verify LibreSSL support later */ /* TODO: Verify LibreSSL support later */
#include <Tls.h>
#if defined(TLS_IMPL) && (TLS_IMPL == TLS_OPENSSL) #if defined(TLS_IMPL) && (TLS_IMPL == TLS_OPENSSL)
#include <openssl/sha.h> #include <openssl/sha.h>

369
src/Tls/TlsMbedTLS.c Normal file
View file

@ -0,0 +1,369 @@
/*
* Copyright (C) 2022-2024 Jordan Bancino <@jordan:bancino.net> with
* other valuable contributors. See CONTRIBUTORS.txt for the full list.
*
* 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 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.
*/
#include <Tls.h>
#if TLS_IMPL == TLS_MBEDTLS
#include "mbedtls/net_sockets.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/debug.h"
#include "mbedtls/error.h"
#include <Memory.h>
#include <Log.h>
#include <string.h>
/*
* #include statements and any implementation structures
* needed should go here.
*/
typedef struct MbedCookie {
int fd;
bool serverside;
mbedtls_net_context serverFD;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctrDrbg;
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
mbedtls_x509_crt cert;
mbedtls_pk_context serverkey;
} MbedCookie;
static void my_debug(void *ctx, int level,
const char *file, int line,
const char *str)
{
((void) level);
fprintf((FILE *) ctx, "%s:%04d: %s\n", file, line, str);
fflush((FILE *) ctx);
}
void *
TlsInitClient(int fd, const char *serverName)
{
MbedCookie *cookie;
char *cafile;
char *seed;
int err;
if (!serverName)
{
return NULL;
}
cookie = Malloc(sizeof(MbedCookie));
memset(cookie, 0, sizeof(MbedCookie));
cookie->fd = fd;
cookie->serverside = false;
/* Initialise MbedTLS */
mbedtls_net_init(&cookie->serverFD);
mbedtls_ssl_init(&cookie->ssl);
mbedtls_ssl_config_init(&cookie->conf);
mbedtls_x509_crt_init(&cookie->cert);
mbedtls_ctr_drbg_init(&cookie->ctrDrbg);
mbedtls_pk_init(&cookie->serverkey);
mbedtls_entropy_init(&cookie->entropy);
err = mbedtls_ctr_drbg_seed(
&cookie->ctrDrbg,
mbedtls_entropy_func,
&cookie->entropy,
(const unsigned char *) serverName, strlen(serverName)
);
if (err != 0)
{
Log(LOG_ERR, "MbedTLS failure on client init: %d", err);
goto error;
}
/* Add a source of entropy if possible(using the CYTO_TLS_SEED env).
* Note that we ignore the error code. */
seed = getenv("CYTO_TLS_SEED");
mbedtls_entropy_update_seed_file(&cookie->entropy, seed);
/* TODO */
cookie->serverFD.fd = fd;
err = mbedtls_ssl_config_defaults(
&cookie->conf,
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT
);
if (err != 0)
{
char message[256];
mbedtls_strerror(err, message, 255);
Log(LOG_ERR, "MbedTLS failure on client certs: %s", message);
goto error;
}
/* Setup key verification */
cafile = getenv("CYTO_TLS_CA");
if ((err = mbedtls_x509_crt_parse_file(&cookie->cert, cafile)) != 0)
{
char message[256];
mbedtls_strerror(err, message, 255);
Log(LOG_ERR, "MbedTLS failure on client certs: %s", message);
//goto error;
}
mbedtls_ssl_conf_ca_chain(&cookie->conf, &cookie->cert, NULL);
/* Setup some callbacks */
mbedtls_ssl_conf_rng(
&cookie->conf,
mbedtls_ctr_drbg_random,
&cookie->ctrDrbg
);
mbedtls_ssl_conf_dbg(&cookie->conf, my_debug, stdout);
if ((err = mbedtls_ssl_setup(&cookie->ssl, &cookie->conf)) != 0)
{
char message[256];
mbedtls_strerror(err, message, 255);
Log(LOG_ERR, "MbedTLS failure on SSL setup: %s", message);
goto error;
}
/* Setup the servername */
if ((err = mbedtls_ssl_set_hostname(&cookie->ssl, serverName)) != 0)
{
char message[256];
mbedtls_strerror(err, message, 255);
Log(LOG_ERR, "MbedTLS failure on client hostname: %s", message);
goto error;
}
/* Setup some functions */
mbedtls_ssl_set_bio(
&cookie->ssl, &cookie->serverFD,
mbedtls_net_send, mbedtls_net_recv, NULL
);
return cookie;
error:
mbedtls_net_free(&cookie->serverFD);
mbedtls_ssl_free(&cookie->ssl);
mbedtls_ssl_config_free(&cookie->conf);
mbedtls_ctr_drbg_free(&cookie->ctrDrbg);
mbedtls_entropy_free(&cookie->entropy);
Free(cookie);
return NULL;
}
void *
TlsInitServer(int fd, const char *crt, const char *key)
{
MbedCookie *cookie;
char *seed;
int err;
if (!crt || !key)
{
return NULL;
}
cookie = Malloc(sizeof(MbedCookie));
memset(cookie, 0, sizeof(MbedCookie));
cookie->fd = fd;
cookie->serverside = true;
/* Initialise MbedTLS */
mbedtls_net_init(&cookie->serverFD);
mbedtls_ssl_init(&cookie->ssl);
mbedtls_ssl_config_init(&cookie->conf);
mbedtls_x509_crt_init(&cookie->cert);
mbedtls_ctr_drbg_init(&cookie->ctrDrbg);
mbedtls_pk_init(&cookie->serverkey);
mbedtls_entropy_init(&cookie->entropy);
err = mbedtls_ctr_drbg_seed(
&cookie->ctrDrbg,
mbedtls_entropy_func,
&cookie->entropy,
(const unsigned char *) key, strlen(key)
);
if (err != 0)
{
Log(LOG_ERR, "MbedTLS failure on server init: %d", err);
goto error;
}
/* Add a source of entropy if possible(using the CYTO_TLS_SEED env).
* Note that we ignore the error code. */
seed = getenv("CYTO_TLS_SEED");
mbedtls_entropy_update_seed_file(&cookie->entropy, seed);
/* Setup key verification */
if ((err = mbedtls_x509_crt_parse_file(&cookie->cert, crt)) != 0)
{
char message[256];
mbedtls_strerror(err, message, 255);
Log(LOG_ERR, "MbedTLS failure on server certs: %s", message);
goto error;
}
if ((err = mbedtls_pk_parse_keyfile(&cookie->serverkey, key, NULL)) != 0)
{
char message[256];
mbedtls_strerror(err, message, 255);
Log(LOG_ERR, "MbedTLS failure on server certs: %s", message);
goto error;
}
mbedtls_ssl_conf_ca_chain(&cookie->conf, cookie->cert.next, NULL);
if ((err = mbedtls_ssl_conf_own_cert(&cookie->conf, &cookie->cert, &cookie->serverkey)) != 0)
{
char message[256];
mbedtls_strerror(err, message, 255);
Log(LOG_ERR, "MbedTLS failure on server certs: %s", message);
goto error;
}
/* Setup SSL */
cookie->serverFD.fd = fd;
err = mbedtls_ssl_config_defaults(
&cookie->conf,
MBEDTLS_SSL_IS_SERVER,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT
);
if (err != 0)
{
char message[256];
mbedtls_strerror(err, message, 255);
Log(LOG_ERR, "MbedTLS failure on server SSL: %s", message);
goto error;
}
/* Setup some callbacks */
mbedtls_ssl_conf_rng(
&cookie->conf,
mbedtls_ctr_drbg_random,
&cookie->ctrDrbg
);
mbedtls_ssl_conf_dbg(&cookie->conf, my_debug, stdout);
mbedtls_ssl_conf_ca_chain(&cookie->conf, cookie->cert.next, NULL);
if ((err = mbedtls_ssl_setup(&cookie->ssl, &cookie->conf)) != 0)
{
char message[256];
mbedtls_strerror(err, message, 255);
Log(LOG_ERR, "MbedTLS failure on SSL setup: %s", message);
goto error;
}
/* Client connexion */
/* Setup some functions */
mbedtls_ssl_set_bio(
&cookie->ssl, &cookie->serverFD,
mbedtls_net_send, mbedtls_net_recv, NULL
);
/* Handshake the client */
while ((err = mbedtls_ssl_handshake(&cookie->ssl)) != 0)
{
switch (err)
{
case MBEDTLS_ERR_SSL_WANT_WRITE:
case MBEDTLS_ERR_SSL_WANT_READ:
break;
default:
goto error;
}
}
return cookie;
error:
mbedtls_net_free(&cookie->serverFD);
mbedtls_ssl_free(&cookie->ssl);
mbedtls_ssl_config_free(&cookie->conf);
mbedtls_ctr_drbg_free(&cookie->ctrDrbg);
mbedtls_entropy_free(&cookie->entropy);
Free(cookie);
return NULL;
}
ssize_t
TlsRead(void *cookie, void *buf, size_t nBytes)
{
MbedCookie *cooked = cookie;
int ret;
if (!cookie || !buf)
{
return -1;
}
ret = mbedtls_ssl_read(&cooked->ssl, buf, nBytes);
if (ret <= 0)
{
ret = -1;
}
return ret;
}
ssize_t
TlsWrite(void *cookie, void *buf, size_t nBytes)
{
MbedCookie *cooked = cookie;
int ret;
if (!cookie || !buf)
{
return -1;
}
ret = mbedtls_ssl_write(&cooked->ssl, buf, nBytes);
if (ret <= 0)
{
ret = -1;
}
return ret;
}
int
TlsClose(void *cookie)
{
MbedCookie *cooked = cookie;
if (!cookie)
{
return -1;
}
mbedtls_net_free(&cooked->serverFD);
mbedtls_ssl_free(&cooked->ssl);
mbedtls_ssl_config_free(&cooked->conf);
mbedtls_ctr_drbg_free(&cooked->ctrDrbg);
mbedtls_entropy_free(&cooked->entropy);
mbedtls_x509_crt_free(&cooked->cert);
if (cooked->serverside)
{
mbedtls_pk_free(&cooked->serverkey);
}
Free(cooked);
return 0;
}
#endif