diff --git a/Makefile b/Makefile index d82aef2..70fd03e 100644 --- a/Makefile +++ b/Makefile @@ -26,11 +26,13 @@ create_build_dir: mkdir -p $(BUILDDIR) mkdir -p $(BUILDDIR)/uip mkdir -p $(BUILDDIR)/httpd + mkdir -p $(BUILDDIR)/crypto SRCS = rtlplayground.c rtl837x_flash.c rtl837x_leds.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c SRCS += rtl837x_stp.c rtl837x_pins.c dhcp.c machine.c cmd_editor.c rtl837x_bandwidth.c rtl837x_init.c SRCS += uip/timer.c uip/uip.c uip/uip_arp.c uip/uiplib.c uip/uip-fw.c uip/uip-neighbor.c uip/uip-split.c SRCS += httpd/httpd.c httpd/page_impl.c +SRCS += crypto/chacha20.c OBJS = ${SRCS:%.c=$(BUILDDIR)/%.rel} DEPS := ${SRCS:%.c=$(BUILDDIR)/%.d} HTML := $(shell find $(html) -name '*.js' -or -name '*.html' -or -name '*.svg') @@ -54,14 +56,13 @@ clean: -rm -f html_data.c html_data.h $(VERSION_HEADER) -rm -rf $(BUILDDIR) +$(BUILDDIR)/%.rel: %.asm + ${ASM} ${AFLAGS} -o $@ $< + $(BUILDDIR)/%.rel: %.c $(CC) -MMD $(CC_FLAGS) -o $@ -c $< -$(BUILDDIR)/%.rel: %.asm - ${ASM} ${AFLAGS} -o $@ $< -# mv -f $(addprefix $(basename $^), .lst .rel .sym) . - -$(BUILDDIR)/rtlplayground.ihx: $(OBJS) $(BUILDDIR)/crtstart.rel $(BUILDDIR)/crc16.rel +$(BUILDDIR)/rtlplayground.ihx: $(OBJS) $(BUILDDIR)/crtstart.rel $(BUILDDIR)/crc16.rel $(BUILDDIR)/crypto/chacha_8051.rel $(CC) $(CC_FLAGS) -Wl-bHOME=0x00000 -Wl-bBANK1=0x14000 -Wl-bBANK2=0x24000 -Wl-r -o $@ $^ $(BUILDDIR)/rtlplayground.img: $(BUILDDIR)/rtlplayground.ihx diff --git a/crypto/chacha.h b/crypto/chacha.h new file mode 100644 index 0000000..9a894ad --- /dev/null +++ b/crypto/chacha.h @@ -0,0 +1,23 @@ +#ifndef _CHACHA_H_ +#define _CHACHA_H_ + +#include + +struct chacha20_t { + uint8_t wstate[64]; // 64 bytes written here + uint8_t constant[16]; // 128 bit constant + uint8_t key[32]; // 256-bit secret key + uint32_t cnt; // 32-bit block counter 1, 2.. Big Endian! + uint8_t nonce[12]; // 96-bit nonce + __xdata uint8_t *plaintext; + uint16_t length; + __xdata uint8_t *cyphertext; +}; + +// Encrypt a plaintext with ChaCha20 as per RFC7539 +void chacha20_encrypt(void); + +// Test ChaCha20 using the example from RFC7539 +void chacha20_test(void); + +#endif diff --git a/crypto/chacha20.c b/crypto/chacha20.c new file mode 100644 index 0000000..b7f33d2 --- /dev/null +++ b/crypto/chacha20.c @@ -0,0 +1,98 @@ +#include "rtl837x_common.h" +#include "chacha.h" + +void chacha_20(void); +void chacha_update(void); +void chacha_count(void); + +// generate a block of ChaCha20 keystream as per RFC7539 + + +__xdata struct chacha20_t __at(0x7000) chacha20; +__xdata uint8_t plaintext[256]; +__xdata uint8_t cyphertext[256]; + +void chacha20_print_block(void) +{ + for (uint8_t i=0; i < 64; i++) { + print_byte(*(uint8_t * __xdata)(chacha20.wstate + i)); + if (i%4 == 3) + write_char(' '); + } +} + + +void chacha20_encrypt(void) +{ + __xdata uint8_t *p = chacha20.plaintext; + + while (chacha20.length) { + register uint8_t i; + chacha_count(); + memcpy(chacha20.wstate, chacha20.wstate + 64, 64); +#ifdef DEBUG + chacha20_print_block(); write_char('\n'); +#endif + chacha_20(); + chacha_update(); +#ifdef DEBUG + chacha20_print_block(); write_char('\n'); +#endif + for (i = 0; i < ((chacha20.length > 64) ? 64 : chacha20.length); i++) + *chacha20.cyphertext++ = *p++ ^ chacha20.wstate[i]; + chacha20.length -= chacha20.length > 64 ? 64 : chacha20.length; +#ifdef DEBUG + print_string("\n round done\n"); +#endif + }; +} + + +// Test the example of RFC 7539 Section 2.4.2 +void chacha20_test(void) +{ + __code uint8_t chacha_c[16] = + { 0x61, 0x70, 0x78, 0x65, 0x33, 0x20, 0x64, 0x6e, + 0x79, 0x62, 0x2d, 0x32, 0x6b, 0x20, 0x65, 0x74 }; + + __code uint8_t key[32] = + { 0x03, 0x02, 0x01, 0x00, 0x07, 0x06, 0x05, 0x04, + 0x0b, 0x0a, 0x09, 0x08, 0x0f, 0x0e, 0x0d, 0x0c, + 0x13, 0x12, 0x11, 0x10, 0x17, 0x16, 0x15, 0x14, + 0x1b, 0x1a, 0x19, 0x18, 0x1f, 0x1e, 0x1d, 0x1c }; + + __code uint8_t nonce[12] = { + 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; + + __code uint8_t sunscreen[] = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for " \ + "the future, sunscreen would be it."; + +/* + Ciphertext Sunscreen (from RFC 7539 Section 2.4.2): + 000 6e 2e 35 9a 25 68 f9 80 41 ba 07 28 dd 0d 69 81 n.5.%h..A..(..i. + 016 e9 7e 7a ec 1d 43 60 c2 0a 27 af cc fd 9f ae 0b .~z..C`..'...... + 032 f9 1b 65 c5 52 47 33 ab 8f 59 3d ab cd 62 b3 57 ..e.RG3..Y=..b.W + 048 16 39 d6 24 e6 51 52 ab 8f 53 0c 35 9f 08 61 d8 .9.$.QR..S.5..a. + 064 07 ca 0d bf 50 0d 6a 61 56 a3 8e 08 8a 22 b6 5e ....P.jaV....".^ + 080 52 bc 51 4d 16 cc f8 06 81 8c e9 1a b7 79 37 36 R.QM.........y76 + 096 5a f9 0b bf 74 a3 5b e6 b4 0b 8e ed f2 78 5e 42 Z...t.[......x^B + 112 87 4d +*/ + strcpy(plaintext, sunscreen); + memcpyc(chacha20.constant, chacha_c, 16); + memcpyc(chacha20.key, key, 32); + chacha20.cnt = 0; + memcpyc(chacha20.nonce, nonce, 12); + chacha20.plaintext = plaintext; + chacha20.length = strlen_x(plaintext); + chacha20.cyphertext = cyphertext; + + print_string("Encrypting...\n"); + chacha20_encrypt(); + print_string("Cypertext:\n"); + uint16_t len = strlen_x(plaintext); + for (uint8_t i = 0; i < len; i++) { + print_byte(cyphertext[i]); write_char(' '); + } +} diff --git a/crypto/chacha_8051.asm b/crypto/chacha_8051.asm new file mode 100644 index 0000000..1d23334 --- /dev/null +++ b/crypto/chacha_8051.asm @@ -0,0 +1,489 @@ +; ChaCha Quater-Round implementation in Assembler + .module chacha_8051 +; Global variables: + .globl _chacha_20 + .globl _chacha_test_1 + .globl _chacha_qr_r + .globl _chacha_update + .globl _chacha_count + +;#define CHACHA_QR(A, B, C, D) { \ +; A += B; D ^= A; D = ROTL32(D, 16); \ +; C += D; B ^= C; B = ROTL32(B, 12); \ +; A += B; D ^= A; D = ROTL32(D, 8); \ +; C += D; B ^= C; B = ROTL32(B, 7); \ +;} + +; r0 r1 r2 r3 +; CHACHA_QR( v[ 0], v[ 4], v[ 8], v[12] ); + + .area HOME (CODE) + +store_32: + ar7 = 0x07 + ar6 = 0x06 + ar5 = 0x05 + ar4 = 0x04 + ar3 = 0x03 + ar2 = 0x02 + ar1 = 0x01 + ar0 = 0x00 + + mov a, r7 + movx @dptr, a + dec dpl + mov a, r6 + movx @dptr, a + dec dpl + mov a, r5 + movx @dptr, a + dec dpl + mov a, r4 + movx @dptr, a + ret + +rol_b: + clr c + mov a, r7 + rlc a + mov r7, a + mov a, r6 + rlc a + mov r6, a + mov a, r5 + rlc a + mov r5, a + mov a, r4 + rlc a + mov r4, a + clr a + addc a, r7 + mov r7, a + djnz dpl, rol_b + ret + +print_regs: + push a + push ar6 + push ar7 + push dpl + mov dpl, a + lcall _print_byte + + pop dpl + pop ar7 + pop ar6 + pop a + + +chacha_plus_xor: +; Load A into registers r4-r7, A pointed to by r0 + mov dptr, #_chacha20 + mov dpl, r0 + movx a, @dptr + mov r7, a + dec dpl + movx a, @dptr + mov r6, a + dec dpl + movx a, @dptr + mov r5, a + dec dpl + movx a, @dptr + mov r4, a + +; A += B, B pointed to by r1 + mov dpl, r1 + movx a, @dptr + add a, r7 + mov r7, a + + dec dpl + movx a, @dptr + addc a, r6 + mov r6, a + + dec dpl + movx a, @dptr + addc a, r5 + mov r5, a + + dec dpl + movx a, @dptr + addc a, r4 + mov r4, a + + mov dpl, r0 ; Store A back + mov a, r7 + movx @dptr, a + dec dpl + mov a, r6 + movx @dptr, a + dec dpl + mov a, r5 + movx @dptr, a + dec dpl + mov a, r4 + movx @dptr, a + +; D ^= A + mov dpl, r3 + movx a, @dptr + xrl a, r7 + mov r7, a + dec dpl + + movx a, @dptr + xrl a, r6 + mov r6, a + dec dpl + + movx a, @dptr + xrl a, r5 + mov r5, a + dec dpl + + movx a, @dptr + xrl a, r4 + mov r4, a + dec dpl + ret + +chacha_qr: +; QR Part: A += B; D ^= A; D = ROTL32(D, 16); + acall chacha_plus_xor + +; rotate left 16. D is r4, r5, r6, r7 -> r6, r7, r4, r5 + mov a, r6 + xch a, r4 + mov r6, a + mov a, r7 + xch a, r5 + mov r7, a + mov dpl, r3 ; Store D + acall store_32 + +;QR Part: C += D; B ^= C; B = ROTL32(B, 12); +; Swap A <-> C and D <-> B + mov a, r0 + xch a, r2 + mov r0, a + mov a, r1 + xch a, r3 + mov r1, a + acall chacha_plus_xor + +; rotate left 12. D is r4, r5, r6, r7 -> r5, r6, r7, r4 + mov a, r4 + xch a, r7 + xch a, r6 + xch a, r5 + mov r4, a + + mov dpl, #4 + acall rol_b + mov dpl, r3 ; Store D (being B) + acall store_32 + +; Swap A <-> C and D <-> B + mov a, r0 + xch a, r2 + mov r0, a + mov a, r1 + xch a, r3 + mov r1, a + + mov dpl, r1 ; Store B + acall store_32 + +; QR Part A += B; D ^= A; D = ROTL32(D, 8); + acall chacha_plus_xor + mov a, r4 + xch a, r7 + xch a, r6 + xch a, r5 + mov r4, a + mov dpl, r3 ; Store D + acall store_32 + +; QR Part +; C += D; B ^= C; B = ROTL32(B, 7); +line4: +; Swap A <-> C and D <-> B + mov a, r0 + xch a, r2 + mov r0, a + mov a, r1 + xch a, r3 + mov r1, a + acall chacha_plus_xor + +; Roll left 7 bits, start by rolling 8 bits left, then roll 1 to the right + mov a, r4 + xch a, r7 + xch a, r6 + xch a, r5 + mov r4, a + + clr c + mov a, r4 + rrc a + mov r4, a + mov a, r5 + rrc a + mov r5, a + mov a, r6 + rrc a + mov r6, a + mov a, r7 + rrc a + mov r7, a + clr a + rrc a + add a, r4 + mov r4, a + +; Swap A <-> C and D <-> B + mov a, r0 + xch a, r2 + mov r0, a + mov a, r1 + xch a, r3 + mov r1, a + mov dpl, r1 ; Store B + acall store_32 + ret + +_chacha_test_1: + mov r0, #3 + mov r1, #7 + mov r2, #11 + mov r3, #15 + acall line4 + ret + +; QUARTERROUND(2,7,8,13) +_chacha_qr_r: + mov r0, #11 + mov r1, #31 + mov r2, #35 + mov r3, #55 + acall chacha_qr + ret + +; +; Implementation of 20 ChaCha Rounds (10 Double Rounds) +; +_chacha_20: + push acc + push b + push dpl + push dph + push ar7 + push ar6 + push ar5 + push ar4 + push ar3 + push ar2 + push ar1 + push ar0 + push psw + + mov b, #10 ; 10 Double rounds +chacha_20_loop: +; CHACHA_QR( v[ 0], v[ 4], v[ 8], v[12] ); + mov r0, #3 + mov r1, #19 + mov r2, #35 + mov r3, #51 + acall chacha_qr + +; CHACHA_QR( v[ 1], v[ 5], v[ 9], v[13] ); 7 23 39 55 + mov r0, #7 + mov r1, #23 + mov r2, #39 + mov r3, #55 + acall chacha_qr + +; CHACHA_QR( v[ 2], v[ 6], v[10], v[14] ); 11 27 43 59 + mov r0, #11 + mov r1, #27 + mov r2, #43 + mov r3, #59 + acall chacha_qr + +; CHACHA_QR( v[ 3], v[ 7], v[11], v[15] ); 15 31 47 63 + mov r0, #15 + mov r1, #31 + mov r2, #47 + mov r3, #63 + acall chacha_qr + +; CHACHA_QR( v[ 0], v[ 5], v[10], v[15] ); 3 23 43 63 + mov r0, #3 + mov r1, #23 + mov r2, #43 + mov r3, #63 + acall chacha_qr + +; CHACHA_QR( v[ 1], v[ 6], v[11], v[12] ); 7 27 47 51 + mov r0, #7 + mov r1, #27 + mov r2, #47 + mov r3, #51 + acall chacha_qr + +; CHACHA_QR( v[ 2], v[ 7], v[ 8], v[13] ); 11 31 35 55 + mov r0, #11 + mov r1, #31 + mov r2, #35 + mov r3, #55 + acall chacha_qr + +; CHACHA_QR( v[ 3], v[ 4], v[ 9], v[14] ); 15 19 39 59 + mov r0, #15 + mov r1, #19 + mov r2, #39 + mov r3, #59 + acall chacha_qr + djnz b, chacha_20_loop + + pop psw + pop ar0 + pop ar1 + pop ar2 + pop ar3 + pop ar4 + pop ar5 + pop ar6 + pop ar7 + pop dph + pop dpl + pop b + pop acc + ret + +; +; Update ChaCHa state +; +_chacha_update: + push acc + push b + push dpl + push dph + push ar4 + push ar3 + push ar2 + push ar1 + push ar0 + push psw + + mov dptr, #_chacha20 + mov b, #16 ; 16 uint32 +update_loop: + mov a, b ; multiply by 4 and subtract 1 + rl a + rl a + dec a +; Load Working State variable into registers r0-r3 + mov dpl, a + + orl a, #64 ; Save pointer to state + mov r4, a + + movx a, @dptr + mov r3, a + dec dpl + movx a, @dptr + mov r2, a + dec dpl + movx a, @dptr + mov r1, a + dec dpl + movx a, @dptr + mov r0, a + +; Add to State variable + mov a, r4 + mov dpl, a + movx a, @dptr + add a, r3 + mov r3, a + + dec dpl + movx a, @dptr + addc a, r2 + mov r2, a + + dec dpl + movx a, @dptr + addc a, r1 + mov r1, a + + dec dpl + movx a, @dptr + addc a, r0 + mov r0, a + +; Store back state variable in LSB, first sequence (serialized) + mov a, r4 + xrl a, #64 ; Save pointer to working state + mov dpl, a + mov a, r0 + movx @dptr, a + dec dpl + mov a, r1 + movx @dptr, a + dec dpl + mov a, r2 + movx @dptr, a + dec dpl + mov a, r3 + movx @dptr, a + + djnz b, update_loop + + pop psw + pop ar0 + pop ar1 + pop ar2 + pop ar3 + pop ar4 + pop dph + pop dpl + pop b + pop acc + ret + +; +; Increase counter in state +; +_chacha_count: + push acc + push dpl + push dph + mov dptr, #_chacha20 + mov dpl, #112 + 3 + movx a, @dptr + inc a + movx @dptr, a + jnc chacha_count_done + dec dpl + movx a, @dptr + inc a + movx @dptr, a + jnc chacha_count_done + dec dpl + movx a, @dptr + inc a + movx @dptr, a + jnc chacha_count_done + dec dpl + movx a, @dptr + inc a + movx @dptr, a +chacha_count_done: + pop dph + pop dpl + pop acc + ret diff --git a/machine.h b/machine.h index 8ae0334..f8cc391 100644 --- a/machine.h +++ b/machine.h @@ -6,7 +6,7 @@ /* * Select your machine type below */ -// #define MACHINE_KP_9000_6XHML_X2 +#define MACHINE_KP_9000_6XHML_X2 // #define MACHINE_KP_9000_6XH_X // #define MACHINE_KP_9000_9XH_X_EU // #define MACHINE_KP_9000_9XHML_X_V2_2 diff --git a/rtlplayground.c b/rtlplayground.c index 2be13b1..9c77fe6 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -24,6 +24,7 @@ #include "uip/uip_arp.h" #include "machine.h" #include "phy.h" +#include "crypto/chacha.h" extern __code const struct machine machine; extern __xdata uint32_t flash_size; @@ -2037,6 +2038,7 @@ void main(void) set_sys_led_state(SYS_LED_ON); cmd_editor_init(); + while (1) { cmd_edit(); idle(); // Enter Idle mode until interrupt occurs