Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/LDG-535--nano-app-implement-deploy-method #36

Merged
merged 4 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/common/handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ int handler(uint8_t INS,
case INS_GET_APP_NAME:
return handleGetAppName();
break;
case INS_DEPLOY_MODULE:
handleDeployModule(cdata, p1, lc);
break;
default:
THROW(ERROR_INVALID_INSTRUCTION);
break;
Expand Down
2 changes: 2 additions & 0 deletions src/common/handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

#define INS_EXPORT_PRIVATE_KEY 0x05

#define INS_DEPLOY_MODULE 0x06

#define INS_ENCRYPTED_AMOUNT_TRANSFER 0x10
#define INS_TRANSFER_TO_ENCRYPTED 0x11
#define INS_TRANSFER_TO_PUBLIC 0x12
Expand Down
1 change: 1 addition & 0 deletions src/common/responseCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ enum {
ERROR_BUFFER_OVERFLOW = 0x6B06,
ERROR_FAILED_CX_OPERATION = 0x6B07,
ERROR_INVALID_INSTRUCTION = 0x6D00,
ERROR_INVALID_SOURCE_LENGTH = 0x6B08,

// Error codes from the Ledger firmware
ERROR_DEVICE_LOCKED = 0x530C,
Expand Down
2 changes: 2 additions & 0 deletions src/common/ui/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,5 @@ extern const ux_flow_step_t *ux_sign_scheduled_amount_transfer[8];
void startInitialScheduledTransferDisplay(bool displayMemo);
void uiSignScheduledTransferPairFlowSignDisplay(void);
void uiSignScheduledTransferPairFlowDisplay(void);

void uiDeployModuleDisplay(void);
19 changes: 19 additions & 0 deletions src/common/ui/display_bagl.c
Original file line number Diff line number Diff line change
Expand Up @@ -794,4 +794,23 @@ void uiSignScheduledTransferPairFlowDisplay(void) {
ux_flow_init(0, ux_sign_scheduled_transfer_pair_flow, NULL);
}

// Deploy Module
UX_STEP_NOCB(ux_deploy_module_1_step,
bnnn_paging,
{.title = "Version", .text = (char *) global.deployModule.versionDisplay});
UX_STEP_NOCB(ux_deploy_module_2_step,
bnnn_paging,
{.title = "TX hash", .text = (char *) global.deployModule.sourceHashDisplay});
UX_FLOW(ux_deploy_module,
&ux_sign_flow_shared_review,
&ux_sign_flow_account_sender_view,
&ux_deploy_module_1_step,
// &ux_deploy_module_2_step,
&ux_sign_flow_shared_sign,
&ux_sign_flow_shared_decline);

void uiDeployModuleDisplay() {
ux_flow_init(0, ux_deploy_module, NULL);
}

#endif
48 changes: 48 additions & 0 deletions src/deployModule.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "os.h"
#include "common/ui/display.h"
#include "common/responseCodes.h"
#include "common/sign.h"
#include "common/util.h"
#include "deployModule.h"

static deployModule_t *ctx_deploy_module = &global.deployModule;
static tx_state_t *tx_state = &global_tx_state;

#define P1_INITIAL 0x00
#define P1_SOURCE 0x01

void handleDeployModule(uint8_t *cdata, uint8_t p1, uint8_t lc) {
if (p1 == P1_INITIAL) {
cdata += parseKeyDerivationPath(cdata);
cx_sha256_init(&tx_state->hash);
cdata += hashAccountTransactionHeaderAndKind(cdata, DEPLOY_MODULE);

// hash the version and source length
updateHash((cx_hash_t *) &tx_state->hash, cdata, 8);
ctx_deploy_module->version = U4BE(cdata, 0);
ctx_deploy_module->sourceLength = U4BE(cdata, 4);
ctx_deploy_module->remainingSourceLength = ctx_deploy_module->sourceLength;
// TODO: Format the version
numberToText((uint8_t *) ctx_deploy_module->versionDisplay,
sizeof(ctx_deploy_module->versionDisplay),
ctx_deploy_module->version);
sendSuccessNoIdle();
}

else if (p1 == P1_SOURCE && ctx_deploy_module->remainingSourceLength > 0) {
if (ctx_deploy_module->remainingSourceLength < lc) {
THROW(ERROR_INVALID_SOURCE_LENGTH);
}

updateHash((cx_hash_t *) &tx_state->hash, cdata, lc);
ctx_deploy_module->remainingSourceLength -= lc;
if (ctx_deploy_module->remainingSourceLength > 0) {
sendSuccessNoIdle();
} else if (ctx_deploy_module->remainingSourceLength == 0) {
uiDeployModuleDisplay();
}

} else {
THROW(ERROR_INVALID_STATE);
}
}
25 changes: 25 additions & 0 deletions src/deployModule.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include <stdint.h>
#include <stdbool.h>

/**
* Handles the DEPLOY_MODULE instruction, which deploys a module
*
*
*/
void handleDeployModule(uint8_t *cdata, uint8_t p1, uint8_t p2);

typedef struct {
uint32_t version;
uint32_t sourceLength;
uint32_t remainingSourceLength;
uint8_t sourceHash[32];
char sourceHashDisplay[65];
char versionDisplay[11];
} deployModule_t;

// typedef struct {
// uint8_t version[32];
// uint8_t sourceLength[32];
// } deployModuleBlob_t;
Comment on lines +22 to +25

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.
4 changes: 2 additions & 2 deletions src/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#include "signTransferToPublic.h"
#include "signTransferWithSchedule.h"
#include "signRegisterData.h"

#include "deployModule.h"
#include "ux.h"

#define LEGACY_PURPOSE 1105
Expand Down Expand Up @@ -124,7 +124,7 @@ typedef union {
signTransferToPublic_t signTransferToPublic;
signConfigureBaker_t signConfigureBaker;
signConfigureDelegationContext_t signConfigureDelegation;

deployModule_t deployModule;
transactionWithDataBlob_t withDataBlob;
} instructionContext;
extern instructionContext global;
Expand Down
54 changes: 54 additions & 0 deletions tests/application_client/boilerplate_command_sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ class P1(IntEnum):
P1_PROOFS = 0x08 # Sent for proof bytes
P1_NEW_OR_EXISTING = 0x09 # Sent for new/existing credential flag

# Parameter 1 for deploy module
P1_DEPLOY_MODULE_INITIAL = 0x00
P1_DEPLOY_MODULE_SOURCE = 0x01


class P2(IntEnum):
# Parameter 2 for sign for GET_PUBLIC_KEY.
Expand Down Expand Up @@ -78,6 +82,7 @@ class InsType(IntEnum):
SIGN_TRANSFER_WITH_SCHEDULE = 0x03
CREDENTIAL_DEPLOYMENT = 0x04
EXPORT_PRIVATE_KEY = 0x05
DEPLOY_MODULE = 0x06
ENCRYPTED_AMOUNT_TRANSFER = 0x10
TRANSFER_TO_ENCRYPTED = 0x11
TRANSFER_TO_PUBLIC = 0x12
Expand Down Expand Up @@ -594,5 +599,54 @@ def credential_deployment_part_3(
print("km--------sent new or existing", response)
yield response

@contextmanager
def deploy_module(
self,
path: str,
header_and_type: bytes,
version: int,
source: bytes,
) -> Generator[None, None, None]:

if version > 0xFFFFFFFF:
raise ValueError("Version must be less than 4294967296")
if len(source) > 0xFFFFFFFF:
raise ValueError("Source length must be less than 4294967296")

data = pack_derivation_path(path)
data += header_and_type
data += version.to_bytes(4, byteorder="big")
data += len(source).to_bytes(4, byteorder="big")
temp_response = self.backend.exchange(
cla=CLA,
ins=InsType.DEPLOY_MODULE,
p1=P1.P1_DEPLOY_MODULE_INITIAL,
p2=P2.P2_NONE,
data=data,
)
if temp_response.status != 0x9000:
raise ExceptionRAPDU(temp_response.status)

source_chunks = split_message(source, MAX_APDU_LEN)
last_chunk = source_chunks.pop()
for chunk in source_chunks:
temp_response = self.backend.exchange(
cla=CLA,
ins=InsType.DEPLOY_MODULE,
p1=P1.P1_DEPLOY_MODULE_SOURCE,
p2=P2.P2_NONE,
data=chunk,
)
if temp_response.status != 0x9000:
raise ExceptionRAPDU(temp_response.status)
with self.backend.exchange_async(
cla=CLA,
ins=InsType.DEPLOY_MODULE,
p1=P1.P1_DEPLOY_MODULE_SOURCE,
p2=P2.P2_NONE,
data=last_chunk,
) as response:
yield response

def get_async_response(self) -> Optional[RAPDU]:
return self.backend.last_async_response
Binary file added tests/snapshots/nanosp/test_deploy_module/00000.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/snapshots/nanosp/test_deploy_module/00001.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/snapshots/nanosp/test_deploy_module/00002.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/snapshots/nanosp/test_deploy_module/00003.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/snapshots/nanosp/test_deploy_module/00004.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/snapshots/nanosp/test_deploy_module/00005.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/snapshots/nanox/test_deploy_module/00000.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/snapshots/nanox/test_deploy_module/00001.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/snapshots/nanox/test_deploy_module/00002.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/snapshots/nanox/test_deploy_module/00003.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/snapshots/nanox/test_deploy_module/00004.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/snapshots/nanox/test_deploy_module/00005.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 34 additions & 0 deletions tests/test_deploy_module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import pytest

from application_client.boilerplate_command_sender import (
BoilerplateCommandSender,
Errors,
)
from application_client.boilerplate_response_unpacker import (
unpack_get_public_key_response,
)
from ragger.bip import calculate_public_key_and_chaincode, CurveChoice
from ragger.error import ExceptionRAPDU
from ragger.navigator import NavInsID, NavIns
from ragger.firmware import Firmware
from utils import navigate_until_text_and_compare, instructions_builder


@pytest.mark.active_test_scope
def test_deploy_module(
backend, firmware, navigator, test_name, default_screenshot_path
):
client = BoilerplateCommandSender(backend)
path = "m/1105/0/0/0/0/2/0/0"
header_and_type = bytes.fromhex(
"20a845815bd43a1999e90fbf971537a70392eb38f89e6bd32b3dd70e1a9551d7000000000000000a0000000000000064000000290000000063de5da700"
)
version = 1
source = b"source"

with client.deploy_module(
path=path, header_and_type=header_and_type, version=version, source=source
):
navigate_until_text_and_compare(
firmware, navigator, "Sign", default_screenshot_path, test_name
)
Loading