From c30224a12e76dbb8307f729d1182629a6029bd11 Mon Sep 17 00:00:00 2001 From: ant Date: Sun, 5 Sep 2021 13:32:18 +0100 Subject: [PATCH 1/2] Add ALPN support --- libraries/WiFiClientSecure/README.md | 15 +++++++++++++++ libraries/WiFiClientSecure/keywords.txt | 1 + .../WiFiClientSecure/src/WiFiClientSecure.cpp | 9 +++++++-- libraries/WiFiClientSecure/src/WiFiClientSecure.h | 2 ++ libraries/WiFiClientSecure/src/ssl_client.cpp | 9 ++++++++- libraries/WiFiClientSecure/src/ssl_client.h | 2 +- 6 files changed, 34 insertions(+), 4 deletions(-) diff --git a/libraries/WiFiClientSecure/README.md b/libraries/WiFiClientSecure/README.md index c7582c15d99..fd5f4f51938 100644 --- a/libraries/WiFiClientSecure/README.md +++ b/libraries/WiFiClientSecure/README.md @@ -66,3 +66,18 @@ To use PSK: encryption for the connection Please see the WiFiClientPSK example. + +Specifying the ALPN Protocol +---------------------------- + +Application-Layer Protocol Negotiation (ALPN) is a Transport Layer Security (TLS) extension that allows +the application layer to negotiate which protocol should be performed over a secure connection in a manner +that avoids additional round trips and which is independent of the application-layer protocols. + +For example, this is used with AWS IoT Custom Authorizers where an MQTT client must set the ALPN protocol to ```mqtt```: + +``` +const char *aws_protos[] = {"mqtt", NULL}; +... +wiFiClient.setAlpnProtocols(aws_protos); +``` \ No newline at end of file diff --git a/libraries/WiFiClientSecure/keywords.txt b/libraries/WiFiClientSecure/keywords.txt index b1bf2c7388a..4bab096dbd5 100644 --- a/libraries/WiFiClientSecure/keywords.txt +++ b/libraries/WiFiClientSecure/keywords.txt @@ -29,6 +29,7 @@ connected KEYWORD2 setCACert KEYWORD2 setCertificate KEYWORD2 setPrivateKey KEYWORD2 +setAlpnProtocols KEYWORD2 ####################################### # Constants (LITERAL1) diff --git a/libraries/WiFiClientSecure/src/WiFiClientSecure.cpp b/libraries/WiFiClientSecure/src/WiFiClientSecure.cpp index 26ac7e431cc..8218bd71a27 100644 --- a/libraries/WiFiClientSecure/src/WiFiClientSecure.cpp +++ b/libraries/WiFiClientSecure/src/WiFiClientSecure.cpp @@ -127,7 +127,7 @@ int WiFiClientSecure::connect(const char *host, uint16_t port, const char *CA_ce if(_timeout > 0){ sslclient->handshake_timeout = _timeout; } - int ret = start_ssl_client(sslclient, host, port, _timeout, CA_cert, cert, private_key, NULL, NULL, _use_insecure); + int ret = start_ssl_client(sslclient, host, port, _timeout, CA_cert, cert, private_key, NULL, NULL, _use_insecure, _alpn_protos); _lastError = ret; if (ret < 0) { log_e("start_ssl_client: %d", ret); @@ -147,7 +147,7 @@ int WiFiClientSecure::connect(const char *host, uint16_t port, const char *pskId if(_timeout > 0){ sslclient->handshake_timeout = _timeout; } - int ret = start_ssl_client(sslclient, host, port, _timeout, NULL, NULL, NULL, pskIdent, psKey, _use_insecure); + int ret = start_ssl_client(sslclient, host, port, _timeout, NULL, NULL, NULL, pskIdent, psKey, _use_insecure, _alpn_protos); _lastError = ret; if (ret < 0) { log_e("start_ssl_client: %d", ret); @@ -341,3 +341,8 @@ void WiFiClientSecure::setHandshakeTimeout(unsigned long handshake_timeout) { sslclient->handshake_timeout = handshake_timeout * 1000; } + +void WiFiClientSecure::setAlpnProtocols(const char **alpn_protos) +{ + _alpn_protos = alpn_protos; +} diff --git a/libraries/WiFiClientSecure/src/WiFiClientSecure.h b/libraries/WiFiClientSecure/src/WiFiClientSecure.h index 8a30145ef47..ca7bc7047b1 100644 --- a/libraries/WiFiClientSecure/src/WiFiClientSecure.h +++ b/libraries/WiFiClientSecure/src/WiFiClientSecure.h @@ -39,6 +39,7 @@ class WiFiClientSecure : public WiFiClient const char *_private_key; const char *_pskIdent; // identity for PSK cipher suites const char *_psKey; // key in hex for PSK cipher suites + const char **_alpn_protos; public: WiFiClientSecure *next; @@ -73,6 +74,7 @@ class WiFiClientSecure : public WiFiClient bool loadPrivateKey(Stream& stream, size_t size); bool verify(const char* fingerprint, const char* domain_name); void setHandshakeTimeout(unsigned long handshake_timeout); + void setAlpnProtocols(const char **alpn_protos); int setTimeout(uint32_t seconds){ return 0; } diff --git a/libraries/WiFiClientSecure/src/ssl_client.cpp b/libraries/WiFiClientSecure/src/ssl_client.cpp index d643f43ee11..03bb68527b2 100644 --- a/libraries/WiFiClientSecure/src/ssl_client.cpp +++ b/libraries/WiFiClientSecure/src/ssl_client.cpp @@ -51,7 +51,7 @@ void ssl_init(sslclient_context *ssl_client) } -int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey, bool insecure) +int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey, bool insecure, const char **alpn_protos) { char buf[512]; int ret, flags; @@ -156,6 +156,13 @@ int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t p return handle_error(ret); } + if (alpn_protos != NULL) { + log_v("Setting ALPN protocols"); + if ((ret = mbedtls_ssl_conf_alpn_protocols(&ssl_client->ssl_conf, alpn_protos) ) != 0) { + return handle_error(ret); + } + } + // MBEDTLS_SSL_VERIFY_REQUIRED if a CA certificate is defined on Arduino IDE and // MBEDTLS_SSL_VERIFY_NONE if not. diff --git a/libraries/WiFiClientSecure/src/ssl_client.h b/libraries/WiFiClientSecure/src/ssl_client.h index 5ee662fbcec..27a6ddf3682 100644 --- a/libraries/WiFiClientSecure/src/ssl_client.h +++ b/libraries/WiFiClientSecure/src/ssl_client.h @@ -29,7 +29,7 @@ typedef struct sslclient_context { void ssl_init(sslclient_context *ssl_client); -int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey, bool insecure); +int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey, bool insecure, const char **alpn_protos); void stop_ssl_socket(sslclient_context *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key); int data_to_read(sslclient_context *ssl_client); int send_ssl_data(sslclient_context *ssl_client, const uint8_t *data, size_t len); From 00da95f6ec7fdafc205c97a0ef7c39562f390b6c Mon Sep 17 00:00:00 2001 From: ant Date: Fri, 15 Oct 2021 10:38:32 +0100 Subject: [PATCH 2/2] set _alpn_protos to NULL in constructors --- libraries/WiFiClientSecure/src/WiFiClientSecure.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/WiFiClientSecure/src/WiFiClientSecure.cpp b/libraries/WiFiClientSecure/src/WiFiClientSecure.cpp index 8218bd71a27..4f19d57a4d0 100644 --- a/libraries/WiFiClientSecure/src/WiFiClientSecure.cpp +++ b/libraries/WiFiClientSecure/src/WiFiClientSecure.cpp @@ -43,6 +43,7 @@ WiFiClientSecure::WiFiClientSecure() _pskIdent = NULL; _psKey = NULL; next = NULL; + _alpn_protos = NULL; } @@ -66,6 +67,7 @@ WiFiClientSecure::WiFiClientSecure(int sock) _pskIdent = NULL; _psKey = NULL; next = NULL; + _alpn_protos = NULL; } WiFiClientSecure::~WiFiClientSecure()