1 /*
2  * FreeRTOS V202212.00
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9  * the Software, and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * https://www.FreeRTOS.org
23  * https://github.com/FreeRTOS
24  *
25  */
26 
27 /**
28  * @file transport_mbedtls_pkcs11.h
29  * @brief TLS transport interface header.
30  * @note This file is derived from the tls_freertos.h header file found in the mqtt
31  * section of IoT Libraries source code. The file has been modified to support using
32  * PKCS #11 when using TLS.
33  */
34 
35 #ifndef TRANSPORT_MBEDTLS_PKCS11
36 #define TRANSPORT_MBEDTLS_PKCS11
37 
38 #define MBEDTLS_ALLOW_PRIVATE_ACCESS
39 
40 #if !defined( MBEDTLS_CONFIG_FILE )
41     #include "mbedtls/mbedtls_config.h"
42 #else
43     #include MBEDTLS_CONFIG_FILE
44 #endif
45 
46 #include "mbedtls/private_access.h"
47 
48 /* TCP Sockets Wrapper include.*/
49 #include "tcp_sockets_wrapper.h"
50 
51 /* Transport interface include. */
52 #include "transport_interface.h"
53 
54 /* mbed TLS includes. */
55 #include "mbedtls/build_info.h"
56 #include "mbedtls/ctr_drbg.h"
57 #include "mbedtls/entropy.h"
58 #include "mbedtls/ssl.h"
59 #include "mbedtls/threading.h"
60 #include "mbedtls/x509.h"
61 #include "mbedtls/pk.h"
62 #include "mbedtls/error.h"
63 
64 #include "pk_wrap.h"
65 
66 /* PKCS #11 includes. */
67 #include "core_pkcs11.h"
68 
69 /**
70  * @brief Secured connection context.
71  */
72 typedef struct SSLContext
73 {
74     mbedtls_ssl_config config;            /**< @brief SSL connection configuration. */
75     mbedtls_ssl_context context;          /**< @brief SSL connection context */
76     mbedtls_x509_crt_profile certProfile; /**< @brief Certificate security profile for this connection. */
77     mbedtls_x509_crt rootCa;              /**< @brief Root CA certificate context. */
78     mbedtls_x509_crt clientCert;          /**< @brief Client certificate context. */
79     mbedtls_pk_context privKey;           /**< @brief Client private key context. */
80     mbedtls_pk_info_t privKeyInfo;        /**< @brief Client private key info. */
81 
82     /* PKCS#11. */
83     CK_FUNCTION_LIST_PTR pxP11FunctionList;
84     CK_SESSION_HANDLE xP11Session;
85     CK_OBJECT_HANDLE xP11PrivateKey;
86 } SSLContext_t;
87 
88 /**
89  * @brief Definition of the network context for the transport interface
90  * implementation that uses mbedTLS and FreeRTOS+TLS sockets.
91  */
92 typedef struct TlsTransportParams
93 {
94     Socket_t tcpSocket;
95     SSLContext_t sslContext;
96 } TlsTransportParams_t;
97 
98 /**
99  * @brief Contains the credentials necessary for tls connection setup.
100  */
101 typedef struct NetworkCredentials
102 {
103     /**
104      * @brief To use ALPN, set this to a NULL-terminated list of supported
105      * protocols in decreasing order of preference.
106      *
107      * See [this link]
108      * (https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/)
109      * for more information.
110      */
111     const char ** pAlpnProtos;
112 
113     /**
114      * @brief Disable server name indication (SNI) for a TLS session.
115      */
116     BaseType_t disableSni;
117 
118     const unsigned char * pRootCa;   /**< @brief String representing a trusted server root certificate. */
119     size_t rootCaSize;               /**< @brief Size associated with #NetworkCredentials.pRootCa. */
120     const unsigned char * pUserName; /**< @brief username for MQTT. */
121     size_t userNameSize;             /**< @brief Size associated with #NetworkCredentials.pUserName. */
122     const unsigned char * pPassword; /**< @brief String representing the password for MQTT. */
123     size_t passwordSize;             /**< @brief Size associated with #NetworkCredentials.pPassword. */
124     const char * pClientCertLabel;   /**< @brief PKCS #11 label string of the client certificate. */
125     const char * pPrivateKeyLabel;   /**< @brief PKCS #11 label for the private key. */
126 } NetworkCredentials_t;
127 
128 /**
129  * @brief TLS Connect / Disconnect return status.
130  */
131 typedef enum TlsTransportStatus
132 {
133     TLS_TRANSPORT_SUCCESS = 0,         /**< Function successfully completed. */
134     TLS_TRANSPORT_INVALID_PARAMETER,   /**< At least one parameter was invalid. */
135     TLS_TRANSPORT_INSUFFICIENT_MEMORY, /**< Insufficient memory required to establish connection. */
136     TLS_TRANSPORT_INVALID_CREDENTIALS, /**< Provided credentials were invalid. */
137     TLS_TRANSPORT_HANDSHAKE_FAILED,    /**< Performing TLS handshake with server failed. */
138     TLS_TRANSPORT_INTERNAL_ERROR,      /**< A call to a system API resulted in an internal error. */
139     TLS_TRANSPORT_CONNECT_FAILURE      /**< Initial connection to the server failed. */
140 } TlsTransportStatus_t;
141 
142 /**
143  * @brief Create a TLS connection with FreeRTOS sockets.
144  *
145  * @param[out] pNetworkContext Pointer to a network context to contain the
146  * initialized socket handle.
147  * @param[in] pHostName The hostname of the remote endpoint.
148  * @param[in] port The destination port.
149  * @param[in] pNetworkCredentials Credentials for the TLS connection.
150  * @param[in] receiveTimeoutMs Receive socket timeout.
151  * @param[in] sendTimeoutMs Send socket timeout.
152  *
153  * @return #TLS_TRANSPORT_SUCCESS, #TLS_TRANSPORT_INSUFFICIENT_MEMORY, #TLS_TRANSPORT_INVALID_CREDENTIALS,
154  * #TLS_TRANSPORT_HANDSHAKE_FAILED, #TLS_TRANSPORT_INTERNAL_ERROR, or #TLS_TRANSPORT_CONNECT_FAILURE.
155  */
156 TlsTransportStatus_t TLS_FreeRTOS_Connect( NetworkContext_t * pNetworkContext,
157                                            const char * pHostName,
158                                            uint16_t port,
159                                            const NetworkCredentials_t * pNetworkCredentials,
160                                            uint32_t receiveTimeoutMs,
161                                            uint32_t sendTimeoutMs );
162 
163 /**
164  * @brief Gracefully disconnect an established TLS connection.
165  *
166  * @param[in] pNetworkContext Network context.
167  */
168 void TLS_FreeRTOS_Disconnect( NetworkContext_t * pNetworkContext );
169 
170 /**
171  * @brief Receives data from an established TLS connection.
172  *
173  * This is the TLS version of the transport interface's
174  * #TransportRecv_t function.
175  *
176  * @param[in] pNetworkContext The Network context.
177  * @param[out] pBuffer Buffer to receive bytes into.
178  * @param[in] bytesToRecv Number of bytes to receive from the network.
179  *
180  * @return Number of bytes (> 0) received if successful;
181  * 0 if the socket times out without reading any bytes;
182  * negative value on error.
183  */
184 int32_t TLS_FreeRTOS_recv( NetworkContext_t * pNetworkContext,
185                            void * pBuffer,
186                            size_t bytesToRecv );
187 
188 /**
189  * @brief Sends data over an established TLS connection.
190  *
191  * @note This is the TLS version of the transport interface's
192  * #TransportSend_t function.
193  *
194  * @param[in] pNetworkContext The network context.
195  * @param[in] pBuffer Buffer containing the bytes to send.
196  * @param[in] bytesToSend Number of bytes to send from the buffer.
197  *
198  * @return Number of bytes (> 0) sent on success;
199  * 0 if the socket times out without sending any bytes;
200  * else a negative value to represent error.
201  */
202 int32_t TLS_FreeRTOS_send( NetworkContext_t * pNetworkContext,
203                            const void * pBuffer,
204                            size_t bytesToSend );
205 
206 
207 #ifdef MBEDTLS_DEBUG_C
208 
209 /**
210  * @brief Write an MBedTLS Debug message to the LogDebug() function
211  *
212  * @param[in] sslContext Pointer of the SSL Context that is being used
213  * @param[in] level The severity level of the debug message from MBedTLS
214  * @param[in] file Name of the file that the debug message is from
215  * @param[in] line The line number that the debug message is from
216  * @param[in] str The full string debug message from MBedTLS
217  *
218  * @return void
219  */
220     void mbedtls_string_printf( void * sslContext,
221                                 int level,
222                                 const char * file,
223                                 int line,
224                                 const char * str );
225 #endif /* MBEDTLS_DEBUG_C */
226 
227 #endif /* ifndef TRANSPORT_MBEDTLS_PKCS11 */
228