Coder Social home page Coder Social logo

speculos's Introduction

Speculos

codecov lgtm

screenshot btc nano s

The goal of this project is to emulate Ledger Nano S/S+, Nano X, Blue, Flex and Stax apps on standard desktop computers, without any hardware device. More information can be found here in the documentation website (or in the docs/ folder directly).

Usage example:

./speculos.py apps/btc.elf --model nanos
# ... and open a browser on http://127.0.0.1:5000

Bugs and contributions

Feel free to open issues and create pull requests on this GitHub repository.

The master branch is protected to disable force pushing. Contributions should be made through pull requests, which are reviewed by @LedgerHQ members before being merged to master:

  • @LedgerHQ members can create branches directly on the repository (if member of a team with write access to the repository)
  • External contributors should fork the repository

Limitations

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.

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, Flex and Stax devices use an internal watchdog enforcing usage of regular calls to io_seproxyhal_io_heartbeat();. This watchdog is not emulated on Speculos.

Security

Apps can make arbitrary Linux system calls (and use QEMU semihosting features), thus don't run Speculos on untrusted apps.

It's worth noting that the syscall implementation (src/) doesn't expect malicious input. By the way, in Speculos, there is no privilege separation between the app and the syscalls. This doesn't reflect the security of the firmware on hardware devices where app and OS isolation is enforced.

Speculos is not part of Ledger bug bounty program.

Are you developing a Nano App as an external developer?

For a smooth and quick integration:

speculos's People

Contributors

abonnaudet-ledger avatar agrojean-ledger avatar aguinet avatar aido avatar aiooss-ledger avatar apaillier-ledger avatar apollounicorn avatar bigspider avatar cbouvet-ledger avatar cfranceschi-ledger avatar dependabot[bot] avatar dj8yfo avatar dmorais-ledger avatar ericson2314 avatar fbeutin-ledger avatar greenknot avatar jibeee avatar jleni avatar kingofpayne avatar lpascal-ledger avatar ndedouhet-ledger avatar niooss-ledger avatar nroggeman-ledger avatar ogoulpeau-ledger avatar philippebonnaz avatar sgliner-ledger avatar srasoamiaramanana-ledger avatar tamtamhero avatar xchapron-ledger avatar yhql avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

speculos's Issues

Can't push a new version of speculos builder to Docker Hub

OpenSSL version was bumped to 1.1.1k in commit 753032f and build.Dockerfile was updated accordingly. I didn't manage to push a new speculos builder Docker image to Docker Hub though (denied: requested access to the resource is denied).

This should be investigated since that image is used by the CI to build the speculos Docker image.

  • Short-term solution: find the appropriate credentials to push to Docker Hub.
  • Long-term solution: let the CI build the speculos builder image; maybe switch to ghcr.io because Docker Hub doesn't seem to be supported by the infra team anymore.

Syscall cx_ecfp_scalar_mult is not implemented

Hello,

When launching the Monero application (https://github.com/LedgerHQ/app-monero) with Speculos, I get:

[*] using SDK version 1.6
[*] patching svc instruction at 0x40004f8a
[*] patching svc instruction at 0x40005754
launcher: failed to emulate syscall 0x60002cf3

0x60002cf3 is SYSCALL_cx_ecfp_scalar_mult_ID_IN: syscall cx_ecfp_scalar_mult is missing. It is used in Monero for almost every operation on Ed25519, and for example in https://github.com/LedgerHQ/app-monero/blob/ad59fa92bac575962c8e89613c6111802c868ca2/src/monero_crypto.c#L610-L618

It would be nice to support this operation :)

Add PRINTF analog that works regardless of IO status

PRINTF only works when USB is ready and it is SE turn to send messages. It may work for big number of cases, but will not work for some test applications when USB is not needed, or during experimenting with IO system itself.
Additional syscall could be added like SPECULOS_LOG(...) that will work only in Speculos, and output into console regardless the current state of IO.

Button Handling OSX

