added unix timestamp macro, fixed RNG implementation with analog pin, fixed bugs (client works now!)
This commit is contained in:
parent
e7fdbfc00e
commit
79a0a6135b
4 changed files with 165 additions and 31 deletions
|
@ -32,8 +32,8 @@ SSLClientImpl::SSLClientImpl(Client* client, const br_x509_trust_anchor *trust_a
|
|||
// zero the iobuf just in case it's still garbage
|
||||
memset(m_iobuf, 0, sizeof m_iobuf);
|
||||
// initlalize the various bearssl libraries so they're ready to go when we connect
|
||||
// br_client_init_TLS12_only(&m_sslctx, &m_x509ctx, m_trust_anchors, m_trust_anchors_num);
|
||||
br_ssl_client_init_full(&m_sslctx, &m_x509ctx, m_trust_anchors, m_trust_anchors_num);
|
||||
br_client_init_TLS12_only(&m_sslctx, &m_x509ctx, m_trust_anchors, m_trust_anchors_num);
|
||||
// br_ssl_client_init_full(&m_sslctx, &m_x509ctx, m_trust_anchors, m_trust_anchors_num);
|
||||
// check if the buffer size is half or full duplex
|
||||
constexpr auto duplex = sizeof m_iobuf <= BR_SSL_BUFSIZE_MONO ? 0 : 1;
|
||||
br_ssl_engine_set_buffer(&m_sslctx.eng, m_iobuf, sizeof m_iobuf, duplex);
|
||||
|
@ -74,7 +74,7 @@ int SSLClientImpl::connect(const char *host, uint16_t port) {
|
|||
/** see SSLClientImpl.h*/
|
||||
size_t SSLClientImpl::write(const uint8_t *buf, size_t size) {
|
||||
// check if the socket is still open and such
|
||||
if(!connected()) {
|
||||
if(br_ssl_engine_current_state(&m_sslctx.eng) == BR_SSL_CLOSED || getWriteError()) {
|
||||
m_print("Client is not connected! Perhaps something has happened?");
|
||||
return 0;
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ size_t SSLClientImpl::write(const uint8_t *buf, size_t size) {
|
|||
/** see SSLClientImpl.h*/
|
||||
int SSLClientImpl::available() {
|
||||
// connection check
|
||||
if (!connected()) {
|
||||
if (br_ssl_engine_current_state(&m_sslctx.eng) == BR_SSL_CLOSED || getWriteError()) {
|
||||
m_print("Warn: Cannot check available of disconnected client");
|
||||
return 0;
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ int SSLClientImpl::read(uint8_t *buf, size_t size) {
|
|||
const size_t read_amount = size > alen ? alen : size;
|
||||
memcpy(buf, br_buf, read_amount);
|
||||
// tell engine we read that many bytes
|
||||
br_ssl_engine_sendapp_ack(&m_sslctx.eng, read_amount);
|
||||
br_ssl_engine_recvapp_ack(&m_sslctx.eng, read_amount);
|
||||
// tell the user we read that many bytes
|
||||
return read_amount;
|
||||
}
|
||||
|
@ -221,7 +221,6 @@ int SSLClientImpl::m_start_ssl(const char* host) {
|
|||
// take the bottom 8 bits of the analog read
|
||||
for (uint8_t i = 0; i < sizeof rng_seeds; i++) rng_seeds[i] = static_cast<uint8_t>(analogRead(m_analog_pin));
|
||||
br_ssl_engine_inject_entropy(&m_sslctx.eng, rng_seeds, sizeof rng_seeds);
|
||||
// reset the client context, and look for previous sessions
|
||||
auto ret = br_ssl_client_reset(&m_sslctx, host, 1);
|
||||
if (!ret) {
|
||||
m_print("Error: reset failed");
|
||||
|
@ -232,11 +231,13 @@ int SSLClientImpl::m_start_ssl(const char* host) {
|
|||
// a little more structural sense to put it here
|
||||
if (m_run_until(BR_SSL_SENDAPP) < 0) {
|
||||
m_print("Error: Failed to initlalize the SSL layer");
|
||||
m_print(br_ssl_engine_last_error(&m_sslctx.eng));
|
||||
setWriteError(SSL_BR_CONNECT_FAIL);
|
||||
return 0;
|
||||
}
|
||||
// all good to go! the SSL socket should be up and running
|
||||
m_print("SSL Initialized");
|
||||
m_print(m_sslctx.eng.selected_protocol);
|
||||
setWriteError(SSL_OK);
|
||||
return 1;
|
||||
}
|
||||
|
@ -246,12 +247,12 @@ int SSLClientImpl::m_run_until(const unsigned target) {
|
|||
unsigned lastState = 0;
|
||||
size_t lastLen = 0;
|
||||
for (;;) {
|
||||
unsigned state = m_update_engine();
|
||||
// error check
|
||||
if (!connected()) {
|
||||
if (state == BR_SSL_CLOSED || getWriteError()) {
|
||||
m_print("Error: tried to run_until when the engine is closed");
|
||||
return -1;
|
||||
}
|
||||
unsigned state = m_update_engine();
|
||||
// debug
|
||||
if (state != lastState) {
|
||||
lastState = state;
|
||||
|
@ -304,9 +305,6 @@ int SSLClientImpl::m_run_until(const unsigned target) {
|
|||
* record.
|
||||
*/
|
||||
if (state & BR_SSL_SENDAPP && target & BR_SSL_RECVAPP) br_ssl_engine_flush(&m_sslctx.eng, 0);
|
||||
|
||||
// debug delay
|
||||
delay(500);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -327,6 +325,7 @@ unsigned SSLClientImpl::m_update_engine() {
|
|||
|
||||
buf = br_ssl_engine_sendrec_buf(&m_sslctx.eng, &len);
|
||||
wlen = m_client->write(buf, len);
|
||||
// let the chip recover
|
||||
if (wlen < 0) {
|
||||
m_print("Error writing to m_client");
|
||||
/*
|
||||
|
@ -404,16 +403,7 @@ unsigned SSLClientImpl::m_update_engine() {
|
|||
m_print("Read bytes from client: ");
|
||||
m_print(avail);
|
||||
m_print(len);
|
||||
/*
|
||||
unsigned char debug[avail];
|
||||
m_client->read(debug, avail);
|
||||
for (size_t i = 0; i < avail; i++) {
|
||||
Serial.print("0x");
|
||||
Serial.print(debug[i], HEX);
|
||||
Serial.print(", ");
|
||||
}
|
||||
while(true) {}
|
||||
*/
|
||||
|
||||
// I suppose so!
|
||||
int rlen = m_client->read(buf, len);
|
||||
if (rlen <= 0) {
|
||||
|
@ -428,8 +418,12 @@ unsigned SSLClientImpl::m_update_engine() {
|
|||
}
|
||||
// guess not, tell the state we're waiting still
|
||||
else {
|
||||
m_print("Bytes avail: ");
|
||||
m_print(avail);
|
||||
// m_print("Bytes avail: ");
|
||||
// m_print(avail);
|
||||
// m_print("Bytes needed: ");
|
||||
// m_print(len);
|
||||
// add a delay since spamming m_client->availible breaks the poor wiz chip
|
||||
delay(10);
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "bearssl.h"
|
||||
#include "bearssl_ssl.h"
|
||||
#include "time_macros.h"
|
||||
|
||||
/*
|
||||
* A "profile" is an initialisation function for a SSL context, that
|
||||
|
@ -420,6 +421,24 @@ br_client_init_TLS12_only(br_ssl_client_context *cc,
|
|||
br_x509_minimal_init(xc, &br_sha256_vtable,
|
||||
trust_anchors, trust_anchors_num);
|
||||
|
||||
/*
|
||||
* Set a fixed epoch time to validate certificates against.
|
||||
* Since we are working with an embedded device, there isn't
|
||||
* really a reliable source of time. To remedy this, we simply
|
||||
* store the time this program was compiled, and assume that
|
||||
* any certificate valid under that time is also valid at the
|
||||
* current time. This is vulnerable to the use of expired
|
||||
* certificates, however an attacker would have to use a
|
||||
* certificate valid after the compile date, which is fairly
|
||||
* difficult given the lifespan of projects here at the lab.
|
||||
* For now, this solution is good enough.
|
||||
*/
|
||||
br_x509_minimal_set_time(xc,
|
||||
// days since 1970 + days from 1970 to year 0
|
||||
(UNIX_TIMESTAMP_UTC / SEC_PER_DAY) + 719528UL,
|
||||
// seconds over start of day
|
||||
UNIX_TIMESTAMP_UTC % SEC_PER_DAY);
|
||||
|
||||
/*
|
||||
* Set suites and asymmetric crypto implementations. We use the
|
||||
* "i31" code for RSA (it is somewhat faster than the "i32"
|
||||
|
@ -431,11 +450,12 @@ br_client_init_TLS12_only(br_ssl_client_context *cc,
|
|||
* the RSA verification function below.
|
||||
*/
|
||||
// br_x509_minimal_set_rsa(xc, &br_rsa_i31_pkcs1_vrfy);
|
||||
br_x509_minimal_set_rsa(xc, &br_rsa_i15_pkcs1_vrfy);
|
||||
br_x509_minimal_set_rsa(xc, br_ssl_engine_get_rsavrfy(&cc->eng));
|
||||
// br_x509_minimal_set_ecdsa(xc,
|
||||
// &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
|
||||
br_x509_minimal_set_ecdsa(xc,
|
||||
&br_ec_all_m15, &br_ecdsa_i15_vrfy_asn1);
|
||||
br_ssl_engine_get_ec(&cc->eng),
|
||||
br_ssl_engine_get_ecdsa(&cc->eng));
|
||||
|
||||
/*
|
||||
* Set supported hash functions. These are for signatures on
|
||||
|
@ -447,11 +467,11 @@ br_client_init_TLS12_only(br_ssl_client_context *cc,
|
|||
* Note: the engine explicitly rejects signatures that use MD5.
|
||||
* Thus, there is no need for MD5 here.
|
||||
*/
|
||||
// br_ssl_engine_set_hash(xc, br_sha1_ID, &br_sha1_vtable);
|
||||
br_ssl_engine_set_hash(xc, br_sha224_ID, &br_sha224_vtable);
|
||||
br_ssl_engine_set_hash(xc, br_sha256_ID, &br_sha256_vtable);
|
||||
br_ssl_engine_set_hash(xc, br_sha384_ID, &br_sha384_vtable);
|
||||
// br_ssl_engine_set_hash(xc, br_sha512_ID, &br_sha512_vtable);
|
||||
// br_x509_minimal_set_hash(xc, br_sha1_ID, &br_sha1_vtable);
|
||||
br_x509_minimal_set_hash(xc, br_sha224_ID, &br_sha224_vtable);
|
||||
br_x509_minimal_set_hash(xc, br_sha256_ID, &br_sha256_vtable);
|
||||
br_x509_minimal_set_hash(xc, br_sha384_ID, &br_sha384_vtable);
|
||||
// br_x509_minimal_set_hash(xc, br_sha512_ID, &br_sha512_vtable);
|
||||
|
||||
/*
|
||||
* Link the X.509 engine in the SSL engine.
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
|
||||
#include "inner.h"
|
||||
#include "time_macros.h"
|
||||
|
||||
/* see bearssl_ssl.h */
|
||||
void
|
||||
|
@ -155,6 +156,24 @@ br_ssl_client_init_full(br_ssl_client_context *cc,
|
|||
br_x509_minimal_set_hash(xc, id, hc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a fixed epoch time to validate certificates against.
|
||||
* Since we are working with an embedded device, there isn't
|
||||
* really a reliable source of time. To remedy this, we simply
|
||||
* store the time this program was compiled, and assume that
|
||||
* any certificate valid under that time is also valid at the
|
||||
* current time. This is vulnerable to the use of expired
|
||||
* certificates, however an attacker would have to use a
|
||||
* certificate valid after the compile date, which is fairly
|
||||
* difficult given the lifespan of projects here at the lab.
|
||||
* For now, this solution is good enough.
|
||||
*/
|
||||
br_x509_minimal_set_time(xc,
|
||||
// days since 1970 + days from 1970 to year 0
|
||||
(UNIX_TIMESTAMP_UTC / SEC_PER_DAY) + 719528UL,
|
||||
// seconds over start of day
|
||||
UNIX_TIMESTAMP_UTC % SEC_PER_DAY);
|
||||
|
||||
/*
|
||||
* Link the X.509 engine in the SSL engine.
|
||||
*/
|
||||
|
|
101
src/time_macros.h
Normal file
101
src/time_macros.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
*
|
||||
* Created: 29.03.2018
|
||||
*
|
||||
* Authors:
|
||||
*
|
||||
* Assembled from the code released on Stackoverflow by:
|
||||
* Dennis (instructable.com/member/nqtronix) | https://stackoverflow.com/questions/23032002/c-c-how-to-get-integer-unix-timestamp-of-build-time-not-string
|
||||
* and
|
||||
* Alexis Wilke | https://stackoverflow.com/questions/10538444/do-you-know-of-a-c-macro-to-compute-unix-time-and-date
|
||||
*
|
||||
* Assembled by Jean Rabault
|
||||
*
|
||||
* UNIX_TIMESTAMP gives the UNIX timestamp (unsigned long integer of seconds since 1st Jan 1970) of compilation from macros using the compiler defined __TIME__ macro.
|
||||
* This should include Gregorian calendar leap days, in particular the 29ths of February, 100 and 400 years modulo leaps.
|
||||
*
|
||||
* Careful: __TIME__ is the local time of the computer, NOT the UTC time in general!
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COMPILE_TIME_H_
|
||||
#define COMPILE_TIME_H_
|
||||
|
||||
// add offset for pacific standard time
|
||||
#define PST_OFFSET (8UL)
|
||||
|
||||
// Some definitions for calculation
|
||||
#define SEC_PER_MIN (60UL)
|
||||
#define SEC_PER_HOUR (3600UL)
|
||||
#define SEC_PER_DAY (86400UL)
|
||||
#define SEC_PER_YEAR (SEC_PER_DAY*365)
|
||||
|
||||
// extracts 1..4 characters from a string and interprets it as a decimal value
|
||||
#define CONV_STR2DEC_1(str, i) (str[i]>'0'?str[i]-'0':0)
|
||||
#define CONV_STR2DEC_2(str, i) (CONV_STR2DEC_1(str, i)*10 + str[i+1]-'0')
|
||||
#define CONV_STR2DEC_3(str, i) (CONV_STR2DEC_2(str, i)*10 + str[i+2]-'0')
|
||||
#define CONV_STR2DEC_4(str, i) (CONV_STR2DEC_3(str, i)*10 + str[i+3]-'0')
|
||||
|
||||
// Custom "glue logic" to convert the month name to a usable number
|
||||
#define GET_MONTH(str, i) (str[i]=='J' && str[i+1]=='a' && str[i+2]=='n' ? 1 : \
|
||||
str[i]=='F' && str[i+1]=='e' && str[i+2]=='b' ? 2 : \
|
||||
str[i]=='M' && str[i+1]=='a' && str[i+2]=='r' ? 3 : \
|
||||
str[i]=='A' && str[i+1]=='p' && str[i+2]=='r' ? 4 : \
|
||||
str[i]=='M' && str[i+1]=='a' && str[i+2]=='y' ? 5 : \
|
||||
str[i]=='J' && str[i+1]=='u' && str[i+2]=='n' ? 6 : \
|
||||
str[i]=='J' && str[i+1]=='u' && str[i+2]=='l' ? 7 : \
|
||||
str[i]=='A' && str[i+1]=='u' && str[i+2]=='g' ? 8 : \
|
||||
str[i]=='S' && str[i+1]=='e' && str[i+2]=='p' ? 9 : \
|
||||
str[i]=='O' && str[i+1]=='c' && str[i+2]=='t' ? 10 : \
|
||||
str[i]=='N' && str[i+1]=='o' && str[i+2]=='v' ? 11 : \
|
||||
str[i]=='D' && str[i+1]=='e' && str[i+2]=='c' ? 12 : 0)
|
||||
|
||||
// extract the information from the time string given by __TIME__ and __DATE__
|
||||
#define __TIME_SECONDS__ CONV_STR2DEC_2(__TIME__, 6)
|
||||
#define __TIME_MINUTES__ CONV_STR2DEC_2(__TIME__, 3)
|
||||
#define __TIME_HOURS__ CONV_STR2DEC_2(__TIME__, 0)
|
||||
#define __TIME_DAYS__ CONV_STR2DEC_2(__DATE__, 4)
|
||||
#define __TIME_MONTH__ GET_MONTH(__DATE__, 0)
|
||||
#define __TIME_YEARS__ CONV_STR2DEC_4(__DATE__, 7)
|
||||
|
||||
// Days in February
|
||||
#define _UNIX_TIMESTAMP_FDAY(year) \
|
||||
(((year) % 400) == 0UL ? 29UL : \
|
||||
(((year) % 100) == 0UL ? 28UL : \
|
||||
(((year) % 4) == 0UL ? 29UL : \
|
||||
28UL)))
|
||||
|
||||
// Days in the year
|
||||
#define _UNIX_TIMESTAMP_YDAY(year, month, day) \
|
||||
( \
|
||||
/* January */ day \
|
||||
/* February */ + (month >= 2 ? 31UL : 0UL) \
|
||||
/* March */ + (month >= 3 ? _UNIX_TIMESTAMP_FDAY(year) : 0UL) \
|
||||
/* April */ + (month >= 4 ? 31UL : 0UL) \
|
||||
/* May */ + (month >= 5 ? 30UL : 0UL) \
|
||||
/* June */ + (month >= 6 ? 31UL : 0UL) \
|
||||
/* July */ + (month >= 7 ? 30UL : 0UL) \
|
||||
/* August */ + (month >= 8 ? 31UL : 0UL) \
|
||||
/* September */+ (month >= 9 ? 31UL : 0UL) \
|
||||
/* October */ + (month >= 10 ? 30UL : 0UL) \
|
||||
/* November */ + (month >= 11 ? 31UL : 0UL) \
|
||||
/* December */ + (month >= 12 ? 30UL : 0UL) \
|
||||
)
|
||||
|
||||
// get the UNIX timestamp from a digits representation
|
||||
#define _UNIX_TIMESTAMP(year, month, day, hour, minute, second) \
|
||||
( /* time */ second \
|
||||
+ minute * SEC_PER_MIN \
|
||||
+ hour * SEC_PER_HOUR \
|
||||
+ /* year day (month + day) */ (_UNIX_TIMESTAMP_YDAY(year, month, day) - 1) * SEC_PER_DAY \
|
||||
+ /* year */ (year - 1970UL) * SEC_PER_YEAR \
|
||||
+ ((year - 1969UL) / 4UL) * SEC_PER_DAY \
|
||||
- ((year - 1901UL) / 100UL) * SEC_PER_DAY \
|
||||
+ ((year - 1601UL) / 400UL) * SEC_PER_DAY \
|
||||
)
|
||||
|
||||
// the UNIX timestamp
|
||||
#define UNIX_TIMESTAMP _UNIX_TIMESTAMP(__TIME_YEARS__, __TIME_MONTH__, __TIME_DAYS__, __TIME_HOURS__, __TIME_MINUTES__, __TIME_SECONDS__)
|
||||
#define UNIX_TIMESTAMP_UTC (UNIX_TIMESTAMP + (PST_OFFSET*SEC_PER_HOUR))
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue