Skip to content

Commit 436e06d

Browse files
luoji-nxp“nxf90552”
authored and
“nxf90552”
committed
Support trusty backed operational keystore
support trusty backed persistent storage operation keystore. Change-Id: I156c51bc415b1e9fb16e054deccb34415a7acc86 Signed-off-by: Ji Luo <ji.luo@nxp.com> Reviewed-on: http://androidsource.nxp.com/project/21252 Reviewed-by: Elven Wang <elven.wang@nxp.com> Reviewed-on: http://androidsource.nxp.com/project/23007
1 parent 7e95491 commit 436e06d

File tree

7 files changed

+293
-2
lines changed

7 files changed

+293
-2
lines changed

examples/platform/linux/AppMain.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,11 @@
131131
using namespace chip::Credentials::Trusty;
132132
#endif
133133

134+
#if CHIP_OP_KEYSTORE_TRUSTY_OS
135+
#include "PersistentStorageOperationalKeystoreTrusty.h"
136+
using namespace chip::Trusty;
137+
#endif
138+
134139
using namespace chip;
135140
using namespace chip::ArgParser;
136141
using namespace chip::Credentials;
@@ -576,6 +581,11 @@ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl)
576581
}
577582
#endif // CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED
578583

584+
#if CHIP_OP_KEYSTORE_TRUSTY_OS
585+
static chip::Trusty::PersistentStorageOperationalKeystoreTrusty sPersistentStorageOperationalKeystore;
586+
initParams.operationalKeystore = &sPersistentStorageOperationalKeystore;
587+
#endif
588+
579589
#if defined(ENABLE_CHIP_SHELL)
580590
Engine::Root().Init();
581591
Shell::RegisterCommissioneeCommands();

examples/platform/linux/BUILD.gn

+8
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ source_set("app-main") {
101101
sources += [
102102
"DeviceAttestationCreds.cpp",
103103
"DeviceAttestationCreds.h",
104+
"PersistentStorageOperationalKeystoreTrusty.cpp",
105+
"PersistentStorageOperationalKeystoreTrusty.h",
104106
]
105107
}
106108

@@ -140,6 +142,12 @@ source_set("app-main") {
140142
defines += [ "CHIP_ATTESTATION_TRUSTY_OS=0" ]
141143
}
142144