It seems in OSX speculos doesn't handle the BUTTON_EVT_RELEASED | BUTTON_LEFT | BUTTON_RIGHT event when I press down both the left and right keyboard keys.

Is there anyway to fix this or to emulate this event programatically? Thanks.

Events are sent before screen updates

It can be problematic in test scenarios where:

  • The test waits for an event to happen
  • A screenshot is saved just after it's received

The following commands reproduce the issue:

$ ./speculos.py --model blue --sdk 1.5 apps/blue#btc#1.5#00000000.elf &
$ wget -O- -q 'http://127.0.0.1:5000/events?stream=true &
$ echo e040010015058000002C80000000800000000000000000000000 | LEDGER_PROXY_ADDRESS=127.0.0.1 LEDGER_PROXY_PORT=9999 ledgerctl send -

The event {"text": "CONFIRM ACCOUNT", "x": 98, "y": 35} is received about 0.2 seconds before the screen is refreshed

Some glyphs are missing

Not all glyphs seem to be supported by speculos.
Met this problem with "CHECK_BADGE" glyph, but probably a lot of more are missing.

PRINTF in library doesn't work

Issue

Using the PRINTF macro in an app loaded as a library (e.g when the app-exchange jumps to another app) doesn't work with speculos.

How to reproduce

  1. Get this app-exchange branch.
  2. cd test
  3. Run the tezos tests with this command : sudo jest --runInBand --detectOpenHandles src/tezos.test.js
  4. I've setup the tezos app to print a special debug message (PRINTF(----------HIIIIIIIIIIIIIIIIIIII-----------------")). So we expect the above test to print the message.
  5. Test will fail (this is expected), but more over speculos won't display "----------HIIIIIIIIIIIIIIIIIIII-----------------" (you can find the code on this branch of the app-tezos).

N.B: The app-exchange app has been compiled with the DEBUG flag, and the app-tezos has also been compiled with the DEBUG flag.

If you need to modify the tezos binary, you need to clone this app-tezos branch, do your modifications then make and cp /path/to/app-tezos/bin/app.elf /path/to/app-exchange/test/elfs/tezos.elf. Same for app-exchange.

Text UI broken on master - "failed to emulate syscall 0x6000721c"

If I run the binary from the repo with --text, it works as I expect:

./speculos.py --text apps/btc.elf

If I do the same with a binary that I built myself from the master branch, it fails with the following error:

launcher: failed to emulate syscall 0x6000721c

Speculos constantly hangs when run in travis

In HWI, we use speculos to test that the Ledger Nano S implementation works. However when these tests are run in Travis CI, speculos routinely hangs resulting in a test timeout. There is no particular place that this happens, it just seems to always happen at some point during the test suite.

Incorrect stack pointer initialization

First of all, I love speculos!

While using it, noticed that the stack pointer seems to be initialized incorrectly. This is problematic because it is not possible to rely on the stack canary.

A typical app.map shows something similar to:

               [!provide]                PROVIDE (app_stack_canary, .)
                0x20001ce8                . = (. + 0x4)
 *fill*         0x20001ce4        0x4 00
                0x20001ce8                _stack_validation = .
                0x20002800                . = (_stack_validation + STACK_SIZE)
 *fill*         0x20001ce8      0xb18 00
                0x20001ce8                _stack = (ABSOLUTE (END_STACK) - STACK_SIZE)
                [!provide]                PROVIDE (_stack, (ABSOLUTE (END_STACK) - STACK_SIZE))
                0x20002800                _estack = ABSOLUTE (END_STACK)
                [!provide]                PROVIDE (_estack, ABSOLUTE (END_STACK))

so sp is expected to be in that range.

As soon as launching gdb, sp is out ot range:

Breakpoint 1, main () at src/main.c:21
-exec info stack
#0  main () at src/main.c:21
#1  0x00010ff8 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

$sp
0x20003000

@yhql pointed me to this line

__asm("mov sp, %0" :: "r"(DATA_VADDR+DATA_VSIZE));

Digging a bit into the code, I noticed the following:

speculos/src/launcher.c

