forked from espressif/arduino-esp32
Add ALPN support to WiFiClientSecure (#5633)
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); } ...
This commit is contained in:
@ -66,3 +66,18 @@ To use PSK:
|
|||||||
encryption for the connection
|
encryption for the connection
|
||||||
|
|
||||||
Please see the WiFiClientPSK example.
|
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);
|
||||||
|
```
|
@ -29,6 +29,7 @@ connected KEYWORD2
|
|||||||
setCACert KEYWORD2
|
setCACert KEYWORD2
|
||||||
setCertificate KEYWORD2
|
setCertificate KEYWORD2
|
||||||
setPrivateKey KEYWORD2
|
setPrivateKey KEYWORD2
|
||||||
|
setAlpnProtocols KEYWORD2
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Constants (LITERAL1)
|
# Constants (LITERAL1)
|
||||||
|
@ -43,6 +43,7 @@ WiFiClientSecure::WiFiClientSecure()
|
|||||||
_pskIdent = NULL;
|
_pskIdent = NULL;
|
||||||
_psKey = NULL;
|
_psKey = NULL;
|
||||||
next = NULL;
|
next = NULL;
|
||||||
|
_alpn_protos = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -66,6 +67,7 @@ WiFiClientSecure::WiFiClientSecure(int sock)
|
|||||||
_pskIdent = NULL;
|
_pskIdent = NULL;
|
||||||
_psKey = NULL;
|
_psKey = NULL;
|
||||||
next = NULL;
|
next = NULL;
|
||||||
|
_alpn_protos = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
WiFiClientSecure::~WiFiClientSecure()
|
WiFiClientSecure::~WiFiClientSecure()
|
||||||
@ -127,7 +129,7 @@ int WiFiClientSecure::connect(const char *host, uint16_t port, const char *CA_ce
|
|||||||
if(_timeout > 0){
|
if(_timeout > 0){
|
||||||
sslclient->handshake_timeout = _timeout;
|
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;
|
_lastError = ret;
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
log_e("start_ssl_client: %d", ret);
|
log_e("start_ssl_client: %d", ret);
|
||||||
@ -147,7 +149,7 @@ int WiFiClientSecure::connect(const char *host, uint16_t port, const char *pskId
|
|||||||
if(_timeout > 0){
|
if(_timeout > 0){
|
||||||
sslclient->handshake_timeout = _timeout;
|
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;
|
_lastError = ret;
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
log_e("start_ssl_client: %d", ret);
|
log_e("start_ssl_client: %d", ret);
|
||||||
@ -341,3 +343,8 @@ void WiFiClientSecure::setHandshakeTimeout(unsigned long handshake_timeout)
|
|||||||
{
|
{
|
||||||
sslclient->handshake_timeout = handshake_timeout * 1000;
|
sslclient->handshake_timeout = handshake_timeout * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WiFiClientSecure::setAlpnProtocols(const char **alpn_protos)
|
||||||
|
{
|
||||||
|
_alpn_protos = alpn_protos;
|
||||||
|
}
|
||||||
|
@ -39,6 +39,7 @@ protected:
|
|||||||
const char *_private_key;
|
const char *_private_key;
|
||||||
const char *_pskIdent; // identity for PSK cipher suites
|
const char *_pskIdent; // identity for PSK cipher suites
|
||||||
const char *_psKey; // key in hex for PSK cipher suites
|
const char *_psKey; // key in hex for PSK cipher suites
|
||||||
|
const char **_alpn_protos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WiFiClientSecure *next;
|
WiFiClientSecure *next;
|
||||||
@ -73,6 +74,7 @@ public:
|
|||||||
bool loadPrivateKey(Stream& stream, size_t size);
|
bool loadPrivateKey(Stream& stream, size_t size);
|
||||||
bool verify(const char* fingerprint, const char* domain_name);
|
bool verify(const char* fingerprint, const char* domain_name);
|
||||||
void setHandshakeTimeout(unsigned long handshake_timeout);
|
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); };
|
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); };
|
bool getFingerprintSHA256(uint8_t sha256_result[32]) { return get_peer_fingerprint(sslclient, sha256_result); };
|
||||||
int setTimeout(uint32_t seconds){ return 0; }
|
int setTimeout(uint32_t seconds){ return 0; }
|
||||||
|
@ -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];
|
char buf[512];
|
||||||
int ret, flags;
|
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);
|
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_REQUIRED if a CA certificate is defined on Arduino IDE and
|
||||||
// MBEDTLS_SSL_VERIFY_NONE if not.
|
// MBEDTLS_SSL_VERIFY_NONE if not.
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ typedef struct sslclient_context {
|
|||||||
|
|
||||||
|
|
||||||
void ssl_init(sslclient_context *ssl_client);
|
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);
|
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 data_to_read(sslclient_context *ssl_client);
|
||||||
int send_ssl_data(sslclient_context *ssl_client, const uint8_t *data, size_t len);
|
int send_ssl_data(sslclient_context *ssl_client, const uint8_t *data, size_t len);
|
||||||
|
Reference in New Issue
Block a user