Skip to content

Commit

Permalink
Added CASE Authenticated Tag (CAT) Support To the Commissioner APIs. (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
emargolis authored and pull[bot] committed Oct 18, 2023
1 parent 1fa6207 commit 2713685
Show file tree
Hide file tree
Showing 25 changed files with 321 additions and 112 deletions.
3 changes: 2 additions & 1 deletion examples/chip-tool/commands/common/CHIPCommand.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Project CHIP Authors
* Copyright (c) 2021-2022 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -224,6 +224,7 @@ CHIP_ERROR CHIPCommand::InitializeCommissioner(std::string key, chip::FabricId f

ReturnLogErrorOnFailure(ephemeralKey.Initialize());
ReturnLogErrorOnFailure(mCredIssuerCmds->GenerateControllerNOCChain(mCommissionerStorage.GetLocalNodeId(), fabricId,
mCommissionerStorage.GetCommissionerCATs(),
ephemeralKey, rcacSpan, icacSpan, nocSpan));
commissionerParams.operationalKeypair = &ephemeralKey;
commissionerParams.controllerRCAC = rcacSpan;
Expand Down
9 changes: 5 additions & 4 deletions examples/chip-tool/commands/common/CredentialIssuerCommands.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Project CHIP Authors
* Copyright (c) 2021-2022 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -63,14 +63,15 @@ class CredentialIssuerCommands
*
* @param[in] nodeId The desired NodeId for the generated NOC Chain - May be optional/unused in some implementations.
* @param[in] fabricId The desired FabricId for the generated NOC Chain - May be optional/unused in some implementations.
* @param[in] cats The desired CATs for the generated NOC Chain - May be optional/unused in some implementations.
* @param[in] keypair The desired Keypair for the generated NOC Chain - May be optional/unused in some implementations.
* @param[in,out] rcac Buffer to hold the Root Certificate of the generated NOC Chain.
* @param[in,out] icac Buffer to hold the Intermediate Certificate of the generated NOC Chain.
* @param[in,out] noc Buffer to hold the Leaf Certificate of the generated NOC Chain.
*
* @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error code.
*/
virtual CHIP_ERROR GenerateControllerNOCChain(chip::NodeId nodeId, chip::FabricId fabricId, chip::Crypto::P256Keypair & keypair,
chip::MutableByteSpan & rcac, chip::MutableByteSpan & icac,
chip::MutableByteSpan & noc) = 0;
virtual CHIP_ERROR GenerateControllerNOCChain(chip::NodeId nodeId, chip::FabricId fabricId, const chip::CATValues & cats,
chip::Crypto::P256Keypair & keypair, chip::MutableByteSpan & rcac,
chip::MutableByteSpan & icac, chip::MutableByteSpan & noc) = 0;
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Project CHIP Authors
* Copyright (c) 2021-2022 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -42,11 +42,11 @@ class ExampleCredentialIssuerCommands : public CredentialIssuerCommands
return CHIP_NO_ERROR;
}
chip::Controller::OperationalCredentialsDelegate * GetCredentialIssuer() override { return &mOpCredsIssuer; }
CHIP_ERROR GenerateControllerNOCChain(chip::NodeId nodeId, chip::FabricId fabricId, chip::Crypto::P256Keypair & keypair,
chip::MutableByteSpan & rcac, chip::MutableByteSpan & icac,
chip::MutableByteSpan & noc) override
CHIP_ERROR GenerateControllerNOCChain(chip::NodeId nodeId, chip::FabricId fabricId, const chip::CATValues & cats,
chip::Crypto::P256Keypair & keypair, chip::MutableByteSpan & rcac,
chip::MutableByteSpan & icac, chip::MutableByteSpan & noc) override
{
return mOpCredsIssuer.GenerateNOCChainAfterValidation(nodeId, fabricId, keypair.Pubkey(), rcac, icac, noc);
return mOpCredsIssuer.GenerateNOCChainAfterValidation(nodeId, fabricId, cats, keypair.Pubkey(), rcac, icac, noc);
}

private:
Expand Down
39 changes: 33 additions & 6 deletions examples/chip-tool/config/PersistentStorage.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Project CHIP Authors
* Copyright (c) 2020-2022 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -32,11 +32,12 @@ using namespace ::chip;
using namespace ::chip::Controller;
using namespace ::chip::Logging;

constexpr const char kDefaultSectionName[] = "Default";
constexpr const char kPortKey[] = "ListenPort";
constexpr const char kLoggingKey[] = "LoggingLevel";
constexpr const char kLocalNodeIdKey[] = "LocalNodeId";
constexpr LogCategory kDefaultLoggingLevel = kLogCategory_Detail;
constexpr const char kDefaultSectionName[] = "Default";
constexpr const char kPortKey[] = "ListenPort";
constexpr const char kLoggingKey[] = "LoggingLevel";
constexpr const char kLocalNodeIdKey[] = "LocalNodeId";
constexpr const char kCommissionerCATsKey[] = "CommissionerCATs";
constexpr LogCategory kDefaultLoggingLevel = kLogCategory_Detail;

std::string GetFilename(const char * name)
{
Expand Down Expand Up @@ -238,3 +239,29 @@ CHIP_ERROR PersistentStorage::SetLocalNodeId(NodeId value)
uint64_t nodeId = Encoding::LittleEndian::HostSwap64(value);
return SyncSetKeyValue(kLocalNodeIdKey, &nodeId, sizeof(nodeId));
}

CATValues PersistentStorage::GetCommissionerCATs()
{
CHIP_ERROR err = CHIP_NO_ERROR;
CATValues cats;
chip::CATValues::Serialized serializedCATs;
uint16_t size = chip::CATValues::kSerializedLength;
err = SyncGetKeyValue(kCommissionerCATsKey, serializedCATs, size);
if (err == CHIP_NO_ERROR && size == chip::CATValues::kSerializedLength)
{
err = cats.Deserialize(serializedCATs);
if (err == CHIP_NO_ERROR)
{
return cats;
}
}
return chip::kUndefinedCATs;
}

CHIP_ERROR PersistentStorage::SetCommissionerCATs(const CATValues & cats)
{
chip::CATValues::Serialized serializedCATs;
ReturnErrorOnFailure(cats.Serialize(serializedCATs));

return SyncSetKeyValue(kCommissionerCATsKey, serializedCATs, sizeof(serializedCATs));
}
8 changes: 7 additions & 1 deletion examples/chip-tool/config/PersistentStorage.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Project CHIP Authors
* Copyright (c) 2020-2022 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -42,6 +42,12 @@ class PersistentStorage : public chip::PersistentStorageDelegate
// Store local node id.
CHIP_ERROR SetLocalNodeId(chip::NodeId nodeId);

// Return the stored local device (commissioner) CASE Authenticated Tags (CATs).
chip::CATValues GetCommissionerCATs();

// Store local CATs.
CHIP_ERROR SetCommissionerCATs(const chip::CATValues & cats);

private:
CHIP_ERROR CommitConfig(const char * name);
inipp::Ini<char> mConfig;
Expand Down
6 changes: 3 additions & 3 deletions examples/platform/linux/AppMain.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright (c) 2021 Project CHIP Authors
* Copyright (c) 2021-2022 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -416,8 +416,8 @@ CHIP_ERROR InitCommissioner()
Crypto::P256Keypair ephemeralKey;
ReturnErrorOnFailure(ephemeralKey.Initialize());

ReturnErrorOnFailure(gOpCredsIssuer.GenerateNOCChainAfterValidation(gLocalId, /* fabricId = */ 1, ephemeralKey.Pubkey(),
rcacSpan, icacSpan, nocSpan));
ReturnErrorOnFailure(gOpCredsIssuer.GenerateNOCChainAfterValidation(gLocalId, /* fabricId = */ 1, chip::kUndefinedCATs,
ephemeralKey.Pubkey(), rcacSpan, icacSpan, nocSpan));

params.operationalKeypair = &ephemeralKey;
params.controllerRCAC = rcacSpan;
Expand Down
14 changes: 8 additions & 6 deletions src/controller/ExampleOperationalCredentialsIssuer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,20 +111,21 @@ CHIP_ERROR ExampleOperationalCredentialsIssuer::Initialize(PersistentStorageDele
}

CHIP_ERROR ExampleOperationalCredentialsIssuer::GenerateNOCChainAfterValidation(NodeId nodeId, FabricId fabricId,
const CATValues & cats,
const Crypto::P256PublicKey & pubkey,
MutableByteSpan & rcac, MutableByteSpan & icac,
MutableByteSpan & noc)
{
ChipDN noc_dn;
// TODO: Is there a way to make this code less error-prone for consumers?
// The consumer doesn't need to know the exact OID value.
noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, fabricId);
noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, nodeId);
// TODO: Add support for the CASE Authenticated Tags attributes
ReturnErrorOnFailure(noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, fabricId));
ReturnErrorOnFailure(noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, nodeId));
ReturnErrorOnFailure(noc_dn.AddCATs(cats));
ChipDN icac_dn;
icac_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipICAId, mIntermediateIssuerId);
ReturnErrorOnFailure(icac_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipICAId, mIntermediateIssuerId));
ChipDN rcac_dn;
rcac_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, mIssuerId);
ReturnErrorOnFailure(rcac_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, mIssuerId));

