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 #if !OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
52 #error "BLE TCAT feature requires `OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE`"
53 #endif
54 
55 class BleSecure : public InstanceLocator, public MeshCoP::Tls::Extension, private NonCopyable
56 {
57 public:
58     /**
59      * Pointer to call when the secure BLE connection state changes.
60      *
61      *  Please see otHandleBleSecureConnect for details.
62      */
63     typedef otHandleBleSecureConnect ConnectCallback;
64 
65     /**
66      * Pointer to call when data was received over the TLS connection.
67      * If line mode is activated the function is called only after EOL has been received.
68      *
69      *  Please see otHandleBleSecureReceive for details.
70      */
71     typedef otHandleBleSecureReceive ReceiveCallback;
72 
73     /**
74      * Represents a TCAT command class.
75      */
76     typedef MeshCoP::TcatAgent::CommandClass CommandClass;
77 
78     /**
79      * Constructor initializes the object.
80      *
81      * @param[in]  aInstance    A reference to the OpenThread instance.
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     Error Start(ConnectCallback aConnectHandler, ReceiveCallback aReceiveHandler, bool aTlvMode, void *aContext);
99 
100     /**
101      * Enables the TCAT protocol over BLE Secure.
102      *
103      * @param[in]  aHandler          Callback to a function that is called when the join operation completes.
104      *
105      * @retval kErrorNone           Successfully started the BLE Secure Joiner role.
106      * @retval kErrorInvalidArgs    The aVendorInfo is invalid.
107      * @retval kErrorInvaidState    The BLE function has not been started or line mode is not selected.
108      */
109     Error TcatStart(MeshCoP::TcatAgent::JoinCallback aHandler);
110 
111     /**
112      * Set the TCAT Vendor Info object
113      *
114      * @param[in] aVendorInfo A pointer to the Vendor Information (must remain valid after the method call).
115      */
TcatSetVendorInfo(const MeshCoP::TcatAgent::VendorInfo & aVendorInfo)116     Error TcatSetVendorInfo(const MeshCoP::TcatAgent::VendorInfo &aVendorInfo)
117     {
118         return mTcatAgent.SetTcatVendorInfo(aVendorInfo);
119     }
120 
121     /**
122      * Stops the secure BLE agent.
123      */
124     void Stop(void);
125 
126     /**
127      * Initializes TLS session with a peer using an already open BLE connection.
128      *
129      * @retval kErrorNone  Successfully started TLS connection.
130      */
131     Error Connect(void);
132 
133     /**
134      * Stops the BLE and TLS connection.
135      */
136     void Disconnect(void);
137 
138     /**
139      * Indicates whether or not the TLS session is active (connected or connecting).
140      *
141      * @retval TRUE  If TLS session is active.
142      * @retval FALSE If TLS session is not active.
143      */
IsConnectionActive(void) const144     bool IsConnectionActive(void) const { return mTls.IsConnectionActive(); }
145 
146     /**
147      * Indicates whether or not the TLS session is connected.
148      *
149      * @retval TRUE   The TLS session is connected.
150      * @retval FALSE  The TLS session is not connected.
151      */
IsConnected(void) const152     bool IsConnected(void) const { return mTls.IsConnected(); }
153 
154     /**
155      * Indicates whether or not the TCAT agent is enabled.
156      *
157      * @retval TRUE   The TCAT agent is enabled.
158      * @retval FALSE  The TCAT agent is not enabled.
159      */
IsTcatEnabled(void) const160     bool IsTcatEnabled(void) const { return mTcatAgent.IsEnabled(); }
161 
162     /**
163      * Indicates whether or not a TCAT command class is authorized for use.
164      *
165      * @param[in]  aInstance  A pointer to an OpenThread instance.
166      * @param[in]  aCommandClass  A command class to subject to authorization check.
167      *
168      * @retval TRUE   The command class is authorized for use by the present TCAT commissioner.
169      * @retval FALSE  The command class is not authorized for use.
170      */
IsCommandClassAuthorized(CommandClass aCommandClass) const171     bool IsCommandClassAuthorized(CommandClass aCommandClass) const
172     {
173         return mTcatAgent.IsCommandClassAuthorized(aCommandClass);
174     }
175 
176     /**
177      * Sets the PSK.
178      *
179      * @param[in]  aPsk        A pointer to the PSK.
180      * @param[in]  aPskLength  The PSK length.
181      *
182      * @retval kErrorNone         Successfully set the PSK.
183      * @retval kErrorInvalidArgs  The PSK is invalid.
184      */
SetPsk(const uint8_t * aPsk,uint8_t aPskLength)185     Error SetPsk(const uint8_t *aPsk, uint8_t aPskLength) { return mTls.SetPsk(aPsk, aPskLength); }
186 
187     /**
188      * Sets the PSK.
189      *
190      * @param[in]  aPskd  A Joiner PSKd.
191      */
192     void SetPsk(const MeshCoP::JoinerPskd &aPskd);
193 
194     /**
195      * Sends a secure BLE message.
196      *
197      * @param[in]  aMessage        A pointer to the message to send.
198      *
199      * If the return value is kErrorNone, OpenThread takes ownership of @p aMessage, and the caller should no longer
200      * reference @p aMessage. If the return value is not kErrorNone, the caller retains ownership of @p aMessage,
201      * including freeing @p aMessage if the message buffer is no longer needed.
202      *
203      * @retval kErrorNone          Successfully sent message.
204      * @retval kErrorNoBufs        Failed to allocate buffer memory.
205      * @retval kErrorInvalidState  TLS connection was not initialized.
206      */
207     Error SendMessage(Message &aMessage);
208 
209     /**
210      * Sends a secure BLE data packet.
211      *
212      * @param[in]  aBuf            A pointer to the data to send as the Value of the TCAT Send Application Data TLV.
213      * @param[in]  aLength         A number indicating the length of the data buffer.
214      *
215      * @retval kErrorNone          Successfully sent data.
216      * @retval kErrorNoBufs        Failed to allocate buffer memory.
217      * @retval kErrorInvalidState  TLS connection was not initialized.
218      */
219     Error Send(uint8_t *aBuf, uint16_t aLength);
220 
221     /**
222      * Sends a secure BLE data packet containing a TCAT Send Application Data TLV.
223      *
224      * @param[in]  aBuf            A pointer to the data to send as the Value of the TCAT Send Application Data TLV.
225      * @param[in]  aLength         A number indicating the length of the data buffer.
226      *
227      * @retval kErrorNone          Successfully sent data.
228      * @retval kErrorNoBufs        Failed to allocate buffer memory.
229      * @retval kErrorInvalidState  TLS connection was not initialized.
230      */
231     Error SendApplicationTlv(uint8_t *aBuf, uint16_t aLength);
232 
233     /**
234      * Sends all remaining bytes in the send buffer.
235      *
236      * @retval kErrorNone          Successfully enqueued data into the output interface.
237      * @retval kErrorNoBufs        Failed to allocate buffer memory.
238      * @retval kErrorInvalidState  TLS connection was not initialized.
239      */
240     Error Flush(void);
241 
242     /**
243      * Used to pass data received over a BLE link to the secure BLE server.
244      *
245      * @param[in]  aBuf            A pointer to the data received.
246      * @param[in]  aLength         A number indicating the length of the data buffer.
247      */
248     Error HandleBleReceive(uint8_t *aBuf, uint16_t aLength);
249 
250     /**
251      * Used to notify the secure BLE server that a BLE Device has been connected.
252      *
253      * @param[in]  aConnectionId    The identifier of the open connection.
254      */
255     void HandleBleConnected(uint16_t aConnectionId);
256 
257     /**
258      * Used to notify the secure BLE server that the BLE Device has been disconnected.
259      *
260      * @param[in]  aConnectionId    The identifier of the open connection.
261      */
262     void HandleBleDisconnected(uint16_t aConnectionId);
263 
264     /**
265      * Used to notify the secure BLE server that the BLE Device has updated ATT_MTU size.
266      *
267      * @param[in]  aMtu             The updated ATT_MTU value.
268      */
269     Error HandleBleMtuUpdate(uint16_t aMtu);
270 
271     /**
272      * @brief Gets the Install Code Verify Status during the current session.
273      *
274      * @return TRUE The install code was correctly verfied.
275      * @return FALSE The install code was not verified.
276      */
GetInstallCodeVerifyStatus(void) const277     bool GetInstallCodeVerifyStatus(void) const { return mTcatAgent.GetInstallCodeVerifyStatus(); }
278 
279 private:
280     enum BleState : uint8_t
281     {
282         kStopped     = 0, // Ble secure not started.
283         kAdvertising = 1, // Ble secure not advertising.
284         kConnected   = 2, // Ble secure not connected.
285     };
286 
287     static constexpr uint8_t  kInitialMtuSize   = 23; // ATT_MTU
288     static constexpr uint8_t  kGattOverhead     = 3;  // BLE GATT payload fits MTU size - 3 bytes
289     static constexpr uint8_t  kPacketBufferSize = OT_BLE_ATT_MTU_MAX - kGattOverhead;
290     static constexpr uint16_t kTxBleHandle      = 0; // Characteristics Handle for TX (not used)
291 
292     static void HandleTlsConnectEvent(MeshCoP::Tls::ConnectEvent aEvent, void *aContext);
293     void        HandleTlsConnectEvent(MeshCoP::Tls::ConnectEvent aEvent);
294 
295     static void HandleTlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength);
296     void        HandleTlsReceive(uint8_t *aBuf, uint16_t aLength);
297 
298     void HandleTransmit(void);
299 
300     static Error HandleTransport(void *aContext, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
301     Error        HandleTransport(ot::Message &aMessage);
302 
303     using TxTask = TaskletIn<BleSecure, &BleSecure::HandleTransmit>;
304 
305     MeshCoP::Tls              mTls;
306     MeshCoP::TcatAgent        mTcatAgent;
307     Callback<ConnectCallback> mConnectCallback;
308     Callback<ReceiveCallback> mReceiveCallback;
309     bool                      mTlvMode;
310     ot::Message              *mReceivedMessage;
311     ot::Message              *mSendMessage;
312     ot::MessageQueue          mTransmitQueue;
313     TxTask                    mTransmitTask;
314     uint8_t                   mPacketBuffer[kPacketBufferSize];
315     BleState                  mBleState;
316     uint16_t                  mMtuSize;
317 };
318 
319 } // namespace Ble
320 } // namespace ot
321 
322 #endif // OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
323 
324 #endif // BLE_SECURE_HPP_
325