diff --git a/ledger/src/ui/test/communication/Makefile b/ledger/src/ui/test/communication/Makefile new file mode 100644 index 00000000..d9b3227b --- /dev/null +++ b/ledger/src/ui/test/communication/Makefile @@ -0,0 +1,50 @@ +# The MIT License (MIT) +# +# Copyright (c) 2021 RSK Labs Ltd +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is furnished to do +# so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +SRCDIR = ../../src +MOCKDIR = ../mock +CFLAGS = -I $(SRCDIR) -I $(MOCKDIR) -I ./ + +PROG = test.out +OBJS = os.o communication.o test_communication.o + +all: $(PROG) + +$(PROG): $(OBJS) + $(CC) -o $@ $^ + +test_communication.o: test_communication.c + $(CC) $(CFLAGS) -c -o $@ $^ + +communication.o: $(SRCDIR)/communication.c + $(CC) $(CFLAGS) -c -o $@ $^ + +os.o: $(MOCKDIR)/os.c + $(CC) $(CFLAGS) -c -o $@ $^ + +.PHONY: clean test + +clean: + rm -f $(PROG) ./*.o + +test: all + ./$(PROG) diff --git a/ledger/src/ui/test/communication/test_communication.c b/ledger/src/ui/test/communication/test_communication.c new file mode 100644 index 00000000..5f407dd3 --- /dev/null +++ b/ledger/src/ui/test/communication/test_communication.c @@ -0,0 +1,61 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 RSK Labs Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include "apdu.h" +#include "defs.h" +#include "communication.h" +#include "os.h" + +void test_echo() { + printf("Test echo...\n"); + unsigned int rx = 4; + assert(4 == echo(rx)); +} + +void test_get_mode() { + printf("Test get mode...\n"); + assert(2 == get_mode()); + assert(RSK_MODE_BOOTLOADER == APDU_AT(1)); +} + +void test_get_retries() { + printf("Test get retries...\n"); + reset_mock_func_call_list(); + assert(3 == get_retries()); + assert(0 == APDU_AT(2)); + assert(get_mock_func_call(0) == MOCK_FUNC_OS_GLOBAL_PIN_RETRIES); + assert(get_mock_func_call_count() == 1); +} + +int main() { + test_echo(); + test_get_mode(); + test_get_retries(); +} diff --git a/ledger/src/ui/test/mock/bolos_ux_onboarding_seed_bip39.h b/ledger/src/ui/test/mock/bolos_ux_onboarding_seed_bip39.h new file mode 120000 index 00000000..3cba64e4 --- /dev/null +++ b/ledger/src/ui/test/mock/bolos_ux_onboarding_seed_bip39.h @@ -0,0 +1 @@ +../../src_common/bolos_ux_onboarding_seed_bip39.h \ No newline at end of file diff --git a/ledger/src/ui/test/mock/cx.c b/ledger/src/ui/test/mock/cx.c new file mode 100644 index 00000000..885a985d --- /dev/null +++ b/ledger/src/ui/test/mock/cx.c @@ -0,0 +1,31 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 RSK Labs Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "cx.h" + +unsigned char mock_random_buffer[] = "random-buffer\0"; + +unsigned char *cx_rng(unsigned char *buffer, unsigned int len) { + return mock_random_buffer; +} \ No newline at end of file diff --git a/ledger/src/ui/test/mock/cx.h b/ledger/src/ui/test/mock/cx.h new file mode 100644 index 00000000..8a6b6a38 --- /dev/null +++ b/ledger/src/ui/test/mock/cx.h @@ -0,0 +1,28 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 RSK Labs Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/** + * generate a random buffer + */ +unsigned char *cx_rng(unsigned char *buffer, unsigned int len); \ No newline at end of file diff --git a/ledger/src/ui/test/mock/os.c b/ledger/src/ui/test/mock/os.c index 1590a831..9c6c5c04 100644 --- a/ledger/src/ui/test/mock/os.c +++ b/ledger/src/ui/test/mock/os.c @@ -25,38 +25,116 @@ #include "os.h" #include "string.h" +static mock_func_call_t mock_func_call_list[128]; +static size_t mock_func_call_count = 0; + /** * Mocks pin currently loaded to device */ unsigned char current_pin[10]; /** - * APDU buffer + * Helper functions to handle call list */ -unsigned char G_io_apdu_buffer[IO_APDU_BUFFER_SIZE]; +void reset_mock_func_call_list() { + explicit_bzero(mock_func_call_list, sizeof(mock_func_call_list)); + mock_func_call_count = 0; +} -unsigned int os_global_pin_check(unsigned char *pin_buffer, - unsigned char pin_length) { - return !strncmp( - (const char *)pin_buffer, (const char *)current_pin, pin_length); +void add_mock_func_call(mock_func_call_t func) { + mock_func_call_list[mock_func_call_count++] = func; +} + +mock_func_call_t get_mock_func_call(int order) { + return mock_func_call_list[order]; } +int get_mock_func_call_count() { + return mock_func_call_count; +} + +/** + * APDU buffer + */ +unsigned char G_io_apdu_buffer[IO_APDU_BUFFER_SIZE]; + void explicit_bzero(void *s, size_t len) { memset(s, '\0', len); /* Compiler barrier. */ asm volatile("" ::: "memory"); } +unsigned int os_global_pin_check(unsigned char *pin_buffer, + unsigned char pin_length) { + add_mock_func_call(MOCK_FUNC_OS_GLOBAL_PIN_CHECK); + return !strncmp( + (const char *)pin_buffer, (const char *)current_pin, pin_length); +} + void os_perso_set_pin(unsigned int identity, unsigned char *pin, unsigned int length) { - // Do nothing + add_mock_func_call(MOCK_FUNC_OS_PERSO_SET_PIN); + strncpy((char *)current_pin, (char *)pin, length); } void os_global_pin_invalidate(void) { - // Do nothing + add_mock_func_call(MOCK_FUNC_OS_GLOBAL_PIN_INVALIDATE); +} + +void os_memset(void *dst, unsigned char c, unsigned int length) { + memset(dst, c, length); } void mock_set_pin(unsigned char *pin, size_t n) { memcpy(current_pin, pin, n); +} + +void nvm_write(void *dst_adr, void *src_adr, unsigned int src_len) { + add_mock_func_call(MOCK_FUNC_NVM_WRITE); + if (src_adr == NULL) { + // Treat as memory reset + memset(dst_adr, 0, src_len); + } else { + // Treat as normal copy + memmove(dst_adr, src_adr, src_len); + } +} + +void os_perso_wipe() { + add_mock_func_call(MOCK_FUNC_OS_PERSO_WIPE); +} + +void os_perso_derive_and_set_seed(unsigned char identity, + const char *prefix, + unsigned int prefix_length, + const char *passphrase, + unsigned int passphrase_length, + const char *words, + unsigned int words_length) { + add_mock_func_call(MOCK_FUNC_OS_PERSO_DERIVE_AND_SET_SEED); +} + +void os_perso_finalize(void) { + add_mock_func_call(MOCK_FUNC_OS_PERSO_FINALIZE); +} + +unsigned int os_perso_isonboarded(void) { + add_mock_func_call(MOCK_FUNC_OS_PERSO_ISONBOARDED); + return 1; +} + +unsigned int os_global_pin_retries(void) { + add_mock_func_call(MOCK_FUNC_OS_GLOBAL_PIN_RETRIES); + return 0; +} + +unsigned int bolos_ux_mnemonic_from_data(unsigned char *in, + unsigned int inLength, + unsigned char *out, + unsigned int outLength) { + add_mock_func_call(MOCK_FUNC_BOLOS_UX_MNEMONIC_FROM_DATA); + const char mnemonic[] = "the-mnemonics"; + strcpy((char *)out, mnemonic); + return strlen(mnemonic); } \ No newline at end of file diff --git a/ledger/src/ui/test/mock/os.h b/ledger/src/ui/test/mock/os.h index deb74c04..a319844e 100644 --- a/ledger/src/ui/test/mock/os.h +++ b/ledger/src/ui/test/mock/os.h @@ -23,12 +23,29 @@ */ #include +#include +#include "cx.h" /** * Utility macros */ #define UNUSED(x) (void)x #define THROW(e) return e +#define PIC(x) (x) + +typedef enum { + MOCK_FUNC_OS_GLOBAL_PIN_CHECK, + MOCK_FUNC_OS_PERSO_SET_PIN, + MOCK_FUNC_OS_GLOBAL_PIN_INVALIDATE, + MOCK_FUNC_OS_MEMSET, + MOCK_FUNC_NVM_WRITE, + MOCK_FUNC_OS_PERSO_WIPE, + MOCK_FUNC_OS_PERSO_DERIVE_AND_SET_SEED, + MOCK_FUNC_OS_PERSO_FINALIZE, + MOCK_FUNC_OS_PERSO_ISONBOARDED, + MOCK_FUNC_BOLOS_UX_MNEMONIC_FROM_DATA, + MOCK_FUNC_OS_GLOBAL_PIN_RETRIES, +} mock_func_call_t; /** * Mock APDU buffer @@ -36,6 +53,14 @@ #define IO_APDU_BUFFER_SIZE 85 extern unsigned char G_io_apdu_buffer[IO_APDU_BUFFER_SIZE]; +/** + * Helper functions to handle call list + */ +void reset_mock_func_call_list(); +void add_mock_func_call(mock_func_call_t func); +mock_func_call_t get_mock_func_call(int order); +int get_mock_func_call_count(); + /** * Mock calls for os API */ @@ -45,6 +70,19 @@ void os_perso_set_pin(unsigned int identity, unsigned char *pin, unsigned int length); void os_global_pin_invalidate(void); +void os_memset(void *dst, unsigned char c, unsigned int length); +void nvm_write(void *dst_adr, void *src_adr, unsigned int src_len); +void os_perso_wipe(); +void os_perso_derive_and_set_seed(unsigned char identity, + const char *prefix, + unsigned int prefix_length, + const char *passphrase, + unsigned int passphrase_length, + const char *words, + unsigned int words_length); +void os_perso_finalize(void); +unsigned int os_perso_isonboarded(void); +unsigned int os_global_pin_retries(void); /** * Other mocks diff --git a/ledger/src/ui/test/onboard/Makefile b/ledger/src/ui/test/onboard/Makefile new file mode 100644 index 00000000..69cc6fa9 --- /dev/null +++ b/ledger/src/ui/test/onboard/Makefile @@ -0,0 +1,57 @@ +# The MIT License (MIT) +# +# Copyright (c) 2021 RSK Labs Ltd +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is furnished to do +# so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +SRCDIR = ../../src +COMMONDIR = ../../src_common +MOCKDIR = ../mock +CFLAGS = -I $(SRCDIR) -I $(MOCKDIR) -I ./ + +PROG = test.out +OBJS = os.o cx.o pin.o onboard.o test_onboard.o + +all: $(PROG) + +$(PROG): $(OBJS) + $(CC) -o $@ $^ + +test_onboard.o: test_onboard.c + $(CC) $(CFLAGS) -c -o $@ $^ + +onboard.o: $(SRCDIR)/onboard.c + $(CC) $(CFLAGS) -c -o $@ $^ + +pin.o: $(SRCDIR)/pin.c + $(CC) $(CFLAGS) -c -o $@ $^ + +os.o: $(MOCKDIR)/os.c + $(CC) $(CFLAGS) -c -o $@ $^ + +cx.o: $(MOCKDIR)/cx.c + $(CC) $(CFLAGS) -c -o $@ $^ + +.PHONY: clean test + +clean: + rm -f $(PROG) ./*.o + +test: all + ./$(PROG) diff --git a/ledger/src/ui/test/onboard/test_onboard.c b/ledger/src/ui/test/onboard/test_onboard.c new file mode 100644 index 00000000..6bdac8e5 --- /dev/null +++ b/ledger/src/ui/test/onboard/test_onboard.c @@ -0,0 +1,180 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 RSK Labs Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include "apdu.h" +#include "cx.h" +#include "defs.h" +#include "onboard.h" +#include "os.h" +#include "pin.h" + +char words_buffer[] = "words_buffer"; +char seed[] = "seed_buffer"; + +void test_reset_onboard_ctx() { + printf("Test reset onboard context...\n"); + onboard_t onboard_ctx; + memcpy(onboard_ctx.words_buffer, words_buffer, sizeof(words_buffer)); + memcpy(onboard_ctx.seed, seed, sizeof(seed)); + + reset_onboard_ctx(&onboard_ctx); + + char expected_words_buffer[sizeof(words_buffer)]; + char expected_seed[sizeof(seed)]; + memset(expected_words_buffer, 0, sizeof(expected_words_buffer)); + memset(expected_seed, 0, sizeof(expected_seed)); + assert(memcmp(expected_words_buffer, + onboard_ctx.words_buffer, + sizeof(expected_words_buffer)) == 0); + assert(memcmp(expected_seed, onboard_ctx.seed, sizeof(expected_seed)) == 0); + assert(onboard_ctx.words_buffer_length == 0); +} + +void test_set_host_seed() { + printf("Test set host seed...\n"); + onboard_t onboard_ctx; + reset_onboard_ctx(&onboard_ctx); + // mock 32 bytes random host seed + const char host_seed[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + unsigned int rx = 4; + for (int i = 0; i < strlen(host_seed); i++) { + SET_APDU_AT(2, i); + SET_APDU_AT(3, host_seed[i]); + assert(0 == set_host_seed(rx, &onboard_ctx)); + } + assert(0 == strncmp((char*)onboard_ctx.host_seed, host_seed, SEEDSIZE)); +} + +void test_onboard_device() { + printf("Test onboard device...\n"); + onboard_t onboard_ctx; + reset_onboard_ctx(&onboard_ctx); + // mock 32 bytes random host seed + const char host_seed[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + // device pin (with prepended length) + const unsigned char valid_pin[] = "X1234567a"; + unsigned int rx; + + // Mock RSK_PIN_CMD + rx = 4; + for (int i = 0; i < sizeof(valid_pin); i++) { + SET_APDU_AT(2, i); + SET_APDU_AT(3, valid_pin[i]); + assert(3 == update_pin_buffer(rx)); + } + + // Mock RSK_SEED_CMD + rx = 4; + for (int i = 0; i < strlen(host_seed); i++) { + SET_APDU_AT(2, i); + SET_APDU_AT(3, host_seed[i]); + assert(0 == set_host_seed(rx, &onboard_ctx)); + } + + reset_mock_func_call_list(); + assert(3 == onboard_device(&onboard_ctx)); + assert(2 == APDU_AT(1)); + assert(1 == APDU_AT(2)); + assert(get_mock_func_call(0) == MOCK_FUNC_NVM_WRITE); + assert(get_mock_func_call(1) == MOCK_FUNC_OS_GLOBAL_PIN_INVALIDATE); + assert(get_mock_func_call(2) == MOCK_FUNC_OS_PERSO_WIPE); + assert(get_mock_func_call(3) == MOCK_FUNC_BOLOS_UX_MNEMONIC_FROM_DATA); + assert(get_mock_func_call(4) == MOCK_FUNC_OS_PERSO_DERIVE_AND_SET_SEED); + assert(get_mock_func_call(5) == MOCK_FUNC_OS_PERSO_SET_PIN); + assert(get_mock_func_call(6) == MOCK_FUNC_OS_PERSO_FINALIZE); + assert(get_mock_func_call(7) == MOCK_FUNC_OS_GLOBAL_PIN_INVALIDATE); + assert(get_mock_func_call(8) == MOCK_FUNC_OS_GLOBAL_PIN_CHECK); + assert(get_mock_func_call(9) == MOCK_FUNC_NVM_WRITE); + assert(get_mock_func_call_count() == 10); + + // Make sure all mnemonic and seed information is wiped after onboard_device + char expected_words_buffer[sizeof(words_buffer)]; + char expected_seed[sizeof(seed)]; + memset(expected_words_buffer, 0, sizeof(expected_words_buffer)); + memset(expected_seed, 0, sizeof(expected_seed)); + assert(memcmp(expected_words_buffer, + onboard_ctx.words_buffer, + sizeof(expected_words_buffer)) == 0); + assert(memcmp(expected_seed, onboard_ctx.seed, sizeof(expected_seed)) == 0); + assert(onboard_ctx.words_buffer_length == 0); +} + +void test_onboard_device_invalid_pin() { + printf("Test onboard device (invalid pin)...\n"); + onboard_t onboard_ctx; + reset_onboard_ctx(&onboard_ctx); + // mock 32 bytes random host seed + const char host_seed[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + // wrong device pin (without prepended length) + const unsigned char invalid_pin[] = "1234567a"; + unsigned int rx; + + // Mock RSK_PIN_CMD + rx = 4; + for (int i = 0; i < sizeof(invalid_pin); i++) { + SET_APDU_AT(2, i); + SET_APDU_AT(3, invalid_pin[i]); + assert(3 == update_pin_buffer(rx)); + } + + // Mock RSK_SEED_CMD + rx = 4; + for (int i = 0; i < strlen(host_seed); i++) { + SET_APDU_AT(2, i); + SET_APDU_AT(3, host_seed[i]); + assert(0 == set_host_seed(rx, &onboard_ctx)); + } + + reset_mock_func_call_list(); + // ERR_INVALID_PIN + assert(0x69A0 == onboard_device(&onboard_ctx)); + assert(get_mock_func_call(0) == MOCK_FUNC_NVM_WRITE); + assert(get_mock_func_call_count() == 1); +} + +void test_is_onboarded() { + printf("Test is onboarded...\n"); + reset_mock_func_call_list(); + assert(5 == is_onboarded()); + assert(1 == APDU_AT(1)); + assert(VERSION_MAJOR == APDU_AT(2)); + assert(VERSION_MINOR == APDU_AT(3)); + assert(VERSION_PATCH == APDU_AT(4)); + assert(get_mock_func_call(0) == MOCK_FUNC_OS_PERSO_ISONBOARDED); + assert(get_mock_func_call_count() == 1); +} + +int main() { + test_reset_onboard_ctx(); + test_set_host_seed(); + test_onboard_device(); + test_onboard_device_invalid_pin(); + test_is_onboarded(); +}