10000 Move BearSSL from STACK_PROXY to a real, thunked 2nd stack by earlephilhower · Pull Request #5168 · esp8266/Arduino · GitHub
[go: up one dir, main page]

Skip to content

Move BearSSL from STACK_PROXY to a real, thunked 2nd stack #5168

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 33 commits into from
Nov 15, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
12e666e
Update to BearSSL 0.6+ release, add AES_CCM modes
earlephilhower Sep 25, 2018
167a11a
Merge branch 'master' into bssl0.6updt
earlephilhower Sep 25, 2018
f771d23
Merge branch 'master' into bssl0.6updt
d-a-v Sep 25, 2018
8fd3938
Enable the aes_ccm initialization in client/server
earlephilhower Sep 25, 2018
416660c
Initial attempt
earlephilhower Sep 25, 2018
ff9cbef
Working code with second stack thunking
earlephilhower Sep 26, 2018 10000
edda69e
Remove #ifdefs in .S file, not needed.
earlephilhower Sep 26, 2018
3dfdfe9
Clean up thunks and remove separate stack flag
earlephilhower Sep 26, 2018
137ba8f
Fix PIO assembler errors
earlephilhower Sep 26, 2018
c34779b
Merge branch 'master' into thunks
earlephilhower Sep 26, 2018
40d17b5
Remove #ifdef code changes, ensure same code as PC
earlephilhower Sep 27, 2018
e908bc6
Merge branch 'thunks' of https://github.com/earlephilhower/Arduino in…
earlephilhower Sep 27, 2018
913b87e
Merge branch 'master' into thunks
earlephilhower Sep 27, 2018
d17fa23
Move to latest BearSSL w/EC progmem savings
earlephilhower Sep 27, 2018
37be1db
Merge with master
earlephilhower Sep 28, 2018
0ebf6e6
Merge branch 'master' of https://github.com/esp8266/Arduino into thunks
earlephilhower Sep 28, 2018
39b6d36
Merge branch 'master' into thunks
earlephilhower Sep 30, 2018
2f83ca9
Add br_thunk_* calls to do ref counting, painting
earlephilhower Sep 30, 2018
1789579
Merge branch 'master' into thunks
earlephilhower Oct 1, 2018
ec6ccdc
Add in postmortem stack dump hooks
earlephilhower Oct 1, 2018
bd4851a
Update stack dump to match decoder expectations
earlephilhower Oct 2, 2018
72362c7
Merge branch 'master' into thunks
earlephilhower Oct 2, 2018
5ee8015
Move thunk to code core for linkiage
earlephilhower Oct 2, 2018
5583696
Add 2nd stack dump utility routine
earlephilhower Oct 2, 2018
3e4de76
Merge branch 'master' into thunks
d-a-v Oct 8, 2018
e6bbf7f
Merge branch 'master' into thunks
earlephilhower Oct 27, 2018
a25f023
Refactor once more, update stack size, add stress
earlephilhower Oct 27, 2018
934f743
Merge branch 'master' into thunks
earlephilhower Oct 31, 2018
36d6fb2
Update to latest to-thunks branch
earlephilhower Oct 31, 2018
65962f4
Add BearSSL device test using stack stress
earlephilhower Oct 31, 2018
17f1548
Use bearssl/master branch, not /to-thunks branch
earlephilhower Oct 31, 2018
a499de2
Merge branch 'master' into thunks
earlephilhower Nov 12, 2018
717169b
Merge branch 'master' into thunks
devyte Nov 13, 2018
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
Prev Previous commit
Next Next commit
Add BearSSL device test using stack stress
Run a series of SSL connection and transmission tests that stress
BearSSL and its stack usage to the device tests.

Modify device tests to include a possible SPIFFS generation and
upload when a make_spiffs.py file is present in a test directory.
  • Loading branch information
earlephilhower committed Oct 31, 2018
commit 65962f48129f5e670c48afb6de5d2b14734718a8
1 change: 1 addition & 0 deletions tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ Some tests need to connect to WiFi AP or to the PC running the tests. In the tes

Environment variables can also be used to pass some information from the test code to the host side helper. To do that, test code can set an environment variable using `setenv` C function. Then the `teardown` host side helper can obtain the value of that variable using `request_env` function defined in `mock_decorators`.

A SPIFFS filesystem may be generated on the host and uploade before a test by including a file called `make_spiffs.py` in the individual test directory.

### Building and running the tests

