Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Completed encryption/decryption state machine
State machine is written to be fully compliant with C (even though Arduino supports C++). I wanted to test out the state machine design pattern in Patterns in C and it worked out really, really well! The program more or less worked on the first try, aside from small changes. Now uses a different input format: byte 0 contains the size of the upcoming input, then the following N bytes contain the input, and the last byte contains either 'E' or 'D' to select encryption or decryption respectively. The state machine is set up to transition on a time step as well as on a character input. By default, states will do nothing in response to either event. In their "constructors" (the "transition_*" functions) they set up a static function pointer as an event handler. To transition to another state, they call that state's transition function. This allows the state struct whose pointer gets passed around to change its behavior (in line with what state it's in) at runtime.
- Loading branch information
Showing
16 changed files
with
257 additions
and
150 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,64 +1,31 @@ | ||
#include "tweetnacl.h" | ||
|
||
#include "state_idle.h" | ||
|
||
#define BUFF_SIZE 256+crypto_box_ZEROBYTES | ||
|
||
#define STATUS_LED 13 | ||
|
||
uint8_t testKey[crypto_box_SECRETKEYBYTES]; | ||
uint8_t nonce[crypto_box_NONCEBYTES]; | ||
|
||
uint8_t serial_in_buff[BUFF_SIZE]; | ||
crypto_state_t state_machine; | ||
|
||
// Subtract one so that we store delimiting first | ||
// char in padding space to be erased. | ||
uint8_t char_insert_i = crypto_box_ZEROBYTES - 1; | ||
uint8_t crypto_out_buff[BUFF_SIZE]; | ||
|
||
void setup() { | ||
// put your setup code here, to run once: | ||
Serial.begin(115200); | ||
pinMode(STATUS_LED, OUTPUT); | ||
memset(serial_in_buff, 0, sizeof(serial_in_buff)); | ||
memset(crypto_out_buff, 0, sizeof(crypto_out_buff)); | ||
|
||
transition_to_idle(&state_machine); | ||
} | ||
|
||
|
||
void loop() { | ||
if(Serial.available()) { | ||
serial_in_buff[char_insert_i++] = Serial.read(); | ||
|
||
if(serial_in_buff[char_insert_i-1] == '\n' || | ||
char_insert_i >= BUFF_SIZE) { | ||
char enc_or_dec = serial_in_buff[crypto_box_ZEROBYTES - 1]; | ||
serial_in_buff[crypto_box_ZEROBYTES - 1] = 0; | ||
|
||
switch(enc_or_dec) { | ||
case 'E': | ||
{ | ||
crypto_secretbox(crypto_out_buff, serial_in_buff, char_insert_i - 1, nonce, testKey); | ||
int crypto_len = char_insert_i - 1 - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES; | ||
Serial.write(&crypto_out_buff[crypto_box_BOXZEROBYTES], crypto_len); | ||
} | ||
break; | ||
case 'D': | ||
{ | ||
uint8_t * encrypted_start = serial_in_buff + (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES); | ||
uint8_t encrypted_len = char_insert_i - 1 - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES; | ||
int success = crypto_secretbox_open(crypto_out_buff, encrypted_start, encrypted_len, nonce, testKey); | ||
if(success == -1) { | ||
digitalWrite(STATUS_LED, HIGH); | ||
} else { | ||
digitalWrite(STATUS_LED, LOW); | ||
} | ||
int crypto_len = encrypted_len - crypto_box_ZEROBYTES; | ||
Serial.write(&crypto_out_buff[crypto_box_ZEROBYTES], crypto_len); | ||
} | ||
break; | ||
} | ||
|
||
// Cleanup | ||
memset(serial_in_buff, 0, sizeof(serial_in_buff)); | ||
memset(crypto_out_buff, 0, sizeof(crypto_out_buff)); | ||
char_insert_i = crypto_box_ZEROBYTES - 1; | ||
} | ||
state_machine.recv_char(&state_machine, Serial.read()); | ||
} | ||
state_machine.fsm_step(&state_machine); | ||
} | ||
|
||
void print(const char * buf, uint16_t len) { | ||
Serial.write(buf, len); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
|
||
#include "secrets.h" | ||
|
||
#include <stdint.h> | ||
#include "tweetnacl.h" | ||
|
||
static const uint8_t secretkey[crypto_secretbox_KEYBYTES] = { | ||
0,1,2,3,4,5,6,7,8,9, | ||
0,1,2,3,4,5,6,7,8,9, | ||
0,1,2,3,4,5,6,7,8,9, | ||
0,1 | ||
}; | ||
|
||
static const uint8_t nonce[crypto_secretbox_NONCEBYTES] = { | ||
0,1,2,3,4,5,6,7,8,9, | ||
0,1,2,3,4,5,6,7,8,9, | ||
0,1,2,3 | ||
}; | ||
|
||
const uint8_t * get_secret_key(void) { | ||
return secretkey; | ||
} | ||
|
||
const uint8_t * get_nonce(void) { | ||
return nonce; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
|
||
|
||
#ifndef SECRETS_H | ||
#define SECRETS_H | ||
|
||
#include <stdint.h> | ||
|
||
const uint8_t * get_secret_key(void); | ||
const uint8_t * get_nonce(void); | ||
|
||
#endif // SECRETS_H | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
|
||
|
||
#include "state.h" | ||
|
||
static void default_event_recv_char(crypto_state_t * state, char c) { | ||
// Spin in same state | ||
return; | ||
} | ||
|
||
static void default_event_fsm_step(crypto_state_t * state) { | ||
// Spin in same state | ||
return; | ||
} | ||
|
||
void state_init_default(crypto_state_t * state) { | ||
state->recv_char = default_event_recv_char; | ||
state->fsm_step = default_event_fsm_step; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,18 @@ | ||
/** | ||
* @file | ||
* @author Riley Wood (riley@clearmotion.com) | ||
* @copyright 2017 ClearMotion Inc., All Rights Reserved. * | ||
* @defgroup state GROUP TITLE | ||
* @addtogroup state | ||
* @{ | ||
* | ||
* @brief DESCRIPTION HERE | ||
* | ||
*/ | ||
|
||
|
||
|
||
#ifndef STATE_H | ||
#define STATE_H | ||
|
||
typedef struct crypto_state_struct crypto_state_t; | ||
|
||
#endif // STATE_H | ||
typedef void (*event_recv_char) (crypto_state_t * state, char c); | ||
typedef void (*event_fsm_step) (crypto_state_t * state); | ||
|
||
struct crypto_state_struct { | ||
event_recv_char recv_char; | ||
event_fsm_step fsm_step; | ||
}; | ||
|
||
void state_init_default(crypto_state_t * state); | ||
|
||
/// @} | ||
|
||
#endif // STATE_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
|
||
#include "state_buffer.h" | ||
|
||
#include <string.h> | ||
#include "tweetnacl.h" | ||
|
||
#include "state_encrypt.h" | ||
#include "state_decrypt.h" | ||
#include "state_idle.h" | ||
|
||
#define BUFFER_SIZE (256 + crypto_secretbox_ZEROBYTES) | ||
|
||
static uint8_t input_len = 0; | ||
static uint8_t input_i = 0; | ||
static char input_buffer[BUFFER_SIZE]; | ||
|
||
static void buffer_recv_char(crypto_state_t * state, char c) { | ||
if(input_i < input_len) { | ||
input_buffer[crypto_secretbox_ZEROBYTES + input_i++] = c; | ||
} else { | ||
if(c == 'D') { | ||
char * decrypt_start = input_buffer + crypto_secretbox_ZEROBYTES - crypto_secretbox_BOXZEROBYTES; | ||
uint16_t decrypt_len = input_len + crypto_secretbox_BOXZEROBYTES; | ||
transition_to_decrypt(state, decrypt_start, decrypt_len); | ||
} | ||
else if(c == 'E') { | ||
uint16_t encrypt_len = input_len + crypto_secretbox_ZEROBYTES; | ||
transition_to_encrypt(state, input_buffer, encrypt_len); | ||
} | ||
else { | ||
transition_to_idle(state); | ||
} | ||
} | ||
} | ||
|
||
void transition_to_buffer(crypto_state_t * state, uint8_t input_l) { | ||
input_len = input_l; | ||
input_i = 0; | ||
memset(input_buffer, 0, sizeof(input_buffer)); | ||
|
||
state_init_default(state); | ||
state->recv_char = buffer_recv_char; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,12 @@ | ||
/** | ||
* @file | ||
* @author Riley Wood (riley@clearmotion.com) | ||
* @copyright 2017 ClearMotion Inc., All Rights Reserved. * | ||
* @defgroup state_buffer GROUP TITLE | ||
* @addtogroup state_buffer | ||
* @{ | ||
* | ||
* @brief DESCRIPTION HERE | ||
* | ||
*/ | ||
|
||
|
||
|
||
#ifndef STATE_BUFFER_H | ||
#define STATE_BUFFER_H | ||
|
||
#include <stdbool.h> | ||
#include <stdint.h> | ||
#include "state.h" | ||
|
||
#endif // STATE_BUFFER_H | ||
#include <stdint.h> | ||
|
||
void transition_to_buffer(crypto_state_t * state, uint8_t input_l); | ||
|
||
/// @} | ||
|
||
#endif // STATE_BUFFER_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
|
||
#include "state_decrypt.h" | ||
|
||
#include <string.h> | ||
#include "tweetnacl.h" | ||
|
||
#include "state.h" | ||
#include "secrets.h" | ||
#include "state_send_result.h" | ||
|
||
static char * to_decrypt = NULL; | ||
static uint16_t to_decrypt_len = 0; | ||
|
||
static void decrypt_fsm_step(crypto_state_t * state) { | ||
const uint8_t * nonce = get_nonce(); | ||
const uint8_t * secret_key = get_secret_key(); | ||
crypto_secretbox_open((unsigned char *)to_decrypt, | ||
(unsigned char *)to_decrypt, | ||
to_decrypt_len, | ||
nonce, | ||
secret_key); | ||
const char * result = &to_decrypt[crypto_secretbox_ZEROBYTES]; | ||
const uint8_t result_len = to_decrypt_len - crypto_secretbox_ZEROBYTES; | ||
transition_to_send_result(state, result, result_len); | ||
} | ||
|
||
void transition_to_decrypt(crypto_state_t * state, char * input, uint16_t input_len){ | ||
to_decrypt = input; | ||
to_decrypt_len = input_len; | ||
|
||
state_init_default(state); | ||
state->fsm_step = decrypt_fsm_step; | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,11 @@ | ||
/** | ||
* @file | ||
* @author Riley Wood (riley@clearmotion.com) | ||
* @copyright 2017 ClearMotion Inc., All Rights Reserved. * | ||
* @defgroup state_decrypt GROUP TITLE | ||
* @addtogroup state_decrypt | ||
* @{ | ||
* | ||
* @brief DESCRIPTION HERE | ||
* | ||
*/ | ||
|
||
|
||
|
||
#ifndef STATE_DECRYPT_H | ||
#define STATE_DECRYPT_H | ||
|
||
#include <stdbool.h> | ||
#include <stdint.h> | ||
#include "state.h" | ||
|
||
#endif // STATE_DECRYPT_H | ||
#include <stdint.h> | ||
|
||
void transition_to_decrypt(crypto_state_t * state, char * input, uint16_t input_len); | ||
|
||
/// @} | ||
|
||
#endif // STATE_DECRYPT_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
|
||
#include "state_encrypt.h" | ||
|
||
#include <string.h> | ||
#include "tweetnacl.h" | ||
|
||
#include "state.h" | ||
#include "secrets.h" | ||
#include "state_send_result.h" | ||
|
||
static char * to_encrypt = NULL; | ||
static uint16_t to_encrypt_len = 0; | ||
|
||
static void encrypt_fsm_step(crypto_state_t * state) { | ||
const uint8_t * nonce = get_nonce(); | ||
const uint8_t * secret_key = get_secret_key(); | ||
crypto_secretbox((unsigned char *)to_encrypt, | ||
(unsigned char *)to_encrypt, | ||
to_encrypt_len, | ||
nonce, | ||
secret_key); | ||
const char * result = &to_encrypt[crypto_secretbox_BOXZEROBYTES]; | ||
const uint8_t result_len = to_encrypt_len - crypto_secretbox_BOXZEROBYTES; | ||
transition_to_send_result(state, result, result_len); | ||
} | ||
|
||
void transition_to_encrypt(crypto_state_t * state, char * input, uint16_t input_len){ | ||
to_encrypt = input; | ||
to_encrypt_len = input_len; | ||
|
||
state_init_default(state); | ||
state->fsm_step = encrypt_fsm_step; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,11 @@ | ||
/** | ||
* @file | ||
* @author Riley Wood (riley@clearmotion.com) | ||
* @copyright 2017 ClearMotion Inc., All Rights Reserved. * | ||
* @defgroup state_encrypt GROUP TITLE | ||
* @addtogroup state_encrypt | ||
* @{ | ||
* | ||
* @brief DESCRIPTION HERE | ||
* | ||
*/ | ||
|
||
|
||
|
||
#ifndef STATE_ENCRYPT_H | ||
#define STATE_ENCRYPT_H | ||
|
||
#include <stdbool.h> | ||
#include "state.h" | ||
|
||
#include <stdint.h> | ||
|
||
#endif // STATE_ENCRYPT_H | ||
void transition_to_encrypt(crypto_state_t * state, char * input, uint16_t input_len); | ||
|
||
#endif // STATE_ENCRYPT_H | ||
|
||
/// @} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
|
||
|
||
#include "state_idle.h" | ||
|
||
#include <stdint.h> | ||
|
||
#include "state_buffer.h" | ||
|
||
static void idle_recv_char(crypto_state_t * state, char c) { | ||
transition_to_buffer(state, (uint8_t)c); | ||
} | ||
|
||
void transition_to_idle(crypto_state_t * state) { | ||
state_init_default(state); | ||
state->recv_char = idle_recv_char; | ||
} |
Oops, something went wrong.