1 /*
2  *  Copyright (c) 2023, 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 BLE Secure implementation.
33  *
34  *  @note
35  *   The functions in this module require the build-time feature `OPENTHREAD_CONFIG_BLE_TCAT_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_BLE_SECURE_H_
45 #define OPENTHREAD_BLE_SECURE_H_
46 
47 #include <stdint.h>
48 #include <openthread/message.h>
49 #include <openthread/tcat.h>
50 
51 #ifdef __cplusplus
52 extern "C" {
53 #endif
54 
55 /**
56  * @addtogroup api-ble-secure
57  *
58  * @brief
59  *   This module includes functions that control BLE Secure (TLS over BLE) communication.
60  *
61  *   The functions in this module are available when BLE Secure API feature
62  *   (`OPENTHREAD_CONFIG_BLE_TCAT_ENABLE`) is enabled.
63  *
64  * @{
65  *
66  */
67 
68 /**
69  * Pointer to call when ble secure connection state changes.
70  *
71  * @param[in]  aInstance            A pointer to an OpenThread instance.
72  * @param[in]  aConnected           TRUE, if a secure connection was established, FALSE otherwise.
73  * @param[in]  aBleConnectionOpen   TRUE if a BLE connection was established to carry a TLS data stream, FALSE
74  *                                  otherwise.
75  * @param[in]  aContext             A pointer to arbitrary context information.
76  *
77  */
78 typedef void (*otHandleBleSecureConnect)(otInstance *aInstance,
79                                          bool        aConnected,
80                                          bool        aBleConnectionOpen,
81                                          void       *aContext);
82 
83 /**
84  * Pointer to call when data was received over a BLE Secure TLS connection.
85  *
86  */
87 typedef otHandleTcatApplicationDataReceive otHandleBleSecureReceive;
88 
89 /**
90  * Starts the BLE Secure service.
91  * When TLV mode is active, the function @p aReceiveHandler will be called once a complete TLV was received and the
92  * message offset points to the TLV value.
93  *
94  * @param[in]  aInstance        A pointer to an OpenThread instance.
95  * @param[in]  aConnectHandler  A pointer to a function that will be called when the connection
96  *                              state changes.
97  * @param[in]  aReceiveHandler  A pointer to a function that will be called once data has been received
98  *                              over the TLS connection.
99  * @param[in]  aTlvMode         A boolean value indicating if line mode shall be activated.
100  * @param[in]  aContext         A pointer to arbitrary context information. May be NULL if not used.
101  *
102  * @retval OT_ERROR_NONE        Successfully started the BLE Secure server.
103  * @retval OT_ERROR_ALREADY     The service was stated already.
104  *
105  */
106 otError otBleSecureStart(otInstance              *aInstance,
107                          otHandleBleSecureConnect aConnectHandler,
108                          otHandleBleSecureReceive aReceiveHandler,
109                          bool                     aTlvMode,
110                          void                    *aContext);
111 
112 /**
113  * Sets TCAT vendor info
114  *
115  * @param[in]  aInstance         A pointer to an OpenThread instance.
116  * @param[in]  aVendorInfo       A pointer to the Vendor Information (must remain valid after the method call.
117  *
118  * @retval OT_ERROR_NONE         Successfully set value.
119  * @retval OT_ERROR_INVALID_ARGS Value not set.
120  */
121 otError otBleSecureSetTcatVendorInfo(otInstance *aInstance, const otTcatVendorInfo *aVendorInfo);
122 
123 /**
124  * Enables the TCAT protocol over BLE Secure.
125  *
126  * @param[in]  aInstance         A pointer to an OpenThread instance.
127  * @param[in]  aVendorInfo       A pointer to the Vendor Information (must remain valid after the method call, may be
128  *                               NULL).
129  * @param[in]  aHandler          A pointer to a function that is called when the join operation completes.
130  *
131  * @retval OT_ERROR_NONE              Successfully started the BLE Secure Joiner role.
132  * @retval OT_ERROR_INVALID_ARGS      @p aElevationPsk or @p aVendorInfo is invalid.
133  * @retval OT_ERROR_INVALID_STATE     The BLE function has not been started or line mode is not selected.
134  *
135  */
136 otError otBleSecureTcatStart(otInstance *aInstance, otHandleTcatJoin aHandler);
137 
138 /**
139  * Stops the BLE Secure server.
140  *
141  * @param[in]  aInstance  A pointer to an OpenThread instance.
142  *
143  */
144 void otBleSecureStop(otInstance *aInstance);
145 
146 /**
147  * Sets the Pre-Shared Key (PSK) and cipher suite
148  * TLS_PSK_WITH_AES_128_CCM_8.
149  *
150  * @note Requires the build-time feature `MBEDTLS_KEY_EXCHANGE_PSK_ENABLED` to be enabled.
151  *
152  * @param[in]  aInstance     A pointer to an OpenThread instance.
153  * @param[in]  aPsk          A pointer to the PSK.
154  * @param[in]  aPskLength    The PSK length.
155  * @param[in]  aPskIdentity  The Identity Name for the PSK.
156  * @param[in]  aPskIdLength  The PSK Identity Length.
157  *
158  */
159 void otBleSecureSetPsk(otInstance    *aInstance,
160                        const uint8_t *aPsk,
161                        uint16_t       aPskLength,
162                        const uint8_t *aPskIdentity,
163                        uint16_t       aPskIdLength);
164 
165 /**
166  * Returns the peer x509 certificate base64 encoded.
167  *
168  * @note Requires the build-time features `MBEDTLS_BASE64_C` and
169  *       `MBEDTLS_SSL_KEEP_PEER_CERTIFICATE` to be enabled.
170  *
171  * @param[in]       aInstance        A pointer to an OpenThread instance.
172  * @param[out]      aPeerCert        A pointer to the base64 encoded certificate buffer.
173  * @param[in,out]   aCertLength      On input, the size the max size of @p aPeerCert.
174  *                                   On output, the length of the base64 encoded peer certificate.
175  *
176  * @retval OT_ERROR_NONE            Successfully get the peer certificate.
177  * @retval OT_ERROR_INVALID_ARGS    @p aInstance or @p aCertLength is invalid.
178  * @retval OT_ERROR_INVALID_STATE   Not connected yet.
179  * @retval OT_ERROR_NO_BUFS         Can't allocate memory for certificate.
180  *
181  */
182 otError otBleSecureGetPeerCertificateBase64(otInstance *aInstance, unsigned char *aPeerCert, size_t *aCertLength);
183 
184 /**
185  * Returns an attribute value identified by its OID from the subject
186  * of the peer x509 certificate. The peer OID is provided in binary format.
187  * The attribute length is set if the attribute was successfully read or zero
188  * if unsuccessful. The ASN.1 type as is set as defineded in the ITU-T X.690 standard
189  * if the attribute was successfully read.
190  *
191  * @note Requires the build-time feature
192  *       `MBEDTLS_SSL_KEEP_PEER_CERTIFICATE` to be enabled.
193  *
194  * @param[in]     aInstance           A pointer to an OpenThread instance.
195  * @param[in]     aOid                A pointer to the OID to be found.
196  * @param[in]     aOidLength          The length of the OID.
197  * @param[out]    aAttributeBuffer    A pointer to the attribute buffer.
198  * @param[in,out] aAttributeLength    On input, the size the max size of @p aAttributeBuffer.
199  *                                    On output, the length of the attribute written to the buffer.
200  * @param[out]    aAsn1Type           A pointer to the ASN.1 type of the attribute written to the buffer.
201  *
202  * @retval OT_ERROR_INVALID_STATE     Not connected yet.
203  * @retval OT_ERROR_INVALID_ARGS      Invalid attribute length.
204  * @retval OT_ERROR_NONE              Successfully read attribute.
205  * @retval OT_ERROR_NO_BUFS           Insufficient memory for storing the attribute value.
206  *
207  */
208 otError otBleSecureGetPeerSubjectAttributeByOid(otInstance *aInstance,
209                                                 const char *aOid,
210                                                 size_t      aOidLength,
211                                                 uint8_t    *aAttributeBuffer,
212                                                 size_t     *aAttributeLength,
213                                                 int        *aAsn1Type);
214 
215 /**
216  * Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of
217  * the peer x509 certificate, where the last digit x is set to aThreadOidDescriptor.
218  * The attribute length is set if the attribute was successfully read or zero if unsuccessful.
219  * Requires a connection to be active.
220  *
221  * @note Requires the build-time feature
222  *       `MBEDTLS_SSL_KEEP_PEER_CERTIFICATE` to be enabled.
223  *
224  * @param[in]     aInstance             A pointer to an OpenThread instance.
225  * @param[in]     aThreadOidDescriptor  The last digit of the Thread attribute OID.
226  * @param[out]    aAttributeBuffer      A pointer to the attribute buffer.
227  * @param[in,out] aAttributeLength      On input, the size the max size of @p aAttributeBuffer.
228  *                                      On output, the length of the attribute written to the buffer.
229  *
230  * @retval OT_ERROR_NONE                Successfully read attribute.
231  * @retval OT_ERROR_INVALID_ARGS        Invalid attribute length.
232  * @retval OT_NOT_FOUND                 The requested attribute was not found.
233  * @retval OT_ERROR_NO_BUFS             Insufficient memory for storing the attribute value.
234  * @retval OT_ERROR_INVALID_STATE       Not connected yet.
235  * @retval OT_ERROR_NOT_IMPLEMENTED     The value of aThreadOidDescriptor is >127.
236  * @retval OT_ERROR_PARSE               The certificate extensions could not be parsed.
237  *
238  */
239 otError otBleSecureGetThreadAttributeFromPeerCertificate(otInstance *aInstance,
240                                                          int         aThreadOidDescriptor,
241                                                          uint8_t    *aAttributeBuffer,
242                                                          size_t     *aAttributeLength);
243 
244 /**
245  * Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of
246  * the own x509 certificate, where the last digit x is set to aThreadOidDescriptor.
247  * The attribute length is set if the attribute was successfully read or zero if unsuccessful.
248  * Requires a connection to be active.
249  *
250  * @param[in]     aInstance             A pointer to an OpenThread instance.
251  * @param[in]     aThreadOidDescriptor  The last digit of the Thread attribute OID.
252  * @param[out]    aAttributeBuffer      A pointer to the attribute buffer.
253  * @param[in,out] aAttributeLength      On input, the size the max size of @p aAttributeBuffer.
254  *                                      On output, the length of the attribute written to the buffer.
255  *
256  * @retval OT_ERROR_NONE                Successfully read attribute.
257  * @retval OT_ERROR_INVALID_ARGS        Invalid attribute length.
258  * @retval OT_NOT_FOUND                 The requested attribute was not found.
259  * @retval OT_ERROR_NO_BUFS             Insufficient memory for storing the attribute value.
260  * @retval OT_ERROR_INVALID_STATE       Not connected yet.
261  * @retval OT_ERROR_NOT_IMPLEMENTED     The value of aThreadOidDescriptor is >127.
262  * @retval OT_ERROR_PARSE               The certificate extensions could not be parsed.
263  *
264  */
265 otError otBleSecureGetThreadAttributeFromOwnCertificate(otInstance *aInstance,
266                                                         int         aThreadOidDescriptor,
267                                                         uint8_t    *aAttributeBuffer,
268                                                         size_t     *aAttributeLength);
269 
270 /**
271  * Sets the authentication mode for the BLE secure connection.
272  *
273  * Disable or enable the verification of peer certificate.
274  * Must be called before start.
275  *
276  * @param[in]   aInstance               A pointer to an OpenThread instance.
277  * @param[in]   aVerifyPeerCertificate  true, to verify the peer certificate.
278  *
279  */
280 void otBleSecureSetSslAuthMode(otInstance *aInstance, bool aVerifyPeerCertificate);
281 
282 /**
283  * Sets the local device's X509 certificate with corresponding private key for
284  * TLS session with TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8.
285  *
286  * @note Requires `MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=1`.
287  *
288  * @param[in]  aInstance          A pointer to an OpenThread instance.
289  * @param[in]  aX509Cert          A pointer to the PEM formatted X509 certificate.
290  * @param[in]  aX509Length        The length of certificate.
291  * @param[in]  aPrivateKey        A pointer to the PEM formatted private key.
292  * @param[in]  aPrivateKeyLength  The length of the private key.
293  *
294  */
295 void otBleSecureSetCertificate(otInstance    *aInstance,
296                                const uint8_t *aX509Cert,
297                                uint32_t       aX509Length,
298                                const uint8_t *aPrivateKey,
299                                uint32_t       aPrivateKeyLength);
300 
301 /**
302  * Sets the trusted top level CAs. It is needed for validating the
303  * certificate of the peer.
304  *
305  * TLS mode "ECDHE ECDSA with AES 128 CCM 8" for secure BLE.
306  *
307  * @note Requires `MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=1`.
308  *
309  * @param[in]  aInstance                A pointer to an OpenThread instance.
310  * @param[in]  aX509CaCertificateChain  A pointer to the PEM formatted X509 CA chain.
311  * @param[in]  aX509CaCertChainLength   The length of chain.
312  *
313  */
314 void otBleSecureSetCaCertificateChain(otInstance    *aInstance,
315                                       const uint8_t *aX509CaCertificateChain,
316                                       uint32_t       aX509CaCertChainLength);
317 
318 /**
319  * Initializes TLS session with a peer using an already open BLE connection.
320  *
321  * @param[in]  aInstance               A pointer to an OpenThread instance.
322  *
323  * @retval OT_ERROR_NONE  Successfully started TLS connection.
324  *
325  */
326 otError otBleSecureConnect(otInstance *aInstance);
327 
328 /**
329  * Stops the BLE and TLS connection.
330  *
331  * @param[in]  aInstance  A pointer to an OpenThread instance.
332  *
333  */
334 void otBleSecureDisconnect(otInstance *aInstance);
335 
336 /**
337  * Indicates whether or not the TLS session is active (connected or connecting).
338  *
339  * @param[in]  aInstance  A pointer to an OpenThread instance.
340  *
341  * @retval TRUE  If TLS session is active.
342  * @retval FALSE If TLS session is not active.
343  *
344  */
345 bool otBleSecureIsConnectionActive(otInstance *aInstance);
346 
347 /**
348  * Indicates whether or not the TLS session is connected.
349  *
350  * @param[in]  aInstance  A pointer to an OpenThread instance.
351  *
352  * @retval TRUE   The TLS session is connected.
353  * @retval FALSE  The TLS session is not connected.
354  *
355  */
356 bool otBleSecureIsConnected(otInstance *aInstance);
357 
358 /**
359  * Indicates whether or not the TCAT agent is enabled.
360  *
361  * @retval TRUE   The TCAT agent is enabled.
362  * @retval FALSE  The TCAT agent is not enabled.
363  *
364  */
365 bool otBleSecureIsTcatEnabled(otInstance *aInstance);
366 
367 /**
368  * Indicates whether or not a TCAT command class is authorized.
369  *
370  * @param[in]  aInstance  A pointer to an OpenThread instance.
371  * @param[in]  aCommandClass  A command class to check.
372  *
373  * @retval TRUE   The command class is authorized.
374  * @retval FALSE  The command class is not authorized.
375  *
376  */
377 bool otBleSecureIsCommandClassAuthorized(otInstance *aInstance, otTcatCommandClass aCommandClass);
378 
379 /**
380  * Sends a secure BLE message.
381  *
382  * @param[in]  aInstance     A pointer to an OpenThread instance.
383  * @param[in]  aMessage      A pointer to the message to send.
384  *
385  * If the return value is OT_ERROR_NONE, OpenThread takes ownership of @p aMessage, and the caller should no longer
386  * reference @p aMessage. If the return value is not OT_ERROR_NONE, the caller retains ownership of @p aMessage,
387  * including freeing @p aMessage if the message buffer is no longer needed.
388  *
389  * @retval OT_ERROR_NONE           Successfully sent message.
390  * @retval OT_ERROR_NO_BUFS        Failed to allocate buffer memory.
391  * @retval OT_ERROR_INVALID_STATE  TLS connection was not initialized.
392  *
393  */
394 otError otBleSecureSendMessage(otInstance *aInstance, otMessage *aMessage);
395 
396 /**
397  * Sends a secure BLE data packet.
398  *
399  * @param[in]  aInstance     A pointer to an OpenThread instance.
400  * @param[in]  aBuf          A pointer to the data to send as the Value of the TCAT Send Application Data TLV.
401  * @param[in]  aLength       A number indicating the length of the data buffer.
402  *
403  * @retval OT_ERROR_NONE           Successfully sent data.
404  * @retval OT_ERROR_NO_BUFS        Failed to allocate buffer memory.
405  * @retval OT_ERROR_INVALID_STATE  TLS connection was not initialized.
406  *
407  */
408 otError otBleSecureSend(otInstance *aInstance, uint8_t *aBuf, uint16_t aLength);
409 
410 /**
411  * Sends a secure BLE data packet containing a TCAT Send Application Data TLV.
412  *
413  * @param[in]  aInstance       A pointer to an OpenThread instance.
414  * @param[in]  aBuf            A pointer to the data to send as the Value of the TCAT Send Application Data TLV.
415  * @param[in]  aLength         A number indicating the length of the data buffer.
416  *
417  * @retval OT_ERROR_NONE           Successfully sent data.
418  * @retval OT_ERROR_NO_BUFS        Failed to allocate buffer memory.
419  * @retval OT_ERROR_INVALID_STATE  TLS connection was not initialized.
420  *
421  */
422 otError otBleSecureSendApplicationTlv(otInstance *aInstance, uint8_t *aBuf, uint16_t aLength);
423 
424 /**
425  * Flushes the send buffer.
426  *
427  * @param[in]  aInstance     A pointer to an OpenThread instance.
428  *
429  * @retval OT_ERROR_NONE           Successfully flushed output buffer.
430  * @retval OT_ERROR_NO_BUFS        Failed to allocate buffer memory.
431  * @retval OT_ERROR_INVALID_STATE  TLS connection was not initialized.
432  *
433  */
434 otError otBleSecureFlush(otInstance *aInstance);
435 
436 /**
437  * @}
438  *
439  */
440 
441 #ifdef __cplusplus
442 } // extern "C"
443 #endif
444 
445 #endif /* OPENTHREAD_BLE_SECURE_H_ */
446