Skip to content

WiFiClientSecure half-duplex contract. #3019

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 60 additions & 3 deletions libraries/ESP8266WiFi/src/WiFiClientSecure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,15 @@ class SSLContext
void connect(ClientContext* ctx, const char* hostName, uint32_t timeout_ms)
{
s_io_ctx = ctx;
_ssl = ssl_client_new(_ssl_ctx, 0, nullptr, 0, hostName);
_ssl_ext = ssl_ext_new();

int name_len = strlen(hostName);

_ssl_ext->host_name = (char*) malloc((name_len + 1) * sizeof (char));
strncpy(_ssl_ext->host_name, hostName, name_len + 1);
_ssl_ext->host_name[name_len] = 0;

_ssl = ssl_client_new(_ssl_ctx, 0, nullptr, 0, _ssl_ext);
uint32_t t = millis();

while (millis() - t < timeout_ms && ssl_handshake_status(_ssl) != SSL_OK) {
Expand All @@ -112,6 +120,11 @@ class SSLContext
{
return _ssl != nullptr && ssl_handshake_status(_ssl) == SSL_OK;
}

void discardCache() {
_available = 0;
_read_ptr = nullptr;
}

int read(uint8_t* dst, size_t size)
{
Expand Down Expand Up @@ -179,6 +192,14 @@ class SSLContext
}
return cb;
}

bool wantRead() {
return _available > 0 || (_ssl && ssl_want_read(_ssl) == 1);
}

bool emptyCache() {
return _available == 0;
}

bool loadObject(int type, Stream& stream, size_t size)
{
Expand Down Expand Up @@ -245,6 +266,7 @@ class SSLContext
static SSL_CTX* _ssl_ctx;
static int _ssl_ctx_refcnt;
SSL* _ssl = nullptr;
SSL_EXTENSIONS* _ssl_ext = nullptr;
int _refcnt = 0;
const uint8_t* _read_ptr = nullptr;
size_t _available = 0;
Expand Down Expand Up @@ -332,7 +354,14 @@ size_t WiFiClientSecure::write(const uint8_t *buf, size_t size)
if (!_ssl) {
return 0;
}


// axTLS is half-duplex so if a read operation is already underway,
// finish the read before trying to write; otherwise the read
// cache will be overwritten and data will be lost
if (!_ssl->emptyCache()) {
return SSL_ERROR_READ_LOCK;
}

int rc = ssl_write(*_ssl, buf, size);
if (rc >= 0) {
return rc;
Expand All @@ -346,6 +375,20 @@ size_t WiFiClientSecure::write(const uint8_t *buf, size_t size)
return 0;
}

int WiFiClientSecure::wantRead() {
if (_ssl) {
return _ssl->wantRead();
}

return 0;
}

void WiFiClientSecure::discardCache() {
if (_ssl) {
_ssl->discardCache();
}
}

int WiFiClientSecure::read(uint8_t *buf, size_t size)
{
if (!_ssl) {
Expand Down Expand Up @@ -420,7 +463,7 @@ err x N N
uint8_t WiFiClientSecure::connected()
{
if (_ssl) {
if (_ssl->available()) {
if (_ssl->wantRead()) {
return true;
}
if (_client && _client->state() == ESTABLISHED && _ssl->connected()) {
Expand Down Expand Up @@ -595,6 +638,20 @@ bool WiFiClientSecure::loadPrivateKey(Stream& stream, size_t size)
return _ssl->loadObject(SSL_OBJ_RSA_KEY, stream, size);
}

extern "C" int __ax_port_pending(int fd) {
//Serial.println("ax_port_pending");
ClientContext* _client = SSLContext::getIOContext(fd);
if (!_client || _client->state() != ESTABLISHED && !_client->getSize()) {
errno = EIO;
return -1;
}

//Serial.printf("pending: %d\r\n", _client->getSize());
return _client->getSize();
}

extern "C" void ax_port_pending() __attribute__ ((weak, alias("__ax_port_pending")));

extern "C" int __ax_port_read(int fd, uint8_t* buffer, size_t count)
{
ClientContext* _client = SSLContext::getIOContext(fd);
Expand Down
4 changes: 4 additions & 0 deletions libraries/ESP8266WiFi/src/WiFiClientSecure.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "WiFiClient.h"
#include "include/ssl.h"

#define SSL_ERROR_READ_LOCK -275

class SSLContext;

Expand All @@ -49,6 +50,9 @@ class WiFiClientSecure : public WiFiClient {
int peek() override;
size_t peekBytes(uint8_t *buffer, size_t length) override;
void stop() override;

void discardCache();
int wantRead();

bool setCACert(const uint8_t* pk, size_t size);
bool setCertificate(const uint8_t* pk, size_t size);
Expand Down
88 changes: 75 additions & 13 deletions libraries/ESP8266WiFi/src/include/ssl.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
/*
* Copyright (c) 2007, Cameron Rich
*
* Copyright (c) 2007-2016, Cameron Rich
* Copyright (c) 2017, Diego Guerrero (ssl_want_write)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
Expand Down Expand Up @@ -72,10 +73,15 @@ extern "C" {

#define EXP_FUNC
#define STDCALL
// struct SSL_CTX_;

typedef struct SSL_CTX_ SSL_CTX;
typedef struct SSL_ SSL;

typedef struct {
char *host_name; /* Needed for the SNI support */
uint16_t max_fragment_size; /* Needed for the Max Fragment Size Extension. Allowed values: 2^9, 2^10 .. 2^14 */
} SSL_EXTENSIONS;

/* The optional parameters that can be given to the client/server SSL engine */
#define SSL_CLIENT_AUTHENTICATION 0x00010000
#define SSL_SERVER_VERIFY_LATER 0x00020000
Expand All @@ -93,13 +99,16 @@ typedef struct SSL_ SSL;
#define SSL_ERROR_DEAD -2
#define SSL_CLOSE_NOTIFY -3
#define SSL_ERROR_CONN_LOST -256
#define SSL_ERROR_RECORD_OVERFLOW -257
#define SSL_ERROR_SOCK_SETUP_FAILURE -258
#define SSL_ERROR_INVALID_HANDSHAKE -260
#define SSL_ERROR_INVALID_PROT_MSG -261
#define SSL_ERROR_INVALID_HMAC -262
#define SSL_ERROR_INVALID_VERSION -263
#define SSL_ERROR_UNSUPPORTED_EXTENSION -264
#define SSL_ERROR_INVALID_SESSION -265
#define SSL_ERROR_NO_CIPHER -266
#define SSL_ERROR_INVALID_CERT_HASH_ALG -267
#define SSL_ERROR_BAD_CERTIFICATE -268
#define SSL_ERROR_INVALID_KEY -269
#define SSL_ERROR_FINISHED_INVALID -271
Expand All @@ -117,19 +126,25 @@ typedef struct SSL_ SSL;
#define SSL_ALERT_CLOSE_NOTIFY 0
#define SSL_ALERT_UNEXPECTED_MESSAGE 10
#define SSL_ALERT_BAD_RECORD_MAC 20
#define SSL_ALERT_RECORD_OVERFLOW 22
#define SSL_ALERT_HANDSHAKE_FAILURE 40
#define SSL_ALERT_BAD_CERTIFICATE 42
#define SSL_ALERT_UNSUPPORTED_CERTIFICATE 43
#define SSL_ALERT_CERTIFICATE_EXPIRED 45
#define SSL_ALERT_CERTIFICATE_UNKNOWN 46
#define SSL_ALERT_ILLEGAL_PARAMETER 47
#define SSL_ALERT_UNKNOWN_CA 48
#define SSL_ALERT_DECODE_ERROR 50
#define SSL_ALERT_DECRYPT_ERROR 51
#define SSL_ALERT_INVALID_VERSION 70
#define SSL_ALERT_NO_RENEGOTIATION 100
#define SSL_ALERT_UNSUPPORTED_EXTENSION 110

/* The ciphers that are supported */
#define SSL_AES128_SHA 0x2f
#define SSL_AES256_SHA 0x35
#define SSL_RC4_128_SHA 0x05
#define SSL_RC4_128_MD5 0x04
#define SSL_AES128_SHA256 0x3c
#define SSL_AES256_SHA256 0x3d

/* build mode ids' */
#define SSL_BUILD_SKELETON_MODE 0x01
Expand Down Expand Up @@ -218,6 +233,22 @@ EXP_FUNC SSL_CTX * STDCALL ssl_ctx_new(uint32_t options, int num_sessions);
*/
EXP_FUNC void STDCALL ssl_ctx_free(SSL_CTX *ssl_ctx);

/**
* @brief Allocates new SSL extensions structure and returns pointer to it
*
* @return ssl_ext Pointer to SSL_EXTENSIONS structure
*
*/
EXP_FUNC SSL_EXTENSIONS * STDCALL ssl_ext_new();

/**
* @brief Frees SSL extensions structure
*
* @param ssl_ext [in] Pointer to SSL_EXTENSION structure
*
*/
EXP_FUNC void STDCALL ssl_ext_free(SSL_EXTENSIONS *ssl_ext);

/**
* @brief (server only) Establish a new SSL connection to an SSL client.
*
Expand All @@ -244,11 +275,11 @@ EXP_FUNC SSL * STDCALL ssl_server_new(SSL_CTX *ssl_ctx, int client_fd);
* can be null if no session resumption is being used or required. This option
* is not used in skeleton mode.
* @param sess_id_size The size of the session id (max 32)
* @param host_name If non-zero, host name to be sent to server for SNI support
* @return An SSL object reference. Use ssl_handshake_status() to check
* @param ssl_ext pointer to a structure with the activated SSL extensions and their values
* @return An SSL object reference. Use ssl_handshake_status() to check
* if a handshake succeeded.
*/
EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const uint8_t *session_id, uint8_t sess_id_size, const char* host_name);
EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const uint8_t *session_id, uint8_t sess_id_size, SSL_EXTENSIONS* ssl_ext);

/**
* @brief Free any used resources on this connection.
Expand All @@ -259,6 +290,19 @@ EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const uin
*/
EXP_FUNC void STDCALL ssl_free(SSL *ssl);

/**
* @brief Check the rx buffer for new information.
* If the socket has new information to be read, 1 will be returned.
* Cheap alternative to check availability without actually decrypting.
* @param ssl [in] An SSL object reference.
* @return Read status:
* - if == 1, then there are bytes to be read,
* - if == 0, then there are not,
* - if < 0, there was an error.
* @see ssl.h for the error code list.
*/
EXP_FUNC int STDCALL ssl_want_read(SSL *ssl);

/**
* @brief Read the SSL data stream.
* If the socket is non-blocking and data is blocked then SSO_OK will be
Expand Down Expand Up @@ -289,6 +333,15 @@ EXP_FUNC int STDCALL ssl_read(SSL *ssl, uint8_t **in_data);
*/
EXP_FUNC int STDCALL ssl_write(SSL *ssl, const uint8_t *out_data, int out_len);

/**
* @brief Calculate the size of the encrypted data from what you are about to send
* @param ssl [in] An SSL obect reference.
* @param out_len [in] The number of bytes to be written.
* @return The number of bytes that will be sent, or if < 0 if an error.
* @see ssl.h for the error code list.
*/
EXP_FUNC int STDCALL ssl_calculate_write_length(SSL *ssl, int out_len);

/**
* @brief Find an ssl object based on a file descriptor.
*
Expand Down Expand Up @@ -367,7 +420,7 @@ EXP_FUNC void STDCALL ssl_display_error(int error_code);

/**
* @brief Authenticate a received certificate.
*
*
* This call is usually made by a client after a handshake is complete and the
* context is in SSL_SERVER_VERIFY_LATER mode.
* @param ssl [in] An SSL object reference.
Expand All @@ -385,8 +438,17 @@ EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl);
EXP_FUNC int STDCALL ssl_match_fingerprint(const SSL *ssl, const uint8_t* fp);

/**
* @brief Retrieve an X.509 distinguished name component.
* @brief Check if SHA256 hash of Subject Public Key Info matches the one given.
*
* @param ssl [in] An SSL object reference.
* @param fp [in] SHA256 hash to match against
* @return SSL_OK if the certificate is verified.
*/
EXP_FUNC int STDCALL ssl_match_spki_sha256(const SSL *ssl, const uint8_t* hash);

/**
* @brief Retrieve an X.509 distinguished name component.
*
* When a handshake is complete and a certificate has been exchanged, then the
* details of the remote certificate can be retrieved.
*
Expand Down
Binary file modified tools/sdk/lib/libaxtls.a
Binary file not shown.