xref: /aosp_15_r20/external/openthread/src/core/radio/ble_secure.hpp (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
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 #ifndef BLE_SECURE_HPP_
30 #define BLE_SECURE_HPP_
31 
32 #include "openthread-core-config.h"
33 
34 #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
35 
36 #include <openthread/ble_secure.h>
37 
38 #include "meshcop/meshcop.hpp"
39 #include "meshcop/secure_transport.hpp"
40 #include "meshcop/tcat_agent.hpp"
41 
42 /**
43  * @file
44  *   Includes definitions for the secure BLE agent.
45  */
46 
47 namespace ot {
48 
49 namespace Ble {
50 
51 class BleSecure : public InstanceLocator, private NonCopyable
52 {
53 public:
54     /**
55      * Pointer to call when the secure BLE connection state changes.
56      *
57      *  Please see otHandleBleSecureConnect for details.
58      *
59      */
60     typedef otHandleBleSecureConnect ConnectCallback;
61 
62     /**
63      * Pointer to call when data was received over the TLS connection.
64      * If line mode is activated the function is called only after EOL has been received.
65      *
66      *  Please see otHandleBleSecureReceive for details.
67      *
68      */
69     typedef otHandleBleSecureReceive ReceiveCallback;
70 
71     /**
72      * Represents a TCAT command class.
73      *
74      */
75     typedef MeshCoP::TcatAgent::CommandClass CommandClass;
76 
77     /**
78      * Constructor initializes the object.
79      *
80      * @param[in]  aInstance    A reference to the OpenThread instance.
81      *
82      */
83     explicit BleSecure(Instance &aInstance);
84 
85     /**
86      * Starts the secure BLE agent.
87      *
88      * @param[in]  aConnectHandler  A pointer to a function that will be called when the connection
89      *                              state changes.
90      * @param[in]  aReceiveHandler  A pointer to a function that will be called once data has been received
91      *                              over the TLS connection.
92      * @param[in]  aTlvMode         A boolean value indicating if line mode shall be activated.
93      * @param[in]  aContext         A pointer to arbitrary context information. May be NULL if not used.
94      *
95      * @retval kErrorNone       Successfully started the BLE agent.
96      * @retval kErrorAlready    Already started.
97      *
98      */
99     Error Start(ConnectCallback aConnectHandler, ReceiveCallback aReceiveHandler, bool aTlvMode, void *aContext);
100 
101     /**
102      * Enables the TCAT protocol over BLE Secure.
103      *
104      * @param[in]  aHandler          Callback to a function that is called when the join operation completes.
105      *
106      * @retval kErrorNone           Successfully started the BLE Secure Joiner role.
107      * @retval kErrorInvalidArgs    The aVendorInfo is invalid.
108      * @retval kErrorInvaidState    The BLE function has not been started or line mode is not selected.
109      *
110      */
111     Error TcatStart(MeshCoP::TcatAgent::JoinCallback aHandler);
112 
113     /**
114      * Set the TCAT Vendor Info object
115      *
116      * @param[in] aVendorInfo A pointer to the Vendor Information (must remain valid after the method call).
117      *
118      */
TcatSetVendorInfo(const MeshCoP::TcatAgent::VendorInfo & aVendorInfo)119     Error TcatSetVendorInfo(const MeshCoP::TcatAgent::VendorInfo &aVendorInfo)
120     {
121         return mTcatAgent.SetTcatVendorInfo(aVendorInfo);
122     }
123 
124     /**
125      * Stops the secure BLE agent.
126      *
127      */
128     void Stop(void);
129 
130     /**
131      * Initializes TLS session with a peer using an already open BLE connection.
132      *
133      * @retval kErrorNone  Successfully started TLS connection.
134      *
135      */
136     Error Connect(void);
137 
138     /**
139      * Stops the BLE and TLS connection.
140      *
141      */
142     void Disconnect(void);
143 
144     /**
145      * Indicates whether or not the TLS session is active (connected or connecting).
146      *
147      * @retval TRUE  If TLS session is active.
148      * @retval FALSE If TLS session is not active.
149      *
150      */
IsConnectionActive(void) const151     bool IsConnectionActive(void) const { return mTls.IsConnectionActive(); }
152 
153     /**
154      * Indicates whether or not the TLS session is connected.
155      *
156      * @retval TRUE   The TLS session is connected.
157      * @retval FALSE  The TLS session is not connected.
158      *
159      */
IsConnected(void) const160     bool IsConnected(void) const { return mTls.IsConnected(); }
161 
162     /**
163      * Indicates whether or not the TCAT agent is enabled.
164      *
165      * @retval TRUE   The TCAT agent is enabled.
166      * @retval FALSE  The TCAT agent is not enabled.
167      *
168      */
IsTcatEnabled(void) const169     bool IsTcatEnabled(void) const { return mTcatAgent.IsEnabled(); }
170 
171     /**
172      * Indicates whether or not a TCAT command class is authorized.
173      *
174      * @param[in]  aInstance  A pointer to an OpenThread instance.
175      * @param[in]  aCommandClass  A command class to check.
176      *
177      * @retval TRUE   The command class is authorized.
178      * @retval FALSE  The command class is not authorized.
179      *
180      */
IsCommandClassAuthorized(CommandClass aCommandClass) const181     bool IsCommandClassAuthorized(CommandClass aCommandClass) const
182     {
183         return mTcatAgent.IsCommandClassAuthorized(aCommandClass);
184     }
185 
186     /**
187      * Sets the PSK.
188      *
189      * @param[in]  aPsk        A pointer to the PSK.
190      * @param[in]  aPskLength  The PSK length.
191      *
192      * @retval kErrorNone         Successfully set the PSK.
193      * @retval kErrorInvalidArgs  The PSK is invalid.
194      *
195      */
SetPsk(const uint8_t * aPsk,uint8_t aPskLength)196     Error SetPsk(const uint8_t *aPsk, uint8_t aPskLength) { return mTls.SetPsk(aPsk, aPskLength); }
197 
198     /**
199      * Sets the PSK.
200      *
201      * @param[in]  aPskd  A Joiner PSKd.
202      *
203      */
204     void SetPsk(const MeshCoP::JoinerPskd &aPskd);
205 
206 #ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
207     /**
208      * Sets the Pre-Shared Key (PSK) for TLS sessions identified by a PSK.
209      *
210      * TLS mode "TLS with AES 128 CCM 8" for secure BLE.
211      *
212      * @param[in]  aPsk          A pointer to the PSK.
213      * @param[in]  aPskLength    The PSK char length.
214      * @param[in]  aPskIdentity  The Identity Name for the PSK.
215      * @param[in]  aPskIdLength  The PSK Identity Length.
216      *
217      */
SetPreSharedKey(const uint8_t * aPsk,uint16_t aPskLength,const uint8_t * aPskIdentity,uint16_t aPskIdLength)218     void SetPreSharedKey(const uint8_t *aPsk, uint16_t aPskLength, const uint8_t *aPskIdentity, uint16_t aPskIdLength)
219     {
220         mTls.SetPreSharedKey(aPsk, aPskLength, aPskIdentity, aPskIdLength);
221     }
222 #endif // MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
223 
224 #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
225     /**
226      * Sets a X509 certificate with corresponding private key for TLS session.
227      *
228      * TLS mode "ECDHE ECDSA with AES 128 CCM 8" for secure BLE.
229      *
230      * @param[in]  aX509Cert          A pointer to the PEM formatted X509 PEM certificate.
231      * @param[in]  aX509Length        The length of certificate.
232      * @param[in]  aPrivateKey        A pointer to the PEM formatted private key.
233      * @param[in]  aPrivateKeyLength  The length of the private key.
234      *
235      */
SetCertificate(const uint8_t * aX509Cert,uint32_t aX509Length,const uint8_t * aPrivateKey,uint32_t aPrivateKeyLength)236     void SetCertificate(const uint8_t *aX509Cert,
237                         uint32_t       aX509Length,
238                         const uint8_t *aPrivateKey,
239                         uint32_t       aPrivateKeyLength)
240     {
241         mTls.SetCertificate(aX509Cert, aX509Length, aPrivateKey, aPrivateKeyLength);
242     }
243 
244     /**
245      * Sets the trusted top level CAs. It is needed for validate the certificate of the peer.
246      *
247      * TLS mode "ECDHE ECDSA with AES 128 CCM 8" for secure BLE.
248      *
249      * @param[in]  aX509CaCertificateChain  A pointer to the PEM formatted X509 CA chain.
250      * @param[in]  aX509CaCertChainLength   The length of chain.
251      *
252      */
SetCaCertificateChain(const uint8_t * aX509CaCertificateChain,uint32_t aX509CaCertChainLength)253     void SetCaCertificateChain(const uint8_t *aX509CaCertificateChain, uint32_t aX509CaCertChainLength)
254     {
255         mTls.SetCaCertificateChain(aX509CaCertificateChain, aX509CaCertChainLength);
256     }
257 #endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
258 
259 #if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
260     /**
261      * Returns the peer x509 certificate base64 encoded.
262      *
263      * TLS mode "ECDHE ECDSA with AES 128 CCM 8" for secure BLE.
264      *
265      * @param[out]  aPeerCert        A pointer to the base64 encoded certificate buffer.
266      * @param[out]  aCertLength      On input, the size the max size of @p aPeerCert.
267      *                               On output, the length of the base64 encoded peer certificate.
268      *
269      * @retval kErrorNone           Successfully get the peer certificate.
270      * @retval kErrorInvalidArgs    @p aInstance or @p aCertLength is invalid.
271      * @retval kErrorInvalidState   Not connected yet.
272      * @retval kErrorNoBufs         Can't allocate memory for certificate.
273      *
274      */
275     Error GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength);
276 #endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
277 
278 #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
279     /**
280      * Returns an attribute value identified by its OID from the subject
281      * of the peer x509 certificate. The peer OID is provided in binary format.
282      * The attribute length is set if the attribute was successfully read or zero
283      * if unsuccessful. The ASN.1 type as is set as defineded in the ITU-T X.690 standard
284      * if the attribute was successfully read.
285      *
286      * @param[in]      aOid                  A pointer to the OID to be found.
287      * @param[in]      aOidLength            The length of the OID.
288      * @param[out]     aAttributeBuffer      A pointer to the attribute buffer.
289      * @param[in,out]  aAttributeLength      On input, the size the max size of @p aAttributeBuffer.
290      *                                           On output, the length of the attribute written to the buffer.
291      * @param[out]  aAsn1Type                A pointer to the ASN.1 type of the attribute written to the buffer.
292      *
293      * @retval kErrorInvalidState   Not connected yet.
294      * @retval kErrorNone           Successfully read attribute.
295      * @retval kErrorNoBufs         Insufficient memory for storing the attribute value.
296      *
297      */
GetPeerSubjectAttributeByOid(const char * aOid,size_t aOidLength,uint8_t * aAttributeBuffer,size_t * aAttributeLength,int * aAsn1Type)298     Error GetPeerSubjectAttributeByOid(const char *aOid,
299                                        size_t      aOidLength,
300                                        uint8_t    *aAttributeBuffer,
301                                        size_t     *aAttributeLength,
302                                        int        *aAsn1Type)
303     {
304         return mTls.GetPeerSubjectAttributeByOid(aOid, aOidLength, aAttributeBuffer, aAttributeLength, aAsn1Type);
305     }
306 
307     /**
308      * Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of
309      * the peer x509 certificate, where the last digit x is set to aThreadOidDescriptor.
310      * The attribute length is set if the attribute was successfully read or zero if unsuccessful.
311      * Requires a connection to be active.
312      *
313      * @param[in]      aThreadOidDescriptor  The last digit of the Thread attribute OID.
314      * @param[out]     aAttributeBuffer      A pointer to the attribute buffer.
315      * @param[in,out]  aAttributeLength      On input, the size the max size of @p aAttributeBuffer.
316      *                                       On output, the length of the attribute written to the buffer.
317      *
318      * @retval kErrorNone             Successfully read attribute.
319      * @retval kErrorNotFound         The requested attribute was not found.
320      * @retval kErrorNoBufs           Insufficient memory for storing the attribute value.
321      * @retval kErrorInvalidState     Not connected yet.
322      * @retval kErrorNotImplemented   The value of aThreadOidDescriptor is >127.
323      * @retval kErrorParse            The certificate extensions could not be parsed.
324      *
325      */
GetThreadAttributeFromPeerCertificate(int aThreadOidDescriptor,uint8_t * aAttributeBuffer,size_t * aAttributeLength)326     Error GetThreadAttributeFromPeerCertificate(int      aThreadOidDescriptor,
327                                                 uint8_t *aAttributeBuffer,
328                                                 size_t  *aAttributeLength)
329     {
330         return mTls.GetThreadAttributeFromPeerCertificate(aThreadOidDescriptor, aAttributeBuffer, aAttributeLength);
331     }
332 #endif // defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
333 
334     /**
335      * Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of
336      * the own x509 certificate, where the last digit x is set to aThreadOidDescriptor.
337      * The attribute length is set if the attribute was successfully read or zero if unsuccessful.
338      * Requires a connection to be active.
339      *
340      * @param[in]      aThreadOidDescriptor  The last digit of the Thread attribute OID.
341      * @param[out]     aAttributeBuffer      A pointer to the attribute buffer.
342      * @param[in,out]  aAttributeLength      On input, the size the max size of @p aAttributeBuffer.
343      *                                       On output, the length of the attribute written to the buffer.
344      *
345      * @retval kErrorNone             Successfully read attribute.
346      * @retval kErrorNotFound         The requested attribute was not found.
347      * @retval kErrorNoBufs           Insufficient memory for storing the attribute value.
348      * @retval kErrorInvalidState     Not connected yet.
349      * @retval kErrorNotImplemented   The value of aThreadOidDescriptor is >127.
350      * @retval kErrorParse            The certificate extensions could not be parsed.
351      *
352      */
GetThreadAttributeFromOwnCertificate(int aThreadOidDescriptor,uint8_t * aAttributeBuffer,size_t * aAttributeLength)353     Error GetThreadAttributeFromOwnCertificate(int      aThreadOidDescriptor,
354                                                uint8_t *aAttributeBuffer,
355                                                size_t  *aAttributeLength)
356     {
357         return mTls.GetThreadAttributeFromOwnCertificate(aThreadOidDescriptor, aAttributeBuffer, aAttributeLength);
358     }
359 
360     /**
361      * Sets the authentication mode for the BLE secure connection. It disables or enables the verification
362      * of peer certificate.
363      *
364      * @param[in]  aVerifyPeerCertificate  true, if the peer certificate should be verified
365      *
366      */
SetSslAuthMode(bool aVerifyPeerCertificate)367     void SetSslAuthMode(bool aVerifyPeerCertificate) { mTls.SetSslAuthMode(aVerifyPeerCertificate); }
368 
369     /**
370      * Sends a secure BLE message.
371      *
372      * @param[in]  aMessage        A pointer to the message to send.
373      *
374      * If the return value is kErrorNone, OpenThread takes ownership of @p aMessage, and the caller should no longer
375      * reference @p aMessage. If the return value is not kErrorNone, the caller retains ownership of @p aMessage,
376      * including freeing @p aMessage if the message buffer is no longer needed.
377      *
378      * @retval kErrorNone          Successfully sent message.
379      * @retval kErrorNoBufs        Failed to allocate buffer memory.
380      * @retval kErrorInvalidState  TLS connection was not initialized.
381      *
382      */
383     Error SendMessage(Message &aMessage);
384 
385     /**
386      * Sends a secure BLE data packet.
387      *
388      * @param[in]  aBuf            A pointer to the data to send as the Value of the TCAT Send Application Data TLV.
389      * @param[in]  aLength         A number indicating the length of the data buffer.
390      *
391      * @retval kErrorNone          Successfully sent data.
392      * @retval kErrorNoBufs        Failed to allocate buffer memory.
393      * @retval kErrorInvalidState  TLS connection was not initialized.
394      *
395      */
396     Error Send(uint8_t *aBuf, uint16_t aLength);
397 
398     /**
399      * Sends a secure BLE data packet containing a TCAT Send Application Data TLV.
400      *
401      * @param[in]  aBuf            A pointer to the data to send as the Value of the TCAT Send Application Data TLV.
402      * @param[in]  aLength         A number indicating the length of the data buffer.
403      *
404      * @retval kErrorNone          Successfully sent data.
405      * @retval kErrorNoBufs        Failed to allocate buffer memory.
406      * @retval kErrorInvalidState  TLS connection was not initialized.
407      *
408      */
409     Error SendApplicationTlv(uint8_t *aBuf, uint16_t aLength);
410 
411     /**
412      * Sends all remaining bytes in the send buffer.
413      *
414      * @retval kErrorNone          Successfully enqueued data into the output interface.
415      * @retval kErrorNoBufs        Failed to allocate buffer memory.
416      * @retval kErrorInvalidState  TLS connection was not initialized.
417      *
418      */
419     Error Flush(void);
420 
421     /**
422      * Used to pass data received over a BLE link to the secure BLE server.
423      *
424      * @param[in]  aBuf            A pointer to the data received.
425      * @param[in]  aLength         A number indicating the length of the data buffer.
426      *
427      */
428     Error HandleBleReceive(uint8_t *aBuf, uint16_t aLength);
429 
430     /**
431      * Used to notify the secure BLE server that a BLE Device has been connected.
432      *
433      * @param[in]  aConnectionId    The identifier of the open connection.
434      *
435      */
436     void HandleBleConnected(uint16_t aConnectionId);
437 
438     /**
439      * Used to notify the secure BLE server that the BLE Device has been disconnected.
440      *
441      * @param[in]  aConnectionId    The identifier of the open connection.
442      *
443      */
444     void HandleBleDisconnected(uint16_t aConnectionId);
445 
446     /**
447      * Used to notify the secure BLE server that the BLE Device has updated ATT_MTU size.
448      *
449      * @param[in]  aMtu             The updated ATT_MTU value.
450      *
451      */
452     Error HandleBleMtuUpdate(uint16_t aMtu);
453 
454 private:
455     enum BleState : uint8_t
456     {
457         kStopped     = 0, // Ble secure not started.
458         kAdvertising = 1, // Ble secure not advertising.
459         kConnected   = 2, // Ble secure not connected.
460     };
461 
462     static constexpr uint8_t  kInitialMtuSize   = 23; // ATT_MTU
463     static constexpr uint8_t  kGattOverhead     = 3;  // BLE GATT payload fits MTU size - 3 bytes
464     static constexpr uint8_t  kPacketBufferSize = OT_BLE_ATT_MTU_MAX - kGattOverhead;
465     static constexpr uint16_t kTxBleHandle      = 0; // Characteristics Handle for TX (not used)
466 
467     static void HandleTlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent, void *aContext);
468     void        HandleTlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent);
469 
470     static void HandleTlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength);
471     void        HandleTlsReceive(uint8_t *aBuf, uint16_t aLength);
472 
473     void HandleTransmit(void);
474 
475     static Error HandleTransport(void *aContext, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
476     Error        HandleTransport(ot::Message &aMessage);
477 
478     using TxTask = TaskletIn<BleSecure, &BleSecure::HandleTransmit>;
479 
480     MeshCoP::SecureTransport  mTls;
481     MeshCoP::TcatAgent        mTcatAgent;
482     Callback<ConnectCallback> mConnectCallback;
483     Callback<ReceiveCallback> mReceiveCallback;
484     bool                      mTlvMode;
485     ot::Message              *mReceivedMessage;
486     ot::Message              *mSendMessage;
487     ot::MessageQueue          mTransmitQueue;
488     TxTask                    mTransmitTask;
489     uint8_t                   mPacketBuffer[kPacketBufferSize];
490     BleState                  mBleState;
491     uint16_t                  mMtuSize;
492 };
493 
494 } // namespace Ble
495 } // namespace ot
496 
497 #endif // OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
498 
499 #endif // BLE_SECURE_HPP_
500