Skip to content

Remove dependency on SD/SPIFFS from CertStore #4760

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jun 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
//
// Why would you need a CertStore?
//
// If you know the exact serve being connected to, or you
// If you know the exact server being connected to, or you
// are generating your own self-signed certificates and aren't
// allowing connections to HTTPS/TLS servers out of your
// control, then you do NOT want a CertStore. Hardcode the
// self-signing CA or the site's x.509 certificate directly.
//
// However, if you don't know what specific sites the system
// will be required to connect to and verify, a
// CertStore{SPIFFS,SD}BearSSL can allow you to select from
// CertStore can allow you to select from among
// 10s or 100s of CAs against which you can check the
// target's X.509, without taking any more RAM than a single
// certificate. This is the same way that standard browsers
Expand All @@ -31,7 +31,7 @@
// Released to the public domain

#include <ESP8266WiFi.h>
#include <CertStoreSPIFFSBearSSL.h>
#include <CertStoreBearSSL.h>
#include <time.h>

const char *ssid = "....";
Expand All @@ -40,7 +40,87 @@ const char *pass = "....";
// A single, global CertStore which can be used by all
// connections. Needs to stay live the entire time any of
// the WiFiClientBearSSLs are present.
CertStoreSPIFFSBearSSL certStore;
BearSSL::CertStore certStore;

// Uncomment below to use the SD card to store the certs
// #define USE_SDCARD 1

// NOTE: The CertStoreFile 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.

#ifdef USE_SDCARD

#include <SD.h>
class SDCertStoreFile : public BearSSL::CertStoreFile {
public:
SDCertStoreFile(const char *name) {
_name = name;
};
virtual ~SDCertStoreFile() override {};

// The main API
virtual bool open(bool write = false) override {
_file = SD.open(_name, write ? FILE_WRITE : FILE_READ);
return _file;
}
virtual bool seek(size_t absolute_pos) override {
return _file.seek(absolute_pos);
}
virtual ssize_t read(void *dest, size_t bytes) override {
return _file.read(dest, bytes);
}
virtual ssize_t write(void *dest, size_t bytes) override {
return _file.write((const uint8_t*)dest, bytes);
}
virtual void close() override {
_file.close();
}

private:
File _file;
const char *_name;
};

SDCertStoreFile certs_idx("/certs.idx");
SDCertStoreFile certs_ar("/certs.ar");

#else

#include <FS.h>
class SPIFFSCertStoreFile : public BearSSL::CertStoreFile {
public:
SPIFFSCertStoreFile(const char *name) {
_name = name;
};
virtual ~SPIFFSCertStoreFile() override {};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll make a non-virtual proposal. What I have in mind is a cerstore object templated generator function that returns the object with the FS type passed as argument. I'll make a draft, then post it here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm running against the clock at wörk, so I can't test this, but off the top of my head I came up with this. This can be part of the repo, and worst case the user would just need to instantiate. Or we can instantiate based on a #define.


// The main API
virtual bool open(bool write = false) override {
_file = SPIFFS.open(_name, write ? "w" : "r");
return _file;
}
virtual bool seek(size_t absolute_pos) override {
return _file.seek(absolute_pos, SeekSet);
}
virtual ssize_t read(void *dest, size_t bytes) override {
return _file.readBytes((char*)dest, bytes);
}
virtual ssize_t write(void *dest, size_t bytes) override {
return _file.write((uint8_t*)dest, bytes);
}
virtual void close() override {
_file.close();
}

private:
File _file;
const char *_name;
};

SPIFFSCertStoreFile certs_idx("/certs.idx");
SPIFFSCertStoreFile certs_ar("/certs.ar");
#endif

// Set time via NTP, as required for x.509 validation
void setClock() {
Expand Down Expand Up @@ -108,6 +188,12 @@ void setup() {
Serial.println();
Serial.println();

#ifdef USE_SDCARD
SD.begin();
#else
SPIFFS.begin();
#endif

// We start by connecting to a WiFi network
Serial.print("Connecting to ");
Serial.println(ssid);
Expand All @@ -126,7 +212,7 @@ void setup() {

setClock(); // Required for X.509 validation

int numCerts = certStore.initCertStore();
int numCerts = certStore.initCertStore(&certs_idx, &certs_ar);
Serial.printf("Number of CA certs read: %d\n", numCerts);
if (numCerts == 0) {
Serial.printf("No certs found. Did you run certs-from-mozill.py and upload the SPIFFS directory before running?\n");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
# Script by Earle F. Philhower, III. Released to the public domain.

import csv
from os import mkdir
from subprocess import Popen, PIPE
import os
from subprocess import Popen, PIPE, call
import urllib2
try:
# for Python 2.x
Expand Down Expand Up @@ -40,12 +40,27 @@
except:
pass

derFiles = []
idx = 0
# Process the text PEM using openssl into DER files
for i in range(0, len(pems)):
certName = "data/ca_%03d.der" % (i);
certName = "data/ca_%03d.der" % (idx);
thisPem = pems[i].replace("'", "")
print names[i] + " -> " + certName
pipe = Popen(['openssl','x509','-inform','PEM','-outform','DER','-out', certName], shell = False, stdin = PIPE).stdin
ssl = Popen(['openssl','x509','-inform','PEM','-outform','DER','-out', certName], shell = False, stdin = PIPE)
pipe = ssl.stdin
pipe.write(thisPem)
pipe.close
pipe.close()
ssl.wait()
if os.path.exists(certName):
derFiles.append(certName)
idx = idx + 1

if os.path.exists("data/certs.ar"):
os.unlink("data/certs.ar");

arCmd = ['ar', 'mcs', 'data/certs.ar'] + derFiles;
call( arCmd )

for der in derFiles:
os.unlink(der)
Loading