//-------------------------------------------------------------------------- // Copyright 2016, RIoT International Pty Ltd // // @author Aaron Ardiri //-------------------------------------------------------------------------- // microTLS - none/aes256 //-------------------------------------------------------------------------- // configuration //-------------------------------------------------------------------------- const char WiFi_SSID[] PROGMEM = "xxxx"; const char WiFi_PASS[] PROGMEM = "xxxx"; const uint8_t SERVER[] PROGMEM = { xxx, xxx, xxx, xxx }; #define SERVER_URI "/xxx/index.php" #define SERVER_NAME "xxx.xxxxxxxx.xxx" #define CLIENT_GUID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" #define CLIENT_INTERVAL 300 // 5 minutes //-------------------------------------------------------------------------- // pre-shared keys //-------------------------------------------------------------------------- // none //-------------------------------------------------------------------------- // modules //-------------------------------------------------------------------------- #include "microTLS-module-aes256.h" #define SESS_SECURITY "none" #define PING_SECURITY "aes-256" //-------------------------------------------------------------------------- // additional globals //-------------------------------------------------------------------------- typedef struct xGlobals { uint8_t aeskey[AES_KEYLEN]; } xGlobals; xGlobals gx; //-------------------------------------------------------------------------- // entry point //-------------------------------------------------------------------------- void microTLS_setup() { } //-------------------------------------------------------------------------- // session: creation //-------------------------------------------------------------------------- void microTLS_sess_prepare() { HashEngine ctx_hash; int ofs; SYS_RAM_CHECK; // we must prepare our send buffer g.scratch.send.len = 0; ofs = g.scratch.token.len + g.scratch.param.len + g.scratch.send.len + g.scratch.recv.len; g.scratch.send.buf = &g.scratch.reserved[ofs]; // copy the token to the send buffer, server expects it g.scratch.send.len = MIN(g.scratch.token.len, CLIENT_SCRATCH_LEN - ofs); memcpy((char *)g.scratch.send.buf, (char *)g.scratch.token.buf, g.scratch.send.len); // we need to generate an integrity hash for the buffer we are sending hashInit(&ctx_hash); hashUpdate(&ctx_hash, g.scratch.send.buf, g.scratch.send.len); hashFinal(&ctx_hash); g.scratch.send.digest = ctx_hash.digest; } bool microTLS_sess_process() { // did we receive a key? if (g.scratch.recv.len == AES_KEYLEN) { // this is our AES key memcpy(gx.aeskey, g.scratch.recv.buf, g.scratch.recv.len); } return false; } //-------------------------------------------------------------------------- // session: update //-------------------------------------------------------------------------- const char msg[] PROGMEM = "sending a message over microTLS"; void microTLS_ping_prepare() { HashEngine ctx_hash; AESEngine ctx_aes; int len, enc_len; uint8_t *p; int i; int ofs; SYS_RAM_CHECK; // how much memory do we need for this operation? len = strlen_P(msg); enc_len = (len + AES_BLOCKSIZE) & ~(AES_BLOCKSIZE-1); enc_len += AES_BLOCKSIZE; // don't forget the IV // we need to make sure both buffers fit in our scratch area if ((len + enc_len) < (CLIENT_SCRATCH_LEN - 2)) { // we'll put our source at the end of scratch p = &g.scratch.reserved[CLIENT_SCRATCH_LEN - len - 1]; strcpy_P((char *)p, msg); // we need to generate an integrity hash for the buffer we are sending hashInit(&ctx_hash); hashUpdate(&ctx_hash, p, len); hashFinal(&ctx_hash); g.scratch.send.digest = ctx_hash.digest; // we must prepare our send buffer g.scratch.send.len = 0; ofs = g.scratch.token.len + g.scratch.param.len + g.scratch.send.len + g.scratch.recv.len; g.scratch.send.buf = &g.scratch.reserved[ofs]; // we must create a random IV - put it in first bytes for (i=0;i < AES_BLOCKSIZE; i++) g.scratch.send.buf[i] = xrand(); // encode our message AESinitState(&ctx_aes, gx.aeskey, g.scratch.send.buf); AESencrypt(&ctx_aes, p, len, g.scratch.send.buf+AES_BLOCKSIZE); // the encrypted value is now stored in g.scratch.buf g.scratch.send.len = enc_len; } } bool microTLS_ping_process() { AESEngine ctx_aes; int len, enc_len; uint8_t *p; int i; int ofs; SYS_RAM_CHECK; enc_len = g.scratch.recv.len; len = enc_len - AES_BLOCKSIZE; // maximum size it can be // we need to make sure both buffers fit in our scratch area if ((len + enc_len) < (CLIENT_SCRATCH_LEN - 2)) { // we'll put our encoded stuff at the end of scratch p = &g.scratch.reserved[CLIENT_SCRATCH_LEN - enc_len - 1]; memcpy(p, g.scratch.recv.buf, g.scratch.recv.len); // decode our message - IV is at start of packet AESinitState(&ctx_aes, gx.aeskey, p); p += AES_BLOCKSIZE; AESdecrypt(&ctx_aes, p, len, g.scratch.recv.buf); // find the PKCS7 padding bytes - correct the length if needed if (g.scratch.recv.buf[len-1] < (AES_BLOCKSIZE+1)) len -= g.scratch.recv.buf[len-1]; // the decrypted value is now stored in g.scratch.buf g.scratch.recv.len = len; // the buffer should now have been shortened } return true; } //--------------------------------------------------------------------------