Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
TLSSocketWrapper.h
00001 /** @file TLSSocketWrapper.h TLSSocketWrapper */ 00002 /* 00003 * Copyright (c) 2018 ARM Limited 00004 * SPDX-License-Identifier: Apache-2.0 00005 * 00006 * Licensed under the Apache License, Version 2.0 (the "License"); 00007 * you may not use this file except in compliance with the License. 00008 * You may obtain a copy of the License at 00009 * 00010 * http://www.apache.org/licenses/LICENSE-2.0 00011 * 00012 * Unless required by applicable law or agreed to in writing, software 00013 * distributed under the License is distributed on an "AS IS" BASIS, 00014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 * See the License for the specific language governing permissions and 00016 * limitations under the License. 00017 */ 00018 /** @addtogroup netsocket 00019 * @{ 00020 */ 00021 00022 #ifndef _MBED_HTTPS_TLS_SOCKET_WRAPPER_H_ 00023 #define _MBED_HTTPS_TLS_SOCKET_WRAPPER_H_ 00024 00025 #include "netsocket/Socket.h" 00026 #include "rtos/EventFlags.h" 00027 #include "platform/Callback.h" 00028 #include "mbedtls/platform.h" 00029 #include "mbedtls/ssl.h" 00030 #include "mbedtls/entropy.h" 00031 #include "mbedtls/ctr_drbg.h" 00032 #include "mbedtls/error.h" 00033 00034 // This class requires Mbed TLS SSL/TLS client code 00035 #if defined(MBEDTLS_SSL_CLI_C) || defined(DOXYGEN_ONLY) 00036 00037 /** 00038 * TLSSocket is a wrapper around Socket for interacting with TLS servers. 00039 * 00040 * TLSSocketWrapper can use any Socket as a transport. After 00041 * completing the TLS handshake, it can be used as any Socket would be used. 00042 * 00043 */ 00044 class TLSSocketWrapper : public Socket { 00045 public: 00046 /** Transport modes */ 00047 enum control_transport { 00048 TRANSPORT_KEEP, /**< Doesn't call connect() or close() on transport socket */ 00049 TRANSPORT_CONNECT_AND_CLOSE, /**< Does call connect() and close() on transport socket */ 00050 TRANSPORT_CONNECT, /**< Does call only connect() on transport socket */ 00051 TRANSPORT_CLOSE, /**< Does call close() on transport socket */ 00052 }; 00053 00054 /** Create a TLSSocketWrapper. 00055 * 00056 * @param transport Underlying transport socket to wrap. 00057 * @param hostname Hostname of the remote host, used for certificate checking. 00058 * @param control Transport control mode. See @ref control_transport. 00059 */ 00060 TLSSocketWrapper(Socket *transport, const char *hostname = NULL, control_transport control = TRANSPORT_CONNECT_AND_CLOSE); 00061 00062 /** Destroy a socket wrapper. 00063 * 00064 * Closes socket wrapper if the socket wrapper is still open. 00065 */ 00066 virtual ~TLSSocketWrapper(); 00067 00068 /** Set hostname. 00069 * 00070 * TLSSocket requires hostname used to verify the certificate. 00071 * If hostname is not given in constructor, this function must be used before 00072 * starting the TLS handshake. 00073 * 00074 * @param hostname Hostname of the remote host, used for certificate checking. 00075 */ 00076 void set_hostname(const char *hostname); 00077 00078 /** Sets the certification of Root CA. 00079 * 00080 * @note Must be called before calling connect() 00081 * 00082 * @param root_ca Root CA Certificate in any Mbed TLS-supported format. 00083 * @param len Length of certificate (including terminating 0 for PEM). 00084 * @retval NSAPI_ERROR_OK on success. 00085 * @retval NSAPI_ERROR_NO_MEMORY in case there is not enough memory to allocate certificate. 00086 * @retval NSAPI_ERROR_PARAMETER in case the provided root_ca parameter failed parsing. 00087 */ 00088 nsapi_error_t set_root_ca_cert(const void *root_ca, size_t len); 00089 00090 /** Sets the certification of Root CA. 00091 * 00092 * @note Must be called before calling connect() 00093 * 00094 * @param root_ca_pem Root CA Certificate in PEM format. 00095 * @retval NSAPI_ERROR_OK on success. 00096 * @retval NSAPI_ERROR_NO_MEMORY in case there is not enough memory to allocate certificate. 00097 * @retval NSAPI_ERROR_PARAMETER in case the provided root_ca parameter failed parsing. 00098 */ 00099 nsapi_error_t set_root_ca_cert(const char *root_ca_pem); 00100 00101 /** Sets client certificate, and client private key. 00102 * 00103 * @param client_cert Client certification in PEM or DER format. 00104 * @param client_cert_len Certificate size including the terminating null byte for PEM data. 00105 * @param client_private_key_pem Client private key in PEM or DER format. 00106 * @param client_private_key_len Key size including the terminating null byte for PEM data 00107 * @retval NSAPI_ERROR_OK on success. 00108 * @retval NSAPI_ERROR_PARAMETER in case the provided root_ca parameter failed parsing. 00109 */ 00110 nsapi_error_t set_client_cert_key(const void *client_cert, size_t client_cert_len, 00111 const void *client_private_key_pem, size_t client_private_key_len); 00112 00113 /** Sets client certificate, and client private key. 00114 * 00115 * @param client_cert_pem Client certification in PEM format. 00116 * @param client_private_key_pem Client private key in PEM format. 00117 * @retval NSAPI_ERROR_OK on success. 00118 * @retval NSAPI_ERROR_PARAMETER in case the provided root_ca parameter failed parsing. 00119 */ 00120 nsapi_error_t set_client_cert_key(const char *client_cert_pem, const char *client_private_key_pem); 00121 00122 /** Send data over a TLS socket. 00123 * 00124 * The socket must be connected to a remote host. Returns the number of 00125 * bytes sent from the buffer. 00126 * 00127 * @param data Buffer of data to send to the host. 00128 * @param size Size of the buffer in bytes. 00129 * @retval int Number of sent bytes on success 00130 * @retval NSAPI_ERROR_NO_SOCKET in case socket was not created correctly. 00131 * @retval NSAPI_ERROR_WOULD_BLOCK in case non-blocking mode is enabled 00132 * and send cannot be performed immediately. 00133 * @retval NSAPI_ERROR_DEVICE_ERROR in case of tls-related errors. 00134 * See @ref mbedtls_ssl_write. 00135 */ 00136 virtual nsapi_error_t send(const void *data, nsapi_size_t size); 00137 00138 /** Receive data over a TLS socket. 00139 * 00140 * The socket must be connected to a remote host. Returns the number of 00141 * bytes received into the buffer. 00142 * 00143 * @param data Destination buffer for data received from the host. 00144 * @param size Size of the buffer in bytes. 00145 * @retval int Number of sent bytes on success 00146 * @retval NSAPI_ERROR_NO_SOCKET in case socket was not created correctly. 00147 * @retval NSAPI_ERROR_WOULD_BLOCK in case non-blocking mode is enabled 00148 * and send cannot be performed immediately. 00149 * @retval NSAPI_ERROR_DEVICE_ERROR in case of tls-related errors. 00150 * See @ref mbedtls_ssl_read. 00151 * @return 0 if no data is available to be received 00152 * and the peer has performed an orderly shutdown. 00153 */ 00154 virtual nsapi_size_or_error_t recv(void *data, nsapi_size_t size); 00155 00156 /* = Functions inherited from Socket = */ 00157 virtual nsapi_error_t close(); 00158 /** 00159 * Connect the transport socket and start handshake. 00160 * 00161 * @note: In case connect() returns an error, the state of the socket is 00162 * unspecified. A new socket should be created before reconnecting. 00163 * 00164 * See @ref Socket::connect and @ref start_handshake 00165 */ 00166 virtual nsapi_error_t connect(const SocketAddress &address = SocketAddress()); 00167 virtual nsapi_size_or_error_t sendto(const SocketAddress &address, const void *data, nsapi_size_t size); 00168 virtual nsapi_size_or_error_t recvfrom(SocketAddress *address, 00169 void *data, nsapi_size_t size); 00170 virtual nsapi_error_t bind(const SocketAddress &address); 00171 virtual void set_blocking(bool blocking); 00172 virtual void set_timeout(int timeout); 00173 virtual void sigio(mbed::Callback<void()> func); 00174 virtual nsapi_error_t setsockopt(int level, int optname, const void *optval, unsigned optlen); 00175 virtual nsapi_error_t getsockopt(int level, int optname, void *optval, unsigned *optlen); 00176 virtual Socket *accept(nsapi_error_t *error = NULL); 00177 virtual nsapi_error_t listen(int backlog = 1); 00178 virtual nsapi_error_t getpeername(SocketAddress *address); 00179 00180 #if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(DOXYGEN_ONLY) 00181 /** Get own certificate directly from Mbed TLS. 00182 * 00183 * @return Internal Mbed TLS X509 structure. 00184 */ 00185 mbedtls_x509_crt *get_own_cert(); 00186 00187 /** Set own certificate directly to Mbed TLS. 00188 * 00189 * @param crt Mbed TLS X509 certificate chain. 00190 * @return error code from mbedtls_ssl_conf_own_cert(). 00191 */ 00192 int set_own_cert(mbedtls_x509_crt *crt); 00193 00194 /** Get CA chain structure. 00195 * 00196 * @return Mbed TLS X509 certificate chain. 00197 */ 00198 mbedtls_x509_crt *get_ca_chain(); 00199 00200 /** Set CA chain directly to Mbed TLS. 00201 * 00202 * @param crt Mbed TLS X509 certificate chain. 00203 */ 00204 void set_ca_chain(mbedtls_x509_crt *crt); 00205 #endif 00206 00207 /** Get internal Mbed TLS configuration structure. 00208 * 00209 * @return Mbed TLS SSL config. 00210 */ 00211 mbedtls_ssl_config *get_ssl_config(); 00212 00213 /** Override Mbed TLS configuration. 00214 * 00215 * @param conf Mbed TLS SSL configuration structure. 00216 */ 00217 void set_ssl_config(mbedtls_ssl_config *conf); 00218 00219 /** Get internal Mbed TLS context structure. 00220 * 00221 * @return SSL context. 00222 */ 00223 mbedtls_ssl_context *get_ssl_context(); 00224 00225 protected: 00226 #ifndef DOXYGEN_ONLY 00227 /** Initiates TLS Handshake. 00228 * 00229 * Initiates a TLS handshake to a remote peer. 00230 * Underlying transport socket should already be connected. 00231 * 00232 * Root CA certification must be set by set_ssl_ca_pem() before 00233 * calling this function. 00234 * 00235 * For non-blocking purposes, this functions needs to know whether this 00236 * was a first call to Socket::connect() API so that NSAPI_ERROR_INPROGRESS 00237 * does not happen twice. 00238 * 00239 * @param first_call is this a first call to Socket::connect() API. 00240 * @retval NSAPI_ERROR_OK if we happen to complete the request on the first call. 00241 * @retval NSAPI_ERROR_IN_PROGRESS if the first call did not complete the request. 00242 * @retval NSAPI_ERROR_NO_SOCKET in case the transport socket was not created correctly. 00243 * @retval NSAPI_ERROR_AUTH_FAILURE in case of tls-related authentication errors. 00244 * See @ref mbedtls_ctr_drbg_seed, @ref mbedtls_ssl_setup. @ref mbedtls_ssl_handshake. 00245 */ 00246 nsapi_error_t start_handshake(bool first_call); 00247 00248 bool is_handshake_started() const; 00249 00250 void event(); 00251 #endif 00252 00253 00254 00255 private: 00256 /** Continue already initialized handshake */ 00257 nsapi_error_t continue_handshake(); 00258 /** 00259 * Helper for pretty-printing Mbed TLS error codes 00260 */ 00261 static void print_mbedtls_error(const char *name, int err); 00262 00263 #if MBED_CONF_TLS_SOCKET_DEBUG_LEVEL > 0 00264 /** 00265 * Debug callback for Mbed TLS 00266 * Just prints on the USB serial port 00267 */ 00268 static void my_debug(void *ctx, int level, const char *file, int line, 00269 const char *str); 00270 00271 /** 00272 * Certificate verification callback for Mbed TLS 00273 * Here we only use it to display information on each cert in the chain 00274 */ 00275 static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags); 00276 00277 #endif /* MBED_CONF_TLS_SOCKET_DEBUG_LEVEL > 0 */ 00278 00279 /** 00280 * Receive callback for Mbed TLS 00281 */ 00282 static int ssl_recv(void *ctx, unsigned char *buf, size_t len); 00283 00284 /** 00285 * Send callback for Mbed TLS 00286 */ 00287 static int ssl_send(void *ctx, const unsigned char *buf, size_t len); 00288 00289 mbedtls_ssl_context _ssl; 00290 #ifdef MBEDTLS_X509_CRT_PARSE_C 00291 mbedtls_pk_context _pkctx; 00292 #endif 00293 mbedtls_ctr_drbg_context _ctr_drbg; 00294 mbedtls_entropy_context _entropy; 00295 00296 rtos::EventFlags _event_flag; 00297 mbed::Callback<void()> _sigio; 00298 Socket *_transport; 00299 int _timeout; 00300 00301 #ifdef MBEDTLS_X509_CRT_PARSE_C 00302 mbedtls_x509_crt *_cacert; 00303 mbedtls_x509_crt *_clicert; 00304 #endif 00305 mbedtls_ssl_config *_ssl_conf; 00306 00307 bool _connect_transport: 1; 00308 bool _close_transport: 1; 00309 bool _tls_initialized: 1; 00310 bool _handshake_completed: 1; 00311 bool _cacert_allocated: 1; 00312 bool _clicert_allocated: 1; 00313 bool _ssl_conf_allocated: 1; 00314 00315 }; 00316 00317 #endif /* MBEDTLS_SSL_CLI_C */ 00318 #endif // _MBED_HTTPS_TLS_SOCKET_WRAPPER_H_ 00319 /** @} */
Generated on Tue Jul 12 2022 13:55:00 by
