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