Skip to content

Commit

Permalink
Implemented CASEServer to fetch credentials, and wait for SigmaR1 mes…
Browse files Browse the repository at this point in the history
…sage
  • Loading branch information
pan-apple committed May 13, 2021
1 parent 22365d8 commit bb08a09
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 15 deletions.
5 changes: 5 additions & 0 deletions src/app/server/Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <messaging/ExchangeMgr.h>
#include <platform/CHIPDeviceLayer.h>
#include <platform/KeyValueStoreManager.h>
#include <protocols/secure_channel/CASEServer.h>
#include <protocols/secure_channel/MessageCounterManager.h>
#include <setup_payload/SetupPayload.h>
#include <support/CodeUtils.h>
Expand Down Expand Up @@ -285,6 +286,7 @@ class ServerRendezvousAdvertisementDelegate : public RendezvousAdvertisementDele
DemoTransportMgr gTransports;
SecureSessionMgr gSessions;
RendezvousServer gRendezvousServer;
CASEServer gCASEServer;
Messaging::ExchangeManager gExchangeMgr;
ServerRendezvousAdvertisementDelegate gAdvDelegate;

Expand Down Expand Up @@ -567,6 +569,9 @@ void InitServer(AppDelegate * delegate)
err = gExchangeMgr.RegisterUnsolicitedMessageHandlerForProtocol(Protocols::ServiceProvisioning::Id, &gCallbacks);
VerifyOrExit(err == CHIP_NO_ERROR, err = CHIP_ERROR_NO_UNSOLICITED_MESSAGE_HANDLER);

err = gCASEServer.WaitForSessionEstablishment(&gExchangeMgr, &gTransports, &gSessions, &GetGlobalAdminPairingTable());
SuccessOrExit(err);