Lines 30 to 32 in b529cd0

// TODO: get these from Elf
#define DATA_VADDR 0x20001800
#define DATA_VSIZE 0x1800 // 6k

As a workaround, I am patching DATA_VSIZE with 0x1000, if you think it makes sense I can make a quick PR. So at least, the stack canary is triggered properly.

I guess in the long term, it would be better to use _estack and retrieve the value from the elf executable.

Update the provided app binaries

It would be nice to update the provided app binaries so that people who are using this for CI can test against updated stuff.

Or is there some place that the apps can be downloaded?

Support multiple USB on/off

This code works:

USB_power(0);
USB_power(1);

But this make the device irresponsible

USB_power(0);
USB_power(1);

USB_power(0);
USB_power(1);

Cannot setup device when running with Docker

I wanted to use the emulator with Ledger live. Used Docker and the instructions here to run. I can connect to emulator using VNC and also see the UI in console when running with text display. I can navigate with left, right, up, and down arrows but I cannot setup a new device by pressing both left and right keys together as Ledger Live says.

The Nano X OCR incorrectly regognizes uppercase I as a L

Here is the output of speculos:

./speculos.py --log-level automation:DEBUG --model nanox --automation file:/app-xrp/tests/automation.json /app-xrp/bin/app.elf
...
12:38:16.440:automation: getting actions for "lssuer
r9cZA1mLK5R5Am25A
rfXFmqgNwjZgnfk59" (47, 6)

(notice lssuer instead of Issuer.)

For the following APDU:

$ LEDGER_PROXY_ADDRESS=127.0.0.1 LEDGER_PROXY_PORT=9999 pytest-3 -v -s -k test_sign_valid_tx tests/
$ echo e0040040b4058000002c80000090800000008000000000000000120010228000000024000000192a21fb3df12e0000000150116f1dfd1d0fe8a32e40e1f2c05cf1c15545bab56b617f9c6c2d63a6b704bef59b68400000000000000a69e0c68db7b413ec0000000000000000000000000055534400000000005e7b112523f68d2f5e879db4eac51c6698a6930481140511e17db83bb6f113939d67bc8ea539edc926fc83147148ebebf7304ccdf1676fefcf9734cf1e780826 | LEDGER_PROXY_ADDRESS=127.0.0.1 LEDGER_PROXY_PORT=9999 ledgerctl send -

Distribute speculos as a single binary

Here are a few notes on how to use pyinstaller to produce a single binary (qemu-user-static is still a requirement, but I guess it can also be embedded):

pyinstaller --onefile --windowed --add-data api/resources/:/api/resources/ --add-data api/swagger/:/api/swagger/ --add-binary build/src/launcher:/build/src/ --add-data cxlib:/cxlib/ speculos.py

which runs successfuly:

root@c3a1333f6f08:/speculos# ls -lh dist/speculos 
-rwxr-xr-x 1 root root 12M Jun 28 00:07 dist/speculos
root@c3a1333f6f08:/speculos# ldd dist/speculos 
	linux-vdso.so.1 (0x00007ffda37b3000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fe6e15fd000)
	libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fe6e15e1000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fe6e15be000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe6e13cc000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fe6e162f000)
root@c3a1333f6f08:/speculos# ./dist/speculos --display headless ./apps/btc.elf 
[*] speculos launcher revision: 027fd47
[*] using SDK version 2.0
[*] loading CXLIB from "/tmp/_MEIlTzPby/cxlib/cx-2.0.elf"
[*] patching svc instruction at 0x125c74
[*] patching svc instruction at 0x40005d8c
 * Serving Flask app 'api.api' (lazy loading)
 * Environment: development
 * Debug mode: off
00:12:32.236:werkzeug:  * Running on all addresses.
   WARNING: This is a development server. Do not use it in a production deployment.
00:12:32.236:werkzeug:  * Running on http://172.17.0.2:5000/ (Press CTRL+C to quit)

bad signature on the TRON app

It seems that, roughly 1 transaction out of 3 creates a bad signature when using the TRON app.

