Mistake on this page?
Report an issue in GitHub or email us
TLSSocketWrapper.h
Go to the documentation of this file.
1 /** @file TLSSocketWrapper.h TLSSocketWrapper */
2 /*
3  * Copyright (c) 2018 ARM Limited
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 /** @addtogroup netsocket
19 * @{
20 */
21 
22 #ifndef _MBED_HTTPS_TLS_SOCKET_WRAPPER_H_
23 #define _MBED_HTTPS_TLS_SOCKET_WRAPPER_H_
24 
25 #include "netsocket/Socket.h"
26 #include "rtos/EventFlags.h"
27 #include "platform/Callback.h"
28 #include "mbedtls/platform.h"
29 #include "mbedtls/ssl.h"
30 #include "mbedtls/entropy.h"
31 #include "mbedtls/ctr_drbg.h"
32 #include "mbedtls/error.h"
33 
34 // This class requires Mbed TLS SSL/TLS client code
35 #if defined(MBEDTLS_SSL_CLI_C) || defined(DOXYGEN_ONLY)
36 
37 /**
38  * TLSSocket is a wrapper around Socket for interacting with TLS servers.
39  *
40  * TLSSocketWrapper can use any Socket as a transport. After
41  * completing the TLS handshake, it can be used as any Socket would be used.
42  *
43  */
44 class TLSSocketWrapper : public Socket {
45 public:
46  /** Transport modes */
48  TRANSPORT_KEEP, /**< Doesn't call connect() or close() on transport socket */
49  TRANSPORT_CONNECT_AND_CLOSE, /**< Does call connect() and close() on transport socket */
50  TRANSPORT_CONNECT, /**< Does call only connect() on transport socket */
51  TRANSPORT_CLOSE, /**< Does call close() on transport socket */
52  };
53 
54  /** Create a TLSSocketWrapper.
55  *
56  * @param transport Underlying transport socket to wrap.
57  * @param hostname Hostname of the remote host, used for certificate checking.
58  * @param control Transport control mode. See @ref control_transport.
59  */
60  TLSSocketWrapper(Socket *transport, const char *hostname = NULL, control_transport control = TRANSPORT_CONNECT_AND_CLOSE);
61 
62  /** Destroy a socket wrapper.
63  *
64  * Closes socket wrapper if the socket wrapper is still open.
65  */
66  virtual ~TLSSocketWrapper();
67 
68  /** Set hostname.
69  *
70  * TLSSocket requires hostname used to verify the certificate.
71  * If hostname is not given in constructor, this function must be used before
72  * starting the TLS handshake.
73  *
74  * @param hostname Hostname of the remote host, used for certificate checking.
75  */
76  void set_hostname(const char *hostname);
77 
78  /** Sets the certification of Root CA.
79  *
80  * @note Must be called before calling connect()
81  *
82  * @param root_ca Root CA Certificate in any Mbed TLS-supported format.
83  * @param len Length of certificate (including terminating 0 for PEM).
84  * @return 0 on success, negative error code on failure.
85  */
86  nsapi_error_t set_root_ca_cert(const void *root_ca, size_t len);
87 
88  /** Sets the certification of Root CA.
89  *
90  * @note Must be called before calling connect()
91  *
92  * @param root_ca_pem Root CA Certificate in PEM format.
93  */
94  nsapi_error_t set_root_ca_cert(const char *root_ca_pem);
95 
96  /** Sets client certificate, and client private key.
97  *
98  * @param client_cert Client certification in PEM or DER format.
99  * @param client_cert_len Certificate size including the terminating null byte for PEM data.
100  * @param client_private_key_pem Client private key in PEM or DER format.
101  * @param client_private_key_len Key size including the terminating null byte for PEM data
102  * @return 0 on success, negative error code on failure.
103  */
104  nsapi_error_t set_client_cert_key(const void *client_cert, size_t client_cert_len,
105  const void *client_private_key_pem, size_t client_private_key_len);
106 
107  /** Sets client certificate, and client private key.
108  *
109  * @param client_cert_pem Client certification in PEM format.
110  * @param client_private_key_pem Client private key in PEM format.
111  * @return 0 on success, negative error code on failure.
112  */
113  nsapi_error_t set_client_cert_key(const char *client_cert_pem, const char *client_private_key_pem);
114 
115  /** Send data over a TLS socket.
116  *
117  * The socket must be connected to a remote host. Returns the number of
118  * bytes sent from the buffer.
119  *
120  * @param data Buffer of data to send to the host.
121  * @param size Size of the buffer in bytes.
122  * @return Number of sent bytes on success, negative error code on failure.
123  */
124  virtual nsapi_error_t send(const void *data, nsapi_size_t size);
125 
126  /** Receive data over a TLS socket.
127  *
128  * The socket must be connected to a remote host. Returns the number of
129  * bytes received into the buffer.
130  *
131  * @param data Destination buffer for data received from the host.
132  * @param size Size of the buffer in bytes.
133  * @return Number of received bytes on success, negative error
134  * code on failure. If no data is available to be received
135  * and the peer has performed an orderly shutdown,
136  * recv() returns 0.
137  */
138  virtual nsapi_size_or_error_t recv(void *data, nsapi_size_t size);
139 
140  /* = Functions inherited from Socket = */
141  virtual nsapi_error_t close();
142  /*
143  * @note: In case connect() returns an error, the state of the socket is
144  * unspecified. A new socket should be created before reconnecting.
145  */
146  virtual nsapi_error_t connect(const SocketAddress &address = SocketAddress());
147  virtual nsapi_size_or_error_t sendto(const SocketAddress &address, const void *data, nsapi_size_t size);
149  void *data, nsapi_size_t size);
150  virtual nsapi_error_t bind(const SocketAddress &address);
151  virtual void set_blocking(bool blocking);
152  virtual void set_timeout(int timeout);
153  virtual void sigio(mbed::Callback<void()> func);
154  virtual nsapi_error_t setsockopt(int level, int optname, const void *optval, unsigned optlen);
155  virtual nsapi_error_t getsockopt(int level, int optname, void *optval, unsigned *optlen);
156  virtual Socket *accept(nsapi_error_t *error = NULL);
157  virtual nsapi_error_t listen(int backlog = 1);
158  virtual nsapi_error_t getpeername(SocketAddress *address);
159 
160 #if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(DOXYGEN_ONLY)
161  /** Get own certificate directly from Mbed TLS.
162  *
163  * @return Internal Mbed TLS X509 structure.
164  */
165  mbedtls_x509_crt *get_own_cert();
166 
167  /** Set own certificate directly to Mbed TLS.
168  *
169  * @param crt Mbed TLS X509 certificate chain.
170  * @return error code from mbedtls_ssl_conf_own_cert().
171  */
172  int set_own_cert(mbedtls_x509_crt *crt);
173 
174  /** Get CA chain structure.
175  *
176  * @return Mbed TLS X509 certificate chain.
177  */
178  mbedtls_x509_crt *get_ca_chain();
179 
180  /** Set CA chain directly to Mbed TLS.
181  *
182  * @param crt Mbed TLS X509 certificate chain.
183  */
184  void set_ca_chain(mbedtls_x509_crt *crt);
185 #endif
186 
187  /** Get internal Mbed TLS configuration structure.
188  *
189  * @return Mbed TLS SSL config.
190  */
191  mbedtls_ssl_config *get_ssl_config();
192 
193  /** Override Mbed TLS configuration.
194  *
195  * @param conf Mbed TLS SSL configuration structure.
196  */
197  void set_ssl_config(mbedtls_ssl_config *conf);
198 
199  /** Get internal Mbed TLS context structure.
200  *
201  * @return SSL context.
202  */
203  mbedtls_ssl_context *get_ssl_context();
204 
205 protected:
206 #ifndef DOXYGEN_ONLY
207  /** Initiates TLS Handshake.
208  *
209  * Initiates a TLS handshake to a remote peer.
210  * Underlying transport socket should already be connected.
211  *
212  * Root CA certification must be set by set_ssl_ca_pem() before
213  * calling this function.
214  *
215  * For non-blocking purposes, this functions needs to know whether this
216  * was a first call to Socket::connect() API so that NSAPI_ERROR_INPROGRESS
217  * does not happen twice.
218  *
219  * @param first_call is this a first call to Socket::connect() API.
220  * @return 0 on success, negative error code on failure
221  */
222  nsapi_error_t start_handshake(bool first_call);
223 
224  bool is_handshake_started() const;
225 
226  void event();
227 #endif
228 
229 
230 
231 private:
232  /** Continue already initialized handshake */
233  nsapi_error_t continue_handshake();
234  /**
235  * Helper for pretty-printing Mbed TLS error codes
236  */
237  static void print_mbedtls_error(const char *name, int err);
238 
239 #if MBED_CONF_TLS_SOCKET_DEBUG_LEVEL > 0
240  /**
241  * Debug callback for Mbed TLS
242  * Just prints on the USB serial port
243  */
244  static void my_debug(void *ctx, int level, const char *file, int line,
245  const char *str);
246 
247  /**
248  * Certificate verification callback for Mbed TLS
249  * Here we only use it to display information on each cert in the chain
250  */
251  static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags);
252 
253 #endif /* MBED_CONF_TLS_SOCKET_DEBUG_LEVEL > 0 */
254 
255  /**
256  * Receive callback for Mbed TLS
257  */
258  static int ssl_recv(void *ctx, unsigned char *buf, size_t len);
259 
260  /**
261  * Send callback for Mbed TLS
262  */
263  static int ssl_send(void *ctx, const unsigned char *buf, size_t len);
264 
265  mbedtls_ssl_context _ssl;
266 #ifdef MBEDTLS_X509_CRT_PARSE_C
267  mbedtls_pk_context _pkctx;
268 #endif
269  mbedtls_ctr_drbg_context _ctr_drbg;
270  mbedtls_entropy_context _entropy;
271 
272  rtos::EventFlags _event_flag;
273  mbed::Callback<void()> _sigio;
274  Socket *_transport;
275  int _timeout;
276 
277 #ifdef MBEDTLS_X509_CRT_PARSE_C
278  mbedtls_x509_crt *_cacert;
279  mbedtls_x509_crt *_clicert;
280 #endif
281  mbedtls_ssl_config *_ssl_conf;
282 
283  bool _connect_transport: 1;
284  bool _close_transport: 1;
285  bool _tls_initialized: 1;
286  bool _handshake_completed: 1;
287  bool _cacert_allocated: 1;
288  bool _clicert_allocated: 1;
289  bool _ssl_conf_allocated: 1;
290 
291 };
292 
293 #endif /* MBEDTLS_SSL_CLI_C */
294 #endif // _MBED_HTTPS_TLS_SOCKET_WRAPPER_H_
295 /** @} */
MBED_NORETURN void error(const char *format,...) MBED_PRINTF(1
To generate a fatal compile-time error, you can use the pre-processor error directive.
The EventFlags class is used to control event flags or wait for event flags other threads control...
Definition: EventFlags.h:51
virtual nsapi_size_or_error_t sendto(const SocketAddress &address, const void *data, nsapi_size_t size)
Send a message on a socket.
virtual void sigio(mbed::Callback< void()> func)
Register a callback on state change of the socket.
TLSSocket is a wrapper around Socket for interacting with TLS servers.
virtual nsapi_error_t listen(int backlog=1)
Listen for incoming connections.
virtual ~TLSSocketWrapper()
Destroy a socket wrapper.
signed int nsapi_error_t
Type used to represent error codes.
Definition: nsapi_types.h:95
virtual nsapi_error_t connect(const SocketAddress &address=SocketAddress())
Connects socket to a remote address.
virtual Socket * accept(nsapi_error_t *error=NULL)
Accepts a connection on a socket.
virtual nsapi_error_t getpeername(SocketAddress *address)
Get the remote-end peer associated with this socket.
mbedtls_ssl_config * get_ssl_config()
Get internal Mbed TLS configuration structure.
signed int nsapi_size_or_error_t
Type used to represent either a size or error passed through sockets.
Definition: nsapi_types.h:106
Abstract Socket interface.
Does call only connect() on transport socket.
virtual nsapi_size_or_error_t recv(void *data, nsapi_size_t size)
Receive data over a TLS socket.
virtual nsapi_error_t setsockopt(int level, int optname, const void *optval, unsigned optlen)
Set socket options.
virtual nsapi_error_t close()
Closes the socket.
Does call close() on transport socket.
mbedtls_x509_crt * get_ca_chain()
Get CA chain structure.
int set_own_cert(mbedtls_x509_crt *crt)
Set own certificate directly to Mbed TLS.
nsapi_error_t set_root_ca_cert(const void *root_ca, size_t len)
Sets the certification of Root CA.
virtual nsapi_error_t send(const void *data, nsapi_size_t size)
Send data over a TLS socket.
nsapi_error_t set_client_cert_key(const void *client_cert, size_t client_cert_len, const void *client_private_key_pem, size_t client_private_key_len)
Sets client certificate, and client private key.
SocketAddress class.
Definition: SocketAddress.h:35
void set_ca_chain(mbedtls_x509_crt *crt)
Set CA chain directly to Mbed TLS.
void set_hostname(const char *hostname)
Set hostname.
mbedtls_x509_crt * get_own_cert()
Get own certificate directly from Mbed TLS.
Socket interface.
Definition: Socket.h:39
Doesn&#39;t call connect() or close() on transport socket.
void set_ssl_config(mbedtls_ssl_config *conf)
Override Mbed TLS configuration.
Does call connect() and close() on transport socket.
virtual nsapi_size_or_error_t recvfrom(SocketAddress *address, void *data, nsapi_size_t size)
Receive a data from a socket.
unsigned int nsapi_size_t
Type used to represent the size of data passed through sockets.
Definition: nsapi_types.h:99
control_transport
Transport modes.
virtual void set_timeout(int timeout)
Set timeout on blocking socket operations.
virtual nsapi_error_t getsockopt(int level, int optname, void *optval, unsigned *optlen)
Get socket options.
virtual nsapi_error_t bind(const SocketAddress &address)
Bind a specific address to a socket.
TLSSocketWrapper(Socket *transport, const char *hostname=NULL, control_transport control=TRANSPORT_CONNECT_AND_CLOSE)
Create a TLSSocketWrapper.
Callback class based on template specialization.
Definition: Callback.h:39
mbedtls_ssl_context * get_ssl_context()
Get internal Mbed TLS context structure.
virtual void set_blocking(bool blocking)
Set blocking or non-blocking mode of the socket.
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.