diff --git a/templates/gapuino/include/api.h b/templates/gapuino/include/api.h new file mode 100644 index 0000000..0b1d09b --- /dev/null +++ b/templates/gapuino/include/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 8 +#define CRYPTO_NOOVERLAP 1 diff --git a/templates/gapuino/include/uartp.h b/templates/gapuino/include/uartp.h index 3a80a60..085073e 100644 --- a/templates/gapuino/include/uartp.h +++ b/templates/gapuino/include/uartp.h @@ -1,3 +1,5 @@ +#include + #pragma once #ifdef __cplusplus extern "C" { diff --git a/templates/gapuino/platformio.ini b/templates/gapuino/platformio.ini index 54a9abc..e614720 100644 --- a/templates/gapuino/platformio.ini +++ b/templates/gapuino/platformio.ini @@ -12,4 +12,6 @@ platform = riscv_gap board = gapuino framework = mbed +board_upload.boot_mode = jtag_hyper +board_upload.commands = reqloop ioloop start wait diff --git a/templates/gapuino/src/api.h b/templates/gapuino/src/api.h new file mode 100644 index 0000000..290a70d --- /dev/null +++ b/templates/gapuino/src/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 32 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 8 +#define CRYPTO_NOOVERLAP 1 diff --git a/templates/gapuino/src/encrypt.c b/templates/gapuino/src/encrypt.c new file mode 100644 index 0000000..2e661d5 --- /dev/null +++ b/templates/gapuino/src/encrypt.c @@ -0,0 +1,199 @@ +/* + TinyJAMBU-256: 256-bit key, 96-bit IV + Reference Implementation for 32-bit processor + The state consists of four 32-bit registers + state[3] || state[2] || state[1] || state[0] + + Implemented by Hongjun Wu +*/ + +#include +#include +#include "crypto_aead.h" + +#define FrameBitsIV 0x10 +#define FrameBitsAD 0x30 +#define FrameBitsPC 0x50 //Framebits for plaintext/ciphertext +#define FrameBitsFinalization 0x70 + +#define NROUND1 128*3 +#define NROUND2 128*10 + +/*non-optimized state update function*/ +void state_update(unsigned int *state, const unsigned char *key, unsigned int number_of_steps) +{ + unsigned int i; + unsigned int t1, t2, t3, t4, feedback; + //in each iteration, we compute 256 steps of the state update function. + for (i = 0; i < (number_of_steps >> 5); i++) + { + t1 = (state[1] >> 15) | (state[2] << 17); // 47 = 1*32+15 + t2 = (state[2] >> 6) | (state[3] << 26); // 47 + 23 = 70 = 2*32 + 6 + t3 = (state[2] >> 21) | (state[3] << 11); // 47 + 23 + 15 = 85 = 2*32 + 21 + t4 = (state[2] >> 27) | (state[3] << 5); // 47 + 23 + 15 + 6 = 91 = 2*32 + 27 + feedback = state[0] ^ t1 ^ (~(t2 & t3)) ^ t4 ^ ((unsigned int*)key)[i & 7]; + // shift 32 bit positions + state[0] = state[1]; state[1] = state[2]; state[2] = state[3]; + state[3] = feedback; + } +} + +// The initialization +/* The input to initialization is the 128-bit key; 96-bit IV;*/ +void initialization(const unsigned char *key, const unsigned char *iv, unsigned int *state) +{ + int i; + + //initialize the state as 0 + for (i = 0; i < 4; i++) state[i] = 0; + + //update the state with the key + state_update(state, key, NROUND2); + + //introduce IV into the state + for (i = 0; i < 3; i++) + { + state[1] ^= FrameBitsIV; + state_update(state, key, NROUND1); + state[3] ^= ((unsigned int*)iv)[i]; + } +} + +//process the associated data +void process_ad(const unsigned char *k, const unsigned char *ad, unsigned long long adlen, unsigned int *state) +{ + unsigned long long i; + unsigned int j; + + for (i = 0; i < (adlen >> 2); i++) + { + state[1] ^= FrameBitsAD; + state_update(state, k, NROUND1); + state[3] ^= ((unsigned int*)ad)[i]; + } + + // if adlen is not a multiple of 4, we process the remaining bytes + if ((adlen & 3) > 0) + { + state[1] ^= FrameBitsAD; + state_update(state, k, NROUND1); + for (j = 0; j < (adlen & 3); j++) ((unsigned char*)state)[12 + j] ^= ad[(i << 2) + j]; + state[1] ^= adlen & 3; + } +} + +//encrypt a message +int crypto_aead_encrypt( + unsigned char *c,unsigned long long *clen, + const unsigned char *m,unsigned long long mlen, + const unsigned char *ad,unsigned long long adlen, + const unsigned char *nsec, + const unsigned char *npub, + const unsigned char *k + ) +{ + unsigned long long i; + unsigned int j; + unsigned char mac[8]; + unsigned int state[4]; + + //initialization stage + initialization(k, npub, state); + + //process the associated data + process_ad(k, ad, adlen, state); + + //process the plaintext + for (i = 0; i < (mlen >> 2); i++) + { + state[1] ^= FrameBitsPC; + state_update(state, k, NROUND2); + state[3] ^= ((unsigned int*)m)[i]; + ((unsigned int*)c)[i] = state[2] ^ ((unsigned int*)m)[i]; + } + // if mlen is not a multiple of 4, we process the remaining bytes + if ((mlen & 3) > 0) + { + state[1] ^= FrameBitsPC; + state_update(state, k, NROUND2); + for (j = 0; j < (mlen & 3); j++) + { + ((unsigned char*)state)[12 + j] ^= m[(i << 2) + j]; + c[(i << 2) + j] = ((unsigned char*)state)[8 + j] ^ m[(i << 2) + j]; + } + state[1] ^= mlen & 3; + } + + //finalization stage, we assume that the tag length is 8 bytes + state[1] ^= FrameBitsFinalization; + state_update(state, k, NROUND2); + ((unsigned int*)mac)[0] = state[2]; + + state[1] ^= FrameBitsFinalization; + state_update(state, k, NROUND1); + ((unsigned int*)mac)[1] = state[2]; + + *clen = mlen + 8; + memcpy(c + mlen, mac, 8); + + return 0; +} + +//decrypt a message +int crypto_aead_decrypt( + unsigned char *m,unsigned long long *mlen, + unsigned char *nsec, + const unsigned char *c,unsigned long long clen, + const unsigned char *ad,unsigned long long adlen, + const unsigned char *npub, + const unsigned char *k + ) +{ + unsigned long long i; + unsigned int j, check = 0; + unsigned char mac[8]; + unsigned int state[4]; + + *mlen = clen - 8; + + //initialization stage + initialization(k, npub, state); + + //process the associated data + process_ad(k, ad, adlen, state); + + //process the ciphertext + for (i = 0; i < (*mlen >> 2); i++) + { + state[1] ^= FrameBitsPC; + state_update(state, k, NROUND2); + ((unsigned int*)m)[i] = state[2] ^ ((unsigned int*)c)[i]; + state[3] ^= ((unsigned int*)m)[i]; + } + // if mlen is not a multiple of 4, we process the remaining bytes + if ((*mlen & 3) > 0) + { + state[1] ^= FrameBitsPC; + state_update(state, k, NROUND2); + for (j = 0; j < (*mlen & 3); j++) + { + m[(i << 2) + j] = c[(i << 2) + j] ^ ((unsigned char*)state)[8 + j]; + ((unsigned char*)state)[12 + j] ^= m[(i << 2) + j]; + } + state[1] ^= *mlen & 3; + } + + //finalization stage, we assume that the tag length is 8 bytes + state[1] ^= FrameBitsFinalization; + state_update(state, k, NROUND2); + ((unsigned int*)mac)[0] = state[2]; + + state[1] ^= FrameBitsFinalization; + state_update(state, k, NROUND1); + ((unsigned int*)mac)[1] = state[2]; + + //verification of the authentication tag + for (j = 0; j < 8; j++) { check |= (mac[j] ^ c[clen - 8 + j]); } + if (check == 0) return 0; + else return -1; +} diff --git a/templates/gapuino/src/main.ino b/templates/gapuino/src/main.cpp similarity index 96% rename from templates/gapuino/src/main.ino rename to templates/gapuino/src/main.cpp index c420b11..86928e1 100644 --- a/templates/gapuino/src/main.ino +++ b/templates/gapuino/src/main.cpp @@ -1,6 +1,6 @@ -#include "crypto_aead.h" #include "api.h" #include "uartp.h" +#include "crypto_aead.h" #include "mbed.h" #define MAX_BYTES 100 @@ -23,7 +23,8 @@ unsigned long long int clen = 0; int res = 0; void setup(); -void loop(); +//void loop(); +DigitalOut crypto_pin(CRYPTO_BUSY); #ifdef __cplusplus extern "C" { @@ -49,12 +50,11 @@ void my_assert(bool b) { if (b) return; for(;;) - yield(); + wait(1); } void setup() { device.baud(115200); - DigitalOut crypto_pin(CRYPTO_BUSY); crypto_pin = 1; wait(100); memset(npub, 0, CRYPTO_NPUBBYTES); @@ -66,12 +66,12 @@ void setup() { device.printf("Hello, World!"); } -void loop() { +int main() { int res; uint16_t len = uartp_recv(cmdbuf, CMDBUF_LEN - 1); uint8_t action = cmdbuf[0]; if (len == 0 || len > CMDBUF_LEN - 1) - return; + return 1; uint16_t l = len - 1; uint16_t rl = 0; diff --git a/templates/gapuino/test b/templates/gapuino/test index 35a54c3..09f0b7d 100755 --- a/templates/gapuino/test +++ b/templates/gapuino/test @@ -28,7 +28,7 @@ def get_serial(): devices = [ p.device for p in ports ] devices.sort() # Might also be 0, one is JTAG, one UART - return devices[-1] + return devices[0] class UARTP: