mirror of
https://github.com/esp8266/Arduino.git
synced 2025-06-20 21:01:25 +03:00
Using a pluggable architecture, allow updates delivered via the Update class to be verified as signed by a certificate. By using plugins, avoid pulling either axTLS or BearSSL into normal builds. A signature is appended to a binary image, followed by the size of the signature as a 32-bit int. The updater takes a verification function and checks this signature using whatever method it chooses, and if it fails the update is not applied. A SHA256 hash class is presently implemented for the signing hash (since MD5 is a busted algorithm). A BearSSLPublicKey based verifier is implemented for RSA keys. The application only needs the Public Key, while to sign you can use OpenSSL and your private key (which should never leave your control or be deployed on any endpoints). An example using automatic signing is included. Update the docs to show the signing steps and how to use it in the automatic and manual modes. Also remove one debugging line from the signing tool. Saves ~600 bytes when in debug mode by moving strings to PMEM Windows can't run the signing script, nor does it normally have OpenSSL installed. When trying to build an automatically signed binary, warn and don't run the python.
181 lines
5.7 KiB
C++
181 lines
5.7 KiB
C++
/*
|
|
WiFiClientBearSSL- SSL client/server for esp8266 using BearSSL libraries
|
|
- Mostly compatible with Arduino WiFi shield library and standard
|
|
WiFiClient/ServerSecure (except for certificate handling).
|
|
|
|
Copyright (c) 2018 Earle F. Philhower, III
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#ifndef _BEARSSLHELPERS_H
|
|
#define _BEARSSLHELPERS_H
|
|
|
|
#include <bearssl/bearssl.h>
|
|
#include <Updater.h>
|
|
|
|
|
|
// Internal opaque structures, not needed by user applications
|
|
namespace brssl {
|
|
class public_key;
|
|
class private_key;
|
|
};
|
|
|
|
namespace BearSSL {
|
|
|
|
// Holds either a single public RSA or EC key for use when BearSSL wants a pubkey.
|
|
// Copies all associated data so no need to keep input PEM/DER keys.
|
|
// All inputs can be either in RAM or PROGMEM.
|
|
class PublicKey {
|
|
public:
|
|
PublicKey();
|
|
PublicKey(const char *pemKey);
|
|
PublicKey(const uint8_t *derKey, size_t derLen);
|
|
~PublicKey();
|
|
|
|
bool parse(const char *pemKey);
|
|
bool parse(const uint8_t *derKey, size_t derLen);
|
|
|
|
// Accessors for internal use, not needed by apps
|
|
bool isRSA() const;
|
|
bool isEC() const;
|
|
const br_rsa_public_key *getRSA() const;
|
|
const br_ec_public_key *getEC() const;
|
|
|
|
// Disable the copy constructor, we're pointer based
|
|
PublicKey(const PublicKey& that) = delete;
|
|
|
|
private:
|
|
brssl::public_key *_key;
|
|
};
|
|
|
|
// Holds either a single private RSA or EC key for use when BearSSL wants a secretkey.
|
|
// Copies all associated data so no need to keep input PEM/DER keys.
|
|
// All inputs can be either in RAM or PROGMEM.
|
|
class PrivateKey {
|
|
public:
|
|
PrivateKey();
|
|
PrivateKey(const char *pemKey);
|
|
PrivateKey(const uint8_t *derKey, size_t derLen);
|
|
~PrivateKey();
|
|
|
|
bool parse(const char *pemKey);
|
|
bool parse(const uint8_t *derKey, size_t derLen);
|
|
|
|
// Accessors for internal use, not needed by apps
|
|
bool isRSA() const;
|
|
bool isEC() const;
|
|
const br_rsa_private_key *getRSA() const;
|
|
const br_ec_private_key *getEC() const;
|
|
|
|
// Disable the copy constructor, we're pointer based
|
|
PrivateKey(const PrivateKey& that) = delete;
|
|
|
|
private:
|
|
brssl::private_key *_key;
|
|
};
|
|
|
|
// Holds one or more X.509 certificates and associated trust anchors for
|
|
// use whenever BearSSL needs a cert or TA. May want to have multiple
|
|
// certs for things like a series of trusted CAs (but check the CertStore class
|
|
// for a more memory efficient way).
|
|
// Copies all associated data so no need to keep input PEM/DER certs.
|
|
// All inputs can be either in RAM or PROGMEM.
|
|
class X509List {
|
|
public:
|
|
X509List();
|
|
X509List(const char *pemCert);
|
|
X509List(const uint8_t *derCert, size_t derLen);
|
|
~X509List();
|
|
|
|
bool append(const char *pemCert);
|
|
bool append(const uint8_t *derCert, size_t derLen);
|
|
|
|
// Accessors
|
|
size_t getCount() const {
|
|
return _count;
|
|
}
|
|
const br_x509_certificate *getX509Certs() const {
|
|
return _cert;
|
|
}
|
|
const br_x509_trust_anchor *getTrustAnchors() const {
|
|
return _ta;
|
|
}
|
|
|
|
// Disable the copy constructor, we're pointer based
|
|
X509List(const X509List& that) = delete;
|
|
|
|
private:
|
|
size_t _count;
|
|
br_x509_certificate *_cert;
|
|
br_x509_trust_anchor *_ta;
|
|
};
|
|
|
|
// Opaque object which wraps the BearSSL SSL session to make repeated connections
|
|
// significantly faster. Completely optional.
|
|
class WiFiClientSecure;
|
|
|
|
class Session {
|
|
friend class WiFiClientSecure;
|
|
|
|
public:
|
|
Session() { memset(&_session, 0, sizeof(_session)); }
|
|
private:
|
|
br_ssl_session_parameters *getSession() { return &_session; }
|
|
// The actual BearSSL ession information
|
|
br_ssl_session_parameters _session;
|
|
};
|
|
|
|
// Updater SHA256 hash and signature verification
|
|
class HashSHA256 : public UpdaterHashClass {
|
|
public:
|
|
virtual void begin() override;
|
|
virtual void add(const void *data, uint32_t len) override;
|
|
virtual void end() override;
|
|
virtual int len() override;
|
|
virtual const void *hash() override;
|
|
private:
|
|
br_sha256_context _cc;
|
|
unsigned char _sha256[32];
|
|
};
|
|
|
|
class SigningVerifier : public UpdaterVerifyClass {
|
|
public:
|
|
virtual uint32_t length() override;
|
|
virtual bool verify(UpdaterHashClass *hash, const void *signature, uint32_t signatureLen) override;
|
|
|
|
public:
|
|
SigningVerifier(PublicKey *pubKey) { _pubKey = pubKey; }
|
|
|
|
private:
|
|
PublicKey *_pubKey;
|
|
};
|
|
|
|
// Stack thunked versions of calls
|
|
extern "C" {
|
|
extern unsigned char *thunk_br_ssl_engine_recvapp_buf( const br_ssl_engine_context *cc, size_t *len);
|
|
extern void thunk_br_ssl_engine_recvapp_ack(br_ssl_engine_context *cc, size_t len);
|
|
extern unsigned char *thunk_br_ssl_engine_recvrec_buf( const br_ssl_engine_context *cc, size_t *len);
|
|
extern void thunk_br_ssl_engine_recvrec_ack(br_ssl_engine_context *cc, size_t len);
|
|
extern unsigned char *thunk_br_ssl_engine_sendapp_buf( const br_ssl_engine_context *cc, size_t *len);
|
|
extern void thunk_br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len);
|
|
extern unsigned char *thunk_br_ssl_engine_sendrec_buf( const br_ssl_engine_context *cc, size_t *len);
|
|
extern void thunk_br_ssl_engine_sendrec_ack(br_ssl_engine_context *cc, size_t len);
|
|
};
|
|
|
|
};
|
|
|
|
#endif
|