Skip to content

Commit 4cb3032

Browse files
gd-mauriandy31415
andauthored
Unit Tests for controller/ExampleOperationalCredentialsIssuer. (project-chip#38525)
* proposed in-memory persistent delegate implementation. * increased coverage and TestPersistentStorageDelegate reused. * bringing constants back into source file. * addressing PR comments. --------- Co-authored-by: Andrei Litvin <[email protected]>
1 parent 6915d2e commit 4cb3032

File tree

2 files changed

+159
-1
lines changed

2 files changed

+159
-1
lines changed

src/controller/tests/BUILD.gn

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ chip_test_suite("tests") {
4040

4141
# Not supported on efr32.
4242
if (chip_device_platform != "efr32") {
43-
test_sources += [ "TestCommissioningWindowOpener.cpp" ]
43+
test_sources += [
44+
"TestCommissioningWindowOpener.cpp",
45+
"TestExampleOperationalCredentialsIssuer.cpp",
46+
]
4447
}
4548
}
4649

@@ -52,6 +55,7 @@ chip_test_suite("tests") {
5255
"${chip_root}/src/controller",
5356
"${chip_root}/src/lib/core:string-builder-adapters",
5457
"${chip_root}/src/lib/support:test_utils",
58+
"${chip_root}/src/lib/support:testing",
5559
"${chip_root}/src/messaging/tests:helpers",
5660
"${chip_root}/src/transport/raw/tests:helpers",
5761
]
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*
2+
*
3+
* Copyright (c) 2020-2025 Project CHIP Authors
4+
* All rights reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#include <pw_unit_test/framework.h>
20+
21+
#include <controller/ExampleOperationalCredentialsIssuer.h>
22+
23+
#include <lib/core/StringBuilderAdapters.h>
24+
#include <lib/support/CHIPMemString.h>
25+
#include <lib/support/PersistentStorageMacros.h>
26+
#include <lib/support/TestPersistentStorageDelegate.h>
27+
28+
#include <cstring>
29+
#include <iostream>
30+
#include <string>
31+
#include <vector>
32+
33+
using namespace chip;
34+
using namespace chip::Controller;
35+
36+
namespace {
37+
38+
static constexpr size_t kNodeId = 999;
39+
static constexpr size_t kFabricId = 1000;
40+
41+
constexpr char kOperationalCredentialsRootCertificateStorage[] = "ExampleCARootCert";
42+
constexpr char kOperationalCredentialsIntermediateCertificateStorage[] = "ExampleCAIntermediateCert";
43+
44+
class ExampleOperationalCredentialsIssuerTest : public ::testing::Test
45+
{
46+
public:
47+
static void SetUpTestSuite() { ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR); }
48+
static void TearDownTestSuite() { chip::Platform::MemoryShutdown(); }
49+
50+
protected:
51+
NodeId mNodeId{ ::kNodeId };
52+
53+
ExampleOperationalCredentialsIssuer mCredsIssuer{ ::kFabricId };
54+
55+
TestPersistentStorageDelegate mPersistentStorageDelegate{};
56+
};
57+
58+
TEST_F(ExampleOperationalCredentialsIssuerTest, SuccessfulyGeneratesDistinctRandomNodeIds)
59+
{
60+
NodeId node_id_1{};
61+
NodeId node_id_2{};
62+
63+
ASSERT_EQ(node_id_1, node_id_2); // should be both 0 since type of NodeId is uint64_t
64+
65+
ExampleOperationalCredentialsIssuer::GetRandomOperationalNodeId(&node_id_1);
66+
ExampleOperationalCredentialsIssuer::GetRandomOperationalNodeId(&node_id_2);
67+
68+
ASSERT_NE(node_id_1, node_id_2);
69+
}
70+
71+
TEST_F(ExampleOperationalCredentialsIssuerTest, SuccessfulyGeneratesRandomNodeId)
72+
{
73+
auto prev_node_id = mNodeId;
74+
auto r = ExampleOperationalCredentialsIssuer::GetRandomOperationalNodeId(&mNodeId);
75+
76+
ASSERT_EQ(prev_node_id, kNodeId);
77+
ASSERT_EQ(r, CHIP_NO_ERROR);
78+
ASSERT_NE(mNodeId, kNodeId);
79+
}
80+
81+
TEST_F(ExampleOperationalCredentialsIssuerTest, SuccessfulyGeneratesNOCChainAfterValidation)
82+
{
83+
Crypto::P256Keypair ephemeralKey;
84+
auto ephemeral_r = ephemeralKey.Initialize(Crypto::ECPKeyTarget::ECDSA);
85+
86+
Platform::ScopedMemoryBuffer<uint8_t> noc;
87+
noc.Calloc(Controller::kMaxCHIPDERCertLength);
88+
ASSERT_TRUE(noc.Get());
89+
90+
Platform::ScopedMemoryBuffer<uint8_t> icac;
91+
icac.Calloc(Controller::kMaxCHIPDERCertLength);
92+
ASSERT_TRUE(icac.Get());
93+
94+
Platform::ScopedMemoryBuffer<uint8_t> rcac;
95+
rcac.Calloc(Controller::kMaxCHIPDERCertLength);
96+
ASSERT_TRUE(rcac.Get());
97+
98+
ASSERT_EQ(ephemeral_r, CHIP_NO_ERROR);
99+
100+
MutableByteSpan nocSpan(noc.Get(), Controller::kMaxCHIPDERCertLength);
101+
MutableByteSpan icacSpan(icac.Get(), Controller::kMaxCHIPDERCertLength);
102+
MutableByteSpan rcacSpan(rcac.Get(), Controller::kMaxCHIPDERCertLength);
103+
104+
mCredsIssuer.Initialize(mPersistentStorageDelegate);
105+
106+
auto r = mCredsIssuer.GenerateNOCChainAfterValidation(mNodeId, ::kFabricId, chip::kUndefinedCATs, ephemeralKey.Pubkey(),
107+
rcacSpan, icacSpan, nocSpan);
108+
109+
ASSERT_EQ(r, CHIP_NO_ERROR);
110+
}
111+
112+
TEST_F(ExampleOperationalCredentialsIssuerTest, SuccessfulyGeneratesNOCChainAfterValidationWithDataInStorage)
113+
{
114+
Crypto::P256Keypair ephemeralKey;
115+
auto ephemeral_r = ephemeralKey.Initialize(Crypto::ECPKeyTarget::ECDSA);
116+
117+
ASSERT_EQ(ephemeral_r, CHIP_NO_ERROR);
118+
119+
Platform::ScopedMemoryBuffer<uint8_t> noc;
120+
noc.Calloc(Controller::kMaxCHIPDERCertLength);
121+
ASSERT_TRUE(noc.Get());
122+
123+
MutableByteSpan nocSpan(noc.Get(), Controller::kMaxCHIPDERCertLength);
124+
125+
std::array<uint8_t, Controller::kMaxCHIPDERCertLength> icacArray{};
126+
MutableByteSpan icacSpan(icacArray);
127+
128+
std::array<uint8_t, Controller::kMaxCHIPDERCertLength> rcacArray{};
129+
MutableByteSpan rcacSpan(rcacArray);
130+
uint16_t rcacBufLen = static_cast<uint16_t>(std::min(rcacSpan.size(), static_cast<size_t>(UINT16_MAX)));
131+
132+
CHIP_ERROR err = CHIP_NO_ERROR;
133+
PERSISTENT_KEY_OP(uint64_t{ 0 }, kOperationalCredentialsRootCertificateStorage, key,
134+
err = mPersistentStorageDelegate.SyncSetKeyValue(key, rcacSpan.data(), rcacBufLen));
135+
136+
ASSERT_EQ(CHIP_NO_ERROR, err);
137+
138+
PERSISTENT_KEY_OP(uint64_t{ 0 }, kOperationalCredentialsIntermediateCertificateStorage, key,
139+
err =
140+
mPersistentStorageDelegate.SyncSetKeyValue(key, icacSpan.data(), static_cast<uint16_t>(icacSpan.size())));
141+
142+
ASSERT_EQ(CHIP_NO_ERROR, err);
143+
144+
mCredsIssuer.Initialize(mPersistentStorageDelegate);
145+
146+
mCredsIssuer.SetMaximallyLargeCertsUsed(true);
147+
148+
auto r = mCredsIssuer.GenerateNOCChainAfterValidation(mNodeId, ::kFabricId, chip::kUndefinedCATs, ephemeralKey.Pubkey(),
149+
rcacSpan, icacSpan, nocSpan);
150+
151+
ASSERT_EQ(r, CHIP_NO_ERROR);
152+
}
153+
154+
} // namespace

0 commit comments

Comments
 (0)