1 // Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #ifndef _ESP_TLS_H_
15 #define _ESP_TLS_H_
16
17 #include <stdbool.h>
18 #include <sys/socket.h>
19 #include <fcntl.h>
20 #include "esp_err.h"
21 #ifdef CONFIG_ESP_TLS_USING_MBEDTLS
22 #include "mbedtls/platform.h"
23 #include "mbedtls/net_sockets.h"
24 #include "mbedtls/esp_debug.h"
25 #include "mbedtls/ssl.h"
26 #include "mbedtls/entropy.h"
27 #include "mbedtls/ctr_drbg.h"
28 #include "mbedtls/error.h"
29 #include "mbedtls/certs.h"
30 #elif CONFIG_ESP_TLS_USING_WOLFSSL
31 #include "wolfssl/wolfcrypt/settings.h"
32 #include "wolfssl/ssl.h"
33 #endif
34
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38
39 #define ESP_ERR_ESP_TLS_BASE 0x8000 /*!< Starting number of ESP-TLS error codes */
40 #define ESP_ERR_ESP_TLS_CANNOT_RESOLVE_HOSTNAME (ESP_ERR_ESP_TLS_BASE + 0x01) /*!< Error if hostname couldn't be resolved upon tls connection */
41 #define ESP_ERR_ESP_TLS_CANNOT_CREATE_SOCKET (ESP_ERR_ESP_TLS_BASE + 0x02) /*!< Failed to create socket */
42 #define ESP_ERR_ESP_TLS_UNSUPPORTED_PROTOCOL_FAMILY (ESP_ERR_ESP_TLS_BASE + 0x03) /*!< Unsupported protocol family */
43 #define ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST (ESP_ERR_ESP_TLS_BASE + 0x04) /*!< Failed to connect to host */
44 #define ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED (ESP_ERR_ESP_TLS_BASE + 0x05) /*!< failed to set socket option */
45 #define ESP_ERR_MBEDTLS_CERT_PARTLY_OK (ESP_ERR_ESP_TLS_BASE + 0x06) /*!< mbedtls parse certificates was partly successful */
46 #define ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED (ESP_ERR_ESP_TLS_BASE + 0x07) /*!< mbedtls api returned error */
47 #define ESP_ERR_MBEDTLS_SSL_SET_HOSTNAME_FAILED (ESP_ERR_ESP_TLS_BASE + 0x08) /*!< mbedtls api returned error */
48 #define ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x09) /*!< mbedtls api returned error */
49 #define ESP_ERR_MBEDTLS_SSL_CONF_ALPN_PROTOCOLS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0A) /*!< mbedtls api returned error */
50 #define ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0B) /*!< mbedtls api returned error */
51 #define ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0C) /*!< mbedtls api returned error */
52 #define ESP_ERR_MBEDTLS_SSL_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0D) /*!< mbedtls api returned error */
53 #define ESP_ERR_MBEDTLS_SSL_WRITE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0E) /*!< mbedtls api returned error */
54 #define ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0F) /*!< mbedtls api returned failed */
55 #define ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x10) /*!< mbedtls api returned failed */
56 #define ESP_ERR_MBEDTLS_SSL_CONF_PSK_FAILED (ESP_ERR_ESP_TLS_BASE + 0x11) /*!< mbedtls api returned failed */
57 #define ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT (ESP_ERR_ESP_TLS_BASE + 0x12) /*!< new connection in esp_tls_low_level_conn connection timeouted */
58 #define ESP_ERR_WOLFSSL_SSL_SET_HOSTNAME_FAILED (ESP_ERR_ESP_TLS_BASE + 0x13) /*!< wolfSSL api returned error */
59 #define ESP_ERR_WOLFSSL_SSL_CONF_ALPN_PROTOCOLS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x14) /*!< wolfSSL api returned error */
60 #define ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x15) /*!< wolfSSL api returned error */
61 #define ESP_ERR_WOLFSSL_KEY_VERIFY_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x16) /*!< wolfSSL api returned error */
62 #define ESP_ERR_WOLFSSL_SSL_HANDSHAKE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x17) /*!< wolfSSL api returned failed */
63 #define ESP_ERR_WOLFSSL_CTX_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x18) /*!< wolfSSL api returned failed */
64 #define ESP_ERR_WOLFSSL_SSL_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x19) /*!< wolfSSL api returned failed */
65 #define ESP_ERR_WOLFSSL_SSL_WRITE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x1A) /*!< wolfSSL api returned failed */
66
67 #define ESP_ERR_ESP_TLS_SE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x1B) /*< esp-tls use Secure Element returned failed */
68 #ifdef CONFIG_ESP_TLS_USING_MBEDTLS
69 #define ESP_TLS_ERR_SSL_WANT_READ MBEDTLS_ERR_SSL_WANT_READ
70 #define ESP_TLS_ERR_SSL_WANT_WRITE MBEDTLS_ERR_SSL_WANT_WRITE
71 #define ESP_TLS_ERR_SSL_TIMEOUT MBEDTLS_ERR_SSL_TIMEOUT
72 #elif CONFIG_ESP_TLS_USING_WOLFSSL /* CONFIG_ESP_TLS_USING_MBEDTLS */
73 #define ESP_TLS_ERR_SSL_WANT_READ WOLFSSL_ERROR_WANT_READ
74 #define ESP_TLS_ERR_SSL_WANT_WRITE WOLFSSL_ERROR_WANT_WRITE
75 #define ESP_TLS_ERR_SSL_TIMEOUT WOLFSSL_CBIO_ERR_TIMEOUT
76 #endif /*CONFIG_ESP_TLS_USING_WOLFSSL */
77
78 /**
79 * Definition of different types/sources of error codes reported
80 * from different components
81 */
82 typedef enum {
83 ESP_TLS_ERR_TYPE_UNKNOWN = 0,
84 ESP_TLS_ERR_TYPE_SYSTEM, /*!< System error -- errno */
85 ESP_TLS_ERR_TYPE_MBEDTLS, /*!< Error code from mbedTLS library */
86 ESP_TLS_ERR_TYPE_MBEDTLS_CERT_FLAGS, /*!< Certificate flags defined in mbedTLS */
87 ESP_TLS_ERR_TYPE_ESP, /*!< ESP-IDF error type -- esp_err_t */
88 ESP_TLS_ERR_TYPE_WOLFSSL, /*!< Error code from wolfSSL library */
89 ESP_TLS_ERR_TYPE_WOLFSSL_CERT_FLAGS, /*!< Certificate flags defined in wolfSSL */
90 ESP_TLS_ERR_TYPE_MAX, /*!< Last err type -- invalid entry */
91 } esp_tls_error_type_t;
92
93 typedef struct esp_tls_last_error* esp_tls_error_handle_t;
94
95 /**
96 * @brief Error structure containing relevant errors in case tls error occurred
97 */
98 typedef struct esp_tls_last_error {
99 esp_err_t last_error; /*!< error code (based on ESP_ERR_ESP_TLS_BASE) of the last occurred error */
100 int esp_tls_error_code; /*!< esp_tls error code from last esp_tls failed api */
101 int esp_tls_flags; /*!< last certification verification flags */
102 } esp_tls_last_error_t;
103
104 /**
105 * @brief ESP-TLS Connection State
106 */
107 typedef enum esp_tls_conn_state {
108 ESP_TLS_INIT = 0,
109 ESP_TLS_CONNECTING,
110 ESP_TLS_HANDSHAKE,
111 ESP_TLS_FAIL,
112 ESP_TLS_DONE,
113 } esp_tls_conn_state_t;
114
115 typedef enum esp_tls_role {
116 ESP_TLS_CLIENT = 0,
117 ESP_TLS_SERVER,
118 } esp_tls_role_t;
119
120 /**
121 * @brief ESP-TLS preshared key and hint structure
122 */
123 typedef struct psk_key_hint {
124 const uint8_t* key; /*!< key in PSK authentication mode in binary format */
125 const size_t key_size; /*!< length of the key */
126 const char* hint; /*!< hint in PSK authentication mode in string format */
127 } psk_hint_key_t;
128
129 /**
130 * @brief Keep alive parameters structure
131 */
132 typedef struct tls_keep_alive_cfg {
133 bool keep_alive_enable; /*!< Enable keep-alive timeout */
134 int keep_alive_idle; /*!< Keep-alive idle time (second) */
135 int keep_alive_interval; /*!< Keep-alive interval time (second) */
136 int keep_alive_count; /*!< Keep-alive packet retry send count */
137 } tls_keep_alive_cfg_t;
138
139 /**
140 * @brief ESP-TLS configuration parameters
141 *
142 * @note Note about format of certificates:
143 * - This structure includes certificates of a Certificate Authority, of client or server as well
144 * as private keys, which may be of PEM or DER format. In case of PEM format, the buffer must be
145 * NULL terminated (with NULL character included in certificate size).
146 * - Certificate Authority's certificate may be a chain of certificates in case of PEM format,
147 * but could be only one certificate in case of DER format
148 * - Variables names of certificates and private key buffers and sizes are defined as unions providing
149 * backward compatibility for legacy *_pem_buf and *_pem_bytes names which suggested only PEM format
150 * was supported. It is encouraged to use generic names such as cacert_buf and cacert_bytes.
151 */
152 typedef struct esp_tls_cfg {
153 const char **alpn_protos; /*!< Application protocols required for HTTP2.
154 If HTTP2/ALPN support is required, a list
155 of protocols that should be negotiated.
156 The format is length followed by protocol
157 name.
158 For the most common cases the following is ok:
159 const char **alpn_protos = { "h2", NULL };
160 - where 'h2' is the protocol name */
161
162 union {
163 const unsigned char *cacert_buf; /*!< Certificate Authority's certificate in a buffer.
164 Format may be PEM or DER, depending on mbedtls-support
165 This buffer should be NULL terminated in case of PEM */
166 const unsigned char *cacert_pem_buf; /*!< CA certificate buffer legacy name */
167 };
168
169 union {
170 unsigned int cacert_bytes; /*!< Size of Certificate Authority certificate
171 pointed to by cacert_buf
172 (including NULL-terminator in case of PEM format) */
173 unsigned int cacert_pem_bytes; /*!< Size of Certificate Authority certificate legacy name */
174 };
175
176 union {
177 const unsigned char *clientcert_buf; /*!< Client certificate in a buffer
178 Format may be PEM or DER, depending on mbedtls-support
179 This buffer should be NULL terminated in case of PEM */
180 const unsigned char *clientcert_pem_buf; /*!< Client certificate legacy name */
181 };
182
183 union {
184 unsigned int clientcert_bytes; /*!< Size of client certificate pointed to by
185 clientcert_pem_buf
186 (including NULL-terminator in case of PEM format) */
187 unsigned int clientcert_pem_bytes; /*!< Size of client certificate legacy name */
188 };
189
190 union {
191 const unsigned char *clientkey_buf; /*!< Client key in a buffer
192 Format may be PEM or DER, depending on mbedtls-support
193 This buffer should be NULL terminated in case of PEM */
194 const unsigned char *clientkey_pem_buf; /*!< Client key legacy name */
195 };
196
197 union {
198 unsigned int clientkey_bytes; /*!< Size of client key pointed to by
199 clientkey_pem_buf
200 (including NULL-terminator in case of PEM format) */
201 unsigned int clientkey_pem_bytes; /*!< Size of client key legacy name */
202 };
203
204 const unsigned char *clientkey_password;/*!< Client key decryption password string */
205
206 unsigned int clientkey_password_len; /*!< String length of the password pointed to by
207 clientkey_password */
208
209 bool non_block; /*!< Configure non-blocking mode. If set to true the
210 underneath socket will be configured in non
211 blocking mode after tls session is established */
212
213 bool use_secure_element; /*!< Enable this option to use secure element or
214 atecc608a chip ( Integrated with ESP32-WROOM-32SE ) */
215
216 int timeout_ms; /*!< Network timeout in milliseconds */
217
218 bool use_global_ca_store; /*!< Use a global ca_store for all the connections in which
219 this bool is set. */
220
221 const char *common_name; /*!< If non-NULL, server certificate CN must match this name.
222 If NULL, server certificate CN must match hostname. */
223
224 bool skip_common_name; /*!< Skip any validation of server certificate CN field */
225
226 tls_keep_alive_cfg_t *keep_alive_cfg; /*!< Enable TCP keep-alive timeout for SSL connection */
227
228 const psk_hint_key_t* psk_hint_key; /*!< Pointer to PSK hint and key. if not NULL (and certificates are NULL)
229 then PSK authentication is enabled with configured setup.
230 Important note: the pointer must be valid for connection */
231
232 esp_err_t (*crt_bundle_attach)(void *conf);
233 /*!< Function pointer to esp_crt_bundle_attach. Enables the use of certification
234 bundle for server verification, must be enabled in menuconfig */
235
236 void *ds_data; /*!< Pointer for digital signature peripheral context */
237 } esp_tls_cfg_t;
238
239 #ifdef CONFIG_ESP_TLS_SERVER
240 typedef struct esp_tls_cfg_server {
241 const char **alpn_protos; /*!< Application protocols required for HTTP2.
242 If HTTP2/ALPN support is required, a list
243 of protocols that should be negotiated.
244 The format is length followed by protocol
245 name.
246 For the most common cases the following is ok:
247 const char **alpn_protos = { "h2", NULL };
248 - where 'h2' is the protocol name */
249
250 union {
251 const unsigned char *cacert_buf; /*!< Client CA certificate in a buffer.
252 This buffer should be NULL terminated */
253 const unsigned char *cacert_pem_buf; /*!< Client CA certificate legacy name */
254 };
255
256 union {
257 unsigned int cacert_bytes; /*!< Size of client CA certificate
258 pointed to by cacert_pem_buf */
259 unsigned int cacert_pem_bytes; /*!< Size of client CA certificate legacy name */
260 };
261
262 union {
263 const unsigned char *servercert_buf; /*!< Server certificate in a buffer
264 This buffer should be NULL terminated */
265 const unsigned char *servercert_pem_buf; /*!< Server certificate legacy name */
266 };
267
268 union {
269 unsigned int servercert_bytes; /*!< Size of server certificate pointed to by
270 servercert_pem_buf */
271 unsigned int servercert_pem_bytes; /*!< Size of server certificate legacy name */
272 };
273
274 union {
275 const unsigned char *serverkey_buf; /*!< Server key in a buffer
276 This buffer should be NULL terminated */
277 const unsigned char *serverkey_pem_buf; /*!< Server key legacy name */
278 };
279
280 union {
281 unsigned int serverkey_bytes; /*!< Size of server key pointed to by
282 serverkey_pem_buf */
283 unsigned int serverkey_pem_bytes; /*!< Size of server key legacy name */
284 };
285
286 const unsigned char *serverkey_password; /*!< Server key decryption password string */
287
288 unsigned int serverkey_password_len; /*!< String length of the password pointed to by
289 serverkey_password */
290
291 } esp_tls_cfg_server_t;
292 #endif /* ! CONFIG_ESP_TLS_SERVER */
293
294 /**
295 * @brief ESP-TLS Connection Handle
296 */
297 typedef struct esp_tls {
298 #ifdef CONFIG_ESP_TLS_USING_MBEDTLS
299 mbedtls_ssl_context ssl; /*!< TLS/SSL context */
300
301 mbedtls_entropy_context entropy; /*!< mbedTLS entropy context structure */
302
303 mbedtls_ctr_drbg_context ctr_drbg; /*!< mbedTLS ctr drbg context structure.
304 CTR_DRBG is deterministic random
305 bit generation based on AES-256 */
306
307 mbedtls_ssl_config conf; /*!< TLS/SSL configuration to be shared
308 between mbedtls_ssl_context
309 structures */
310
311 mbedtls_net_context server_fd; /*!< mbedTLS wrapper type for sockets */
312
313 mbedtls_x509_crt cacert; /*!< Container for the X.509 CA certificate */
314
315 mbedtls_x509_crt *cacert_ptr; /*!< Pointer to the cacert being used. */
316
317 mbedtls_x509_crt clientcert; /*!< Container for the X.509 client certificate */
318
319 mbedtls_pk_context clientkey; /*!< Container for the private key of the client
320 certificate */
321 #ifdef CONFIG_ESP_TLS_SERVER
322 mbedtls_x509_crt servercert; /*!< Container for the X.509 server certificate */
323
324 mbedtls_pk_context serverkey; /*!< Container for the private key of the server
325 certificate */
326 #endif
327 #elif CONFIG_ESP_TLS_USING_WOLFSSL
328 void *priv_ctx;
329 void *priv_ssl;
330 #endif
331 int sockfd; /*!< Underlying socket file descriptor. */
332
333 ssize_t (*read)(struct esp_tls *tls, char *data, size_t datalen); /*!< Callback function for reading data from TLS/SSL
334 connection. */
335
336 ssize_t (*write)(struct esp_tls *tls, const char *data, size_t datalen); /*!< Callback function for writing data to TLS/SSL
337 connection. */
338
339 esp_tls_conn_state_t conn_state; /*!< ESP-TLS Connection state */
340
341 fd_set rset; /*!< read file descriptors */
342
343 fd_set wset; /*!< write file descriptors */
344
345 bool is_tls; /*!< indicates connection type (TLS or NON-TLS) */
346
347 esp_tls_role_t role; /*!< esp-tls role
348 - ESP_TLS_CLIENT
349 - ESP_TLS_SERVER */
350
351 esp_tls_error_handle_t error_handle; /*!< handle to error descriptor */
352
353 } esp_tls_t;
354
355
356 /**
357 * @brief Create TLS connection
358 *
359 * This function allocates and initializes esp-tls structure handle.
360 *
361 * @return tls Pointer to esp-tls as esp-tls handle if successfully initialized,
362 * NULL if allocation error
363 */
364 esp_tls_t *esp_tls_init(void);
365
366
367
368
369 /**
370 * @brief Create a new blocking TLS/SSL connection
371 *
372 * This function establishes a TLS/SSL connection with the specified host in blocking manner.
373 *
374 * Note: This API is present for backward compatibility reasons. Alternative function
375 * with the same functionality is `esp_tls_conn_new_sync` (and its asynchronous version
376 * `esp_tls_conn_new_async`)
377 *
378 * @param[in] hostname Hostname of the host.
379 * @param[in] hostlen Length of hostname.
380 * @param[in] port Port number of the host.
381 * @param[in] cfg TLS configuration as esp_tls_cfg_t. If you wish to open
382 * non-TLS connection, keep this NULL. For TLS connection,
383 * a pass pointer to esp_tls_cfg_t. At a minimum, this
384 * structure should be zero-initialized.
385 *
386 * @return pointer to esp_tls_t, or NULL if connection couldn't be opened.
387 */
388 esp_tls_t *esp_tls_conn_new(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg) __attribute__ ((deprecated));
389
390 /**
391 * @brief Create a new blocking TLS/SSL connection
392 *
393 * This function establishes a TLS/SSL connection with the specified host in blocking manner.
394 *
395 * @param[in] hostname Hostname of the host.
396 * @param[in] hostlen Length of hostname.
397 * @param[in] port Port number of the host.
398 * @param[in] cfg TLS configuration as esp_tls_cfg_t. If you wish to open
399 * non-TLS connection, keep this NULL. For TLS connection,
400 * a pass pointer to esp_tls_cfg_t. At a minimum, this
401 * structure should be zero-initialized.
402 * @param[in] tls Pointer to esp-tls as esp-tls handle.
403 *
404 * @return
405 * - -1 If connection establishment fails.
406 * - 1 If connection establishment is successful.
407 * - 0 If connection state is in progress.
408 */
409 int esp_tls_conn_new_sync(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls);
410
411 /**
412 * @brief Create a new blocking TLS/SSL connection with a given "HTTP" url
413 *
414 * The behaviour is same as esp_tls_conn_new() API. However this API accepts host's url.
415 *
416 * @param[in] url url of host.
417 * @param[in] cfg TLS configuration as esp_tls_cfg_t. If you wish to open
418 * non-TLS connection, keep this NULL. For TLS connection,
419 * a pass pointer to 'esp_tls_cfg_t'. At a minimum, this
420 * structure should be zero-initialized.
421 * @return pointer to esp_tls_t, or NULL if connection couldn't be opened.
422 */
423 esp_tls_t *esp_tls_conn_http_new(const char *url, const esp_tls_cfg_t *cfg);
424
425 /**
426 * @brief Create a new non-blocking TLS/SSL connection
427 *
428 * This function initiates a non-blocking TLS/SSL connection with the specified host, but due to
429 * its non-blocking nature, it doesn't wait for the connection to get established.
430 *
431 * @param[in] hostname Hostname of the host.
432 * @param[in] hostlen Length of hostname.
433 * @param[in] port Port number of the host.
434 * @param[in] cfg TLS configuration as esp_tls_cfg_t. `non_block` member of
435 * this structure should be set to be true.
436 * @param[in] tls pointer to esp-tls as esp-tls handle.
437 *
438 * @return
439 * - -1 If connection establishment fails.
440 * - 0 If connection establishment is in progress.
441 * - 1 If connection establishment is successful.
442 */
443 int esp_tls_conn_new_async(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls);
444
445 /**
446 * @brief Create a new non-blocking TLS/SSL connection with a given "HTTP" url
447 *
448 * The behaviour is same as esp_tls_conn_new() API. However this API accepts host's url.
449 *
450 * @param[in] url url of host.
451 * @param[in] cfg TLS configuration as esp_tls_cfg_t.
452 * @param[in] tls pointer to esp-tls as esp-tls handle.
453 *
454 * @return
455 * - -1 If connection establishment fails.
456 * - 0 If connection establishment is in progress.
457 * - 1 If connection establishment is successful.
458 */
459 int esp_tls_conn_http_new_async(const char *url, const esp_tls_cfg_t *cfg, esp_tls_t *tls);
460
461 /**
462 * @brief Write from buffer 'data' into specified tls connection.
463 *
464 * @param[in] tls pointer to esp-tls as esp-tls handle.
465 * @param[in] data Buffer from which data will be written.
466 * @param[in] datalen Length of data buffer.
467 *
468 * @return
469 * - >=0 if write operation was successful, the return value is the number
470 * of bytes actually written to the TLS/SSL connection.
471 * - <0 if write operation was not successful, because either an
472 * error occured or an action must be taken by the calling process.
473 */
esp_tls_conn_write(esp_tls_t * tls,const void * data,size_t datalen)474 static inline ssize_t esp_tls_conn_write(esp_tls_t *tls, const void *data, size_t datalen)
475 {
476 return tls->write(tls, (char *)data, datalen);
477 }
478
479 /**
480 * @brief Read from specified tls connection into the buffer 'data'.
481 *
482 * @param[in] tls pointer to esp-tls as esp-tls handle.
483 * @param[in] data Buffer to hold read data.
484 * @param[in] datalen Length of data buffer.
485 *
486 * @return
487 * - >0 if read operation was successful, the return value is the number
488 * of bytes actually read from the TLS/SSL connection.
489 * - 0 if read operation was not successful. The underlying
490 * connection was closed.
491 * - <0 if read operation was not successful, because either an
492 * error occured or an action must be taken by the calling process.
493 */
esp_tls_conn_read(esp_tls_t * tls,void * data,size_t datalen)494 static inline ssize_t esp_tls_conn_read(esp_tls_t *tls, void *data, size_t datalen)
495 {
496 return tls->read(tls, (char *)data, datalen);
497 }
498
499 /**
500 * @brief Compatible version of esp_tls_conn_destroy() to close the TLS/SSL connection
501 *
502 * @note This API will be removed in IDFv5.0
503 *
504 * @param[in] tls pointer to esp-tls as esp-tls handle.
505 */
506 void esp_tls_conn_delete(esp_tls_t *tls);
507
508 /**
509 * @brief Close the TLS/SSL connection and free any allocated resources.
510 *
511 * This function should be called to close each tls connection opened with esp_tls_conn_new() or
512 * esp_tls_conn_http_new() APIs.
513 *
514 * @param[in] tls pointer to esp-tls as esp-tls handle.
515 *
516 * @return - 0 on success
517 * - -1 if socket error or an invalid argument
518 */
519 int esp_tls_conn_destroy(esp_tls_t *tls);
520
521 /**
522 * @brief Return the number of application data bytes remaining to be
523 * read from the current record
524 *
525 * This API is a wrapper over mbedtls's mbedtls_ssl_get_bytes_avail() API.
526 *
527 * @param[in] tls pointer to esp-tls as esp-tls handle.
528 *
529 * @return
530 * - -1 in case of invalid arg
531 * - bytes available in the application data
532 * record read buffer
533 */
534 ssize_t esp_tls_get_bytes_avail(esp_tls_t *tls);
535
536 /**
537 * @brief Returns the connection socket file descriptor from esp_tls session
538 *
539 * @param[in] tls handle to esp_tls context
540 *
541 * @param[out] sockfd int pointer to sockfd value.
542 *
543 * @return - ESP_OK on success and value of sockfd will be updated with socket file descriptor for connection
544 * - ESP_ERR_INVALID_ARG if (tls == NULL || sockfd == NULL)
545 */
546 esp_err_t esp_tls_get_conn_sockfd(esp_tls_t *tls, int *sockfd);
547
548 /**
549 * @brief Create a global CA store, initially empty.
550 *
551 * This function should be called if the application wants to use the same CA store for multiple connections.
552 * This function initialises the global CA store which can be then set by calling esp_tls_set_global_ca_store().
553 * To be effective, this function must be called before any call to esp_tls_set_global_ca_store().
554 *
555 * @return
556 * - ESP_OK if creating global CA store was successful.
557 * - ESP_ERR_NO_MEM if an error occured when allocating the mbedTLS resources.
558 */
559 esp_err_t esp_tls_init_global_ca_store(void);
560
561 /**
562 * @brief Set the global CA store with the buffer provided in pem format.
563 *
564 * This function should be called if the application wants to set the global CA store for
565 * multiple connections i.e. to add the certificates in the provided buffer to the certificate chain.
566 * This function implicitly calls esp_tls_init_global_ca_store() if it has not already been called.
567 * The application must call this function before calling esp_tls_conn_new().
568 *
569 * @param[in] cacert_pem_buf Buffer which has certificates in pem format. This buffer
570 * is used for creating a global CA store, which can be used
571 * by other tls connections.
572 * @param[in] cacert_pem_bytes Length of the buffer.
573 *
574 * @return
575 * - ESP_OK if adding certificates was successful.
576 * - Other if an error occured or an action must be taken by the calling process.
577 */
578 esp_err_t esp_tls_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes);
579
580 /**
581 * @brief Free the global CA store currently being used.
582 *
583 * The memory being used by the global CA store to store all the parsed certificates is
584 * freed up. The application can call this API if it no longer needs the global CA store.
585 */
586 void esp_tls_free_global_ca_store(void);
587
588 /**
589 * @brief Returns last error in esp_tls with detailed mbedtls related error codes.
590 * The error information is cleared internally upon return
591 *
592 * @param[in] h esp-tls error handle.
593 * @param[out] esp_tls_code last error code returned from mbedtls api (set to zero if none)
594 * This pointer could be NULL if caller does not care about esp_tls_code
595 * @param[out] esp_tls_flags last certification verification flags (set to zero if none)
596 * This pointer could be NULL if caller does not care about esp_tls_code
597 *
598 * @return
599 * - ESP_ERR_INVALID_STATE if invalid parameters
600 * - ESP_OK (0) if no error occurred
601 * - specific error code (based on ESP_ERR_ESP_TLS_BASE) otherwise
602 */
603 esp_err_t esp_tls_get_and_clear_last_error(esp_tls_error_handle_t h, int *esp_tls_code, int *esp_tls_flags);
604
605 /**
606 * @brief Returns the last error captured in esp_tls of a specific type
607 * The error information is cleared internally upon return
608 *
609 * @param[in] h esp-tls error handle.
610 * @param[in] err_type specific error type
611 * @param[out] error_code last error code returned from mbedtls api (set to zero if none)
612 * This pointer could be NULL if caller does not care about esp_tls_code
613 * @return
614 * - ESP_ERR_INVALID_STATE if invalid parameters
615 * - ESP_OK if a valid error returned and was cleared
616 */
617 esp_err_t esp_tls_get_and_clear_error_type(esp_tls_error_handle_t h, esp_tls_error_type_t err_type, int *error_code);
618
619 #if CONFIG_ESP_TLS_USING_MBEDTLS
620 /**
621 * @brief Get the pointer to the global CA store currently being used.
622 *
623 * The application must first call esp_tls_set_global_ca_store(). Then the same
624 * CA store could be used by the application for APIs other than esp_tls.
625 *
626 * @note Modifying the pointer might cause a failure in verifying the certificates.
627 *
628 * @return
629 * - Pointer to the global CA store currently being used if successful.
630 * - NULL if there is no global CA store set.
631 */
632 mbedtls_x509_crt *esp_tls_get_global_ca_store(void);
633
634 #endif /* CONFIG_ESP_TLS_USING_MBEDTLS */
635 #ifdef CONFIG_ESP_TLS_SERVER
636 /**
637 * @brief Create TLS/SSL server session
638 *
639 * This function creates a TLS/SSL server context for already accepted client connection
640 * and performs TLS/SSL handshake with the client
641 *
642 * @param[in] cfg Pointer to esp_tls_cfg_server_t
643 * @param[in] sockfd FD of accepted connection
644 * @param[out] tls Pointer to allocated esp_tls_t
645 *
646 * @return
647 * - 0 if successful
648 * - <0 in case of error
649 *
650 */
651 int esp_tls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp_tls_t *tls);
652
653 /**
654 * @brief Close the server side TLS/SSL connection and free any allocated resources.
655 *
656 * This function should be called to close each tls connection opened with esp_tls_server_session_create()
657 *
658 * @param[in] tls pointer to esp_tls_t
659 */
660 void esp_tls_server_session_delete(esp_tls_t *tls);
661 #endif /* ! CONFIG_ESP_TLS_SERVER */
662
663 #ifdef __cplusplus
664 }
665 #endif
666
667 #endif /* ! _ESP_TLS_H_ */
668