1 /*
2  *  Copyright (c) 2018, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  * @brief
32  *  This file defines the top-level functions for the OpenThread CoAP Secure implementation.
33  *
34  *  @note
35  *   The functions in this module require the build-time feature `OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE=1`.
36  *
37  *  @note
38  *   To enable cipher suite DTLS_PSK_WITH_AES_128_CCM_8, MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
39  *    must be enabled in mbedtls-config.h
40  *   To enable cipher suite DTLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
41  *    MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED must be enabled in mbedtls-config.h.
42  */
43 
44 #ifndef OPENTHREAD_COAP_SECURE_H_
45 #define OPENTHREAD_COAP_SECURE_H_
46 
47 #include <stdint.h>
48 
49 #include <openthread/coap.h>
50 
51 #ifdef __cplusplus
52 extern "C" {
53 #endif
54 
55 /**
56  * @addtogroup api-coap-secure
57  *
58  * @brief
59  *   This module includes functions that control CoAP Secure (CoAP over DTLS) communication.
60  *
61  *   The functions in this module are available when CoAP Secure API feature
62  *   (`OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE`) is enabled.
63  *
64  * @{
65  *
66  */
67 
68 #define OT_DEFAULT_COAP_SECURE_PORT 5684 ///< Default CoAP Secure port, as specified in RFC 7252
69 
70 /**
71  * CoAP secure connection event types.
72  *
73  */
74 typedef enum otCoapSecureConnectEvent
75 {
76     OT_COAP_SECURE_CONNECTED = 0,             ///< Connection established
77     OT_COAP_SECURE_DISCONNECTED_PEER_CLOSED,  ///< Disconnected by peer
78     OT_COAP_SECURE_DISCONNECTED_LOCAL_CLOSED, ///< Disconnected locally
79     OT_COAP_SECURE_DISCONNECTED_MAX_ATTEMPTS, ///< Disconnected due to reaching the max connection attempts
80     OT_COAP_SECURE_DISCONNECTED_ERROR,        ///< Disconnected due to an error
81 } otCoapSecureConnectEvent;
82 
83 /**
84  * Pointer is called when the DTLS connection state changes.
85  *
86  * @param[in]  aEvent      The connection event.
87  * @param[in]  aContext    A pointer to arbitrary context information.
88  *
89  */
90 typedef void (*otHandleCoapSecureClientConnect)(otCoapSecureConnectEvent aEvent, void *aContext);
91 
92 /**
93  * Callback function pointer to notify when the CoAP secure agent is automatically stopped due to reaching the maximum
94  * number of connection attempts.
95  *
96  * @param[in] aContext    A pointer to arbitrary context information.
97  *
98  */
99 typedef void (*otCoapSecureAutoStopCallback)(void *aContext);
100 
101 /**
102  * Starts the CoAP Secure service.
103  *
104  * @param[in]  aInstance  A pointer to an OpenThread instance.
105  * @param[in]  aPort      The local UDP port to bind to.
106  *
107  * @retval OT_ERROR_NONE  Successfully started the CoAP Secure server.
108  *
109  */
110 otError otCoapSecureStart(otInstance *aInstance, uint16_t aPort);
111 
112 /**
113  * Starts the CoAP secure service and sets the maximum number of allowed connection attempts before stopping the
114  * agent automatically.
115  *
116  * @param[in] aInstance       A pointer to an OpenThread instance.
117  * @param[in] aPort           The local UDP port to bind to.
118  * @param[in] aMaxAttempts    Maximum number of allowed connection request attempts. Zero indicates no limit.
119  * @param[in] aCallback       Callback to notify if max number of attempts has reached and agent is stopped.
120  * @param[in] aContext        A pointer to arbitrary context to use with @p aCallback.
121  *
122  * @retval OT_ERROR_NONE        Successfully started the CoAP agent.
123  * @retval OT_ERROR_ALREADY     Already started.
124  *
125  */
126 otError otCoapSecureStartWithMaxConnAttempts(otInstance                  *aInstance,
127                                              uint16_t                     aPort,
128                                              uint16_t                     aMaxAttempts,
129                                              otCoapSecureAutoStopCallback aCallback,
130                                              void                        *aContext);
131 
132 /**
133  * Stops the CoAP Secure server.
134  *
135  * @param[in]  aInstance  A pointer to an OpenThread instance.
136  *
137  */
138 void otCoapSecureStop(otInstance *aInstance);
139 
140 /**
141  * Sets the Pre-Shared Key (PSK) and cipher suite
142  * DTLS_PSK_WITH_AES_128_CCM_8.
143  *
144  * @note This function requires the build-time feature `MBEDTLS_KEY_EXCHANGE_PSK_ENABLED` to be enabled.
145  *
146  * @param[in]  aInstance     A pointer to an OpenThread instance.
147  * @param[in]  aPsk          A pointer to the PSK.
148  * @param[in]  aPskLength    The PSK length.
149  * @param[in]  aPskIdentity  The Identity Name for the PSK.
150  * @param[in]  aPskIdLength  The PSK Identity Length.
151  *
152  */
153 void otCoapSecureSetPsk(otInstance    *aInstance,
154                         const uint8_t *aPsk,
155                         uint16_t       aPskLength,
156                         const uint8_t *aPskIdentity,
157                         uint16_t       aPskIdLength);
158 
159 /**
160  * Returns the peer x509 certificate base64 encoded.
161  *
162  * @note This function requires the build-time features `MBEDTLS_BASE64_C` and
163  *       `MBEDTLS_SSL_KEEP_PEER_CERTIFICATE` to be enabled.
164  *
165  * @param[in]   aInstance        A pointer to an OpenThread instance.
166  * @param[out]  aPeerCert        A pointer to the base64 encoded certificate buffer.
167  * @param[out]  aCertLength      The length of the base64 encoded peer certificate.
168  * @param[in]   aCertBufferSize  The buffer size of aPeerCert.
169  *
170  * @retval OT_ERROR_INVALID_STATE   Not connected yet.
171  * @retval OT_ERROR_NONE            Successfully get the peer certificate.
172  * @retval OT_ERROR_NO_BUFS         Can't allocate memory for certificate.
173  *
174  */
175 otError otCoapSecureGetPeerCertificateBase64(otInstance    *aInstance,
176                                              unsigned char *aPeerCert,
177                                              size_t        *aCertLength,
178                                              size_t         aCertBufferSize);
179 
180 /**
181  * Sets the authentication mode for the coap secure connection.
182  *
183  * Disable or enable the verification of peer certificate.
184  * Must be called before start.
185  *
186  * @param[in]   aInstance               A pointer to an OpenThread instance.
187  * @param[in]   aVerifyPeerCertificate  true, to verify the peer certificate.
188  *
189  */
190 void otCoapSecureSetSslAuthMode(otInstance *aInstance, bool aVerifyPeerCertificate);
191 
192 /**
193  * Sets the local device's X509 certificate with corresponding private key for
194  * DTLS session with DTLS_ECDHE_ECDSA_WITH_AES_128_CCM_8.
195  *
196  * @note This function requires `MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=1`.
197  *
198  * @param[in]  aInstance          A pointer to an OpenThread instance.
199  * @param[in]  aX509Cert          A pointer to the PEM formatted X509 certificate.
200  * @param[in]  aX509Length        The length of certificate.
201  * @param[in]  aPrivateKey        A pointer to the PEM formatted private key.
202  * @param[in]  aPrivateKeyLength  The length of the private key.
203  *
204  */
205 void otCoapSecureSetCertificate(otInstance    *aInstance,
206                                 const uint8_t *aX509Cert,
207                                 uint32_t       aX509Length,
208                                 const uint8_t *aPrivateKey,
209                                 uint32_t       aPrivateKeyLength);
210 
211 /**
212  * Sets the trusted top level CAs. It is needed for validating the
213  * certificate of the peer.
214  *
215  * DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS.
216  *
217  * @note This function requires `MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=1`.
218  *
219  * @param[in]  aInstance                A pointer to an OpenThread instance.
220  * @param[in]  aX509CaCertificateChain  A pointer to the PEM formatted X509 CA chain.
221  * @param[in]  aX509CaCertChainLength   The length of chain.
222  *
223  */
224 void otCoapSecureSetCaCertificateChain(otInstance    *aInstance,
225                                        const uint8_t *aX509CaCertificateChain,
226                                        uint32_t       aX509CaCertChainLength);
227 
228 /**
229  * Initializes DTLS session with a peer.
230  *
231  * @param[in]  aInstance               A pointer to an OpenThread instance.
232  * @param[in]  aSockAddr               A pointer to the remote socket address.
233  * @param[in]  aHandler                A pointer to a function that will be called when the DTLS connection
234  *                                     state changes.
235  * @param[in]  aContext                A pointer to arbitrary context information.
236  *
237  * @retval OT_ERROR_NONE  Successfully started DTLS connection.
238  *
239  */
240 otError otCoapSecureConnect(otInstance                     *aInstance,
241                             const otSockAddr               *aSockAddr,
242                             otHandleCoapSecureClientConnect aHandler,
243                             void                           *aContext);
244 
245 /**
246  * Stops the DTLS connection.
247  *
248  * @param[in]  aInstance  A pointer to an OpenThread instance.
249  *
250  */
251 void otCoapSecureDisconnect(otInstance *aInstance);
252 
253 /**
254  * Indicates whether or not the DTLS session is connected.
255  *
256  * @param[in]  aInstance  A pointer to an OpenThread instance.
257  *
258  * @retval TRUE   The DTLS session is connected.
259  * @retval FALSE  The DTLS session is not connected.
260  *
261  */
262 bool otCoapSecureIsConnected(otInstance *aInstance);
263 
264 /**
265  * Indicates whether or not the DTLS session is active.
266  *
267  * @param[in]  aInstance  A pointer to an OpenThread instance.
268  *
269  * @retval TRUE  If DTLS session is active.
270  * @retval FALSE If DTLS session is not active.
271  *
272  */
273 bool otCoapSecureIsConnectionActive(otInstance *aInstance);
274 
275 /**
276  * Indicates whether or not the DTLS session is closed.
277  *
278  * @param[in]  aInstance  A pointer to an OpenThread instance.
279  *
280  * @retval TRUE   The DTLS session is closed.
281  * @retval FALSE  The DTLS session is not closed.
282  *
283  */
284 bool otCoapSecureIsClosed(otInstance *aInstance);
285 
286 /**
287  * Sends a CoAP request block-wise over secure DTLS connection.
288  *
289  * Is available when OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE configuration
290  * is enabled.
291  *
292  * If a response for a request is expected, respective function and context information should be provided.
293  * If no response is expected, these arguments should be NULL pointers.
294  * If Message Id was not set in the header (equal to 0), this function will assign unique Message Id to the message.
295  *
296  * @param[in]  aInstance     A pointer to an OpenThread instance.
297  * @param[in]  aMessage      A reference to the message to send.
298  * @param[in]  aHandler      A function pointer that shall be called on response reception or time-out.
299  * @param[in]  aContext      A pointer to arbitrary context information.
300  * @param[in]  aTransmitHook A function pointer that is called on Block1 response reception.
301  * @param[in]  aReceiveHook  A function pointer that is called on Block2 response reception.
302  *
303  * @retval OT_ERROR_NONE           Successfully sent CoAP message.
304  * @retval OT_ERROR_NO_BUFS        Failed to allocate retransmission data.
305  * @retval OT_ERROR_INVALID_STATE  DTLS connection was not initialized.
306  *
307  */
308 otError otCoapSecureSendRequestBlockWise(otInstance                 *aInstance,
309                                          otMessage                  *aMessage,
310                                          otCoapResponseHandler       aHandler,
311                                          void                       *aContext,
312                                          otCoapBlockwiseTransmitHook aTransmitHook,
313                                          otCoapBlockwiseReceiveHook  aReceiveHook);
314 
315 /**
316  * Sends a CoAP request over secure DTLS connection.
317  *
318  * If a response for a request is expected, respective function and context information should be provided.
319  * If no response is expected, these arguments should be NULL pointers.
320  * If Message Id was not set in the header (equal to 0), this function will assign unique Message Id to the message.
321  *
322  * @param[in]  aInstance     A pointer to an OpenThread instance.
323  * @param[in]  aMessage      A reference to the message to send.
324  * @param[in]  aHandler      A function pointer that shall be called on response reception or time-out.
325  * @param[in]  aContext      A pointer to arbitrary context information.
326  *
327  * @retval OT_ERROR_NONE           Successfully sent CoAP message.
328  * @retval OT_ERROR_NO_BUFS        Failed to allocate retransmission data.
329  * @retval OT_ERROR_INVALID_STATE  DTLS connection was not initialized.
330  *
331  */
332 otError otCoapSecureSendRequest(otInstance           *aInstance,
333                                 otMessage            *aMessage,
334                                 otCoapResponseHandler aHandler,
335                                 void                 *aContext);
336 
337 /**
338  * Adds a resource to the CoAP Secure server.
339  *
340  * @param[in]  aInstance  A pointer to an OpenThread instance.
341  * @param[in]  aResource  A pointer to the resource.
342  *
343  */
344 void otCoapSecureAddResource(otInstance *aInstance, otCoapResource *aResource);
345 
346 /**
347  * Removes a resource from the CoAP Secure server.
348  *
349  * @param[in]  aInstance  A pointer to an OpenThread instance.
350  * @param[in]  aResource  A pointer to the resource.
351  *
352  */
353 void otCoapSecureRemoveResource(otInstance *aInstance, otCoapResource *aResource);
354 
355 /**
356  * Adds a block-wise resource to the CoAP Secure server.
357  *
358  * @param[in]  aInstance  A pointer to an OpenThread instance.
359  * @param[in]  aResource  A pointer to the resource.
360  *
361  */
362 void otCoapSecureAddBlockWiseResource(otInstance *aInstance, otCoapBlockwiseResource *aResource);
363 
364 /**
365  * Removes a block-wise resource from the CoAP Secure server.
366  *
367  * @param[in]  aInstance  A pointer to an OpenThread instance.
368  * @param[in]  aResource  A pointer to the resource.
369  *
370  */
371 void otCoapSecureRemoveBlockWiseResource(otInstance *aInstance, otCoapBlockwiseResource *aResource);
372 
373 /**
374  * Sets the default handler for unhandled CoAP Secure requests.
375  *
376  * @param[in]  aInstance  A pointer to an OpenThread instance.
377  * @param[in]  aHandler   A function pointer that shall be called when an unhandled request arrives.
378  * @param[in]  aContext   A pointer to arbitrary context information. May be NULL if not used.
379  *
380  */
381 void otCoapSecureSetDefaultHandler(otInstance *aInstance, otCoapRequestHandler aHandler, void *aContext);
382 
383 /**
384  * Sets the connect event callback to indicate when
385  * a Client connection to the CoAP Secure server has changed.
386  *
387  * @param[in]  aInstance     A pointer to an OpenThread instance.
388  * @param[in]  aHandler      A pointer to a function that will be called once DTLS connection has changed.
389  * @param[in]  aContext      A pointer to arbitrary context information. May be NULL if not used.
390  *
391  */
392 void otCoapSecureSetClientConnectEventCallback(otInstance                     *aInstance,
393                                                otHandleCoapSecureClientConnect aHandler,
394                                                void                           *aContext);
395 
396 /**
397  * Sends a CoAP response block-wise from the CoAP Secure server.
398  *
399  * Is available when OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE configuration
400  * is enabled.
401  *
402  * @param[in]  aInstance     A pointer to an OpenThread instance.
403  * @param[in]  aMessage      A pointer to the CoAP response to send.
404  * @param[in]  aMessageInfo  A pointer to the message info associated with @p aMessage.
405  * @param[in]  aContext      A pointer to arbitrary context information. May be NULL if not used.
406  * @param[in]  aTransmitHook A function pointer that is called on Block1 request reception.
407  *
408  * @retval OT_ERROR_NONE     Successfully enqueued the CoAP response message.
409  * @retval OT_ERROR_NO_BUFS  Insufficient buffers available to send the CoAP response.
410  *
411  */
412 otError otCoapSecureSendResponseBlockWise(otInstance                 *aInstance,
413                                           otMessage                  *aMessage,
414                                           const otMessageInfo        *aMessageInfo,
415                                           void                       *aContext,
416                                           otCoapBlockwiseTransmitHook aTransmitHook);
417 
418 /**
419  * Sends a CoAP response from the CoAP Secure server.
420  *
421  * @param[in]  aInstance     A pointer to an OpenThread instance.
422  * @param[in]  aMessage      A pointer to the CoAP response to send.
423  * @param[in]  aMessageInfo  A pointer to the message info associated with @p aMessage.
424  *
425  * @retval OT_ERROR_NONE     Successfully enqueued the CoAP response message.
426  * @retval OT_ERROR_NO_BUFS  Insufficient buffers available to send the CoAP response.
427  *
428  */
429 otError otCoapSecureSendResponse(otInstance *aInstance, otMessage *aMessage, const otMessageInfo *aMessageInfo);
430 
431 /**
432  * @}
433  *
434  */
435 
436 #ifdef __cplusplus
437 } // extern "C"
438 #endif
439 
440 #endif /* OPENTHREAD_COAP_SECURE_H_ */
441