Skip to content

Commit

Permalink
Securing Rendezvous messages
Browse files Browse the repository at this point in the history
  • Loading branch information
vivien-apple committed Sep 15, 2020
1 parent 042d2b3 commit c191c77
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 21 deletions.
4 changes: 2 additions & 2 deletions src/controller/CHIPDeviceController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,17 +312,16 @@ CHIP_ERROR ChipDeviceController::SendMessage(void * appReqState, PacketBuffer *
CHIP_ERROR err = CHIP_NO_ERROR;

VerifyOrExit(mRemoteDeviceId.HasValue(), err = CHIP_ERROR_INCORRECT_STATE);
VerifyOrExit(IsSecurelyConnected(), err = CHIP_ERROR_INCORRECT_STATE);

mAppReqState = appReqState;

if (mRendezvousSession != NULL)
{
VerifyOrExit(IsConnected(), err = CHIP_ERROR_INCORRECT_STATE);
err = mRendezvousSession->SendMessage(buffer);
}
else
{
VerifyOrExit(IsSecurelyConnected(), err = CHIP_ERROR_INCORRECT_STATE);
err = mSessionManager->SendMessage(mRemoteDeviceId.Value(), buffer);
}
exit:
Expand Down Expand Up @@ -404,6 +403,7 @@ void ChipDeviceController::OnRendezvousError(CHIP_ERROR err)
void ChipDeviceController::OnRendezvousConnectionOpened()
{
mPairingSession = mRendezvousSession->GetPairingSession();
mConState = kConnectionState_SecureConnected;

if (mOnNewConnection)
{
Expand Down
14 changes: 12 additions & 2 deletions src/transport/BLE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,18 +127,28 @@ CHIP_ERROR BLE::DelegateConnection(Ble::BleLayer * bleLayer, const uint16_t conn

CHIP_ERROR BLE::SendMessage(const MessageHeader & header, const Transport::PeerAddress & address, System::PacketBuffer * msgBuf)
{
CHIP_ERROR err = CHIP_NO_ERROR;
CHIP_ERROR err = CHIP_NO_ERROR;
const size_t headerSize = header.EncodeSizeBytes();
size_t actualEncodedHeaderSize;

VerifyOrExit(address.GetTransportType() == Type::kBle, err = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(mState == State::kInitialized, err = CHIP_ERROR_INCORRECT_STATE);
VerifyOrExit(mBleEndPoint != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
VerifyOrExit(msgBuf->EnsureReservedSize(headerSize), err = CHIP_ERROR_NO_MEMORY);

msgBuf->SetStart(msgBuf->Start() - headerSize);

err = header.Encode(msgBuf->Start(), msgBuf->DataLength(), &actualEncodedHeaderSize);
SuccessOrExit(err);

VerifyOrExit(headerSize == actualEncodedHeaderSize, err = CHIP_ERROR_INTERNAL);

err = mBleEndPoint->Send(msgBuf);
msgBuf = nullptr;
SuccessOrExit(err);

exit:
if (msgBuf != NULL)
if (msgBuf != nullptr)
{
System::PacketBuffer::Free(msgBuf);
msgBuf = nullptr;
Expand Down
175 changes: 161 additions & 14 deletions src/transport/RendezvousSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <transport/BLE.h>
#include <transport/RendezvousSession.h>

static const size_t kMax_SecureSDU_Length = 1024;
static constexpr uint32_t kSpake2p_Iteration_Count = 50000;
static const char * kSpake2pKeyExchangeSalt = "SPAKE2P Key Exchange Salt";

Expand Down Expand Up @@ -64,13 +65,82 @@ RendezvousSession::~RendezvousSession()
mDelegate = nullptr;
}

CHIP_ERROR RendezvousSession::SendMessage(System::PacketBuffer * buffer)
CHIP_ERROR RendezvousSession::SendMessage(System::PacketBuffer * msgBuf)
{
// Rendezvous does not use a MessageHeader yet, but the Transport::Base API expects one, so
// let build an empty one for now.
CHIP_ERROR err = CHIP_NO_ERROR;
err = mPairingInProgress ? SendPairingMessage(msgBuf) : SendSecureMessage(msgBuf);
if (err != CHIP_NO_ERROR)
{
mPairingInProgress ? OnPairingError(err) : OnRendezvousError(err);
}

return err;
}

CHIP_ERROR RendezvousSession::SendPairingMessage(System::PacketBuffer * msgBuf)
{
CHIP_ERROR err = CHIP_NO_ERROR;
MessageHeader header;
size_t headerSize = 0;

VerifyOrExit(msgBuf != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(msgBuf->Next() == nullptr, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);

err = header.Decode(msgBuf->Start(), msgBuf->DataLength(), &headerSize);
SuccessOrExit(err);

msgBuf->ConsumeHead(headerSize);
err = mTransport->SendMessage(header, Transport::PeerAddress::BLE(), msgBuf);
SuccessOrExit(err);

exit:
return err;
}

CHIP_ERROR RendezvousSession::SendSecureMessage(System::PacketBuffer * msgBuf)
{
CHIP_ERROR err = CHIP_NO_ERROR;
MessageHeader header;
CHIP_ERROR err = mTransport->SendMessage(header, Transport::PeerAddress::BLE(), buffer);
const size_t headerSize = header.EncryptedHeaderSizeBytes();
size_t actualEncodedHeaderSize;
uint8_t * data = nullptr;
size_t totalLen = 0;
size_t taglen = 0;

VerifyOrExit(msgBuf != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(msgBuf->Next() == nullptr, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);
VerifyOrExit(msgBuf->TotalLength() < kMax_SecureSDU_Length, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);

header
.SetSourceNodeId(mParams.GetLocalNodeId()) //
.SetMessageId(mSecureMessageIndex) //
.SetEncryptionKeyID(mPairingSession.GetLocalKeyId()) //
.SetPayloadLength(headerSize + msgBuf->TotalLength());

VerifyOrExit(msgBuf->EnsureReservedSize(headerSize), err = CHIP_ERROR_NO_MEMORY);

msgBuf->SetStart(msgBuf->Start() - headerSize);
data = msgBuf->Start();
totalLen = msgBuf->TotalLength();

err = header.EncodeEncryptedHeader(data, totalLen, &actualEncodedHeaderSize);
SuccessOrExit(err);

err = mSecureSession.Encrypt(data, totalLen, data, header);
SuccessOrExit(err);

err = header.EncodeMACTag(&data[totalLen], kMaxTagLen, &taglen);
SuccessOrExit(err);

msgBuf->SetDataLength(totalLen + taglen);

err = mTransport->SendMessage(header, Transport::PeerAddress::BLE(), msgBuf);
SuccessOrExit(err);

mSecureMessageIndex++;
msgBuf = nullptr;

exit:
return err;
}

Expand All @@ -83,6 +153,15 @@ void RendezvousSession::OnPairingError(CHIP_ERROR err)
void RendezvousSession::OnPairingComplete()
{
mPairingInProgress = false;

CHIP_ERROR err = mPairingSession.DeriveSecureSession((const unsigned char *) kSpake2pI2RSessionInfo,
strlen(kSpake2pI2RSessionInfo), mSecureSession);
if (err != CHIP_NO_ERROR)
{
ChipLogError(Ble, "Failed to initialize a secure session: %s", ErrorStr(err));
return;
}

mDelegate->OnRendezvousConnectionOpened();
}

Expand Down Expand Up @@ -117,21 +196,89 @@ void RendezvousSession::OnRendezvousError(CHIP_ERROR err)
mDelegate->OnRendezvousError(err);
}

void RendezvousSession::OnRendezvousMessageReceived(PacketBuffer * buffer)
void RendezvousSession::OnRendezvousMessageReceived(PacketBuffer * msgBuf)
{
if (mPairingInProgress)
{
MessageHeader header;
size_t headerSize = 0;
header.Decode(buffer->Start(), buffer->DataLength(), &headerSize);
CHIP_ERROR err = CHIP_NO_ERROR;

buffer->ConsumeHead(headerSize);
mPairingSession.HandlePeerMessage(header, buffer);
err = mPairingInProgress ? HandlePairingMessage(msgBuf) : HandleSecureMessage(msgBuf);
if (err != CHIP_NO_ERROR)
{
mPairingInProgress ? OnPairingError(err) : OnRendezvousError(err);
}
else
}

CHIP_ERROR RendezvousSession::HandlePairingMessage(PacketBuffer * msgBuf)
{
CHIP_ERROR err = CHIP_NO_ERROR;
MessageHeader header;
size_t headerSize = 0;

err = header.Decode(msgBuf->Start(), msgBuf->DataLength(), &headerSize);
SuccessOrExit(err);

msgBuf->ConsumeHead(headerSize);

err = mPairingSession.HandlePeerMessage(header, msgBuf);
SuccessOrExit(err);

exit:
return err;
}

CHIP_ERROR RendezvousSession::HandleSecureMessage(PacketBuffer * msgBuf)
{
CHIP_ERROR err = CHIP_NO_ERROR;
MessageHeader header;
size_t headerSize = 0;
uint8_t * data = nullptr;
uint8_t * plainText = nullptr;
uint16_t len = 0;
size_t decodedSize = 0;
size_t taglen = 0;
System::PacketBuffer * origMsg = nullptr;

err = header.Decode(msgBuf->Start(), msgBuf->DataLength(), &headerSize);
SuccessOrExit(err);
msgBuf->ConsumeHead(headerSize);

headerSize = header.EncryptedHeaderSizeBytes();
data = msgBuf->Start();
len = msgBuf->TotalLength();

#if CHIP_SYSTEM_CONFIG_USE_LWIP
/* This is a workaround for the case where PacketBuffer payload is not
allocated as an inline buffer to PacketBuffer structure */
origMsg = msgBuf;
msgBuf = PacketBuffer::NewWithAvailableSize(len);
msgBuf->SetDataLength(len, msgBuf);
#endif
plainText = msgBuf->Start();

err = header.DecodeMACTag(&data[header.GetPayloadLength()], kMaxTagLen, &taglen);
SuccessOrExit(err);

len -= taglen;
msgBuf->SetDataLength(len);

err = mSecureSession.Decrypt(data, len, plainText, header);
SuccessOrExit(err);

err = header.DecodeEncryptedHeader(plainText, headerSize, &decodedSize);
SuccessOrExit(err);
VerifyOrExit(headerSize == decodedSize, err = CHIP_ERROR_INCORRECT_STATE);

msgBuf->ConsumeHead(headerSize);

mDelegate->OnRendezvousMessageReceived(msgBuf);
msgBuf = nullptr;

exit:
if (origMsg != nullptr)
{
mDelegate->OnRendezvousMessageReceived(buffer);
PacketBuffer::Free(origMsg);
}

return err;
}

CHIP_ERROR RendezvousSession::WaitForPairing(Optional<NodeId> nodeId, uint32_t setupPINCode)
Expand Down
13 changes: 10 additions & 3 deletions src/transport/RendezvousSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class RendezvousSession : public SecurePairingSessionDelegate, public Rendezvous
SecurePairingSession & GetPairingSession() { return mPairingSession; };

//////////// SecurePairingSessionDelegate Implementation ///////////////
virtual CHIP_ERROR SendMessage(System::PacketBuffer * buffer) override;
virtual CHIP_ERROR SendMessage(System::PacketBuffer * msgBuf) override;
virtual void OnPairingError(CHIP_ERROR err) override;
virtual void OnPairingComplete() override;

Expand All @@ -60,16 +60,23 @@ class RendezvousSession : public SecurePairingSessionDelegate, public Rendezvous
void OnRendezvousMessageReceived(PacketBuffer * buffer) override;

private:
CHIP_ERROR SendPairingMessage(System::PacketBuffer * msgBug);
CHIP_ERROR HandlePairingMessage(System::PacketBuffer * msgBug);
CHIP_ERROR Pair(Optional<NodeId> nodeId, uint32_t setupPINCode);
CHIP_ERROR WaitForPairing(Optional<NodeId> nodeId, uint32_t setupPINCode);

CHIP_ERROR SendSecureMessage(System::PacketBuffer * msgBug);
CHIP_ERROR HandleSecureMessage(System::PacketBuffer * msgBuf);

Transport::Base * mTransport = nullptr; ///< Underlying transport
RendezvousSessionDelegate * mDelegate = nullptr; ///< Underlying transport events
const RendezvousParameters mParams; ///< Rendezvous configuration

SecurePairingSession mPairingSession;
uint16_t mNextKeyId = 0;
bool mPairingInProgress = false;
SecureSession mSecureSession;
bool mPairingInProgress = false;
uint32_t mSecureMessageIndex = 0;
uint16_t mNextKeyId = 0;
};

} // namespace chip
Expand Down

0 comments on commit c191c77

Please sign in to comment.