ChipLogProgress(Controller, "Generating NOC");
X509CertRequestParams noc_request = { 1, mNow, mNow + mValidity, noc_dn, icac_dn };
Expand Down Expand Up @@ -223,7 +224,8 @@ CHIP_ERROR ExampleOperationalCredentialsIssuer::GenerateNOCChain(const ByteSpan
ReturnErrorCodeIf(!rcac.Alloc(kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY);
MutableByteSpan rcacSpan(rcac.Get(), kMaxCHIPDERCertLength);

ReturnErrorOnFailure(GenerateNOCChainAfterValidation(assignedId, mNextFabricId, pubkey, rcacSpan, icacSpan, nocSpan));
ReturnErrorOnFailure(
GenerateNOCChainAfterValidation(assignedId, mNextFabricId, chip::kUndefinedCATs, pubkey, rcacSpan, icacSpan, nocSpan));

ChipLogProgress(Controller, "Providing certificate chain to the commissioner");
onCompletion->mCall(onCompletion->mContext, CHIP_NO_ERROR, nocSpan, icacSpan, rcacSpan, Optional<AesCcm128KeySpan>(),
Expand Down
8 changes: 5 additions & 3 deletions src/controller/ExampleOperationalCredentialsIssuer.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright (c) 2021 Project CHIP Authors
* Copyright (c) 2021-2022 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -31,6 +31,7 @@

#include <controller/OperationalCredentialsDelegate.h>
#include <crypto/CHIPCryptoPAL.h>
#include <lib/core/CASEAuthTag.h>
#include <lib/core/CHIPError.h>
#include <lib/core/CHIPPersistentStorageDelegate.h>
#include <lib/support/CodeUtils.h>
Expand Down Expand Up @@ -99,8 +100,9 @@ class DLL_EXPORT ExampleOperationalCredentialsIssuer : public OperationalCredent
* This method is expected to be called once all the checks (e.g. device attestation, CSR verification etc)
* have been completed, or not required (e.g. for self trusted devices such as commissioner apps).
*/
CHIP_ERROR GenerateNOCChainAfterValidation(NodeId nodeId, FabricId fabricId, const Crypto::P256PublicKey & pubkey,
MutableByteSpan & rcac, MutableByteSpan & icac, MutableByteSpan & noc);
CHIP_ERROR GenerateNOCChainAfterValidation(NodeId nodeId, FabricId fabricId, const CATValues & cats,
const Crypto::P256PublicKey & pubkey, MutableByteSpan & rcac, MutableByteSpan & icac,
MutableByteSpan & noc);

private:
Crypto::P256Keypair mIssuer;
Expand Down
6 changes: 3 additions & 3 deletions src/controller/java/AndroidDeviceControllerWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ void AndroidDeviceControllerWrapper::CallJavaMethod(const char * methodName, jin

AndroidDeviceControllerWrapper *
AndroidDeviceControllerWrapper::AllocateNew(JavaVM * vm, jobject deviceControllerObj, chip::NodeId nodeId,
chip::System::Layer * systemLayer,
const chip::CATValues & cats, chip::System::Layer * systemLayer,
chip::Inet::EndPointManager<Inet::TCPEndPoint> * tcpEndPointManager,
chip::Inet::EndPointManager<Inet::UDPEndPoint> * udpEndPointManager,
AndroidOperationalCredentialsIssuerPtr opCredsIssuerPtr, CHIP_ERROR * errInfoOnFailure)
Expand Down Expand Up @@ -163,8 +163,8 @@ AndroidDeviceControllerWrapper::AllocateNew(JavaVM * vm, jobject deviceControlle
return nullptr;
}

*errInfoOnFailure = opCredsIssuer->GenerateNOCChainAfterValidation(nodeId, /* fabricId = */ 1, ephemeralKey.Pubkey(), rcacSpan,
icacSpan, nocSpan);
*errInfoOnFailure = opCredsIssuer->GenerateNOCChainAfterValidation(nodeId, /* fabricId = */ 1, cats, ephemeralKey.Pubkey(),
rcacSpan, icacSpan, nocSpan);
if (*errInfoOnFailure != CHIP_NO_ERROR)
{
return nullptr;
Expand Down
4 changes: 2 additions & 2 deletions src/controller/java/AndroidDeviceControllerWrapper.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020-2021 Project CHIP Authors
* Copyright (c) 2020-2022 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -72,7 +72,7 @@ class AndroidDeviceControllerWrapper : public chip::Controller::DevicePairingDel
using AndroidOperationalCredentialsIssuerPtr = std::unique_ptr<chip::Controller::AndroidOperationalCredentialsIssuer>;

static AndroidDeviceControllerWrapper * AllocateNew(JavaVM * vm, jobject deviceControllerObj, chip::NodeId nodeId,
chip::System::Layer * systemLayer,
const chip::CATValues & cats, chip::System::Layer * systemLayer,
chip::Inet::EndPointManager<chip::Inet::TCPEndPoint> * tcpEndPointManager,
chip::Inet::EndPointManager<chip::Inet::UDPEndPoint> * udpEndPointManager,
AndroidOperationalCredentialsIssuerPtr opCredsIssuer,
Expand Down
12 changes: 8 additions & 4 deletions src/controller/java/AndroidOperationalCredentialsIssuer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "AndroidOperationalCredentialsIssuer.h"
#include <algorithm>
#include <credentials/CHIPCert.h>
#include <lib/core/CASEAuthTag.h>
#include <lib/core/CHIPTLV.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
Expand Down Expand Up @@ -76,15 +77,17 @@ CHIP_ERROR AndroidOperationalCredentialsIssuer::Initialize(PersistentStorageDele
}

CHIP_ERROR AndroidOperationalCredentialsIssuer::GenerateNOCChainAfterValidation(NodeId nodeId, FabricId fabricId,
const CATValues & cats,
const Crypto::P256PublicKey & pubkey,
MutableByteSpan & rcac, MutableByteSpan & icac,
MutableByteSpan & noc)
{
ChipDN noc_dn;
noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, fabricId);
noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, nodeId);
ReturnErrorOnFailure(noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, fabricId));
ReturnErrorOnFailure(noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, nodeId));
ReturnErrorOnFailure(noc_dn.AddCATs(cats));
ChipDN rcac_dn;
rcac_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, mIssuerId);
ReturnErrorOnFailure(rcac_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, mIssuerId));

ChipLogProgress(Controller, "Generating NOC");
chip::Credentials::X509CertRequestParams noc_request = { 1, mNow, mNow + mValidity, noc_dn, rcac_dn };
Expand Down Expand Up @@ -172,7 +175,8 @@ CHIP_ERROR AndroidOperationalCredentialsIssuer::GenerateNOCChain(const ByteSpan

MutableByteSpan icacSpan;

ReturnErrorOnFailure(GenerateNOCChainAfterValidation(assignedId, mNextFabricId, pubkey, rcacSpan, icacSpan, nocSpan));
ReturnErrorOnFailure(
GenerateNOCChainAfterValidation(assignedId, mNextFabricId, chip::kUndefinedCATs, pubkey, rcacSpan, icacSpan, nocSpan));

onCompletion->mCall(onCompletion->mContext, CHIP_NO_ERROR, nocSpan, ByteSpan(), rcacSpan, Optional<AesCcm128KeySpan>(),
Optional<NodeId>());
Expand Down
8 changes: 5 additions & 3 deletions src/controller/java/AndroidOperationalCredentialsIssuer.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright (c) 2021 Project CHIP Authors
* Copyright (c) 2021-2022 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -31,6 +31,7 @@

#include <controller/OperationalCredentialsDelegate.h>
#include <crypto/CHIPCryptoPAL.h>
#include <lib/core/CASEAuthTag.h>
#include <lib/core/CHIPError.h>
#include <lib/core/CHIPPersistentStorageDelegate.h>
#include <lib/support/CodeUtils.h>
Expand Down Expand Up @@ -81,8 +82,9 @@ class DLL_EXPORT AndroidOperationalCredentialsIssuer : public OperationalCredent
* This method is expected to be called once all the checks (e.g. device attestation, CSR verification etc)
* have been completed, or not required (e.g. for self trusted devices such as commissioner apps).
*/
CHIP_ERROR GenerateNOCChainAfterValidation(NodeId nodeId, FabricId fabricId, const Crypto::P256PublicKey & pubkey,
MutableByteSpan & rcac, MutableByteSpan & icac, MutableByteSpan & noc);
CHIP_ERROR GenerateNOCChainAfterValidation(NodeId nodeId, FabricId fabricId, const CATValues & cats,
const Crypto::P256PublicKey & pubkey, MutableByteSpan & rcac, MutableByteSpan & icac,
MutableByteSpan & noc);

private:
Crypto::P256Keypair mIssuer;
Expand Down
6 changes: 3 additions & 3 deletions src/controller/java/CHIPDeviceController-JNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,9 @@ JNI_METHOD(jlong, newDeviceController)(JNIEnv * env, jobject self)
ChipLogProgress(Controller, "newDeviceController() called");
std::unique_ptr<chip::Controller::AndroidOperationalCredentialsIssuer> opCredsIssuer(
new chip::Controller::AndroidOperationalCredentialsIssuer());
wrapper = AndroidDeviceControllerWrapper::AllocateNew(sJVM, self, kLocalDeviceId, &DeviceLayer::SystemLayer(),
DeviceLayer::TCPEndPointManager(), DeviceLayer::UDPEndPointManager(),
std::move(opCredsIssuer), &err);
wrapper = AndroidDeviceControllerWrapper::AllocateNew(sJVM, self, kLocalDeviceId, chip::kUndefinedCATs,
&DeviceLayer::SystemLayer(), DeviceLayer::TCPEndPointManager(),
DeviceLayer::UDPEndPointManager(), std::move(opCredsIssuer), &err);
SuccessOrExit(err);

// Create and start the IO thread. Must be called after Controller()->Init
Expand Down
Loading

0 comments on commit 2713685

Please sign in to comment.