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  * Pointer is called when the DTLS connection state changes.
72  *
73  * @param[in]  aConnected  true, if a connection was established, false otherwise.
74  * @param[in]  aContext    A pointer to arbitrary context information.
75  *
76  */
77 typedef void (*otHandleCoapSecureClientConnect)(bool aConnected, void *aContext);
78 
79 /**
80  * Starts the CoAP Secure service.
81  *
82  * @param[in]  aInstance  A pointer to an OpenThread instance.
83  * @param[in]  aPort      The local UDP port to bind to.
84  *
85  * @retval OT_ERROR_NONE  Successfully started the CoAP Secure server.
86  *
87  */
88 otError otCoapSecureStart(otInstance *aInstance, uint16_t aPort);
89 
90 /**
91  * Stops the CoAP Secure server.
92  *
93  * @param[in]  aInstance  A pointer to an OpenThread instance.
94  *
95  */
96 void otCoapSecureStop(otInstance *aInstance);
97 
98 /**
99  * Sets the Pre-Shared Key (PSK) and cipher suite
100  * DTLS_PSK_WITH_AES_128_CCM_8.
101  *
102  * @note This function requires the build-time feature `MBEDTLS_KEY_EXCHANGE_PSK_ENABLED` to be enabled.
103  *
104  * @param[in]  aInstance     A pointer to an OpenThread instance.
105  * @param[in]  aPsk          A pointer to the PSK.
106  * @param[in]  aPskLength    The PSK length.
107  * @param[in]  aPskIdentity  The Identity Name for the PSK.
108  * @param[in]  aPskIdLength  The PSK Identity Length.
109  *
110  */
111 void otCoapSecureSetPsk(otInstance    *aInstance,
112                         const uint8_t *aPsk,
113                         uint16_t       aPskLength,
114                         const uint8_t *aPskIdentity,
115                         uint16_t       aPskIdLength);
116 
117 /**
118  * Returns the peer x509 certificate base64 encoded.
119  *
120  * @note This function requires the build-time features `MBEDTLS_BASE64_C` and
121  *       `MBEDTLS_SSL_KEEP_PEER_CERTIFICATE` to be enabled.
122  *
123  * @param[in]   aInstance        A pointer to an OpenThread instance.
124  * @param[out]  aPeerCert        A pointer to the base64 encoded certificate buffer.
125  * @param[out]  aCertLength      The length of the base64 encoded peer certificate.
126  * @param[in]   aCertBufferSize  The buffer size of aPeerCert.
127  *
128  * @retval OT_ERROR_INVALID_STATE   Not connected yet.
129  * @retval OT_ERROR_NONE            Successfully get the peer certificate.
130  * @retval OT_ERROR_NO_BUFS         Can't allocate memory for certificate.
131  *
132  */
133 otError otCoapSecureGetPeerCertificateBase64(otInstance    *aInstance,
134                                              unsigned char *aPeerCert,
135                                              size_t        *aCertLength,
136                                              size_t         aCertBufferSize);
137 
138 /**
139  * Sets the authentication mode for the coap secure connection.
140  *
141  * Disable or enable the verification of peer certificate.
142  * Must be called before start.
143  *
144  * @param[in]   aInstance               A pointer to an OpenThread instance.
145  * @param[in]   aVerifyPeerCertificate  true, to verify the peer certificate.
146  *
147  */
148 void otCoapSecureSetSslAuthMode(otInstance *aInstance, bool aVerifyPeerCertificate);
149 
150 /**
151  * Sets the local device's X509 certificate with corresponding private key for
152  * DTLS session with DTLS_ECDHE_ECDSA_WITH_AES_128_CCM_8.
153  *
154  * @note This function requires `MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=1`.
155  *
156  * @param[in]  aInstance          A pointer to an OpenThread instance.
157  * @param[in]  aX509Cert          A pointer to the PEM formatted X509 certificate.
158  * @param[in]  aX509Length        The length of certificate.
159  * @param[in]  aPrivateKey        A pointer to the PEM formatted private key.
160  * @param[in]  aPrivateKeyLength  The length of the private key.
161  *
162  */
163 void otCoapSecureSetCertificate(otInstance    *aInstance,
164                                 const uint8_t *aX509Cert,
165                                 uint32_t       aX509Length,
166                                 const uint8_t *aPrivateKey,
167                                 uint32_t       aPrivateKeyLength);
168 
169 /**
170  * Sets the trusted top level CAs. It is needed for validating the
171  * certificate of the peer.
172  *
173  * DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS.
174  *
175  * @note This function requires `MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=1`.
176  *
177  * @param[in]  aInstance                A pointer to an OpenThread instance.
178  * @param[in]  aX509CaCertificateChain  A pointer to the PEM formatted X509 CA chain.
179  * @param[in]  aX509CaCertChainLength   The length of chain.
180  *
181  */
182 void otCoapSecureSetCaCertificateChain(otInstance    *aInstance,
183                                        const uint8_t *aX509CaCertificateChain,
184                                        uint32_t       aX509CaCertChainLength);
185 
186 /**
187  * Initializes DTLS session with a peer.
188  *
189  * @param[in]  aInstance               A pointer to an OpenThread instance.
190  * @param[in]  aSockAddr               A pointer to the remote socket address.
191  * @param[in]  aHandler                A pointer to a function that will be called when the DTLS connection
192  *                                     state changes.
193  * @param[in]  aContext                A pointer to arbitrary context information.
194  *
195  * @retval OT_ERROR_NONE  Successfully started DTLS connection.
196  *
197  */
198 otError otCoapSecureConnect(otInstance                     *aInstance,
199                             const otSockAddr               *aSockAddr,
200                             otHandleCoapSecureClientConnect aHandler,
201                             void                           *aContext);
202 
203 /**
204  * Stops the DTLS connection.
205  *
206  * @param[in]  aInstance  A pointer to an OpenThread instance.
207  *
208  */
209 void otCoapSecureDisconnect(otInstance *aInstance);
210 
211 /**
212  * Indicates whether or not the DTLS session is connected.
213  *
214  * @param[in]  aInstance  A pointer to an OpenThread instance.
215  *
216  * @retval TRUE   The DTLS session is connected.
217  * @retval FALSE  The DTLS session is not connected.
218  *
219  */
220 bool otCoapSecureIsConnected(otInstance *aInstance);
221 
222 /**
223  * Indicates whether or not the DTLS session is active.
224  *
225  * @param[in]  aInstance  A pointer to an OpenThread instance.
226  *
227  * @retval TRUE  If DTLS session is active.
228  * @retval FALSE If DTLS session is not active.
229  *
230  */
231 bool otCoapSecureIsConnectionActive(otInstance *aInstance);
232 
233 /**
234  * Sends a CoAP request block-wise over secure DTLS connection.
235  *
236  * Is available when OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE configuration
237  * is enabled.
238  *
239  * If a response for a request is expected, respective function and context information should be provided.
240  * If no response is expected, these arguments should be NULL pointers.
241  * If Message Id was not set in the header (equal to 0), this function will assign unique Message Id to the message.
242  *
243  * @param[in]  aInstance     A pointer to an OpenThread instance.
244  * @param[in]  aMessage      A reference to the message to send.
245  * @param[in]  aHandler      A function pointer that shall be called on response reception or time-out.
246  * @param[in]  aContext      A pointer to arbitrary context information.
247  * @param[in]  aTransmitHook A function pointer that is called on Block1 response reception.
248  * @param[in]  aReceiveHook  A function pointer that is called on Block2 response reception.
249  *
250  * @retval OT_ERROR_NONE           Successfully sent CoAP message.
251  * @retval OT_ERROR_NO_BUFS        Failed to allocate retransmission data.
252  * @retval OT_ERROR_INVALID_STATE  DTLS connection was not initialized.
253  *
254  */
255 otError otCoapSecureSendRequestBlockWise(otInstance                 *aInstance,
256                                          otMessage                  *aMessage,
257                                          otCoapResponseHandler       aHandler,
258                                          void                       *aContext,
259                                          otCoapBlockwiseTransmitHook aTransmitHook,
260                                          otCoapBlockwiseReceiveHook  aReceiveHook);
261 
262 /**
263  * Sends a CoAP request over secure DTLS connection.
264  *
265  * If a response for a request is expected, respective function and context information should be provided.
266  * If no response is expected, these arguments should be NULL pointers.
267  * If Message Id was not set in the header (equal to 0), this function will assign unique Message Id to the message.
268  *
269  * @param[in]  aInstance     A pointer to an OpenThread instance.
270  * @param[in]  aMessage      A reference to the message to send.
271  * @param[in]  aHandler      A function pointer that shall be called on response reception or time-out.
272  * @param[in]  aContext      A pointer to arbitrary context information.
273  *
274  * @retval OT_ERROR_NONE           Successfully sent CoAP message.
275  * @retval OT_ERROR_NO_BUFS        Failed to allocate retransmission data.
276  * @retval OT_ERROR_INVALID_STATE  DTLS connection was not initialized.
277  *
278  */
279 otError otCoapSecureSendRequest(otInstance           *aInstance,
280                                 otMessage            *aMessage,
281                                 otCoapResponseHandler aHandler,
282                                 void                 *aContext);
283 
284 /**
285  * Adds a resource to the CoAP Secure server.
286  *
287  * @param[in]  aInstance  A pointer to an OpenThread instance.
288  * @param[in]  aResource  A pointer to the resource.
289  *
290  */
291 void otCoapSecureAddResource(otInstance *aInstance, otCoapResource *aResource);
292 
293 /**
294  * Removes a resource from the CoAP Secure server.
295  *
296  * @param[in]  aInstance  A pointer to an OpenThread instance.
297  * @param[in]  aResource  A pointer to the resource.
298  *
299  */
300 void otCoapSecureRemoveResource(otInstance *aInstance, otCoapResource *aResource);
301 
302 /**
303  * Adds a block-wise resource to the CoAP Secure server.
304  *
305  * @param[in]  aInstance  A pointer to an OpenThread instance.
306  * @param[in]  aResource  A pointer to the resource.
307  *
308  */
309 void otCoapSecureAddBlockWiseResource(otInstance *aInstance, otCoapBlockwiseResource *aResource);
310 
311 /**
312  * Removes a block-wise resource from the CoAP Secure server.
313  *
314  * @param[in]  aInstance  A pointer to an OpenThread instance.
315  * @param[in]  aResource  A pointer to the resource.
316  *
317  */
318 void otCoapSecureRemoveBlockWiseResource(otInstance *aInstance, otCoapBlockwiseResource *aResource);
319 
320 /**
321  * Sets the default handler for unhandled CoAP Secure requests.
322  *
323  * @param[in]  aInstance  A pointer to an OpenThread instance.
324  * @param[in]  aHandler   A function pointer that shall be called when an unhandled request arrives.
325  * @param[in]  aContext   A pointer to arbitrary context information. May be NULL if not used.
326  *
327  */
328 void otCoapSecureSetDefaultHandler(otInstance *aInstance, otCoapRequestHandler aHandler, void *aContext);
329 
330 /**
331  * Sets the connected callback to indicate, when
332  * a Client connect to the CoAP Secure server.
333  *
334  * @param[in]  aInstance     A pointer to an OpenThread instance.
335  * @param[in]  aHandler      A pointer to a function that will be called once DTLS connection is established.
336  * @param[in]  aContext      A pointer to arbitrary context information. May be NULL if not used.
337  *
338  */
339 void otCoapSecureSetClientConnectedCallback(otInstance                     *aInstance,
340                                             otHandleCoapSecureClientConnect aHandler,
341                                             void                           *aContext);
342 
343 /**
344  * Sends a CoAP response block-wise from the CoAP Secure server.
345  *
346  * Is available when OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE configuration
347  * is enabled.
348  *
349  * @param[in]  aInstance     A pointer to an OpenThread instance.
350  * @param[in]  aMessage      A pointer to the CoAP response to send.
351  * @param[in]  aMessageInfo  A pointer to the message info associated with @p aMessage.
352  * @param[in]  aContext      A pointer to arbitrary context information. May be NULL if not used.
353  * @param[in]  aTransmitHook A function pointer that is called on Block1 request reception.
354  *
355  * @retval OT_ERROR_NONE     Successfully enqueued the CoAP response message.
356  * @retval OT_ERROR_NO_BUFS  Insufficient buffers available to send the CoAP response.
357  *
358  */
359 otError otCoapSecureSendResponseBlockWise(otInstance                 *aInstance,
360                                           otMessage                  *aMessage,
361                                           const otMessageInfo        *aMessageInfo,
362                                           void                       *aContext,
363                                           otCoapBlockwiseTransmitHook aTransmitHook);
364 
365 /**
366  * Sends a CoAP response from the CoAP Secure server.
367  *
368  * @param[in]  aInstance     A pointer to an OpenThread instance.
369  * @param[in]  aMessage      A pointer to the CoAP response to send.
370  * @param[in]  aMessageInfo  A pointer to the message info associated with @p aMessage.
371  *
372  * @retval OT_ERROR_NONE     Successfully enqueued the CoAP response message.
373  * @retval OT_ERROR_NO_BUFS  Insufficient buffers available to send the CoAP response.
374  *
375  */
376 otError otCoapSecureSendResponse(otInstance *aInstance, otMessage *aMessage, const otMessageInfo *aMessageInfo);
377 
378 /**
379  * @}
380  *
381  */
382 
383 #ifdef __cplusplus
384 } // extern "C"
385 #endif
386 
387 #endif /* OPENTHREAD_COAP_SECURE_H_ */
388