blob: 4458d27ca50a14883e2bcbfc0c761241cafda707 [file] [log] [blame]
/*
*
* Copyright (c) 2020 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "RendezvousSession.h"
#include <support/CodeUtils.h>
#include <support/ErrorStr.h>
#include <support/logging/CHIPLogging.h>
#include <system/SystemPacketBuffer.h>
using namespace ::chip;
extern CHIP_ERROR SetWiFiStationProvisioning(char * ssid, char * key);
BluetoothWidget * RendezvousSession::mVirtualLed;
Ble::BLEEndPoint * RendezvousSession::mEndPoint = nullptr;
bool RendezvousSession::mPairingInProgress = false;
SecurePairingSession RendezvousSession::mPairing;
static constexpr uint32_t kSpake2p_Iteration_Count = 50000;
static const char * kSpake2pKeyExchangeSalt = "SPAKE2P Key Exchange Salt";
extern void PairingComplete(Optional<NodeId> peerNodeId, uint16_t peerKeyId, uint16_t localKeyId, SecurePairingSession * pairing);
RendezvousSession::RendezvousSession(BluetoothWidget * virtualLed, uint32_t setUpPINCode, NodeId myNodeId)
{
mVirtualLed = virtualLed;
DeviceLayer::ConnectivityMgr().AddCHIPoBLEConnectionHandler(HandleConnectionOpened);
RendezvousSession::mPairing.WaitForPairing(setUpPINCode, kSpake2p_Iteration_Count,
(const unsigned char *) kSpake2pKeyExchangeSalt, strlen(kSpake2pKeyExchangeSalt),
Optional<NodeId>::Value(myNodeId), 0, this);
RendezvousSession::mPairingInProgress = true;
mSetUpPINCode = setUpPINCode;
mNodeId = myNodeId;
}
CHIP_ERROR RendezvousSession::OnNewMessageForPeer(System::PacketBuffer * buffer)
{
CHIP_ERROR err = CHIP_NO_ERROR;
VerifyOrExit(mEndPoint, err = CHIP_ERROR_INCORRECT_STATE);
err = mEndPoint->Send(buffer);
exit:
return err;
}
void RendezvousSession::OnPairingError(CHIP_ERROR error)
{
ChipLogError(Ble, "RendezvousSession: failed in pairing");
mPaired = false;
RendezvousSession::mPairing.WaitForPairing(mSetUpPINCode, kSpake2p_Iteration_Count,
(const unsigned char *) kSpake2pKeyExchangeSalt, strlen(kSpake2pKeyExchangeSalt),
Optional<NodeId>::Value(mNodeId), 0, this);
RendezvousSession::mPairingInProgress = true;
}
void RendezvousSession::OnPairingComplete(Optional<NodeId> peerNodeId, uint16_t peerKeyId, uint16_t localKeyId)
{
ChipLogProgress(Ble, "RendezvousSession: pairing complete");
mPaired = true;
RendezvousSession::mPairingInProgress = false;
PairingComplete(peerNodeId, peerKeyId, localKeyId, &RendezvousSession::mPairing);
}
CHIP_ERROR RendezvousSession::Send(const char * msg)
{
CHIP_ERROR err = CHIP_NO_ERROR;
System::PacketBuffer * buffer;
const size_t msgLen = strlen(msg);
VerifyOrExit(mEndPoint, err = CHIP_ERROR_INCORRECT_STATE);
buffer = System::PacketBuffer::NewWithAvailableSize(msgLen);
memcpy(buffer->Start(), msg, msgLen);
buffer->SetDataLength(msgLen);
err = mEndPoint->Send(buffer);
exit:
return err;
}
void RendezvousSession::HandleConnectionOpened(Ble::BLEEndPoint * endPoint)
{
ChipLogProgress(Ble, "RendezvousSession: Connection opened");
mEndPoint = endPoint;
mEndPoint->OnMessageReceived = HandleMessageReceived;
mEndPoint->OnConnectionClosed = HandleConnectionClosed;
mVirtualLed->Set(true);
}
void RendezvousSession::HandleConnectionClosed(Ble::BLEEndPoint * endPoint, BLE_ERROR err)
{
ChipLogProgress(Ble, "RendezvousSession: Connection closed (%s)", ErrorStr(err));
mEndPoint = nullptr;
mVirtualLed->Set(false);
}
void RendezvousSession::HandleMessageReceived(Ble::BLEEndPoint * endPoint, PacketBuffer * buffer)
{
if (RendezvousSession::mPairingInProgress)
{
MessageHeader header;
size_t headerSize = 0;
CHIP_ERROR err = header.Decode(buffer->Start(), buffer->DataLength(), &headerSize);
SuccessOrExit(err);
buffer->ConsumeHead(headerSize);
RendezvousSession::mPairing.HandlePeerMessage(header, buffer);
}
else
{
const size_t bufferLen = buffer->DataLength();
char msg[bufferLen];
msg[bufferLen] = 0;
memcpy(msg, buffer->Start(), bufferLen);
ChipLogProgress(Ble, "RendezvousSession: Receive message: %s", msg);
if ((bufferLen > 3) && (msg[0] == msg[1]) && (msg[0] == msg[bufferLen - 1]))
{
// WiFi credentials, of the form ‘::SSID:password:’, where ‘:’ can be any single ASCII character.
msg[1] = 0;
char * ssid = strtok(&msg[2], msg);
char * key = strtok(NULL, msg);
if (ssid && key)
{
ChipLogProgress(Ble, "RendezvousSession: SSID: %s, key: %s", ssid, key);
SetWiFiStationProvisioning(ssid, key);
}
else
{
ChipLogError(Ble, "RendezvousSession: SSID: %p, key: %p", ssid, key);
}
}
else
{
// Echo.
mEndPoint->Send(buffer);
}
}
exit:
return;
}