Skip to content

Commit 896f177

Browse files
authored
Merge pull request meshtastic#4 from mskvortsov/mbedtls
Port to Mbed TLS
2 parents 23665b3 + 2ab1741 commit 896f177

File tree

7 files changed

+161
-98
lines changed

7 files changed

+161
-98
lines changed

src/ConnectionContext.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include <IPAddress.h>
66

77
// Required for SSL
8-
#include "openssl/ssl.h"
8+
#include "mbedtls/ssl.h"
99
#undef read
1010

1111
namespace httpsserver {

src/HTTPResponse.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#undef write
1010
#include <vector>
1111

12-
#include <openssl/ssl.h>
12+
#include <mbedtls/ssl.h>
1313

1414
#include "util.hpp"
1515

src/HTTPSConnection.cpp

Lines changed: 76 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
#include "HTTPSConnection.hpp"
2+
#include "mbedtls/net_sockets.h"
23

34
namespace httpsserver {
45

56

67
HTTPSConnection::HTTPSConnection(ResourceResolver * resResolver):
78
HTTPConnection(resResolver) {
8-
_ssl = NULL;
9+
_sslCreated = false;
10+
_socket = 0;
911
}
1012

1113
HTTPSConnection::~HTTPSConnection() {
@@ -17,38 +19,58 @@ bool HTTPSConnection::isSecure() {
1719
return true;
1820
}
1921

22+
bool HTTPSConnection::setup(mbedtls_ssl_config *sslConfig) {
23+
mbedtls_ssl_init(&_ssl);
24+
int res = mbedtls_ssl_setup(&_ssl, sslConfig);
25+
if (res == 0) {
26+
return true;
27+
} else {
28+
mbedtls_ssl_free(&_ssl);
29+
return false;
30+
}
31+
}
32+
33+
bool HTTPSConnection::handshake() {
34+
int res;
35+
while (true) {
36+
res = mbedtls_ssl_handshake(&_ssl);
37+
if (res == 0) {
38+
return true;
39+
}
40+
if (res != MBEDTLS_ERR_SSL_WANT_READ && res != MBEDTLS_ERR_SSL_WANT_WRITE) {
41+
return false;
42+
}
43+
}
44+
}
45+
2046
/**
2147
* Initializes the connection from a server socket.
2248
*
2349
* The call WILL BLOCK if accept(serverSocketID) blocks. So use select() to check for that in advance.
2450
*/
25-
int HTTPSConnection::initialize(int serverSocketID, SSL_CTX * sslCtx, HTTPHeaders *defaultHeaders) {
51+
int HTTPSConnection::initialize(int serverSocketID, mbedtls_ssl_config *sslConfig, HTTPHeaders *defaultHeaders) {
2652
if (_connectionState == STATE_UNDEFINED) {
2753
// Let the base class connect the plain tcp socket
2854
int resSocket = HTTPConnection::initialize(serverSocketID, defaultHeaders);
2955

3056
// Build up SSL Connection context if the socket has been created successfully
3157
if (resSocket >= 0) {
3258

33-
_ssl = SSL_new(sslCtx);
59+
_socket = resSocket;
60+
_sslCreated = setup(sslConfig);
3461

35-
if (_ssl) {
62+
if (_sslCreated) {
3663
// Bind SSL to the socket
37-
int success = SSL_set_fd(_ssl, resSocket);
38-
if (success) {
39-
40-
// Perform the handshake
41-
success = SSL_accept(_ssl);
42-
if (success) {
43-
return resSocket;
44-
} else {
45-
HTTPS_LOGE("SSL_accept failed. Aborting handshake. FID=%d", resSocket);
46-
}
64+
mbedtls_ssl_set_bio(&_ssl, &_socket, mbedtls_net_send, mbedtls_net_recv, NULL);
65+
66+
// Perform the handshake
67+
if (handshake()) {
68+
return resSocket;
4769
} else {
48-
HTTPS_LOGE("SSL_set_fd failed. Aborting handshake. FID=%d", resSocket);
70+
HTTPS_LOGE("SSL handshake failed. Aborting handshake. FID=%d", resSocket);
4971
}
5072
} else {
51-
HTTPS_LOGE("SSL_new failed. Aborting handshake. FID=%d", resSocket);
73+
HTTPS_LOGE("SSL setup failed. Aborting handshake. FID=%d", resSocket);
5274
}
5375

5476
} else {
@@ -66,6 +88,18 @@ int HTTPSConnection::initialize(int serverSocketID, SSL_CTX * sslCtx, HTTPHeader
6688
return -1;
6789
}
6890

91+
int HTTPSConnection::shutdown() {
92+
int res;
93+
while (true) {
94+
res = mbedtls_ssl_close_notify(&_ssl);
95+
if (res == 0) {
96+
return 1;
97+
}
98+
if (res != MBEDTLS_ERR_SSL_WANT_WRITE) {
99+
return 0;
100+
}
101+
}
102+
}
69103

70104
void HTTPSConnection::closeConnection() {
71105

@@ -83,41 +117,53 @@ void HTTPSConnection::closeConnection() {
83117
}
84118

85119
// Try to tear down SSL while we are in the _shutdownTS timeout period or if an error occurred
86-
if (_ssl) {
87-
if(_connectionState == STATE_ERROR || SSL_shutdown(_ssl) == 0) {
88-
// SSL_shutdown will return 1 as soon as the client answered with close notify
120+
if (_sslCreated) {
121+
if (_connectionState == STATE_ERROR || shutdown() == 0) {
122+
// SSL shutdown will return 1 as soon as the client answered with close notify
89123
// This means we are safe to close the socket
90-
SSL_free(_ssl);
91-
_ssl = NULL;
124+
mbedtls_ssl_free(&_ssl);
125+
_sslCreated = false;
92126
} else if (_shutdownTS + HTTPS_SHUTDOWN_TIMEOUT < millis()) {
93-
// The timeout has been hit, we force SSL shutdown now by freeing the context
94-
SSL_free(_ssl);
95-
_ssl = NULL;
96-
HTTPS_LOGW("SSL_shutdown did not receive close notification from the client");
127+
// The timeout has been hit, we force SSL shutdown now by resetting the session
128+
mbedtls_ssl_free(&_ssl);
129+
_sslCreated = false;
130+
HTTPS_LOGW("SSL shutdown did not receive close notification from the client");
97131
_connectionState = STATE_ERROR;
98132
}
99133
}
100134

101135
// If SSL has been brought down, close the socket
102-
if (!_ssl) {
136+
if (!_sslCreated) {
103137
HTTPConnection::closeConnection();
104138
}
105139
}
106140

107141
size_t HTTPSConnection::writeBuffer(byte* buffer, size_t length) {
108-
return SSL_write(_ssl, buffer, length);
142+
while (true) {
143+
int res = mbedtls_ssl_write(&_ssl, buffer, length);
144+
if (res == MBEDTLS_ERR_SSL_WANT_READ || res == MBEDTLS_ERR_SSL_WANT_WRITE) {
145+
continue;
146+
}
147+
return res;
148+
}
109149
}
110150

111151
size_t HTTPSConnection::readBytesToBuffer(byte* buffer, size_t length) {
112-
return SSL_read(_ssl, buffer, length);
152+
while (true) {
153+
int res = mbedtls_ssl_read(&_ssl, buffer, length);
154+
if (res == MBEDTLS_ERR_SSL_WANT_READ || res == MBEDTLS_ERR_SSL_WANT_WRITE) {
155+
continue;
156+
}
157+
return res;
158+
}
113159
}
114160

115161
size_t HTTPSConnection::pendingByteCount() {
116-
return SSL_pending(_ssl);
162+
return mbedtls_ssl_get_bytes_avail(&_ssl);
117163
}
118164

119165
bool HTTPSConnection::canReadData() {
120-
return HTTPConnection::canReadData() || (SSL_pending(_ssl) > 0);
166+
return HTTPConnection::canReadData() || (mbedtls_ssl_get_bytes_avail(&_ssl) > 0);
121167
}
122168

123169
} /* namespace httpsserver */

src/HTTPSConnection.hpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#include <string>
77

88
// Required for SSL
9-
#include "openssl/ssl.h"
9+
#include "mbedtls/ssl.h"
1010
#undef read
1111

1212
// Required for sockets
@@ -34,9 +34,12 @@ class HTTPSConnection : public HTTPConnection {
3434
HTTPSConnection(ResourceResolver * resResolver);
3535
virtual ~HTTPSConnection();
3636

37-
virtual int initialize(int serverSocketID, SSL_CTX * sslCtx, HTTPHeaders *defaultHeaders);
37+
virtual int initialize(int serverSocketID, mbedtls_ssl_config *sslConfig, HTTPHeaders *defaultHeaders);
3838
virtual void closeConnection();
3939
virtual bool isSecure();
40+
bool setup(mbedtls_ssl_config *sslConfig);
41+
bool handshake();
42+
int shutdown();
4043

4144
protected:
4245
friend class HTTPRequest;
@@ -49,7 +52,9 @@ class HTTPSConnection : public HTTPConnection {
4952

5053
private:
5154
// SSL context for this connection
52-
SSL * _ssl;
55+
mbedtls_ssl_context _ssl;
56+
bool _sslCreated;
57+
int _socket;
5358

5459
};
5560

src/HTTPSServer.cpp

Lines changed: 51 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -8,95 +8,87 @@ HTTPSServer::HTTPSServer(SSLCert * cert, const uint16_t port, const uint8_t maxC
88
_cert(cert) {
99

1010
// Configure runtime data
11-
_sslctx = NULL;
11+
mbedtls_ssl_config_init(&_ssl_config);
12+
mbedtls_x509_crt_init(&_ssl_cert);
13+
mbedtls_pk_init(&_ssl_pk);
14+
mbedtls_entropy_init(&_ssl_entropy);
15+
mbedtls_ctr_drbg_init(&_ssl_ctr_drbg);
16+
17+
mbedtls_ctr_drbg_seed(&_ssl_ctr_drbg, mbedtls_entropy_func, &_ssl_entropy, nullptr, 0);
18+
mbedtls_ssl_conf_rng(&_ssl_config, mbedtls_ctr_drbg_random, &_ssl_ctr_drbg);
1219
}
1320

1421
HTTPSServer::~HTTPSServer() {
1522

23+
mbedtls_ctr_drbg_init(&_ssl_ctr_drbg);
24+
mbedtls_entropy_init(&_ssl_entropy);
25+
mbedtls_pk_free(&_ssl_pk);
26+
mbedtls_x509_crt_free(&_ssl_cert);
27+
mbedtls_ssl_config_free(&_ssl_config);
1628
}
1729

1830
/**
1931
* This method starts the server and begins to listen on the port
2032
*/
2133
uint8_t HTTPSServer::setupSocket() {
22-
if (!isRunning()) {
23-
if (!setupSSLCTX()) {
24-
Serial.println("setupSSLCTX failed");
25-
return 0;
26-
}
27-
28-
if (!setupCert()) {
29-
Serial.println("setupCert failed");
30-
SSL_CTX_free(_sslctx);
31-
_sslctx = NULL;
32-
return 0;
33-
}
34-
35-
if (HTTPServer::setupSocket()) {
36-
return 1;
37-
} else {
38-
Serial.println("setupSockets failed");
39-
SSL_CTX_free(_sslctx);
40-
_sslctx = NULL;
41-
return 0;
42-
}
43-
} else {
34+
if (isRunning()) {
4435
return 1;
4536
}
37+
38+
int res = mbedtls_ssl_config_defaults(&_ssl_config,
39+
MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
40+
if (res != 0) {
41+
Serial.println("Setting SSL default config failed");
42+
return 0;
43+
}
44+
45+
if (setupCert() != 0) {
46+
Serial.println("setupCert failed");
47+
return 0;
48+
}
49+
50+
if (!HTTPServer::setupSocket()) {
51+
Serial.println("setupSockets failed");
52+
return 0;
53+
}
54+
55+
return 1;
4656
}
4757

4858
void HTTPSServer::teardownSocket() {
4959

5060
HTTPServer::teardownSocket();
51-
52-
// Tear down the SSL context
53-
SSL_CTX_free(_sslctx);
54-
_sslctx = NULL;
5561
}
5662

5763
int HTTPSServer::createConnection(int idx) {
5864
HTTPSConnection * newConnection = new HTTPSConnection(this);
5965
_connections[idx] = newConnection;
60-
return newConnection->initialize(_socket, _sslctx, &_defaultHeaders);
61-
}
62-
63-
/**
64-
* This method configures the ssl context that is used for the server
65-
*/
66-
uint8_t HTTPSServer::setupSSLCTX() {
67-
_sslctx = SSL_CTX_new(TLSv1_2_server_method());
68-
if (_sslctx) {
69-
// Set SSL Timeout to 5 minutes
70-
SSL_CTX_set_timeout(_sslctx, 300);
71-
return 1;
72-
} else {
73-
_sslctx = NULL;
74-
return 0;
75-
}
66+
return newConnection->initialize(_socket, &_ssl_config, &_defaultHeaders);
7667
}
7768

7869
/**
7970
* This method configures the certificate and private key for the given
8071
* ssl context
8172
*/
82-
uint8_t HTTPSServer::setupCert() {
83-
// Configure the certificate first
84-
uint8_t ret = SSL_CTX_use_certificate_ASN1(
85-
_sslctx,
86-
_cert->getCertLength(),
87-
_cert->getCertData()
88-
);
89-
90-
// Then set the private key accordingly
91-
if (ret) {
92-
ret = SSL_CTX_use_RSAPrivateKey_ASN1(
93-
_sslctx,
94-
_cert->getPKData(),
95-
_cert->getPKLength()
96-
);
73+
int HTTPSServer::setupCert() {
74+
int res = 0;
75+
76+
res = mbedtls_x509_crt_parse(&_ssl_cert, _cert->getCertData(), _cert->getCertLength());
77+
if (res != 0) {
78+
return res;
79+
}
80+
81+
#if ESP_IDF_VERSION_MAJOR > 4
82+
res = mbedtls_pk_parse_key(&_ssl_pk, _cert->getPKData(), _cert->getPKLength(), nullptr, 0,
83+
mbedtls_ctr_drbg_random, &_ssl_ctr_drbg);
84+
#else
85+
res = mbedtls_pk_parse_key(&_ssl_pk, _cert->getPKData(), _cert->getPKLength(), nullptr, 0);
86+
#endif
87+
if (res != 0) {
88+
return res;
9789
}
9890

99-
return ret;
91+
return mbedtls_ssl_conf_own_cert(&_ssl_config, &_ssl_cert, &_ssl_pk);
10092
}
10193

10294
} /* namespace httpsserver */

0 commit comments

Comments
 (0)