Expand Down
11 changes: 11 additions & 0 deletions tests/device/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ ESP8266_CORE_PATH ?= ../..
BUILD_DIR ?= $(PWD)/.build
HARDWARE_DIR ?= $(PWD)/.hardware
ESPTOOL ?= $(ESP8266_CORE_PATH)/tools/esptool/esptool
MKSPIFFS ?= $(ESP8266_CORE_PATH)/tools/mkspiffs/mkspiffs
UPLOAD_PORT ?= $(shell ls /dev/tty* | grep -m 1 -i USB)
UPLOAD_BAUD ?= 921600
UPLOAD_BOARD ?= nodemcu
Expand Down Expand Up @@ -55,6 +56,16 @@ ifneq ("$(NO_BUILD)","1")
endif
ifneq ("$(NO_UPLOAD)","1")
@test -n "$(UPLOAD_PORT)" || (echo "Failed to detect upload port, please export UPLOAD_PORT manually" && exit 1)
@test -e $(dir $@)/make_spiffs.py && (echo "Generating and uploading SPIFFS" && \
(cd $(dir $@) && python ./make_spiffs.py) && \
$(MKSPIFFS) --create $(dir $@)data/ --size 0xFB000 \
--block 8192 --page 256 $(LOCAL_BUILD_DIR)/spiffs.img && \
$(ESPTOOL) $(UPLOAD_VERBOSE_FLAG) \
-cp $(UPLOAD_PORT) \
-cb $(UPLOAD_BAUD) \
-cd $(UPLOAD_BOARD) \
-ca 0x300000 \
-cf $(LOCAL_BUILD_DIR)/spiffs.img ) || (echo "No SPIFFS to upload")
@echo Uploading binary
$(SILENT)$(ESPTOOL) $(UPLOAD_VERBOSE_FLAG) \
-cp $(UPLOAD_PORT) \
Expand Down
2 changes: 1 addition & 1 deletion tests/device/libraries/BSTest/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def run_tests(self):

def run_test(self, index):
self.sp.sendline('{}'.format(index))
timeout = 10
timeout = 20 # 10
while timeout > 0:
res = self.sp.expect(['>>>>>bs_test_start', EOF, TIMEOUT])
if res == 0:
Expand Down
66 changes: 66 additions & 0 deletions tests/device/test_BearSSL/make_spiffs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/python

# This script pulls the list of Mozilla trusted certificate authorities
# from the web at the "mozurl" below, parses the file to grab the PEM
# for each cert, and then generates DER files in a new ./data directory
# Upload these to a SPIFFS filesystem and use the CertManager to parse
# and use them for your outgoing SSL connections.
#
# Script by Earle F. Philhower, III. Released to the public domain.

import csv
import os
from subprocess import Popen, PIPE, call
import urllib2
try:
# for Python 2.x
from StringIO import StringIO
except ImportError:
# for Python 3.x
from io import StringIO

# Mozilla's URL for the CSV file with included PEM certs
mozurl = "https://ccadb-public.secure.force.com/mozilla/IncludedCACertificateReportPEMCSV"

# Load the manes[] and pems[] array from the URL
names = []
pems = []
response = urllib2.urlopen(mozurl)
csvData = response.read()
csvReader = csv.reader(StringIO(csvData))
for row in csvReader:
names.append(row[0]+":"+row[1]+":"+row[2])
pems.append(row[28])
del names[0] # Remove headers
del pems[0] # Remove headers

# Try and make ./data, skip if present
try:
os.mkdir("data")
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" % (idx);
thisPem = pems[i].replace("'", "")
print names[i] + " -> " + certName
ssl = Popen(['openssl','x509','-inform','PEM','-outform','DER','-out', certName], shell = False, stdin = PIPE)
pipe = ssl.stdin
pipe.write(thisPem)
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', 'q', 'data/certs.ar'] + derFiles;
call( arCmd )

for der in derFiles:
os.unlink(der)
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,21 @@
// November 2018 by Earle F. Philhower, III
// Released to the public domain

#include <Arduino.h>
#include <BSTest.h>
#include <ESP8266WiFi.h>
#include <CertStoreBearSSL.h>
#include <FS.h>
#include <time.h>
#include <StackThunk.h>

const char *ssid = "....";
const char *pass = "....";
extern "C" {
#include "user_interface.h"
}

BS_ENV_DECLARE();

void setClock();

// A single, global CertStore which can be used by all
// connections. Needs to stay live the entire time any of
Expand All @@ -25,7 +33,6 @@ BearSSL::CertStore certStore;
// model in a future release. Expect some changes to the interface,
// no matter what, as the SD and SPIFFS filesystem get unified.

