diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5660ea5..48c37a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,48 +8,57 @@ env: CARGO_TERM_COLOR: always jobs: - # This job handles all testing - test-compiler: + # Now we split the builds into separate jobs + build-compiler: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - # ... (insert your cache step here) ... - - name: Compiler Tests + - name: Install ARM tools + run: sudo apt-get update && sudo apt-get install -y gcc-arm-none-eabi qemu-user + + - name: Build Compiler working-directory: ./compiler - run: cargo test - - test-interpreter: + run: cargo build --release + + build-interpreter: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - # ... (insert your cache step here) ... - - name: Interpreter Tests + - name: Install ARM tools + run: sudo apt-get update && sudo apt-get install -y gcc-arm-none-eabi qemu-user + + - name: Build Interpreter working-directory: ./interpreter - run: cargo test + run: cargo build --release - # Now we split the builds into separate jobs - build-compiler: + # This job handles all testing + test-compiler: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - # ... (insert your cache step here) ... - - name: Build Compiler + - name: Install ARM tools + run: sudo apt-get update && sudo apt-get install -y gcc-arm-none-eabi qemu-user + + - name: Compiler Tests working-directory: ./compiler - run: cargo build --release - - build-interpreter: + run: cargo test + + test-interpreter: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - # ... (insert your cache step here) ... - - name: Build Interpreter + - name: Install ARM tools + run: sudo apt-get update && sudo apt-get install -y gcc-arm-none-eabi qemu-user + + - name: Interpreter Tests working-directory: ./interpreter - run: cargo build --release + run: cargo test + diff --git a/.gitignore b/.gitignore index ac53c9d..d26baa7 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,6 @@ /testing/bin /testing/artifacts /testing/src/__pycache__ +/testing/[0-9]*-*/ +/testing/hardened.asm +/testing/out.asm diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..d849f24 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "minimc"] + path = minimc + url = https://github.com/dannybpoulsen/minimc diff --git a/compiler/fissc/crt-rsa.trv b/compiler/fissc/crt-rsa.trv index d44292c..b1ce082 100644 --- a/compiler/fissc/crt-rsa.trv +++ b/compiler/fissc/crt-rsa.trv @@ -113,7 +113,7 @@ func main() -> Integer { g_sign = tmp; - print("g_sign herro = ", 1337); + print("g_sign = ", g_sign); print("g_countermeasure: ", g_countermeasure); return g_sign; diff --git a/compiler/fissc/verifypin.trv b/compiler/fissc/verifypin.trv new file mode 100644 index 0000000..6cb4402 --- /dev/null +++ b/compiler/fissc/verifypin.trv @@ -0,0 +1,59 @@ +func main() -> Integer { + let ptc : Integer = 3; + let authenticated : Integer = 0; + let cardPin1 : Integer = 1; + let cardPin2 : Integer = 2; + let cardPin3 : Integer = 3; + let cardPin4 : Integer = 4; + let userPin1 : Integer = 0; + let userPin2 : Integer = 0; + let userPin3 : Integer = 0; + let userPin4 : Integer = 0; + + authenticated = 0; + + if ptc > 0 then { + let pinsEqual : Integer = 1; + if userPin1 != cardPin1 then { + pinsEqual = 0; + } + else { + pinsEqual = 1; + } + + if userPin2 != cardPin2 then { + pinsEqual = 0; + } + else { + pinsEqual = 1; + } + + if userPin3 != cardPin3 then { + pinsEqual = 0; + } + else { + pinsEqual = 1; + } + + if userPin4 != cardPin4 then { + pinsEqual = 0; + } + else { + pinsEqual = 1; + } + + if pinsEqual == 1 then { + ptc = 3; + authenticated = 1; + } else { + ptc = ptc - 1; + } + } + else { + let x : Integer = 1; + } + print("g_authenticated: ", authenticated); + print("g_ptc: ", ptc); + + return authenticated; +} diff --git a/compiler/hard.asm b/compiler/hard.asm new file mode 100644 index 0000000..bd7cc4a --- /dev/null +++ b/compiler/hard.asm @@ -0,0 +1,471 @@ +.syntax unified +.thumb + +.section .text +.global _start +.type _start, %function + +_start: + mov r9, #0 + mov r10, #1 + sub sp, sp, #4 + mov r0, #3 + str r0, [sp] + add r9, r9, #1 + cmp r9, #1 + bne countermeasure + add r9, r9, #1 + cmp r9, #2 + bne countermeasure + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + add r9, r9, #1 + cmp r9, #3 + bne countermeasure + add r9, r9, #1 + cmp r9, #4 + bne countermeasure + sub sp, sp, #4 + mov r0, #1 + str r0, [sp] + add r9, r9, #1 + cmp r9, #5 + bne countermeasure + add r9, r9, #1 + cmp r9, #6 + bne countermeasure + sub sp, sp, #4 + mov r0, #2 + str r0, [sp] + add r9, r9, #1 + cmp r9, #7 + bne countermeasure + add r9, r9, #1 + cmp r9, #8 + bne countermeasure + sub sp, sp, #4 + mov r0, #3 + str r0, [sp] + add r9, r9, #1 + cmp r9, #9 + bne countermeasure + add r9, r9, #1 + cmp r9, #10 + bne countermeasure + sub sp, sp, #4 + mov r0, #4 + str r0, [sp] + add r9, r9, #1 + cmp r9, #11 + bne countermeasure + add r9, r9, #1 + cmp r9, #12 + bne countermeasure + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + add r9, r9, #1 + cmp r9, #13 + bne countermeasure + add r9, r9, #1 + cmp r9, #14 + bne countermeasure + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + add r9, r9, #1 + cmp r9, #15 + bne countermeasure + add r9, r9, #1 + cmp r9, #16 + bne countermeasure + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + add r9, r9, #1 + cmp r9, #17 + bne countermeasure + add r9, r9, #1 + cmp r9, #18 + bne countermeasure + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + add r9, r9, #1 + cmp r9, #19 + bne countermeasure + add r9, r9, #1 + cmp r9, #20 + bne countermeasure + mov r0, #0 + str r0, [sp, #32] + add r9, r9, #1 + cmp r9, #21 + bne countermeasure + add r9, r9, #1 + cmp r9, #22 + bne countermeasure + ldr r0, [sp, #36] + mov r1, r0 + mov r0, #0 + cmp r1, r0 + mov r0, #0 + it gt + movgt r0, #1 + cmp r0, #0 + beq else_0 + add r9, r9, #1 + cmp r9, #23 + bne countermeasure + sub sp, sp, #4 + mov r0, #1 + str r0, [sp] + add r9, r9, #1 + cmp r9, #24 + bne countermeasure + add r9, r9, #1 + cmp r9, #25 + bne countermeasure + ldr r0, [sp, #16] + mov r1, r0 + ldr r0, [sp, #32] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_1 + add r9, r9, #1 + cmp r9, #26 + bne countermeasure + mov r0, #0 + str r0, [sp] + add r9, r9, #1 + cmp r9, #27 + bne countermeasure + add r9, r9, #1 + cmp r9, #28 + bne countermeasure + mov r9, #25 + b endif_1 +else_1: + add r9, r9, #1 + cmp r9, #26 + bne countermeasure + mov r0, #1 + str r0, [sp] + add r9, r9, #1 + cmp r9, #27 + bne countermeasure + add r9, r9, #1 + cmp r9, #28 + bne countermeasure + mov r9, #25 +endif_1: + add r9, r9, #1 + cmp r9, #26 + bne countermeasure + ldr r0, [sp, #12] + mov r1, r0 + ldr r0, [sp, #28] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_2 + add r9, r9, #1 + cmp r9, #27 + bne countermeasure + mov r0, #0 + str r0, [sp] + add r9, r9, #1 + cmp r9, #28 + bne countermeasure + add r9, r9, #1 + cmp r9, #29 + bne countermeasure + mov r9, #26 + b endif_2 +else_2: + add r9, r9, #1 + cmp r9, #27 + bne countermeasure + mov r0, #1 + str r0, [sp] + add r9, r9, #1 + cmp r9, #28 + bne countermeasure + add r9, r9, #1 + cmp r9, #29 + bne countermeasure + mov r9, #26 +endif_2: + add r9, r9, #1 + cmp r9, #27 + bne countermeasure + ldr r0, [sp, #8] + mov r1, r0 + ldr r0, [sp, #24] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_3 + add r9, r9, #1 + cmp r9, #28 + bne countermeasure + mov r0, #0 + str r0, [sp] + add r9, r9, #1 + cmp r9, #29 + bne countermeasure + add r9, r9, #1 + cmp r9, #30 + bne countermeasure + mov r9, #27 + b endif_3 +else_3: + add r9, r9, #1 + cmp r9, #28 + bne countermeasure + mov r0, #1 + str r0, [sp] + add r9, r9, #1 + cmp r9, #29 + bne countermeasure + add r9, r9, #1 + cmp r9, #30 + bne countermeasure + mov r9, #27 +endif_3: + add r9, r9, #1 + cmp r9, #28 + bne countermeasure + ldr r0, [sp, #4] + mov r1, r0 + ldr r0, [sp, #20] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_4 + add r9, r9, #1 + cmp r9, #29 + bne countermeasure + mov r0, #0 + str r0, [sp] + add r9, r9, #1 + cmp r9, #30 + bne countermeasure + add r9, r9, #1 + cmp r9, #31 + bne countermeasure + mov r9, #28 + b endif_4 +else_4: + add r9, r9, #1 + cmp r9, #29 + bne countermeasure + mov r0, #1 + str r0, [sp] + add r9, r9, #1 + cmp r9, #30 + bne countermeasure + add r9, r9, #1 + cmp r9, #31 + bne countermeasure + mov r9, #28 +endif_4: + add r9, r9, #1 + cmp r9, #29 + bne countermeasure + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #1 + cmp r1, r0 + mov r0, #0 + it eq + moveq r0, #1 + cmp r0, #0 + beq else_5 + add r9, r9, #1 + cmp r9, #30 + bne countermeasure + mov r0, #3 + str r0, [sp, #40] + add r9, r9, #1 + cmp r9, #31 + bne countermeasure + add r9, r9, #1 + cmp r9, #32 + bne countermeasure + mov r0, #1 + str r0, [sp, #36] + add r9, r9, #1 + cmp r9, #33 + bne countermeasure + add r9, r9, #1 + cmp r9, #34 + bne countermeasure + mov r9, #29 + b endif_5 +else_5: + add r9, r9, #1 + cmp r9, #30 + bne countermeasure + ldr r0, [sp, #40] + mov r1, r0 + mov r0, #1 + sub r0, r1, r0 + str r0, [sp, #40] + add r9, r9, #1 + cmp r9, #31 + bne countermeasure + add r9, r9, #1 + cmp r9, #32 + bne countermeasure + mov r9, #29 +endif_5: + add r9, r9, #1 + cmp r9, #30 + bne countermeasure + add sp, sp, #4 + mov r9, #22 + b endif_0 +else_0: + add r9, r9, #1 + cmp r9, #23 + bne countermeasure + sub sp, sp, #4 + mov r0, #1 + str r0, [sp] + add r9, r9, #1 + cmp r9, #24 + bne countermeasure + add r9, r9, #1 + cmp r9, #25 + bne countermeasure + add sp, sp, #4 + mov r9, #22 +endif_0: + add r9, r9, #1 + cmp r9, #23 + bne countermeasure + mov r0, #1 + ldr r1, =.Lstr0 + mov r2, #17 + mov r7, #4 + svc #0 + ldr r0, [sp, #32] + mov r4, r0 + ldr r1, =num_buf + add r1, r1, #16 + mov r2, #0 + cmp r4, #0 + bne print_int_loop_6 + mov r3, #48 + sub r1, r1, #1 + strb r3, [r1] + mov r2, #1 + b print_int_done_6 +print_int_loop_6: + mov r0, r4 + mov r3, #10 + sdiv r5, r0, r3 + mul r6, r5, r3 + sub r7, r0, r6 + add r7, r7, #48 + sub r1, r1, #1 + strb r7, [r1] + add r2, r2, #1 + mov r4, r5 + cmp r4, #0 + bne print_int_loop_6 +print_int_done_6: + mov r0, #1 + mov r1, r1 + mov r2, r2 + mov r7, #4 + svc #0 + mov r0, #1 + ldr r1, =newline + mov r2, #1 + mov r7, #4 + svc #0 + add r9, r9, #1 + cmp r9, #24 + bne countermeasure + mov r0, #1 + ldr r1, =.Lstr1 + mov r2, #7 + mov r7, #4 + svc #0 + ldr r0, [sp, #36] + mov r4, r0 + ldr r1, =num_buf + add r1, r1, #16 + mov r2, #0 + cmp r4, #0 + bne print_int_loop_7 + mov r3, #48 + sub r1, r1, #1 + strb r3, [r1] + mov r2, #1 + b print_int_done_7 +print_int_loop_7: + mov r0, r4 + mov r3, #10 + sdiv r5, r0, r3 + mul r6, r5, r3 + sub r7, r0, r6 + add r7, r7, #48 + sub r1, r1, #1 + strb r7, [r1] + add r2, r2, #1 + mov r4, r5 + cmp r4, #0 + bne print_int_loop_7 +print_int_done_7: + mov r0, #1 + mov r1, r1 + mov r2, r2 + mov r7, #4 + svc #0 + mov r0, #1 + ldr r1, =newline + mov r2, #1 + mov r7, #4 + svc #0 + add r9, r9, #1 + cmp r9, #25 + bne countermeasure + ldr r0, [sp, #32] + mov r7, #1 + svc #0 + add r9, r9, #1 + cmp r9, #26 + bne countermeasure +countermeasure: + mov r0, #77 + mov r7, #1 + svc #0 + +.size _start, .-_start + +.section .data +.Lstr0: + .ascii "g_authenticated: " +.Lstr1: + .ascii "g_ptc: " +newline: + .ascii "\n" +num_buf: + .space 16 +step_counter: + .word 0 +fault_msg: + .ascii "Control flow violation detected\n" diff --git a/compiler/main.asm b/compiler/main.asm deleted file mode 100644 index 7613098..0000000 --- a/compiler/main.asm +++ /dev/null @@ -1,455 +0,0 @@ -.syntax unified -.thumb - -.section .text -.global _start -.type _start, %function - -_start: - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #11413 - str r0, [sp] - sub sp, sp, #4 - mov r0, #3533 - str r0, [sp] - sub sp, sp, #4 - mov r0, #101 - str r0, [sp] - sub sp, sp, #4 - mov r0, #113 - str r0, [sp] - sub sp, sp, #4 - mov r0, #59 - str r0, [sp] - sub sp, sp, #4 - mov r0, #97 - str r0, [sp] - sub sp, sp, #4 - mov r0, #101 - str r0, [sp] - sub sp, sp, #4 - mov r0, #-1 - str r0, [sp] - sub sp, sp, #4 - mov r0, #23 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - ldr r0, [sp, #64] - str r0, [sp, #48] - ldr r0, [sp, #76] - str r0, [sp, #44] - ldr r0, [sp, #88] - str r0, [sp, #40] - mov r0, #1 - str r0, [sp, #36] - mov r0, #0 - str r0, [sp, #4] -while_0: - ldr r0, [sp, #4] - mov r1, r0 - ldr r0, [sp, #44] - cmp r1, r0 - mov r0, #0 - it lt - movlt r0, #1 - cmp r0, #0 - beq end_while_0 - ldr r0, [sp, #36] - str r0, [sp, #28] - ldr r0, [sp, #48] - str r0, [sp, #24] - ldr r0, [sp, #40] - str r0, [sp, #20] - mov r0, #0 - str r0, [sp, #16] -while_1: - ldr r0, [sp, #24] - mov r1, r0 - mov r0, #0 - cmp r1, r0 - mov r0, #0 - it gt - movgt r0, #1 - cmp r0, #0 - beq end_while_1 - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #28] - add r0, r1, r0 - str r0, [sp, #16] -while_2: - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - cmp r1, r0 - mov r0, #0 - it gt - movgt r0, #1 - cmp r0, #0 - beq end_while_2 - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - sub r0, r1, r0 - str r0, [sp, #16] - b while_2 -end_while_2: -while_3: - ldr r0, [sp, #16] - mov r1, r0 - mov r0, #0 - cmp r1, r0 - mov r0, #0 - it lt - movlt r0, #1 - cmp r0, #0 - beq end_while_3 - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - add r0, r1, r0 - str r0, [sp, #16] - b while_3 -end_while_3: - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - cmp r1, r0 - mov r0, #0 - it eq - moveq r0, #1 - cmp r0, #0 - beq else_4 - mov r0, #0 - str r0, [sp, #16] - b endif_4 -else_4: -endif_4: - ldr r0, [sp, #24] - mov r1, r0 - mov r0, #1 - sub r0, r1, r0 - str r0, [sp, #24] - b while_1 -end_while_1: - ldr r0, [sp, #16] - str r0, [sp, #36] - ldr r0, [sp, #4] - mov r1, r0 - mov r0, #1 - add r0, r1, r0 - str r0, [sp, #4] - b while_0 -end_while_0: - ldr r0, [sp, #36] - str r0, [sp, #60] - ldr r0, [sp, #64] - str r0, [sp, #48] - ldr r0, [sp, #72] - str r0, [sp, #44] - ldr r0, [sp, #84] - str r0, [sp, #40] - mov r0, #1 - str r0, [sp, #36] - mov r0, #0 - str r0, [sp, #4] -while_5: - ldr r0, [sp, #4] - mov r1, r0 - ldr r0, [sp, #44] - cmp r1, r0 - mov r0, #0 - it lt - movlt r0, #1 - cmp r0, #0 - beq end_while_5 - ldr r0, [sp, #36] - str r0, [sp, #28] - ldr r0, [sp, #48] - str r0, [sp, #24] - ldr r0, [sp, #40] - str r0, [sp, #20] - mov r0, #0 - str r0, [sp, #16] -while_6: - ldr r0, [sp, #24] - mov r1, r0 - mov r0, #0 - cmp r1, r0 - mov r0, #0 - it gt - movgt r0, #1 - cmp r0, #0 - beq end_while_6 - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #28] - add r0, r1, r0 - str r0, [sp, #16] -while_7: - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - cmp r1, r0 - mov r0, #0 - it gt - movgt r0, #1 - cmp r0, #0 - beq end_while_7 - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - sub r0, r1, r0 - str r0, [sp, #16] - b while_7 -end_while_7: -while_8: - ldr r0, [sp, #16] - mov r1, r0 - mov r0, #0 - cmp r1, r0 - mov r0, #0 - it lt - movlt r0, #1 - cmp r0, #0 - beq end_while_8 - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - add r0, r1, r0 - str r0, [sp, #16] - b while_8 -end_while_8: - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - cmp r1, r0 - mov r0, #0 - it eq - moveq r0, #1 - cmp r0, #0 - beq else_9 - mov r0, #0 - str r0, [sp, #16] - b endif_9 -else_9: -endif_9: - ldr r0, [sp, #24] - mov r1, r0 - mov r0, #1 - sub r0, r1, r0 - str r0, [sp, #24] - b while_6 -end_while_6: - ldr r0, [sp, #16] - str r0, [sp, #36] - ldr r0, [sp, #4] - mov r1, r0 - mov r0, #1 - add r0, r1, r0 - str r0, [sp, #4] - b while_5 -end_while_5: - ldr r0, [sp, #36] - str r0, [sp, #56] - ldr r0, [sp, #60] - mov r1, r0 - ldr r0, [sp, #56] - sub r0, r1, r0 - str r0, [sp, #52] - ldr r0, [sp, #52] - str r0, [sp, #28] - ldr r0, [sp, #80] - str r0, [sp, #24] - ldr r0, [sp, #88] - str r0, [sp, #20] - mov r0, #0 - str r0, [sp, #16] -while_10: - ldr r0, [sp, #24] - mov r1, r0 - mov r0, #0 - cmp r1, r0 - mov r0, #0 - it gt - movgt r0, #1 - cmp r0, #0 - beq end_while_10 - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #28] - add r0, r1, r0 - str r0, [sp, #16] -while_11: - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - cmp r1, r0 - mov r0, #0 - it gt - movgt r0, #1 - cmp r0, #0 - beq end_while_11 - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - sub r0, r1, r0 - str r0, [sp, #16] - b while_11 -end_while_11: -while_12: - ldr r0, [sp, #16] - mov r1, r0 - mov r0, #0 - cmp r1, r0 - mov r0, #0 - it lt - movlt r0, #1 - cmp r0, #0 - beq end_while_12 - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - add r0, r1, r0 - str r0, [sp, #16] - b while_12 -end_while_12: - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - cmp r1, r0 - mov r0, #0 - it eq - moveq r0, #1 - cmp r0, #0 - beq else_13 - mov r0, #0 - str r0, [sp, #16] - b endif_13 -else_13: -endif_13: - ldr r0, [sp, #24] - mov r1, r0 - mov r0, #1 - sub r0, r1, r0 - str r0, [sp, #24] - b while_10 -end_while_10: - ldr r0, [sp, #16] - str r0, [sp, #52] - ldr r0, [sp, #52] - mov r1, r0 - ldr r0, [sp, #84] - mul r0, r1, r0 - str r0, [sp, #52] - ldr r0, [sp, #52] - mov r1, r0 - ldr r0, [sp, #56] - add r0, r1, r0 - str r0, [sp, #52] - ldr r0, [sp, #52] - str r0, [sp, #68] - mov r0, #1 - ldr r1, =.Lstr0 - mov r2, #12 - mov r7, #4 - svc #0 - ldr r0, [sp, #68] - mov r4, r0 - ldr r1, =num_buf - add r1, r1, #16 - mov r2, #0 - cmp r4, #0 - bne print_int_loop_14 - mov r3, #48 - sub r1, r1, #1 - strb r3, [r1] - mov r2, #1 - b print_int_done_14 -print_int_loop_14: - mov r0, r4 - mov r3, #10 - sdiv r5, r0, r3 - mul r6, r5, r3 - sub r7, r0, r6 - add r7, r7, #48 - sub r1, r1, #1 - strb r7, [r1] - add r2, r2, #1 - mov r4, r5 - cmp r4, #0 - bne print_int_loop_14 -print_int_done_14: - mov r0, #1 - mov r1, r1 - mov r2, r2 - mov r7, #4 - svc #0 - mov r0, #1 - ldr r1, =newline - mov r2, #1 - mov r7, #4 - svc #0 - ldr r0, [sp, #68] - mov r7, #1 - svc #0 - -.size _start, .-_start - -.section .data -.Lstr0: - .ascii "gang_sign = " -newline: - .ascii "\n" -num_buf: - .space 16 diff --git a/compiler/out.asm b/compiler/out.asm index f05f88c..3aa5ccf 100644 --- a/compiler/out.asm +++ b/compiler/out.asm @@ -6,493 +6,64 @@ .type _start, %function _start: - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #11413 - str r0, [sp] - sub sp, sp, #4 - mov r0, #3533 - str r0, [sp] - sub sp, sp, #4 - mov r0, #101 - str r0, [sp] - sub sp, sp, #4 - mov r0, #113 - str r0, [sp] - sub sp, sp, #4 - mov r0, #59 - str r0, [sp] - sub sp, sp, #4 - mov r0, #97 - str r0, [sp] - sub sp, sp, #4 - mov r0, #101 - str r0, [sp] - sub sp, sp, #4 - mov r0, #-1 - str r0, [sp] - sub sp, sp, #4 - mov r0, #23 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - ldr r0, [sp, #64] - str r0, [sp, #48] - ldr r0, [sp, #76] - str r0, [sp, #44] - ldr r0, [sp, #88] - str r0, [sp, #40] - mov r0, #1 - str r0, [sp, #36] - mov r0, #0 - str r0, [sp, #4] + mov r9, #0 + mov r10, #1 + sub sp, sp, #4 + mov r0, #9 + str r0, [sp] + add r9, r9, #1 + cmp r9, #1 + bne countermeasure + add r9, r9, #1 + cmp r9, #2 + bne countermeasure + mov r10, #3 while_0: - ldr r0, [sp, #4] + add r9, r9, #1 + cmp r9, r10 + bne countermeasure + add r10, r10, #1 + ldr r0, [sp, #0] mov r1, r0 - ldr r0, [sp, #44] + mov r0, #12 cmp r1, r0 mov r0, #0 it lt movlt r0, #1 cmp r0, #0 beq end_while_0 - ldr r0, [sp, #36] - str r0, [sp, #28] - ldr r0, [sp, #48] - str r0, [sp, #24] - ldr r0, [sp, #40] - str r0, [sp, #20] - mov r0, #0 - str r0, [sp, #16] -while_1: - ldr r0, [sp, #24] - mov r1, r0 - mov r0, #0 - cmp r1, r0 - mov r0, #0 - it gt - movgt r0, #1 - cmp r0, #0 - beq end_while_1 - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #28] - add r0, r1, r0 - str r0, [sp, #16] -while_2: - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - cmp r1, r0 - mov r0, #0 - it gt - movgt r0, #1 - cmp r0, #0 - beq end_while_2 - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - sub r0, r1, r0 - str r0, [sp, #16] - b while_2 -end_while_2: -while_3: - ldr r0, [sp, #16] - mov r1, r0 - mov r0, #0 - cmp r1, r0 - mov r0, #0 - it lt - movlt r0, #1 - cmp r0, #0 - beq end_while_3 - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - add r0, r1, r0 - str r0, [sp, #16] - b while_3 -end_while_3: - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - cmp r1, r0 - mov r0, #0 - it eq - moveq r0, #1 - cmp r0, #0 - beq else_4 - mov r0, #0 - str r0, [sp, #16] - b endif_4 -else_4: -endif_4: - ldr r0, [sp, #24] - mov r1, r0 - mov r0, #1 - sub r0, r1, r0 - str r0, [sp, #24] - b while_1 -end_while_1: - ldr r0, [sp, #16] - str r0, [sp, #36] - ldr r0, [sp, #4] + ldr r0, [sp, #0] mov r1, r0 mov r0, #1 add r0, r1, r0 - str r0, [sp, #4] + str r0, [sp] + add r9, r9, #1 + cmp r9, r10 + bne countermeasure + add r10, r10, #1 + add r9, r9, #1 + cmp r9, r10 + bne countermeasure + add r10, r10, #1 + add r9, r9, #1 + cmp r9, r10 + bne countermeasure + add r10, r10, #1 b while_0 end_while_0: - ldr r0, [sp, #36] - str r0, [sp, #60] - ldr r0, [sp, #64] - str r0, [sp, #48] - ldr r0, [sp, #72] - str r0, [sp, #44] - ldr r0, [sp, #84] - str r0, [sp, #40] - mov r0, #1 - str r0, [sp, #36] - mov r0, #0 - str r0, [sp, #4] -while_5: - ldr r0, [sp, #4] - mov r1, r0 - ldr r0, [sp, #44] - cmp r1, r0 - mov r0, #0 - it lt - movlt r0, #1 - cmp r0, #0 - beq end_while_5 - ldr r0, [sp, #36] - str r0, [sp, #28] - ldr r0, [sp, #48] - str r0, [sp, #24] - ldr r0, [sp, #40] - str r0, [sp, #20] - mov r0, #0 - str r0, [sp, #16] -while_6: - ldr r0, [sp, #24] - mov r1, r0 - mov r0, #0 - cmp r1, r0 - mov r0, #0 - it gt - movgt r0, #1 - cmp r0, #0 - beq end_while_6 - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #28] - add r0, r1, r0 - str r0, [sp, #16] -while_7: - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - cmp r1, r0 - mov r0, #0 - it gt - movgt r0, #1 - cmp r0, #0 - beq end_while_7 - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - sub r0, r1, r0 - str r0, [sp, #16] - b while_7 -end_while_7: -while_8: - ldr r0, [sp, #16] - mov r1, r0 - mov r0, #0 - cmp r1, r0 - mov r0, #0 - it lt - movlt r0, #1 - cmp r0, #0 - beq end_while_8 - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - add r0, r1, r0 - str r0, [sp, #16] - b while_8 -end_while_8: - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - cmp r1, r0 - mov r0, #0 - it eq - moveq r0, #1 - cmp r0, #0 - beq else_9 - mov r0, #0 - str r0, [sp, #16] - b endif_9 -else_9: -endif_9: - ldr r0, [sp, #24] - mov r1, r0 - mov r0, #1 - sub r0, r1, r0 - str r0, [sp, #24] - b while_6 -end_while_6: - ldr r0, [sp, #16] - str r0, [sp, #36] - ldr r0, [sp, #4] - mov r1, r0 - mov r0, #1 - add r0, r1, r0 - str r0, [sp, #4] - b while_5 -end_while_5: - ldr r0, [sp, #36] - str r0, [sp, #56] - ldr r0, [sp, #60] - mov r1, r0 - ldr r0, [sp, #56] - sub r0, r1, r0 - str r0, [sp, #52] - ldr r0, [sp, #52] - str r0, [sp, #28] - ldr r0, [sp, #80] - str r0, [sp, #24] - ldr r0, [sp, #88] - str r0, [sp, #20] - mov r0, #0 - str r0, [sp, #16] -while_10: - ldr r0, [sp, #24] - mov r1, r0 - mov r0, #0 - cmp r1, r0 - mov r0, #0 - it gt - movgt r0, #1 - cmp r0, #0 - beq end_while_10 - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #28] - add r0, r1, r0 - str r0, [sp, #16] -while_11: - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - cmp r1, r0 - mov r0, #0 - it gt - movgt r0, #1 - cmp r0, #0 - beq end_while_11 - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - sub r0, r1, r0 - str r0, [sp, #16] - b while_11 -end_while_11: -while_12: - ldr r0, [sp, #16] - mov r1, r0 - mov r0, #0 - cmp r1, r0 - mov r0, #0 - it lt - movlt r0, #1 - cmp r0, #0 - beq end_while_12 - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - add r0, r1, r0 - str r0, [sp, #16] - b while_12 -end_while_12: - ldr r0, [sp, #16] - mov r1, r0 - ldr r0, [sp, #20] - cmp r1, r0 - mov r0, #0 - it eq - moveq r0, #1 - cmp r0, #0 - beq else_13 - mov r0, #0 - str r0, [sp, #16] - b endif_13 -else_13: -endif_13: - ldr r0, [sp, #24] - mov r1, r0 - mov r0, #1 - sub r0, r1, r0 - str r0, [sp, #24] - b while_10 -end_while_10: - ldr r0, [sp, #16] - str r0, [sp, #52] - ldr r0, [sp, #52] - mov r1, r0 - ldr r0, [sp, #84] - mul r0, r1, r0 - str r0, [sp, #52] - ldr r0, [sp, #52] - mov r1, r0 - ldr r0, [sp, #56] - add r0, r1, r0 - str r0, [sp, #52] - ldr r0, [sp, #52] - str r0, [sp, #68] - mov r0, #1 - ldr r1, =.Lstr0 - mov r2, #15 - mov r7, #4 - svc #0 - mov r0, #1337 - mov r4, r0 - ldr r1, =num_buf - add r1, r1, #16 - mov r2, #0 - cmp r4, #0 - bne print_int_loop_14 - mov r3, #48 - sub r1, r1, #1 - strb r3, [r1] - mov r2, #1 - b print_int_done_14 -print_int_loop_14: - mov r0, r4 - mov r3, #10 - sdiv r5, r0, r3 - mul r6, r5, r3 - sub r7, r0, r6 - add r7, r7, #48 - sub r1, r1, #1 - strb r7, [r1] - add r2, r2, #1 - mov r4, r5 - cmp r4, #0 - bne print_int_loop_14 -print_int_done_14: - mov r0, #1 - mov r1, r1 - mov r2, r2 - mov r7, #4 - svc #0 - mov r0, #1 - ldr r1, =newline - mov r2, #1 - mov r7, #4 - svc #0 - mov r0, #1 - ldr r1, =.Lstr1 - mov r2, #18 - mov r7, #4 - svc #0 - ldr r0, [sp, #100] - mov r4, r0 - ldr r1, =num_buf - add r1, r1, #16 - mov r2, #0 - cmp r4, #0 - bne print_int_loop_15 - mov r3, #48 - sub r1, r1, #1 - strb r3, [r1] - mov r2, #1 - b print_int_done_15 -print_int_loop_15: - mov r0, r4 - mov r3, #10 - sdiv r5, r0, r3 - mul r6, r5, r3 - sub r7, r0, r6 - add r7, r7, #48 - sub r1, r1, #1 - strb r7, [r1] - add r2, r2, #1 - mov r4, r5 - cmp r4, #0 - bne print_int_loop_15 -print_int_done_15: - mov r0, #1 - mov r1, r1 - mov r2, r2 - mov r7, #4 - svc #0 - mov r0, #1 - ldr r1, =newline - mov r2, #1 - mov r7, #4 +mov r9, #2 + add r9, r9, #1 + cmp r9, #3 + bne countermeasure + ldr r0, [sp, #0] + mov r7, #1 svc #0 - ldr r0, [sp, #68] + add r9, r9, #1 + cmp r9, #4 + bne countermeasure +countermeasure: + mov r0, #77 mov r7, #1 svc #0 .size _start, .-_start - -.section .data -.Lstr0: - .ascii "g_sign herro = " -.Lstr1: - .ascii "g_countermeasure: " -newline: - .ascii "\n" -num_buf: - .space 16 diff --git a/compiler/src/codegen/codegen.rs b/compiler/src/codegen/codegen.rs index a3c801e..c5061b9 100644 --- a/compiler/src/codegen/codegen.rs +++ b/compiler/src/codegen/codegen.rs @@ -12,6 +12,7 @@ pub struct CodeGenerator { string_literals: Vec<(String, String)>, need_int_print: bool, step_counter: i32, + in_loop: bool, } impl CodeGenerator { @@ -25,6 +26,7 @@ impl CodeGenerator { string_literals: Vec::new(), need_int_print: false, step_counter: 0, + in_loop: false, } } pub fn generate(&mut self, ast: AST, is_hard: bool) { @@ -33,9 +35,6 @@ impl CodeGenerator { for func in ast { self.emit(func); } - if self.hard { - self.emit_countermeasure(); - } self.emit_print_data(); } @@ -123,11 +122,19 @@ impl CodeGenerator { if !self.hard { return; } - - self.write_line("add r9, r9, #1", 1); - self.write_line("cmp r9, r10", 1); - self.write_line("bne countermeasure", 1); - self.write_line("add r10, r10, #1", 1); + self.step_counter += 1; + + if self.in_loop { + self.write_line("add r9, r9, #1", 1); + self.write_line("cmp r9, r10", 1); + self.write_line("bne countermeasure", 1); + self.write_line("add r10, r10, #1", 1); + + } else { + self.write_line("add r9, r9, #1", 1); + self.write_line(&format!("cmp r9, #{}", self.step_counter), 1); + self.write_line("bne countermeasure", 1); + } } fn emit_print_data(&mut self) { @@ -172,23 +179,30 @@ impl CodeGenerator { // THEN branch self.emit_step_check(); self.emit_block(block, false); - let then_end = self.step_counter; + if self.hard { + self.step_counter = saved; + self.write_line(&format!("mov r9, #{}", self.step_counter), 1); + } self.write_line(&format!("b endif_{}", label_id), 1); // ELSE branch self.write_line(&format!("else_{}:", label_id), 0); - self.step_counter = saved; + if self.hard { + self.step_counter = saved; + } if let Some(else_block) = option { self.emit_step_check(); self.emit_block(else_block, false); + if self.hard { + self.step_counter = saved; + self.write_line(&format!("mov r9, #{}", self.step_counter), 1); + } } - let else_end = self.step_counter; self.write_line(&format!("endif_{}:", label_id), 0); - self.step_counter = then_end.max(else_end); } _ => panic!("emit_if called with non-if statement"), } @@ -199,7 +213,13 @@ impl CodeGenerator { Stmt::While { expr, block } => { let label_id = self.label_count; self.label_count += 1; + let saved = self.step_counter; + self.in_loop = true; + + if self.hard { + self.write_line(&format!("mov r10, #{}", self.step_counter + 1), 1); + } self.write_line(&format!("while_{}:", label_id), 0); self.emit_step_check(); @@ -212,6 +232,11 @@ impl CodeGenerator { self.write_line(&format!("b while_{}", label_id), 1); self.write_line(&format!("end_while_{}:", label_id), 0); + if self.hard { + self.step_counter = saved; + self.write_line(&format!("mov r9, #{}", self.step_counter), 1); + } + self.in_loop = false; } _ => panic!("emit_while called with non-while statement"), } diff --git a/compiler/vpin/VerifyPIN_0/Makefile b/compiler/vpin/VerifyPIN_0/Makefile new file mode 100755 index 0000000..094bf73 --- /dev/null +++ b/compiler/vpin/VerifyPIN_0/Makefile @@ -0,0 +1,26 @@ +# Makefile script with commands to generate the benchmark assembly and binaries. +# Description of the targets: +# x86-ptc: produce lazart object files with oracle PTC +# x86-auth: produce lazart object files with oracle AUTH +# clean: clean generated files, including output binaries + +.PHONY: clean x86-ptc x86-auth + +TARGET = verifypin_0 +FILES = src/countermeasure.c src/initialize.c src/oracle.c src/code.c src/main.c + +INC_DIR = -I../share -Iinclude +BIN_DIR = bin + +CFLAGS = $(INC_DIR) -Wall -Wextra + +x86-auth: + @mkdir -p $(BIN_DIR) + @clang -DAUTH $(FILES) $(CFLAGS) -o $(BIN_DIR)/$(TARGET) + +x86-ptc: + @mkdir -p $(BIN_DIR) + @clang -DPTC $(FILES) $(CFLAGS) -o $(BIN_DIR)/$(TARGET) + +clean: + @rm -rf $(BIN_DIR) diff --git a/compiler/vpin/VerifyPIN_0/src/code.c b/compiler/vpin/VerifyPIN_0/src/code.c new file mode 100755 index 0000000..72553cd --- /dev/null +++ b/compiler/vpin/VerifyPIN_0/src/code.c @@ -0,0 +1,58 @@ +/**************************************************************************/ +/* */ +/* This file is part of FISSC. */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 3.0. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 3.0 */ +/* for more details (enclosed in the file LICENSE). */ +/* */ +/**************************************************************************/ + +#include "interface.h" +#include "types.h" +#include "commons.h" + +extern SBYTE g_ptc; +extern BOOL g_authenticated; +extern UBYTE g_userPin[PIN_SIZE]; +extern UBYTE g_cardPin[PIN_SIZE]; + +#ifdef INLINE +__attribute__((always_inline)) inline BOOL byteArrayCompare(UBYTE* a1, UBYTE* a2, UBYTE size) +#else +BOOL byteArrayCompare(UBYTE* a1, UBYTE* a2, UBYTE size) +#endif +{ + int i; + for(i = 0; i < size; i++) { + if(a1[i] != a2[i]) { + return 0; + } + } + return 1; +} + +BOOL verifyPIN() { + g_authenticated = 0; + + if(g_ptc > 0) { + if(byteArrayCompare(g_userPin, g_cardPin, PIN_SIZE) == 1) { + g_ptc = 3; + g_authenticated = 1; // Authentication(); + return 1; + } else { + g_ptc--; + return 0; + } + } + + return 0; +} diff --git a/compiler/vpin/VerifyPIN_0/src/commons.h b/compiler/vpin/VerifyPIN_0/src/commons.h new file mode 100755 index 0000000..78ce18f --- /dev/null +++ b/compiler/vpin/VerifyPIN_0/src/commons.h @@ -0,0 +1,26 @@ +/**************************************************************************/ +/* */ +/* This file is part of FISSC. */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 3.0. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 3.0 */ +/* for more details (enclosed in the file LICENSE). */ +/* */ +/**************************************************************************/ + +#ifndef H_COMMONS +#define H_COMMONS + +// macro definitions +#define INITIAL_VALUE 0x2a +#define PIN_SIZE 4 + +#endif // H_COMMONS diff --git a/compiler/vpin/VerifyPIN_0/src/countermeasure.c b/compiler/vpin/VerifyPIN_0/src/countermeasure.c new file mode 100755 index 0000000..3475fbf --- /dev/null +++ b/compiler/vpin/VerifyPIN_0/src/countermeasure.c @@ -0,0 +1,27 @@ +/**************************************************************************/ +/* */ +/* This file is part of FISSC. */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 3.0. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 3.0 */ +/* for more details (enclosed in the file LICENSE). */ +/* */ +/**************************************************************************/ + +#include "interface.h" +#include "types.h" + +extern UBYTE g_countermeasure; + +void countermeasure() +{ + g_countermeasure = 1; +} diff --git a/compiler/vpin/VerifyPIN_0/src/initialize.c b/compiler/vpin/VerifyPIN_0/src/initialize.c new file mode 100755 index 0000000..50abcc9 --- /dev/null +++ b/compiler/vpin/VerifyPIN_0/src/initialize.c @@ -0,0 +1,48 @@ +/**************************************************************************/ +/* */ +/* This file is part of FISSC. */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 3.0. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 3.0 */ +/* for more details (enclosed in the file LICENSE). */ +/* */ +/**************************************************************************/ + +#include "types.h" +#include "interface.h" +#include "commons.h" + +// global variables definition +BOOL g_authenticated; +SBYTE g_ptc; +UBYTE g_countermeasure; +UBYTE g_userPin[PIN_SIZE]; +UBYTE g_cardPin[PIN_SIZE]; + + +void initialize() +{ + // local variables + int i; + // global variables initialization + g_authenticated = 0; + g_ptc = 3; + g_countermeasure = 0; + // card PIN = 1 2 3 4 5... + for (i = 0; i < PIN_SIZE; ++i) { + g_cardPin[i] = i+1; + } + // user PIN = 0 0 0 0 0... + for (i = 0 ; i < PIN_SIZE; ++i) { + g_userPin[i] = 0; + } +} + diff --git a/compiler/vpin/VerifyPIN_0/src/main.c b/compiler/vpin/VerifyPIN_0/src/main.c new file mode 100755 index 0000000..159fb1c --- /dev/null +++ b/compiler/vpin/VerifyPIN_0/src/main.c @@ -0,0 +1,50 @@ +/**************************************************************************/ +/* */ +/* This file is part of FISSC. */ +/* */ +/* You can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 3.0. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 3.0 */ +/* for more details (enclosed in the file LICENSE). */ +/* */ +/**************************************************************************/ + +/*$ + @name = VerifyPIN_0 + @feature = verifyPIN + @fault-model = test-inversion + @attack-scenario = oracle + @countermeasure = none + @maintainers = Etienne Boespflug, VERIMAG + @authors = Lionel Rivière, SERTIF Consortium + @version 2.2 +*/ + +#include + +#include "interface.h" +#include "types.h" +#include "lazart.h" + +extern UBYTE g_countermeasure; +extern BOOL g_authenticated; +extern SBYTE g_ptc; + +BOOL verifyPIN(void); + +int main() +{ + initialize(); + verifyPIN(); + LAZART_ORACLE(oracle()); + + printf("[@] g_countermeasure = %i, g_authenticated = %x, g_ptc = %i\n", g_countermeasure, g_authenticated, g_ptc); + return 0; +} diff --git a/compiler/vpin/VerifyPIN_0/src/oracle.c b/compiler/vpin/VerifyPIN_0/src/oracle.c new file mode 100755 index 0000000..72306cb --- /dev/null +++ b/compiler/vpin/VerifyPIN_0/src/oracle.c @@ -0,0 +1,45 @@ +/**************************************************************************/ +/* */ +/* This file is part of FISSC. */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 3.0. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 3.0 */ +/* for more details (enclosed in the file LICENSE). */ +/* */ +/**************************************************************************/ + +#include "interface.h" +#include "types.h" + +// define the oracle you want to use. +#ifdef AUTH +#define oracle_auth oracle +#endif + +#ifdef PTC +#define oracle_ptc oracle +#endif + +extern UBYTE g_countermeasure; +extern BOOL g_authenticated; +extern SBYTE g_ptc; + +BOOL oracle_auth() +{ + return g_countermeasure != 1 && g_authenticated == 1; +} + +BOOL oracle_ptc() +{ + return g_countermeasure != 1 && g_ptc >= 3; +} + + diff --git a/testing/out.asm b/compiler/vpin/crt-rsa.asm similarity index 100% rename from testing/out.asm rename to compiler/vpin/crt-rsa.asm diff --git a/testing/fissc/crt-rsa.trv b/compiler/vpin/crt-rsa.trv similarity index 99% rename from testing/fissc/crt-rsa.trv rename to compiler/vpin/crt-rsa.trv index b1ce082..62fc913 100644 --- a/testing/fissc/crt-rsa.trv +++ b/compiler/vpin/crt-rsa.trv @@ -114,6 +114,7 @@ func main() -> Integer { g_sign = tmp; print("g_sign = ", g_sign); + print("g_countermeasure: ", g_countermeasure); return g_sign; diff --git a/compiler/vpin/out.asm b/compiler/vpin/out.asm new file mode 100644 index 0000000..83c42ef --- /dev/null +++ b/compiler/vpin/out.asm @@ -0,0 +1,276 @@ +.syntax unified +.thumb + +.section .text +.global _start +.type _start, %function + +_start: + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + sub sp, sp, #4 + mov r0, #3 + str r0, [sp] + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + sub sp, sp, #4 + mov r0, #1 + str r0, [sp] + sub sp, sp, #4 + mov r0, #2 + str r0, [sp] + sub sp, sp, #4 + mov r0, #3 + str r0, [sp] + sub sp, sp, #4 + mov r0, #4 + str r0, [sp] + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + mov r0, #0 + str r0, [sp, #32] + ldr r0, [sp, #36] + mov r1, r0 + mov r0, #0 + cmp r1, r0 + mov r0, #0 + it gt + movgt r0, #1 + cmp r0, #0 + beq else_0 + sub sp, sp, #4 + mov r0, #1 + str r0, [sp] + ldr r0, [sp, #16] + mov r1, r0 + ldr r0, [sp, #32] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_1 + mov r0, #0 + str r0, [sp] + b endif_1 +else_1: +endif_1: + ldr r0, [sp, #12] + mov r1, r0 + ldr r0, [sp, #28] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_2 + mov r0, #0 + str r0, [sp] + b endif_2 +else_2: +endif_2: + ldr r0, [sp, #8] + mov r1, r0 + ldr r0, [sp, #24] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_3 + mov r0, #0 + str r0, [sp] + b endif_3 +else_3: +endif_3: + ldr r0, [sp, #4] + mov r1, r0 + ldr r0, [sp, #20] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_4 + mov r0, #0 + str r0, [sp] + b endif_4 +else_4: +endif_4: + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #1 + cmp r1, r0 + mov r0, #0 + it eq + moveq r0, #1 + cmp r0, #0 + beq else_5 + mov r0, #3 + str r0, [sp, #40] + mov r0, #1 + str r0, [sp, #36] + b endif_5 +else_5: + ldr r0, [sp, #40] + mov r1, r0 + mov r0, #1 + sub r0, r1, r0 + str r0, [sp, #40] +endif_5: + add sp, sp, #4 + b endif_0 +else_0: +endif_0: + mov r0, #1 + ldr r1, =.Lstr0 + mov r2, #18 + mov r7, #4 + svc #0 + ldr r0, [sp, #40] + mov r4, r0 + ldr r1, =num_buf + add r1, r1, #16 + mov r2, #0 + cmp r4, #0 + bne print_int_loop_6 + mov r3, #48 + sub r1, r1, #1 + strb r3, [r1] + mov r2, #1 + b print_int_done_6 +print_int_loop_6: + mov r0, r4 + mov r3, #10 + sdiv r5, r0, r3 + mul r6, r5, r3 + sub r7, r0, r6 + add r7, r7, #48 + sub r1, r1, #1 + strb r7, [r1] + add r2, r2, #1 + mov r4, r5 + cmp r4, #0 + bne print_int_loop_6 +print_int_done_6: + mov r0, #1 + mov r1, r1 + mov r2, r2 + mov r7, #4 + svc #0 + mov r0, #1 + ldr r1, =newline + mov r2, #1 + mov r7, #4 + svc #0 + mov r0, #1 + ldr r1, =.Lstr1 + mov r2, #17 + mov r7, #4 + svc #0 + ldr r0, [sp, #32] + mov r4, r0 + ldr r1, =num_buf + add r1, r1, #16 + mov r2, #0 + cmp r4, #0 + bne print_int_loop_7 + mov r3, #48 + sub r1, r1, #1 + strb r3, [r1] + mov r2, #1 + b print_int_done_7 +print_int_loop_7: + mov r0, r4 + mov r3, #10 + sdiv r5, r0, r3 + mul r6, r5, r3 + sub r7, r0, r6 + add r7, r7, #48 + sub r1, r1, #1 + strb r7, [r1] + add r2, r2, #1 + mov r4, r5 + cmp r4, #0 + bne print_int_loop_7 +print_int_done_7: + mov r0, #1 + mov r1, r1 + mov r2, r2 + mov r7, #4 + svc #0 + mov r0, #1 + ldr r1, =newline + mov r2, #1 + mov r7, #4 + svc #0 + mov r0, #1 + ldr r1, =.Lstr2 + mov r2, #7 + mov r7, #4 + svc #0 + ldr r0, [sp, #36] + mov r4, r0 + ldr r1, =num_buf + add r1, r1, #16 + mov r2, #0 + cmp r4, #0 + bne print_int_loop_8 + mov r3, #48 + sub r1, r1, #1 + strb r3, [r1] + mov r2, #1 + b print_int_done_8 +print_int_loop_8: + mov r0, r4 + mov r3, #10 + sdiv r5, r0, r3 + mul r6, r5, r3 + sub r7, r0, r6 + add r7, r7, #48 + sub r1, r1, #1 + strb r7, [r1] + add r2, r2, #1 + mov r4, r5 + cmp r4, #0 + bne print_int_loop_8 +print_int_done_8: + mov r0, #1 + mov r1, r1 + mov r2, r2 + mov r7, #4 + svc #0 + mov r0, #1 + ldr r1, =newline + mov r2, #1 + mov r7, #4 + svc #0 + ldr r0, [sp, #32] + mov r7, #1 + svc #0 + +.size _start, .-_start + +.section .data +.Lstr0: + .ascii "g_countermeasure: " +.Lstr1: + .ascii "g_authenticated: " +.Lstr2: + .ascii "g_ptc: " +newline: + .ascii "\n" +num_buf: + .space 16 diff --git a/compiler/vpin/share/interface.h b/compiler/vpin/share/interface.h new file mode 100755 index 0000000..62ea22f --- /dev/null +++ b/compiler/vpin/share/interface.h @@ -0,0 +1,49 @@ +/**************************************************************************/ +/* */ +/* This file is part of FISSC. */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 3.0. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 3.0 */ +/* for more details (enclosed in the file LICENSE). */ +/* */ +/**************************************************************************/ + +/*$ + @authors = SERTIF Consortium + @feature = N/A + @target = N/A + @countermeasure = N/A + @difficulties = N/A + @purpose = shared interface for examples +*/ + +#ifndef H_INTERFACE +#define H_INTERFACE + +#include "types.h" + +/* defines what happens when a fault has been detected + implementation defined +*/ +void countermeasure(void); + +/* initializes global variables at the beginning of an example + implementation-defined + example-defined +*/ +void initialize(void); + +/* determines whether an attack is successful + example-defined +*/ +BOOL oracle(void); + +#endif // H_INTERFACE diff --git a/compiler/vpin/share/lazart.h b/compiler/vpin/share/lazart.h new file mode 100755 index 0000000..cf68670 --- /dev/null +++ b/compiler/vpin/share/lazart.h @@ -0,0 +1,21 @@ +#ifndef LAZART_API_HPP +#define LAZART_API_HPP + +#ifdef LAZART + +#include + +/*#define LAZART_ORACLE(oracle) \ + if(oracle) { \ + klee_assume(oracle); \ + } else { \ + klee_assume(0 != 0 ); \ + }*/ + +#define LAZART_ORACLE(oracle) klee_assume(oracle) + +#else +#define LAZART_ORACLE(oracle) +#endif // LAZART + +#endif // LAZART_API_HPP diff --git a/compiler/vpin/share/types.h b/compiler/vpin/share/types.h new file mode 100755 index 0000000..74bb38e --- /dev/null +++ b/compiler/vpin/share/types.h @@ -0,0 +1,29 @@ +/**************************************************************************/ +/* */ +/* This file is part of FISSC. */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 3.0. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 3.0 */ +/* for more details (enclosed in the file LICENSE). */ +/* */ +/**************************************************************************/ + +#ifndef H_TYPES +#define H_TYPES +typedef signed char SBYTE; +typedef unsigned char UBYTE; +typedef unsigned char BOOL; +typedef unsigned long ULONG; + +#define BOOL_TRUE 0xAA +#define BOOL_FALSE 0x55 + +#endif // H_TYPES diff --git a/compiler/vpin/verifypin.asm b/compiler/vpin/verifypin.asm new file mode 100644 index 0000000..204cb5b --- /dev/null +++ b/compiler/vpin/verifypin.asm @@ -0,0 +1,282 @@ +.syntax unified +.thumb + +.section .text +.global _start +.type _start, %function + +_start: + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + sub sp, sp, #4 + mov r0, #3 + str r0, [sp] + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + sub sp, sp, #4 + mov r0, #1 + str r0, [sp] + sub sp, sp, #4 + mov r0, #2 + str r0, [sp] + sub sp, sp, #4 + mov r0, #3 + str r0, [sp] + sub sp, sp, #4 + mov r0, #4 + str r0, [sp] + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + mov r0, #0 + str r0, [sp, #32] + ldr r0, [sp, #36] + mov r1, r0 + mov r0, #0 + cmp r1, r0 + mov r0, #0 + it gt + movgt r0, #1 + cmp r0, #0 + beq else_0 + sub sp, sp, #4 + mov r0, #1 + str r0, [sp] + ldr r0, [sp, #16] + mov r1, r0 + ldr r0, [sp, #32] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_1 + mov r0, #0 + str r0, [sp] + b endif_1 +else_1: +endif_1: + ldr r0, [sp, #12] + mov r1, r0 + ldr r0, [sp, #28] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_2 + mov r0, #0 + str r0, [sp] + b endif_2 +else_2: +endif_2: + ldr r0, [sp, #8] + mov r1, r0 + ldr r0, [sp, #24] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_3 + mov r0, #0 + str r0, [sp] + b endif_3 +else_3: +endif_3: + ldr r0, [sp, #4] + mov r1, r0 + ldr r0, [sp, #20] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_4 + mov r0, #0 + str r0, [sp] + b endif_4 +else_4: +endif_4: + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #1 + cmp r1, r0 + mov r0, #0 + it eq + moveq r0, #1 + cmp r0, #0 + beq else_5 + mov r0, #3 + str r0, [sp, #40] + mov r0, #1 + str r0, [sp, #36] + ldr r0, [sp, #36] + mov r7, #1 + svc #0 + b endif_5 +else_5: + ldr r0, [sp, #40] + mov r1, r0 + mov r0, #1 + sub r0, r1, r0 + str r0, [sp, #40] + mov r0, #0 + mov r7, #1 + svc #0 +endif_5: + add sp, sp, #4 + b endif_0 +else_0: +endif_0: + mov r0, #1 + ldr r1, =.Lstr0 + mov r2, #18 + mov r7, #4 + svc #0 + ldr r0, [sp, #40] + mov r4, r0 + ldr r1, =num_buf + add r1, r1, #16 + mov r2, #0 + cmp r4, #0 + bne print_int_loop_6 + mov r3, #48 + sub r1, r1, #1 + strb r3, [r1] + mov r2, #1 + b print_int_done_6 +print_int_loop_6: + mov r0, r4 + mov r3, #10 + sdiv r5, r0, r3 + mul r6, r5, r3 + sub r7, r0, r6 + add r7, r7, #48 + sub r1, r1, #1 + strb r7, [r1] + add r2, r2, #1 + mov r4, r5 + cmp r4, #0 + bne print_int_loop_6 +print_int_done_6: + mov r0, #1 + mov r1, r1 + mov r2, r2 + mov r7, #4 + svc #0 + mov r0, #1 + ldr r1, =newline + mov r2, #1 + mov r7, #4 + svc #0 + mov r0, #1 + ldr r1, =.Lstr1 + mov r2, #17 + mov r7, #4 + svc #0 + ldr r0, [sp, #32] + mov r4, r0 + ldr r1, =num_buf + add r1, r1, #16 + mov r2, #0 + cmp r4, #0 + bne print_int_loop_7 + mov r3, #48 + sub r1, r1, #1 + strb r3, [r1] + mov r2, #1 + b print_int_done_7 +print_int_loop_7: + mov r0, r4 + mov r3, #10 + sdiv r5, r0, r3 + mul r6, r5, r3 + sub r7, r0, r6 + add r7, r7, #48 + sub r1, r1, #1 + strb r7, [r1] + add r2, r2, #1 + mov r4, r5 + cmp r4, #0 + bne print_int_loop_7 +print_int_done_7: + mov r0, #1 + mov r1, r1 + mov r2, r2 + mov r7, #4 + svc #0 + mov r0, #1 + ldr r1, =newline + mov r2, #1 + mov r7, #4 + svc #0 + mov r0, #1 + ldr r1, =.Lstr2 + mov r2, #7 + mov r7, #4 + svc #0 + ldr r0, [sp, #36] + mov r4, r0 + ldr r1, =num_buf + add r1, r1, #16 + mov r2, #0 + cmp r4, #0 + bne print_int_loop_8 + mov r3, #48 + sub r1, r1, #1 + strb r3, [r1] + mov r2, #1 + b print_int_done_8 +print_int_loop_8: + mov r0, r4 + mov r3, #10 + sdiv r5, r0, r3 + mul r6, r5, r3 + sub r7, r0, r6 + add r7, r7, #48 + sub r1, r1, #1 + strb r7, [r1] + add r2, r2, #1 + mov r4, r5 + cmp r4, #0 + bne print_int_loop_8 +print_int_done_8: + mov r0, #1 + mov r1, r1 + mov r2, r2 + mov r7, #4 + svc #0 + mov r0, #1 + ldr r1, =newline + mov r2, #1 + mov r7, #4 + svc #0 + mov r0, #0 + mov r7, #1 + svc #0 + +.size _start, .-_start + +.section .data +.Lstr0: + .ascii "g_countermeasure: " +.Lstr1: + .ascii "g_authenticated: " +.Lstr2: + .ascii "g_ptc: " +newline: + .ascii "\n" +num_buf: + .space 16 diff --git a/compiler/vpin/verifypin.trv b/compiler/vpin/verifypin.trv new file mode 100644 index 0000000..904bbf5 --- /dev/null +++ b/compiler/vpin/verifypin.trv @@ -0,0 +1,46 @@ +func main() -> Integer { + let g_countermeasure : Integer = 0; + let ptc : Integer = 3; + let authenticated : Integer = 0; + let cardPin1 : Integer = 1; + let cardPin2 : Integer = 2; + let cardPin3 : Integer = 3; + let cardPin4 : Integer = 4; + let userPin1 : Integer = 0; + let userPin2 : Integer = 0; + let userPin3 : Integer = 0; + let userPin4 : Integer = 0; + + authenticated = 0; + + if ptc > 0 then { + let pinsEqual : Integer = 1; + if userPin1 != cardPin1 then { + pinsEqual = 0; + } + + if userPin2 != cardPin2 then { + pinsEqual = 0; + } + + if userPin3 != cardPin3 then { + pinsEqual = 0; + } + + if userPin4 != cardPin4 then { + pinsEqual = 0; + } + + if pinsEqual == 1 then { + ptc = 3; + authenticated = 1; + } else { + ptc = ptc - 1; + } + } + print("g_countermeasure: ", g_countermeasure); + print("g_authenticated: ", authenticated); + print("g_ptc: ", ptc); + + return authenticated; +} diff --git a/interpreter/Cargo.lock b/interpreter/Cargo.lock index 2dd1dd9..b1c241e 100644 --- a/interpreter/Cargo.lock +++ b/interpreter/Cargo.lock @@ -116,6 +116,12 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" +[[package]] +name = "json" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" + [[package]] name = "once_cell_polyfill" version = "1.70.2" @@ -172,6 +178,7 @@ name = "thumb2_interpreter" version = "0.1.0" dependencies = [ "clap", + "json", "pretty_assertions", ] diff --git a/interpreter/Cargo.toml b/interpreter/Cargo.toml index 02732e6..c14e0d6 100644 --- a/interpreter/Cargo.toml +++ b/interpreter/Cargo.toml @@ -8,3 +8,4 @@ pretty_assertions = "1.4" [dependencies] clap = { version = "4.5.60", features = ["derive"] } +json = "0.12.4" diff --git a/interpreter/hard.asm b/interpreter/hard.asm new file mode 100644 index 0000000..59dd9e2 --- /dev/null +++ b/interpreter/hard.asm @@ -0,0 +1,414 @@ +.syntax unified +.thumb + +.section .text +.global _start +.type _start, %function + +_start: + mov r9, #0 + mov r10, #1 + sub sp, sp, #4 + mov r0, #3 + str r0, [sp] + add r9, r9, #1 + cmp r9, #1 + bne countermeasure + add r9, r9, #1 + cmp r9, #2 + bne countermeasure + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + add r9, r9, #1 + cmp r9, #3 + bne countermeasure + add r9, r9, #1 + cmp r9, #4 + bne countermeasure + sub sp, sp, #4 + mov r0, #1 + str r0, [sp] + add r9, r9, #1 + cmp r9, #5 + bne countermeasure + add r9, r9, #1 + cmp r9, #6 + bne countermeasure + sub sp, sp, #4 + mov r0, #2 + str r0, [sp] + add r9, r9, #1 + cmp r9, #7 + bne countermeasure + add r9, r9, #1 + cmp r9, #8 + bne countermeasure + sub sp, sp, #4 + mov r0, #3 + str r0, [sp] + add r9, r9, #1 + cmp r9, #9 + bne countermeasure + add r9, r9, #1 + cmp r9, #10 + bne countermeasure + sub sp, sp, #4 + mov r0, #4 + str r0, [sp] + add r9, r9, #1 + cmp r9, #11 + bne countermeasure + add r9, r9, #1 + cmp r9, #12 + bne countermeasure + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + add r9, r9, #1 + cmp r9, #13 + bne countermeasure + add r9, r9, #1 + cmp r9, #14 + bne countermeasure + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + add r9, r9, #1 + cmp r9, #15 + bne countermeasure + add r9, r9, #1 + cmp r9, #16 + bne countermeasure + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + add r9, r9, #1 + cmp r9, #17 + bne countermeasure + add r9, r9, #1 + cmp r9, #18 + bne countermeasure + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] + add r9, r9, #1 + cmp r9, #19 + bne countermeasure + add r9, r9, #1 + cmp r9, #20 + bne countermeasure + mov r0, #0 + str r0, [sp, #32] + add r9, r9, #1 + cmp r9, #21 + bne countermeasure + add r9, r9, #1 + cmp r9, #22 + bne countermeasure + ldr r0, [sp, #36] + mov r1, r0 + mov r0, #0 + cmp r1, r0 + mov r0, #0 + it gt + movgt r0, #1 + cmp r0, #0 + beq else_0 + add r9, r9, #1 + cmp r9, #23 + bne countermeasure + sub sp, sp, #4 + mov r0, #1 + str r0, [sp] + add r9, r9, #1 + cmp r9, #24 + bne countermeasure + add r9, r9, #1 + cmp r9, #25 + bne countermeasure + ldr r0, [sp, #16] + mov r1, r0 + ldr r0, [sp, #32] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_1 + add r9, r9, #1 + cmp r9, #26 + bne countermeasure + mov r0, #0 + str r0, [sp] + add r9, r9, #1 + cmp r9, #27 + bne countermeasure + add r9, r9, #1 + cmp r9, #28 + bne countermeasure + mov r9, #25 + b endif_1 +else_1: + mov r9, #25 +endif_1: + add r9, r9, #1 + cmp r9, #26 + bne countermeasure + ldr r0, [sp, #12] + mov r1, r0 + ldr r0, [sp, #28] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_2 + add r9, r9, #1 + cmp r9, #27 + bne countermeasure + mov r0, #0 + str r0, [sp] + add r9, r9, #1 + cmp r9, #28 + bne countermeasure + add r9, r9, #1 + cmp r9, #29 + bne countermeasure + mov r9, #26 + b endif_2 +else_2: + mov r9, #26 +endif_2: + add r9, r9, #1 + cmp r9, #27 + bne countermeasure + ldr r0, [sp, #8] + mov r1, r0 + ldr r0, [sp, #24] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_3 + add r9, r9, #1 + cmp r9, #28 + bne countermeasure + mov r0, #0 + str r0, [sp] + add r9, r9, #1 + cmp r9, #29 + bne countermeasure + add r9, r9, #1 + cmp r9, #30 + bne countermeasure + mov r9, #27 + b endif_3 +else_3: + mov r9, #27 +endif_3: + add r9, r9, #1 + cmp r9, #28 + bne countermeasure + ldr r0, [sp, #4] + mov r1, r0 + ldr r0, [sp, #20] + cmp r1, r0 + mov r0, #0 + it ne + movne r0, #1 + cmp r0, #0 + beq else_4 + add r9, r9, #1 + cmp r9, #29 + bne countermeasure + mov r0, #0 + str r0, [sp] + add r9, r9, #1 + cmp r9, #30 + bne countermeasure + add r9, r9, #1 + cmp r9, #31 + bne countermeasure + mov r9, #28 + b endif_4 +else_4: + mov r9, #28 +endif_4: + add r9, r9, #1 + cmp r9, #29 + bne countermeasure + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #1 + cmp r1, r0 + mov r0, #0 + it eq + moveq r0, #1 + cmp r0, #0 + beq else_5 + add r9, r9, #1 + cmp r9, #30 + bne countermeasure + mov r0, #3 + str r0, [sp, #40] + add r9, r9, #1 + cmp r9, #31 + bne countermeasure + add r9, r9, #1 + cmp r9, #32 + bne countermeasure + mov r0, #1 + str r0, [sp, #36] + add r9, r9, #1 + cmp r9, #33 + bne countermeasure + add r9, r9, #1 + cmp r9, #34 + bne countermeasure + mov r9, #29 + b endif_5 +else_5: + add r9, r9, #1 + cmp r9, #30 + bne countermeasure + ldr r0, [sp, #40] + mov r1, r0 + mov r0, #1 + sub r0, r1, r0 + str r0, [sp, #40] + add r9, r9, #1 + cmp r9, #31 + bne countermeasure + add r9, r9, #1 + cmp r9, #32 + bne countermeasure + mov r9, #29 +endif_5: + add r9, r9, #1 + cmp r9, #30 + bne countermeasure + add sp, sp, #4 + mov r9, #22 + b endif_0 +else_0: + mov r9, #22 +endif_0: + add r9, r9, #1 + cmp r9, #23 + bne countermeasure + mov r0, #1 + ldr r1, =.Lstr0 + mov r2, #17 + mov r7, #4 + svc #0 + ldr r0, [sp, #32] + mov r4, r0 + ldr r1, =num_buf + add r1, r1, #16 + mov r2, #0 + cmp r4, #0 + bne print_int_loop_6 + mov r3, #48 + sub r1, r1, #1 + strb r3, [r1] + mov r2, #1 + b print_int_done_6 +print_int_loop_6: + mov r0, r4 + mov r3, #10 + sdiv r5, r0, r3 + mul r6, r5, r3 + sub r7, r0, r6 + add r7, r7, #48 + sub r1, r1, #1 + strb r7, [r1] + add r2, r2, #1 + mov r4, r5 + cmp r4, #0 + bne print_int_loop_6 +print_int_done_6: + mov r0, #1 + mov r1, r1 + mov r2, r2 + mov r7, #4 + svc #0 + mov r0, #1 + ldr r1, =newline + mov r2, #1 + mov r7, #4 + svc #0 + add r9, r9, #1 + cmp r9, #24 + bne countermeasure + mov r0, #1 + ldr r1, =.Lstr1 + mov r2, #7 + mov r7, #4 + svc #0 + ldr r0, [sp, #36] + mov r4, r0 + ldr r1, =num_buf + add r1, r1, #16 + mov r2, #0 + cmp r4, #0 + bne print_int_loop_7 + mov r3, #48 + sub r1, r1, #1 + strb r3, [r1] + mov r2, #1 + b print_int_done_7 +print_int_loop_7: + mov r0, r4 + mov r3, #10 + sdiv r5, r0, r3 + mul r6, r5, r3 + sub r7, r0, r6 + add r7, r7, #48 + sub r1, r1, #1 + strb r7, [r1] + add r2, r2, #1 + mov r4, r5 + cmp r4, #0 + bne print_int_loop_7 +print_int_done_7: + mov r0, #1 + mov r1, r1 + mov r2, r2 + mov r7, #4 + svc #0 + mov r0, #1 + ldr r1, =newline + mov r2, #1 + mov r7, #4 + svc #0 + add r9, r9, #1 + cmp r9, #25 + bne countermeasure + ldr r0, [sp, #32] + mov r7, #1 + svc #0 + add r9, r9, #1 + cmp r9, #26 + bne countermeasure +countermeasure: + mov r0, #77 + mov r7, #1 + svc #0 + +.size _start, .-_start + +.section .data +.Lstr0: + .ascii "g_authenticated: " +.Lstr1: + .ascii "g_ptc: " +newline: + .ascii "\n" +num_buf: + .space 16 +step_counter: + .word 0 +fault_msg: + .ascii "Control flow violation detected\n" diff --git a/interpreter/src/interpreter.rs b/interpreter/src/interpreter.rs index 8e9954b..4ef3f87 100644 --- a/interpreter/src/interpreter.rs +++ b/interpreter/src/interpreter.rs @@ -4,9 +4,12 @@ use std::io::BufRead; use std::process::exit; use std::usize; +use json::{ JsonValue, object }; + use crate::memory::EmulatorMemory; -const NUM_REGISTERS: usize = 32; +const NUM_REGISTERS: usize = 13; //FIXME: Find out if num registers is 13 (r0-r12) plsssss +//FIXME: Also find out what to do with sp, lr, apsr, cpsr #[derive(Clone, Debug, PartialEq, Default)] pub struct ItState { @@ -89,6 +92,7 @@ pub enum InjectionTarget { pub struct InjectionSpec { pub target: InjectionTarget, pub trigger_pc: i32, + pub has_triggered: bool, } pub struct Interpreter { @@ -101,9 +105,11 @@ pub struct Interpreter { cpsr: Cpsr, file: Vec, debug: bool, + test_mode: bool, start_time: std::time::Instant, max_time: std::time::Duration, fault_spec: InjectionSpec, + test_report: json::JsonValue, } impl Interpreter { @@ -118,12 +124,15 @@ impl Interpreter { cpsr: Cpsr::default(), file: Vec::new(), debug: false, + test_mode: false, start_time: std::time::Instant::now(), max_time: std::time::Duration::from_millis(1000), fault_spec: InjectionSpec { target: InjectionTarget::None, trigger_pc: -1, + has_triggered: false, }, + test_report: object! { title: "test_report" }, } } @@ -172,6 +181,9 @@ impl Interpreter { ); } } + pub fn set_test_mode(&mut self, test_mode: bool) { + self.test_mode = test_mode; + } pub fn set_debug(&mut self, debug: bool) { self.debug = debug; @@ -250,6 +262,9 @@ impl Interpreter { println!(" ║"); } } + if 32 % 4 != 0 { + println!("║"); + } println!("╟──────────────────────────────────────────────────────────────────╢"); println!("║ CPSR FLAGS: ║"); @@ -740,10 +755,9 @@ impl Interpreter { if self.debug { println!("Executing cmp instruction: {}", content); } - let pc = self.pc; let parts: Vec<&str> = content - .split(|c: char| (c == ',' || c.is_whitespace())) + .split(|c: char| c == ',' || c.is_whitespace()) .filter(|s| !s.is_empty()) .collect(); @@ -956,7 +970,9 @@ impl Interpreter { } fn trigger_register_fault(&mut self, register: usize, bit: u32) { let old_val = self.registers[register]; + self.test_report["reg_old_value"] = old_val.into(); self.registers[register] = self.flip_bit(old_val, bit); + self.test_report["reg_new_value"] = self.registers[register].clone().into(); println!("REGISTER FAULT TRIGGERED!"); } @@ -968,14 +984,20 @@ impl Interpreter { } while self.pc < self.eof_pc { let instruction = start_block.get(self.pc as usize).unwrap(); - - if (self.pc as i32) == self.fault_spec.trigger_pc { + if (self.pc as i32) == self.fault_spec.trigger_pc && !self.fault_spec.has_triggered { match self.fault_spec.target { InjectionTarget::Register { register, bit } => { self.trigger_register_fault(register, bit); + self.fault_spec.has_triggered = true; } InjectionTarget::ProgramCounter { bit } => { + self.test_report["pc_old_value"] = self.pc.clone().into(); self.pc = self.flip_bit_u32(self.pc, bit); + self.test_report["pc_new_value"] = self.pc.clone().into(); + let actual_exec_instr = start_block.get(self.pc as usize).unwrap(); + self.test_report["expected_exec_instr"] = instruction.as_str().into(); + self.test_report["actual_exec_instr"] = actual_exec_instr.as_str().into(); + self.fault_spec.has_triggered = true; continue; } _ => panic!("Injection type not implemented yet."), @@ -996,10 +1018,14 @@ impl Interpreter { self.set_pc(self.pc + 1); continue; // Skip the match logic entirely } + match instruction { f if f.starts_with("mov") => self.exec_mov(instruction.clone()), f if f.starts_with("svc") => { if let Some(exit_code) = self.exec_svc(instruction.clone()) { + if self.test_mode { + println!("{}", self.test_report.dump()); + } return (exit_code as u32) & 0xff; } } @@ -1022,6 +1048,9 @@ impl Interpreter { } self.set_pc(self.pc + 1); } + if self.test_mode { + println!("{}", self.test_report.dump()); + } 0 } } diff --git a/interpreter/src/main.rs b/interpreter/src/main.rs index 2c2369d..222ae24 100644 --- a/interpreter/src/main.rs +++ b/interpreter/src/main.rs @@ -16,7 +16,10 @@ struct Args { max_time: Option, #[arg(short, long)] - injection_point: Option + injection_point: Option, + + #[arg(long)] + test_mode: bool } fn main() { @@ -25,7 +28,7 @@ fn main() { let mut interpreter = Interpreter::default(); interpreter.set_debug(args.debug); - + interpreter.set_test_mode(args.test_mode); if let Some(time) = args.max_time { interpreter.set_max_time(time); } diff --git a/minimc b/minimc new file mode 160000 index 0000000..e496b90 --- /dev/null +++ b/minimc @@ -0,0 +1 @@ +Subproject commit e496b903866a93436f561834e375197b68e16511 diff --git a/testing/1-20260313_104334/compiled_test_files/simple.hard.asm b/testing/1-20260313_104334/compiled_test_files/simple.hard.asm deleted file mode 100644 index b540827..0000000 --- a/testing/1-20260313_104334/compiled_test_files/simple.hard.asm +++ /dev/null @@ -1,134 +0,0 @@ -.syntax unified -.thumb - -.section .text -.global _start -.type _start, %function - -_start: - mov r9, #0 - mov r10, #1 - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - sub sp, sp, #4 - mov r0, #1 - str r0, [sp] - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 -while_0: - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - ldr r0, [sp, #4] - mov r1, r0 - mov r0, #10 - cmp r1, r0 - mov r0, #0 - it lt - movlt r0, #1 - cmp r0, #0 - beq end_while_0 - sub sp, sp, #4 - mov r0, #1 - str r0, [sp] - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - ldr r0, [sp, #8] - mov r1, r0 - ldr r0, [sp, #0] - add r0, r1, r0 - str r0, [sp, #8] - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - add sp, sp, #4 - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - b while_0 -end_while_0: - ldr r0, [sp, #4] - mov r1, r0 - mov r0, #10 - cmp r1, r0 - mov r0, #0 - it gt - movgt r0, #1 - cmp r0, #0 - beq else_1 - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - mov r0, #12 - str r0, [sp, #4] - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - add sp, sp, #4 - b endif_1 -else_1: - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - mov r0, #11 - str r0, [sp, #4] - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 -endif_1: - ldr r0, [sp, #0] - mov r1, r0 - mov r0, #1 - cmp r1, r0 - mov r0, #0 - it ne - movne r0, #1 - cmp r0, #0 - beq else_2 - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - ldr r0, [sp, #0] - mov r7, #1 - svc #0 - b endif_2 -else_2: - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - ldr r0, [sp, #4] - mov r7, #1 - svc #0 -endif_2: - add sp, sp, #8 -countermeasure: - mov r0, #77 - mov r7, #1 - svc #0 - -.size _start, .-_start diff --git a/testing/1-20260313_104334/tests/simple.trv b/testing/1-20260313_104334/tests/simple.trv deleted file mode 100644 index 0205385..0000000 --- a/testing/1-20260313_104334/tests/simple.trv +++ /dev/null @@ -1,22 +0,0 @@ -func main() -> Boolean { - let num : Integer = 0; - let test : Boolean = True; - - while num < 10 do { - let etellerandet : Integer = 1; - num = num + etellerandet; - } - - if num > 10 { - num = 12; - let dingdong : Integer = 0; - } else { - num = 11; - } - - if test != True { - return test; - } else { - return num; - } -} diff --git a/testing/1-20260313_104334/tests/simple.trv.output b/testing/1-20260313_104334/tests/simple.trv.output deleted file mode 100644 index b4de394..0000000 --- a/testing/1-20260313_104334/tests/simple.trv.output +++ /dev/null @@ -1 +0,0 @@ -11 diff --git a/testing/2-20260313_125959/compiled_test_files/simple.hard.asm b/testing/2-20260313_125959/compiled_test_files/simple.hard.asm deleted file mode 100644 index b540827..0000000 --- a/testing/2-20260313_125959/compiled_test_files/simple.hard.asm +++ /dev/null @@ -1,134 +0,0 @@ -.syntax unified -.thumb - -.section .text -.global _start -.type _start, %function - -_start: - mov r9, #0 - mov r10, #1 - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - sub sp, sp, #4 - mov r0, #1 - str r0, [sp] - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 -while_0: - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - ldr r0, [sp, #4] - mov r1, r0 - mov r0, #10 - cmp r1, r0 - mov r0, #0 - it lt - movlt r0, #1 - cmp r0, #0 - beq end_while_0 - sub sp, sp, #4 - mov r0, #1 - str r0, [sp] - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - ldr r0, [sp, #8] - mov r1, r0 - ldr r0, [sp, #0] - add r0, r1, r0 - str r0, [sp, #8] - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - add sp, sp, #4 - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - b while_0 -end_while_0: - ldr r0, [sp, #4] - mov r1, r0 - mov r0, #10 - cmp r1, r0 - mov r0, #0 - it gt - movgt r0, #1 - cmp r0, #0 - beq else_1 - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - mov r0, #12 - str r0, [sp, #4] - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - add sp, sp, #4 - b endif_1 -else_1: - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - mov r0, #11 - str r0, [sp, #4] - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 -endif_1: - ldr r0, [sp, #0] - mov r1, r0 - mov r0, #1 - cmp r1, r0 - mov r0, #0 - it ne - movne r0, #1 - cmp r0, #0 - beq else_2 - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - ldr r0, [sp, #0] - mov r7, #1 - svc #0 - b endif_2 -else_2: - add r9, r9, #1 - cmp r9, r10 - bne countermeasure - add r10, r10, #1 - ldr r0, [sp, #4] - mov r7, #1 - svc #0 -endif_2: - add sp, sp, #8 -countermeasure: - mov r0, #77 - mov r7, #1 - svc #0 - -.size _start, .-_start diff --git a/testing/2-20260313_125959/tests/simple.trv b/testing/2-20260313_125959/tests/simple.trv deleted file mode 100644 index 0205385..0000000 --- a/testing/2-20260313_125959/tests/simple.trv +++ /dev/null @@ -1,22 +0,0 @@ -func main() -> Boolean { - let num : Integer = 0; - let test : Boolean = True; - - while num < 10 do { - let etellerandet : Integer = 1; - num = num + etellerandet; - } - - if num > 10 { - num = 12; - let dingdong : Integer = 0; - } else { - num = 11; - } - - if test != True { - return test; - } else { - return num; - } -} diff --git a/testing/2-20260313_125959/tests/simple.trv.output b/testing/2-20260313_125959/tests/simple.trv.output deleted file mode 100644 index b4de394..0000000 --- a/testing/2-20260313_125959/tests/simple.trv.output +++ /dev/null @@ -1 +0,0 @@ -11 diff --git a/testing/compiled_test_files/simple.asm b/testing/compiled_test_files/simple.asm new file mode 100644 index 0000000..60e98bc --- /dev/null +++ b/testing/compiled_test_files/simple.asm @@ -0,0 +1,46 @@ +.syntax unified +.thumb + +.section .text +.global _start +.type _start, %function + +_start: + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] +while_0: + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #10 + cmp r1, r0 + mov r0, #0 + it lt + movlt r0, #1 + cmp r0, #0 + beq end_while_0 + mov r0, #11 + str r0, [sp] + b while_0 +end_while_0: + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #10 + cmp r1, r0 + mov r0, #0 + it gt + movgt r0, #1 + cmp r0, #0 + beq else_1 + mov r0, #12 + str r0, [sp] + b endif_1 +else_1: + mov r0, #11 + str r0, [sp] +endif_1: + ldr r0, [sp, #0] + mov r7, #1 + svc #0 + +.size _start, .-_start diff --git a/testing/compiled_test_files/simple.hard.asm b/testing/compiled_test_files/simple.hard.asm new file mode 100644 index 0000000..60e98bc --- /dev/null +++ b/testing/compiled_test_files/simple.hard.asm @@ -0,0 +1,46 @@ +.syntax unified +.thumb + +.section .text +.global _start +.type _start, %function + +_start: + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] +while_0: + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #10 + cmp r1, r0 + mov r0, #0 + it lt + movlt r0, #1 + cmp r0, #0 + beq end_while_0 + mov r0, #11 + str r0, [sp] + b while_0 +end_while_0: + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #10 + cmp r1, r0 + mov r0, #0 + it gt + movgt r0, #1 + cmp r0, #0 + beq else_1 + mov r0, #12 + str r0, [sp] + b endif_1 +else_1: + mov r0, #11 + str r0, [sp] +endif_1: + ldr r0, [sp, #0] + mov r7, #1 + svc #0 + +.size _start, .-_start diff --git a/testing/compiled_test_files/test_if_else.asm b/testing/compiled_test_files/test_if_else.asm new file mode 100644 index 0000000..9683485 --- /dev/null +++ b/testing/compiled_test_files/test_if_else.asm @@ -0,0 +1,32 @@ +.syntax unified +.thumb + +.section .text +.global _start +.type _start, %function + +_start: + sub sp, sp, #4 + mov r0, #9 + str r0, [sp] + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #10 + cmp r1, r0 + mov r0, #0 + it gt + movgt r0, #1 + cmp r0, #0 + beq else_0 + mov r0, #11 + str r0, [sp] + b endif_0 +else_0: + mov r0, #12 + str r0, [sp] +endif_0: + ldr r0, [sp, #0] + mov r7, #1 + svc #0 + +.size _start, .-_start diff --git a/testing/compiled_test_files/test_if_else.hard.asm b/testing/compiled_test_files/test_if_else.hard.asm new file mode 100644 index 0000000..9683485 --- /dev/null +++ b/testing/compiled_test_files/test_if_else.hard.asm @@ -0,0 +1,32 @@ +.syntax unified +.thumb + +.section .text +.global _start +.type _start, %function + +_start: + sub sp, sp, #4 + mov r0, #9 + str r0, [sp] + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #10 + cmp r1, r0 + mov r0, #0 + it gt + movgt r0, #1 + cmp r0, #0 + beq else_0 + mov r0, #11 + str r0, [sp] + b endif_0 +else_0: + mov r0, #12 + str r0, [sp] +endif_0: + ldr r0, [sp, #0] + mov r7, #1 + svc #0 + +.size _start, .-_start diff --git a/testing/compiled_test_files/test_main_let.asm b/testing/compiled_test_files/test_main_let.asm new file mode 100644 index 0000000..890e947 --- /dev/null +++ b/testing/compiled_test_files/test_main_let.asm @@ -0,0 +1,16 @@ +.syntax unified +.thumb + +.section .text +.global _start +.type _start, %function + +_start: + sub sp, sp, #4 + mov r0, #27 + str r0, [sp] + ldr r0, [sp, #0] + mov r7, #1 + svc #0 + +.size _start, .-_start diff --git a/testing/compiled_test_files/test_main_let.hard.asm b/testing/compiled_test_files/test_main_let.hard.asm new file mode 100644 index 0000000..890e947 --- /dev/null +++ b/testing/compiled_test_files/test_main_let.hard.asm @@ -0,0 +1,16 @@ +.syntax unified +.thumb + +.section .text +.global _start +.type _start, %function + +_start: + sub sp, sp, #4 + mov r0, #27 + str r0, [sp] + ldr r0, [sp, #0] + mov r7, #1 + svc #0 + +.size _start, .-_start diff --git a/testing/compiled_test_files/test_main_return.asm b/testing/compiled_test_files/test_main_return.asm new file mode 100644 index 0000000..01167be --- /dev/null +++ b/testing/compiled_test_files/test_main_return.asm @@ -0,0 +1,13 @@ +.syntax unified +.thumb + +.section .text +.global _start +.type _start, %function + +_start: + mov r0, #69 + mov r7, #1 + svc #0 + +.size _start, .-_start diff --git a/testing/compiled_test_files/test_main_return.hard.asm b/testing/compiled_test_files/test_main_return.hard.asm new file mode 100644 index 0000000..01167be --- /dev/null +++ b/testing/compiled_test_files/test_main_return.hard.asm @@ -0,0 +1,13 @@ +.syntax unified +.thumb + +.section .text +.global _start +.type _start, %function + +_start: + mov r0, #69 + mov r7, #1 + svc #0 + +.size _start, .-_start diff --git a/testing/compiled_test_files/test_while.asm b/testing/compiled_test_files/test_while.asm new file mode 100644 index 0000000..af133c7 --- /dev/null +++ b/testing/compiled_test_files/test_while.asm @@ -0,0 +1,33 @@ +.syntax unified +.thumb + +.section .text +.global _start +.type _start, %function + +_start: + sub sp, sp, #4 + mov r0, #9 + str r0, [sp] +while_0: + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #12 + cmp r1, r0 + mov r0, #0 + it lt + movlt r0, #1 + cmp r0, #0 + beq end_while_0 + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #1 + add r0, r1, r0 + str r0, [sp] + b while_0 +end_while_0: + ldr r0, [sp, #0] + mov r7, #1 + svc #0 + +.size _start, .-_start diff --git a/testing/compiled_test_files/test_while.hard.asm b/testing/compiled_test_files/test_while.hard.asm new file mode 100644 index 0000000..af133c7 --- /dev/null +++ b/testing/compiled_test_files/test_while.hard.asm @@ -0,0 +1,33 @@ +.syntax unified +.thumb + +.section .text +.global _start +.type _start, %function + +_start: + sub sp, sp, #4 + mov r0, #9 + str r0, [sp] +while_0: + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #12 + cmp r1, r0 + mov r0, #0 + it lt + movlt r0, #1 + cmp r0, #0 + beq end_while_0 + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #1 + add r0, r1, r0 + str r0, [sp] + b while_0 +end_while_0: + ldr r0, [sp, #0] + mov r7, #1 + svc #0 + +.size _start, .-_start diff --git a/testing/compiled_test_files/test_while_nested.asm b/testing/compiled_test_files/test_while_nested.asm new file mode 100644 index 0000000..e8ede92 --- /dev/null +++ b/testing/compiled_test_files/test_while_nested.asm @@ -0,0 +1,54 @@ +.syntax unified +.thumb + +.section .text +.global _start +.type _start, %function + +_start: + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] +while_0: + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #3 + cmp r1, r0 + mov r0, #0 + it lt + movlt r0, #1 + cmp r0, #0 + beq end_while_0 + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] +while_1: + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #2 + cmp r1, r0 + mov r0, #0 + it lt + movlt r0, #1 + cmp r0, #0 + beq end_while_1 + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #1 + add r0, r1, r0 + str r0, [sp] + b while_1 +end_while_1: + ldr r0, [sp, #4] + mov r1, r0 + mov r0, #1 + add r0, r1, r0 + str r0, [sp, #4] + add sp, sp, #4 + b while_0 +end_while_0: + ldr r0, [sp, #0] + mov r7, #1 + svc #0 + +.size _start, .-_start diff --git a/testing/compiled_test_files/test_while_nested.hard.asm b/testing/compiled_test_files/test_while_nested.hard.asm new file mode 100644 index 0000000..e8ede92 --- /dev/null +++ b/testing/compiled_test_files/test_while_nested.hard.asm @@ -0,0 +1,54 @@ +.syntax unified +.thumb + +.section .text +.global _start +.type _start, %function + +_start: + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] +while_0: + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #3 + cmp r1, r0 + mov r0, #0 + it lt + movlt r0, #1 + cmp r0, #0 + beq end_while_0 + sub sp, sp, #4 + mov r0, #0 + str r0, [sp] +while_1: + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #2 + cmp r1, r0 + mov r0, #0 + it lt + movlt r0, #1 + cmp r0, #0 + beq end_while_1 + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #1 + add r0, r1, r0 + str r0, [sp] + b while_1 +end_while_1: + ldr r0, [sp, #4] + mov r1, r0 + mov r0, #1 + add r0, r1, r0 + str r0, [sp, #4] + add sp, sp, #4 + b while_0 +end_while_0: + ldr r0, [sp, #0] + mov r7, #1 + svc #0 + +.size _start, .-_start diff --git a/testing/compiled_test_files/test_while_simple.asm b/testing/compiled_test_files/test_while_simple.asm new file mode 100644 index 0000000..af133c7 --- /dev/null +++ b/testing/compiled_test_files/test_while_simple.asm @@ -0,0 +1,33 @@ +.syntax unified +.thumb + +.section .text +.global _start +.type _start, %function + +_start: + sub sp, sp, #4 + mov r0, #9 + str r0, [sp] +while_0: + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #12 + cmp r1, r0 + mov r0, #0 + it lt + movlt r0, #1 + cmp r0, #0 + beq end_while_0 + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #1 + add r0, r1, r0 + str r0, [sp] + b while_0 +end_while_0: + ldr r0, [sp, #0] + mov r7, #1 + svc #0 + +.size _start, .-_start diff --git a/testing/compiled_test_files/test_while_simple.hard.asm b/testing/compiled_test_files/test_while_simple.hard.asm new file mode 100644 index 0000000..af133c7 --- /dev/null +++ b/testing/compiled_test_files/test_while_simple.hard.asm @@ -0,0 +1,33 @@ +.syntax unified +.thumb + +.section .text +.global _start +.type _start, %function + +_start: + sub sp, sp, #4 + mov r0, #9 + str r0, [sp] +while_0: + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #12 + cmp r1, r0 + mov r0, #0 + it lt + movlt r0, #1 + cmp r0, #0 + beq end_while_0 + ldr r0, [sp, #0] + mov r1, r0 + mov r0, #1 + add r0, r1, r0 + str r0, [sp] + b while_0 +end_while_0: + ldr r0, [sp, #0] + mov r7, #1 + svc #0 + +.size _start, .-_start diff --git a/testing/2-20260313_125959/compiled_test_files/simple.asm b/testing/compiled_test_files/test_while_two_loops.asm similarity index 59% rename from testing/2-20260313_125959/compiled_test_files/simple.asm rename to testing/compiled_test_files/test_while_two_loops.asm index 7116286..18d6895 100644 --- a/testing/2-20260313_125959/compiled_test_files/simple.asm +++ b/testing/compiled_test_files/test_while_two_loops.asm @@ -10,67 +10,47 @@ _start: mov r0, #0 str r0, [sp] sub sp, sp, #4 - mov r0, #1 + mov r0, #0 str r0, [sp] while_0: ldr r0, [sp, #4] mov r1, r0 - mov r0, #10 + mov r0, #3 cmp r1, r0 mov r0, #0 it lt movlt r0, #1 cmp r0, #0 beq end_while_0 - sub sp, sp, #4 - mov r0, #1 - str r0, [sp] - ldr r0, [sp, #8] + ldr r0, [sp, #4] mov r1, r0 - ldr r0, [sp, #0] + mov r0, #1 add r0, r1, r0 - str r0, [sp, #8] - add sp, sp, #4 + str r0, [sp, #4] b while_0 end_while_0: - ldr r0, [sp, #4] +while_1: + ldr r0, [sp, #0] mov r1, r0 - mov r0, #10 + mov r0, #4 cmp r1, r0 mov r0, #0 - it gt - movgt r0, #1 + it lt + movlt r0, #1 cmp r0, #0 - beq else_1 - mov r0, #12 - str r0, [sp, #4] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - add sp, sp, #4 - b endif_1 -else_1: - mov r0, #11 - str r0, [sp, #4] -endif_1: + beq end_while_1 ldr r0, [sp, #0] mov r1, r0 mov r0, #1 - cmp r1, r0 - mov r0, #0 - it ne - movne r0, #1 - cmp r0, #0 - beq else_2 - ldr r0, [sp, #0] - mov r7, #1 - svc #0 - b endif_2 -else_2: + add r0, r1, r0 + str r0, [sp] + b while_1 +end_while_1: ldr r0, [sp, #4] + mov r1, r0 + ldr r0, [sp, #0] + add r0, r1, r0 mov r7, #1 svc #0 -endif_2: - add sp, sp, #8 .size _start, .-_start diff --git a/testing/1-20260313_104334/compiled_test_files/simple.asm b/testing/compiled_test_files/test_while_two_loops.hard.asm similarity index 59% rename from testing/1-20260313_104334/compiled_test_files/simple.asm rename to testing/compiled_test_files/test_while_two_loops.hard.asm index 7116286..18d6895 100644 --- a/testing/1-20260313_104334/compiled_test_files/simple.asm +++ b/testing/compiled_test_files/test_while_two_loops.hard.asm @@ -10,67 +10,47 @@ _start: mov r0, #0 str r0, [sp] sub sp, sp, #4 - mov r0, #1 + mov r0, #0 str r0, [sp] while_0: ldr r0, [sp, #4] mov r1, r0 - mov r0, #10 + mov r0, #3 cmp r1, r0 mov r0, #0 it lt movlt r0, #1 cmp r0, #0 beq end_while_0 - sub sp, sp, #4 - mov r0, #1 - str r0, [sp] - ldr r0, [sp, #8] + ldr r0, [sp, #4] mov r1, r0 - ldr r0, [sp, #0] + mov r0, #1 add r0, r1, r0 - str r0, [sp, #8] - add sp, sp, #4 + str r0, [sp, #4] b while_0 end_while_0: - ldr r0, [sp, #4] +while_1: + ldr r0, [sp, #0] mov r1, r0 - mov r0, #10 + mov r0, #4 cmp r1, r0 mov r0, #0 - it gt - movgt r0, #1 + it lt + movlt r0, #1 cmp r0, #0 - beq else_1 - mov r0, #12 - str r0, [sp, #4] - sub sp, sp, #4 - mov r0, #0 - str r0, [sp] - add sp, sp, #4 - b endif_1 -else_1: - mov r0, #11 - str r0, [sp, #4] -endif_1: + beq end_while_1 ldr r0, [sp, #0] mov r1, r0 mov r0, #1 - cmp r1, r0 - mov r0, #0 - it ne - movne r0, #1 - cmp r0, #0 - beq else_2 - ldr r0, [sp, #0] - mov r7, #1 - svc #0 - b endif_2 -else_2: + add r0, r1, r0 + str r0, [sp] + b while_1 +end_while_1: ldr r0, [sp, #4] + mov r1, r0 + ldr r0, [sp, #0] + add r0, r1, r0 mov r7, #1 svc #0 -endif_2: - add sp, sp, #8 .size _start, .-_start diff --git a/testing/config.toml b/testing/config.toml index 77f1099..0c776a1 100644 --- a/testing/config.toml +++ b/testing/config.toml @@ -1,3 +1,16 @@ -tests_folder = "tests" +test_folder = "fissc" +modeled_registers = [ + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12" +] +[pass_mode] +default = "stdout" + +[pass_mode.returncode] +expected = 0 + +[pass_mode.stdout] +expected_pass = "g_authenticated: 0" +expected_fail = "g_authenticated: 1" diff --git a/testing/fissc/disabled/crt-rsa.trv b/testing/fissc/disabled/crt-rsa.trv new file mode 100644 index 0000000..62fc913 --- /dev/null +++ b/testing/fissc/disabled/crt-rsa.trv @@ -0,0 +1,121 @@ +func main() -> Integer { + let g_countermeasure : Integer = 0; + let g_N : Integer = 11413; + let g_e : Integer = 3533; + let g_p : Integer = 101; + let g_q : Integer = 113; + let g_iq : Integer = 59; + let g_dp : Integer = 97; + let g_dq : Integer = 101; + let g_sign : Integer = -1; + let g_M : Integer = 23; + + let Cp : Integer = 0; + let Cq : Integer = 0; + let tmp : Integer = 0; + + let a : Integer = 0; + let b : Integer = 0; + let n : Integer = 0; + let r : Integer = 0; + + let mul_r : Integer = 0; + let mul_a : Integer = 0; + let mul_b : Integer = 0; + let mul_n : Integer = 0; + let mul_tmp : Integer = 0; + + let pow_a : Integer = 0; + let pow_tmp : Integer = 0; + let pow_b : Integer = 0; + let pow_n : Integer = 0; + + a = g_M; + b = g_dp; + n = g_p; + r = 1; + pow_b = 0; + while pow_b < b { + mul_a = r; + mul_b = a; + mul_n = n; + mul_tmp = 0; + while mul_b > 0 { + mul_tmp = mul_tmp + mul_a; + while mul_tmp > mul_n { + mul_tmp = mul_tmp - mul_n; + } + while mul_tmp < 0 { + mul_tmp = mul_tmp + mul_n; + } + if mul_tmp == mul_n { + mul_tmp = 0; + } + mul_b = mul_b - 1; + } + r = mul_tmp; + pow_b = pow_b + 1; + } + Cp = r; + + a = g_M; + b = g_dq; + n = g_q; + r = 1; + pow_b = 0; + while pow_b < b { + mul_a = r; + mul_b = a; + mul_n = n; + mul_tmp = 0; + while mul_b > 0 { + mul_tmp = mul_tmp + mul_a; + while mul_tmp > mul_n { + mul_tmp = mul_tmp - mul_n; + } + while mul_tmp < 0 { + mul_tmp = mul_tmp + mul_n; + } + if mul_tmp == mul_n { + mul_tmp = 0; + } + mul_b = mul_b - 1; + } + r = mul_tmp; + pow_b = pow_b + 1; + } + Cq = r; + + tmp = Cp - Cq; + + mul_a = tmp; + mul_b = g_iq; + mul_n = g_p; + mul_tmp = 0; + while mul_b > 0 { + mul_tmp = mul_tmp + mul_a; + while mul_tmp > mul_n { + mul_tmp = mul_tmp - mul_n; + } + while mul_tmp < 0 { + mul_tmp = mul_tmp + mul_n; + } + if mul_tmp == mul_n { + mul_tmp = 0; + } + mul_b = mul_b - 1; + } + tmp = mul_tmp; + + tmp = tmp * g_q; + + tmp = tmp + Cq; + + g_sign = tmp; + + print("g_sign = ", g_sign); + + print("g_countermeasure: ", g_countermeasure); + + return g_sign; +} diff --git a/testing/fissc/disabled/crt-rsa.trv.output b/testing/fissc/disabled/crt-rsa.trv.output new file mode 100644 index 0000000..cfeff4a --- /dev/null +++ b/testing/fissc/disabled/crt-rsa.trv.output @@ -0,0 +1 @@ +11254 diff --git a/testing/fissc/verifypin.trv b/testing/fissc/verifypin.trv new file mode 100644 index 0000000..e432608 --- /dev/null +++ b/testing/fissc/verifypin.trv @@ -0,0 +1,44 @@ +func main() -> Integer { + let ptc : Integer = 3; + let authenticated : Integer = 0; + let cardPin1 : Integer = 1; + let cardPin2 : Integer = 2; + let cardPin3 : Integer = 3; + let cardPin4 : Integer = 4; + let userPin1 : Integer = 0; + let userPin2 : Integer = 0; + let userPin3 : Integer = 0; + let userPin4 : Integer = 0; + + authenticated = 0; + + if ptc > 0 then { + let pinsEqual : Integer = 1; + if userPin1 != cardPin1 then { + pinsEqual = 0; + } + + if userPin2 != cardPin2 then { + pinsEqual = 0; + } + + if userPin3 != cardPin3 then { + pinsEqual = 0; + } + + if userPin4 != cardPin4 then { + pinsEqual = 0; + } + + if pinsEqual == 1 then { + ptc = 3; + authenticated = 1; + } else { + ptc = ptc - 1; + } + } + print("g_authenticated: ", authenticated); + print("g_ptc: ", ptc); + + return authenticated; +} diff --git a/testing/fissc/verifypin.trv.output b/testing/fissc/verifypin.trv.output new file mode 100644 index 0000000..4eda5e0 --- /dev/null +++ b/testing/fissc/verifypin.trv.output @@ -0,0 +1,3 @@ +g_countermeasure: 0 +g_authenticated: 0 +g_ptc: 2 diff --git a/testing/requirements.txt b/testing/requirements.txt index bd79a65..90df715 100644 --- a/testing/requirements.txt +++ b/testing/requirements.txt @@ -1 +1,2 @@ toml +tqdm \ No newline at end of file diff --git a/testing/src/database.py b/testing/src/database.py new file mode 100644 index 0000000..aa76f6e --- /dev/null +++ b/testing/src/database.py @@ -0,0 +1,143 @@ +import json +import sqlite3 +from datetime import datetime + + +class ResultsDatabase: + SCHEMA = """ + CREATE TABLE IF NOT EXISTS runs ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + run_number INTEGER NOT NULL, + timestamp TEXT NOT NULL, + tests_folder TEXT, + created_at TEXT DEFAULT CURRENT_TIMESTAMP + ); + + CREATE TABLE IF NOT EXISTS test_results ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + run_id INTEGER NOT NULL, + test TEXT NOT NULL, + variant TEXT NOT NULL, + injection_point TEXT NOT NULL, + fault_type TEXT, + fault_pc INTEGER, + fault_reg INTEGER, + fault_bit INTEGER, + returncode INTEGER NOT NULL, + pc_before INTEGER, + pc_after INTEGER, + expected_exec_instr TEXT, + actual_exec_instr TEXT, + reg_old_value INTEGER, + reg_new_value INTEGER, + stdout TEXT, + stderr TEXT, + expected_output TEXT NOT NULL, + matched_output_line TEXT, + passed INTEGER NOT NULL, + FOREIGN KEY (run_id) REFERENCES runs(id) + ); + + CREATE INDEX IF NOT EXISTS idx_test_results_run_id ON test_results(run_id); + CREATE INDEX IF NOT EXISTS idx_test_results_test ON test_results(test); + CREATE INDEX IF NOT EXISTS idx_test_results_variant ON test_results(variant); + CREATE INDEX IF NOT EXISTS idx_test_results_passed ON test_results(passed); + """ + + def __init__(self, db_path): + self.db_path = db_path + self._conn = None + self._init_db() + + def _init_db(self): + self._conn = sqlite3.connect(self.db_path) + self._conn.executescript(self.SCHEMA) + self._conn.commit() + + def close(self): + if self._conn: + self._conn.close() + self._conn = None + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.close() + + def create_run(self, run_number, tests_folder=None): + timestamp = datetime.now().isoformat() + cursor = self._conn.execute( + "INSERT INTO runs (run_number, timestamp, tests_folder) VALUES (?, ?, ?)", + (run_number, timestamp, tests_folder), + ) + self._conn.commit() + return cursor.lastrowid + + def insert_results_batch(self, run_id, results): + rows = [] + for res in results: + parts = res["injection_point"].split(":") + if parts[0] == "pc": + fault_type, fault_pc, fault_reg, fault_bit = ("pc", int(parts[1]), None, int(parts[2])) + elif parts[0] == "reg": + fault_type, fault_pc, fault_reg, fault_bit = ("reg", int(parts[1]), int(parts[2]), int(parts[3])) + else: + fault_type, fault_pc, fault_reg, fault_bit = (None, None, None, None) + test_report = json.loads(res["test_report"]) + pc_before = test_report.get("pc_old_value", None) + pc_new = test_report.get("pc_new_value", None) + expected_exec_instr = test_report.get("expected_exec_instr", "N/A") + actual_exec_instr = test_report.get("actual_exec_instr", "N/A") + reg_old_value = test_report.get("reg_old_value", None) + reg_new_value = test_report.get("reg_new_value", None) + + def _clamp_int(val, max_val=2**63 - 1, min_val=-(2**63)): + if val is None: + return None + try: + int_val = int(val) + except (ValueError, TypeError): + return None + if int_val > max_val or int_val < min_val: + return str(int_val) + return int_val + + pc_before = _clamp_int(pc_before) + pc_new = _clamp_int(pc_new) + reg_old_value = _clamp_int(reg_old_value) + reg_new_value = _clamp_int(reg_new_value) + + rows.append(( + run_id, + res["test"], + res["variant"], + res["injection_point"], + fault_type, + fault_pc, + fault_reg, + fault_bit, + res["returncode"], + pc_before, + pc_new, + expected_exec_instr, + actual_exec_instr, + reg_old_value, + reg_new_value, + res["stdout"], + res["stderr"], + res["expected_output"], + res.get("matched_output_line"), + int(res["passed"]), + )) + + self._conn.executemany( + """ + INSERT INTO test_results + (run_id, test, variant, injection_point, fault_type, fault_pc, fault_reg, fault_bit, + returncode, pc_before, pc_after, expected_exec_instr, actual_exec_instr, reg_old_value, reg_new_value, stdout, stderr, expected_output, matched_output_line, passed) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """, + rows, + ) + self._conn.commit() diff --git a/testing/src/testrunner.py b/testing/src/testrunner.py index 44fd7e5..a7b4a39 100644 --- a/testing/src/testrunner.py +++ b/testing/src/testrunner.py @@ -1,50 +1,181 @@ import os +import re import sys import subprocess import shutil import toml +import csv from datetime import datetime +import concurrent.futures +import multiprocessing +from tqdm import tqdm +from src.database import ResultsDatabase + + +def _fault_worker(args): + asm_path, injection_point, pass_mode_config = args + + bin_dir = os.path.join(os.path.dirname(__file__), "..", "bin") + interpreter_path = os.path.join(bin_dir, "interpreter") + + cmd = [interpreter_path, asm_path, "--injection-point", injection_point, "--test-mode"] + + result = subprocess.run(cmd, cwd=bin_dir, capture_output=True, text=True) + + passed = _check_passed(result, pass_mode_config) + + matched_output_line = None + if pass_mode_config.get("mode") == "stdout": + expected_pass = pass_mode_config.get("expected_pass", "") + expected_fail = pass_mode_config.get("expected_fail", "") + + stdout_lines = result.stdout.strip().split("\n") + + if passed and expected_pass: + for line in stdout_lines: + if expected_pass in line: + matched_output_line = line.strip() + break + elif not passed and expected_fail: + for line in stdout_lines: + if expected_fail in line: + matched_output_line = line.strip() + break + + if matched_output_line is None: + matched_output_line = "N/A" + return { + "injection_point": injection_point, + "returncode": result.returncode, + "stdout": result.stdout.strip(), + "stderr": result.stderr.strip(), + "expected_output": pass_mode_config.get("expected_pass", ""), + "matched_output_line": matched_output_line, + "passed": passed, + "test_report": _extract_test_report(result.stdout), + } + +def _extract_test_report(stdout: str): + keyword = '"title":\s*"test_report"' + pattern = rf'\{{[^{{}}]*{keyword}[^{{}}]*\}}' + match = re.search(pattern, stdout,flags=re.MULTILINE) + if match: + return match.group(0) + return '{"title": "test_report"}' + +def _check_passed(result, pass_mode_config): + mode = pass_mode_config.get("mode", "returncode") + expected_pass = pass_mode_config.get("expected_pass", None) + expected_fail = pass_mode_config.get("expected_fail", None) + + if mode == "returncode": + return result.returncode == 0 + elif mode == "stdout": + if expected_pass and expected_pass in result.stdout: + return True + elif expected_fail and expected_fail in result.stdout and result.returncode == 1: + return False + return True + else: + raise ValueError(f"Unknown pass mode: {mode}") + class TestRunner: def __init__(self, config_path=None): if config_path is None: config_path = os.path.join(os.path.dirname(__file__), "..", "config.toml") - - with open(config_path, 'r') as f: + + with open(config_path, "r") as f: config = toml.load(f) - + self.base_dir = os.path.join(os.path.dirname(__file__), "..") - self.tests_folder = os.path.join(self.base_dir, config.get('tests_folder', 'tests')) + self.tests_folder = os.path.join( + self.base_dir, config.get("test_folder", "fissc") + ) self.artifacts_folder = os.path.join(self.base_dir, "artifacts") + self.modeled_registers = config.get( + "modeled_registers", + [ + "r0", + "r1", + "r2", + "r3", + "r4", + "r5", + "r6", + "r7", + "r8", + "r9", + "r10", + "r11", + "r12", + ], + ) + self.default_pass_mode = config.get("pass_mode", {}).get("default", "returncode") + self.pass_mode_configs = config.get("pass_mode", {}) self.tests = self._discover_tests() - + self.compile_results = None + def _discover_tests(self): tests = [] if not os.path.exists(self.tests_folder): return tests - + files = os.listdir(self.tests_folder) - trv_files = sorted([f for f in files if f.endswith('.trv')]) - + trv_files = sorted([f for f in files if f.endswith(".trv")]) + for trv_file in trv_files: test_name = trv_file[:-4] output_file = trv_file + ".output" - - if output_file in files: - trv_path = os.path.join(self.tests_folder, trv_file) - output_path = os.path.join(self.tests_folder, output_file) - - with open(output_path, 'r') as f: - expected_output = f.read().strip() - - tests.append({ - 'name': test_name, - 'path': trv_path, - 'expected_output': expected_output - }) - + toml_file = trv_file + ".toml" + + if output_file not in files: + continue + + trv_path = os.path.join(self.tests_folder, trv_file) + output_path = os.path.join(self.tests_folder, output_file) + + with open(output_path, "r") as f: + expected_output = f.read().strip() + + pass_mode_config = self._load_pass_mode_config(test_name, trv_file, files) + + tests.append( + { + "name": test_name, + "path": trv_path, + "expected_output": expected_output, + "pass_mode": pass_mode_config, + } + ) + return tests - + + def _load_pass_mode_config(self, test_name, trv_file, files): + toml_file = trv_file + ".toml" + + if toml_file in files: + toml_path = os.path.join(self.tests_folder, toml_file) + with open(toml_path, "r") as f: + test_config = toml.load(f) + pass_mode = test_config.get("pass_mode", {}) + if "mode" in pass_mode: + mode = pass_mode["mode"] + mode_config = self.pass_mode_configs.get(mode, {}) + return { + "mode": mode, + "expected_pass": pass_mode.get("expected_pass", mode_config.get("expected_pass", 0)), + "expected_fail": pass_mode.get("expected_fail", mode_config.get("expected_fail", None)), + } + + mode = self.default_pass_mode + mode_config = self.pass_mode_configs.get(mode, {}) + return { + "mode": mode, + "expected_pass": mode_config.get("expected_pass", 0), + "expected_fail": mode_config.get("expected_fail", None), + } + def check_bin(self): from pathlib import Path @@ -72,39 +203,61 @@ def check_bin(self): ) def compile_test(self, test, hard, compiled_folder): - trv_path = test['path'] - test_name = test['name'] - + trv_path = test["path"] + test_name = test["name"] + if hard: asm_path = os.path.join(compiled_folder, f"{test_name}.hard.asm") else: asm_path = os.path.join(compiled_folder, f"{test_name}.asm") - + compiler_dir = os.path.join(os.path.dirname(__file__), "..", "bin") - + cmd = [os.path.join(compiler_dir, "compiler"), trv_path, "-o", asm_path] if hard: cmd.append("--hard") - + result = subprocess.run(cmd, cwd=compiler_dir, capture_output=True, text=True) return result.returncode == 0, asm_path, result.stdout, result.stderr - + + def interpret_test(self, asm_path, injection_point=None, debug=False): + bin_dir = os.path.join(os.path.dirname(__file__), "..", "bin") + interpreter_path = os.path.join(bin_dir, "interpreter") + + cmd = [interpreter_path, asm_path] + + if debug: + cmd.append("--debug") + + if injection_point: + cmd.extend(["--injection-point", injection_point]) + + result = subprocess.run(cmd, cwd=bin_dir, capture_output=True, text=True) + + return { + "returncode": result.returncode, + "stdout": result.stdout.strip(), + "stderr": result.stderr.strip(), + } + def list_tests(self): return self.tests - + def _get_next_run_number(self): if not os.path.exists(self.artifacts_folder): return 1 - + max_num = 0 for item in os.listdir(self.artifacts_folder): - base_name = item[:-4] if item.endswith('.zip') else item - if os.path.isdir(os.path.join(self.artifacts_folder, item)) or item.endswith('.zip'): - parts = base_name.split('-', 1) + base_name = item[:-4] if item.endswith(".zip") else item + if os.path.isdir( + os.path.join(self.artifacts_folder, item) + ) or item.endswith(".zip"): + parts = base_name.split("-", 1) if len(parts) == 2 and parts[0].isdigit(): max_num = max(max_num, int(parts[0])) return max_num + 1 - + def setup(self): timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") run_num = self._get_next_run_number() @@ -112,44 +265,195 @@ def setup(self): self.run_folder = os.path.join(self.artifacts_folder, self.run_folder_name) self.run_tests_folder = os.path.join(self.run_folder, "tests") self.compiled_folder = os.path.join(self.run_folder, "compiled_test_files") - + self.db_path = os.path.join(self.run_folder, "results.db") + os.makedirs(self.run_folder, exist_ok=True) os.makedirs(self.run_tests_folder, exist_ok=True) os.makedirs(self.compiled_folder, exist_ok=True) - + for f in os.listdir(self.tests_folder): - if f.endswith('.trv') or f.endswith('.trv.output'): + if f.endswith(".trv") or f.endswith(".trv.output"): shutil.copy(os.path.join(self.tests_folder, f), self.run_tests_folder) - + + self.db = ResultsDatabase(self.db_path) + self.run_id = self.db.create_run(run_num, self.tests_folder) + return self.run_folder - + + def _get_program_max_pc(self, asm_path): + with open(asm_path, "r") as f: + lines = f.readlines() + + in_start = False + instruction_count = 0 + + for raw_line in lines: + line = raw_line.strip() + + if not line: + continue + + # remove comments + if ";" in line: + line = line.split(";", 1)[0].strip() + if "//" in line: + line = line.split("//", 1)[0].strip() + + if not line: + continue + + if not in_start: + if line == "_start:": + in_start = True + continue + + # skip labels after _start + if line.endswith(":"): + continue + + if line.startswith("."): + continue + + # count everything else as an instruction + instruction_count += 1 + + return instruction_count + + def _generate_injection_points(self, asm_path): + max_pc = self._get_program_max_pc(asm_path) + injection_points = [] + + # pc faults: pc:: + for pc in range(1, max_pc): + for bit in range( + 0, 31 + ): # TODO: Find ud af om den skal hedde 33 eller 32, ændrede til 32 selvom chatten mente 33 + injection_points.append(f"pc:{pc}:{bit}") + + # reg faults: reg::: + for pc in range(1, max_pc): + for reg in range(13): + for bit in range(0, 31): + injection_points.append(f"reg:{pc}:{reg}:{bit}") + + return injection_points + + def _run_fault_campaign(self, test_name, variant, asm_path, pass_mode_config, limit=None): + injection_points = self._generate_injection_points(asm_path) + + if limit is not None and len(injection_points) > limit: + injection_points = injection_points[:limit] + print(f" Limited to {limit} injection points") + + cpu_count = multiprocessing.cpu_count() + print(f" Using {cpu_count} workers") + + results = [] + + tasks = [ + (asm_path, injection_point, pass_mode_config) + for injection_point in injection_points + ] + + with concurrent.futures.ProcessPoolExecutor(max_workers=cpu_count) as executor: + for res in tqdm( + executor.map(_fault_worker, tasks, chunksize=50), + total=len(tasks), + desc="Fault Injection", + ): + res["test"] = test_name + res["variant"] = variant + results.append(res) + + return results + def compile(self): results = [] for test in self.tests: - test_result = {'name': test['name'], 'normal': None, 'hard': None} - + test_result = {"name": test["name"], "normal": None, "hard": None} + for hard in [False, True]: hard_str = "hard" if hard else "normal" - success, asm_path, stdout, stderr = self.compile_test(test, hard, self.compiled_folder) - test_result[hard_str] = {'success': success, 'asm_path': asm_path, 'stdout': stdout, 'stderr': stderr} - + success, asm_path, stdout, stderr = self.compile_test( + test, hard, self.compiled_folder + ) + test_result[hard_str] = { + "success": success, + "asm_path": asm_path, + "stdout": stdout, + "stderr": stderr, + } + results.append(test_result) - + self.compile_results = results return results - - def run_tests(self): - + def run_tests(self, limit=None, run_variants="both"): + if not hasattr(self, "run_folder"): + self.setup() + + if self.compile_results is None: + self.compile() + + all_fault_results = [] + + if run_variants == "normal": + variants = [False] + elif run_variants == "hard": + variants = [True] + else: + variants = [False, True] + compile_results = self.compile_results or [] + + for test, result in zip(self.tests, compile_results): + print(f"Test: {test['name']}") + + for hard in variants: + hard_str = "hard" if hard else "normal" + res = result[hard_str] + + if not res["success"]: + print(f" Compilation failed ({hard_str})") + if res["stdout"]: + print(f" stdout: {res['stdout']}") + if res["stderr"]: + print(f" stderr: {res['stderr']}") + continue + + asm_path = res["asm_path"] + max_pc = self._get_program_max_pc(asm_path) + injection_points = self._generate_injection_points(asm_path) + + print(f" Compiled ({hard_str}) successfully") + print(f" ASM path: {asm_path}") + print(f" Max PC: {max_pc}") + print(f" Fault runs to execute: {len(injection_points)}") + + fault_results = self._run_fault_campaign( + test_name=test["name"], + variant=hard_str, + asm_path=asm_path, + pass_mode_config=test["pass_mode"], + limit=limit, + ) + + all_fault_results.extend(fault_results) + + self.db.insert_results_batch(self.run_id, all_fault_results) + self.db.close() + zip_base = os.path.join(self.artifacts_folder, self.run_folder_name) - shutil.make_archive(zip_base, 'zip', self.artifacts_folder, self.run_folder_name) + shutil.make_archive( + zip_base, "zip", self.artifacts_folder, self.run_folder_name + ) shutil.rmtree(self.run_folder) - + print(f"\nArtifacts saved to: {zip_base}.zip") if __name__ == "__main__": runner = TestRunner() - + print(f"Running test runner") print(f"Found {len(runner.tests)} tests") runner.run_tests() diff --git a/testing/test b/testing/test index 65aae71..7c39202 100755 --- a/testing/test +++ b/testing/test @@ -8,8 +8,22 @@ def main(): parser = argparse.ArgumentParser() parser.add_argument('--config', type=str, default=None, help='Path to config.toml') parser.add_argument('--skip-run', action='store_true', help='Only setup and compile, skip running tests') + parser.add_argument('--limit', type=int, default=None, help='Limit number of injection points to test') + parser.add_argument('--nohard', action='store_true', help='Skip hardened version when running tests') + parser.add_argument('--hard', action='store_true', help='Only run hardened version') args = parser.parse_args() + if args.nohard and args.hard: + print("Error: Cannot use both --nohard and --hard") + return + + if args.hard: + run_variants = "hard" + elif args.nohard: + run_variants = "normal" + else: + run_variants = "both" + runner = TestRunner(config_path=args.config) # check that the compiler and interpreter is present: runner.check_bin() @@ -25,7 +39,7 @@ def main(): if not args.skip_run: print(f"\nRunning tests...") - runner.run_tests() + runner.run_tests(limit=args.limit, run_variants=run_variants) else: print(f"\nSkipping test run (--skip-run)") diff --git a/testing/tests/simple.trv.output b/testing/tests/simple.trv.output index b4de394..48082f7 100644 --- a/testing/tests/simple.trv.output +++ b/testing/tests/simple.trv.output @@ -1 +1 @@ -11 +12 diff --git a/testing/tests/test_if_else.trv b/testing/tests/test_if_else.trv new file mode 100644 index 0000000..3b984ea --- /dev/null +++ b/testing/tests/test_if_else.trv @@ -0,0 +1,9 @@ +func main() -> Integer { + let num : Integer = 9; + if num > 10 { + num = 11; + } else { + num = 12; + } + return num; +} diff --git a/testing/tests/test_if_else.trv.output b/testing/tests/test_if_else.trv.output new file mode 100644 index 0000000..48082f7 --- /dev/null +++ b/testing/tests/test_if_else.trv.output @@ -0,0 +1 @@ +12 diff --git a/testing/tests/test_main_let.trv b/testing/tests/test_main_let.trv new file mode 100644 index 0000000..fdc57cb --- /dev/null +++ b/testing/tests/test_main_let.trv @@ -0,0 +1,4 @@ +func main() -> Integer { + let num : Integer = 27; + return num; +} diff --git a/testing/tests/test_main_let.trv.output b/testing/tests/test_main_let.trv.output new file mode 100644 index 0000000..f64f5d8 --- /dev/null +++ b/testing/tests/test_main_let.trv.output @@ -0,0 +1 @@ +27 diff --git a/testing/tests/test_main_return.trv b/testing/tests/test_main_return.trv new file mode 100644 index 0000000..c66bbb3 --- /dev/null +++ b/testing/tests/test_main_return.trv @@ -0,0 +1,3 @@ +func main() -> Integer { + return 69; +} diff --git a/testing/tests/test_main_return.trv.output b/testing/tests/test_main_return.trv.output new file mode 100644 index 0000000..b5489e5 --- /dev/null +++ b/testing/tests/test_main_return.trv.output @@ -0,0 +1 @@ +69 diff --git a/testing/tests/test_while.trv b/testing/tests/test_while.trv new file mode 100644 index 0000000..db54eef --- /dev/null +++ b/testing/tests/test_while.trv @@ -0,0 +1,7 @@ +func main() -> Integer { + let num : Integer = 9; + while num < 12 { + num = num + 1; + } + return num; +} diff --git a/testing/tests/test_while.trv.output b/testing/tests/test_while.trv.output new file mode 100644 index 0000000..48082f7 --- /dev/null +++ b/testing/tests/test_while.trv.output @@ -0,0 +1 @@ +12 diff --git a/testing/tests/test_while_nested.trv b/testing/tests/test_while_nested.trv new file mode 100644 index 0000000..7102f7f --- /dev/null +++ b/testing/tests/test_while_nested.trv @@ -0,0 +1,11 @@ +func main() -> Integer { + let a : Integer = 0; + while a < 3 { + let b : Integer = 0; + while b < 2 { + b = b + 1; + } + a = a + 1; + } + return a; +} diff --git a/testing/tests/test_while_nested.trv.output b/testing/tests/test_while_nested.trv.output new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/testing/tests/test_while_nested.trv.output @@ -0,0 +1 @@ +3 diff --git a/testing/tests/test_while_simple.trv b/testing/tests/test_while_simple.trv new file mode 100644 index 0000000..db54eef --- /dev/null +++ b/testing/tests/test_while_simple.trv @@ -0,0 +1,7 @@ +func main() -> Integer { + let num : Integer = 9; + while num < 12 { + num = num + 1; + } + return num; +} diff --git a/testing/tests/test_while_simple.trv.output b/testing/tests/test_while_simple.trv.output new file mode 100644 index 0000000..48082f7 --- /dev/null +++ b/testing/tests/test_while_simple.trv.output @@ -0,0 +1 @@ +12 diff --git a/testing/tests/test_while_two_loops.trv b/testing/tests/test_while_two_loops.trv new file mode 100644 index 0000000..629c22c --- /dev/null +++ b/testing/tests/test_while_two_loops.trv @@ -0,0 +1,11 @@ +func main() -> Integer { + let a : Integer = 0; + let b : Integer = 0; + while a < 3 { + a = a + 1; + } + while b < 4 { + b = b + 1; + } + return a+b; +} diff --git a/testing/tests/test_while_two_loops.trv.output b/testing/tests/test_while_two_loops.trv.output new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/testing/tests/test_while_two_loops.trv.output @@ -0,0 +1 @@ +7