exit:
if (err != CHIP_NO_ERROR)
{
Expand Down
2 changes: 2 additions & 0 deletions src/protocols/secure_channel/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ static_library("secure_channel") {
output_name = "libSecureChannel"

sources = [
"CASEServer.cpp",
"CASEServer.h",
"CASESession.cpp",
"CASESession.h",
"PASESession.cpp",
Expand Down
119 changes: 119 additions & 0 deletions src/protocols/secure_channel/CASEServer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
*
* Copyright (c) 2021 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 <protocols/secure_channel/CASEServer.h>

#include <core/CHIPError.h>
#include <support/CodeUtils.h>
#include <support/SafeInt.h>
#include <transport/SecureSessionMgr.h>

using namespace ::chip::Inet;
using namespace ::chip::Transport;

namespace chip {

CHIP_ERROR CASEServer::WaitForSessionEstablishment(Messaging::ExchangeManager * exchangeManager, TransportMgrBase * transportMgr,
SecureSessionMgr * sessionMgr, Transport::AdminPairingTable * admins)
{
VerifyOrReturnError(transportMgr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(exchangeManager != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(sessionMgr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(admins != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

mSessionMgr = sessionMgr;
mAdmins = admins;
mExchangeManager = exchangeManager;

ReturnErrorOnFailure(mPairingSession.MessageDispatch().Init(transportMgr));

ReturnErrorOnFailure(
mExchangeManager->RegisterUnsolicitedMessageHandlerForType(Protocols::SecureChannel::MsgType::CASE_SigmaR1, this));
return CHIP_NO_ERROR;
}

CHIP_ERROR CASEServer::InitCASEHandshake(Messaging::ExchangeContext * ec)
{
ReturnErrorCodeIf(ec == nullptr, CHIP_ERROR_INVALID_ARGUMENT);

// Lookup the admin that corresponds to the CASE session setup request.
// Each admin provisions their own credentials on the device. So it's essential to
// use the correct operational certificates for CASE session setup.
mAdminId = ec->GetSecureSession().GetAdminId();
ReturnErrorCodeIf(mAdminId == Transport::kUndefinedAdminId, CHIP_ERROR_INVALID_ARGUMENT);

Transport::AdminPairingInfo * admin = mAdmins->FindAdminWithId(mAdminId);
ReturnErrorCodeIf(admin == nullptr, CHIP_ERROR_INVALID_ARGUMENT);

ReturnErrorOnFailure(admin->GetOperationalCertificateSet(mCertificates));

mCredentials.Release();
ReturnErrorOnFailure(mCredentials.Init(&mCertificates, mCertificates.GetCertCount()));

// Setup CASE state machine using the credentials for the current admin.
ReturnErrorOnFailure(mPairingSession.WaitForSessionEstablishment(&mCredentials, mNextKeyId++, this));

// Hand over the exchange context to the CASE session.
ec->SetDelegate(&mPairingSession);

return CHIP_NO_ERROR;
}

void CASEServer::OnMessageReceived(Messaging::ExchangeContext * ec, const PacketHeader & packetHeader,
const PayloadHeader & payloadHeader, System::PacketBufferHandle payload)
{
ReturnOnFailure(InitCASEHandshake(ec));
mPairingSession.OnMessageReceived(ec, packetHeader, payloadHeader, std::move(payload));

// TODO - Enable multiple concurrent CASE session establishment
// This will prevent CASEServer to process another CASE session establishment request until the current
// one completes (successfully or failed)
mExchangeManager->UnregisterUnsolicitedMessageHandlerForType(Protocols::SecureChannel::MsgType::CASE_SigmaR1);
}

void CASEServer::Cleanup()
{
// Let's re-register for CASE SigmaR1 message, so that the next CASE session setup request can be processed.
mExchangeManager->RegisterUnsolicitedMessageHandlerForType(Protocols::SecureChannel::MsgType::CASE_SigmaR1, this);
mAdminId = Transport::kUndefinedAdminId;
mCredentials.Release();
}

void CASEServer::OnSessionEstablishmentError(CHIP_ERROR err)
{
ChipLogProgress(AppServer, "CASE Session establishment failed: %s", ErrorStr(err));
Cleanup();
}

void CASEServer::OnSessionEstablished()
{
ChipLogProgress(AppServer, "CASE Session established. Setting up the secure channel.");
CHIP_ERROR err =
mSessionMgr->NewPairing(Optional<Transport::PeerAddress>::Value(mPairingSession.PeerConnection().GetPeerAddress()),
mPairingSession.PeerConnection().GetPeerNodeId(), &mPairingSession,
SecureSession::SessionRole::kResponder, mAdminId, nullptr);
if (err != CHIP_NO_ERROR)
{
ChipLogError(Ble, "Failed in setting up secure channel: err %s", ErrorStr(err));
OnSessionEstablishmentError(err);
return;
}

ChipLogProgress(AppServer, "CASE secure channel is available now.");
Cleanup();
}
} // namespace chip
78 changes: 78 additions & 0 deletions src/protocols/secure_channel/CASEServer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
*
* Copyright (c) 2021 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.
*/

#pragma once

#include <messaging/ExchangeDelegate.h>
#include <messaging/ExchangeMgr.h>
#include <protocols/secure_channel/CASESession.h>

namespace chip {

class CASEServer : public SessionEstablishmentDelegate, public Messaging::ExchangeDelegateBase
{
public:
CASEServer() {}
~CASEServer()
{
if (mExchangeManager != nullptr)
{
mExchangeManager->UnregisterUnsolicitedMessageHandlerForType(Protocols::SecureChannel::MsgType::CASE_SigmaR1);
}

mCredentials.Release();
}

CHIP_ERROR WaitForSessionEstablishment(Messaging::ExchangeManager * exchangeManager, TransportMgrBase * transportMgr,
SecureSessionMgr * sessionMgr, Transport::AdminPairingTable * admins);

//////////// SessionEstablishmentDelegate Implementation ///////////////
void OnSessionEstablishmentError(CHIP_ERROR error) override;
void OnSessionEstablished() override;

void Cleanup();

uint16_t GetNextKeyId() const { return mNextKeyId; }
void SetNextKeyId(uint16_t id) { mNextKeyId = id; }

//// ExchangeDelegate Implementation ////
void OnMessageReceived(Messaging::ExchangeContext * ec, const PacketHeader & packetHeader, const PayloadHeader & payloadHeader,
System::PacketBufferHandle payload) override;
void OnResponseTimeout(Messaging::ExchangeContext * ec) override {}
Messaging::ExchangeMessageDispatch * GetMessageDispatch(Messaging::ReliableMessageMgr * reliableMessageManager,
SecureSessionMgr * sessionMgr) override
{
return mPairingSession.GetMessageDispatch(reliableMessageManager, sessionMgr);
}

private:
Messaging::ExchangeManager * mExchangeManager = nullptr;

CASESession mPairingSession;
uint16_t mNextKeyId = 0;
SecureSessionMgr * mSessionMgr = nullptr;

Transport::AdminId mAdminId = Transport::kUndefinedAdminId;

Transport::AdminPairingTable * mAdmins = nullptr;
ChipCertificateSet mCertificates;
OperationalCredentialSet mCredentials;

CHIP_ERROR InitCASEHandshake(Messaging::ExchangeContext * ec);
};

} // namespace chip
26 changes: 21 additions & 5 deletions src/transport/AdminPairingTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <transport/AdminPairingTable.h>

namespace chip {
using namespace Credentials;
using namespace Crypto;

namespace Transport {

Expand All @@ -49,7 +51,7 @@ CHIP_ERROR AdminPairingInfo::StoreIntoKVS(PersistentStorageDelegate * kvs)
}
else
{
Crypto::P256Keypair keypair;
P256Keypair keypair;
SuccessOrExit(err = keypair.Initialize());
SuccessOrExit(err = keypair.Serialize(info->mOperationalKey));
}
Expand Down Expand Up @@ -115,7 +117,7 @@ CHIP_ERROR AdminPairingInfo::FetchFromKVS(PersistentStorageDelegate * kvs)

if (mOperationalKey == nullptr)
{
mOperationalKey = chip::Platform::New<Crypto::P256Keypair>();
mOperationalKey = chip::Platform::New<P256Keypair>();
}
VerifyOrExit(mOperationalKey != nullptr, err = CHIP_ERROR_NO_MEMORY);
SuccessOrExit(err = mOperationalKey->Deserialize(info->mOperationalKey));
Expand Down Expand Up @@ -160,13 +162,13 @@ CHIP_ERROR AdminPairingInfo::GenerateKey(AdminId id, char * key, size_t len)
return CHIP_NO_ERROR;
}

CHIP_ERROR AdminPairingInfo::SetOperationalKey(const Crypto::P256Keypair & key)
CHIP_ERROR AdminPairingInfo::SetOperationalKey(const P256Keypair & key)
{
Crypto::P256SerializedKeypair serialized;
P256SerializedKeypair serialized;
ReturnErrorOnFailure(key.Serialize(serialized));
if (mOperationalKey == nullptr)
{
mOperationalKey = chip::Platform::New<Crypto::P256Keypair>();
mOperationalKey = chip::Platform::New<P256Keypair>();
}
VerifyOrReturnError(mOperationalKey != nullptr, CHIP_ERROR_NO_MEMORY);
return mOperationalKey->Deserialize(serialized);
Expand Down Expand Up @@ -248,6 +250,20 @@ CHIP_ERROR AdminPairingInfo::SetOperationalCert(const ByteSpan & cert)
return CHIP_NO_ERROR;
}

CHIP_ERROR AdminPairingInfo::GetOperationalCertificateSet(ChipCertificateSet & certSet)
{
constexpr uint8_t kMaxNumCertsInOpCreds = 3;
ReturnErrorOnFailure(certSet.Init(kMaxNumCertsInOpCreds, kMaxChipCertSize * kMaxNumCertsInOpCreds));

ReturnErrorOnFailure(
certSet.LoadCert(mRootCert, mRootCertLen,
BitFlags<CertDecodeFlags>(CertDecodeFlags::kIsTrustAnchor).Set(CertDecodeFlags::kGenerateTBSHash)));
// TODO - Add support of ICA certificates
ReturnErrorOnFailure(
certSet.LoadCert(mOperationalCert, mOpCertLen, BitFlags<CertDecodeFlags>(CertDecodeFlags::kGenerateTBSHash)));
return CHIP_NO_ERROR;
}

AdminPairingInfo * AdminPairingTable::AssignAdminId(AdminId adminId)
{
for (size_t i = 0; i < CHIP_CONFIG_MAX_DEVICE_ADMINS; i++)
Expand Down
13 changes: 3 additions & 10 deletions src/transport/AdminPairingTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include <app/util/basic-types.h>
#include <core/CHIPPersistentStorageDelegate.h>
#include <credentials/CHIPCert.h>
#include <crypto/CHIPCryptoPAL.h>
#include <support/CHIPMem.h>
#include <support/DLLUtil.h>
Expand All @@ -42,11 +43,6 @@ constexpr char kAdminTableCountKey[] = "CHIPAdminNextId";

constexpr uint16_t kMaxChipCertSize = 600;

struct OperationalCredentials
{
uint32_t placeholder;
};

struct AccessControlList
{
uint32_t placeholder;
Expand Down Expand Up @@ -100,9 +96,7 @@ class DLL_EXPORT AdminPairingInfo
CHIP_ERROR SetOperationalCert(const chip::ByteSpan & cert);
CHIP_ERROR SetRootCert(const chip::ByteSpan & cert);

const OperationalCredentials & GetOperationalCreds() const { return mOpCred; }
OperationalCredentials & GetOperationalCreds() { return mOpCred; }
void SetOperationalCreds(const OperationalCredentials & creds) { mOpCred = creds; }
CHIP_ERROR GetOperationalCertificateSet(Credentials::ChipCertificateSet & certSet);

const AccessControlList & GetACL() const { return mACL; }
AccessControlList & GetACL() { return mACL; }
Expand Down Expand Up @@ -131,12 +125,11 @@ class DLL_EXPORT AdminPairingInfo
friend class AdminPairingTable;

private:
AdminId mAdmin = kUndefinedAdminId;
NodeId mNodeId = kUndefinedNodeId;
FabricId mFabricId = kUndefinedFabricId;
AdminId mAdmin = kUndefinedAdminId;
uint16_t mVendorId = kUndefinedVendorId;

OperationalCredentials mOpCred;
AccessControlList mACL;

Crypto::P256Keypair * mOperationalKey = nullptr;
Expand Down

0 comments on commit bb08a09

Please sign in to comment.