Here is an example of transaction that failed in our ledger-live bot:

all accounts sync in 4.4s
โ–ฌ Tron 0.2.2 on nanoS 1.6.0
โ†’ FROM Tron 4: TRX 39.8 (54ops) (TBtPherJfuSMaJnWVtuuo2AvjgdfxzUhAb on 44'/195'/3'/0/0) #3 
max spendable ~26.85
โ˜… using mutation 'send max to another account'
โ†’ TO Tron 1: TRX 4.511 (60ops) (TJz8r6opgQn7CXW2pDwfxUj5GiQWHkfB1z on 44'/195'/0'/0/0) #0 
โœ”๏ธ transaction 
SEND MAX 
TO TJz8r6opgQn7CXW2pDwfxUj5GiQWHkfB1z
STATUS (2076ms)
  amount: TRX 26.851715
  estimated fees: TRX 0
  total spent: TRX 26.851715
โœ”๏ธ has been signed! (4.1s) {"operation":{"id":"js:2:tron:TBtPherJfuSMaJnWVtuuo2AvjgdfxzUhAb:-3ff0dcd16ca5bf6298c2babc1f1c29c5c644449a3d45c80c620b3e81516fd1c9-OUT","hash":"3ff0dcd16ca5bf6298c2babc1f1c29c5c644449a3d45c80c620b3e81516fd1c9","type":"OUT","blockHash":null,"blockHeight":null,"senders":["TBtPherJfuSMaJnWVtuuo2AvjgdfxzUhAb"],"recipients":["TJz8r6opgQn7CXW2pDwfxUj5GiQWHkfB1z"],"accountId":"js:2:tron:TBtPherJfuSMaJnWVtuuo2AvjgdfxzUhAb:","extra":{},"date":"2020-08-17T10:51:36.828Z","value":"26851715","fee":"0"},"signature":"8f80e965d007c137e4559ade81dfa5d7bf9787dc5873db2efdc8ac0609c20b2d11379a0155969709120c51af4f7186abbb3385671ab6c4d37526b16e3c92b96a00","expirationDate":null,"signatureRaw":{"contract":[{"parameter":{"value":{"amount":26851715,"owner_address":"4115071a84c2d7748e0c29efc03f6035d46b1cf0c0","to_address":"4162e6147e8ff558f579d9dea6031b3468b2b3e4a3"},"type_url":"type.googleapis.com/protocol.TransferContract"},"type":"TransferContract"}],"ref_block_bytes":"c2c1","ref_block_hash":"eda7cac306318b98","expiration":1597661553000,"timestamp":1597661493685}}
โš ๏ธ Error

Error

when looking at the technical error, we see the API is rejecting us with

{ "code": "SIGERROR", message: "validate signature error 48c2beb032b1350f3f11f8d73498d953a1713404b77cffcc319b8391fa604a867288e71ff48a1e29c412947e122fc15c281da98b6bb90d2d27a077ef714fe3f600 is signed by TWPLHq8aYcbzEV3c472tjJFYFQ98MYDQuY but it is not contained of permission." }

which correspond to signing with an incorrect private key

with the same codebase of live-common we never see this issue with a real device so we highly suspect something on speculos.

Any call to the SDK hangs if gdb is attached

Any call to the SDK hangs if gdb is attached. I am able to debug the emulator fine prior to calling in to the SDK.

Here are the steps that I have followed:

#DEBUG = 0
DEBUG = 1

#CFLAGS   += -O3 -Os
CFLAGS   += -g

#LDFLAGS  += -O3 -Os
LDFLAGS  += -g
  • I put PRINTF() statements in functions btchip_apdu_hash_input_start() and btchip_apdu_hash_input_finalize_full().

  • First, as a sanity check, I run the emulator with no debugging:

./speculos.py --sdk 1.5 apps/btc.ledger.master.elf

  • From btchip-python I send a TX to the emulator. Within the emulator I sign the TX. In the stdout I see the PRINTF() statements from btchip_apdu_hash_input_start() and btchip_apdu_hash_input_finalize_full(), so I know that these functions are hit.

  • Now I run the emulator in the debugger:

./speculos.py --sdk 1.5 -d apps/btc.ledger.master.elf &
./tools/debug.sh apps/btc.ledger.master.elf

gdb$ b io_exchange
Breakpoint 2 at 0x40005f50: file /home/erik/projects/ledger/nanos-secure-sdk/src/os_io_seproxyhal.c, line 957.
gdb$ b btchip_apdu_hash_input_start
Breakpoint 3 at 0x400011bc: file src/btchip_apdu_hash_input_start.c, line 32.
gdb$ b btchip_apdu_hash_input_finalize_full
Breakpoint 4 at 0x40000d34: file src/btchip_apdu_hash_input_finalize_full.c, line 498.
gdb$ c
Continuing.

Then from btchip-python I send a TX to the emulator. gdb breaks in io_exchange(), I hit c(ontinue), after that gdb never returns. The emulator remains responsive to user button presses but does not receive the TX that has been sent to it. Through further analysis I see that the process hangs in file os_io_seproxyhal.c, in function io_exchange(), near line 1130: for (;;) { ... } It calls in to the SDK and never returns. My PRINTF() statements in functions btchip_apdu_hash_input_start() and btchip_apdu_hash_input_finalize_full() are never executed.

Add support for --display text for the Nano X

Using --display text in combination with --model nanox currently throws error unsupported model 'nanox' with argument -x.

Would it be possible to add text support for the Nano X?

Concatenation of APDU messages is not supported

Longer APDU messages are typically read into G_io_apdu_buffer by concatenating multiple smaller messages that are received in G_io_seproxyhal_spi_buffer. It seems like this functionality relies on io_seproxyhal_spi_is_status_sent to return a non-zero value when more data is available (i.e. sent on SPI but not yet read into G_io_seproxyhal_spi_buffer). I think that this code may be related.

The current implementation of this function always returns zero, which effectively disables support for message concatenation (see /src/emu_seproxyhal.c).

With message concatenation disabled, received messages risk to be cut off if G_io_apdu_buffer is larger than G_io_seproxyhal_spi_buffer. In these cases, the cut off part is filled with zeroes.

The problem can be mitigated on the app side by defining IO_SEPROXYHAL_BUFFER_SIZE_B to be sufficiently large. However, the current implementation creates confusion as to why apps behave the way they do when tested using Speculos.

Automation HTTP service

It could be interesting to have Speculos creating an HTTP service that would serve an API which would allow to control automation (and the device itself) while it's running. This would potentially replace also the features provided by --automation-port, --button-port and --finger-port.

One use case I have in mind is being able to test Ledger companion apps on Windows & OSX using e.g. GitHub actions. Indeed, in GitHub actions, for a job, you can run a "background" service under Linux, that would be used by the job itself running on another OS. So, we could have Speculos running under Linux, exposing its automation port, for which we could push "automation JSON" depending on the test case.

This is a first "brain dump", and IMHO needs more thinking, especially on the HTTP API definition.

Unexpected crash for nano x

Hi,

I had another crash when loading a nano x application.
Here the message :

serving at port 9998
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-zondax'
[*] using SDK version 1.2
[*] patching svc instruction at 0x40001e68
[*] patching svc instruction at 0x4000c628
launcher: failed to emulate syscall 0x60009c8b
libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast
vnc_server: readall: connection closed

No action needed to trigger it. It directly crash when starting.

SHA224 support

cx_sha224_init leads to "launcher: failed to emulate syscall 0x6000095b"

ECDSA - RFC6979 support broke signing with blake2b

The following commit 3708d07 broke blake2b ecdsa signatures

This check is triggered:

const cx_hash_info_t *hash_info = cx_hash_get_info(hash_id);
if (hash_info == NULL || hash_info->output_size == 0) {
THROW(INVALID_PARAMETER);
}

because blake2b

speculos/src/emu_cx_hash.c

Lines 107 to 116 in 4b531e8

static const cx_hash_info_t cx_blake2b_info = {
CX_BLAKE2B,
0,
BLAKE2B_BLOCKBYTES,
NULL,
(int (*)(void *ctx, const uint8_t *data, size_t len))cx_blake2b_update,
(int (*)(void *ctx, uint8_t *digest))cx_blake2b_final,
(int (*)(void *ctx, size_t output_size))cx_blake2b_init,
(int (*)(const void *ctx))cx_blake2b_validate_context,
(size_t(*)(const void *ctx))cx_blake2b_get_output_size};

speculos/src/cx_hash.h

Lines 173 to 184 in 4b531e8

/* Generic API */
typedef struct {
cx_md_t md_type;
unsigned int output_size;
unsigned int block_size;
int (*init_func)(void *ctx);
int (*update_func)(void *ctx, const uint8_t *data, size_t len);
int (*finish_func)(void *ctx, uint8_t *digest);
int (*init_ex_func)(void *ctx, size_t output_size);
int (*validate_context)(const void *ctx);
size_t (*output_size_func)(const void *ctx);
} cx_hash_info_t;

Checking different hash types it seems that output_size is set to zero for variable size hash functions.

The cx_rng_rfc6979_init received hash length h1_len so I think that could be used instead.

void cx_rng_rfc6979_init(
cx_rnd_rfc6979_ctx_t *rfc_ctx, cx_md_t hash_id, const uint8_t *x,
size_t x_len, const uint8_t *h1, size_t h1_len, const uint8_t *q,
size_t q_len
/*const uint8_t *additional_input, size_t additional_input_len*/) {

No crash on unaligned pointer access

I'm not sure if this is a speculos problem or if it actually can be solved at all ...

On real hardware the microcontroller crashes on unaligned pointer accesses, speculos doesn't care.

This make debugging quite hard because outcome of tests can diverge (Ok when run in speculos, Crash when run on real hardware).

Would be nice if this could be fixed (if even possible).

Blake2b APIs

It seems that all the sources to handle the Blake2b hash are part of speculos/src but in the file emu_cx_hash.c the Blake2b object structure are disabled through a #if 0 directive (line 107).

Blue touch areas aren't correct with --zoom

Reported by @hcleonis:

when applied to a Blue app, the UI in indeed displayed twice as big but the touch areas keep their original sizes and positions. So you have to guess its original position from the actual widget position and the zoom ratio to be able to interact with the app.

Add ability to mock syscalls for tests

While writing functional tests, it is often the case that some code paths only happen based on the return values of certain APDUs.
Therefore, to get a good test coverage, it would be very helpful to hook into the syscall emulation and programmatically control the syscalls' return values.

In the best of all possible worlds, python tests would have a speculos fixture running an app, that has god-mode control over the device:

def test_something(speculos):
    def mock_os_my_syscall(param):
       return 1 if param == 0xF00 else 0

   speculos.on("os_my_syscall", mock_os_my_syscall)

  # test stuff

Ideally, it should be possible to alter the behavior during execution, to test more complex interactions where the syscall is called multiple times and its return values is different.

My current use case is to test code depending on the result of os_global_pin_is_validated; so even less powerful customization on speculos might be enough.

math syscalls might behave incorrectly when arithmetic overflow occurs

On a real device, it seems that some arithmetic syscalls such as cx_math_add truncate results silently when an arithmetic overflow occurs. The speculos implementation should have the same behavior. See

speculos/src/emu_os_bip32.c

Lines 276 to 284 in 8081103

// cx_math_add(ZR, ZR, kRP, 32) can return invalid result when an overflow
// occurs, so perform addition on 33 bytes and truncate the result to 32
// bytes
a[0] = '\x00';
memcpy(a + 1, ZR, 32);
b[0] = '\x00';
memcpy(b + 1, kRP, 32);
cx_math_add(a, a, b, 33);
memcpy(ZR, a + 1, 32);

BTW, the return value of BN_bn2binpad isn't verified in cx_math_add:

BN_bn2binpad(rr, r, len);
while it returns -1 because len is less than BN_num_bytes(rr). Return values of OpenSSL functions are almost never checked. This should be enforced.

SDK 1.5.5

Hey guys thanks for this project, I truly appreciate the great work. I was wondering is there anyway to launch speculos for sdk 1.5.5? Because when I try to do this i get the following error

launcher: invalid SDK version
vnc_server: readall: connection closed

And the docker command i'm using to launch speculos is the following

docker run --name spec  --rm -it -v "$(pwd)"/.:/speculos/apps -p 1234:1234 -p 40000:40000 -p 41000:41000 -p 42000:42000 speculos --model nanos "./apps/bin/app.elf" --sdk 1.5.5 --seed "secret" --display headless --apdu-port 40000 --vnc-port 41000 --vnc-password toto --button-port 42000

Thanks

cx_eddsa_get_public_key: invalid key size with value 64, but works on physical device

Hi,

I'm seeing a different behavior between speculos and a physical Nano S.

I tried speculos to run this app (https://github.com/jelurida-dev/app-ledger-ardor-main) and got this error message:

[*] using SDK version 1.6
[*] patching svc instruction at 0x4000637a
[*] patching svc instruction at 0x400073b8
09:50:31.254:apdu: > e0060100142c00008072410080000000800100008000000000
09:50:31.255:seproxyhal: printf:
09:50:31.257:seproxyhal: printf:  canery check 1 last command number 0
09:50:32.376:seproxyhal.ticker: skipping ticker events (expected within a debugger)
launcher: cx_eddsa_get_public_key: invalid key size (0x40)
vnc_server: readall: connection closed

The emulator code strictly expects a 32 in the private length: https://github.com/LedgerHQ/speculos/blob/master/src/cx_ec.c#L288-L291

Just checked our code, done by a previous developer. Funny comment...

// weird custom initilization, code copied from Cardano's EdDSA implementaion
privateKey.curve = CX_CURVE_Ed25519;
privateKey.d_len = 64; //don't know why the length is 64 instead of 32, it just works
os_memmove(privateKey.d, KLKR, 32); //Copy just the KL part

"it just works"...
And indeed it does on the Nano S. ๐Ÿคท

Unable to connect to VNC server using MacOS Screen Sharing application

Issue

Connecting to the VNC server from MacOS Screen Sharing app hangs and does not connect.

Screenshot 2020-03-06 at 13 08 26

Replication

  1. Start the server by running docker-compose up with the default options
  2. Open Screen Sharing and attempt to connect to vnc://localhost:41000
  3. Asks for a password, hit enter with no password
  4. Hangs with no output

System Info

  • MacOS 10.14.6
  • Docker 2.2.0.3

Issue links

For context, this was initially discussed in #33.

Display the screen on the web server

On MacOS, VNC is the only mechanism to display the screen of the emulated device.

It would be great to add a web page (index.html?) to the web server which make use of the REST API to:

  • display the screen
  • interact with the device (buttons, maybe APDUs?)

The script tools/gif-recorder.py shows how the API can be used to get notified when the screen changes.

Unable to run VNC server with --display=qt inside Docker

Issue

Running the emulator from docker-compose with --display qt fails with numerous errors.

Replication

Run the following --model nanos ./apps/btc.elf --sdk 1.6 --seed secret --display qt --apdu-port 40000 --vnc-port 41000 --button-port 42000" as the command. At first there will be a number of libs missing:

  • Python: pyqt5
  • Apt: libgl1-mesa-glx, libglib2.0-0, libdbus-1-3 and libfontconfig

After these are installed, the error output is as follows:

qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, wayland-egl, wayland, wayland-xcomposite-egl, wayland-xcomposite-glx, webgl, xcb.

[*] using SDK version 1.6
vnc_server: readall: connection closed

Running with export QT_DEBUG_PLUGINS=1 yields only a little more info:

Got keys from plugin meta data ("xcb")
QFactoryLoader::QFactoryLoader() checking directory path "/usr/local/bin/platforms" ...
loaded library "/usr/local/lib/python3.8/site-packages/PyQt5/Qt/plugins/platforms/libqxcb.so"
qt.qpa.xcb: could not connect to display qt

class APDU is defined twice in api

There are two class APDU in speculos/api/api.py:

class APDU:
def __init__(self):
# We want to be notified when APDU response is transmitted from the SE
self.endpoint_lock = threading.Lock()
self.response_condition = threading.Condition()
and
class APDU(Resource):
schema = load_json_schema("apdu.schema")
def post(self):

One of them should be renamed.

default handler for "failed to emulate syscall xxxxxx"

At the moment, any missing syscall emulation results in the emulator terminating.

It would be nice that missing syscall would trigger a default handler that returns an error to the app without crashing the emulator.

seccomp prevents vnc feature from working

Using the latest version of master (14ce91a) and building the docker container (on macOS) results in the vnc feature not working - the vnc server launches however the bridge doesn't send any data back to the python wrapper.

If I DISABLE_SANDBOX in vnc_server.c and build again the vnc feature works as expected.

I have not tracked down which calls are being filtered as I am not familiar at all with the internals of how seccomp is meant to work. It does feel tho that using seccomp here may be a bit overkill for what is a testing tool. Maybe this is macOS specific (even tho I am running in docker) and linux users are not seeing the same issues.

app-boilerplate failed to emulate syscall

I'm in the process of going through the developer docs and setting up a dev environment for creating an app. The Ledger app-boilerplate fails to run on Speculos with the following log

./speculos.py ../../app-boilerplate/bin/app.elf 
/opt/ledger/speculos/mcu/nanox_ocr.py:155: SyntaxWarning: "is" with a literal. Did you mean "=="?
  if self.text is b"":
[*] speculos launcher revision: 53d114d
[*] using SDK version 1.6
[*] patching svc instruction at 0x40002230
launcher: failed to emulate syscall 0x60010b06

The syscall in question is defined in nanos-secure-sdk as

include/syscalls.h:#define SYSCALL_try_context_set_ID_IN 0x60010b06UL

I hope it is not unrealistic to expect that at least the boilerplate app works, no?

Issue with os_global_pin_is_validated with nano x

I am not quite sure what issue is actually but it seems that I have different behavior between nano s and nano x.

In our app we have a os_global_pin_is_validated check. We are using zemu to run test which depend on speculos. The check pass when running the test for nano s but not for nano x.

If someone has an idea of what I am missing that would be nice.

Build fails error "multiple definition of `G_cx'; libemu.a(cx_blake2b.c.o):(.bss+0x0): first defined here"

I am building on Kubuntu 20.10 with kernel 5.8.0-29-generic and building the master branch of the repo. I followed the instructions here, installed the dependencies with apt and then ran

cmake -Bbuild -H. -DWITH_VNC=1
make -C build/

I get the following errors

/usr/lib/gcc-cross/arm-linux-gnueabihf/10/../../../../arm-linux-gnueabihf/bin/ld: libemu.a(cx_hmac.c.o):(.bss+0x0): multiple definition of `G_cx'; libemu.a(cx_blake2b.c.o):(.bss+0x0): first defined here
/usr/lib/gcc-cross/arm-linux-gnueabihf/10/../../../../arm-linux-gnueabihf/bin/ld: libemu.a(cx_sha256.c.o):(.bss+0x0): multiple definition of `G_cx'; libemu.a(cx_blake2b.c.o):(.bss+0x0): first defined here
/usr/lib/gcc-cross/arm-linux-gnueabihf/10/../../../../arm-linux-gnueabihf/bin/ld: libemu.a(cx_sha512.c.o):(.bss+0x0): multiple definition of `G_cx'; libemu.a(cx_blake2b.c.o):(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status
make[2]: *** [src/CMakeFiles/launcher.dir/build.make:85: src/launcher] Error 1

Even if i try to build without VNC, i get similar errors.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.