145+
if (chip_with_trusty_os == 1) {
146+
defines += [ "CHIP_OP_KEYSTORE_TRUSTY_OS=1" ]
147+
} else {
148+
defines += [ "CHIP_OP_KEYSTORE_TRUSTY_OS=0" ]
149+
}
150+
143151
if (chip_enable_pw_rpc) {
144152
defines += [ "PW_RPC_ENABLED" ]
145153
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/*
2+
* Copyright (c) 2022 Project CHIP Authors
3+
* All rights reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
* Copyright 2023 NXP
18+
*/
19+
20+
#include <crypto/OperationalKeystore.h>
21+
#include <lib/core/CHIPError.h>
22+
#include <lib/core/CHIPPersistentStorageDelegate.h>
23+
#include <lib/core/DataModelTypes.h>
24+
#include <lib/support/CHIPMem.h>
25+
#include <lib/support/CodeUtils.h>
26+
#include <lib/support/DefaultStorageKeyAllocator.h>
27+
#include <lib/support/SafeInt.h>
28+
29+
#include "PersistentStorageOperationalKeystoreTrusty.h"
30+
31+
using namespace matter;
32+
33+
namespace chip {
34+
namespace Trusty {
35+
36+
using namespace chip::Crypto;
37+
38+
bool PersistentStorageOperationalKeystoreTrusty::HasOpKeypairForFabric(FabricIndex fabricIndex) const
39+
{
40+
VerifyOrReturnError(IsValidFabricIndex(fabricIndex), false);
41+
42+
// If there was a pending keypair, then there's really a usable key
43+
if (mIsPendingKeypairActive && (fabricIndex == mPendingFabricIndex) && (mPendingKeypair != nullptr))
44+
{
45+
return true;
46+
}
47+
48+
return trusty_matter.HasOpKeypairForFabric(fabricIndex);
49+
}
50+
51+
CHIP_ERROR PersistentStorageOperationalKeystoreTrusty::NewOpKeypairForFabric(FabricIndex fabricIndex,
52+
MutableByteSpan & outCertificateSigningRequest)
53+
{
54+
VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
55+
// If a key is pending, we cannot generate for a different fabric index until we commit or revert.
56+
if ((mPendingFabricIndex != kUndefinedFabricIndex) && (fabricIndex != mPendingFabricIndex))
57+
{
58+
return CHIP_ERROR_INVALID_FABRIC_INDEX;
59+
}
60+
VerifyOrReturnError(outCertificateSigningRequest.size() >= Crypto::kMIN_CSR_Buffer_Size, CHIP_ERROR_BUFFER_TOO_SMALL);
61+
62+
// Replace previous pending keypair, if any was previously allocated
63+
ResetPendingKey();
64+
65+
mPendingKeypair = Platform::New<Crypto::P256Keypair>();
66+
VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_NO_MEMORY);
67+
68+
mPendingKeypair->fabricIndex = fabricIndex;
69+
mPendingKeypair->Initialize(Crypto::ECPKeyTarget::ECDSA);
70+
size_t csrLength = outCertificateSigningRequest.size();
71+
CHIP_ERROR err = mPendingKeypair->NewCertificateSigningRequest(outCertificateSigningRequest.data(), csrLength);
72+
if (err != CHIP_NO_ERROR)
73+
{
74+
ResetPendingKey();
75+
return err;
76+
}
77+
78+
outCertificateSigningRequest.reduce_size(csrLength);
79+
mPendingFabricIndex = fabricIndex;
80+
81+
return CHIP_NO_ERROR;
82+
}
83+
84+
CHIP_ERROR PersistentStorageOperationalKeystoreTrusty::ActivateOpKeypairForFabric(FabricIndex fabricIndex,
85+
const Crypto::P256PublicKey & nocPublicKey)
86+
{
87+
VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
88+
VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && (fabricIndex == mPendingFabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
89+
90+
// Validate public key being activated matches last generated pending keypair
91+
VerifyOrReturnError(mPendingKeypair->Pubkey().Matches(nocPublicKey), CHIP_ERROR_INVALID_PUBLIC_KEY);
92+
93+
mIsPendingKeypairActive = true;
94+
95+
return CHIP_NO_ERROR;
96+
}
97+
98+
CHIP_ERROR PersistentStorageOperationalKeystoreTrusty::CommitOpKeypairForFabric(FabricIndex fabricIndex)
99+
{
100+
int rc = 0;
101+
VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
102+
VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && (fabricIndex == mPendingFabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
103+
VerifyOrReturnError(mIsPendingKeypairActive == true, CHIP_ERROR_INCORRECT_STATE);
104+
105+
// Try to store persistent key. On failure, leave everything pending as-is
106+
rc = trusty_matter.CommitOpKeypairForFabric(mPendingKeypair->p256_handler, fabricIndex);
107+
if (rc != MATTER_ERROR_OK)
108+
ReturnErrorOnFailure(CHIP_ERROR_INTERNAL);
109+
110+
// If we got here, we succeeded and can reset the pending key: next `SignWithOpKeypair` will use the stored key.
111+
ResetPendingKey();
112+
return CHIP_NO_ERROR;
113+
}
114+
115+
CHIP_ERROR PersistentStorageOperationalKeystoreTrusty::RemoveOpKeypairForFabric(FabricIndex fabricIndex)
116+
{
117+
int rc = 0;
118+
VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
119+
120+
// Remove pending state if matching
121+
if ((mPendingKeypair != nullptr) && (fabricIndex == mPendingFabricIndex))
122+
{
123+
RevertPendingKeypair();
124+
}
125+
126+
rc = trusty_matter.RemoveOpKeypairForFabric(fabricIndex);
127+
if (rc != MATTER_ERROR_OK)
128+
return CHIP_ERROR_INVALID_FABRIC_INDEX;
129+
130+
return CHIP_NO_ERROR;
131+
}
132+
133+
void PersistentStorageOperationalKeystoreTrusty::RevertPendingKeypair()
134+
{
135+
// Just reset the pending key, it hasn't been stored into secure storage.
136+
ResetPendingKey();
137+
}
138+
139+
CHIP_ERROR PersistentStorageOperationalKeystoreTrusty::SignWithOpKeypair(FabricIndex fabricIndex, const ByteSpan & message,
140+
Crypto::P256ECDSASignature & outSignature) const
141+
{
142+
int rc = 0;
143+
size_t sig_size = 0;
144+
uint8_t sig[kP256_ECDSA_Signature_Length_Raw];
145+
146+
VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
147+
148+
if (mIsPendingKeypairActive && (fabricIndex == mPendingFabricIndex))
149+
{
150+
VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INTERNAL);
151+
// We have an override key: sign with it!
152+
return mPendingKeypair->ECDSA_sign_msg(message.data(), message.size(), outSignature);
153+
}
154+
155+
rc = trusty_matter.SignWithStoredOpKey(fabricIndex, message.data(), message.size(), sig, sig_size);
156+
if (rc != MATTER_ERROR_OK)
157+
return CHIP_ERROR_INTERNAL;
158+
159+
VerifyOrReturnError(sig_size == kP256_ECDSA_Signature_Length_Raw, CHIP_ERROR_INTERNAL);
160+
VerifyOrReturnError(outSignature.SetLength(sig_size) == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL);
161+
memcpy(outSignature.Bytes(), sig, sig_size);
162+
return CHIP_NO_ERROR;
163+
}
164+
165+
Crypto::P256Keypair * PersistentStorageOperationalKeystoreTrusty::AllocateEphemeralKeypairForCASE()
166+
{
167+
return Platform::New<Crypto::P256Keypair>();
168+
}
169+
170+
void PersistentStorageOperationalKeystoreTrusty::ReleaseEphemeralKeypair(Crypto::P256Keypair * keypair)
171+
{
172+
Platform::Delete<Crypto::P256Keypair>(keypair);
173+
}
174+
175+
} // namespace Trusty
176+
} // namespace chip
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright (c) 2022 Project CHIP Authors
3+
* All rights reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
* Copyright 2023 NXP
18+
*/
19+
20+
#pragma once
21+
22+
#include <crypto/OperationalKeystore.h>
23+
#include <lib/core/CHIPError.h>
24+
#include <lib/support/CHIPMem.h>
25+
#include <lib/support/CodeUtils.h>
26+
27+
#include <trusty_matter.h>
28+
29+
using namespace matter;
30+
31+
namespace chip {
32+
namespace Trusty {
33+
34+
/**
35+
* @brief OperationalKeystore implementation making use of Trusty secure storage
36+
* to load/store keypairs.
37+
*
38+
*/
39+
class PersistentStorageOperationalKeystoreTrusty : public Crypto::OperationalKeystore
40+
{
41+
public:
42+
PersistentStorageOperationalKeystoreTrusty() = default;
43+
virtual ~PersistentStorageOperationalKeystoreTrusty() { Finish(); }
44+
45+
// Non-copyable
46+
PersistentStorageOperationalKeystoreTrusty(PersistentStorageOperationalKeystoreTrusty const &) = delete;
47+
void operator=(PersistentStorageOperationalKeystoreTrusty const &) = delete;
48+
49+
/**
50+
* @brief Finalize the keystore, so that subsequent operations fail
51+
*/
52+
void Finish()
53+
{
54+
ResetPendingKey();
55+
}
56+
57+
bool HasPendingOpKeypair() const override { return (mPendingKeypair != nullptr); }
58+
59+
bool HasOpKeypairForFabric(FabricIndex fabricIndex) const override;
60+
CHIP_ERROR NewOpKeypairForFabric(FabricIndex fabricIndex, MutableByteSpan & outCertificateSigningRequest) override;
61+
CHIP_ERROR ActivateOpKeypairForFabric(FabricIndex fabricIndex, const Crypto::P256PublicKey & nocPublicKey) override;
62+
CHIP_ERROR CommitOpKeypairForFabric(FabricIndex fabricIndex) override;
63+
CHIP_ERROR RemoveOpKeypairForFabric(FabricIndex fabricIndex) override;
64+
void RevertPendingKeypair() override;
65+
CHIP_ERROR SignWithOpKeypair(FabricIndex fabricIndex, const ByteSpan & message,
66+
Crypto::P256ECDSASignature & outSignature) const override;
67+
Crypto::P256Keypair * AllocateEphemeralKeypairForCASE() override;
68+
void ReleaseEphemeralKeypair(Crypto::P256Keypair * keypair) override;
69+
70+
protected:
71+
void ResetPendingKey()
72+
{
73+
if (!mIsExternallyOwnedKeypair && (mPendingKeypair != nullptr))
74+
{
75+
Platform::Delete(mPendingKeypair);
76+
}
77+
mPendingKeypair = nullptr;
78+
mIsExternallyOwnedKeypair = false;
79+
mIsPendingKeypairActive = false;
80+
mPendingFabricIndex = kUndefinedFabricIndex;
81+
}
82+
83+
FabricIndex mPendingFabricIndex = kUndefinedFabricIndex;
84+
Crypto::P256Keypair * mPendingKeypair = nullptr;
85+
bool mIsPendingKeypairActive = false;
86+
87+
// If overridding NewOpKeypairForFabric method in a subclass, set this to true in
88+
// `NewOpKeypairForFabric` if the mPendingKeypair should not be deleted when no longer in use.
89+
bool mIsExternallyOwnedKeypair = false;
90+
91+
private:
92+
mutable TrustyMatter trusty_matter;
93+
};
94+
95+
} // namespace Trusty
96+
} // namespace chip

src/crypto/CHIPCryptoPAL.h

+1
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,7 @@ class P256Keypair : public P256KeypairBase
591591

592592
#if CHIP_CRYPTO_TRUSTY_OS
593593
uint64_t p256_handler = 0;
594+
uint8_t fabricIndex = 0;
594595
#endif
595596

596597
protected:

src/crypto/CHIPCryptoPALOpenSSL.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1158,7 +1158,7 @@ CHIP_ERROR P256Keypair::Initialize(ECPKeyTarget key_target)
11581158
uint8_t public_key[kP256_PublicKey_Length];
11591159
int rc = 0;
11601160

1161-
rc = trusty_matter.P256KeypairInitialize(p256_handler, public_key);
1161+
rc = trusty_matter.P256KeypairInitialize(p256_handler, fabricIndex, public_key);
11621162
VerifyOrExit(rc == MATTER_ERROR_OK, error = CHIP_ERROR_INTERNAL);
11631163

11641164
memcpy(Uint8::to_uchar(mPublicKey), public_key, kP256_PublicKey_Length);

0 commit comments

Comments
 (0)