Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / transport / NetworkProvisioning.cpp
1 /*
2  *
3  *    Copyright (c) 2020-2021 Project CHIP Authors
4  *
5  *    Licensed under the Apache License, Version 2.0 (the "License");
6  *    you may not use this file except in compliance with the License.
7  *    You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *    Unless required by applicable law or agreed to in writing, software
12  *    distributed under the License is distributed on an "AS IS" BASIS,
13  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *    See the License for the specific language governing permissions and
15  *    limitations under the License.
16  */
17
18 #include <core/CHIPEncoding.h>
19 #include <core/CHIPSafeCasts.h>
20 #include <platform/internal/DeviceNetworkInfo.h>
21 #include <protocols/Protocols.h>
22 #include <support/CodeUtils.h>
23 #include <support/ErrorStr.h>
24 #include <support/SafeInt.h>
25 #include <transport/NetworkProvisioning.h>
26 #include <transport/SecureSessionMgr.h>
27
28 #if CONFIG_DEVICE_LAYER
29 #include <platform/CHIPDeviceLayer.h>
30 #if defined(CHIP_DEVICE_LAYER_TARGET)
31 #define DEVICENETWORKPROVISIONING_HEADER <platform/CHIP_DEVICE_LAYER_TARGET/DeviceNetworkProvisioningDelegateImpl.h>
32 #include DEVICENETWORKPROVISIONING_HEADER
33 #endif
34 #endif
35
36 namespace chip {
37
38 constexpr char kAPInterfaceNamePrefix[]      = "ap";
39 constexpr char kLoobackInterfaceNamePrefix[] = "lo";
40
41 void NetworkProvisioning::Init(NetworkProvisioningDelegate * delegate)
42 {
43     mDelegate = delegate;
44 #if CONFIG_DEVICE_LAYER
45 #if defined(CHIP_DEVICE_LAYER_TARGET)
46     DeviceLayer::PlatformMgr().AddEventHandler(ConnectivityHandler, reinterpret_cast<intptr_t>(this));
47 #endif
48 #endif
49 }
50
51 NetworkProvisioning::~NetworkProvisioning()
52 {
53 #if CONFIG_DEVICE_LAYER
54 #if defined(CHIP_DEVICE_LAYER_TARGET)
55     DeviceLayer::PlatformMgr().RemoveEventHandler(ConnectivityHandler, reinterpret_cast<intptr_t>(this));
56 #endif
57 #endif
58 }
59
60 CHIP_ERROR NetworkProvisioning::HandleNetworkProvisioningMessage(uint8_t msgType, const System::PacketBufferHandle & msgBuf)
61 {
62     CHIP_ERROR err = CHIP_NO_ERROR;
63
64     switch (msgType)
65     {
66     case NetworkProvisioning::MsgTypes::kWiFiAssociationRequest: {
67         char SSID[chip::DeviceLayer::Internal::kMaxWiFiSSIDLength];
68         char passwd[chip::DeviceLayer::Internal::kMaxWiFiKeyLength];
69         Encoding::LittleEndian::BufferWriter bbufSSID(Uint8::from_char(SSID), chip::DeviceLayer::Internal::kMaxWiFiSSIDLength);
70         Encoding::LittleEndian::BufferWriter bbufPW(Uint8::from_char(passwd), chip::DeviceLayer::Internal::kMaxWiFiKeyLength);
71
72         const uint8_t * buffer = msgBuf->Start();
73         size_t len             = msgBuf->DataLength();
74         size_t offset          = 0;
75
76         ChipLogProgress(NetworkProvisioning, "Received kWiFiAssociationRequest.\n");
77
78         err = DecodeString(&buffer[offset], len - offset, bbufSSID, offset);
79         // TODO: Check for the error once network provisioning is moved to delegate calls
80
81         err = DecodeString(&buffer[offset], len - offset, bbufPW, offset);
82         // TODO: Check for the error once network provisioning is moved to delegate calls
83
84 #if CONFIG_DEVICE_LAYER
85 #if defined(CHIP_DEVICE_LAYER_TARGET)
86         DeviceLayer::DeviceNetworkProvisioningDelegateImpl deviceDelegate;
87         err = deviceDelegate.ProvisionWiFi(SSID, passwd);
88         SuccessOrExit(err);
89
90         if (DeviceLayer::ConnectivityMgr().IsWiFiStationConnected())
91         {
92             err = SendCurrentIPv4Address();
93         }
94 #endif
95 #endif
96     }
97     break;
98
99     case NetworkProvisioning::MsgTypes::kThreadAssociationRequest:
100         ChipLogProgress(NetworkProvisioning, "Received kThreadAssociationRequest");
101         err = DecodeThreadAssociationRequest(msgBuf);
102         break;
103
104     case NetworkProvisioning::MsgTypes::kIPAddressAssigned: {
105         ChipLogProgress(NetworkProvisioning, "Received kIPAddressAssigned");
106         if (!Inet::IPAddress::FromString(Uint8::to_const_char(msgBuf->Start()), msgBuf->DataLength(), mDeviceAddress))
107         {
108             ExitNow(err = CHIP_ERROR_INVALID_ADDRESS);
109         }
110     }
111     break;
112
113     default:
114         ExitNow(err = CHIP_ERROR_INVALID_MESSAGE_TYPE);
115         break;
116     };
117
118 exit:
119     if (mDelegate != nullptr)
120     {
121         if (err != CHIP_NO_ERROR)
122         {
123             ChipLogError(NetworkProvisioning, "Failed in HandleNetworkProvisioningMessage. error %s\n", ErrorStr(err));
124             mDelegate->OnNetworkProvisioningError(err);
125         }
126         else
127         {
128             // Network provisioning handshake requires only one message exchange in either direction.
129             // If the current message handling did not result in an error, network provisioning is
130             // complete.
131             mDelegate->OnNetworkProvisioningComplete();
132         }
133     }
134     return err;
135 }
136
137 size_t NetworkProvisioning::EncodedStringSize(const char * str)
138 {
139     return strlen(str) + sizeof(uint16_t);
140 }
141
142 CHIP_ERROR NetworkProvisioning::EncodeString(const char * str, Encoding::LittleEndian::BufferWriter & bbuf)
143 {
144     CHIP_ERROR err  = CHIP_NO_ERROR;
145     size_t length   = strlen(str);
146     uint16_t u16len = static_cast<uint16_t>(length);
147     VerifyOrExit(CanCastTo<uint16_t>(length), err = CHIP_ERROR_INVALID_ARGUMENT);
148
149     bbuf.Put16(u16len);
150     bbuf.Put(str);
151
152 exit:
153     return err;
154 }
155
156 CHIP_ERROR NetworkProvisioning::DecodeString(const uint8_t * input, size_t input_len, Encoding::LittleEndian::BufferWriter & bbuf,
157                                              size_t & consumed)
158 {
159     CHIP_ERROR err  = CHIP_NO_ERROR;
160     uint16_t length = 0;
161
162     VerifyOrExit(input_len >= sizeof(uint16_t), err = CHIP_ERROR_BUFFER_TOO_SMALL);
163     length   = chip::Encoding::LittleEndian::Get16(input);
164     consumed = sizeof(uint16_t);
165
166     VerifyOrExit(input_len - consumed >= length, err = CHIP_ERROR_BUFFER_TOO_SMALL);
167     bbuf.Put(&input[consumed], length);
168
169     consumed += bbuf.Needed();
170     bbuf.Put(static_cast<uint8_t>('\0'));
171
172     VerifyOrExit(bbuf.Fit(), err = CHIP_ERROR_BUFFER_TOO_SMALL);
173
174 exit:
175     return err;
176 }
177
178 CHIP_ERROR NetworkProvisioning::SendIPAddress(const Inet::IPAddress & addr)
179 {
180     char * addrStr;
181     CHIP_ERROR err                    = CHIP_NO_ERROR;
182     System::PacketBufferHandle buffer = System::PacketBufferHandle::New(Inet::kMaxIPAddressStringLength);
183     VerifyOrExit(!buffer.IsNull(), err = CHIP_ERROR_NO_MEMORY);
184     addrStr = addr.ToString(Uint8::to_char(buffer->Start()), buffer->AvailableDataLength());
185     buffer->SetDataLength(static_cast<uint16_t>(strlen(addrStr) + 1));
186
187     ChipLogProgress(NetworkProvisioning, "Sending IP Address. Delegate %p\n", mDelegate);
188     VerifyOrExit(mDelegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
189     VerifyOrExit(addrStr != nullptr, err = CHIP_ERROR_INVALID_ADDRESS);
190
191     err = mDelegate->SendSecureMessage(Protocols::NetworkProvisioning::Id, NetworkProvisioning::MsgTypes::kIPAddressAssigned,
192                                        std::move(buffer));
193     SuccessOrExit(err);
194
195 exit:
196     if (CHIP_NO_ERROR != err)
197         ChipLogError(NetworkProvisioning, "Failed in sending IP address. error %s\n", ErrorStr(err));
198     return err;
199 }
200
201 CHIP_ERROR NetworkProvisioning::SendCurrentIPv4Address()
202 {
203     for (chip::Inet::InterfaceAddressIterator it; it.HasCurrent(); it.Next())
204     {
205         char ifName[chip::Inet::InterfaceIterator::kMaxIfNameLength];
206         if (it.IsUp() && CHIP_NO_ERROR == it.GetInterfaceName(ifName, sizeof(ifName)) &&
207             memcmp(ifName, kAPInterfaceNamePrefix, sizeof(kAPInterfaceNamePrefix) - 1) &&
208             memcmp(ifName, kLoobackInterfaceNamePrefix, sizeof(kLoobackInterfaceNamePrefix) - 1))
209         {
210             chip::Inet::IPAddress addr = it.GetAddress();
211             if (addr.IsIPv4())
212             {
213                 return SendIPAddress(addr);
214             }
215         }
216     }
217
218     return CHIP_NO_ERROR;
219 }
220
221 CHIP_ERROR NetworkProvisioning::SendNetworkCredentials(const char * ssid, const char * passwd)
222 {
223     CHIP_ERROR err          = CHIP_NO_ERROR;
224     const size_t bufferSize = EncodedStringSize(ssid) + EncodedStringSize(passwd);
225     VerifyOrExit(CanCastTo<uint16_t>(bufferSize), err = CHIP_ERROR_INVALID_ARGUMENT);
226     {
227         Encoding::LittleEndian::PacketBufferWriter bbuf(MessagePacketBuffer::New(bufferSize), bufferSize);
228
229         ChipLogProgress(NetworkProvisioning, "Sending Network Creds. Delegate %p\n", mDelegate);
230         VerifyOrExit(mDelegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
231         VerifyOrExit(!bbuf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
232         SuccessOrExit(EncodeString(ssid, bbuf));
233         SuccessOrExit(EncodeString(passwd, bbuf));
234         VerifyOrExit(bbuf.Fit(), err = CHIP_ERROR_BUFFER_TOO_SMALL);
235
236         err = mDelegate->SendSecureMessage(Protocols::NetworkProvisioning::Id,
237                                            NetworkProvisioning::MsgTypes::kWiFiAssociationRequest, bbuf.Finalize());
238         SuccessOrExit(err);
239     }
240
241 exit:
242     if (CHIP_NO_ERROR != err)
243         ChipLogError(NetworkProvisioning, "Failed in sending Network Creds. error %s\n", ErrorStr(err));
244     return err;
245 }
246
247 CHIP_ERROR NetworkProvisioning::SendThreadCredentials(const DeviceLayer::Internal::DeviceNetworkInfo & threadData)
248 {
249     CHIP_ERROR err = CHIP_NO_ERROR;
250     /* clang-format off */
251     constexpr uint16_t credentialSize =
252         sizeof(threadData.ThreadNetworkName) +
253         sizeof(threadData.ThreadExtendedPANId) +
254         sizeof(threadData.ThreadMeshPrefix) +
255         sizeof(threadData.ThreadMasterKey) +
256         sizeof(threadData.ThreadPSKc) +
257         sizeof (uint16_t) + // threadData.ThereadPANId
258         4;                  // threadData.ThreadChannel, threadData.FieldPresent.ThreadExtendedPANId,
259                             // threadData.FieldPresent.ThreadMeshPrefix, threadData.FieldPresent.ThreadPSKc
260     /* clang-format on */
261     Encoding::LittleEndian::PacketBufferWriter bbuf(MessagePacketBuffer::New(credentialSize), credentialSize);
262
263     ChipLogProgress(NetworkProvisioning, "Sending Thread Credentials");
264     VerifyOrExit(mDelegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
265     VerifyOrExit(!bbuf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
266
267     bbuf.Put(threadData.ThreadNetworkName, sizeof(threadData.ThreadNetworkName));
268     bbuf.Put(threadData.ThreadExtendedPANId, sizeof(threadData.ThreadExtendedPANId));
269     bbuf.Put(threadData.ThreadMeshPrefix, sizeof(threadData.ThreadMeshPrefix));
270     bbuf.Put(threadData.ThreadMasterKey, sizeof(threadData.ThreadMasterKey));
271     bbuf.Put(threadData.ThreadPSKc, sizeof(threadData.ThreadPSKc));
272     bbuf.Put16(threadData.ThreadPANId);
273     bbuf.Put(threadData.ThreadChannel);
274     bbuf.Put(static_cast<uint8_t>(threadData.FieldPresent.ThreadExtendedPANId));
275     bbuf.Put(static_cast<uint8_t>(threadData.FieldPresent.ThreadMeshPrefix));
276     bbuf.Put(static_cast<uint8_t>(threadData.FieldPresent.ThreadPSKc));
277
278     VerifyOrExit(bbuf.Fit(), err = CHIP_ERROR_BUFFER_TOO_SMALL);
279     err = mDelegate->SendSecureMessage(Protocols::NetworkProvisioning::Id, NetworkProvisioning::MsgTypes::kThreadAssociationRequest,
280                                        bbuf.Finalize());
281
282 exit:
283     if (CHIP_NO_ERROR != err)
284         ChipLogError(NetworkProvisioning, "Failed to send Thread Credentials: %s", ErrorStr(err));
285     return err;
286 }
287
288 #ifdef CHIP_ENABLE_OPENTHREAD
289 CHIP_ERROR NetworkProvisioning::DecodeThreadAssociationRequest(const System::PacketBufferHandle & msgBuf)
290 {
291     CHIP_ERROR err                                       = CHIP_NO_ERROR;
292     DeviceLayer::Internal::DeviceNetworkInfo networkInfo = {};
293     uint8_t * data                                       = msgBuf->Start();
294     size_t dataLen                                       = msgBuf->DataLength();
295
296     VerifyOrExit(dataLen >= sizeof(networkInfo.ThreadNetworkName),
297                  ChipLogProgress(NetworkProvisioning, "Invalid network provision message"));
298     memcpy(networkInfo.ThreadNetworkName, data, sizeof(networkInfo.ThreadNetworkName));
299     data += sizeof(networkInfo.ThreadNetworkName);
300     dataLen -= sizeof(networkInfo.ThreadNetworkName);
301
302     VerifyOrExit(dataLen >= sizeof(networkInfo.ThreadExtendedPANId),
303                  ChipLogProgress(NetworkProvisioning, "Invalid network provision message"));
304     memcpy(networkInfo.ThreadExtendedPANId, data, sizeof(networkInfo.ThreadExtendedPANId));
305     data += sizeof(networkInfo.ThreadExtendedPANId);
306     dataLen -= sizeof(networkInfo.ThreadExtendedPANId);
307
308     VerifyOrExit(dataLen >= sizeof(networkInfo.ThreadMeshPrefix),
309                  ChipLogProgress(NetworkProvisioning, "Invalid network provision message"));
310     memcpy(networkInfo.ThreadMeshPrefix, data, sizeof(networkInfo.ThreadMeshPrefix));
311     data += sizeof(networkInfo.ThreadMeshPrefix);
312     dataLen -= sizeof(networkInfo.ThreadMeshPrefix);
313
314     VerifyOrExit(dataLen >= sizeof(networkInfo.ThreadMasterKey),
315                  ChipLogProgress(NetworkProvisioning, "Invalid network provision message"));
316     memcpy(networkInfo.ThreadMasterKey, data, sizeof(networkInfo.ThreadMasterKey));
317     data += sizeof(networkInfo.ThreadMasterKey);
318     dataLen -= sizeof(networkInfo.ThreadMasterKey);
319
320     VerifyOrExit(dataLen >= sizeof(networkInfo.ThreadPSKc),
321                  ChipLogProgress(NetworkProvisioning, "Invalid network provision message"));
322     memcpy(networkInfo.ThreadPSKc, data, sizeof(networkInfo.ThreadPSKc));
323     data += sizeof(networkInfo.ThreadPSKc);
324     dataLen -= sizeof(networkInfo.ThreadPSKc);
325
326     VerifyOrExit(dataLen >= sizeof(networkInfo.ThreadPANId),
327                  ChipLogProgress(NetworkProvisioning, "Invalid network provision message"));
328     networkInfo.ThreadPANId = Encoding::LittleEndian::Get16(data);
329     data += sizeof(networkInfo.ThreadPANId);
330     dataLen -= sizeof(networkInfo.ThreadPANId);
331
332     VerifyOrExit(dataLen >= sizeof(networkInfo.ThreadChannel),
333                  ChipLogProgress(NetworkProvisioning, "Invalid network provision message"));
334     networkInfo.ThreadChannel = data[0];
335     data += sizeof(networkInfo.ThreadChannel);
336     dataLen -= sizeof(networkInfo.ThreadChannel);
337
338     VerifyOrExit(dataLen >= 3, ChipLogProgress(NetworkProvisioning, "Invalid network provision message"));
339     networkInfo.FieldPresent.ThreadExtendedPANId = *data;
340     data++;
341     networkInfo.FieldPresent.ThreadMeshPrefix = *data;
342     data++;
343     networkInfo.FieldPresent.ThreadPSKc = *data;
344     data++;
345     networkInfo.NetworkId              = 0;
346     networkInfo.FieldPresent.NetworkId = true;
347
348 #if CONFIG_DEVICE_LAYER
349     // Start listening for OpenThread changes to be able to respond with SLAAC/On-Mesh IP Address
350     DeviceLayer::PlatformMgr().AddEventHandler(ConnectivityHandler, reinterpret_cast<intptr_t>(this));
351 #if defined(CHIP_DEVICE_LAYER_TARGET)
352     {
353         DeviceLayer::DeviceNetworkProvisioningDelegateImpl deviceDelegate;
354         err = deviceDelegate.ProvisionThread(networkInfo);
355     }
356 #endif
357 #endif
358
359 exit:
360     return err;
361 }
362 #else  // CHIP_ENABLE_OPENTHREAD
363 CHIP_ERROR NetworkProvisioning::DecodeThreadAssociationRequest(const System::PacketBufferHandle &)
364 {
365     return CHIP_ERROR_INVALID_MESSAGE_TYPE;
366 }
367 #endif // CHIP_ENABLE_OPENTHREAD
368
369 #if CONFIG_DEVICE_LAYER
370 void NetworkProvisioning::ConnectivityHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg)
371 {
372     NetworkProvisioning * session = reinterpret_cast<NetworkProvisioning *>(arg);
373
374     VerifyOrExit(session != nullptr, /**/);
375
376     if (event->Type == DeviceLayer::DeviceEventType::kInternetConnectivityChange &&
377         event->InternetConnectivityChange.IPv4 == DeviceLayer::kConnectivity_Established)
378     {
379         Inet::IPAddress addr;
380         Inet::IPAddress::FromString(event->InternetConnectivityChange.address, addr);
381         (void) session->SendIPAddress(addr);
382     }
383
384 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
385     if (event->Type == DeviceLayer::DeviceEventType::kThreadStateChange && event->ThreadStateChange.AddressChanged)
386     {
387         Inet::IPAddress addr;
388         SuccessOrExit(DeviceLayer::ThreadStackMgr().GetExternalIPv6Address(addr));
389         (void) session->SendIPAddress(addr);
390     }
391 #endif
392
393 exit:
394     return;
395 }
396 #endif
397
398 } // namespace chip