#include <FS.h>
class SPIFFSCertStoreFile : public BearSSL::CertStoreFile {
public:
SPIFFSCertStoreFile(const char *name) {
Expand Down Expand Up @@ -59,6 +66,39 @@ class SPIFFSCertStoreFile : public BearSSL::CertStoreFile {
SPIFFSCertStoreFile certs_idx("/certs.idx"); // Generated by the ESP8266
SPIFFSCertStoreFile certs_ar("/certs.ar"); // Uploaded by the user


void setup()
{
Serial.begin(115200);
Serial.setDebugOutput(true);
WiFi.persistent(false);
WiFi.mode(WIFI_STA);
WiFi.begin(getenv("STA_SSID"), getenv("STA_PASS"));
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
setClock();
SPIFFS.begin();
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");
REQUIRE(1==0);
}
BS_RUN(Serial);
}

static void stopAll()
{
WiFiClient::stopAll();
}

static void disconnectWiFI()
{
wifi_station_disconnect();
}


// Set time via NTP, as required for x.509 validation
void setClock() {
configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov");
Expand Down Expand Up @@ -120,75 +160,61 @@ void fetchURL(BearSSL::WiFiClientSecure *client, const char *host, const uint16_
Serial.printf("\n-------\n");
}

void setup() {
Serial.begin(115200);
SPIFFS.begin();
Serial.println();
Serial.println();

// We start by connecting to a WiFi network
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, pass);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");

Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());

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

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");
return; // Can't connect to anything w/o certs!
}
int run(const char *str)
{
BearSSL::WiFiClientSecure *bear = new BearSSL::WiFiClientSecure();
// Integrate the cert store with this connection
bear->setCertStore(&certStore);

BearSSL::WiFiClientSecure *bear = new BearSSL::WiFiClientSecure();
// Integrate the cert store with this connection
bear->setCertStore(&certStore);
const char *badssl[] = { "ecc384", "expired", "wrong.host", "self-signed", "untrusted-root", "revoked",
"pinning-test", "no-common-name", "no-subject", "incomplete-chain", "sha1-intermediate",
"sha256", "sha384", "sha512", "1000-sans", "10000-sans", "ecc256", "ecc384", "rsa2048",
"rsa4096", "extended-validataion", "dh480", "dh512", "dh1024", "dh2048",
"dh-small-subgroup", "dh-composite", "static-rsa", "tls-v1-0", "tls-v1-1",
"tls-v1-2", "invalid-expected-sct"};
char buff[100];
uint32_t maxUsage = 0;
for (size_t i=0; i<sizeof(badssl)/sizeof(badssl[0]); i++) {
char buff[100];
uint32_t maxUsage = 0;
stack_thunk_repaint();
sprintf(buff, "%s.badssl.com", badssl[i]);
sprintf(buff, "%s.badssl.com", str);
Serial.printf("%s: ", buff);
fetchURL(bear, buff, 443, "/");
Serial.printf("Stack: %d\n", stack_thunk_get_max_usage());
maxUsage = std::max(maxUsage, stack_thunk_get_max_usage());
}
delete bear;
delete bear;

printf("\n\n\nMAX THUNK STACK USAGE: %d\n", maxUsage);
printf("\n\n\nMAX THUNK STACK USAGE: %d\n", maxUsage);
return maxUsage;
}

#define TC(x) TEST_CASE("BearSSL - Maximum stack usage < 5600 bytes @ "x".badssl.org", "[bearssl]") { REQUIRE(run(x) < 5600); }

TC("expired")
TC("wrong.host")
TC("self-signed")
TC("untrusted-root")
TC("revoked")
TC("pinning-test")
TC("no-common-name")
TC("no-subject")
TC("incomplete-chain")
TC("sha1-intermediate")
TC("sha256")
TC("sha384")
TC("sha512")
TC("1000-sans")
// TC("10000-sans") // Runs for >10 seconds, so causes false failure. Covered by the 1000 SAN anyway
TC("ecc256")
TC("ecc384")
TC("rsa2048")
TC("rsa4096")
TC("extended-validation")
TC("dh480")
TC("dh512")
TC("dh1024")
TC("dh2048")
TC("dh-small-subgroup")
TC("dh-composite")
TC("static-rsa")
TC("tls-v1-0")
TC("tls-v1-1")
TC("tls-v1-2")
TC("invalid-expected-sct")

void loop() {
Serial.printf("\nPlease enter a website address (www.blah.com) to connect to: ");
String site;
do {
site = Serial.readString();
} while (site == "");
Serial.printf("https://%s/\n", site.c_str());

BearSSL::WiFiClientSecure *bear = new BearSSL::WiFiClientSecure();
// Integrate the cert store with this connection
bear->setCertStore(&certStore);
stack_thunk_repaint();
fetchURL(bear, site.c_str(), 443, "/");
Serial.printf("Stack: %d\n", stack_thunk_get_max_usage());
delete bear;
}

0