Skip to content

Commit

Permalink
Add ALPN support to WiFiClientSecure (#5633)
Browse files Browse the repository at this point in the history
This adds a function to WiFiClientSecure to set the ALPN protocol.

This is required for an MQTT client to connect to AWS IoT when using an AWS Custom Authorizer, as described here.

Example code snippet:

...
WiFiClientSecure wiFiClient;

// ALPN protocol, needed with AWS custom authorizer
const char *aws_protos[] = {"mqtt", NULL};

void setup() {
  wiFiClient.setCACert(AWSCAPEM);
  wiFiClient.setAlpnProtocols(aws_protos);
}
...
  • Loading branch information
torntrousers committed Oct 25, 2021
1 parent 02c3ec0 commit 15bbd0a
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 4 deletions.
15 changes: 15 additions & 0 deletions libraries/WiFiClientSecure/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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);
```
1 change: 1 addition & 0 deletions libraries/WiFiClientSecure/keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ connected KEYWORD2
setCACert KEYWORD2
setCertificate KEYWORD2
setPrivateKey KEYWORD2
setAlpnProtocols KEYWORD2

#######################################
# Constants (LITERAL1)
Expand Down
11 changes: 9 additions & 2 deletions libraries/WiFiClientSecure/src/WiFiClientSecure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ WiFiClientSecure::WiFiClientSecure()
_pskIdent = NULL;
_psKey = NULL;
next = NULL;
_alpn_protos = NULL;
}


Expand All @@ -66,6 +67,7 @@ WiFiClientSecure::WiFiClientSecure(int sock)
_pskIdent = NULL;
_psKey = NULL;
next = NULL;
_alpn_protos = NULL;
}

WiFiClientSecure::~WiFiClientSecure()
Expand Down Expand Up @@ -127,7 +129,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);
Expand All @@ -147,7 +149,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);
Expand Down Expand Up @@ -341,3 +343,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;
}
2 changes: 2 additions & 0 deletions libraries/WiFiClientSecure/src/WiFiClientSecure.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
const mbedtls_x509_crt* getPeerCertificate() { return mbedtls_ssl_get_peer_cert(&sslclient->ssl_ctx); };
bool getFingerprintSHA256(uint8_t sha256_result[32]) { return get_peer_fingerprint(sslclient, sha256_result); };
int setTimeout(uint32_t seconds){ return 0; }
Expand Down
9 changes: 8 additions & 1 deletion libraries/WiFiClientSecure/src/ssl_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.

Expand Down
2 changes: 1 addition & 1 deletion libraries/WiFiClientSecure/src/ssl_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 15bbd0a

Please sign in to comment.