diff --git a/examples/platform/linux/testing/CustomCSRResponseOperationalKeyStore.cpp b/examples/platform/linux/testing/CustomCSRResponseOperationalKeyStore.cpp index dfd063e866f9ea..05845423abb911 100644 --- a/examples/platform/linux/testing/CustomCSRResponseOperationalKeyStore.cpp +++ b/examples/platform/linux/testing/CustomCSRResponseOperationalKeyStore.cpp @@ -63,8 +63,8 @@ CHIP_ERROR CustomCSRResponseOperationalKeyStore::ReuseOpKeypair(FabricIndex fabr // Scope 1: Load up the keypair data from storage { - // Use a CapacityBoundBuffer to get RAII secret data clearing on scope exit. - Crypto::CapacityBoundBuffer buf; + // Use a SensitiveDataBuffer to get RAII secret data clearing on scope exit. + Crypto::SensitiveDataBuffer buf; // Load up the operational key structure from storage uint16_t size = static_cast(buf.Capacity()); diff --git a/src/controller/AutoCommissioner.cpp b/src/controller/AutoCommissioner.cpp index 982f62765bace6..eacb988b15bbef 100644 --- a/src/controller/AutoCommissioner.cpp +++ b/src/controller/AutoCommissioner.cpp @@ -450,7 +450,7 @@ Optional AutoCommissioner::GetCommandTimeout(DeviceProxy return MakeOptional(timeout); } -CHIP_ERROR AutoCommissioner::NOCChainGenerated(ByteSpan noc, ByteSpan icac, ByteSpan rcac, AesCcm128KeySpan ipk, +CHIP_ERROR AutoCommissioner::NOCChainGenerated(ByteSpan noc, ByteSpan icac, ByteSpan rcac, IdentityProtectionKeySpan ipk, NodeId adminSubject) { // Reuse ICA Cert buffer for temporary store Root Cert. diff --git a/src/controller/AutoCommissioner.h b/src/controller/AutoCommissioner.h index f459f5015debe7..f2807a4a26542d 100644 --- a/src/controller/AutoCommissioner.h +++ b/src/controller/AutoCommissioner.h @@ -63,7 +63,7 @@ class AutoCommissioner : public CommissioningDelegate ByteSpan GetDAC() const { return ByteSpan(mDAC, mDACLen); } ByteSpan GetPAI() const { return ByteSpan(mPAI, mPAILen); } - CHIP_ERROR NOCChainGenerated(ByteSpan noc, ByteSpan icac, ByteSpan rcac, AesCcm128KeySpan ipk, NodeId adminSubject); + CHIP_ERROR NOCChainGenerated(ByteSpan noc, ByteSpan icac, ByteSpan rcac, IdentityProtectionKeySpan ipk, NodeId adminSubject); /** * The device argument to GetCommandTimeout is the device whose session will * be used for sending the relevant command. diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 46200403e0fcc7..7f7ea648107dcf 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -1244,7 +1244,7 @@ void DeviceCommissioner::OnOperationalCertificateSigningRequest( } void DeviceCommissioner::OnDeviceNOCChainGeneration(void * context, CHIP_ERROR status, const ByteSpan & noc, const ByteSpan & icac, - const ByteSpan & rcac, Optional ipk, + const ByteSpan & rcac, Optional ipk, Optional adminSubject) { MATTER_TRACE_EVENT_SCOPE("OnDeviceNOCChainGeneration", "DeviceCommissioner"); @@ -1271,7 +1271,7 @@ void DeviceCommissioner::OnDeviceNOCChainGeneration(void * context, CHIP_ERROR s // TODO - Verify that the generated root cert matches with commissioner's root cert CommissioningDelegate::CommissioningReport report; - report.Set(NocChain(noc, icac, rcac, ipk.HasValue() ? ipk.Value() : AesCcm128KeySpan(placeHolderIpk), + report.Set(NocChain(noc, icac, rcac, ipk.HasValue() ? ipk.Value() : IdentityProtectionKeySpan(placeHolderIpk), adminSubject.HasValue() ? adminSubject.Value() : commissioner->GetNodeId())); commissioner->CommissioningStageComplete(status, report); } @@ -1325,8 +1325,9 @@ CHIP_ERROR DeviceCommissioner::ProcessCSR(DeviceProxy * proxy, const ByteSpan & } CHIP_ERROR DeviceCommissioner::SendOperationalCertificate(DeviceProxy * device, const ByteSpan & nocCertBuf, - const Optional & icaCertBuf, const AesCcm128KeySpan ipk, - const NodeId adminSubject, Optional timeout) + const Optional & icaCertBuf, + const IdentityProtectionKeySpan ipk, const NodeId adminSubject, + Optional timeout) { MATTER_TRACE_EVENT_SCOPE("SendOperationalCertificate", "DeviceCommissioner"); diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index cc3588fa17a38a..3e6daecb5ab00e 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -732,7 +732,8 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, The function does not hold a reference to the device object. */ CHIP_ERROR SendOperationalCertificate(DeviceProxy * device, const ByteSpan & nocCertBuf, const Optional & icaCertBuf, - AesCcm128KeySpan ipk, NodeId adminSubject, Optional timeout); + IdentityProtectionKeySpan ipk, NodeId adminSubject, + Optional timeout); /* This function sends the trusted root certificate to the device. The function does not hold a reference to the device object. */ @@ -792,7 +793,8 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, Credentials::AttestationVerificationResult result); static void OnDeviceNOCChainGeneration(void * context, CHIP_ERROR status, const ByteSpan & noc, const ByteSpan & icac, - const ByteSpan & rcac, Optional ipk, Optional adminSubject); + const ByteSpan & rcac, Optional ipk, + Optional adminSubject); static void OnArmFailSafe(void * context, const chip::app::Clusters::GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType & data); static void OnSetRegulatoryConfigResponse( diff --git a/src/controller/CommissioningDelegate.h b/src/controller/CommissioningDelegate.h index 868f27f2f39f94..75344ca5eb6e12 100644 --- a/src/controller/CommissioningDelegate.h +++ b/src/controller/CommissioningDelegate.h @@ -177,9 +177,9 @@ class CommissioningParameters // Epoch key for the identity protection key for the node being commissioned. In the AutoCommissioner, this is set by by the // kGenerateNOCChain stage through the OperationalCredentialsDelegate. // This value must be set before calling PerformCommissioningStep for the kSendNOC step. - const Optional GetIpk() const + const Optional GetIpk() const { - return mIpk.HasValue() ? Optional(mIpk.Value().Span()) : Optional(); + return mIpk.HasValue() ? Optional(mIpk.Value().Span()) : Optional(); } // Admin subject id used for the case access control entry created if the AddNOC command succeeds. In the AutoCommissioner, this @@ -321,9 +321,9 @@ class CommissioningParameters mIcac.SetValue(icac); return *this; } - CommissioningParameters & SetIpk(const AesCcm128KeySpan ipk) + CommissioningParameters & SetIpk(const IdentityProtectionKeySpan ipk) { - mIpk.SetValue(AesCcm128Key(ipk)); + mIpk.SetValue(IdentityProtectionKey(ipk)); return *this; } CommissioningParameters & SetAdminSubject(const NodeId adminSubject) @@ -439,7 +439,7 @@ class CommissioningParameters Optional mRootCert; Optional mNoc; Optional mIcac; - Optional mIpk; + Optional mIpk; Optional mAdminSubject; // Items that come from the device in commissioning steps Optional mAttestationElements; @@ -484,13 +484,13 @@ struct CSRResponse struct NocChain { - NocChain(ByteSpan newNoc, ByteSpan newIcac, ByteSpan newRcac, AesCcm128KeySpan newIpk, NodeId newAdminSubject) : + NocChain(ByteSpan newNoc, ByteSpan newIcac, ByteSpan newRcac, IdentityProtectionKeySpan newIpk, NodeId newAdminSubject) : noc(newNoc), icac(newIcac), rcac(newRcac), ipk(newIpk), adminSubject(newAdminSubject) {} ByteSpan noc; ByteSpan icac; ByteSpan rcac; - AesCcm128KeySpan ipk; + IdentityProtectionKeySpan ipk; NodeId adminSubject; }; diff --git a/src/controller/ExampleOperationalCredentialsIssuer.cpp b/src/controller/ExampleOperationalCredentialsIssuer.cpp index 7b120c73d30337..a651c0d070d9a9 100644 --- a/src/controller/ExampleOperationalCredentialsIssuer.cpp +++ b/src/controller/ExampleOperationalCredentialsIssuer.cpp @@ -386,7 +386,7 @@ CHIP_ERROR ExampleOperationalCredentialsIssuer::GenerateNOCChain(const ByteSpan // Prepare IPK to be sent back. A more fully-fledged operational credentials delegate // would obtain a suitable key per fabric. uint8_t ipkValue[CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES]; - Crypto::AesCcm128KeySpan ipkSpan(ipkValue); + Crypto::IdentityProtectionKeySpan ipkSpan(ipkValue); ReturnErrorCodeIf(defaultIpkSpan.size() != sizeof(ipkValue), CHIP_ERROR_INTERNAL); memcpy(&ipkValue[0], defaultIpkSpan.data(), defaultIpkSpan.size()); diff --git a/src/controller/OperationalCredentialsDelegate.h b/src/controller/OperationalCredentialsDelegate.h index e34b728b1ee9da..5d51f820bf7ef7 100644 --- a/src/controller/OperationalCredentialsDelegate.h +++ b/src/controller/OperationalCredentialsDelegate.h @@ -30,7 +30,8 @@ namespace chip { namespace Controller { typedef void (*OnNOCChainGeneration)(void * context, CHIP_ERROR status, const ByteSpan & noc, const ByteSpan & icac, - const ByteSpan & rcac, Optional ipk, Optional adminSubject); + const ByteSpan & rcac, Optional ipk, + Optional adminSubject); constexpr uint32_t kMaxCHIPDERCertLength = 600; constexpr size_t kCSRNonceLength = 32; diff --git a/src/controller/java/AndroidOperationalCredentialsIssuer.cpp b/src/controller/java/AndroidOperationalCredentialsIssuer.cpp index d9fc3d41adfd93..8d405396a03901 100644 --- a/src/controller/java/AndroidOperationalCredentialsIssuer.cpp +++ b/src/controller/java/AndroidOperationalCredentialsIssuer.cpp @@ -297,7 +297,8 @@ CHIP_ERROR AndroidOperationalCredentialsIssuer::CallbackGenerateNOCChain(const B } CHIP_ERROR AndroidOperationalCredentialsIssuer::NOCChainGenerated(CHIP_ERROR status, const ByteSpan & noc, const ByteSpan & icac, - const ByteSpan & rcac, Optional ipk, + const ByteSpan & rcac, + Optional ipk, Optional adminSubject) { ReturnErrorCodeIf(mOnNOCCompletionCallback == nullptr, CHIP_ERROR_INCORRECT_STATE); @@ -384,7 +385,7 @@ CHIP_ERROR AndroidOperationalCredentialsIssuer::LocalGenerateNOCChain(const Byte // Prepare IPK to be sent back. A more fully-fledged operational credentials delegate // would obtain a suitable key per fabric. uint8_t ipkValue[CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES]; - Crypto::AesCcm128KeySpan ipkSpan(ipkValue); + Crypto::IdentityProtectionKeySpan ipkSpan(ipkValue); ReturnErrorCodeIf(defaultIpkSpan.size() != sizeof(ipkValue), CHIP_ERROR_INTERNAL); diff --git a/src/controller/java/AndroidOperationalCredentialsIssuer.h b/src/controller/java/AndroidOperationalCredentialsIssuer.h index 49a845710b3e4b..11ca4a5c49d8df 100644 --- a/src/controller/java/AndroidOperationalCredentialsIssuer.h +++ b/src/controller/java/AndroidOperationalCredentialsIssuer.h @@ -53,7 +53,7 @@ class DLL_EXPORT AndroidOperationalCredentialsIssuer : public OperationalCredent Callback::Callback * onCompletion) override; CHIP_ERROR NOCChainGenerated(CHIP_ERROR status, const ByteSpan & noc, const ByteSpan & icac, const ByteSpan & rcac, - Optional ipk, Optional adminSubject); + Optional ipk, Optional adminSubject); void SetUseJavaCallbackForNOCRequest(bool useJavaCallbackForNOCRequest) { diff --git a/src/controller/java/CHIPDeviceController-JNI.cpp b/src/controller/java/CHIPDeviceController-JNI.cpp index 5716efe361ac0e..a973ba1d8c240f 100644 --- a/src/controller/java/CHIPDeviceController-JNI.cpp +++ b/src/controller/java/CHIPDeviceController-JNI.cpp @@ -202,9 +202,9 @@ JNI_METHOD(jint, onNOCChainGeneration) // use ipk and adminSubject from CommissioningParameters if not set in ControllerParams CommissioningParameters commissioningParams = wrapper->GetCommissioningParameters(); - Optional ipkOptional; + Optional ipkOptional; uint8_t ipkValue[CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES]; - Crypto::AesCcm128KeySpan ipkTempSpan(ipkValue); + Crypto::IdentityProtectionKeySpan ipkTempSpan(ipkValue); jbyteArray ipk = (jbyteArray) env->CallObjectMethod(controllerParams, getIpk); if (ipk != nullptr) diff --git a/src/controller/python/ChipDeviceController-IssueNocChain.cpp b/src/controller/python/ChipDeviceController-IssueNocChain.cpp index fe5b8ecc3919b0..9b450ce2bccb84 100644 --- a/src/controller/python/ChipDeviceController-IssueNocChain.cpp +++ b/src/controller/python/ChipDeviceController-IssueNocChain.cpp @@ -50,7 +50,7 @@ PyChipError pychip_DeviceController_IssueNOCChain(chip::Controller::DeviceCommis } void pychip_DeviceController_IssueNOCChainCallback(void * context, CHIP_ERROR status, const ByteSpan & noc, const ByteSpan & icac, - const ByteSpan & rcac, Optional ipk, + const ByteSpan & rcac, Optional ipk, Optional adminSubject) { if (pychip_DeviceController_IssueNOCChainCallbackPythonCallbackFunct == nullptr) @@ -65,8 +65,8 @@ void pychip_DeviceController_IssueNOCChainCallback(void * context, CHIP_ERROR st MutableByteSpan chipIcacSpan; MutableByteSpan chipRcacSpan; - Crypto::AesCcm128KeySpan ipkData; - ipkData = ipk.ValueOr(Crypto::AesCcm128KeySpan()); + Crypto::IdentityProtectionKeySpan ipkData; + ipkData = ipk.ValueOr(Crypto::IdentityProtectionKeySpan()); CHIP_ERROR err = status; if (err != CHIP_NO_ERROR) diff --git a/src/credentials/CHIPCert.cpp b/src/credentials/CHIPCert.cpp index 969448fe858d40..3d6af3db842e8e 100644 --- a/src/credentials/CHIPCert.cpp +++ b/src/credentials/CHIPCert.cpp @@ -296,7 +296,7 @@ CHIP_ERROR ChipCertificateSet::VerifySignature(const ChipCertificateData * cert, VerifyOrReturnError((cert != nullptr) && (caCert != nullptr), CHIP_ERROR_INVALID_ARGUMENT); ReturnErrorOnFailure(signature.SetLength(cert->mSignature.size())); - memcpy(signature, cert->mSignature.data(), cert->mSignature.size()); + memcpy(signature.Bytes(), cert->mSignature.data(), cert->mSignature.size()); memcpy(caPublicKey, caCert->mPublicKey.data(), caCert->mPublicKey.size()); diff --git a/src/credentials/CertificationDeclaration.cpp b/src/credentials/CertificationDeclaration.cpp index cbe79dd2d32ced..6b48bcfb8783bf 100644 --- a/src/credentials/CertificationDeclaration.cpp +++ b/src/credentials/CertificationDeclaration.cpp @@ -475,7 +475,7 @@ CHIP_ERROR EncodeSignerInfo(const ByteSpan & signerKeyId, const P256ECDSASignatu uint8_t asn1SignatureBuf[kMax_ECDSA_Signature_Length_Der]; MutableByteSpan asn1Signature(asn1SignatureBuf); - ReturnErrorOnFailure(EcdsaRawSignatureToAsn1(kP256_FE_Length, ByteSpan(signature, signature.Length()), asn1Signature)); + ReturnErrorOnFailure(EcdsaRawSignatureToAsn1(kP256_FE_Length, signature.Span(), asn1Signature)); // signature OCTET STRING ReturnErrorOnFailure(writer.PutOctetString(asn1Signature.data(), static_cast(asn1Signature.size()))); @@ -539,7 +539,7 @@ CHIP_ERROR DecodeSignerInfo(ASN1Reader & reader, ByteSpan & signerKeyId, P256ECD // signature OCTET STRING ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_OctetString); - MutableByteSpan signatureSpan(signature, signature.Capacity()); + MutableByteSpan signatureSpan(signature.Bytes(), signature.Capacity()); ReturnErrorOnFailure( EcdsaAsn1SignatureToRaw(kP256_FE_Length, ByteSpan(reader.GetValue(), reader.GetValueLen()), signatureSpan)); ReturnErrorOnFailure(signature.SetLength(signatureSpan.size())); diff --git a/src/credentials/tests/TestCertificationDeclaration.cpp b/src/credentials/tests/TestCertificationDeclaration.cpp index e0e678f176b56c..17a3667d90ce56 100644 --- a/src/credentials/tests/TestCertificationDeclaration.cpp +++ b/src/credentials/tests/TestCertificationDeclaration.cpp @@ -363,7 +363,7 @@ static void TestCD_CMSSignAndVerify(nlTestSuite * inSuite, void * inContext) // Test with known key P256Keypair keypair2; P256SerializedKeypair serializedKeypair; - memcpy(serializedKeypair, sTestCMS_SignerSerializedKeypair, sizeof(sTestCMS_SignerSerializedKeypair)); + memcpy(serializedKeypair.Bytes(), sTestCMS_SignerSerializedKeypair, sizeof(sTestCMS_SignerSerializedKeypair)); serializedKeypair.SetLength(sizeof(sTestCMS_SignerSerializedKeypair)); cdContentIn = ByteSpan(sTestCMS_CDContent02); signedMessage = MutableByteSpan(signedMessageBuf); diff --git a/src/credentials/tests/TestFabricTable.cpp b/src/credentials/tests/TestFabricTable.cpp index 04825393b83712..f098dc78bcb49a 100644 --- a/src/credentials/tests/TestFabricTable.cpp +++ b/src/credentials/tests/TestFabricTable.cpp @@ -89,8 +89,8 @@ static CHIP_ERROR LoadTestFabric_Node01_01(nlTestSuite * inSuite, FabricTable & static Crypto::P256Keypair opKey_Node01_01; FabricIndex fabricIndex; - memcpy((uint8_t *) (opKeysSerialized), TestCerts::sTestCert_Node01_01_PublicKey, TestCerts::sTestCert_Node01_01_PublicKey_Len); - memcpy((uint8_t *) (opKeysSerialized) + TestCerts::sTestCert_Node01_01_PublicKey_Len, TestCerts::sTestCert_Node01_01_PrivateKey, + memcpy(opKeysSerialized.Bytes(), TestCerts::sTestCert_Node01_01_PublicKey, TestCerts::sTestCert_Node01_01_PublicKey_Len); + memcpy(opKeysSerialized.Bytes() + TestCerts::sTestCert_Node01_01_PublicKey_Len, TestCerts::sTestCert_Node01_01_PrivateKey, TestCerts::sTestCert_Node01_01_PrivateKey_Len); ByteSpan rcacSpan(TestCerts::sTestCert_Root01_Chip, TestCerts::sTestCert_Root01_Chip_Len); @@ -119,8 +119,8 @@ static CHIP_ERROR LoadTestFabric_Node01_02(nlTestSuite * inSuite, FabricTable & FabricIndex fabricIndex; static Crypto::P256Keypair opKey_Node01_02; - memcpy((uint8_t *) (opKeysSerialized), TestCerts::sTestCert_Node01_02_PublicKey, TestCerts::sTestCert_Node01_02_PublicKey_Len); - memcpy((uint8_t *) (opKeysSerialized) + TestCerts::sTestCert_Node01_02_PublicKey_Len, TestCerts::sTestCert_Node01_02_PrivateKey, + memcpy(opKeysSerialized.Bytes(), TestCerts::sTestCert_Node01_02_PublicKey, TestCerts::sTestCert_Node01_02_PublicKey_Len); + memcpy(opKeysSerialized.Bytes() + TestCerts::sTestCert_Node01_02_PublicKey_Len, TestCerts::sTestCert_Node01_02_PrivateKey, TestCerts::sTestCert_Node01_02_PrivateKey_Len); ByteSpan rcacSpan(TestCerts::sTestCert_Root01_Chip, TestCerts::sTestCert_Root01_Chip_Len); @@ -151,8 +151,8 @@ static CHIP_ERROR LoadTestFabric_Node02_01(nlTestSuite * inSuite, FabricTable & FabricIndex fabricIndex; static Crypto::P256Keypair opKey_Node02_01; - memcpy((uint8_t *) (opKeysSerialized), TestCerts::sTestCert_Node02_01_PublicKey, TestCerts::sTestCert_Node02_01_PublicKey_Len); - memcpy((uint8_t *) (opKeysSerialized) + TestCerts::sTestCert_Node02_01_PublicKey_Len, TestCerts::sTestCert_Node02_01_PrivateKey, + memcpy(opKeysSerialized.Bytes(), TestCerts::sTestCert_Node02_01_PublicKey, TestCerts::sTestCert_Node02_01_PublicKey_Len); + memcpy(opKeysSerialized.Bytes() + TestCerts::sTestCert_Node02_01_PublicKey_Len, TestCerts::sTestCert_Node02_01_PrivateKey, TestCerts::sTestCert_Node02_01_PrivateKey_Len); ByteSpan rcacSpan(TestCerts::sTestCert_Root02_Chip, TestCerts::sTestCert_Root02_Chip_Len); diff --git a/src/crypto/CHIPCryptoPAL.h b/src/crypto/CHIPCryptoPAL.h index 00733b7d9e7402..36f9310c596360 100644 --- a/src/crypto/CHIPCryptoPAL.h +++ b/src/crypto/CHIPCryptoPAL.h @@ -228,68 +228,118 @@ class ECPKey const Sig & signature) const = 0; }; -template -class CapacityBoundBuffer +template +class SensitiveDataBuffer { public: - ~CapacityBoundBuffer() + ~SensitiveDataBuffer() { // Sanitize after use - ClearSecretData(&bytes[0], Cap); + ClearSecretData(mBytes); } - CapacityBoundBuffer & operator=(const CapacityBoundBuffer & other) + SensitiveDataBuffer & operator=(const SensitiveDataBuffer & other) { // Guard self assignment if (this == &other) return *this; - ClearSecretData(&bytes[0], Cap); + ClearSecretData(mBytes); SetLength(other.Length()); - ::memcpy(Bytes(), other.Bytes(), other.Length()); + ::memcpy(Bytes(), other.ConstBytes(), other.Length()); return *this; } - /** @brief Set current length of the buffer that's being used - * @return Returns error if new length is > capacity - **/ - CHIP_ERROR SetLength(size_t len) + /** + * @brief Set current length of the buffer + * @return Error if new length is exceeds capacity of the buffer + */ + CHIP_ERROR SetLength(size_t length) { - VerifyOrReturnError(len <= sizeof(bytes), CHIP_ERROR_INVALID_ARGUMENT); - length = len; + VerifyOrReturnError(length <= kCapacity, CHIP_ERROR_INVALID_ARGUMENT); + mLength = length; return CHIP_NO_ERROR; } - /** @brief Returns current length of the buffer that's being used - * @return Returns 0 if SetLength() was never called - **/ - size_t Length() const { return length; } + /** + * @brief Returns current length of the buffer + */ + size_t Length() const { return mLength; } - /** @brief Returns max capacity of the buffer - **/ - static constexpr size_t Capacity() { return sizeof(bytes); } + /** + * @brief Returns non-const pointer to start of the underlying buffer + */ + uint8_t * Bytes() { return &mBytes[0]; } - /** @brief Returns pointer to start of underlying buffer - **/ - uint8_t * Bytes() { return &bytes[0]; } + /** + * @brief Returns const pointer to start of the underlying buffer + */ + const uint8_t * ConstBytes() const { return &mBytes[0]; } - /** @brief Returns const pointer to start of underlying buffer - **/ - const uint8_t * ConstBytes() const { return &bytes[0]; } + /** + * @brief Constructs fixed span from the underlying buffer + */ + ByteSpan Span() const { return ByteSpan(ConstBytes(), Length()); } - /** @brief Returns buffer pointer - **/ - operator uint8_t *() { return bytes; } - operator const uint8_t *() const { return bytes; } + /** + * @brief Returns capacity of the buffer + */ + static constexpr size_t Capacity() { return kCapacity; } + +private: + uint8_t mBytes[kCapacity]; + size_t mLength = 0; +}; + +template +class SensitiveDataFixedBuffer +{ +public: + constexpr explicit SensitiveDataFixedBuffer(const uint8_t (&rawValue)[kCapacity]) + { + memcpy(&mBytes[0], &rawValue[0], kCapacity); + } + + constexpr explicit SensitiveDataFixedBuffer(const FixedByteSpan & value) + { + memcpy(&mBytes[0], value.data(), kCapacity); + } + + ~SensitiveDataFixedBuffer() + { + // Sanitize after use + ClearSecretData(mBytes); + } + + /** + * @brief Returns fixed length of the buffer + */ + constexpr size_t Length() const { return kCapacity; } + + /** + * @brief Returns non-const pointer to start of the underlying buffer + */ + uint8_t * Bytes() { return &mBytes[0]; } + + /** + * @brief Returns const pointer to start of the underlying buffer + */ + const uint8_t * ConstBytes() const { return &mBytes[0]; } + + /** + * @brief Constructs span from the underlying buffer + */ + FixedByteSpan Span() const { return FixedByteSpan(mBytes); } private: - uint8_t bytes[Cap]; - size_t length = 0; + uint8_t mBytes[kCapacity]; }; -typedef CapacityBoundBuffer P256ECDSASignature; +using P256ECDSASignature = SensitiveDataBuffer; +using P256ECDHDerivedSecret = SensitiveDataBuffer; -typedef CapacityBoundBuffer P256ECDHDerivedSecret; +using IdentityProtectionKey = SensitiveDataFixedBuffer; +using IdentityProtectionKeySpan = FixedByteSpan; class P256PublicKey : public ECPKey { @@ -382,7 +432,7 @@ struct alignas(size_t) P256KeypairContext uint8_t mBytes[kMAX_P256Keypair_Context_Size]; }; -typedef CapacityBoundBuffer P256SerializedKeypair; +using P256SerializedKeypair = SensitiveDataBuffer; class P256KeypairBase : public ECPKeypair { @@ -477,47 +527,6 @@ class P256Keypair : public P256KeypairBase bool mInitialized = false; }; -/** - * @brief A data structure for holding an AES CCM128 symmetric key, without the ownership of it. - */ -using AesCcm128KeySpan = FixedByteSpan; - -class AesCcm128Key -{ -public: - AesCcm128Key() {} - - ~AesCcm128Key() - { - // Sanitize after use - ClearSecretData(&bytes[0], Length()); - } - - template - constexpr AesCcm128Key(const uint8_t (&raw_value)[N]) - { - static_assert(N == kAES_CCM128_Key_Length, "Can only array-initialize from proper bounds"); - memcpy(&bytes[0], &raw_value[0], N); - } - - template - constexpr AesCcm128Key(const FixedByteSpan & value) - { - static_assert(N == kAES_CCM128_Key_Length, "Can only initialize from proper sized byte span"); - memcpy(&bytes[0], value.data(), N); - } - - size_t Length() const { return sizeof(bytes); } - operator uint8_t *() { return bytes; } - operator const uint8_t *() const { return bytes; } - const uint8_t * ConstBytes() const { return &bytes[0]; } - AesCcm128KeySpan Span() const { return AesCcm128KeySpan(bytes); } - uint8_t * Bytes() { return &bytes[0]; } - -private: - uint8_t bytes[kAES_CCM128_Key_Length]; -}; - /** * @brief Convert a raw ECDSA signature to ASN.1 signature (per X9.62) as used by TLS libraries. * @@ -1415,8 +1424,6 @@ CHIP_ERROR GenerateCompressedFabricId(const Crypto::P256PublicKey & root_public_ CHIP_ERROR GenerateCompressedFabricId(const Crypto::P256PublicKey & rootPublicKey, uint64_t fabricId, uint64_t & compressedFabricId); -typedef CapacityBoundBuffer X509DerCertificate; - enum class CertificateChainValidationResult { kSuccess = 0, diff --git a/src/crypto/CHIPCryptoPALOpenSSL.cpp b/src/crypto/CHIPCryptoPALOpenSSL.cpp index def307997f5e04..f914b2a59b742e 100644 --- a/src/crypto/CHIPCryptoPALOpenSSL.cpp +++ b/src/crypto/CHIPCryptoPALOpenSSL.cpp @@ -941,7 +941,7 @@ CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_k VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL); out_buf_length = (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length(); - result = EVP_PKEY_derive(context, Uint8::to_uchar(out_secret), &out_buf_length); + result = EVP_PKEY_derive(context, out_secret.Bytes(), &out_buf_length); VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL); SuccessOrExit(out_secret.SetLength(out_buf_length)); @@ -1077,7 +1077,7 @@ CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const { size_t len = output.Length() == 0 ? output.Capacity() : output.Length(); - Encoding::BufferWriter bbuf(output, len); + Encoding::BufferWriter bbuf(output.Bytes(), len); bbuf.Put(mPublicKey, mPublicKey.Length()); bbuf.Put(privkey, sizeof(privkey)); VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY); @@ -1108,10 +1108,10 @@ CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input) int result = 0; int nid = NID_undef; - const uint8_t * privkey = Uint8::to_const_uchar(input) + mPublicKey.Length(); + const uint8_t * privkey = input.ConstBytes() + mPublicKey.Length(); VerifyOrExit(input.Length() == mPublicKey.Length() + kP256_PrivateKey_Length, error = CHIP_ERROR_INVALID_ARGUMENT); - bbuf.Put(input, mPublicKey.Length()); + bbuf.Put(input.ConstBytes(), mPublicKey.Length()); VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY); nid = _nidForCurve(curve); diff --git a/src/crypto/CHIPCryptoPALTinyCrypt.cpp b/src/crypto/CHIPCryptoPALTinyCrypt.cpp index dd6f875a58287b..c7b4d08ac94b4e 100644 --- a/src/crypto/CHIPCryptoPALTinyCrypt.cpp +++ b/src/crypto/CHIPCryptoPALTinyCrypt.cpp @@ -584,7 +584,7 @@ CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_k VerifyOrExit(mInitialized, error = CHIP_ERROR_WELL_UNINITIALIZED); // Fully padded raw uncompressed points expected, first byte is always 0x04 i.e uncompressed - result = uECC_shared_secret(remote_public_key.ConstBytes() + 1, keypair->private_key, Uint8::to_uchar(out_secret)); + result = uECC_shared_secret(remote_public_key.ConstBytes() + 1, keypair->private_key, out_secret.Bytes()); VerifyOrExit(result == UECC_SUCCESS, error = CHIP_ERROR_INTERNAL); SuccessOrExit(out_secret.SetLength(secret_length)); @@ -657,7 +657,7 @@ CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const { const mbedtls_uecc_keypair * keypair = to_const_keypair(&mKeypair); size_t len = output.Length() == 0 ? output.Capacity() : output.Length(); - Encoding::BufferWriter bbuf(output, len); + Encoding::BufferWriter bbuf(output.Bytes(), len); uint8_t privkey[kP256_PrivateKey_Length]; CHIP_ERROR error = CHIP_NO_ERROR; int result = 0; diff --git a/src/crypto/CHIPCryptoPALmbedTLS.cpp b/src/crypto/CHIPCryptoPALmbedTLS.cpp index ff42f9e3df411b..95c44e43a0241c 100644 --- a/src/crypto/CHIPCryptoPALmbedTLS.cpp +++ b/src/crypto/CHIPCryptoPALmbedTLS.cpp @@ -664,7 +664,7 @@ CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_k mbedtls_ecdh_compute_shared(&ecp_grp, &mpi_secret, &ecp_pubkey, &keypair->CHIP_CRYPTO_PAL_PRIVATE(d), CryptoRNG, nullptr); VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); - result = mbedtls_mpi_write_binary(&mpi_secret, Uint8::to_uchar(out_secret), secret_length); + result = mbedtls_mpi_write_binary(&mpi_secret, out_secret.Bytes(), secret_length); VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); SuccessOrExit(out_secret.SetLength(secret_length)); @@ -753,7 +753,7 @@ CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const { const mbedtls_ecp_keypair * keypair = to_const_keypair(&mKeypair); size_t len = output.Length() == 0 ? output.Capacity() : output.Length(); - Encoding::BufferWriter bbuf(output, len); + Encoding::BufferWriter bbuf(output.Bytes(), len); uint8_t privkey[kP256_PrivateKey_Length]; CHIP_ERROR error = CHIP_NO_ERROR; int result = 0; @@ -795,7 +795,7 @@ CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input) VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); VerifyOrExit(input.Length() == mPublicKey.Length() + kP256_PrivateKey_Length, error = CHIP_ERROR_INVALID_ARGUMENT); - bbuf.Put((const uint8_t *) input, mPublicKey.Length()); + bbuf.Put(input.ConstBytes(), mPublicKey.Length()); VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY); result = mbedtls_ecp_point_read_binary(&keypair->CHIP_CRYPTO_PAL_PRIVATE(grp), &keypair->CHIP_CRYPTO_PAL_PRIVATE(Q), @@ -803,7 +803,7 @@ CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input) VerifyOrExit(result == 0, error = CHIP_ERROR_INVALID_ARGUMENT); { - const uint8_t * privkey = Uint8::to_const_uchar(input) + mPublicKey.Length(); + const uint8_t * privkey = input.ConstBytes() + mPublicKey.Length(); result = mbedtls_mpi_read_binary(&keypair->CHIP_CRYPTO_PAL_PRIVATE(d), privkey, kP256_PrivateKey_Length); VerifyOrExit(result == 0, error = CHIP_ERROR_INVALID_ARGUMENT); diff --git a/src/crypto/PersistentStorageOperationalKeystore.cpp b/src/crypto/PersistentStorageOperationalKeystore.cpp index f578c5a8ad74dc..d1d5b2f725c40d 100644 --- a/src/crypto/PersistentStorageOperationalKeystore.cpp +++ b/src/crypto/PersistentStorageOperationalKeystore.cpp @@ -57,8 +57,8 @@ CHIP_ERROR StoreOperationalKey(FabricIndex fabricIndex, PersistentStorageDelegat VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && (storage != nullptr) && (keypair != nullptr), CHIP_ERROR_INVALID_ARGUMENT); - // Use a CapacityBoundBuffer to get RAII secret data clearing on scope exit. - Crypto::CapacityBoundBuffer buf; + // Use a SensitiveDataBuffer to get RAII secret data clearing on scope exit. + Crypto::SensitiveDataBuffer buf; TLV::TLVWriter writer; writer.Init(buf.Bytes(), buf.Capacity()); @@ -80,7 +80,7 @@ CHIP_ERROR StoreOperationalKey(FabricIndex fabricIndex, PersistentStorageDelegat const auto opKeyLength = writer.GetLengthWritten(); VerifyOrReturnError(CanCastTo(opKeyLength), CHIP_ERROR_BUFFER_TOO_SMALL); - ReturnErrorOnFailure(storage->SyncSetKeyValue(DefaultStorageKeyAllocator::FabricOpKey(fabricIndex).KeyName(), buf, + ReturnErrorOnFailure(storage->SyncSetKeyValue(DefaultStorageKeyAllocator::FabricOpKey(fabricIndex).KeyName(), buf.ConstBytes(), static_cast(opKeyLength))); return CHIP_NO_ERROR; @@ -107,8 +107,8 @@ CHIP_ERROR SignWithStoredOpKey(FabricIndex fabricIndex, PersistentStorageDelegat // Scope 1: Load up the keypair data from storage { - // Use a CapacityBoundBuffer to get RAII secret data clearing on scope exit. - Crypto::CapacityBoundBuffer buf; + // Use a SensitiveDataBuffer to get RAII secret data clearing on scope exit. + Crypto::SensitiveDataBuffer buf; // Load up the operational key structure from storage uint16_t size = static_cast(buf.Capacity()); @@ -177,8 +177,8 @@ bool PersistentStorageOperationalKeystore::HasOpKeypairForFabric(FabricIndex fab // properly enforcing CHIP_ERROR_BUFFER_TOO_SMALL behavior needed by // PersistentStorageDelegate. Very unfortunate, needs fixing ASAP. - // Use a CapacityBoundBuffer to get RAII secret data clearing on scope exit. - Crypto::CapacityBoundBuffer buf; + // Use a SensitiveDataBuffer to get RAII secret data clearing on scope exit. + Crypto::SensitiveDataBuffer buf; uint16_t keySize = static_cast(buf.Capacity()); CHIP_ERROR err = diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp b/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp index 6374b98cbda08e..737ba703b265ca 100644 --- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp +++ b/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp @@ -208,7 +208,7 @@ CHIP_ERROR P256KeypairHSM::ECDSA_sign_msg(const uint8_t * msg, size_t msg_length CHIP_ERROR P256KeypairHSM::Serialize(P256SerializedKeypair & output) const { const size_t len = output.Length() == 0 ? output.Capacity() : output.Length(); - Encoding::BufferWriter bbuf(output, len); + Encoding::BufferWriter bbuf(output.Bytes(), len); uint8_t privkey[kP256_PrivateKey_Length] = { 0, }; @@ -249,7 +249,7 @@ CHIP_ERROR P256KeypairHSM::Deserialize(P256SerializedKeypair & input) VerifyOrReturnError(bbuf.Fit(), CHIP_ERROR_NO_MEMORY); { /* When HSM is used for ECC key generation, key info in stored in private key buffer */ - const uint8_t * privkey = Uint8::to_const_uchar(input) + public_key.Length(); + const uint8_t * privkey = input.ConstBytes() + public_key.Length(); keyid = Encoding::LittleEndian::Get32(privkey); public_key.SetPublicKeyId(keyid); } diff --git a/src/crypto/tests/CHIPCryptoPALTest.cpp b/src/crypto/tests/CHIPCryptoPALTest.cpp index ae96316fff0002..ffbc72090f5beb 100644 --- a/src/crypto/tests/CHIPCryptoPALTest.cpp +++ b/src/crypto/tests/CHIPCryptoPALTest.cpp @@ -460,38 +460,76 @@ static void TestAES_CCM_128DecryptInvalidNonceLen(nlTestSuite * inSuite, void * NL_TEST_ASSERT(inSuite, numOfTestsRan > 0); } -static void TestAES_CCM_128Containers(nlTestSuite * inSuite, void * inContext) +static void TestSensitiveDataBuffer(nlTestSuite * inSuite, void * inContext) { HeapChecker heapChecker(inSuite); - uint8_t testVector[kAES_CCM128_Key_Length]; - AesCcm128Key deepCopy; - AesCcm128KeySpan shallowCopy; - CHIP_ERROR err = CHIP_NO_ERROR; + + constexpr size_t kCapacity = 32; + constexpr size_t kLength = 16; + using Buffer = SensitiveDataBuffer; + const uint8_t kAllZeros[kCapacity] = { 0 }; + uint8_t testVector[kCapacity]; // Give us some data. - err = DRBG_get_bytes(testVector, sizeof(testVector)); + CHIP_ERROR err = DRBG_get_bytes(testVector, sizeof(testVector)); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - // Test deep copy from array. - deepCopy = AesCcm128Key(testVector); - NL_TEST_ASSERT(inSuite, memcmp(deepCopy, testVector, sizeof(testVector)) == 0); + // Test initial value + Buffer buffer; + NL_TEST_ASSERT(inSuite, buffer.ConstBytes() == (const uint8_t *) buffer.Bytes()); + NL_TEST_ASSERT(inSuite, buffer.Length() == 0); + + // Put data in the buffer and test all accessors + memcpy(buffer.Bytes(), testVector, kCapacity); + buffer.SetLength(kLength); + + NL_TEST_ASSERT(inSuite, buffer.ConstBytes() == (const uint8_t *) buffer.Bytes()); + NL_TEST_ASSERT(inSuite, buffer.ConstBytes() == buffer.Span().data()); + NL_TEST_ASSERT(inSuite, buffer.Length() == kLength); + NL_TEST_ASSERT(inSuite, buffer.Length() == buffer.Span().size()); + + // Test sanitization of entire buffer (even though length < capacity) + const void * bufferStorage = buffer.ConstBytes(); + buffer.~Buffer(); + NL_TEST_ASSERT(inSuite, memcmp(bufferStorage, kAllZeros, kCapacity) == 0); + NL_TEST_ASSERT(inSuite, memcmp(bufferStorage, testVector, kCapacity)); +} - // Test sanitization. - deepCopy.~AesCcm128Key(); - new (&deepCopy) AesCcm128Key(); - NL_TEST_ASSERT(inSuite, memcmp(deepCopy, testVector, sizeof(testVector))); +static void TestSensitiveDataFixedBuffer(nlTestSuite * inSuite, void * inContext) +{ + HeapChecker heapChecker(inSuite); - // Give us different data. - err = DRBG_get_bytes(testVector, sizeof(testVector)); + constexpr size_t kCapacity = 32; + using Buffer = SensitiveDataFixedBuffer; + using BufferSpan = FixedByteSpan; + const uint8_t kAllZeros[kCapacity] = { 0 }; + uint8_t testVector[kCapacity]; + + // Give us some data. + CHIP_ERROR err = DRBG_get_bytes(testVector, sizeof(testVector)); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - // Test deep copy from KeySpan. - shallowCopy = AesCcm128KeySpan(testVector); - deepCopy = AesCcm128Key(shallowCopy); - NL_TEST_ASSERT(inSuite, memcmp(deepCopy, testVector, sizeof(testVector)) == 0); + // Test construction from array and all accessors + Buffer buffer(testVector); + NL_TEST_ASSERT(inSuite, buffer.ConstBytes() == (const uint8_t *) buffer.Bytes()); + NL_TEST_ASSERT(inSuite, buffer.ConstBytes() == buffer.Span().data()); + NL_TEST_ASSERT(inSuite, memcmp(buffer.ConstBytes(), testVector, kCapacity) == 0); + + // Test sanitization + const void * bufferStorage = buffer.ConstBytes(); + buffer.~Buffer(); + NL_TEST_ASSERT(inSuite, memcmp(bufferStorage, kAllZeros, kCapacity) == 0); + NL_TEST_ASSERT(inSuite, memcmp(bufferStorage, testVector, kCapacity)); + + // Give us different data + err = DRBG_get_bytes(testVector, sizeof(testVector)); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - // Test Span getter. - NL_TEST_ASSERT(inSuite, memcmp(testVector, deepCopy.Span().data(), deepCopy.Span().size()) == 0); + // Test construction from span and all accessors + new (&buffer) Buffer(BufferSpan(testVector)); + NL_TEST_ASSERT(inSuite, buffer.ConstBytes() == (const uint8_t *) buffer.Bytes()); + NL_TEST_ASSERT(inSuite, buffer.ConstBytes() == buffer.Span().data()); + NL_TEST_ASSERT(inSuite, memcmp(buffer.ConstBytes(), testVector, kCapacity) == 0); } static void TestAsn1Conversions(nlTestSuite * inSuite, void * inContext) @@ -919,7 +957,7 @@ static void TestECDSA_ValidationFailIncorrectMsgSignature(nlTestSuite * inSuite, P256ECDSASignature signature; CHIP_ERROR signing_error = keypair.ECDSA_sign_msg(reinterpret_cast(msg), msg_length, signature); NL_TEST_ASSERT(inSuite, signing_error == CHIP_NO_ERROR); - signature[0] = static_cast(~signature[0]); // Flipping bits should invalidate the signature. + signature.Bytes()[0] = static_cast(~signature.ConstBytes()[0]); // Flipping bits should invalidate the signature. CHIP_ERROR validation_error = keypair.Pubkey().ECDSA_validate_msg_signature(reinterpret_cast(msg), msg_length, signature); @@ -942,7 +980,7 @@ static void TestECDSA_ValidationFailIncorrectHashSignature(nlTestSuite * inSuite P256ECDSASignature signature; CHIP_ERROR signing_error = keypair.ECDSA_sign_msg(msg, msg_length, signature); NL_TEST_ASSERT(inSuite, signing_error == CHIP_NO_ERROR); - signature[0] = static_cast(~signature[0]); // Flipping bits should invalidate the signature. + signature.Bytes()[0] = static_cast(~signature.ConstBytes()[0]); // Flipping bits should invalidate the signature. CHIP_ERROR validation_error = keypair.Pubkey().ECDSA_validate_hash_signature(hash, sizeof(hash), signature); NL_TEST_ASSERT(inSuite, validation_error == CHIP_ERROR_INVALID_SIGNATURE); @@ -1029,14 +1067,14 @@ static void TestECDH_EstablishSecret(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, keypair2.Initialize(ECPKeyTarget::ECDH) == CHIP_NO_ERROR); P256ECDHDerivedSecret out_secret1; - out_secret1[0] = 0; + out_secret1.Bytes()[0] = 0; P256ECDHDerivedSecret out_secret2; - out_secret2[0] = 1; + out_secret2.Bytes()[0] = 1; CHIP_ERROR error = CHIP_NO_ERROR; NL_TEST_ASSERT(inSuite, - memcmp(Uint8::to_uchar(out_secret1), Uint8::to_uchar(out_secret2), out_secret1.Capacity()) != + memcmp(out_secret1.ConstBytes(), out_secret2.ConstBytes(), out_secret1.Capacity()) != 0); // Validate that buffers are indeed different. error = keypair2.ECDH_derive_secret(keypair1.Pubkey(), out_secret1); @@ -1048,7 +1086,7 @@ static void TestECDH_EstablishSecret(nlTestSuite * inSuite, void * inContext) bool signature_lengths_match = out_secret1.Length() == out_secret2.Length(); NL_TEST_ASSERT(inSuite, signature_lengths_match); - bool signatures_match = (memcmp(Uint8::to_uchar(out_secret1), Uint8::to_uchar(out_secret2), out_secret1.Length()) == 0); + bool signatures_match = (memcmp(out_secret1.ConstBytes(), out_secret2.ConstBytes(), out_secret1.Length()) == 0); NL_TEST_ASSERT(inSuite, signatures_match); } @@ -2498,7 +2536,6 @@ static const nlTest sTests[] = { NL_TEST_DEF("Test encrypting AES-CCM-128 using invalid tag", TestAES_CCM_128EncryptInvalidTagLen), NL_TEST_DEF("Test decrypting AES-CCM-128 invalid key", TestAES_CCM_128DecryptInvalidKey), NL_TEST_DEF("Test decrypting AES-CCM-128 invalid nonce", TestAES_CCM_128DecryptInvalidNonceLen), - NL_TEST_DEF("Test decrypting AES-CCM-128 Containers", TestAES_CCM_128Containers), NL_TEST_DEF("Test encrypt/decrypt AES-CTR-128 test vectors", TestAES_CTR_128CryptTestVectors), NL_TEST_DEF("Test ASN.1 signature conversion routines", TestAsn1Conversions), NL_TEST_DEF("Test Integer to ASN.1 DER conversion", TestRawIntegerToDerValidCases), @@ -2547,6 +2584,8 @@ static const nlTest sTests[] = { NL_TEST_DEF("Test Group Operation Key Derivation", TestGroup_OperationalKeyDerivation), NL_TEST_DEF("Test Group Session ID Derivation", TestGroup_SessionIdDerivation), NL_TEST_DEF("Test Group Privacy Key Derivation", TestGroup_PrivacyKeyDerivation), + NL_TEST_DEF("Test sensitive data buffer", TestSensitiveDataBuffer), + NL_TEST_DEF("Test sensitive data fixed buffer", TestSensitiveDataFixedBuffer), NL_TEST_SENTINEL() }; diff --git a/src/darwin/Framework/CHIP/MTROperationalCredentialsDelegate.h b/src/darwin/Framework/CHIP/MTROperationalCredentialsDelegate.h index f31eb18a631b89..8f0f10a813d0e7 100644 --- a/src/darwin/Framework/CHIP/MTROperationalCredentialsDelegate.h +++ b/src/darwin/Framework/CHIP/MTROperationalCredentialsDelegate.h @@ -79,7 +79,7 @@ class MTROperationalCredentialsDelegate : public chip::Controller::OperationalCr CHIP_ERROR GenerateNOC(chip::NodeId nodeId, chip::FabricId fabricId, const chip::CATValues & cats, const chip::Crypto::P256PublicKey & pubkey, chip::MutableByteSpan & noc); - const chip::Crypto::AesCcm128KeySpan GetIPK() { return mIPK.Span(); } + const chip::Crypto::IdentityProtectionKeySpan GetIPK() { return mIPK.Span(); } // Get the root/intermediate X.509 DER certs as a ByteSpan. chip::ByteSpan RootCertSpan() const; @@ -133,7 +133,7 @@ class MTROperationalCredentialsDelegate : public chip::Controller::OperationalCr ChipP256KeypairPtr mIssuerKey; - chip::Crypto::AesCcm128Key mIPK; + chip::Crypto::IdentityProtectionKey mIPK; static const uint32_t kCertificateValiditySecs = 365 * 24 * 60 * 60; diff --git a/src/darwin/Framework/CHIP/MTROperationalCredentialsDelegate.mm b/src/darwin/Framework/CHIP/MTROperationalCredentialsDelegate.mm index 467528a01252d9..d66a9053bc4c77 100644 --- a/src/darwin/Framework/CHIP/MTROperationalCredentialsDelegate.mm +++ b/src/darwin/Framework/CHIP/MTROperationalCredentialsDelegate.mm @@ -249,7 +249,7 @@ return; } - AesCcm128KeySpan ipk = commissioningParameters.Value().GetIpk().ValueOr(GetIPK()); + IdentityProtectionKeySpan ipk = commissioningParameters.Value().GetIpk().ValueOr(GetIPK()); Optional adminSubject; if (info.adminSubject != nil) { diff --git a/src/platform/silabs/EFR32/CHIPCryptoPALPsaEfr32.cpp b/src/platform/silabs/EFR32/CHIPCryptoPALPsaEfr32.cpp index 184da071eeddce..03f78882e3a031 100644 --- a/src/platform/silabs/EFR32/CHIPCryptoPALPsaEfr32.cpp +++ b/src/platform/silabs/EFR32/CHIPCryptoPALPsaEfr32.cpp @@ -873,7 +873,7 @@ CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const CHIP_ERROR error = CHIP_NO_ERROR; const psa_plaintext_ecp_keypair * keypair = to_const_keypair(&mKeypair); size_t len = output.Length() == 0 ? output.Capacity() : output.Length(); - Encoding::BufferWriter bbuf(output, len); + Encoding::BufferWriter bbuf(output.Bytes(), len); VerifyOrExit(mInitialized, error = CHIP_ERROR_WELL_UNINITIALIZED); diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index 67351f96c0903a..005e12d3bddc4c 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -317,7 +317,7 @@ CHIP_ERROR CASESession::DeriveSecureSession(CryptoContext & session) const VerifyOrReturnError(bbuf.Fit(), CHIP_ERROR_BUFFER_TOO_SMALL); } - ReturnErrorOnFailure(session.InitFromSecret(ByteSpan(mSharedSecret, mSharedSecret.Length()), ByteSpan(msg_salt), + ReturnErrorOnFailure(session.InitFromSecret(mSharedSecret.Span(), ByteSpan(msg_salt), CryptoContext::SessionInfoType::kSessionEstablishment, mRole)); return CHIP_NO_ERROR; @@ -333,7 +333,7 @@ CHIP_ERROR CASESession::DeriveSecureSession(CryptoContext & session) const VerifyOrReturnError(bbuf.Fit(), CHIP_ERROR_BUFFER_TOO_SMALL); } - ReturnErrorOnFailure(session.InitFromSecret(ByteSpan(mSharedSecret, mSharedSecret.Length()), ByteSpan(msg_salt), + ReturnErrorOnFailure(session.InitFromSecret(mSharedSecret.Span(), ByteSpan(msg_salt), CryptoContext::SessionInfoType::kSessionResumption, mRole)); return CHIP_NO_ERROR; @@ -745,8 +745,8 @@ CHIP_ERROR CASESession::SendSigma2() HKDF_sha_crypto mHKDF; uint8_t sr2k[CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES]; - ReturnErrorOnFailure(mHKDF.HKDF_SHA256(mSharedSecret, mSharedSecret.Length(), saltSpan.data(), saltSpan.size(), kKDFSR2Info, - kKDFInfoLength, sr2k, CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES)); + ReturnErrorOnFailure(mHKDF.HKDF_SHA256(mSharedSecret.ConstBytes(), mSharedSecret.Length(), saltSpan.data(), saltSpan.size(), + kKDFSR2Info, kKDFInfoLength, sr2k, CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES)); // Construct Sigma2 TBS Data size_t msg_r2_signed_len = @@ -791,7 +791,7 @@ CHIP_ERROR CASESession::SendSigma2() nocCert = MutableByteSpan{}; } - ReturnErrorOnFailure(tlvWriter.PutBytes(TLV::ContextTag(kTag_TBEData_Signature), tbsData2Signature, + ReturnErrorOnFailure(tlvWriter.PutBytes(TLV::ContextTag(kTag_TBEData_Signature), tbsData2Signature.ConstBytes(), static_cast(tbsData2Signature.Length()))); // Generate a new resumption ID @@ -992,7 +992,7 @@ CHIP_ERROR CASESession::HandleSigma2(System::PacketBufferHandle && msg) SuccessOrExit(err); HKDF_sha_crypto mHKDF; - err = mHKDF.HKDF_SHA256(mSharedSecret, mSharedSecret.Length(), saltSpan.data(), saltSpan.size(), kKDFSR2Info, + err = mHKDF.HKDF_SHA256(mSharedSecret.ConstBytes(), mSharedSecret.Length(), saltSpan.data(), saltSpan.size(), kKDFSR2Info, kKDFInfoLength, sr2k, CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES); SuccessOrExit(err); } @@ -1057,7 +1057,7 @@ CHIP_ERROR CASESession::HandleSigma2(System::PacketBufferHandle && msg) VerifyOrExit(TLV::TagNumFromTag(decryptedDataTlvReader.GetTag()) == kTag_TBEData_Signature, err = CHIP_ERROR_INVALID_TLV_TAG); VerifyOrExit(tbsData2Signature.Capacity() >= decryptedDataTlvReader.GetLength(), err = CHIP_ERROR_INVALID_TLV_ELEMENT); tbsData2Signature.SetLength(decryptedDataTlvReader.GetLength()); - SuccessOrExit(err = decryptedDataTlvReader.GetBytes(tbsData2Signature, tbsData2Signature.Length())); + SuccessOrExit(err = decryptedDataTlvReader.GetBytes(tbsData2Signature.Bytes(), tbsData2Signature.Length())); // Validate signature SuccessOrExit(err = responderPublicKey.ECDSA_validate_msg_signature(msg_R2_Signed.Get(), msg_r2_signed_len, tbsData2Signature)); @@ -1163,7 +1163,7 @@ CHIP_ERROR CASESession::SendSigma3() nocCert = MutableByteSpan{}; } - SuccessOrExit(err = tlvWriter.PutBytes(TLV::ContextTag(kTag_TBEData_Signature), tbsData3Signature, + SuccessOrExit(err = tlvWriter.PutBytes(TLV::ContextTag(kTag_TBEData_Signature), tbsData3Signature.ConstBytes(), static_cast(tbsData3Signature.Length()))); SuccessOrExit(err = tlvWriter.EndContainer(outerContainerType)); SuccessOrExit(err = tlvWriter.Finalize()); @@ -1177,7 +1177,7 @@ CHIP_ERROR CASESession::SendSigma3() SuccessOrExit(err); HKDF_sha_crypto mHKDF; - err = mHKDF.HKDF_SHA256(mSharedSecret, mSharedSecret.Length(), saltSpan.data(), saltSpan.size(), kKDFSR3Info, + err = mHKDF.HKDF_SHA256(mSharedSecret.ConstBytes(), mSharedSecret.Length(), saltSpan.data(), saltSpan.size(), kKDFSR3Info, kKDFInfoLength, sr3k, CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES); SuccessOrExit(err); } @@ -1299,7 +1299,7 @@ CHIP_ERROR CASESession::HandleSigma3(System::PacketBufferHandle && msg) SuccessOrExit(err); HKDF_sha_crypto mHKDF; - err = mHKDF.HKDF_SHA256(mSharedSecret, mSharedSecret.Length(), saltSpan.data(), saltSpan.size(), kKDFSR3Info, + err = mHKDF.HKDF_SHA256(mSharedSecret.ConstBytes(), mSharedSecret.Length(), saltSpan.data(), saltSpan.size(), kKDFSR3Info, kKDFInfoLength, sr3k, CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES); SuccessOrExit(err); } @@ -1347,7 +1347,7 @@ CHIP_ERROR CASESession::HandleSigma3(System::PacketBufferHandle && msg) VerifyOrExit(TLV::TagNumFromTag(decryptedDataTlvReader.GetTag()) == kTag_TBEData_Signature, err = CHIP_ERROR_INVALID_TLV_TAG); VerifyOrExit(tbsData3Signature.Capacity() >= decryptedDataTlvReader.GetLength(), err = CHIP_ERROR_INVALID_TLV_ELEMENT); tbsData3Signature.SetLength(decryptedDataTlvReader.GetLength()); - SuccessOrExit(err = decryptedDataTlvReader.GetBytes(tbsData3Signature, tbsData3Signature.Length())); + SuccessOrExit(err = decryptedDataTlvReader.GetBytes(tbsData3Signature.Bytes(), tbsData3Signature.Length())); // TODO - Validate message signature prior to validating the received operational credentials. // The op cert check requires traversal of cert chain, that is a more expensive operation. @@ -1450,8 +1450,8 @@ CHIP_ERROR CASESession::ConstructSigmaResumeKey(const ByteSpan & initiatorRandom VerifyOrReturnError(bbuf.Fit(saltWritten), CHIP_ERROR_BUFFER_TOO_SMALL); HKDF_sha_crypto mHKDF; - ReturnErrorOnFailure(mHKDF.HKDF_SHA256(mSharedSecret, mSharedSecret.Length(), salt, saltWritten, skInfo.data(), skInfo.size(), - resumeKey.data(), CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES)); + ReturnErrorOnFailure(mHKDF.HKDF_SHA256(mSharedSecret.ConstBytes(), mSharedSecret.Length(), salt, saltWritten, skInfo.data(), + skInfo.size(), resumeKey.data(), CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES)); resumeKey.reduce_size(CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES); return CHIP_NO_ERROR; } diff --git a/src/protocols/secure_channel/tests/TestCASESession.cpp b/src/protocols/secure_channel/tests/TestCASESession.cpp index bcfe98f1d57af0..c3628a707c9acb 100644 --- a/src/protocols/secure_channel/tests/TestCASESession.cpp +++ b/src/protocols/secure_channel/tests/TestCASESession.cpp @@ -226,8 +226,8 @@ CHIP_ERROR InitCredentialSets() P256SerializedKeypair opKeysSerialized; // TODO: Rename gCommissioner* to gInitiator* - memcpy((uint8_t *) (opKeysSerialized), sTestCert_Node01_02_PublicKey, sTestCert_Node01_02_PublicKey_Len); - memcpy((uint8_t *) (opKeysSerialized) + sTestCert_Node01_02_PublicKey_Len, sTestCert_Node01_02_PrivateKey, + memcpy(opKeysSerialized.Bytes(), sTestCert_Node01_02_PublicKey, sTestCert_Node01_02_PublicKey_Len); + memcpy(opKeysSerialized.Bytes() + sTestCert_Node01_02_PublicKey_Len, sTestCert_Node01_02_PrivateKey, sTestCert_Node01_02_PrivateKey_Len); ReturnErrorOnFailure(opKeysSerialized.SetLength(sTestCert_Node01_02_PublicKey_Len + sTestCert_Node01_02_PrivateKey_Len)); @@ -254,8 +254,8 @@ CHIP_ERROR InitCredentialSets() P256SerializedKeypair opKeysSerialized; auto deviceOpKey = Platform::MakeUnique(); - memcpy((uint8_t *) (opKeysSerialized), sTestCert_Node01_01_PublicKey, sTestCert_Node01_01_PublicKey_Len); - memcpy((uint8_t *) (opKeysSerialized) + sTestCert_Node01_01_PublicKey_Len, sTestCert_Node01_01_PrivateKey, + memcpy(opKeysSerialized.Bytes(), sTestCert_Node01_01_PublicKey, sTestCert_Node01_01_PublicKey_Len); + memcpy(opKeysSerialized.Bytes() + sTestCert_Node01_01_PublicKey_Len, sTestCert_Node01_01_PrivateKey, sTestCert_Node01_01_PrivateKey_Len); ReturnErrorOnFailure(opKeysSerialized.SetLength(sTestCert_Node01_01_PublicKey_Len + sTestCert_Node01_01_PrivateKey_Len)); diff --git a/src/protocols/secure_channel/tests/TestDefaultSessionResumptionStorage.cpp b/src/protocols/secure_channel/tests/TestDefaultSessionResumptionStorage.cpp index e3bec1c39361ad..547fb2aa9c9f2c 100644 --- a/src/protocols/secure_channel/tests/TestDefaultSessionResumptionStorage.cpp +++ b/src/protocols/secure_channel/tests/TestDefaultSessionResumptionStorage.cpp @@ -92,7 +92,8 @@ void TestSave(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, sessionStorage.FindByScopedNodeId(vector.node, outResumptionId, outSharedSecret, outCats) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, memcmp(vector.resumptionId.data(), outResumptionId.data(), vector.resumptionId.size()) == 0); - NL_TEST_ASSERT(inSuite, memcmp(vector.sharedSecret.ConstBytes(), outSharedSecret, vector.sharedSecret.Length()) == 0); + NL_TEST_ASSERT(inSuite, + memcmp(vector.sharedSecret.ConstBytes(), outSharedSecret.ConstBytes(), vector.sharedSecret.Length()) == 0); NL_TEST_ASSERT(inSuite, vector.cats.values[0] == outCats.values[0]); NL_TEST_ASSERT(inSuite, vector.cats.values[1] == outCats.values[1]); NL_TEST_ASSERT(inSuite, vector.cats.values[2] == outCats.values[2]); @@ -101,7 +102,8 @@ void TestSave(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, sessionStorage.FindByResumptionId(vector.resumptionId, outNode, outSharedSecret, outCats) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, vector.node == outNode); - NL_TEST_ASSERT(inSuite, memcmp(vector.sharedSecret.Bytes(), outSharedSecret, vector.sharedSecret.Length()) == 0); + NL_TEST_ASSERT(inSuite, + memcmp(vector.sharedSecret.Bytes(), outSharedSecret.ConstBytes(), vector.sharedSecret.Length()) == 0); NL_TEST_ASSERT(inSuite, vector.cats.values[0] == outCats.values[0]); NL_TEST_ASSERT(inSuite, vector.cats.values[1] == outCats.values[1]); NL_TEST_ASSERT(inSuite, vector.cats.values[2] == outCats.values[2]); @@ -173,7 +175,9 @@ void TestInPlaceSave(nlTestSuite * inSuite, void * inContext) CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, memcmp(vectors[i].resumptionId.data(), outResumptionId.data(), vectors[i].resumptionId.size()) == 0); - NL_TEST_ASSERT(inSuite, memcmp(vectors[i].sharedSecret.Bytes(), outSharedSecret, vectors[i].sharedSecret.Length()) == 0); + NL_TEST_ASSERT( + inSuite, + memcmp(vectors[i].sharedSecret.ConstBytes(), outSharedSecret.ConstBytes(), vectors[i].sharedSecret.Length()) == 0); NL_TEST_ASSERT(inSuite, vectors[i].cats.values[0] == outCats.values[0]); NL_TEST_ASSERT(inSuite, vectors[i].cats.values[1] == outCats.values[1]); NL_TEST_ASSERT(inSuite, vectors[i].cats.values[2] == outCats.values[2]); @@ -183,7 +187,9 @@ void TestInPlaceSave(nlTestSuite * inSuite, void * inContext) sessionStorage.FindByResumptionId(vectors[i].resumptionId, outNode, outSharedSecret, outCats) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, vectors[i].node == outNode); - NL_TEST_ASSERT(inSuite, memcmp(vectors[i].sharedSecret.Bytes(), outSharedSecret, vectors[i].sharedSecret.Length()) == 0); + NL_TEST_ASSERT( + inSuite, + memcmp(vectors[i].sharedSecret.ConstBytes(), outSharedSecret.ConstBytes(), vectors[i].sharedSecret.Length()) == 0); NL_TEST_ASSERT(inSuite, vectors[i].cats.values[0] == outCats.values[0]); NL_TEST_ASSERT(inSuite, vectors[i].cats.values[1] == outCats.values[1]); NL_TEST_ASSERT(inSuite, vectors[i].cats.values[2] == outCats.values[2]); @@ -211,7 +217,9 @@ void TestInPlaceSave(nlTestSuite * inSuite, void * inContext) CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, memcmp(vectors[i].resumptionId.data(), outResumptionId.data(), vectors[i].resumptionId.size()) == 0); - NL_TEST_ASSERT(inSuite, memcmp(vectors[i].sharedSecret.Bytes(), outSharedSecret, vectors[i].sharedSecret.Length()) == 0); + NL_TEST_ASSERT( + inSuite, + memcmp(vectors[i].sharedSecret.ConstBytes(), outSharedSecret.ConstBytes(), vectors[i].sharedSecret.Length()) == 0); NL_TEST_ASSERT(inSuite, vectors[i].cats.values[0] == outCats.values[0]); NL_TEST_ASSERT(inSuite, vectors[i].cats.values[1] == outCats.values[1]); NL_TEST_ASSERT(inSuite, vectors[i].cats.values[2] == outCats.values[2]); @@ -221,7 +229,9 @@ void TestInPlaceSave(nlTestSuite * inSuite, void * inContext) sessionStorage.FindByResumptionId(vectors[i].resumptionId, outNode, outSharedSecret, outCats) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, vectors[i].node == outNode); - NL_TEST_ASSERT(inSuite, memcmp(vectors[i].sharedSecret.Bytes(), outSharedSecret, vectors[i].sharedSecret.Length()) == 0); + NL_TEST_ASSERT( + inSuite, + memcmp(vectors[i].sharedSecret.ConstBytes(), outSharedSecret.ConstBytes(), vectors[i].sharedSecret.Length()) == 0); NL_TEST_ASSERT(inSuite, vectors[i].cats.values[0] == outCats.values[0]); NL_TEST_ASSERT(inSuite, vectors[i].cats.values[1] == outCats.values[1]); NL_TEST_ASSERT(inSuite, vectors[i].cats.values[2] == outCats.values[2]); diff --git a/src/tools/chip-cert/Cmd_GenCD.cpp b/src/tools/chip-cert/Cmd_GenCD.cpp index 77f77471d93ffa..aa89ee3d9fbfa1 100644 --- a/src/tools/chip-cert/Cmd_GenCD.cpp +++ b/src/tools/chip-cert/Cmd_GenCD.cpp @@ -995,7 +995,7 @@ CHIP_ERROR EncodeSignerInfo_Ignor_Error(const ByteSpan & signerKeyId, const P256 uint8_t asn1SignatureBuf[kMax_ECDSA_Signature_Length_Der]; MutableByteSpan asn1Signature(asn1SignatureBuf); - ReturnErrorOnFailure(EcdsaRawSignatureToAsn1(kP256_FE_Length, ByteSpan(signature, signature.Length()), asn1Signature)); + ReturnErrorOnFailure(EcdsaRawSignatureToAsn1(kP256_FE_Length, signature.Span(), asn1Signature)); if (!cdConfig.IsCMSSignatureCorrect()) { diff --git a/src/transport/CryptoContext.cpp b/src/transport/CryptoContext.cpp index 825aebac579e64..44306bf3be0bde 100644 --- a/src/transport/CryptoContext.cpp +++ b/src/transport/CryptoContext.cpp @@ -129,7 +129,7 @@ CHIP_ERROR CryptoContext::InitFromKeyPair(const Crypto::P256Keypair & local_keyp P256ECDHDerivedSecret secret; ReturnErrorOnFailure(local_keypair.ECDH_derive_secret(remote_public_key, secret)); - return InitFromSecret(ByteSpan(secret, secret.Length()), salt, infoType, role); + return InitFromSecret(secret.Span(), salt, infoType, role); } CHIP_ERROR CryptoContext::BuildNonce(NonceView nonce, uint8_t securityFlags, uint32_t messageCounter, NodeId nodeId)