mirror of
https://github.com/esp8266/Arduino.git
synced 2025-08-20 05:03:14 +03:00
Make CertStore natively use File interface (#6131)
__This is a breaking change, but the header and example did warn everyone that this API was in flux due to the incompatible SD and SPIFFS File implementations.__ BearSSL CertStores now simply need a filesystem and the names of the data (generated on-chip) and archive (uploaded by user) files on it. No more need to roll your own virtual CertStoreFile class. Update the library, examples, and device test.
This commit is contained in:
committed by
GitHub
parent
44bda41cf6
commit
8859b818d8
@@ -37,6 +37,12 @@ extern "C" {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CertStore::~CertStore() {
|
||||
free(_indexName);
|
||||
free(_dataName);
|
||||
}
|
||||
|
||||
CertStore::CertInfo CertStore::_preprocessCert(uint32_t length, uint32_t offset, const void *raw) {
|
||||
CertStore::CertInfo ci;
|
||||
|
||||
@@ -70,46 +76,54 @@ CertStore::CertInfo CertStore::_preprocessCert(uint32_t length, uint32_t offset,
|
||||
|
||||
// The certs.ar file is a UNIX ar format file, concatenating all the
|
||||
// individual certificates into a single blob in a space-efficient way.
|
||||
int CertStore::initCertStore(CertStoreFile *index, CertStoreFile *data) {
|
||||
int CertStore::initCertStore(FS &fs, const char *indexFileName, const char *dataFileName) {
|
||||
int count = 0;
|
||||
uint32_t offset = 0;
|
||||
|
||||
_index = index;
|
||||
_data = data;
|
||||
_fs = &fs;
|
||||
|
||||
if (!_index || !data) {
|
||||
// No strdup_P, so manually do it
|
||||
_indexName = (char *)malloc(strlen_P(indexFileName) + 1);
|
||||
_dataName = (char *)malloc(strlen_P(dataFileName) + 1);
|
||||
if (!_indexName || !_dataName) {
|
||||
free(_indexName);
|
||||
free(_dataName);
|
||||
return 0;
|
||||
}
|
||||
memcpy_P(_indexName, indexFileName, strlen_P(indexFileName) + 1);
|
||||
memcpy_P(_dataName, dataFileName, strlen_P(dataFileName) + 1);
|
||||
|
||||
File index = _fs->open(_indexName, "w");
|
||||
if (!index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_index->open(true)) {
|
||||
File data = _fs->open(_dataName, "r");
|
||||
if (!data) {
|
||||
index.close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_data->open(false)) {
|
||||
_index->close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
char magic[8];
|
||||
if (_data->read(magic, sizeof(magic)) != sizeof(magic) ||
|
||||
uint8_t magic[8];
|
||||
if (data.read(magic, sizeof(magic)) != sizeof(magic) ||
|
||||
memcmp(magic, "!<arch>\n", sizeof(magic)) ) {
|
||||
_data->close();
|
||||
_index->close();
|
||||
data.close();
|
||||
index.close();
|
||||
return 0;
|
||||
}
|
||||
offset += sizeof(magic);
|
||||
|
||||
while (true) {
|
||||
char fileHeader[60];
|
||||
uint8_t fileHeader[60];
|
||||
// 0..15 = filename in ASCII
|
||||
// 48...57 = length in decimal ASCII
|
||||
uint32_t length;
|
||||
if (data->read(fileHeader, sizeof(fileHeader)) != sizeof(fileHeader)) {
|
||||
if (data.read(fileHeader, sizeof(fileHeader)) != sizeof(fileHeader)) {
|
||||
break;
|
||||
}
|
||||
offset += sizeof(fileHeader);
|
||||
fileHeader[58] = 0;
|
||||
if (1 != sscanf(fileHeader + 48, "%d", &length) || !length) {
|
||||
if (1 != sscanf((char *)(fileHeader + 48), "%d", &length) || !length) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -117,7 +131,7 @@ int CertStore::initCertStore(CertStoreFile *index, CertStoreFile *data) {
|
||||
if (!raw) {
|
||||
break;
|
||||
}
|
||||
if (_data->read(raw, length) != (ssize_t)length) {
|
||||
if (data.read((uint8_t *)raw, length) != length) {
|
||||
free(raw);
|
||||
break;
|
||||
}
|
||||
@@ -125,7 +139,7 @@ int CertStore::initCertStore(CertStoreFile *index, CertStoreFile *data) {
|
||||
// If the filename starts with "//" then this is a rename file, skip it
|
||||
if (fileHeader[0] != '/' || fileHeader[1] != '/') {
|
||||
CertStore::CertInfo ci = _preprocessCert(length, offset, raw);
|
||||
if (_index->write(&ci, sizeof(ci)) != (ssize_t)sizeof(ci)) {
|
||||
if (index.write((uint8_t *)&ci, sizeof(ci)) != (ssize_t)sizeof(ci)) {
|
||||
free(raw);
|
||||
break;
|
||||
}
|
||||
@@ -135,13 +149,13 @@ int CertStore::initCertStore(CertStoreFile *index, CertStoreFile *data) {
|
||||
offset += length;
|
||||
free(raw);
|
||||
if (offset & 1) {
|
||||
char x;
|
||||
_data->read(&x, 1);
|
||||
uint8_t x;
|
||||
data.read(&x, 1);
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
_data->close();
|
||||
_index->close();
|
||||
data.close();
|
||||
index.close();
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -153,35 +167,37 @@ const br_x509_trust_anchor *CertStore::findHashedTA(void *ctx, void *hashed_dn,
|
||||
CertStore *cs = static_cast<CertStore*>(ctx);
|
||||
CertStore::CertInfo ci;
|
||||
|
||||
if (!cs || len != sizeof(ci.sha256) || !cs->_index || !cs->_data) {
|
||||
if (!cs || len != sizeof(ci.sha256) || !cs->_indexName || !cs->_dataName || !cs->_fs) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!cs->_index->open(false)) {
|
||||
File index = cs->_fs->open(cs->_indexName, "r");
|
||||
if (!index) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
while (cs->_index->read(&ci, sizeof(ci)) == sizeof(ci)) {
|
||||
while (index.read((uint8_t *)&ci, sizeof(ci)) == sizeof(ci)) {
|
||||
if (!memcmp(ci.sha256, hashed_dn, sizeof(ci.sha256))) {
|
||||
cs->_index->close();
|
||||
index.close();
|
||||
uint8_t *der = (uint8_t*)malloc(ci.length);
|
||||
if (!der) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!cs->_data->open(false)) {
|
||||
File data = cs->_fs->open(cs->_dataName, "r");
|
||||
if (!data) {
|
||||
free(der);
|
||||
return nullptr;
|
||||
}
|
||||
if (!cs->_data->seek(ci.offset)) {
|
||||
cs->_data->close();
|
||||
if (!data.seek(ci.offset, SeekSet)) {
|
||||
data.close();
|
||||
free(der);
|
||||
return nullptr;
|
||||
}
|
||||
if (cs->_data->read(der, ci.length) != (ssize_t)ci.length) {
|
||||
if (data.read((uint8_t *)der, ci.length) != ci.length) {
|
||||
free(der);
|
||||
return nullptr;
|
||||
}
|
||||
cs->_data->close();
|
||||
data.close();
|
||||
cs->_x509 = new X509List(der, ci.length);
|
||||
free(der);
|
||||
if (!cs->_x509) {
|
||||
@@ -196,7 +212,7 @@ const br_x509_trust_anchor *CertStore::findHashedTA(void *ctx, void *hashed_dn,
|
||||
return ta;
|
||||
}
|
||||
}
|
||||
cs->_index->close();
|
||||
index.close();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#include <Arduino.h>
|
||||
#include <BearSSLHelpers.h>
|
||||
#include <bearssl/bearssl.h>
|
||||
#include <FS.h>
|
||||
|
||||
// Base class for the certificate stores, which allow use
|
||||
// of a large set of certificates stored on SPIFFS of SD card to
|
||||
@@ -30,43 +31,21 @@
|
||||
|
||||
namespace BearSSL {
|
||||
|
||||
// Subclass this and provide virtual functions appropriate for your storage.
|
||||
// Required because there are conflicting definitions for a "File" in the
|
||||
// Arduino setup, and there is no simple way to work around the minor
|
||||
// differences.
|
||||
// See the examples for implementations to use in your own code.
|
||||
//
|
||||
// NOTE: This virtual class may migrate to a templated model in a future
|
||||
// release. Expect some changes to the interface, no matter what, as the
|
||||
// SD and SPIFFS filesystem get unified.
|
||||
class CertStoreFile {
|
||||
public:
|
||||
CertStoreFile() {};
|
||||
virtual ~CertStoreFile() {};
|
||||
|
||||
// The main API
|
||||
virtual bool open(bool write=false) = 0;
|
||||
virtual bool seek(size_t absolute_pos) = 0;
|
||||
virtual ssize_t read(void *dest, size_t bytes) = 0;
|
||||
virtual ssize_t write(void *dest, size_t bytes) = 0;
|
||||
virtual void close() = 0;
|
||||
};
|
||||
|
||||
|
||||
class CertStore {
|
||||
public:
|
||||
CertStore() { };
|
||||
~CertStore() { };
|
||||
~CertStore();
|
||||
|
||||
// Set the file interface instances, do preprocessing
|
||||
int initCertStore(CertStoreFile *index, CertStoreFile *data);
|
||||
int initCertStore(FS &fs, const char *indexFileName, const char *dataFileName);
|
||||
|
||||
// Installs the cert store into the X509 decoder (normally via static function callbacks)
|
||||
void installCertStore(br_x509_minimal_context *ctx);
|
||||
|
||||
protected:
|
||||
CertStoreFile *_index = nullptr;
|
||||
CertStoreFile *_data = nullptr;
|
||||
FS *_fs = nullptr;
|
||||
char *_indexName = nullptr;
|
||||
char *_dataName = nullptr;
|
||||
X509List *_x509 = nullptr;
|
||||
|
||||
// These need to be static as they are callbacks from BearSSL C code
|
||||
|
Reference in New Issue
Block a user