From d7c56ff93aa1e87199a3cd097d217c905138843d Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Fri, 14 May 2021 16:56:54 -0700 Subject: [PATCH] Persist keypair used by example opcert signer (#6821) * Persist keypair used by example opcert signer * Fix Android build --- .../commands/clusters/ModelCommand.cpp | 8 ++-- .../commands/pairing/PairingCommand.cpp | 12 +++--- .../commands/pairing/PairingCommand.h | 1 - .../commands/reporting/ReportingCommand.cpp | 8 ++-- .../ExampleOperationalCredentialsIssuer.cpp | 26 ++++++++++++ .../ExampleOperationalCredentialsIssuer.h | 41 ++++++------------- .../java/AndroidDeviceControllerWrapper.cpp | 2 +- .../ChipDeviceController-ScriptBinding.cpp | 2 +- .../python/chip/internal/CommissionerImpl.cpp | 3 +- 9 files changed, 59 insertions(+), 44 deletions(-) diff --git a/examples/chip-tool/commands/clusters/ModelCommand.cpp b/examples/chip-tool/commands/clusters/ModelCommand.cpp index 0bd0f2914dc0e0..c556197ccea74a 100644 --- a/examples/chip-tool/commands/clusters/ModelCommand.cpp +++ b/examples/chip-tool/commands/clusters/ModelCommand.cpp @@ -41,10 +41,12 @@ CHIP_ERROR ModelCommand::Run(PersistentStorage & storage, NodeId localId, NodeId { CHIP_ERROR err = CHIP_NO_ERROR; - mOpCredsIssuer.Initialize(); - chip::Controller::CommissionerInitParams initParams; - initParams.storageDelegate = &storage; + initParams.storageDelegate = &storage; + + err = mOpCredsIssuer.Initialize(storage); + VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init failure! Operational Cred Issuer: %s", ErrorStr(err))); + initParams.operationalCredentialsDelegate = &mOpCredsIssuer; err = mCommissioner.SetUdpListenPort(storage.GetListenPort()); diff --git a/examples/chip-tool/commands/pairing/PairingCommand.cpp b/examples/chip-tool/commands/pairing/PairingCommand.cpp index 7521c39418934f..ff54619d5e1daf 100644 --- a/examples/chip-tool/commands/pairing/PairingCommand.cpp +++ b/examples/chip-tool/commands/pairing/PairingCommand.cpp @@ -31,12 +31,14 @@ CHIP_ERROR PairingCommand::Run(PersistentStorage & storage, NodeId localId, Node { CHIP_ERROR err = CHIP_NO_ERROR; - mOpCredsIssuer.Initialize(); - chip::Controller::CommissionerInitParams params; - params.storageDelegate = &storage; - params.mDeviceAddressUpdateDelegate = this; - params.pairingDelegate = this; + params.storageDelegate = &storage; + params.mDeviceAddressUpdateDelegate = this; + params.pairingDelegate = this; + + err = mOpCredsIssuer.Initialize(storage); + VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init failure! Operational Cred Issuer: %s", ErrorStr(err))); + params.operationalCredentialsDelegate = &mOpCredsIssuer; err = mCommissioner.SetUdpListenPort(storage.GetListenPort()); diff --git a/examples/chip-tool/commands/pairing/PairingCommand.h b/examples/chip-tool/commands/pairing/PairingCommand.h index 871186e45c2f7a..d5e122263ab211 100644 --- a/examples/chip-tool/commands/pairing/PairingCommand.h +++ b/examples/chip-tool/commands/pairing/PairingCommand.h @@ -93,7 +93,6 @@ class PairingCommand : public Command, AddArgument("device-remote-port", 0, UINT16_MAX, &mRemotePort); break; } - mOpCredsIssuer.Initialize(); } /////////// Command Interface ///////// diff --git a/examples/chip-tool/commands/reporting/ReportingCommand.cpp b/examples/chip-tool/commands/reporting/ReportingCommand.cpp index 29d43c77dd3f4d..447c1c82eb9c7c 100644 --- a/examples/chip-tool/commands/reporting/ReportingCommand.cpp +++ b/examples/chip-tool/commands/reporting/ReportingCommand.cpp @@ -32,12 +32,14 @@ CHIP_ERROR ReportingCommand::Run(PersistentStorage & storage, NodeId localId, No { CHIP_ERROR err = CHIP_NO_ERROR; - mOpCredsIssuer.Initialize(); - chip::Controller::BasicCluster cluster; chip::Controller::CommissionerInitParams initParams; - initParams.storageDelegate = &storage; + initParams.storageDelegate = &storage; + + err = mOpCredsIssuer.Initialize(storage); + VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init failure! Operational Cred Issuer: %s", ErrorStr(err))); + initParams.operationalCredentialsDelegate = &mOpCredsIssuer; err = mCommissioner.SetUdpListenPort(storage.GetListenPort()); diff --git a/src/controller/ExampleOperationalCredentialsIssuer.cpp b/src/controller/ExampleOperationalCredentialsIssuer.cpp index f0680b13ca84a8..88da5d82cb18d4 100644 --- a/src/controller/ExampleOperationalCredentialsIssuer.cpp +++ b/src/controller/ExampleOperationalCredentialsIssuer.cpp @@ -22,9 +22,35 @@ namespace chip { namespace Controller { +constexpr const char kOperationalCredentialsIssuerKeypairStorage[] = "ExampleOpCredsCAKey"; + using namespace Credentials; using namespace Crypto; +CHIP_ERROR ExampleOperationalCredentialsIssuer::Initialize(PersistentStorageDelegate & storage) +{ + Crypto::P256SerializedKeypair serializedKey; + uint16_t keySize = static_cast(serializedKey.Capacity()); + + if (storage.SyncGetKeyValue(kOperationalCredentialsIssuerKeypairStorage, serializedKey, keySize) != CHIP_NO_ERROR) + { + // Storage doesn't have an existing keypair. Let's create one and add it to the storage. + ReturnErrorOnFailure(mIssuer.Initialize()); + ReturnErrorOnFailure(mIssuer.Serialize(serializedKey)); + + keySize = static_cast(serializedKey.Length()); + ReturnErrorOnFailure(storage.SyncSetKeyValue(kOperationalCredentialsIssuerKeypairStorage, serializedKey, keySize)); + } + else + { + // Use the keypair from the storage + ReturnErrorOnFailure(mIssuer.Deserialize(serializedKey)); + } + + mInitialized = true; + return CHIP_NO_ERROR; +} + CHIP_ERROR ExampleOperationalCredentialsIssuer::GenerateNodeOperationalCertificate(const PeerId & peerId, const ByteSpan & csr, int64_t serialNumber, uint8_t * certBuf, uint32_t certBufSize, uint32_t & outCertLen) diff --git a/src/controller/ExampleOperationalCredentialsIssuer.h b/src/controller/ExampleOperationalCredentialsIssuer.h index 00eba9452fbba8..a8ae6a8fc725aa 100644 --- a/src/controller/ExampleOperationalCredentialsIssuer.h +++ b/src/controller/ExampleOperationalCredentialsIssuer.h @@ -22,12 +22,16 @@ * issuer for CHIP devices. The class can be used as a guideline on how to * construct your own certificate issuer. It can also be used in tests and tools * if a specific signing authority is not required. + * + * NOTE: This class stores the encryption key in clear storage. This is not suited + * for production use. This should only be used in test tools. */ #pragma once #include #include +#include #include #include @@ -45,36 +49,17 @@ class DLL_EXPORT ExampleOperationalCredentialsIssuer : public OperationalCredent CHIP_ERROR GetRootCACertificate(FabricId fabricId, uint8_t * certBuf, uint32_t certBufSize, uint32_t & outCertLen) override; /** - * @brief Serialize the issuer's keypair. - * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise - **/ - CHIP_ERROR Serialize(Crypto::P256SerializedKeypair & issuer) - { - VerifyOrReturnError(mInitialized, CHIP_ERROR_INCORRECT_STATE); - return mIssuer.Serialize(issuer); - } - - /** - * @brief Deserialize the keypair as issuer's keypair. - * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise - **/ - CHIP_ERROR Deserialize(Crypto::P256SerializedKeypair & issuer) - { - ReturnErrorOnFailure(mIssuer.Deserialize(issuer)); - mInitialized = true; - return CHIP_NO_ERROR; - } - - /** - * @brief Initialize the issuer with a new keypair. + * @brief Initialize the issuer with the keypair in the storage. + * If the storage doesn't have one, it'll create one, and it to the storage. + * + * @param[in] storage A reference to the storage, where the keypair is stored. + * The object of ExampleOperationalCredentialsIssuer doesn't hold + * on the reference of storage. + * * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise **/ - CHIP_ERROR Initialize() - { - ReturnErrorOnFailure(mIssuer.Initialize()); - mInitialized = true; - return CHIP_NO_ERROR; - } + [[deprecated("This class stores the encryption key in clear storage. Don't use it for production code.")]] CHIP_ERROR + Initialize(PersistentStorageDelegate & storage); void SetIssuerId(uint32_t id) { mIssuerId = id; } diff --git a/src/controller/java/AndroidDeviceControllerWrapper.cpp b/src/controller/java/AndroidDeviceControllerWrapper.cpp index bb061f5da0bfd6..f40e51976b16d9 100644 --- a/src/controller/java/AndroidDeviceControllerWrapper.cpp +++ b/src/controller/java/AndroidDeviceControllerWrapper.cpp @@ -143,7 +143,7 @@ AndroidDeviceControllerWrapper * AndroidDeviceControllerWrapper::AllocateNew(Jav initParams.inetLayer = inetLayer; initParams.bleLayer = GetJNIBleLayer(); - *errInfoOnFailure = wrapper->OpCredsIssuer().Initialize(); + *errInfoOnFailure = wrapper->OpCredsIssuer().Initialize(*initParams.storageDelegate); if (*errInfoOnFailure != CHIP_NO_ERROR) { return nullptr; diff --git a/src/controller/python/ChipDeviceController-ScriptBinding.cpp b/src/controller/python/ChipDeviceController-ScriptBinding.cpp index dcc5f3ee18206c..f497c37eb375a6 100644 --- a/src/controller/python/ChipDeviceController-ScriptBinding.cpp +++ b/src/controller/python/ChipDeviceController-ScriptBinding.cpp @@ -143,7 +143,7 @@ CHIP_ERROR pychip_DeviceController_NewDeviceController(chip::Controller::DeviceC localDeviceId = kDefaultLocalDeviceId; } - ReturnErrorOnFailure(sOperationalCredentialsIssuer.Initialize()); + ReturnErrorOnFailure(sOperationalCredentialsIssuer.Initialize(sStorageDelegate)); initParams.storageDelegate = &sStorageDelegate; initParams.mDeviceAddressUpdateDelegate = &sDeviceAddressUpdateDelegate; diff --git a/src/controller/python/chip/internal/CommissionerImpl.cpp b/src/controller/python/chip/internal/CommissionerImpl.cpp index bc1b7c6ab05d33..0f722313c5498a 100644 --- a/src/controller/python/chip/internal/CommissionerImpl.cpp +++ b/src/controller/python/chip/internal/CommissionerImpl.cpp @@ -101,8 +101,7 @@ extern "C" chip::Controller::DeviceCommissioner * pychip_internal_Commissioner_N params.inetLayer = &chip::DeviceLayer::InetLayer; params.pairingDelegate = &gPairingDelegate; - err = gOperationalCredentialsIssuer.Initialize(); - + err = gOperationalCredentialsIssuer.Initialize(gServerStorage); if (err != CHIP_NO_ERROR) { ChipLogError(Controller, "Operational credentials issuer initialization failed: %s", chip::ErrorStr(err));