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  * Enables the TCAT protocol over BLE Secure.
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, may be
117  *                               NULL).
118  * @param[in]  aHandler          A pointer to a function that is called when the join operation completes.
119  *
120  * @retval OT_ERROR_NONE              Successfully started the BLE Secure Joiner role.
121  * @retval OT_ERROR_INVALID_ARGS      @p aElevationPsk or @p aVendorInfo is invalid.
122  * @retval OT_ERROR_INVALID_STATE     The BLE function has not been started or line mode is not selected.
123  *
124  */
125 otError otBleSecureTcatStart(otInstance *aInstance, const otTcatVendorInfo *aVendorInfo, otHandleTcatJoin aHandler);
126 
127 /**
128  * Stops the BLE Secure server.
129  *
130  * @param[in]  aInstance  A pointer to an OpenThread instance.
131  *
132  */
133 void otBleSecureStop(otInstance *aInstance);
134 
135 /**
136  * Sets the Pre-Shared Key (PSK) and cipher suite
137  * TLS_PSK_WITH_AES_128_CCM_8.
138  *
139  * @note Requires the build-time feature `MBEDTLS_KEY_EXCHANGE_PSK_ENABLED` to be enabled.
140  *
141  * @param[in]  aInstance     A pointer to an OpenThread instance.
142  * @param[in]  aPsk          A pointer to the PSK.
143  * @param[in]  aPskLength    The PSK length.
144  * @param[in]  aPskIdentity  The Identity Name for the PSK.
145  * @param[in]  aPskIdLength  The PSK Identity Length.
146  *
147  */
148 void otBleSecureSetPsk(otInstance    *aInstance,
149                        const uint8_t *aPsk,
150                        uint16_t       aPskLength,
151                        const uint8_t *aPskIdentity,
152                        uint16_t       aPskIdLength);
153 
154 /**
155  * Returns the peer x509 certificate base64 encoded.
156  *
157  * @note Requires the build-time features `MBEDTLS_BASE64_C` and
158  *       `MBEDTLS_SSL_KEEP_PEER_CERTIFICATE` to be enabled.
159  *
160  * @param[in]       aInstance        A pointer to an OpenThread instance.
161  * @param[out]      aPeerCert        A pointer to the base64 encoded certificate buffer.
162  * @param[in,out]   aCertLength      On input, the size the max size of @p aPeerCert.
163  *                                   On output, the length of the base64 encoded peer certificate.
164  *
165  * @retval OT_ERROR_NONE            Successfully get the peer certificate.
166  * @retval OT_ERROR_INVALID_ARGS    @p aInstance or @p aCertLength is invalid.
167  * @retval OT_ERROR_INVALID_STATE   Not connected yet.
168  * @retval OT_ERROR_NO_BUFS         Can't allocate memory for certificate.
169  *
170  */
171 otError otBleSecureGetPeerCertificateBase64(otInstance *aInstance, unsigned char *aPeerCert, size_t *aCertLength);
172 
173 /**
174  * Returns an attribute value identified by its OID from the subject
175  * of the peer x509 certificate. The peer OID is provided in binary format.
176  * The attribute length is set if the attribute was successfully read or zero
177  * if unsuccessful. The ASN.1 type as is set as defineded in the ITU-T X.690 standard
178  * if the attribute was successfully read.
179  *
180  * @note Requires the build-time feature
181  *       `MBEDTLS_SSL_KEEP_PEER_CERTIFICATE` to be enabled.
182  *
183  * @param[in]     aInstance           A pointer to an OpenThread instance.
184  * @param[in]     aOid                A pointer to the OID to be found.
185  * @param[in]     aOidLength          The length of the OID.
186  * @param[out]    aAttributeBuffer    A pointer to the attribute buffer.
187  * @param[in,out] aAttributeLength    On input, the size the max size of @p aAttributeBuffer.
188  *                                    On output, the length of the attribute written to the buffer.
189  * @param[out]    aAsn1Type           A pointer to the ASN.1 type of the attribute written to the buffer.
190  *
191  * @retval OT_ERROR_INVALID_STATE     Not connected yet.
192  * @retval OT_ERROR_INVALID_ARGS      Invalid attribute length.
193  * @retval OT_ERROR_NONE              Successfully read attribute.
194  * @retval OT_ERROR_NO_BUFS           Insufficient memory for storing the attribute value.
195  *
196  */
197 otError otBleSecureGetPeerSubjectAttributeByOid(otInstance *aInstance,
198                                                 const char *aOid,
199                                                 size_t      aOidLength,
200                                                 uint8_t    *aAttributeBuffer,
201                                                 size_t     *aAttributeLength,
202                                                 int        *aAsn1Type);
203 
204 /**
205  * Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of
206  * the peer x509 certificate, where the last digit x is set to aThreadOidDescriptor.
207  * The attribute length is set if the attribute was successfully read or zero if unsuccessful.
208  * Requires a connection to be active.
209  *
210  * @note Requires the build-time feature
211  *       `MBEDTLS_SSL_KEEP_PEER_CERTIFICATE` to be enabled.
212  *
213  * @param[in]     aInstance             A pointer to an OpenThread instance.
214  * @param[in]     aThreadOidDescriptor  The last digit of the Thread attribute OID.
215  * @param[out]    aAttributeBuffer      A pointer to the attribute buffer.
216  * @param[in,out] aAttributeLength      On input, the size the max size of @p aAttributeBuffer.
217  *                                      On output, the length of the attribute written to the buffer.
218  *
219  * @retval OT_ERROR_NONE                Successfully read attribute.
220  * @retval OT_ERROR_INVALID_ARGS        Invalid attribute length.
221  * @retval OT_NOT_FOUND                 The requested attribute was not found.
222  * @retval OT_ERROR_NO_BUFS             Insufficient memory for storing the attribute value.
223  * @retval OT_ERROR_INVALID_STATE       Not connected yet.
224  * @retval OT_ERROR_NOT_IMPLEMENTED     The value of aThreadOidDescriptor is >127.
225  * @retval OT_ERROR_PARSE               The certificate extensions could not be parsed.
226  *
227  */
228 otError otBleSecureGetThreadAttributeFromPeerCertificate(otInstance *aInstance,
229                                                          int         aThreadOidDescriptor,
230                                                          uint8_t    *aAttributeBuffer,
231                                                          size_t     *aAttributeLength);
232 
233 /**
234  * Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of
235  * the own x509 certificate, where the last digit x is set to aThreadOidDescriptor.
236  * The attribute length is set if the attribute was successfully read or zero if unsuccessful.
237  * Requires a connection to be active.
238  *
239  * @param[in]     aInstance             A pointer to an OpenThread instance.
240  * @param[in]     aThreadOidDescriptor  The last digit of the Thread attribute OID.
241  * @param[out]    aAttributeBuffer      A pointer to the attribute buffer.
242  * @param[in,out] aAttributeLength      On input, the size the max size of @p aAttributeBuffer.
243  *                                      On output, the length of the attribute written to the buffer.
244  *
245  * @retval OT_ERROR_NONE                Successfully read attribute.
246  * @retval OT_ERROR_INVALID_ARGS        Invalid attribute length.
247  * @retval OT_NOT_FOUND                 The requested attribute was not found.
248  * @retval OT_ERROR_NO_BUFS             Insufficient memory for storing the attribute value.
249  * @retval OT_ERROR_INVALID_STATE       Not connected yet.
250  * @retval OT_ERROR_NOT_IMPLEMENTED     The value of aThreadOidDescriptor is >127.
251  * @retval OT_ERROR_PARSE               The certificate extensions could not be parsed.
252  *
253  */
254 otError otBleSecureGetThreadAttributeFromOwnCertificate(otInstance *aInstance,
255                                                         int         aThreadOidDescriptor,
256                                                         uint8_t    *aAttributeBuffer,
257                                                         size_t     *aAttributeLength);
258 
259 /**
260  * Sets the authentication mode for the BLE secure connection.
261  *
262  * Disable or enable the verification of peer certificate.
263  * Must be called before start.
264  *
265  * @param[in]   aInstance               A pointer to an OpenThread instance.
266  * @param[in]   aVerifyPeerCertificate  true, to verify the peer certificate.
267  *
268  */
269 void otBleSecureSetSslAuthMode(otInstance *aInstance, bool aVerifyPeerCertificate);
270 
271 /**
272  * Sets the local device's X509 certificate with corresponding private key for
273  * TLS session with TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8.
274  *
275  * @note Requires `MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=1`.
276  *
277  * @param[in]  aInstance          A pointer to an OpenThread instance.
278  * @param[in]  aX509Cert          A pointer to the PEM formatted X509 certificate.
279  * @param[in]  aX509Length        The length of certificate.
280  * @param[in]  aPrivateKey        A pointer to the PEM formatted private key.
281  * @param[in]  aPrivateKeyLength  The length of the private key.
282  *
283  */
284 void otBleSecureSetCertificate(otInstance    *aInstance,
285                                const uint8_t *aX509Cert,
286                                uint32_t       aX509Length,
287                                const uint8_t *aPrivateKey,
288                                uint32_t       aPrivateKeyLength);
289 
290 /**
291  * Sets the trusted top level CAs. It is needed for validating the
292  * certificate of the peer.
293  *
294  * TLS mode "ECDHE ECDSA with AES 128 CCM 8" for secure BLE.
295  *
296  * @note Requires `MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=1`.
297  *
298  * @param[in]  aInstance                A pointer to an OpenThread instance.
299  * @param[in]  aX509CaCertificateChain  A pointer to the PEM formatted X509 CA chain.
300  * @param[in]  aX509CaCertChainLength   The length of chain.
301  *
302  */
303 void otBleSecureSetCaCertificateChain(otInstance    *aInstance,
304                                       const uint8_t *aX509CaCertificateChain,
305                                       uint32_t       aX509CaCertChainLength);
306 
307 /**
308  * Initializes TLS session with a peer using an already open BLE connection.
309  *
310  * @param[in]  aInstance               A pointer to an OpenThread instance.
311  *
312  * @retval OT_ERROR_NONE  Successfully started TLS connection.
313  *
314  */
315 otError otBleSecureConnect(otInstance *aInstance);
316 
317 /**
318  * Stops the BLE and TLS connection.
319  *
320  * @param[in]  aInstance  A pointer to an OpenThread instance.
321  *
322  */
323 void otBleSecureDisconnect(otInstance *aInstance);
324 
325 /**
326  * Indicates whether or not the TLS session is active (connected or conneting).
327  *
328  * @param[in]  aInstance  A pointer to an OpenThread instance.
329  *
330  * @retval TRUE  If TLS session is active.
331  * @retval FALSE If TLS session is not active.
332  *
333  */
334 bool otBleSecureIsConnectionActive(otInstance *aInstance);
335 
336 /**
337  * Indicates whether or not the TLS session is connected.
338  *
339  * @param[in]  aInstance  A pointer to an OpenThread instance.
340  *
341  * @retval TRUE   The TLS session is connected.
342  * @retval FALSE  The TLS session is not connected.
343  *
344  */
345 bool otBleSecureIsConnected(otInstance *aInstance);
346 
347 /**
348  * Indicates whether or not the TCAT agent is enabled.
349  *
350  * @retval TRUE   The TCAT agent is enabled.
351  * @retval FALSE  The TCAT agent is not enabled.
352  *
353  */
354 bool otBleSecureIsTcatEnabled(otInstance *aInstance);
355 
356 /**
357  * Indicates whether or not a TCAT command class is authorized.
358  *
359  * @param[in]  aInstance  A pointer to an OpenThread instance.
360  * @param[in]  aCommandClass  A command class to check.
361  *
362  * @retval TRUE   The command class is authorized.
363  * @retval FALSE  The command class is not authorized.
364  *
365  */
366 bool otBleSecureIsCommandClassAuthorized(otInstance *aInstance, otTcatCommandClass aCommandClass);
367 
368 /**
369  * Sends a secure BLE message.
370  *
371  * @param[in]  aInstance     A pointer to an OpenThread instance.
372  * @param[in]  aMessage      A pointer to the message to send.
373  *
374  * If the return value is OT_ERROR_NONE, OpenThread takes ownership of @p aMessage, and the caller should no longer
375  * reference @p aMessage. If the return value is not OT_ERROR_NONE, the caller retains ownership of @p aMessage,
376  * including freeing @p aMessage if the message buffer is no longer needed.
377  *
378  * @retval OT_ERROR_NONE           Successfully sent message.
379  * @retval OT_ERROR_NO_BUFS        Failed to allocate buffer memory.
380  * @retval OT_ERROR_INVALID_STATE  TLS connection was not initialized.
381  *
382  */
383 otError otBleSecureSendMessage(otInstance *aInstance, otMessage *aMessage);
384 
385 /**
386  * Sends a secure BLE data packet.
387  *
388  * @param[in]  aInstance     A pointer to an OpenThread instance.
389  * @param[in]  aBuf          A pointer to the data to send as the Value of the TCAT Send Application Data TLV.
390  * @param[in]  aLength       A number indicating the length of the data buffer.
391  *
392  * @retval OT_ERROR_NONE           Successfully sent data.
393  * @retval OT_ERROR_NO_BUFS        Failed to allocate buffer memory.
394  * @retval OT_ERROR_INVALID_STATE  TLS connection was not initialized.
395  *
396  */
397 otError otBleSecureSend(otInstance *aInstance, uint8_t *aBuf, uint16_t aLength);
398 
399 /**
400  * Sends a secure BLE data packet containing a TCAT Send Application Data TLV.
401  *
402  * @param[in]  aInstance       A pointer to an OpenThread instance.
403  * @param[in]  aBuf            A pointer to the data to send as the Value of the TCAT Send Application Data TLV.
404  * @param[in]  aLength         A number indicating the length of the data buffer.
405  *
406  * @retval OT_ERROR_NONE           Successfully sent data.
407  * @retval OT_ERROR_NO_BUFS        Failed to allocate buffer memory.
408  * @retval OT_ERROR_INVALID_STATE  TLS connection was not initialized.
409  *
410  */
411 otError otBleSecureSendApplicationTlv(otInstance *aInstance, uint8_t *aBuf, uint16_t aLength);
412 
413 /**
414  * Flushes the send buffer.
415  *
416  * @param[in]  aInstance     A pointer to an OpenThread instance.
417  *
418  * @retval OT_ERROR_NONE           Successfully flushed output buffer.
419  * @retval OT_ERROR_NO_BUFS        Failed to allocate buffer memory.
420  * @retval OT_ERROR_INVALID_STATE  TLS connection was not initialized.
421  *
422  */
423 otError otBleSecureFlush(otInstance *aInstance);
424 
425 /**
426  * @}
427  *
428  */
429 
430 #ifdef __cplusplus
431 } // extern "C"
432 #endif
433 
434 #endif /* OPENTHREAD_BLE_SECURE_H_ */
435