mbedsock: Init

This commit is contained in:
2022-11-07 23:20:45 +01:00
parent 276ad4f22b
commit 4ef73546aa
17 changed files with 911 additions and 1 deletions

16
mbedsock/CMakeLists.txt Normal file
View File

@@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.7 FATAL_ERROR)
project(mbedsock VERSION 1.0.0 LANGUAGES C)
add_library(mbedsock SHARED mbedsock.c mbedsock.h mbedsock.def)
target_include_directories(mbedsock PUBLIC ${MBEDTLS_ROOT_DIR}/include)
target_link_libraries(mbedsock mbedtls mbedx509 mbedcrypto)
link_directories(${MBEDTLS_ROOT_DIR}/lib)
set_target_properties(mbedsock PROPERTIES
PUBLIC_HEADER mbedsock.h
VERSION ${PROJECT_VERSION}
SOVERSION 1
OUTPUT_NAME "mbedsock"
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Hex_Identity_ID_Goes_Here"
)
install(TARGETS mbedsock)

188
mbedsock/mbedsock.c Normal file
View File

@@ -0,0 +1,188 @@
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedsock.h"
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
struct mbedsock_ctx *mbedsock_ctx_new_ex(const char *capath) {
struct mbedsock_ctx *ctx = malloc(sizeof(struct mbedsock_ctx));
mbedsock_ctx_new(ctx, capath);
return ctx;
}
struct mbedsock *mbedsock_new_ex(struct mbedsock_ctx *ctx) {
struct mbedsock *sock = malloc(sizeof(struct mbedsock));
mbedsock_new(ctx, sock);
return sock;
}
int mbedsock_ctx_new(struct mbedsock_ctx *ctx, const char *capath) {
int ret = 1;
mbedtls_x509_crt_init(&ctx->chain);
mbedtls_ctr_drbg_init(&ctx->ctr_drbg);
mbedtls_entropy_init(&ctx->entropy);
if ((ret = mbedtls_ctr_drbg_seed(&ctx->ctr_drbg, mbedtls_entropy_func, &ctx->entropy,
(unsigned char *) SSL_PERS,
SSL_PERS_LEN)) != 0)
return ret;
if((ret = mbedtls_x509_crt_parse_path(&ctx->chain, capath)) < 0 )
return ret;
return 0;
}
int mbedsock_new(struct mbedsock_ctx *ctx, struct mbedsock *sock) {
int ret = 1;
mbedtls_net_init(&sock->server_fd);
mbedtls_ssl_init(&sock->ssl);
mbedtls_ssl_config_init(&sock->conf);
mbedtls_ssl_conf_authmode(&sock->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
mbedtls_ssl_conf_ca_chain(&sock->conf, &ctx->chain, NULL);
mbedtls_ssl_conf_rng(&sock->conf, mbedtls_ctr_drbg_random, &ctx->ctr_drbg);
if ((ret = mbedtls_ssl_setup(&sock->ssl, &sock->conf)) != 0)
return ret;
mbedtls_ssl_set_bio(&sock->ssl, &sock->server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
if ((ret = mbedtls_ssl_config_defaults(&sock->conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
return ret;
sock->secure = false;
return 0;
}
void mbedsock_free(struct mbedsock *sock) {
mbedtls_net_free(&sock->server_fd);
mbedtls_ssl_free(&sock->ssl);
mbedtls_ssl_config_free(&sock->conf);
}
void mbedsock_ctx_free(struct mbedsock_ctx *ctx) {
mbedtls_x509_crt_free(&ctx->chain);
mbedtls_ctr_drbg_free(&ctx->ctr_drbg);
mbedtls_entropy_free(&ctx->entropy);
}
void mbedsock_free_ex(struct mbedsock *sock) {
mbedsock_free(sock);
free(sock);
}
void mbedsock_ctx_free_ex(struct mbedsock_ctx *ctx) {
mbedsock_ctx_free(ctx);
free(ctx);
}
int mbedsock_do_handshake(struct mbedsock *sock, const char *alpn, const char *sni) {
int ret = 1;
// Set ALPN, if desired
if (alpn != NULL) {
const char *alpn_list[2];
alpn_list[0] = alpn;
alpn_list[1] = NULL;
if ((ret = mbedtls_ssl_conf_alpn_protocols(&sock->conf, alpn_list)) != 0) {
return ret;
}
}
// Set SNI, if desired
if (sni != NULL) {
if ((ret = mbedtls_ssl_set_hostname(&sock->ssl, sni)) != 0) {
return ret;
}
}
while ((ret = mbedtls_ssl_handshake(&sock->ssl)) != 0) {
if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
return ret;
}
// Verify the certificates
if ((ret = mbedtls_ssl_get_verify_result(&sock->ssl)) != 0) {
return ret;
}
sock->secure = true;
return 0;
}
int mbedsock_connect_secure(struct mbedsock *sock, const char *host, const char *port, const char *alpn, const char *sni) {
int ret = 1;
if ((ret = mbedtls_net_connect(&sock->server_fd, host, port, MBEDTLS_NET_PROTO_TCP)) != 0)
return ret;
if ((ret = mbedsock_do_handshake(sock, alpn, sni)))
return ret;
return 0;
}
int mbedsock_connect(struct mbedsock *sock, const char *host, const char *port) {
return mbedtls_net_connect(&sock->server_fd, host, port, MBEDTLS_NET_PROTO_TCP);
}
int mbedsock_write(struct mbedsock *sock, const unsigned char *data, int len) {
int ret = 1;
if (sock->secure) {
while ((ret = mbedtls_ssl_write(&sock->ssl, data, len)) <= 0) {
if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
return -1;
}
} else {
if ((ret = mbedtls_net_send(&sock->server_fd, data, len)) <= 0)
return -1;
}
return ret;
}
int mbedsock_read(struct mbedsock *sock, unsigned char *buf, int len) {
int ret = 1;
memset(buf, 0, len);
if (sock->secure) {
do {
ret = mbedtls_ssl_read(&sock->ssl, buf, len);
if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)
continue;
// TODO: Notify
if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
break;
if (ret < 0)
return -1;
return ret;
} while (true);
} else {
ret = mbedtls_net_recv(&sock->server_fd, buf, len);
if (ret < 0)
return -1;
return ret;
}
return 0;
}
bool mbedsock_is_secure(struct mbedsock *sock) {
return sock->secure;
}

4
mbedsock/mbedsock.def Normal file
View File

@@ -0,0 +1,4 @@
LIBRARY mbedsock
EXPORTS
mbedsock_ctx_new
mbedsock_new

109
mbedsock/mbedsock.h Normal file
View File

@@ -0,0 +1,109 @@
#ifndef __MBEDSOCK_H__
#define __MBEDSOCK_H__
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/ctr_drbg.h"
#include <stdbool.h>
#define SSL_PERS "moxxmpp_socket"
#define SSL_PERS_LEN sizeof(SSL_PERS)/sizeof(char)
/*
* The context for the sockets. This must be created once and is shared between all
* sockets.
*/
struct mbedsock_ctx {
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_x509_crt chain;
};
/*
* The data for the socket.
*/
struct mbedsock {
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
mbedtls_net_context server_fd;
// Indicates whether the socket is secured using TLS (true) or not (false).
bool secure;
};
/*
* Create a new mbedsock_ctx context and write it to @ctx. @capath is the path
* to the directory containing the system's .crt root CA files.
*
* Returns true if everything went well; something non-zero on errors.
*/
int mbedsock_ctx_new(struct mbedsock_ctx *ctx, const char *capath);
struct mbedsock_ctx *mbedsock_ctx_new_ex(const char *capath);
/*
* Create a new socket using the context @ctx and writes it to @sock. Returns zero
* on success; something non-zero on error.
*/
int mbedsock_new(struct mbedsock_ctx *ctx, struct mbedsock *sock);
struct mbedsock *mbedsock_new_ex(struct mbedsock_ctx *ctx);
/*
* Free the resources used by @sock.
*/
void mbedsock_free(struct mbedsock *sock);
void mbedsock_free_ex(struct mbedsock *sock);
/*
* Free the resources used by @ctx.
*/
void mbedsock_ctx_free(struct mbedsock_ctx *ctx);
void mbedsock_ctx_free_ex(struct mbedsock_ctx *ctx);
/*
* Performs the TLS handshake and upgrades the connection @sock to a secured one.
* If @alpn is not NULL, then its value will be used for TLS ALPN. If @sni is not NULL,
* then its value will be used for Server Name Indication.
*
* Returns 0 on success; something non-zero on failure.
*/
int mbedsock_do_handshake(struct mbedsock *sock, const char *alpn, const char *sni);
/*
* Use socket @sock to to connect to @host:@port and immediately call
* mbedsock_do_handshake. @alpn and @sni are used for mbedsock_do_handshake.
*
* Returns 0 on success; something non-zero on failure.
*/
int mbedsock_connect_secure(struct mbedsock *sock, const char *host, const char *port, const char *alpn, const char *sni);
/*
* Use socket @sock to to connect to @host:@port. The socket is not secured on success.
*
* Returns 0 on success; something non-zero on failure.
*/
int mbedsock_connect(struct mbedsock *sock, const char *host, const char *port);
/*
* Write @data - @len being the amount of bytes in data to read - to @sock. The function
* uses @sock's secure attribute to decide whether to use TLS or not.
*
* Returns the amount of bytes written on success. The documentation for
* mbedtls_ssl_write and mbedtls_net_send apply for the return value. Returns -1
* if an error occurred.
*/
int mbedsock_write(struct mbedsock *sock, const unsigned char *data, int len);
/*
* Read data from @sock into @buf. @len is the size of the buffer.
*
* Returns the amount of bytes read on success. The documentation for
* mbedtls_ssl_read and mbedtls_net_recv apply for the return value. Returns -1
* if an error occurred.
*/
int mbedsock_read(struct mbedsock *sock, unsigned char *buf, int len);
bool mbedsock_is_secure(struct mbedsock *sock);
#endif // __MBEDSOCK_H__