Skip to content

Commit

Permalink
Commit fhessel#169 for ESP TLS IDFv5
Browse files Browse the repository at this point in the history
  • Loading branch information
gb-123-git committed Oct 21, 2023
1 parent 4df47fd commit d37e476
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 107 deletions.
3 changes: 3 additions & 0 deletions src/ConnectionContext.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
#include <Arduino.h>
#include <IPAddress.h>

/* Openssl removed from IDF V5, move to esp_tls.h
// Required for SSL
#include "openssl/ssl.h"
#undef read
*/
#include <esp_tls.h>

namespace httpsserver {

Expand Down
2 changes: 1 addition & 1 deletion src/HTTPConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,7 @@ void handleWebsocketHandshake(HTTPRequest * req, HTTPResponse * res) {
std::string websocketKeyResponseHash(std::string const &key) {
std::string newKey = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
uint8_t shaData[HTTPS_SHA1_LENGTH];
esp_sha(SHA1, (uint8_t*)newKey.data(), newKey.length(), shaData);
mbedtls_sha1_ret((uint8_t*)newKey.data(), newKey.length(), shaData);

// Get output size required for base64 representation
size_t b64BufferSize = 0;
Expand Down
1 change: 1 addition & 0 deletions src/HTTPConnection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
//#include <hwcrypto/sha.h>
#include <sha/sha_parallel_engine.h> // For use with IDF4.4
//#include <esp32/sha.h> // Deprecated
//#include <mbedtls/sha1.h> //TODO Use instead of sha/sha_parallel_engine.h ?

#include <functional>

Expand Down
3 changes: 2 additions & 1 deletion src/HTTPResponse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
#undef write
#include <vector>

#include <openssl/ssl.h>
// #include <openssl/ssl.h> //Deprecated w.e.f IDF v5
#include <esp_tls.h>

#include "util.hpp"

Expand Down
68 changes: 25 additions & 43 deletions src/HTTPSConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace httpsserver {

HTTPSConnection::HTTPSConnection(ResourceResolver * resResolver):
HTTPConnection(resResolver) {
_ssl = NULL;
_ssl = esp_tls_init();
}

HTTPSConnection::~HTTPSConnection() {
Expand All @@ -22,36 +22,30 @@ bool HTTPSConnection::isSecure() {
*
* The call WILL BLOCK if accept(serverSocketID) blocks. So use select() to check for that in advance.
*/
int HTTPSConnection::initialize(int serverSocketID, SSL_CTX * sslCtx, HTTPHeaders *defaultHeaders) {
int HTTPSConnection::initialize(int serverSocketID, esp_tls_cfg_server_t * cfgSrv, HTTPHeaders *defaultHeaders) {
if (_connectionState == STATE_UNDEFINED) {
// Let the base class connect the plain tcp socket
int resSocket = HTTPConnection::initialize(serverSocketID, defaultHeaders);

HTTPS_LOGI("Cert len:%d, apn:%s\n",cfgSrv->servercert_bytes,cfgSrv->alpn_protos[0]);
// Build up SSL Connection context if the socket has been created successfully
if (resSocket >= 0) {

_ssl = SSL_new(sslCtx);

if (_ssl) {
int res=esp_tls_server_session_create(cfgSrv,resSocket,_ssl);
if (0==res) {
esp_tls_cfg_server_session_tickets_init(cfgSrv);
_cfg = cfgSrv;
// Bind SSL to the socket
int success = SSL_set_fd(_ssl, resSocket);
if (success) {

// Perform the handshake
success = SSL_accept(_ssl);
if (success) {
return resSocket;
} else {
HTTPS_LOGE("SSL_accept failed. Aborting handshake. FID=%d", resSocket);
}
} else {
HTTPS_LOGE("SSL_set_fd failed. Aborting handshake. FID=%d", resSocket);
if (ESP_OK == esp_tls_get_conn_sockfd(_ssl,&resSocket)) {
return resSocket;
}
else {
HTTPS_LOGE("SSL_accept failed. Aborting handshake. FID=%d", resSocket);
}
} else {
HTTPS_LOGE("SSL_new failed. Aborting handshake. FID=%d", resSocket);
}
else {
HTTPS_LOGE("SSL_new failed. Aborting handshake. Error=%d", res);
}

} else {
}
else {
HTTPS_LOGE("Could not accept() new connection. FID=%d", resSocket);
}

Expand All @@ -66,9 +60,7 @@ int HTTPSConnection::initialize(int serverSocketID, SSL_CTX * sslCtx, HTTPHeader
return -1;
}


void HTTPSConnection::closeConnection() {

// FIXME: Copy from HTTPConnection, could be done better probably
if (_connectionState != STATE_ERROR && _connectionState != STATE_CLOSED) {

Expand All @@ -81,47 +73,37 @@ void HTTPSConnection::closeConnection() {
// correctly
_connectionState = STATE_CLOSING;
}

// Try to tear down SSL while we are in the _shutdownTS timeout period or if an error occurred
if (_ssl) {
if(_connectionState == STATE_ERROR || SSL_shutdown(_ssl) == 0) {
// SSL_shutdown will return 1 as soon as the client answered with close notify
// This means we are safe to close the socket
SSL_free(_ssl);
_ssl = NULL;
} else if (_shutdownTS + HTTPS_SHUTDOWN_TIMEOUT < millis()) {
// The timeout has been hit, we force SSL shutdown now by freeing the context
SSL_free(_ssl);
_ssl = NULL;
HTTPS_LOGW("SSL_shutdown did not receive close notification from the client");
_connectionState = STATE_ERROR;
}
esp_tls_cfg_server_session_tickets_free(_cfg);
esp_tls_server_session_delete(_ssl);
_ssl = NULL;
_connectionState = STATE_ERROR;
}

// If SSL has been brought down, close the socket
if (!_ssl) {
HTTPConnection::closeConnection();
}
}

size_t HTTPSConnection::writeBuffer(byte* buffer, size_t length) {
return SSL_write(_ssl, buffer, length);
return esp_tls_conn_write(_ssl,buffer,length);
}

size_t HTTPSConnection::readBytesToBuffer(byte* buffer, size_t length) {
int ret = SSL_read(_ssl, buffer, length);
int ret = esp_tls_conn_read(_ssl, buffer, length);
if (ret < 0) {
HTTPS_LOGD("SSL_read error: %d", SSL_get_error(_ssl, ret));
}
return ret;
}

size_t HTTPSConnection::pendingByteCount() {
return SSL_pending(_ssl);
return esp_tls_get_bytes_avail(_ssl);
}

bool HTTPSConnection::canReadData() {
return HTTPConnection::canReadData() || (SSL_pending(_ssl) > 0);
return HTTPConnection::canReadData() || (esp_tls_get_bytes_avail(_ssl) > 0);
}

} /* namespace httpsserver */
8 changes: 6 additions & 2 deletions src/HTTPSConnection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@

#include <string>

/* OpenSSL Depracation in IDF v5
// Required for SSL
#include "openssl/ssl.h"
#undef read
*/
#include <esp_tls.h>

// Required for sockets
#include "lwip/netdb.h"
Expand All @@ -34,7 +37,7 @@ class HTTPSConnection : public HTTPConnection {
HTTPSConnection(ResourceResolver * resResolver);
virtual ~HTTPSConnection();

virtual int initialize(int serverSocketID, SSL_CTX * sslCtx, HTTPHeaders *defaultHeaders);
virtual int initialize(int serverSocketID,esp_tls_cfg_server_t * cfgSrv, HTTPHeaders *defaultHeaders);
virtual void closeConnection();
virtual bool isSecure();

Expand All @@ -49,7 +52,8 @@ class HTTPSConnection : public HTTPConnection {

private:
// SSL context for this connection
SSL * _ssl;
esp_tls_t * _ssl;
esp_tls_cfg_server_t * _cfg;

};

Expand Down
80 changes: 24 additions & 56 deletions src/HTTPSServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,77 +2,56 @@

namespace httpsserver {

constexpr const char * alpn_protos[] = { "http/1.1", NULL } ;

HTTPSServer::HTTPSServer(SSLCert * cert, const uint16_t port, const uint8_t maxConnections, const in_addr_t bindAddress):
HTTPServer(port, maxConnections, bindAddress),
_cert(cert) {

// Configure runtime data
_sslctx = NULL;
_cfg = new esp_tls_cfg_server();
_cfg->alpn_protos = (const char **)alpn_protos;
_cfg->cacert_buf = NULL;
_cfg->cacert_bytes = 0;
_cfg->servercert_buf =cert->getCertData();
_cfg->servercert_bytes = cert->getCertLength();
_cfg->serverkey_buf= cert->getPKData();
_cfg->serverkey_bytes= cert->getPKLength();
}

HTTPSServer::~HTTPSServer() {

free(_cfg);
}

/**
* This method starts the server and begins to listen on the port
*/
uint8_t HTTPSServer::setupSocket() {
if (!isRunning()) {
if (!setupSSLCTX()) {
Serial.println("setupSSLCTX failed");
return 0;
}

if (!setupCert()) {
Serial.println("setupCert failed");
SSL_CTX_free(_sslctx);
_sslctx = NULL;
return 0;
}

_cfg->servercert_buf= _cert->getCertData();
_cfg->servercert_bytes = _cert->getCertLength();
_cfg->serverkey_buf= _cert->getPKData();
_cfg->serverkey_bytes= _cert->getPKLength();
if (HTTPServer::setupSocket()) {
return 1;
} else {
}
else {
Serial.println("setupSockets failed");
SSL_CTX_free(_sslctx);
_sslctx = NULL;
return 0;
}
} else {
}
else {
return 1;
}
}

void HTTPSServer::teardownSocket() {

HTTPServer::teardownSocket();

// Tear down the SSL context
SSL_CTX_free(_sslctx);
_sslctx = NULL;
}

int HTTPSServer::createConnection(int idx) {
HTTPSConnection * newConnection = new HTTPSConnection(this);
_connections[idx] = newConnection;
return newConnection->initialize(_socket, _sslctx, &_defaultHeaders);
}

/**
* This method configures the ssl context that is used for the server
*/
uint8_t HTTPSServer::setupSSLCTX() {
_sslctx = SSL_CTX_new(TLSv1_2_server_method());
if (_sslctx) {
// Set SSL Timeout to 5 minutes
SSL_CTX_set_timeout(_sslctx, 300);
return 1;
} else {
_sslctx = NULL;
return 0;
}
return newConnection->initialize(_socket, _cfg, &_defaultHeaders);
}

/**
Expand All @@ -81,22 +60,11 @@ uint8_t HTTPSServer::setupSSLCTX() {
*/
uint8_t HTTPSServer::setupCert() {
// Configure the certificate first
uint8_t ret = SSL_CTX_use_certificate_ASN1(
_sslctx,
_cert->getCertLength(),
_cert->getCertData()
);

// Then set the private key accordingly
if (ret) {
ret = SSL_CTX_use_RSAPrivateKey_ASN1(
_sslctx,
_cert->getPKData(),
_cert->getPKLength()
);
_cfg->servercert_buf= _cert->getCertData();
_cfg->servercert_bytes = _cert->getCertLength();
_cfg->serverkey_buf= _cert->getPKData();
_cfg->serverkey_bytes= _cert->getPKLength();
return 1;
}

return ret;
}

} /* namespace httpsserver */
7 changes: 5 additions & 2 deletions src/HTTPSServer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
// Arduino stuff
#include <Arduino.h>

/* OpenSSL wrapper depracated in IDF v5
// Required for SSL
#include "openssl/ssl.h"
#undef read
*/
#include <esp_tls.h>

// Internal includes
#include "HTTPServer.hpp"
Expand All @@ -31,14 +34,14 @@ class HTTPSServer : public HTTPServer {
public:
HTTPSServer(SSLCert * cert, const uint16_t portHTTPS = 443, const uint8_t maxConnections = 4, const in_addr_t bindAddress = 0);
virtual ~HTTPSServer();

virtual esp_tls_cfg_server_t *getConfig() {return _cfg;}
private:
// Static configuration. Port, keys, etc. ====================
// Certificate that should be used (includes private key)
SSLCert * _cert;

//// Runtime data ============================================
SSL_CTX * _sslctx;
esp_tls_cfg_server_t * _cfg;
// Status of the server: Are we running, or not?

// Setup functions
Expand Down
7 changes: 5 additions & 2 deletions src/WebsocketHandler.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#include "WebsocketHandler.hpp"

#ifndef TAG
static const char *TAG = "WebsocketHandler";
#endif

namespace httpsserver {

/**
Expand All @@ -16,7 +20,7 @@ static void dumpFrame(WebsocketFrame frame) {
case WebsocketHandler::OPCODE_PONG: opcode = std::string("PONG"); break;
case WebsocketHandler::OPCODE_TEXT: opcode = std::string("TEXT"); break;
}
/* Commenting logging function to resolve compilation
Commenting logging function to resolve compilation
ESP_LOGI(
TAG,
"Fin: %d, OpCode: %d (%s), Mask: %d, Len: %d",
Expand All @@ -26,7 +30,6 @@ static void dumpFrame(WebsocketFrame frame) {
(int)frame.mask,
(int)frame.len
);
*/
}

WebsocketHandler::WebsocketHandler() {
Expand Down

0 comments on commit d37e476

Please sign in to comment.