diff --git a/libraries/WiFiS3/src/WiFiSSLClient.cpp b/libraries/WiFiS3/src/WiFiSSLClient.cpp index bfe7c488..e0653e3d 100644 --- a/libraries/WiFiS3/src/WiFiSSLClient.cpp +++ b/libraries/WiFiS3/src/WiFiSSLClient.cpp @@ -62,6 +62,18 @@ int WiFiSSLClient::connect(const char* host, uint16_t port) { if(!modem.passthrough((uint8_t *)_ecc_cert, _ecc_cert_len)) { return 0; } + } else if(_client_cert != nullptr && _private_key != nullptr) { // TODO make sure if set certificate is called to not use the above code + size_t size = strlen(_client_cert); + modem.write_nowait(string(PROMPT(_SSLCLIENTSETCERT)),res, "%s%d,%d\r\n" , CMD_WRITE(_SSLCLIENTSETCERT), _sock, size); + if(!modem.passthrough((uint8_t *)_client_cert, size)) { + return 0; + } + + size = strlen(_private_key); + modem.write_nowait(string(PROMPT(_SSLCLIENTSETPKEY)),res, "%s%d,%d\r\n" , CMD_WRITE(_SSLCLIENTSETPKEY), _sock, size); + if(!modem.passthrough((uint8_t *)_private_key, size)) { + return 0; + } } if (_connectionTimeout) { @@ -88,6 +100,9 @@ void WiFiSSLClient::setEccSlot(int ecc508KeySlot, const byte cert[], int certLen _ecc_slot = ecc508KeySlot; _ecc_cert = cert; _ecc_cert_len = certLength; + + _client_cert = nullptr; + _private_key = nullptr; } /* -------------------------------------------------------------------------- */ @@ -282,4 +297,22 @@ uint16_t WiFiSSLClient::remotePort(){ } } return rv; -} \ No newline at end of file +} + +/* -------------------------------------------------------------------------- */ +void WiFiSSLClient::setCertificate(const char* clientCert){ +/* -------------------------------------------------------------------------- */ + _client_cert = clientCert; + _ecc_slot = -1; + _ecc_cert = nullptr; + _ecc_cert_len = 0; +} + +/* -------------------------------------------------------------------------- */ +void WiFiSSLClient::setPrivateKey(const char* privateKey){ +/* -------------------------------------------------------------------------- */ + _private_key = privateKey; + _ecc_slot = -1; + _ecc_cert = nullptr; + _ecc_cert_len = 0; +} diff --git a/libraries/WiFiS3/src/WiFiSSLClient.h b/libraries/WiFiS3/src/WiFiSSLClient.h index 2642c3d4..31add3ea 100644 --- a/libraries/WiFiS3/src/WiFiSSLClient.h +++ b/libraries/WiFiS3/src/WiFiSSLClient.h @@ -27,7 +27,7 @@ /** * @brief A specialized client class for secure SSL/TLS connections. - * + * * The WiFiSSLClient class extends the functionality of the WiFiClient class to provide secure * communication over SSL/TLS protocols. It ensures encrypted and authenticated communication * between the client and a remote server. @@ -43,21 +43,21 @@ class WiFiSSLClient : public WiFiClient { /** * @brief Establishes a secure SSL connection to a specified IP address and port. - * + * * @param It takes an `IPAddress` object representing the IP address of the server * and a `uint16_t` port number as parameters. * - * @return Returns a status code indicating the success or failure of the + * @return Returns a status code indicating the success or failure of the * connection. */ virtual int connect(IPAddress ip, uint16_t port); /** * @brief Establishes a secure SSL connection to a specified host and port. - * + * * @param `host` is the hostname or IP address of the server to connect to. * `port` is the port number to connect to. - * + * * @return Returns `1` if the connection is successfully established, `0` otherwise. */ virtual int connect(const char* host, uint16_t port); @@ -65,28 +65,31 @@ class WiFiSSLClient : public WiFiClient { /** * @brief Sets the Certificate Authority (CA) for SSL/TLS verification. * - * @param `root_ca` is a pointer to a null-terminated string containing the root - * CA certificate in PEM format. If set to `nullptr`, the default root + * @param `root_ca` is a pointer to a null-terminated string containing the root + * CA certificate in PEM format. If set to `nullptr`, the default root * CA bundle will be used. */ void setCACert(const char* root_ca); /** - * @brief Sets the ECC (Elliptic Curve Cryptography) key slot and + * @brief Sets the ECC (Elliptic Curve Cryptography) key slot and * certificate for establishing secure SSL connections. - * + * + * Note that this function will disable custom certificates and private keys set with + * setCertificate() and setPrivateKey() + * * @param `int ecc508KeySlot` specifies the ECC key slot to be used for the SSL connection. * @param `const byte cert[]` is a pointer to the certificate data in the form of an array of bytes. * @param `int certLength` specifies the length of the certificate data array. */ void setEccSlot(int ecc508KeySlot, const byte cert[], int certLength); - + /** * @brief Writes a single byte of data to the SSL connection. - * + * * @param `b` is the byte to be sent. - * - * @return The number of bytes successfully written. Returns `1` if the byte + * + * @return The number of bytes successfully written. Returns `1` if the byte * was sent successfully, or `0` if an error occurred. */ virtual size_t write(uint8_t); @@ -97,14 +100,14 @@ class WiFiSSLClient : public WiFiClient { * @param `buf` is a pointer to the buffer containing the data to be sent. * @param `size` is the number of bytes to send from the buffer. * - * @return Returns `size` if the data is successfully sent, + * @return Returns `size` if the data is successfully sent, * or `0` if the transmission fails or the socket is invalid. */ virtual size_t write(const uint8_t *buf, size_t size); - + /** * @brief Checks the number of bytes available for reading from the SSL connection. - * + * * @return Returns the number of bytes available to read from the SSL connection without blocking. */ virtual int available(); @@ -112,7 +115,7 @@ class WiFiSSLClient : public WiFiClient { /** * @brief Reads data from the SSL connection into the receive buffer. * - * @return Returns the number of bytes successfully read into the buffer. Returns + * @return Returns the number of bytes successfully read into the buffer. Returns * `0` if no data is received, or `-1` if the socket is invalid or an error occurs. */ virtual int read(); @@ -123,7 +126,7 @@ class WiFiSSLClient : public WiFiClient { * @param `buf` is a pointer to the buffer where the read data will be stored. * `size` is the maximum number of bytes to read into the buffer. * - * @return The number of bytes successfully read. Returns `0` if no data is + * @return The number of bytes successfully read. Returns `0` if no data is * available or an error occurs. */ virtual int read(uint8_t *buf, size_t size); @@ -131,18 +134,18 @@ class WiFiSSLClient : public WiFiClient { /** * @brief Peeks at the next byte available from the SSL connection without removing it. * - * This function queries the modem to retrieve the next byte available in the + * This function queries the modem to retrieve the next byte available in the * SSL/TLS connection, allowing the byte to remain in the buffer for future reads. * - * @return The next byte available as an integer value (0–255), or `-1` if + * @return The next byte available as an integer value (0–255), or `-1` if * the socket is invalid or no data is available. */ virtual int peek(); /** * @brief Flushes the write buffer of the SSL connection. - * - * This function clears the write buffer, ensuring that any pending data is sent + * + * This function clears the write buffer, ensuring that any pending data is sent * over the SSL/TLS connection. It uses the modem to handle the flush operation. */ virtual void flush(); @@ -155,8 +158,8 @@ class WiFiSSLClient : public WiFiClient { /** * @brief Checks if the SSL/TLS connection is active. * - * This function determines if the SSL/TLS client is still connected by querying - * the modem for the connection status. It checks the validity of the socket + * This function determines if the SSL/TLS client is still connected by querying + * the modem for the connection status. It checks the validity of the socket * before proceeding with the query. * * @return Returns `1` if the client is connected, `0` otherwise. @@ -165,7 +168,7 @@ class WiFiSSLClient : public WiFiClient { /** * @brief Implicit conversion operator to check if the SSL client is connected. - * + * * @return `true` if the socket is valid (i.e., connected), `false` otherwise. */ virtual operator bool() { @@ -174,9 +177,9 @@ class WiFiSSLClient : public WiFiClient { /** * @brief Comparison operator to check equality between two `WiFiSSLClient` objects. - * + * * @param `WiFiSSLClient` object to compare. - * + * * @return `true` if both WiFiSSLClient objects are equivalent (i.e., they have the same socket), * `false` otherwise. */ @@ -184,10 +187,10 @@ class WiFiSSLClient : public WiFiClient { /** * @brief Inequality operator to compare two `WiFiSSLClient` objects. - * + * * This operator compares the current `WiFiSSLClient` object with another `WiFiSSLClient` object * to determine if they are not equal, based on their underlying socket or connection. - * + * * @param `whs` The WiFiSSLClient object to compare with. * @return `true` if the two WiFiSSLClient objects do not represent the same connection (i.e., have different sockets), * `false` otherwise. @@ -200,10 +203,10 @@ class WiFiSSLClient : public WiFiClient { /** * @brief Retrieves the remote IP address of the WiFi SSL client. * - * This function queries the modem for the remote IP address associated with + * This function queries the modem for the remote IP address associated with * the current connection. * - * @return The remote IP address of the client. Returns `0.0.0.0` if the + * @return The remote IP address of the client. Returns `0.0.0.0` if the * socket is not valid or the query fails. */ virtual IPAddress remoteIP(); @@ -211,27 +214,50 @@ class WiFiSSLClient : public WiFiClient { /** * @brief Retrieves the remote port number of the WiFi SSL client. * - * This function queries the modem to obtain the remote port number associated + * This function queries the modem to obtain the remote port number associated * with the current connection. * - * @return Returns the remote port number of the client. Returns `0` if the socket + * @return Returns the remote port number of the client. Returns `0` if the socket * is not valid or the query fails. */ virtual uint16_t remotePort(); + /** + * @brief Set the public certificate for this ssl client communication + * + * This function explicitly sets the certificate to use for this client in tls + * communication. Note that if setEccSlot was used it will be disabled for this client. + * This function should be called in conjunction with setPrivateKey() + * + * @param `clientCert` client certificate in PEM format + * + */ + void setCertificate(const char* clientCert); + + /** + * @brief Set the private key for this ssl client communication + * + * This function explicitly sets the private key to use for this client in tls + * communication. Note that if setEccSlot was used it will be disabled for this client. + * This function should be called in conjunction with setCertificate() + * + * @param `privateKey` client private key in PEM format + * + */ + void setPrivateKey(const char* privateKey); /** * @brief Declares WiFiServer as a friend class. - * - * This allows the WiFiServer class to access private and protected members + * + * This allows the WiFiServer class to access private and protected members * of the WiFiSSLClient class. */ friend class WiFiServer; /** * @brief Inherits the `write` method from the Print class. - * - * This allows the WiFiSSLClient class to use the `write` method defined in the + * + * This allows the WiFiSSLClient class to use the `write` method defined in the * Print class. */ using Print::write; @@ -241,6 +267,8 @@ class WiFiSSLClient : public WiFiClient { int _read(); void read_if_needed(size_t s); const char* _root_ca = nullptr; + const char* _client_cert = nullptr; + const char* _private_key = nullptr; int _ecc_slot = -1; const byte* _ecc_cert = nullptr; int _ecc_cert_len = 0;