diff --git a/examples/chip-tool/commands/common/CHIPCommand.cpp b/examples/chip-tool/commands/common/CHIPCommand.cpp index fe981615def3b8..d69c5be7408e5f 100644 --- a/examples/chip-tool/commands/common/CHIPCommand.cpp +++ b/examples/chip-tool/commands/common/CHIPCommand.cpp @@ -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"); @@ -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; diff --git a/examples/chip-tool/commands/common/CredentialIssuerCommands.h b/examples/chip-tool/commands/common/CredentialIssuerCommands.h index 0682aef4876da5..951ef86efceb40 100644 --- a/examples/chip-tool/commands/common/CredentialIssuerCommands.h +++ b/examples/chip-tool/commands/common/CredentialIssuerCommands.h @@ -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"); @@ -63,6 +63,7 @@ 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. @@ -70,7 +71,7 @@ class CredentialIssuerCommands * * @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; }; diff --git a/examples/chip-tool/commands/example/ExampleCredentialIssuerCommands.h b/examples/chip-tool/commands/example/ExampleCredentialIssuerCommands.h index 8d6f7deeeb30d8..74646c8b5f10ba 100644 --- a/examples/chip-tool/commands/example/ExampleCredentialIssuerCommands.h +++ b/examples/chip-tool/commands/example/ExampleCredentialIssuerCommands.h @@ -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"); @@ -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: diff --git a/examples/chip-tool/config/PersistentStorage.cpp b/examples/chip-tool/config/PersistentStorage.cpp index f5ef4eaf94ab6e..d580a80ece50a7 100644 --- a/examples/chip-tool/config/PersistentStorage.cpp +++ b/examples/chip-tool/config/PersistentStorage.cpp @@ -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"); @@ -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) { @@ -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)); +} diff --git a/examples/chip-tool/config/PersistentStorage.h b/examples/chip-tool/config/PersistentStorage.h index fd06571c1b6b61..35c5e8653d607f 100644 --- a/examples/chip-tool/config/PersistentStorage.h +++ b/examples/chip-tool/config/PersistentStorage.h @@ -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"); @@ -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 mConfig; diff --git a/examples/platform/linux/AppMain.cpp b/examples/platform/linux/AppMain.cpp index f8fb1dd1fb8bcd..a3901bd2c990da 100644 --- a/examples/platform/linux/AppMain.cpp +++ b/examples/platform/linux/AppMain.cpp @@ -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"); @@ -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; diff --git a/src/controller/ExampleOperationalCredentialsIssuer.cpp b/src/controller/ExampleOperationalCredentialsIssuer.cpp index 34a823cb872065..97b704be471dbc 100644 --- a/src/controller/ExampleOperationalCredentialsIssuer.cpp +++ b/src/controller/ExampleOperationalCredentialsIssuer.cpp @@ -111,6 +111,7 @@ 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) @@ -118,13 +119,13 @@ CHIP_ERROR ExampleOperationalCredentialsIssuer::GenerateNOCChainAfterValidation( 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 }; @@ -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(), diff --git a/src/controller/ExampleOperationalCredentialsIssuer.h b/src/controller/ExampleOperationalCredentialsIssuer.h index 96023a4945dc5a..47b6392caecc94 100644 --- a/src/controller/ExampleOperationalCredentialsIssuer.h +++ b/src/controller/ExampleOperationalCredentialsIssuer.h @@ -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"); @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -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; diff --git a/src/controller/java/AndroidDeviceControllerWrapper.cpp b/src/controller/java/AndroidDeviceControllerWrapper.cpp index f396492773051f..2c30deae8981a2 100644 --- a/src/controller/java/AndroidDeviceControllerWrapper.cpp +++ b/src/controller/java/AndroidDeviceControllerWrapper.cpp @@ -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 * tcpEndPointManager, chip::Inet::EndPointManager * udpEndPointManager, AndroidOperationalCredentialsIssuerPtr opCredsIssuerPtr, CHIP_ERROR * errInfoOnFailure) @@ -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; diff --git a/src/controller/java/AndroidDeviceControllerWrapper.h b/src/controller/java/AndroidDeviceControllerWrapper.h index d8887aecb42ec1..24c87433a0ff27 100644 --- a/src/controller/java/AndroidDeviceControllerWrapper.h +++ b/src/controller/java/AndroidDeviceControllerWrapper.h @@ -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"); @@ -72,7 +72,7 @@ class AndroidDeviceControllerWrapper : public chip::Controller::DevicePairingDel using AndroidOperationalCredentialsIssuerPtr = std::unique_ptr; 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 * tcpEndPointManager, chip::Inet::EndPointManager * udpEndPointManager, AndroidOperationalCredentialsIssuerPtr opCredsIssuer, diff --git a/src/controller/java/AndroidOperationalCredentialsIssuer.cpp b/src/controller/java/AndroidOperationalCredentialsIssuer.cpp index 7a6bdf23f29349..2555acfabd0f4c 100644 --- a/src/controller/java/AndroidOperationalCredentialsIssuer.cpp +++ b/src/controller/java/AndroidOperationalCredentialsIssuer.cpp @@ -19,6 +19,7 @@ #include "AndroidOperationalCredentialsIssuer.h" #include #include +#include #include #include #include @@ -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 }; @@ -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(), Optional()); diff --git a/src/controller/java/AndroidOperationalCredentialsIssuer.h b/src/controller/java/AndroidOperationalCredentialsIssuer.h index 54a5cfcb376005..b770f73833b38c 100644 --- a/src/controller/java/AndroidOperationalCredentialsIssuer.h +++ b/src/controller/java/AndroidOperationalCredentialsIssuer.h @@ -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"); @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -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; diff --git a/src/controller/java/CHIPDeviceController-JNI.cpp b/src/controller/java/CHIPDeviceController-JNI.cpp index 001bdf0445ca01..f4456bd11c888d 100644 --- a/src/controller/java/CHIPDeviceController-JNI.cpp +++ b/src/controller/java/CHIPDeviceController-JNI.cpp @@ -160,9 +160,9 @@ JNI_METHOD(jlong, newDeviceController)(JNIEnv * env, jobject self) ChipLogProgress(Controller, "newDeviceController() called"); std::unique_ptr 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 diff --git a/src/controller/python/OpCredsBinding.cpp b/src/controller/python/OpCredsBinding.cpp index 5dbf928dd7e2a9..25ffe5daa7aab4 100644 --- a/src/controller/python/OpCredsBinding.cpp +++ b/src/controller/python/OpCredsBinding.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2020-2022 Project CHIP Authors * Copyright (c) 2019-2020 Google LLC. * Copyright (c) 2013-2018 Nest Labs, Inc. * All rights reserved. @@ -59,10 +59,10 @@ class OperationalCredentialsAdapter : public OperationalCredentialsDelegate CHIP_ERROR Initialize(PersistentStorageDelegate & storageDelegate) { return mExampleOpCredsIssuer.Initialize(storageDelegate); } - CHIP_ERROR GenerateNOCChain(NodeId nodeId, FabricId fabricId, const Crypto::P256PublicKey & pubKey, MutableByteSpan & rcac, - MutableByteSpan & icac, MutableByteSpan & noc) + CHIP_ERROR GenerateNOCChain(NodeId nodeId, FabricId fabricId, const CATValues & cats, const Crypto::P256PublicKey & pubKey, + MutableByteSpan & rcac, MutableByteSpan & icac, MutableByteSpan & noc) { - return mExampleOpCredsIssuer.GenerateNOCChainAfterValidation(nodeId, fabricId, pubKey, rcac, icac, noc); + return mExampleOpCredsIssuer.GenerateNOCChainAfterValidation(nodeId, fabricId, cats, pubKey, rcac, icac, noc); } private: @@ -159,7 +159,8 @@ ChipError::StorageType pychip_OpCreds_AllocateController(OpCredsContext * contex ReturnErrorCodeIf(!rcac.Alloc(Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY.AsInteger()); MutableByteSpan rcacSpan(rcac.Get(), Controller::kMaxCHIPDERCertLength); - err = context->mAdapter->GenerateNOCChain(nodeId, fabricId, ephemeralKey.Pubkey(), rcacSpan, icacSpan, nocSpan); + err = context->mAdapter->GenerateNOCChain(nodeId, fabricId, chip::kUndefinedCATs, ephemeralKey.Pubkey(), rcacSpan, icacSpan, + nocSpan); VerifyOrReturnError(err == CHIP_NO_ERROR, err.AsInteger()); Controller::SetupParams initParams; diff --git a/src/controller/python/chip/configuration/__init__.py b/src/controller/python/chip/configuration/__init__.py index 3cb5ca535dfe2d..b64b5f0fa35de5 100644 --- a/src/controller/python/chip/configuration/__init__.py +++ b/src/controller/python/chip/configuration/__init__.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2021 Project CHIP Authors +# Copyright (c) 2021-2022 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. @@ -19,8 +19,10 @@ # Represents the node ID that is to be used when creating device # controllers/commissioning devices _local_node_id: Optional[int] = None +_local_cat: Optional[int] = None DEFAULT_LOCAL_NODE_ID = 12345 +DEFAULT_COMMISSIONER_CAT = 0xABCD0010 def SetLocalNodeId(node_id: int): @@ -44,3 +46,26 @@ def GetLocalNodeId() -> int: SetLocalNodeId(DEFAULT_LOCAL_NODE_ID) return _local_node_id + + +def SetCommissionerCAT(cat: int): + """Local (controllers/commissioning) device CASE Authenticated Tag (CAT). + Can be set at the start of scripts, however once set it cannot be reassigned. + """ + global _local_cat + + if _local_cat is not None: + raise Exception('Local CAT is already set.') + + _local_cat = cat + + +def GetCommissionerCAT() -> int: + """Returns the current local (controllers/commissioning) device CAT. If none has been set, + a default is set and used.""" + global _local_cat + + if _local_cat is None: + SetCommissionerCAT(DEFAULT_COMMISSIONER_CAT) + + return _local_cat diff --git a/src/controller/python/chip/internal/CommissionerImpl.cpp b/src/controller/python/chip/internal/CommissionerImpl.cpp index 94fe9b1dd27673..4ac48a0993f54a 100644 --- a/src/controller/python/chip/internal/CommissionerImpl.cpp +++ b/src/controller/python/chip/internal/CommissionerImpl.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2021 Project CHIP Authors + * Copyright (c) 2021-2022 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. @@ -93,7 +93,8 @@ pychip_internal_PairingDelegate_SetPairingCompleteCallback(ScriptDevicePairingDe gPairingDelegate.SetPairingCompleteCallback(callback); } -extern "C" chip::Controller::DeviceCommissioner * pychip_internal_Commissioner_New(uint64_t localDeviceId) +extern "C" chip::Controller::DeviceCommissioner * pychip_internal_Commissioner_New(uint64_t localDeviceId, + uint32_t localCommissionerCAT) { std::unique_ptr result; CHIP_ERROR err; @@ -138,8 +139,9 @@ extern "C" chip::Controller::DeviceCommissioner * pychip_internal_Commissioner_N chip::MutableByteSpan nocSpan(noc.Get(), chip::Controller::kMaxCHIPDERCertLength); chip::MutableByteSpan icacSpan(icac.Get(), chip::Controller::kMaxCHIPDERCertLength); chip::MutableByteSpan rcacSpan(rcac.Get(), chip::Controller::kMaxCHIPDERCertLength); - err = gOperationalCredentialsIssuer.GenerateNOCChainAfterValidation(localDeviceId, /* fabricId = */ 1, - ephemeralKey.Pubkey(), rcacSpan, icacSpan, nocSpan); + err = gOperationalCredentialsIssuer.GenerateNOCChainAfterValidation( + localDeviceId, /* fabricId = */ 1, { { localCommissionerCAT, chip::kUndefinedCAT, chip::kUndefinedCAT } }, + ephemeralKey.Pubkey(), rcacSpan, icacSpan, nocSpan); SuccessOrExit(err); commissionerParams.operationalCredentialsDelegate = &gOperationalCredentialsIssuer; diff --git a/src/controller/python/chip/internal/commissioner.py b/src/controller/python/chip/internal/commissioner.py index 7976c93c09c5ca..46766faeb374c9 100644 --- a/src/controller/python/chip/internal/commissioner.py +++ b/src/controller/python/chip/internal/commissioner.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2021 Project CHIP Authors +# Copyright (c) 2021-2022 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. @@ -14,6 +14,7 @@ # limitations under the License. # from chip.configuration import GetLocalNodeId +from chip.configuration import GetCommissionerCAT from chip.native import NativeLibraryHandleMethodArguments, GetLibraryHandle from enum import Enum from typing import Optional @@ -103,7 +104,7 @@ def _SetNativeCallSignatues(handle: ctypes.CDLL): setter = NativeLibraryHandleMethodArguments(handle) setter.Set('pychip_internal_Commissioner_New', - Commissioner_p, [ctypes.c_uint64]) + Commissioner_p, [ctypes.c_uint64, ctypes.c_uint32]) setter.Set('pychip_internal_Commissioner_Unpair', ctypes.c_uint32, [Commissioner_p, ctypes.c_uint64]) setter.Set('pychip_internal_Commissioner_BleConnectForPairing', @@ -119,7 +120,7 @@ def _SetNativeCallSignatues(handle: ctypes.CDLL): def GetCommissioner() -> Commissioner: """Gets a reference to the global commissioner singleton. - Uses the configuration GetLocalNodeId(). + Uses the configuration GetLocalNodeId() and GetCommissionerCAT(). """ global commissionerSingleton @@ -128,7 +129,8 @@ def GetCommissioner() -> Commissioner: handle = GetLibraryHandle() _SetNativeCallSignatues(handle) - native = handle.pychip_internal_Commissioner_New(GetLocalNodeId()) + native = handle.pychip_internal_Commissioner_New( + GetLocalNodeId(), GetCommissionerCAT()) if not native: raise Exception('Failed to create commissioner object.') diff --git a/src/credentials/CHIPCert.cpp b/src/credentials/CHIPCert.cpp index 4b92d0e9e79686..d053bc4e087d52 100644 --- a/src/credentials/CHIPCert.cpp +++ b/src/credentials/CHIPCert.cpp @@ -576,6 +576,19 @@ CHIP_ERROR ChipDN::AddAttribute(chip::ASN1::OID oid, uint64_t val) return CHIP_NO_ERROR; } +CHIP_ERROR ChipDN::AddCATs(const chip::CATValues & cats) +{ + for (auto & cat : cats.values) + { + if (cat != kUndefinedCAT) + { + ReturnErrorOnFailure(AddAttribute(chip::ASN1::kOID_AttributeType_ChipCASEAuthenticatedTag, cat)); + } + } + + return CHIP_NO_ERROR; +} + CHIP_ERROR ChipDN::AddAttribute(chip::ASN1::OID oid, CharSpan val, bool isPrintableString) { uint8_t rdnCount = RDNCount(); diff --git a/src/credentials/CHIPCert.h b/src/credentials/CHIPCert.h index 660d9e9c449ce4..872a6e59f9262d 100644 --- a/src/credentials/CHIPCert.h +++ b/src/credentials/CHIPCert.h @@ -230,6 +230,15 @@ class ChipDN **/ CHIP_ERROR AddAttribute(chip::ASN1::OID oid, uint64_t val); + /** + * @brief Add CASE Authenticated Tags (CATs) attributes to the DN. + * + * @param cats Array of CAT values. + * + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ + CHIP_ERROR AddCATs(const chip::CATValues & cats); + /** * @brief Add string attribute to the DN. * diff --git a/src/credentials/tests/TestChipCert.cpp b/src/credentials/tests/TestChipCert.cpp index ed14292b892706..d532e33cba72ac 100644 --- a/src/credentials/tests/TestChipCert.cpp +++ b/src/credentials/tests/TestChipCert.cpp @@ -185,6 +185,56 @@ static void TestChipCert_X509ToChip(nlTestSuite * inSuite, void * inContext) } } +static void TestChipCert_ChipDN(nlTestSuite * inSuite, void * inContext) +{ + const static char noc_rdn[] = "Test NOC"; + const static char noc_rdn2[] = "John"; + const static CATValues noc_cats = { { 0xABCD0001, chip::kUndefinedCAT, chip::kUndefinedCAT } }; + + ChipDN chip_dn; + NL_TEST_ASSERT(inSuite, + chip_dn.AddAttribute(chip::ASN1::kOID_AttributeType_CommonName, CharSpan(noc_rdn, strlen(noc_rdn)), false) == + CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, chip_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, 0xAAAABBBBCCCCDDDD) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, chip_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB00000FAB00001) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, + chip_dn.AddAttribute(chip::ASN1::kOID_AttributeType_GivenName, CharSpan(noc_rdn2, strlen(noc_rdn2)), true) == + CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, chip_dn.AddCATs(noc_cats) == CHIP_NO_ERROR); + + NL_TEST_ASSERT(inSuite, + chip_dn.AddAttribute(chip::ASN1::kOID_AttributeType_GivenName, CharSpan(noc_rdn2, strlen(noc_rdn2)), true) == + CHIP_ERROR_NO_MEMORY); + + uint8_t certType; + NL_TEST_ASSERT(inSuite, chip_dn.GetCertType(certType) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, certType == kCertType_Node); + + uint64_t certId; + NL_TEST_ASSERT(inSuite, chip_dn.GetCertChipId(certId) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, certId == 0xAAAABBBBCCCCDDDD); + + uint64_t fabricId; + NL_TEST_ASSERT(inSuite, chip_dn.GetCertFabricId(fabricId) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, fabricId == 0xFAB00000FAB00001); + + chip_dn.Clear(); + NL_TEST_ASSERT(inSuite, chip_dn.GetCertType(certType) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, chip_dn.IsEmpty() == true); + NL_TEST_ASSERT(inSuite, certType == kCertType_NotSpecified); + + CATValues noc_cats2; + chip::CATValues::Serialized serializedCATs; + NL_TEST_ASSERT(inSuite, noc_cats.Serialize(serializedCATs) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, noc_cats2.Deserialize(serializedCATs) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, memcmp(&noc_cats, &noc_cats2, chip::CATValues::kSerializedLength) == 0); + + CATValues noc_cats3 = { { 0xABCD0001, 0xFFEEAA00, 0x0001F012 } }; + NL_TEST_ASSERT(inSuite, noc_cats3.Serialize(serializedCATs) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, noc_cats2.Deserialize(serializedCATs) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, memcmp(&noc_cats3, &noc_cats2, chip::CATValues::kSerializedLength) == 0); +} + static void TestChipCert_CertValidation(nlTestSuite * inSuite, void * inContext) { CHIP_ERROR err; @@ -739,7 +789,7 @@ static void TestChipCert_GenerateRootCert(nlTestSuite * inSuite, void * inContex ChipCertificateData certData; ChipDN root_dn; - root_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, 0xabcdabcd); + NL_TEST_ASSERT(inSuite, root_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, 0xabcdabcd) == CHIP_NO_ERROR); X509CertRequestParams root_params = { 1234, 631161876, 729942000, root_dn, root_dn }; MutableByteSpan signed_cert_span(signed_cert); @@ -754,22 +804,27 @@ static void TestChipCert_GenerateRootCert(nlTestSuite * inSuite, void * inContex // Test error case: root cert subject provided ICA OID Attribute. root_params.SubjectDN.Clear(); - root_params.SubjectDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipICAId, 0xabcdabcd); + NL_TEST_ASSERT(inSuite, + root_params.SubjectDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipICAId, 0xabcdabcd) == CHIP_NO_ERROR); root_params.IssuerDN.Clear(); - root_params.IssuerDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipICAId, 0xabcdabcd); + NL_TEST_ASSERT(inSuite, + root_params.IssuerDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipICAId, 0xabcdabcd) == CHIP_NO_ERROR); MutableByteSpan signed_cert_span1(signed_cert); NL_TEST_ASSERT(inSuite, NewRootX509Cert(root_params, keypair, signed_cert_span1) == CHIP_ERROR_INVALID_ARGUMENT); // Test error case: root cert provided different subject and issuer DNs. root_params.SubjectDN.Clear(); - root_params.SubjectDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, 0xabcdabcd); + NL_TEST_ASSERT(inSuite, + root_params.SubjectDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, 0xabcdabcd) == CHIP_NO_ERROR); root_params.IssuerDN.Clear(); - root_params.IssuerDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, 0xffffeeee); + NL_TEST_ASSERT(inSuite, + root_params.IssuerDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, 0xffffeeee) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, NewRootX509Cert(root_params, keypair, signed_cert_span1) == CHIP_ERROR_INVALID_ARGUMENT); // Test that serial number cannot be negative root_params.IssuerDN.Clear(); - root_params.IssuerDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, 0xabcdabcd); + NL_TEST_ASSERT(inSuite, + root_params.IssuerDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, 0xabcdabcd) == CHIP_NO_ERROR); root_params.SerialNumber = -1; NL_TEST_ASSERT(inSuite, NewRootX509Cert(root_params, keypair, signed_cert_span1) == CHIP_ERROR_INVALID_ARGUMENT); } @@ -788,8 +843,8 @@ static void TestChipCert_GenerateRootFabCert(nlTestSuite * inSuite, void * inCon MutableByteSpan outCert(outCertBuf); ChipDN root_dn; - root_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, 0xabcdabcd); - root_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xabcd); + NL_TEST_ASSERT(inSuite, root_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, 0xabcdabcd) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, root_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xabcd) == CHIP_NO_ERROR); X509CertRequestParams root_params_fabric = { 1234, 631161876, 729942000, root_dn, root_dn }; @@ -815,9 +870,9 @@ static void TestChipCert_GenerateICACert(nlTestSuite * inSuite, void * inContext ChipCertificateData certData; ChipDN ica_dn; - ica_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipICAId, 0xABCDABCDABCDABCD); + NL_TEST_ASSERT(inSuite, ica_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipICAId, 0xABCDABCDABCDABCD) == CHIP_NO_ERROR); ChipDN issuer_dn; - issuer_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, 0x43215678FEDCABCD); + NL_TEST_ASSERT(inSuite, issuer_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, 0x43215678FEDCABCD) == CHIP_NO_ERROR); X509CertRequestParams ica_params = { 1234, 631161876, 729942000, ica_dn, issuer_dn }; P256Keypair ica_keypair; @@ -832,15 +887,19 @@ static void TestChipCert_GenerateICACert(nlTestSuite * inSuite, void * inContext // Test error case: ICA cert subject provided a node ID attribute ica_params.SubjectDN.Clear(); - ica_params.SubjectDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, 0xABCDABCDABCDABCD); - ica_params.SubjectDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB00000FAB00001); + NL_TEST_ASSERT( + inSuite, ica_params.SubjectDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, 0xABCDABCDABCDABCD) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, + ica_params.SubjectDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB00000FAB00001) == + CHIP_NO_ERROR); MutableByteSpan signed_cert_span1(signed_cert); NL_TEST_ASSERT(inSuite, NewICAX509Cert(ica_params, ica_keypair.Pubkey(), keypair, signed_cert_span1) == CHIP_ERROR_INVALID_ARGUMENT); // Test that serial number cannot be negative ica_params.SubjectDN.Clear(); - ica_params.SubjectDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipICAId, 0xABCDABCDABCDABCD); + NL_TEST_ASSERT( + inSuite, ica_params.SubjectDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipICAId, 0xABCDABCDABCDABCD) == CHIP_NO_ERROR); ica_params.SerialNumber = -1; NL_TEST_ASSERT(inSuite, NewICAX509Cert(ica_params, ica_keypair.Pubkey(), keypair, signed_cert_span1) == CHIP_ERROR_INVALID_ARGUMENT); @@ -860,10 +919,10 @@ static void TestChipCert_GenerateNOCRoot(nlTestSuite * inSuite, void * inContext ChipCertificateData certData; ChipDN noc_dn; - noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, 0xABCDABCDABCDABCD); - noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB00000FAB00001); + NL_TEST_ASSERT(inSuite, noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, 0xABCDABCDABCDABCD) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB00000FAB00001) == CHIP_NO_ERROR); ChipDN issuer_dn; - issuer_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, 0x8888999944442222); + NL_TEST_ASSERT(inSuite, issuer_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, 0x8888999944442222) == CHIP_NO_ERROR); X509CertRequestParams noc_params = { 123456, 631161876, 729942000, noc_dn, issuer_dn }; P256Keypair noc_keypair; @@ -879,7 +938,9 @@ static void TestChipCert_GenerateNOCRoot(nlTestSuite * inSuite, void * inContext // Test error case: NOC cert subject doesn't have NodeId attribute noc_params.SubjectDN.Clear(); - noc_params.SubjectDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB00000FAB00001); + NL_TEST_ASSERT(inSuite, + noc_params.SubjectDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB00000FAB00001) == + CHIP_NO_ERROR); MutableByteSpan signed_cert_span1(signed_cert, sizeof(signed_cert)); NL_TEST_ASSERT(inSuite, @@ -888,7 +949,8 @@ static void TestChipCert_GenerateNOCRoot(nlTestSuite * inSuite, void * inContext // Test error case: NOC cert subject doesn't have fabric ID attribute noc_params.SubjectDN.Clear(); - noc_params.SubjectDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, 0xABCDABCDABCDABCD); + NL_TEST_ASSERT( + inSuite, noc_params.SubjectDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, 0xABCDABCDABCDABCD) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, NewNodeOperationalX509Cert(noc_params, noc_keypair.Pubkey(), keypair, signed_cert_span1) == @@ -896,11 +958,17 @@ static void TestChipCert_GenerateNOCRoot(nlTestSuite * inSuite, void * inContext // Test error case: issuer cert DN type is Node certificate noc_params.SubjectDN.Clear(); - noc_params.SubjectDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, 0xABCDABCDABCDABCD); - noc_params.SubjectDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB00000FAB00001); + NL_TEST_ASSERT( + inSuite, noc_params.SubjectDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, 0xABCDABCDABCDABCD) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, + noc_params.SubjectDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB00000FAB00001) == + CHIP_NO_ERROR); noc_params.IssuerDN.Clear(); - noc_params.IssuerDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, 0x8888999944442222); - noc_params.IssuerDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB00000FAB00001); + NL_TEST_ASSERT( + inSuite, noc_params.IssuerDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, 0x8888999944442222) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, + noc_params.IssuerDN.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB00000FAB00001) == + CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, NewNodeOperationalX509Cert(noc_params, noc_keypair.Pubkey(), keypair, signed_cert_span1) == @@ -928,15 +996,21 @@ static void TestChipCert_GenerateNOCICA(nlTestSuite * inSuite, void * inContext) const static char noc_name_rdn[] = "Smith"; ChipDN noc_dn; - noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_CommonName, CharSpan(noc_cn_rdn, strlen(noc_cn_rdn)), false); - noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, 0xAAAABBBBCCCCDDDD); - noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB00000FAB00001); - noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_GivenName, CharSpan(noc_givenname_rdn, strlen(noc_givenname_rdn)), true); - noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_Name, CharSpan(noc_name_rdn, strlen(noc_name_rdn)), true); + NL_TEST_ASSERT(inSuite, + noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_CommonName, CharSpan(noc_cn_rdn, strlen(noc_cn_rdn)), + false) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, 0xAAAABBBBCCCCDDDD) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB00000FAB00001) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, + noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_GivenName, + CharSpan(noc_givenname_rdn, strlen(noc_givenname_rdn)), true) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, + noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_Name, CharSpan(noc_name_rdn, strlen(noc_name_rdn)), true) == + CHIP_NO_ERROR); ChipDN ica_dn; - ica_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipICAId, 0x8888999944442222); - ica_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB00000FAB00001); + NL_TEST_ASSERT(inSuite, ica_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipICAId, 0x8888999944442222) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, ica_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB00000FAB00001) == CHIP_NO_ERROR); X509CertRequestParams noc_params = { 12348765, 631161876, 729942000, noc_dn, ica_dn }; P256Keypair noc_keypair; @@ -963,8 +1037,8 @@ static void TestChipCert_VerifyGeneratedCerts(nlTestSuite * inSuite, void * inCo static uint8_t root_cert[kMaxDERCertLength]; ChipDN root_dn; - root_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, 0xAAAABBBBCCCCDDDD); - root_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB0000000008888); + NL_TEST_ASSERT(inSuite, root_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, 0xAAAABBBBCCCCDDDD) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, root_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB0000000008888) == CHIP_NO_ERROR); X509CertRequestParams root_params = { 1234, 631161876, 729942000, root_dn, root_dn }; MutableByteSpan root_cert_span(root_cert); @@ -973,8 +1047,8 @@ static void TestChipCert_VerifyGeneratedCerts(nlTestSuite * inSuite, void * inCo static uint8_t ica_cert[kMaxDERCertLength]; ChipDN ica_dn; - ica_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipICAId, 0xAABBCCDDAABBCCDD); - ica_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB0000000008888); + NL_TEST_ASSERT(inSuite, ica_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipICAId, 0xAABBCCDDAABBCCDD) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, ica_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB0000000008888) == CHIP_NO_ERROR); X509CertRequestParams ica_params = { 12345, 631161876, 729942000, ica_dn, root_dn }; P256Keypair ica_keypair; @@ -986,8 +1060,8 @@ static void TestChipCert_VerifyGeneratedCerts(nlTestSuite * inSuite, void * inCo static uint8_t noc_cert[kMaxDERCertLength]; ChipDN noc_dn; - noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, 0xAABBCCDDAABBCCDD); - noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB0000000008888); + NL_TEST_ASSERT(inSuite, noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, 0xAABBCCDDAABBCCDD) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB0000000008888) == CHIP_NO_ERROR); X509CertRequestParams noc_params = { 123456, 631161876, 729942000, noc_dn, ica_dn }; P256Keypair noc_keypair; @@ -1043,9 +1117,11 @@ static void TestChipCert_VerifyGeneratedCertsNoICA(nlTestSuite * inSuite, void * const static char root_cn_rdn[] = "Test Root Operational Cert"; ChipDN root_dn; - root_dn.AddAttribute(chip::ASN1::kOID_AttributeType_CommonName, CharSpan(root_cn_rdn, strlen(root_cn_rdn)), false); - root_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, 0xAAAABBBBCCCCDDDD); - root_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB0000000008888); + NL_TEST_ASSERT(inSuite, + root_dn.AddAttribute(chip::ASN1::kOID_AttributeType_CommonName, CharSpan(root_cn_rdn, strlen(root_cn_rdn)), + false) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, root_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, 0xAAAABBBBCCCCDDDD) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, root_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB0000000008888) == CHIP_NO_ERROR); X509CertRequestParams root_params = { 1234, 631161876, 729942000, root_dn, root_dn }; MutableByteSpan root_cert_span(root_cert); @@ -1056,10 +1132,13 @@ static void TestChipCert_VerifyGeneratedCertsNoICA(nlTestSuite * inSuite, void * const static char noc_cn_rdn[] = "Test NOC"; ChipDN noc_dn; - noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_CommonName, CharSpan(noc_cn_rdn, strlen(noc_cn_rdn)), true); - noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, 0xAABBCCDDAABBCCDD); - noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB0000000008888); - noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipCASEAuthenticatedTag, 0xABCD0010); + NL_TEST_ASSERT(inSuite, + noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_CommonName, CharSpan(noc_cn_rdn, strlen(noc_cn_rdn)), true) == + CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipNodeId, 0xAABBCCDDAABBCCDD) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, 0xFAB0000000008888) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, + noc_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipCASEAuthenticatedTag, 0xABCD0010) == CHIP_NO_ERROR); X509CertRequestParams noc_params = { 1234, 631161876, 729942000, noc_dn, root_dn }; P256Keypair noc_keypair; @@ -1422,6 +1501,7 @@ int TestChipCert_Teardown(void * inContext) static const nlTest sTests[] = { NL_TEST_DEF("Test CHIP Certificate CHIP to X509 Conversion", TestChipCert_ChipToX509), NL_TEST_DEF("Test CHIP Certificate X509 to CHIP Conversion", TestChipCert_X509ToChip), + NL_TEST_DEF("Test CHIP Certificate Distinguish Name", TestChipCert_ChipDN), NL_TEST_DEF("Test CHIP Certificate Validation", TestChipCert_CertValidation), NL_TEST_DEF("Test CHIP Certificate Validation time", TestChipCert_CertValidTime), NL_TEST_DEF("Test CHIP Certificate Usage", TestChipCert_CertUsage), diff --git a/src/darwin/Framework/CHIP/CHIPDeviceController.mm b/src/darwin/Framework/CHIP/CHIPDeviceController.mm index 8d4e54ae952f97..bfbf7b3f46e722 100644 --- a/src/darwin/Framework/CHIP/CHIPDeviceController.mm +++ b/src/darwin/Framework/CHIP/CHIPDeviceController.mm @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2022 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. @@ -214,7 +214,7 @@ - (BOOL)startup:(_Nullable id)storageDelegate chip::MutableByteSpan icac; errorCode = _operationalCredentialsDelegate->GenerateNOCChainAfterValidation( - _localDeviceId, /* fabricId = */ 1, ephemeralKey.Pubkey(), rcac, icac, noc); + _localDeviceId, /* fabricId = */ 1, chip::kUndefinedCATs, ephemeralKey.Pubkey(), rcac, icac, noc); if ([self checkForStartError:(CHIP_NO_ERROR == errorCode) logMsg:kErrorCommissionerInit]) { return; } diff --git a/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.h b/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.h index 64d2e7c9414881..f2d92873ebf4f8 100644 --- a/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.h +++ b/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.h @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2021 Project CHIP Authors + * Copyright (c) 2021-2022 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. @@ -25,6 +25,7 @@ #import "CHIPPersistentStorageDelegateBridge.h" #include +#include #include NS_ASSUME_NONNULL_BEGIN @@ -52,7 +53,7 @@ class CHIPOperationalCredentialsDelegate : public chip::Controller::OperationalC void SetDeviceID(chip::NodeId deviceId) { mDeviceBeingPaired = deviceId; } void ResetDeviceID() { mDeviceBeingPaired = chip::kUndefinedNodeId; } - CHIP_ERROR GenerateNOCChainAfterValidation(chip::NodeId nodeId, chip::FabricId fabricId, + CHIP_ERROR GenerateNOCChainAfterValidation(chip::NodeId nodeId, chip::FabricId fabricId, const chip::CATValues & cats, const chip::Crypto::P256PublicKey & pubkey, chip::MutableByteSpan & rcac, chip::MutableByteSpan & icac, chip::MutableByteSpan & noc); diff --git a/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.mm b/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.mm index 8351632b57383f..de132ee91df2a4 100644 --- a/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.mm +++ b/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.mm @@ -188,7 +188,8 @@ static BOOL isRunningTests(void) } CHIP_ERROR CHIPOperationalCredentialsDelegate::GenerateNOCChainAfterValidation(NodeId nodeId, FabricId fabricId, - const Crypto::P256PublicKey & pubkey, MutableByteSpan & rcac, MutableByteSpan & icac, MutableByteSpan & noc) + const chip::CATValues & cats, const Crypto::P256PublicKey & pubkey, MutableByteSpan & rcac, MutableByteSpan & icac, + MutableByteSpan & noc) { uint32_t validityStart, validityEnd; @@ -203,11 +204,12 @@ static BOOL isRunningTests(void) } 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); - rcac_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, fabricId); + ReturnErrorOnFailure(rcac_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipRootId, mIssuerId)); + ReturnErrorOnFailure(rcac_dn.AddAttribute(chip::ASN1::kOID_AttributeType_ChipFabricId, fabricId)); X509CertRequestParams noc_request = { 1, validityStart, validityEnd, noc_dn, rcac_dn }; ReturnErrorOnFailure(NewNodeOperationalX509Cert(noc_request, pubkey, *mIssuerKey, noc)); @@ -280,7 +282,7 @@ static BOOL isRunningTests(void) MutableByteSpan icac; - ReturnErrorOnFailure(GenerateNOCChainAfterValidation(assignedId, mNextFabricId, pubkey, rcac, icac, noc)); + ReturnErrorOnFailure(GenerateNOCChainAfterValidation(assignedId, mNextFabricId, chip::kUndefinedCATs, pubkey, rcac, icac, noc)); onCompletion->mCall(onCompletion->mContext, CHIP_NO_ERROR, noc, icac, rcac, Optional(), Optional()); diff --git a/src/lib/core/CASEAuthTag.h b/src/lib/core/CASEAuthTag.h index fcc9c9b536c5e0..cd490d70d28334 100644 --- a/src/lib/core/CASEAuthTag.h +++ b/src/lib/core/CASEAuthTag.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2021 Project CHIP Authors + * Copyright (c) 2021-2022 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. @@ -18,6 +18,7 @@ #pragma once #include +#include #include #include @@ -56,6 +57,29 @@ struct CATValues } return false; } + + static constexpr size_t kSerializedLength = kMaxSubjectCATAttributeCount * sizeof(CASEAuthTag); + typedef uint8_t Serialized[kSerializedLength]; + + CHIP_ERROR Serialize(Serialized & outSerialized) const + { + uint8_t * p = outSerialized; + for (size_t i = 0; i < kMaxSubjectCATAttributeCount; i++) + { + Encoding::LittleEndian::Write32(p, values[i]); + } + return CHIP_NO_ERROR; + } + + CHIP_ERROR Deserialize(const Serialized & inSerialized) + { + const uint8_t * p = inSerialized; + for (size_t i = 0; i < kMaxSubjectCATAttributeCount; i++) + { + values[i] = Encoding::LittleEndian::Read32(p); + } + return CHIP_NO_ERROR; + } }; static constexpr CATValues kUndefinedCATs = { { kUndefinedCAT } }; diff --git a/src/lib/core/CHIPVendorIdentifiers.hpp b/src/lib/core/CHIPVendorIdentifiers.hpp index 8de7b14ed9bd5f..bd894e608a4017 100644 --- a/src/lib/core/CHIPVendorIdentifiers.hpp +++ b/src/lib/core/CHIPVendorIdentifiers.hpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2020-2022 Project CHIP Authors * Copyright (c) 2014-2017 Nest Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -50,4 +50,9 @@ enum VendorId : uint16_t NotSpecified = 0xFFFFu }; +constexpr bool IsTestVendorId(VendorId vid) +{ + return (vid >= TestVendor1 && vid <= TestVendor4); +} + } // namespace chip