esp-open-rtos/examples/aws_iot/ssl_connection.c

171 lines
4.9 KiB
C
Raw Normal View History

#include <espressif/esp_common.h>
#include <lwip/sockets.h>
#include <lwip/inet.h>
#include <lwip/netdb.h>
#include <lwip/sys.h>
#include <string.h>
// this must be ahead of any mbedtls header files so the local mbedtls/config.h can be properly referenced
#include "ssl_connection.h"
#define SSL_READ_TIMEOUT_MS 2000
const char *pers = "esp-tls";
static int handle_error(int err) {
#ifdef MBEDTLS_ERROR_C
char error_buf[100];
mbedtls_strerror(err, error_buf, 100);
printf("%s\n", error_buf);
#endif
printf("Error: %d\n", err);
return err;
}
#ifdef MBEDTLS_DEBUG_C
static void my_debug(void *ctx, int level, const char *file, int line,
const char *str) {
((void) level);
fprintf((FILE *) ctx, "%s:%04d: %s", file, line, str);
fflush((FILE *) ctx);
}
#endif
void ssl_init(SSLConnection* conn) {
/*
* Initialize the RNG and the session data
*/
mbedtls_net_init(&conn->net_ctx);
mbedtls_ssl_init(&conn->ssl_ctx);
mbedtls_ssl_config_init(&conn->ssl_conf);
mbedtls_x509_crt_init(&conn->ca_cert);
mbedtls_x509_crt_init(&conn->client_cert);
mbedtls_pk_init(&conn->client_key);
mbedtls_ctr_drbg_init(&conn->drbg_ctx);
mbedtls_entropy_init(&conn->entropy_ctx);
}
int ssl_connect(SSLConnection* conn, const char* host, int port) {
int ret;
char buffer[8];
ret = mbedtls_ctr_drbg_seed(&conn->drbg_ctx, mbedtls_entropy_func,
&conn->entropy_ctx, (const unsigned char *) pers, strlen(pers));
if (ret < 0) {
return -1;
}
ret = mbedtls_x509_crt_parse(&conn->ca_cert,
(const unsigned char *) conn->ca_cert_str,
strlen(conn->ca_cert_str) + 1);
if (ret < 0) {
return handle_error(ret);
}
ret = mbedtls_x509_crt_parse(&conn->client_cert,
(const unsigned char *) conn->client_cert_str,
strlen(conn->client_cert_str) + 1);
if (ret < 0) {
return handle_error(ret);
}
ret = mbedtls_pk_parse_key(&conn->client_key,
(const unsigned char *) conn->client_key_str,
strlen(conn->client_key_str) + 1, NULL, 0);
if (ret != 0) {
return handle_error(ret);
}
snprintf(buffer, sizeof(buffer), "%d", port);
ret = mbedtls_net_connect(&conn->net_ctx, host, buffer,
MBEDTLS_NET_PROTO_TCP);
if (ret != 0) {
return handle_error(ret);
}
ret = mbedtls_ssl_config_defaults(&conn->ssl_conf, MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
if (ret != 0) {
return handle_error(ret);
}
#ifdef MBEDTLS_DEBUG_C
mbedtls_ssl_conf_dbg(&conn->ssl_conf, my_debug, stdout);
mbedtls_debug_set_threshold(5);
#endif
mbedtls_ssl_conf_authmode(&conn->ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
mbedtls_ssl_conf_rng(&conn->ssl_conf, mbedtls_ctr_drbg_random,
&conn->drbg_ctx);
mbedtls_ssl_conf_read_timeout(&conn->ssl_conf, SSL_READ_TIMEOUT_MS);
mbedtls_ssl_conf_ca_chain(&conn->ssl_conf, &conn->ca_cert, NULL);
ret = mbedtls_ssl_conf_own_cert(&conn->ssl_conf, &conn->client_cert,
&conn->client_key);
if (ret != 0) {
return handle_error(ret);
}
ret = mbedtls_ssl_setup(&conn->ssl_ctx, &conn->ssl_conf);
if (ret != 0) {
return handle_error(ret);
}
ret = mbedtls_ssl_set_hostname(&conn->ssl_ctx, host);
if (ret != 0) {
return handle_error(ret);
}
mbedtls_ssl_set_bio(&conn->ssl_ctx, &conn->net_ctx, mbedtls_net_send, NULL,
mbedtls_net_recv_timeout);
while ((ret = mbedtls_ssl_handshake(&conn->ssl_ctx)) != 0) {
if (ret != MBEDTLS_ERR_SSL_WANT_READ
&& ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
return handle_error(ret);
}
}
handle_error(ret);
vTaskDelay(5000 / portTICK_RATE_MS);
}
mbedtls_ssl_get_record_expansion(&conn->ssl_ctx);
ret = mbedtls_ssl_get_verify_result(&conn->ssl_ctx);
if (ret != 0) {
return handle_error(ret);
}
return ret;
}
int ssl_destroy(SSLConnection* conn) {
mbedtls_net_free(&conn->net_ctx);
mbedtls_ssl_free(&conn->ssl_ctx);
mbedtls_ssl_config_free(&conn->ssl_conf);
mbedtls_ctr_drbg_free(&conn->drbg_ctx);
mbedtls_entropy_free(&conn->entropy_ctx);
mbedtls_x509_crt_free(&conn->ca_cert);
mbedtls_x509_crt_free(&conn->client_cert);
mbedtls_pk_free(&conn->client_key);
return 0;
}
int ssl_read(SSLConnection* n, unsigned char* buffer, int len, int timeout_ms) {
// NB: timeout_ms is ignored, so blocking read will timeout after SSL_READ_TIMEOUT_MS
return mbedtls_ssl_read(&n->ssl_ctx, buffer, len);
}
int ssl_write(SSLConnection* n, unsigned char* buffer, int len,
int timeout_ms) {
// NB: timeout_ms is ignored, so write is always block write
return mbedtls_ssl_write(&n->ssl_ctx, buffer, len);
}