123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 |
- /* server-tls.c
- *
- * Copyright (C) 2006-2024 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
- #include "server-tls.h"
- /* Espressif FreeRTOS */
- #ifndef SINGLE_THREADED
- #include <freertos/FreeRTOS.h>
- #include <freertos/task.h>
- #include <freertos/event_groups.h>
- #endif
- /* socket includes */
- #include <lwip/netdb.h>
- #include <lwip/sockets.h>
- #include <netinet/tcp.h> /* For TCP options */
- #include <sys/socket.h>
- #ifndef TCP_RTO_MIN
- #define TCP_RTO_MIN 1500
- #endif
- /* wolfSSL */
- #include <wolfssl/wolfcrypt/settings.h>
- #include <wolfssl/certs_test.h>
- #include <wolfssl/ssl.h>
- #ifdef WOLFSSL_TRACK_MEMORY
- #include <wolfssl/wolfcrypt/mem_track.h>
- #endif
- #ifndef NO_DH
- /* see also wolfssl/test.h */
- #undef DEFAULT_MIN_DHKEY_BITS
- #define DEFAULT_MIN_DHKEY_BITS 1024
- #undef DEFAULT_MAX_DHKEY_BITS
- #define DEFAULT_MAX_DHKEY_BITS 2048
- #endif
- /* Project */
- #include "wifi_connect.h"
- #include "time_helper.h"
- static const char* const TAG = "server-tls";
- int stack_start = -1;
- int ShowCiphers(WOLFSSL* ssl)
- {
- #define CLIENT_TLS_MAX_CIPHER_LENGTH 4096
- char ciphers[CLIENT_TLS_MAX_CIPHER_LENGTH];
- const char* cipher_used;
- int ret = 0;
- if (ssl == NULL) {
- ESP_LOGI(TAG, "WOLFSSL* ssl is NULL, so no cipher in use");
- ret = wolfSSL_get_ciphers(ciphers, (int)sizeof(ciphers));
- if (ret == WOLFSSL_SUCCESS) {
- for (int i = 0; i < CLIENT_TLS_MAX_CIPHER_LENGTH; i++) {
- if (ciphers[i] == ':') {
- ciphers[i] = '\n';
- }
- }
- ESP_LOGI(TAG, "Available Ciphers:\n%s\n", ciphers);
- }
- else {
- ESP_LOGE(TAG, "Failed to call wolfSSL_get_ciphers. Error: %d", ret);
- }
- }
- else {
- cipher_used = wolfSSL_get_cipher_name(ssl);
- ESP_LOGI(TAG, "WOLFSSL* ssl using %s", cipher_used);
- }
- return ret;
- }
- /* FreeRTOS */
- /* server task */
- WOLFSSL_ESP_TASK tls_smp_server_task(void *args)
- {
- #if defined(SINGLE_THREADED)
- #define TLS_SMP_SERVER_TASK_RET ret
- #else
- #define TLS_SMP_SERVER_TASK_RET
- #endif
- char buff[256];
- const char msg[] = "I hear you fa shizzle!";
- struct sockaddr_in servAddr;
- struct sockaddr_in clientAddr;
- int sockfd;
- int connd;
- int shutdown = 0;
- int ret;
- socklen_t size = sizeof(clientAddr);
- size_t len;
- #if 0
- /* optionally set TCP RTO. See also below. */
- int rto_min = 200; /* Minimum TCP RTO in milliseconds */
- #endif
- /* declare wolfSSL objects */
- WOLFSSL_CTX* ctx;
- WOLFSSL* ssl;
- WOLFSSL_ENTER("tls_smp_server_task");
- #ifdef DEBUG_WOLFSSL
- wolfSSL_Debugging_ON();
- ShowCiphers(NULL);
- #endif
- /* Initialize wolfSSL */
- WOLFSSL_MSG("Start wolfSSL_Init()");
- wolfSSL_Init();
- /* Create a socket that uses an internet IPv4 address,
- * Sets the socket to be stream based (TCP),
- * 0 means choose the default protocol. */
- WOLFSSL_MSG( "start socket())");
- if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
- ESP_LOGE(TAG, "ERROR: failed to create the socket");
- }
- /* Optionally set TCP RTO
- setsockopt(sockfd, IPPROTO_TCP, TCP_RTO_MIN, &rto_min, sizeof(rto_min)); */
- /* Create and initialize WOLFSSL_CTX */
- WOLFSSL_MSG("Create and initialize WOLFSSL_CTX");
- #if defined(WOLFSSL_SM2) || defined(WOLFSSL_SM3) || defined(WOLFSSL_SM4)
- ctx = wolfSSL_CTX_new(wolfSSLv23_server_method());
- /* ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); for only TLS 1.3 */
- if (ctx == NULL) {
- ESP_LOGE(TAG, "ERROR: failed to create WOLFSSL_CTX");
- }
- #else
- if ((ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())) == NULL) {
- ESP_LOGE(TAG, "ERROR: failed to create WOLFSSL_CTX");
- }
- #endif
- #if defined(WOLFSSL_SM2) || defined(WOLFSSL_SM3) || defined(WOLFSSL_SM4)
- ESP_LOGI(TAG, "Start SM3\n");
- /* Optional set explicit ciphers
- ret = wolfSSL_CTX_set_cipher_list(ctx, WOLFSSL_ESP32_CIPHER_SUITE);
- if (ret == SSL_SUCCESS) {
- ESP_LOGI(TAG, "Set cipher list: "WOLFSSL_ESP32_CIPHER_SUITE"\n");
- }
- else {
- ESP_LOGE(TAG, "ERROR: failed to set cipher list: "WOLFSSL_ESP32_CIPHER_SUITE"\n");
- }
- */
- ShowCiphers(NULL);
- ESP_LOGI(TAG, "Stack used: %d\n", CONFIG_ESP_MAIN_TASK_STACK_SIZE
- - uxTaskGetStackHighWaterMark(NULL));
- WOLFSSL_MSG("Loading certificate...");
- /* -c Load server certificates into WOLFSSL_CTX */
- ret = wolfSSL_CTX_use_certificate_chain_buffer_format(ctx,
- CTX_SERVER_CERT,
- CTX_SERVER_CERT_SIZE,
- CTX_SERVER_CERT_TYPE
- );
- /* optional wolfSSL_CTX_use_certificate_buffer
- ret = wolfSSL_CTX_use_certificate_buffer(ctx,
- server_sm2,
- sizeof_server_sm2,
- WOLFSSL_FILETYPE_PEM);
- */
- if (ret == SSL_SUCCESS) {
- ESP_LOGI(TAG, "Loaded server_sm2\n");
- }
- else {
- ESP_LOGE(TAG, "ERROR: failed to load cert\n");
- }
- ESP_LOGI(TAG, "Stack used: %d\n", CONFIG_ESP_MAIN_TASK_STACK_SIZE
- - uxTaskGetStackHighWaterMark(NULL));
- #ifndef NO_DH
- #define DEFAULT_MIN_DHKEY_BITS 1024
- #define DEFAULT_MAX_DHKEY_BITS 2048
- int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS;
- ret = wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits);
- #endif
- #ifndef NO_RSA
- #define DEFAULT_MIN_RSAKEY_BITS 1024
- short minRsaKeyBits = DEFAULT_MIN_RSAKEY_BITS;
- ret = wolfSSL_CTX_SetMinRsaKey_Sz(ctx, minRsaKeyBits);
- #endif
- WOLFSSL_MSG("Loading key info...");
- /* -k Load server key into WOLFSSL_CTX */
- ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx,
- CTX_SERVER_KEY,
- CTX_SERVER_KEY_SIZE,
- CTX_SERVER_KEY_TYPE);
- if (ret == SSL_SUCCESS) {
- ESP_LOGI(TAG, "Loaded PrivateKey_buffer server_sm2_priv\n");
- }
- else {
- ESP_LOGE(TAG, "ERROR: failed to load "
- "PrivateKey_buffer server_sm2_priv\n");
- }
- ESP_LOGI(TAG, "Stack used: %d\n", CONFIG_ESP_MAIN_TASK_STACK_SIZE
- - uxTaskGetStackHighWaterMark(NULL));
- /* -A load authority */
- ret = wolfSSL_CTX_load_verify_buffer(ctx,
- client_sm2,
- sizeof_client_sm2,
- WOLFSSL_FILETYPE_PEM);
- if (ret == SSL_SUCCESS) {
- ESP_LOGI(TAG, "Success: load verify buffer\n");
- }
- else {
- ESP_LOGE(TAG, "ERROR: failed to load verify buffer\n");
- }
- ESP_LOGI(TAG, "Finish SM2\n");
- #else
- WOLFSSL_MSG("Loading certificate...");
- /* Load server certificates into WOLFSSL_CTX */
- if ((ret = wolfSSL_CTX_use_certificate_buffer(ctx, server_cert_der_2048,
- sizeof_server_cert_der_2048,
- WOLFSSL_FILETYPE_ASN1)) != SSL_SUCCESS) {
- ESP_LOGE(TAG, "ERROR: failed to load cert");
- }
- WOLFSSL_MSG("Loading key info...");
- /* Load server key into WOLFSSL_CTX */
- if((ret=wolfSSL_CTX_use_PrivateKey_buffer(ctx,
- server_key_der_2048, sizeof_server_key_der_2048,
- WOLFSSL_FILETYPE_ASN1)) != SSL_SUCCESS) {
- ESP_LOGE(TAG, "ERROR: failed to load privatekey");
- }
- #endif
- /* TODO when using ECDSA,it loads the provisioned certificate and present it.
- TODO when using ECDSA,it uses the generated key instead of loading key */
- /* Initialize the server address struct with zeros */
- memset(&servAddr, 0, sizeof(servAddr));
- /* Fill in the server address */
- servAddr.sin_family = AF_INET; /* using IPv4 */
- servAddr.sin_port = htons(TLS_SMP_DEFAULT_PORT); /* on port */
- servAddr.sin_addr.s_addr = INADDR_ANY; /* from anywhere */
- /* Bind the server socket to our port */
- if (bind(sockfd, (struct sockaddr*)&servAddr, sizeof(servAddr)) == -1) {
- ESP_LOGE(TAG, "ERROR: failed to bind");
- }
- /* Listen for a new connection, allow 5 pending connections */
- if (listen(sockfd, 5) == -1) {
- ESP_LOGE(TAG, "ERROR: failed to listen");
- }
- #if defined(WOLFSSL_ESPWROOM32SE) && defined(HAVE_PK_CALLBACKS) \
- && defined(WOLFSSL_ATECC508A)
- atcatls_set_callbacks(ctx);
- /* when using a custom slot allocation */
- #if defined(CUSTOM_SLOT_ALLOCATION)
- my_atmel_slotInit();
- atmel_set_slot_allocator(my_atmel_alloc, my_atmel_free);
- #endif
- #endif
- ESP_LOGI(TAG, "accept clients...");
- /* Continue to accept clients until shutdown is issued */
- while (!shutdown) {
- ESP_LOGI(TAG, "Stack used: %d\n", TLS_SMP_SERVER_TASK_BYTES
- - uxTaskGetStackHighWaterMark(NULL) );
- WOLFSSL_MSG("Waiting for a connection...");
- wifi_show_ip();
- /* Accept client socket connections */
- if ((connd = accept(sockfd, (struct sockaddr*)&clientAddr, &size))
- == -1) {
- ESP_LOGE(TAG, "ERROR: failed to accept the connection");
- }
- #if defined(WOLFSSL_EXPERIMENTAL_SETTINGS)
- ESP_LOGW(TAG, "WOLFSSL_EXPERIMENTAL_SETTINGS is enabled");
- #endif
- /* Create a WOLFSSL object */
- if ((ssl = wolfSSL_new(ctx)) == NULL) {
- ESP_LOGE(TAG, "ERROR: failed to create WOLFSSL object");
- }
- #if defined(WOLFSSL_HAVE_KYBER)
- else {
- /* If success creating CTX and Kyber enabled, set key share: */
- ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_P521_KYBER_LEVEL5);
- if (ret == SSL_SUCCESS) {
- ESP_LOGI(TAG, "UseKeyShare WOLFSSL_P521_KYBER_LEVEL5 success");
- }
- else {
- ESP_LOGE(TAG, "UseKeyShare WOLFSSL_P521_KYBER_LEVEL5 failed");
- }
- }
- #else
- ESP_LOGI(TAG, "WOLFSSL_HAVE_KYBER is not enabled");
- #endif
- /* show what cipher connected for this WOLFSSL* object */
- ShowCiphers(ssl);
- /* Attach wolfSSL to the socket */
- wolfSSL_set_fd(ssl, connd);
- /* Establish TLS connection */
- ret = wolfSSL_accept(ssl);
- if (ret == SSL_SUCCESS) {
- ShowCiphers(ssl);
- }
- else {
- ESP_LOGE(TAG, "wolfSSL_accept error %d",
- wolfSSL_get_error(ssl, ret));
- }
- ESP_LOGI(TAG, "Client connected successfully");
- /* Read the client data into our buff array */
- memset(buff, 0, sizeof(buff));
- if (wolfSSL_read(ssl, buff, sizeof(buff)-1) == -1) {
- ESP_LOGE(TAG, "ERROR: failed to read");
- }
- ESP_LOGI(TAG, "Client sends: %s", buff);
- /* Check for server shutdown command */
- if (strncmp(buff, "shutdown", 8) == 0) {
- ESP_LOGI(TAG, "Shutdown command issued!");
- shutdown = 1;
- }
- /* Write our reply into buff */
- memset(buff, 0, sizeof(buff));
- memcpy(buff, msg, sizeof(msg));
- len = strnlen(buff, sizeof(buff));
- /* Reply back to the client */
- if (wolfSSL_write(ssl, buff, len) != len) {
- ESP_LOGE(TAG, "ERROR: failed to write");
- }
- ESP_LOGI(TAG, "Done! Cleanup...");
- /* Cleanup after this connection */
- wolfSSL_free(ssl); /* Free the wolfSSL object */
- close(connd); /* Close the connection to the client */
- } /* !shutdown */
- /* Cleanup and return */
- wolfSSL_free(ssl); /* Free the wolfSSL object */
- wolfSSL_CTX_free(ctx); /* Free the wolfSSL context object */
- wolfSSL_Cleanup(); /* Cleanup the wolfSSL environment */
- close(sockfd); /* Close the socket listening for clients */
- vTaskDelete(NULL);
- return TLS_SMP_SERVER_TASK_RET;
- }
- #if defined(SINGLE_THREADED)
- /* we don't initialize a thread */
- #else
- /* create task */
- WOLFSSL_ESP_TASK tls_smp_server_init(void* args)
- {
- #if defined(SINGLE_THREADED)
- #define TLS_SMP_CLIENT_TASK_RET ret
- #else
- #define TLS_SMP_CLIENT_TASK_RET
- #endif
- int thisPort = 0;
- int ret_i = 0; /* interim return result */
- if (thisPort == 0) {
- thisPort = TLS_SMP_DEFAULT_PORT;
- }
- #if ESP_IDF_VERSION_MAJOR >= 4
- TaskHandle_t _handle;
- #else
- xTaskHandle _handle;
- #endif
- /* Note that despite vanilla FreeRTOS using WORDS for a parameter,
- * Espressif uses BYTES for the task stack size here.
- * See https://docs.espressif.com/projects/esp-idf/en/v4.3/esp32/api-reference/system/freertos.html */
- ESP_LOGI(TAG, "Creating tls_smp_server_task with stack size = %d",
- TLS_SMP_SERVER_TASK_BYTES);
- ret_i = xTaskCreate(tls_smp_server_task,
- TLS_SMP_SERVER_TASK_NAME,
- TLS_SMP_SERVER_TASK_BYTES,
- (void*)&thisPort,
- TLS_SMP_SERVER_TASK_PRIORITY,
- &_handle);
- if (ret_i != pdPASS) {
- ESP_LOGI(TAG, "create thread %s failed", TLS_SMP_SERVER_TASK_NAME);
- }
- /* vTaskStartScheduler(); called automatically in ESP-IDF */
- return TLS_SMP_CLIENT_TASK_RET;
- }
- #endif
|