esp-open-rtos/examples/websocket_mbedtls/conn.c

229 lines
5.7 KiB
C

#include "espressif/esp_common.h"
#include "esp/uart.h"
#include <string.h>
#include "FreeRTOS.h"
#include "task.h"
#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"
#include "lwip/api.h"
#include "ssid_config.h"
/* mbedtls/config.h MUST appear before all other mbedtls headers, or
you'll get the default config.
(Although mostly that isn't a big problem, you just might get
errors at link time if functions don't exist.) */
#include "mbedtls/config.h"
#include "mbedtls/net.h"
#include "mbedtls/debug.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h"
#include "mbedtls/certs.h"
#include <stdio.h>
#include <string.h>
#include "conn.h"
/* SSL file descriptors */
#define SSL_HANDLES_SIZE 4
mbedtls_ssl_context* sslHandles[SSL_HANDLES_SIZE] = {NULL, NULL, NULL, NULL};
unsigned char ctxC = 0;
mbedtls_ssl_config conf;
mbedtls_x509_crt cacert;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_context entropy;
/* Connect to a hostname and port using TLS 1.2 and
return a index for one SSL connection on the pool or -1 if error
*/
int ConnConnect(char *hostname, int port) {
int ret = 0;
mbedtls_ssl_context *sslFD;
mbedtls_net_context *socketFD;
int sslHandle = 0;
char s_port[10];
// configure mbedtls
if (!ctxC) {
mbedtls_ssl_config_init( &conf );
mbedtls_x509_crt_init( &cacert );
mbedtls_ctr_drbg_init( &ctr_drbg );
mbedtls_entropy_init( &entropy );
if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *) "ssl_client1",
strlen( "ssl_client1" ) ) ) != 0 )
{
printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret );
return -1;
}
ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem,
mbedtls_test_cas_pem_len );
if( ret < 0 )
{
printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret );
return -1;
}
if( ( ret = mbedtls_ssl_config_defaults( &conf,
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
{
printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
return -1;
}
mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_OPTIONAL );
mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL );
mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
ctxC = 1;
}
// find a free slot at sslHandles
while(sslHandle < SSL_HANDLES_SIZE) {
if (sslHandles[sslHandle] == NULL) {
sslFD = malloc(sizeof(mbedtls_ssl_context));
socketFD = malloc(sizeof(mbedtls_net_context));
mbedtls_ssl_init( sslFD );
mbedtls_net_init( socketFD );
sslHandles[sslHandle] = sslFD;
break;
}
sslHandle++;
}
// no free slot at sslHandles
if (sslHandle == SSL_HANDLES_SIZE) {
return -1;
}
// connect mbedtls socket
memset(s_port, 0, sizeof(s_port));
sprintf(s_port, "%d", port);
ret = mbedtls_net_connect(socketFD, hostname, s_port, MBEDTLS_NET_PROTO_TCP);
if (ret != 0) {
ConnClose(sslHandle);
return -1;
}
if(( ret = mbedtls_ssl_setup( sslFD, &conf ) ) != 0 )
{
printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret );
ConnClose(sslHandle);
return -1;
}
if( ( ret = mbedtls_ssl_set_hostname( sslFD, "mbed TLS Server 1" ) ) != 0 )
{
printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret );
ConnClose(sslHandle);
return -1;
}
mbedtls_ssl_set_bio( sslFD, socketFD, mbedtls_net_send, mbedtls_net_recv, NULL );
while( ( ret = mbedtls_ssl_handshake( sslFD ) ) != 0 )
{
if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
{
printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret );
ConnClose(sslHandle);
return -1;
}
}
return sslHandle;
}
int ConnReadBytesAvailable(int sslHandle) {
mbedtls_ssl_context* sslFD = NULL;
mbedtls_net_context* socketFD = NULL;
int count = 0;
if (sslHandle >= 0) sslFD = sslHandles[sslHandle];
else return -1;
if (sslFD) {
socketFD = (mbedtls_net_context *) sslFD->p_bio;
lwip_ioctl(socketFD->fd, FIONREAD, &count);
return count;
} else {
return -1;
}
}
/* Read bytes from a valid SSL connection on the pool. Blocking! */
int ConnRead(int sslHandle, void *buf, int num) {
mbedtls_ssl_context* sslFD = NULL;
int ret;
if (sslHandle >= 0) sslFD = sslHandles[sslHandle];
else return -1;
if (sslFD) {
if (num == 0) return 0;
ret = mbedtls_ssl_read(sslFD, buf, num);
return ret;
} else {
return -1;
}
}
/* Write bytes to a valid SSL connection on the pool */
int ConnWrite(int sslHandle, const void *buf, int num) {
mbedtls_ssl_context* sslFD = NULL;
int ret;
if (sslHandle >= 0) sslFD = sslHandles[sslHandle];
else return -1;
if (sslFD) {
if (num == 0) return 0;
ret = mbedtls_ssl_write(sslFD, buf, num);
return ret;
} else {
return -1;
}
}
/* Close a valid SSL connection on the pool, release the resources and
open the slot to another connection */
void ConnClose(int sslHandle) {
mbedtls_ssl_context *sslFD = NULL;
if (sslHandle >= 0) sslFD = sslHandles[sslHandle];
else return;
if (sslFD) {
mbedtls_ssl_close_notify( sslFD );
mbedtls_net_free( sslFD->p_bio );
free(sslFD->p_bio);
mbedtls_ssl_free( sslFD );
free(sslFD);
}
sslHandles[sslHandle] = NULL;
}
void sleep_ms(int milliseconds)
{
vTaskDelay(milliseconds / portTICK_RATE_MS);
}