Merge branch 'controller/spiffs_paa' into 'main'

controller: Add reading PAA cert from spiffs partition

See merge request app-frameworks/esp-matter!304
This commit is contained in:
Shu Chen
2023-03-07 14:05:27 +08:00
10 changed files with 245 additions and 5 deletions
@@ -7,10 +7,12 @@ if (CONFIG_ESP_MATTER_CONTROLLER_ENABLE)
endif()
if (NOT CONFIG_ESP_MATTER_COMMISSIONER_ENABLE)
list(APPEND exclude_srcs_list esp_matter_commissioner.cpp esp_matter_controller_pairing_command.cpp)
list(APPEND exclude_srcs_list esp_matter_commissioner.cpp
esp_matter_controller_pairing_command.cpp
esp_matter_attestation_trust_store.cpp)
endif()
idf_component_register(SRC_DIRS ${src_dirs_list}
EXCLUDE_SRCS ${exclude_srcs_list}
INCLUDE_DIRS ${include_dirs_list}
REQUIRES chip esp_matter esp_matter_console json_parser)
REQUIRES chip esp_matter esp_matter_console json_parser spiffs)
+19
View File
@@ -20,4 +20,23 @@ menu "ESP Matter Controller"
help
Maximum number of active device the commissioner supports.
choice ESP_MATTER_COMMISSIONER_ATTESTATION_TRUST_STORE
prompt "Attestation Trust Store"
depends on ESP_MATTER_COMMISSIONER_ENABLE
default TEST_ATTESTATION_TRUST_STORE
help
This option determines where the commissioner reads PAA trust root certificate.
config TEST_ATTESTATION_TRUST_STORE
bool "Attestation Trust Store - Test"
help
Use the two hardcoded PAA certificates(Chip-Test-PAA-FFF1-Cert&Chip-Test-PAA-NoVID-Cert) in the firmware.
config SPIFFS_ATTESTATION_TRUST_STORE
bool "Attestation Trust Store - Spiffs"
help
Read the PAA root certificates from the spiffs partition
endchoice
endmenu
@@ -0,0 +1,147 @@
// Copyright 2023 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/attestation_verifier/DefaultDeviceAttestationVerifier.h>
#include <esp_check.h>
#include <esp_log.h>
#include <esp_matter_attestation_trust_store.h>
#include <esp_spiffs.h>
const char TAG[] = "spiffs_attestation";
namespace chip {
namespace Credentials {
static const char *get_filename_extension(const char *filename)
{
const char *dot = strrchr(filename, '.');
if (!dot || dot == filename) {
return "";
}
return dot + 1;
}
paa_der_cert_iterator::paa_der_cert_iterator(const char *path)
{
strncpy(m_path, path, strnlen(path, 16));
m_path[15] = 0;
m_dir = opendir(path);
if (!m_dir) {
ESP_LOGE(TAG, "Failed to open the directory");
return;
}
m_count = 0;
m_index = 0;
dirent *entry = NULL;
while ((entry = readdir(m_dir)) != NULL) {
const char *extension = get_filename_extension(entry->d_name);
if (strncmp(extension, "der", strlen("der")) == 0) {
m_count++;
}
}
if (m_count == 0) {
ESP_LOGE(TAG, "No DER file in the directory");
closedir(m_dir);
m_dir = NULL;
} else {
rewinddir(m_dir);
}
}
bool paa_der_cert_iterator::next(paa_der_cert_t &item)
{
dirent *entry = NULL;
if (m_index >= m_count) {
return false;
}
while ((entry = readdir(m_dir)) != NULL) {
const char *extension = get_filename_extension(entry->d_name);
if (strncmp(extension, "der", strlen("der")) == 0) {
break;
}
}
if (!entry) {
return false;
}
m_index++;
char filename[280] = {0};
snprintf(filename, sizeof(filename), "%s/%s", m_path, entry->d_name);
FILE *file = fopen(filename, "rb");
if (file == nullptr) {
item.m_len = 0;
return true;
}
item.m_len = fread(item.m_buffer, sizeof(uint8_t), kMaxDERCertLength, file);
fclose(file);
return true;
}
void paa_der_cert_iterator::release()
{
if (m_dir) {
closedir(m_dir);
}
}
esp_err_t spiffs_attestation_trust_store::init()
{
esp_vfs_spiffs_conf_t conf = {
.base_path = "/paa", .partition_label = nullptr, .max_files = 5, .format_if_mount_failed = false};
ESP_RETURN_ON_ERROR(esp_vfs_spiffs_register(&conf), TAG, "Failed to initialize SPIFFS");
size_t total = 0, used = 0;
ESP_RETURN_ON_ERROR(esp_spiffs_info(conf.partition_label, &total, &used), TAG, "Failed to get SPIFFS info");
ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);
m_is_initialized = true;
return ESP_OK;
}
CHIP_ERROR spiffs_attestation_trust_store::GetProductAttestationAuthorityCert(const ByteSpan &skid,
MutableByteSpan &outPaaDerBuffer) const
{
if (m_is_initialized) {
paa_der_cert_iterator iter("/paa");
paa_der_cert_t paa_cert;
while (iter.next(paa_cert)) {
if (paa_cert.m_len == 0) {
continue;
}
uint8_t skid_buf[Crypto::kSubjectKeyIdentifierLength] = {0};
MutableByteSpan skid_span{skid_buf};
if (CHIP_NO_ERROR !=
Crypto::ExtractSKIDFromX509Cert(ByteSpan{paa_cert.m_buffer, paa_cert.m_len}, skid_span)) {
continue;
}
if (skid.data_equal(skid_span)) {
return CopySpanToMutableSpan(ByteSpan{paa_cert.m_buffer, paa_cert.m_len}, outPaaDerBuffer);
}
}
return CHIP_ERROR_CA_CERT_NOT_FOUND;
}
return CHIP_ERROR_INCORRECT_STATE;
}
const AttestationTrustStore *get_attestation_trust_store()
{
// TODO: Fetch the PAA certificates from DCL
#if CONFIG_TEST_ATTESTATION_TRUST_STORE
return GetTestAttestationTrustStore();
#elif CONFIG_SPIFFS_ATTESTATION_TRUST_STORE
spiffs_attestation_trust_store::get_instance().init();
return &spiffs_attestation_trust_store::get_instance();
#endif
}
} // namespace Credentials
} // namespace chip
@@ -0,0 +1,70 @@
// Copyright 2023 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.
#pragma once
#include <credentials/CHIPCert.h>
#include <credentials/attestation_verifier/DeviceAttestationVerifier.h>
#include <dirent.h>
#include <esp_err.h>
#include <lib/support/IntrusiveList.h>
namespace chip {
namespace Credentials {
typedef struct paa_der_cert {
uint8_t m_buffer[kMaxDERCertLength] = {0};
size_t m_len = 0;
} paa_der_cert_t;
class paa_der_cert_iterator {
public:
paa_der_cert_iterator(const char *path);
~paa_der_cert_iterator() { release(); };
size_t count() { return m_count; }
bool next(paa_der_cert_t &item);
void release();
private:
DIR *m_dir = NULL;
char m_path[16] = {0};
size_t m_count = 0;
size_t m_index = 0;
};
class spiffs_attestation_trust_store : public AttestationTrustStore {
public:
spiffs_attestation_trust_store(spiffs_attestation_trust_store &other) = delete;
void operator=(const spiffs_attestation_trust_store &) = delete;
static spiffs_attestation_trust_store &get_instance()
{
static spiffs_attestation_trust_store instance;
return instance;
}
CHIP_ERROR GetProductAttestationAuthorityCert(const ByteSpan &skid,
MutableByteSpan &outPaaDerBuffer) const override;
esp_err_t init();
private:
bool m_is_initialized = false;
spiffs_attestation_trust_store() {}
};
const AttestationTrustStore *get_attestation_trust_store();
} // namespace Credentials
} // namespace chip
@@ -22,6 +22,7 @@
#include <credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h>
#include <crypto/CHIPCryptoPAL.h>
#include <esp_heap_caps.h>
#include <esp_matter_attestation_trust_store.h>
#include <esp_matter_commissioner.h>
#include <esp_matter_controller_pairing_command.h>
#include <lib/support/TestGroupData.h>
@@ -119,8 +120,7 @@ esp_err_t init(uint16_t commissioner_port)
return ESP_FAIL;
}
// TODO: Root Store using spiffs
const Credentials::AttestationTrustStore *testingRootStore = Credentials::GetTestAttestationTrustStore();
const Credentials::AttestationTrustStore *testingRootStore = Credentials::get_attestation_trust_store();
SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore));
Platform::ScopedMemoryBuffer<uint8_t> noc;
+2
View File
@@ -4,5 +4,7 @@ idf_component_register(SRC_DIRS "."
PRIV_INCLUDE_DIRS "."
PRIV_REQUIRES ${PRIV_REQUIRES_LIST})
spiffs_create_partition_image(paa_cert ${CMAKE_SOURCE_DIR}/paa_cert FLASH_IN_PROJECT)
set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 14)
target_compile_options(${COMPONENT_LIB} PRIVATE "-DLWIP_IPV6_SCOPES=0" "-DCHIP_HAVE_CONFIG_H")
Binary file not shown.
+1 -1
View File
@@ -6,4 +6,4 @@ otadata, data, ota, , 0x2000
phy_init, data, phy, , 0x1000,
ota_0, app, ota_0, 0x20000, 0x1E0000,
ota_1, app, ota_1, 0x200000, 0x1E0000,
fctry, data, nvs, 0x3E0000, 0x6000
paa_cert, data, spiffs, , 0x20000
1 # Name, Type, SubType, Offset, Size, Flags
6 phy_init, data, phy, , 0x1000,
7 ota_0, app, ota_0, 0x20000, 0x1E0000,
8 ota_1, app, ota_1, 0x200000, 0x1E0000,
9 fctry, data, nvs, 0x3E0000, 0x6000 paa_cert, data, spiffs, , 0x20000