Skip to content

Commit

Permalink
Merge branch 'master' into cx_bn_gf2_n_mul
Browse files Browse the repository at this point in the history
  • Loading branch information
aido authored Oct 27, 2023
2 parents a7d0e91 + 2452ccf commit 97d9519
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 11 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.3.3] - 2023-10-26

### Fixed
- Launcher: Fix missing RAM relocation emulation on NanoX, NanoSP and Stax

## [0.3.2] - 2023-09-28

### Fixed
- API: the API thread is asked to stop when Speculos exits

## [0.3.1] - 2023-09-28

### Fixed
- OCR: Prevent null dereference when expected font is not in ELF file

## [0.3.0] - 2023-09-11

Expand Down
46 changes: 39 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,49 @@ being merged to `master`:

## Limitations

The emulator handles only a few syscalls made by common apps; for instance,
There is absolutely no guarantee that apps will have the same behavior on
hardware devices and Speculos, though the differences are limited.

### Syscalls

The emulator handles only a few syscalls made by common apps. For instance,
syscalls related to app install, firmware update or OS info can't be
implemented.

There is absolutely no guarantee that apps will have the same behavior on
hardware devices and Speculos:
Invalid syscall parameters might throw an exception on a real device while
being ignored on Speculos.
Notably, this is the case for application allowed derivation path and curve and
application settings flags which are enforced by the device OS, but ignored by
Speculos.

### Memory alignment

Attempts to perform unaligned accesses when not allowed (eg. dereferencing a
misaligned pointer) will cause an alignment fault on a Ledger Nano S device but
not on Speculos. Note that such unaligned accesses are supported by other
Ledger devices.

Following code crashes on LNS device, but not on Speculos nor on other devices.
```
uint8_t buffer[20];
for (int i = 0; i < 20; i++) {
buffer[i] = i;
}
uint32_t display_value = *((uint32_t*) (buffer + 1));
PRINTF("display_value: %d\n", display_value);
```

### Watchdog

NanoX and Stax devices use an internal watchdog enforcing usage of regular
calls to `io_seproxyhal_io_heartbeat();`. This watchdog is not emulated on
Speculos.

### Pending review screen

- Invalid syscall parameters might throw an exception on a real device while
being ignored on Speculos.
- Attempts to perform unaligned accesses when not allowed (eg. dereferencing a
misaligned pointer) will cause an alignment fault on a hardware device.
The C SDK offers a feature to display a warning screen upon app launch
indicating that the app has not been reviewed.
As the `_install_parameters` are not handled by Speculos, the screen won't be displayed.


## Security
Expand Down
8 changes: 6 additions & 2 deletions speculos/api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def __init__(self, api_port: int) -> None:
self._notify_exit: socket.socket
self.sock, self._notify_exit = socket.socketpair()
self.api_port: int = api_port
self._api_thread: threading.Thread

@property
def file(self):
Expand All @@ -55,8 +56,11 @@ def start_server_thread(self,
automation_server: BroadcastInterface) -> None:
wrapper = ApiWrapper(screen_, seph_, automation_server)
self._app = wrapper.app
api_thread = threading.Thread(target=self._run, name="API-server", daemon=True)
api_thread.start()
self._api_thread = threading.Thread(target=self._run, name="API-server", daemon=True)
self._api_thread.start()

def stop(self):
self._api_thread.join(10)


class ApiWrapper:
Expand Down
5 changes: 5 additions & 0 deletions speculos/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ def get_elf_infos(app_path):
fonts_addr = bagl_fonts_symbol[0]['st_value']
fonts_size = bagl_fonts_symbol[0]['st_size']
logger.info(f"Found C_bagl_fonts at 0x{fonts_addr:X} ({fonts_size} bytes)\n")
else:
logger.info("Disabling OCR.")

supp_ram = elf.get_section_by_name('.rfbss')
ram_addr, ram_size = (supp_ram['sh_addr'], supp_ram['sh_size']) if supp_ram is not None else (0, 0)
Expand Down Expand Up @@ -518,6 +520,9 @@ def main(prog=None) -> int:

screen_notifier.run()

if apirun is not None:
apirun.stop()

s2.close()
_, status = os.waitpid(qemu_pid, 0)
qemu_exit_status = os.WEXITSTATUS(status)
Expand Down
2 changes: 1 addition & 1 deletion src/bolos/cx_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#ifndef NATIVE_64BITS // NO 64BITS
/** 64bits types, native or by-hands, depending on target and/or compiler
* support.
* This type is defined here only because sha-3 struct used it INTENALLY.
* This type is defined here only because sha-3 struct used it INTERNALLY.
* It should never be directly used by other modules.
*/
struct uint64_s {
Expand Down
5 changes: 5 additions & 0 deletions src/bolos/fonts_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@ void parse_fonts(void *code, unsigned long text_load_addr,
nb_fonts = fonts_size / 4;
}

// There is no font or we don't know its format
if (!nb_fonts) {
return;
}

// Checks that fonts & nb_fonts are coherent
if (fonts[nb_fonts] != nb_fonts) {
fprintf(stdout, "ERROR: Expecting nb_fonts=%u and found %u instead!\n",
Expand Down
13 changes: 12 additions & 1 deletion src/launcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include "svc.h"

#define LOAD_ADDR ((void *)0x40000000)
#define LINK_RAM_ADDR (0xda7a0000)
#define LOAD_RAM_ADDR (0x50000000)
#define MAX_APP 16
#define MAIN_APP_NAME "main"

Expand Down Expand Up @@ -299,6 +301,11 @@ static void *load_app(char *name)
data_addr = get_lower_page_aligned_addr(app->elf.stack_addr);
data_size = get_upper_page_aligned_size(
app->elf.stack_size + app->elf.stack_addr - (unsigned long)data_addr);
if (app->elf.stack_addr == LINK_RAM_ADDR) {
// Emulate RAM relocation
data_addr = (void *)LOAD_RAM_ADDR;
data_size = get_upper_page_aligned_size(app->elf.stack_size);
}

/* load code
* map an extra page in case the _install_params are mapped in the beginning
Expand Down Expand Up @@ -547,7 +554,11 @@ static int run_app(char *name, unsigned long *parameters)
/* thumb mode */
f = (void *)((unsigned long)p | 1);
stack_end = app->elf.stack_addr;
stack_start = app->elf.stack_addr + app->elf.stack_size;
if (app->elf.stack_addr == LINK_RAM_ADDR) {
// Emulate RAM relocation
stack_end = LOAD_RAM_ADDR;
}
stack_start = stack_end + app->elf.stack_size;

asm volatile("mov r0, %2\n"
"mov r9, %1\n"
Expand Down

0 comments on commit 97d9519

Please sign in to comment.