From dbaeb6c4436606e137351e3134426a5bd8b024d4 Mon Sep 17 00:00:00 2001 From: abenso Date: Fri, 30 Aug 2024 20:02:20 -0300 Subject: [PATCH] wip --- app/src/apdu_handler_legacy.c | 135 +++++++++++++++++++- tests_zemu/package.json | 2 +- tests_zemu/tests/legacy.test.ts | 10 +- tests_zemu/tests/testscases/transactions.ts | 3 +- tests_zemu/tests/transactions.test.ts | 6 +- 5 files changed, 140 insertions(+), 16 deletions(-) diff --git a/app/src/apdu_handler_legacy.c b/app/src/apdu_handler_legacy.c index b4f2604..3a06e02 100644 --- a/app/src/apdu_handler_legacy.c +++ b/app/src/apdu_handler_legacy.c @@ -55,7 +55,7 @@ void legacy_app_reply_address() { io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, action_addrResponseLen + 2); } -void legacy_extractHDPath(uint8_t *buffer, uint32_t rx, uint32_t offset) { +void legacy_extractHDPath(uint8_t *buffer, uint32_t rx, uint32_t offset, bool check_len) { if (rx < offset) { THROW(APDU_CODE_WRONG_LENGTH); } @@ -68,8 +68,10 @@ void legacy_extractHDPath(uint8_t *buffer, uint32_t rx, uint32_t offset) { ZEMU_LOGF(50, "hdPathLen: %d\n", hdPathLen); ZEMU_LOGF(50, "offset_hdpath_data: %d\n", offset_hdpath_data); - if (rx - offset_hdpath_data != hdPathLen) { - THROW(APDU_CODE_WRONG_LENGTH); + if (check_len) { + if (rx - offset_hdpath_data != hdPathLen) { + THROW(APDU_CODE_WRONG_LENGTH); + } } MEMCPY(hdPath, buffer + offset_hdpath_data, hdPathLen); @@ -114,7 +116,7 @@ uint32_t legacy_check_request(volatile uint32_t *tx) { } // get hdpath - legacy_extractHDPath(tx_buffer, tx_buffer_length, payload_length); + legacy_extractHDPath(tx_buffer, tx_buffer_length, payload_length, true); // verify sizes if (tx_buffer_length != hdpath_length + payload_length) { @@ -127,8 +129,22 @@ uint32_t legacy_check_request(volatile uint32_t *tx) { return tx_buffer_length - hdpath_length; } +void legacy_append_data(uint8_t *buffer, uint32_t len) { + uint32_t added = tx_append(buffer, len); + + char print[200] = {0}; + array_to_hexstr(print, sizeof(print), buffer, len); + ZEMU_LOGF(200, "legacy_append_data: %s\n", print); + + if (added != len) { + tx_reset(); + tx_initialized = false; + THROW(APDU_CODE_OUTPUT_BUFFER_TOO_SMALL); + } +} + void legacy_handleGetAddr(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx, const uint8_t requireConfirmation) { - legacy_extractHDPath(G_io_apdu_buffer, rx, LEGACY_OFFSET_HDPATH_LEN); + legacy_extractHDPath(G_io_apdu_buffer, rx, LEGACY_OFFSET_HDPATH_LEN,true); zxerr_t zxerr = app_fill_address(); if (zxerr != zxerr_ok) { @@ -178,6 +194,101 @@ bool legacy_process_chunk(__Z_UNUSED volatile uint32_t *tx, uint32_t rx, bool ha tx_reset(); tx_initialized = true; } + + // TODO: use legacy_append_data + uint32_t added = tx_append(&(G_io_apdu_buffer[offset]), payload_size); + if (added != payload_size) { + tx_reset(); + tx_initialized = false; + THROW(APDU_CODE_OUTPUT_BUFFER_TOO_SMALL); + } + + // Check if the end of the chunk is reached + if ((rx < LEGACY_CHUNK_SIZE + LEGACY_HEADER_LENGTH) || legacy_check_end_of_chunk()) { + tx_initialized = false; + return true; + } + + return false; +} + +bool legacy_process_transfer_chunk(__Z_UNUSED volatile uint32_t *tx, uint32_t rx) { + if (rx < LEGACY_HEADER_LENGTH) { + tx_initialized = false; + THROW(APDU_CODE_WRONG_LENGTH); + } + + if (!tx_initialized) { + // get hdpath + legacy_extractHDPath(G_io_apdu_buffer, LEGACY_OFFSET_HDPATH_LEN + 1, LEGACY_OFFSET_HDPATH_LEN, false); + + tx_initialize(); + tx_reset(); + tx_initialized = true; + } + + + ZEMU_LOGF(50, "rx: %d\n", rx); + ZEMU_LOGF(50, "hdpath_length: %d\n", hdpath_length); + uint8_t payload_qty = G_io_apdu_buffer[hdpath_length + LEGACY_OFFSET_HDPATH_LEN]; + ZEMU_LOGF(50, "payload_qty: %d\n", payload_qty); + + uint32_t bytes_read = 0; + uint32_t offset = hdpath_length + LEGACY_OFFSET_HDPATH_LEN; + uint32_t payload_size = 1; + legacy_append_data(&G_io_apdu_buffer[offset], payload_size); + + offset += payload_size; + payload_size = G_io_apdu_buffer[offset]; + ZEMU_LOGF(50, "payload_size: %d\n", payload_size); + legacy_append_data(&G_io_apdu_buffer[offset], payload_size + 1); + + offset += payload_size + 1; + payload_size = G_io_apdu_buffer[offset]; + ZEMU_LOGF(50, "payload_size: %d\n", payload_size); + legacy_append_data(&G_io_apdu_buffer[offset], payload_size + 1); + + offset += payload_size + 1; + payload_size = G_io_apdu_buffer[offset]; + ZEMU_LOGF(50, "payload_size: %d\n", payload_size); + legacy_append_data(&G_io_apdu_buffer[offset], payload_size + 1); + + offset += payload_size + 1; + payload_size = G_io_apdu_buffer[offset]; + ZEMU_LOGF(50, "payload_size: %d\n", payload_size); + legacy_append_data(&G_io_apdu_buffer[offset], payload_size + 1); + + + offset += payload_size + 1; + payload_size = G_io_apdu_buffer[offset]; + ZEMU_LOGF(50, "payload_size: %d\n", payload_size); + legacy_append_data(&G_io_apdu_buffer[offset], payload_size + 1); + + offset += payload_size + 1; + payload_size = G_io_apdu_buffer[offset]; + ZEMU_LOGF(50, "payload_size: %d\n", payload_size); + legacy_append_data(&G_io_apdu_buffer[offset], payload_size + 1); + + offset += payload_size + 1; + payload_size = G_io_apdu_buffer[offset]; + ZEMU_LOGF(50, "payload_size: %d\n", payload_size); + legacy_append_data(&G_io_apdu_buffer[offset], payload_size + 1); + + offset += payload_size + 1; + payload_size = G_io_apdu_buffer[offset]; + ZEMU_LOGF(50, "payload_size: %d\n", payload_size); + legacy_append_data(&G_io_apdu_buffer[offset], payload_size + 1); + + +// 00100000a6052c0000807202008000000080000000000000000000 +// 4038333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930 +// 0130 +// 09746573746e65743034 +// 04312e3233 +// 00 +// 00 +// 06312e30652d36 +// 04323330300a3136363536343738313001301e323032322d31302d31332030373a35363a35302e3839333235372055544303363030 uint32_t added = tx_append(&(G_io_apdu_buffer[offset]), payload_size); if (added != payload_size) { @@ -244,9 +355,11 @@ void legacy_handleSignHash(volatile uint32_t *flags, volatile uint32_t *tx, uint *flags |= IO_ASYNCH_REPLY; } +// bytes: | 1 | 1 | 1 | 1 | 1 | 4*hdpath_qty | n | +// data: | CLA | INS | P1 | P2 | hdpath_qty | hdpath_data | payload | void legacy_handleSignTransferTx(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { zemu_log("handleSignLegacyTransferTx\n"); - if (!legacy_process_chunk(tx, rx, false, 32)) { + if (!legacy_process_transfer_chunk(tx, rx)) { THROW(APDU_CODE_OK); } @@ -266,3 +379,13 @@ void legacy_handleSignTransferTx(volatile uint32_t *flags, volatile uint32_t *tx view_review_show(REVIEW_TXN); *flags |= IO_ASYNCH_REPLY; } + +// 00100000a6052c0000807202008000000080000000000000000000 +// 4038333933346330663962303035663337386261333532306639646561393532666230613930653561613336663162356666383337643962333063343731373930 +// 0130 +// 09746573746e65743034 +// 04312e3233 +// 00 +// 00 +// 06312e30652d36 +// 04323330300a3136363536343738313001301e323032322d31302d31332030373a35363a35302e3839333235372055544303363030 \ No newline at end of file diff --git a/tests_zemu/package.json b/tests_zemu/package.json index 75972e0..6bccba7 100644 --- a/tests_zemu/package.json +++ b/tests_zemu/package.json @@ -53,6 +53,6 @@ "ts-jest": "^29.2.3", "ts-node": "^10.9.2", "typescript": "^5.5.4", - "hw-app-kda": "link:hw-app-kda" + "hw-app-kda": "git+https://github.com/obsidiansystems/hw-app-kda" } } diff --git a/tests_zemu/tests/legacy.test.ts b/tests_zemu/tests/legacy.test.ts index 0b2e99a..efd5362 100644 --- a/tests_zemu/tests/legacy.test.ts +++ b/tests_zemu/tests/legacy.test.ts @@ -23,7 +23,6 @@ import { JSON_TEST_CASES } from './testscases/json' import { HASH_TEST_CASES } from './testscases/hash' import { TRANSACTIONS_TEST_CASES } from './testscases/transactions' import { APDU_TEST_CASES } from './testscases/legacy_apdu' - // @ts-expect-error import ed25519 from 'ed25519-supercop' @@ -106,7 +105,7 @@ test.concurrent.each(models)('legacy show address - reject', async function (m) }) describe.each(JSON_TEST_CASES)('Tx transactions', function (data) { - test.only.each(models)('sign json', async function (m) { + test.concurrent.each(models)('sign json', async function (m) { const sim = new Zemu(m.path) try { await sim.start({ ...defaultOptions, model: m.name }) @@ -183,18 +182,19 @@ describe.each(HASH_TEST_CASES)('Hash transactions', function (data) { }) describe.each(TRANSACTIONS_TEST_CASES)('Tx transactions', function (data) { - test.concurrent.each(models)('sign', async function (m) { + test.only.each(models)('sign', async function (m) { const sim = new Zemu(m.path) try { await sim.start({ ...defaultOptions, model: m.name }) const app = new Kda(sim.getTransport()); - const responseAddr = await app.getPublicKey(data.path) + const responseAddr = await app.getPublicKey(data.txParams.path) const pubKey = responseAddr.publicKey console.log(pubKey) + // do not wait here... we need to navigate - const signatureRequest = app.signTransferTx(data.path, data) + let signatureRequest = await app["signTransferTx"](data.txParams); // // Wait until we are not in the main menu // await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot()) diff --git a/tests_zemu/tests/testscases/transactions.ts b/tests_zemu/tests/testscases/transactions.ts index 90847d4..9c16581 100644 --- a/tests_zemu/tests/testscases/transactions.ts +++ b/tests_zemu/tests/testscases/transactions.ts @@ -1,11 +1,12 @@ import { PATH } from '../common' import { TransferTxType } from '@zondax/ledger-kadena' +import Kda from "hw-app-kda"; export const TRANSACTIONS_TEST_CASES = [ { name: 'transfer_1', - path: PATH, txParams: { + path: PATH, recipient: '83934c0f9b005f378ba3520f9dea952fb0a90e5aa36f1b5ff837d9b30c471790', amount: "1.23", network: "testnet04", diff --git a/tests_zemu/tests/transactions.test.ts b/tests_zemu/tests/transactions.test.ts index aa05f88..403c24d 100644 --- a/tests_zemu/tests/transactions.test.ts +++ b/tests_zemu/tests/transactions.test.ts @@ -78,11 +78,11 @@ describe.each(TRANSACTIONS_TEST_CASES)('Tx transactions', function (data) { await sim.start({ ...defaultOptions, model: m.name }) const app = new KadenaApp(sim.getTransport()) - const responseAddr = await app.getAddressAndPubKey(data.path) + const responseAddr = await app.getAddressAndPubKey(data.txParams.path) const pubKey = responseAddr.pubkey // do not wait here... we need to navigate - const signatureRequest = app.signTransferTx(data.path, data.txParams) + const signatureRequest = app.signTransferTx(data.txParams.path, data.txParams) // // Wait until we are not in the main menu await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot()) @@ -91,7 +91,7 @@ describe.each(TRANSACTIONS_TEST_CASES)('Tx transactions', function (data) { const signatureResponse = await signatureRequest const context = blake2bInit(32) - blake2bUpdate(context, Buffer.from(data.blob)) + //blake2bUpdate(context, Buffer.from(data.blob)) const hash = Buffer.from(blake2bFinal(context)) // Now verify the signature