2016-02-08 04:41:44 +00:00
|
|
|
/* tls_server - simple TLS server that outputs some statistics to a connecting client,
|
|
|
|
* then closes the socket.
|
|
|
|
*
|
|
|
|
* Similar to the the ssl_server example in mbedtls.
|
|
|
|
*
|
|
|
|
* To test this program, connect to the ESP using openssl command line like this:
|
|
|
|
*
|
|
|
|
* openssl s_client -connect 192.168.66.209:800
|
|
|
|
*
|
|
|
|
* The openssl command line client will print some information for the (self-signed) server certificate,
|
|
|
|
* then after a couple of seconds (validation) there will be a few lines of text output sent from the ESP.
|
|
|
|
*
|
|
|
|
* See the cert.c file for private key & certificate (PEM format), plus information for generation.
|
|
|
|
*
|
|
|
|
* Original Copyright (C) 2006-2015, ARM Limited, All Rights Reserved, Apache 2.0 License.
|
|
|
|
* Additions Copyright (C) 2016 Angus Gratton, Apache 2.0 License.
|
|
|
|
*/
|
|
|
|
#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"
|
|
|
|
|
|
|
|
/* Server cert & key */
|
|
|
|
extern const char *server_cert;
|
|
|
|
extern const char *server_key;
|
|
|
|
|
|
|
|
/* 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"
|
|
|
|
|
|
|
|
#define PORT "800"
|
|
|
|
|
|
|
|
void tls_server_task(void *pvParameters)
|
|
|
|
{
|
|
|
|
int successes = 0, failures = 0, ret;
|
|
|
|
printf("TLS server task starting...\n");
|
|
|
|
|
|
|
|
const char *pers = "tls_server";
|
|
|
|
|
|
|
|
mbedtls_entropy_context entropy;
|
|
|
|
mbedtls_ctr_drbg_context ctr_drbg;
|
|
|
|
mbedtls_ssl_context ssl;
|
|
|
|
mbedtls_x509_crt srvcert;
|
|
|
|
mbedtls_pk_context pkey;
|
|
|
|
mbedtls_ssl_config conf;
|
|
|
|
mbedtls_net_context server_ctx;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 0. Initialize the RNG and the session data
|
|
|
|
*/
|
|
|
|
mbedtls_ssl_init(&ssl);
|
|
|
|
mbedtls_x509_crt_init(&srvcert);
|
|
|
|
mbedtls_pk_init( &pkey );
|
|
|
|
mbedtls_ctr_drbg_init(&ctr_drbg);
|
|
|
|
printf("\n . Seeding the random number generator...");
|
|
|
|
|
|
|
|
mbedtls_ssl_config_init(&conf);
|
|
|
|
|
|
|
|
mbedtls_entropy_init(&entropy);
|
|
|
|
if((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
|
|
|
|
(const unsigned char *) pers,
|
|
|
|
strlen(pers))) != 0)
|
|
|
|
{
|
|
|
|
printf(" failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret);
|
|
|
|
while(1) {} /* todo: replace with abort() */
|
|
|
|
}
|
|
|
|
|
|
|
|
printf(" ok\n");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 0. Initialize certificates
|
|
|
|
*/
|
|
|
|
printf(" . Loading the server certificate ...");
|
|
|
|
|
|
|
|
ret = mbedtls_x509_crt_parse(&srvcert, (uint8_t*)server_cert, strlen(server_cert)+1);
|
|
|
|
if(ret < 0)
|
|
|
|
{
|
|
|
|
printf(" failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret);
|
|
|
|
while(1) {} /* todo: replace with abort() */
|
|
|
|
}
|
|
|
|
|
|
|
|
printf(" ok (%d skipped)\n", ret);
|
|
|
|
|
|
|
|
printf(" . Loading the server private key ...");
|
|
|
|
ret = mbedtls_pk_parse_key(&pkey, (uint8_t *)server_key, strlen(server_key)+1, NULL, 0);
|
|
|
|
if(ret != 0)
|
|
|
|
{
|
|
|
|
printf(" failed\n ! mbedtls_pk_parse_key returned - 0x%x\n\n", -ret);
|
|
|
|
while(1) { } /*todo: replace with abort() */
|
|
|
|
}
|
|
|
|
|
|
|
|
printf(" ok\n");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 2. Setup stuff
|
|
|
|
*/
|
|
|
|
printf(" . Setting up the SSL/TLS structure...");
|
|
|
|
|
|
|
|
if((ret = mbedtls_ssl_config_defaults(&conf,
|
|
|
|
MBEDTLS_SSL_IS_SERVER,
|
|
|
|
MBEDTLS_SSL_TRANSPORT_STREAM,
|
|
|
|
MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
|
|
|
|
{
|
|
|
|
printf(" failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret);
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf(" ok\n");
|
|
|
|
|
|
|
|
mbedtls_ssl_conf_ca_chain(&conf, srvcert.next, NULL);
|
|
|
|
if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 )
|
|
|
|
{
|
|
|
|
printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret );
|
|
|
|
while(1) { }
|
|
|
|
}
|
|
|
|
|
|
|
|
mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
|
|
|
|
#ifdef MBEDTLS_DEBUG_C
|
|
|
|
mbedtls_debug_set_threshold(DEBUG_LEVEL);
|
|
|
|
mbedtls_ssl_conf_dbg(&conf, my_debug, stdout);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0)
|
|
|
|
{
|
|
|
|
printf(" failed\n ! mbedtls_ssl_setup returned %d\n\n", ret);
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(1) {
|
|
|
|
mbedtls_net_context client_ctx;
|
|
|
|
mbedtls_net_init(&server_ctx);
|
|
|
|
mbedtls_net_init(&client_ctx);
|
|
|
|
printf("top of loop, free heap = %u\n", xPortGetFreeHeapSize());
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 1. Start the connection
|
|
|
|
*/
|
2016-02-08 23:54:57 +00:00
|
|
|
ret = mbedtls_net_bind(&server_ctx, NULL, PORT, MBEDTLS_NET_PROTO_TCP);
|
2016-02-08 04:41:44 +00:00
|
|
|
if(ret != 0)
|
|
|
|
{
|
|
|
|
printf(" failed\n ! mbedtls_net_bind returned %d\n\n", ret);
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf(" ok\n");
|
|
|
|
|
|
|
|
ret=mbedtls_net_accept(&server_ctx, &client_ctx, NULL, 0 , NULL);
|
|
|
|
if( ret != 0 ){
|
|
|
|
printf(" Failed to accept connection. Restarting.\n");
|
|
|
|
mbedtls_net_free(&server_ctx);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
mbedtls_ssl_set_bio(&ssl, &client_ctx, mbedtls_net_send, mbedtls_net_recv, NULL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 4. Handshake
|
|
|
|
*/
|
|
|
|
printf(" . Performing the SSL/TLS handshake...");
|
|
|
|
|
|
|
|
while((ret = mbedtls_ssl_handshake(&ssl)) != 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);
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
printf(" ok\n");
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 3. Write the GET request
|
|
|
|
*/
|
|
|
|
printf(" > Writing status to new client... ");
|
|
|
|
|
|
|
|
struct sockaddr_in peer_addr;
|
|
|
|
socklen_t peer_addr_len = sizeof(struct sockaddr_in);
|
|
|
|
getpeername(client_ctx.fd, (struct sockaddr *)&peer_addr, &peer_addr_len);
|
|
|
|
unsigned char buf[256];
|
|
|
|
int len = sprintf((char *) buf, "O hai, client %d.%d.%d.%d:%d\nFree heap size is %d bytes\n",
|
|
|
|
ip4_addr1(&peer_addr.sin_addr), ip4_addr2(&peer_addr.sin_addr),
|
|
|
|
ip4_addr3(&peer_addr.sin_addr), ip4_addr4(&peer_addr.sin_addr),
|
|
|
|
peer_addr.sin_port, xPortGetFreeHeapSize());
|
|
|
|
while((ret = mbedtls_ssl_write(&ssl, buf, len)) <= 0)
|
|
|
|
{
|
|
|
|
if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
|
|
|
|
{
|
|
|
|
printf(" failed\n ! mbedtls_ssl_write returned %d\n\n", ret);
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
len = ret;
|
|
|
|
printf(" %d bytes written. Closing socket on client.\n\n%s", len, (char *) buf);
|
|
|
|
|
|
|
|
mbedtls_ssl_close_notify(&ssl);
|
|
|
|
|
|
|
|
exit:
|
|
|
|
mbedtls_ssl_session_reset(&ssl);
|
|
|
|
mbedtls_net_free(&client_ctx);
|
|
|
|
mbedtls_net_free(&server_ctx);
|
|
|
|
|
|
|
|
if(ret != 0)
|
|
|
|
{
|
|
|
|
char error_buf[100];
|
|
|
|
mbedtls_strerror(ret, error_buf, 100);
|
|
|
|
printf("\n\nLast error was: %d - %s\n\n", ret, error_buf);
|
|
|
|
failures++;
|
|
|
|
} else {
|
|
|
|
successes++;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("\n\nsuccesses = %d failures = %d\n", successes, failures);
|
|
|
|
printf("Waiting for next client...\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void user_init(void)
|
|
|
|
{
|
|
|
|
uart_set_baud(0, 115200);
|
|
|
|
printf("SDK version:%s\n", sdk_system_get_sdk_version());
|
|
|
|
|
|
|
|
struct sdk_station_config config = {
|
|
|
|
.ssid = WIFI_SSID,
|
|
|
|
.password = WIFI_PASS,
|
|
|
|
};
|
|
|
|
|
|
|
|
/* required to call wifi_set_opmode before station_set_config */
|
|
|
|
sdk_wifi_set_opmode(STATION_MODE);
|
|
|
|
sdk_wifi_station_set_config(&config);
|
|
|
|
|
|
|
|
xTaskCreate(&tls_server_task, (signed char *)"server_task", 2048, NULL, 2, NULL);
|
|
|
|
}
|