mirror of
https://github.com/espressif/esp-matter.git
synced 2026-04-27 19:13:13 +00:00
167 lines
6.8 KiB
C++
167 lines
6.8 KiB
C++
// Copyright 2022 Espressif Systems (Shanghai) PTE LTD
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include <credentials/examples/DeviceAttestationCredsExample.h>
|
|
#include <credentials/CHIPCert.h>
|
|
#include <crypto/CHIPCryptoPAL.h>
|
|
#include <platform/ESP32/ESP32Config.h>
|
|
#include <platform/ESP32/ESP32FactoryDataProvider.h>
|
|
#include <esp_fault.h>
|
|
#include <esp_log.h>
|
|
#include <esp_secure_cert_read.h>
|
|
|
|
#define TAG "dac_provider"
|
|
|
|
#if CONFIG_SEC_CERT_DAC_PROVIDER
|
|
|
|
namespace chip {
|
|
namespace DeviceLayer {
|
|
|
|
using namespace chip::Credentials;
|
|
using namespace chip::DeviceLayer::Internal;
|
|
|
|
namespace {
|
|
static constexpr uint32_t kDACPrivateKeySize = 32;
|
|
static constexpr uint32_t kDACPublicKeySize = 65;
|
|
static constexpr uint8_t kPrivKeyOffset = 7;
|
|
static constexpr uint8_t kPubKeyOffset = 56;
|
|
|
|
CHIP_ERROR LoadKeypairFromRaw(ByteSpan privateKey, ByteSpan publicKey, Crypto::P256Keypair & keypair)
|
|
{
|
|
Crypto::P256SerializedKeypair serializedKeypair;
|
|
ReturnErrorOnFailure(serializedKeypair.SetLength(privateKey.size() + publicKey.size()));
|
|
memcpy(serializedKeypair.Bytes(), publicKey.data(), publicKey.size());
|
|
memcpy(serializedKeypair.Bytes() + publicKey.size(), privateKey.data(), privateKey.size());
|
|
return keypair.Deserialize(serializedKeypair);
|
|
}
|
|
} // namespace
|
|
|
|
class SecureCertDACProvider: public Credentials::DeviceAttestationCredentialsProvider
|
|
{
|
|
public:
|
|
SecureCertDACProvider() : Credentials::DeviceAttestationCredentialsProvider() {}
|
|
|
|
CHIP_ERROR GetCertificationDeclaration(MutableByteSpan & outBuffer) override
|
|
{
|
|
size_t certSize;
|
|
ReturnErrorOnFailure(
|
|
ESP32Config::ReadConfigValueBin(ESP32Config::kConfigKey_CertDeclaration, outBuffer.data(), outBuffer.size(), certSize));
|
|
outBuffer.reduce_size(certSize);
|
|
return CHIP_NO_ERROR;
|
|
}
|
|
|
|
CHIP_ERROR GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer) override
|
|
{
|
|
// We do not provide any FirmwareInformation.
|
|
out_firmware_info_buffer.reduce_size(0);
|
|
return CHIP_NO_ERROR;
|
|
}
|
|
|
|
CHIP_ERROR GetDeviceAttestationCert(MutableByteSpan & outBuffer) override
|
|
{
|
|
char *dac_cert = NULL;
|
|
uint32_t dac_len = 0;
|
|
|
|
esp_err_t err = esp_secure_cert_get_device_cert(&dac_cert, &dac_len);
|
|
if (err == ESP_OK && dac_cert != NULL && dac_len != 0)
|
|
{
|
|
ESP_FAULT_ASSERT(err == ESP_OK && dac_cert != NULL && dac_len != 0);
|
|
VerifyOrReturnError(dac_len <= kMaxDERCertLength, CHIP_ERROR_UNSUPPORTED_CERT_FORMAT, esp_secure_cert_free_ca_cert(dac_cert));
|
|
VerifyOrReturnError(dac_len <= outBuffer.size(), CHIP_ERROR_BUFFER_TOO_SMALL, esp_secure_cert_free_ca_cert(dac_cert));
|
|
memcpy(outBuffer.data(), dac_cert, outBuffer.size());
|
|
outBuffer.reduce_size(dac_len);
|
|
esp_secure_cert_free_device_cert(dac_cert);
|
|
return CHIP_NO_ERROR;
|
|
}
|
|
|
|
ESP_LOGE(TAG, "esp_secure_cert_get_device_cert failed err:%d", err);
|
|
return CHIP_ERROR_INCORRECT_STATE;
|
|
}
|
|
|
|
CHIP_ERROR GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer) override
|
|
{
|
|
char *pai_cert = NULL;
|
|
uint32_t pai_len = 0;
|
|
|
|
esp_err_t err = esp_secure_cert_get_ca_cert(&pai_cert, &pai_len);
|
|
if (err == ESP_OK && pai_cert != NULL && pai_len != 0)
|
|
{
|
|
ESP_FAULT_ASSERT(err == ESP_OK && pai_cert != NULL && pai_len != 0);
|
|
VerifyOrReturnError(pai_len <= kMaxDERCertLength, CHIP_ERROR_UNSUPPORTED_CERT_FORMAT, esp_secure_cert_free_ca_cert(pai_cert));
|
|
VerifyOrReturnError(pai_len <= outBuffer.size(), CHIP_ERROR_BUFFER_TOO_SMALL, esp_secure_cert_free_ca_cert(pai_cert));
|
|
memcpy(outBuffer.data(), pai_cert, outBuffer.size());
|
|
outBuffer.reduce_size(pai_len);
|
|
esp_secure_cert_free_ca_cert(pai_cert);
|
|
return CHIP_NO_ERROR;
|
|
}
|
|
|
|
ESP_LOGE(TAG, "esp_secure_cert_get_ca_cert failed err:%d", err);
|
|
return CHIP_ERROR_INCORRECT_STATE;
|
|
}
|
|
|
|
CHIP_ERROR SignWithDeviceAttestationKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) override
|
|
{
|
|
Crypto::P256ECDSASignature signature;
|
|
Crypto::P256Keypair keypair;
|
|
char *sc_keypair = NULL;
|
|
uint32_t sc_keypair_len = 0;
|
|
|
|
VerifyOrReturnError(IsSpanUsable(outSignBuffer), CHIP_ERROR_INVALID_ARGUMENT);
|
|
VerifyOrReturnError(IsSpanUsable(messageToSign), CHIP_ERROR_INVALID_ARGUMENT);
|
|
VerifyOrReturnError(outSignBuffer.size() >= signature.Capacity(), CHIP_ERROR_BUFFER_TOO_SMALL);
|
|
|
|
esp_err_t err = esp_secure_cert_get_priv_key(&sc_keypair, &sc_keypair_len);
|
|
if (err == ESP_OK && sc_keypair != NULL && sc_keypair_len != 0)
|
|
{
|
|
ESP_FAULT_ASSERT(err == ESP_OK && sc_keypair != NULL && sc_keypair_len != 0);
|
|
|
|
CHIP_ERROR chipError = LoadKeypairFromRaw(ByteSpan(reinterpret_cast<const uint8_t *>(sc_keypair + kPrivKeyOffset), kDACPrivateKeySize),
|
|
ByteSpan(reinterpret_cast<const uint8_t *>(sc_keypair + kPubKeyOffset), kDACPublicKeySize), keypair);
|
|
VerifyOrReturnError(chipError == CHIP_NO_ERROR, chipError, esp_secure_cert_free_priv_key(sc_keypair));
|
|
|
|
chipError = keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature);
|
|
VerifyOrReturnError(chipError == CHIP_NO_ERROR, chipError, esp_secure_cert_free_priv_key(sc_keypair));
|
|
|
|
esp_secure_cert_free_priv_key(sc_keypair);
|
|
chipError = CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer);
|
|
return chipError;
|
|
}
|
|
|
|
ESP_LOGE(TAG, "esp_secure_cert_get_priv_key failed err:%d", err);
|
|
return CHIP_ERROR_INCORRECT_STATE;
|
|
}
|
|
};
|
|
} // namespace DeviceLayer
|
|
} // namespace chip
|
|
|
|
#endif // CONFIG_SEC_CERT_DAC_PROVIDER
|
|
|
|
namespace esp_matter {
|
|
|
|
// TODO: Need some method or mechanism to use the custom implementation along with the above three
|
|
chip::Credentials::DeviceAttestationCredentialsProvider * get_dac_provider(void)
|
|
{
|
|
#if CONFIG_SEC_CERT_DAC_PROVIDER
|
|
static chip::DeviceLayer::SecureCertDACProvider instance;
|
|
return &instance;
|
|
#elif CONFIG_FACTORY_PARTITION_DAC_PROVIDER
|
|
static chip::DeviceLayer::ESP32FactoryDataProvider instance;
|
|
return &instance;
|
|
#else // CONFIG_EXAMPLE_DAC_PROVIDER
|
|
return chip::Credentials::Examples::GetExampleDACProvider();
|
|
#endif
|
|
}
|
|
|
|
} // namespace esp_matter
|