diff --git a/app/src/addr.c b/app/src/addr.c index 47278b5..abb356a 100644 --- a/app/src/addr.c +++ b/app/src/addr.c @@ -84,7 +84,7 @@ zxerr_t addr_getItem(int8_t displayIdx, case addr_secp256k1: { snprintf(outKey, outKeyLen, "BIP44 Path"); - bip32_to_str(buffer, sizeof(buffer), hdPath.secp256k1_path, HDPATH_LEN_BIP44); + bip32_to_str(buffer, sizeof(buffer), hdPath.secp256k1_path, hdPath.pathLen); pageString(outVal, outValLen, buffer, pageIdx, pageCount); return zxerr_ok; diff --git a/app/src/apdu_handler.c b/app/src/apdu_handler.c index a19a69a..0b1031a 100644 --- a/app/src/apdu_handler.c +++ b/app/src/apdu_handler.c @@ -63,7 +63,13 @@ void handleApdu(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { case INS_GET_ADDR_SECP256K1: { CHECK_PIN_VALIDATED() - handleGetAddrSecp256K1(flags, tx, rx); + handleGetAddrSecp256K1(flags, tx, rx, false); + break; + } + + case INS_GET_UNIFIED_ADDR_SECP256K1: { + CHECK_PIN_VALIDATED() + handleGetAddrSecp256K1(flags, tx, rx, true); break; } diff --git a/app/src/coin.h b/app/src/coin.h index 7cae012..ed1baa4 100644 --- a/app/src/coin.h +++ b/app/src/coin.h @@ -71,6 +71,7 @@ extern "C" { #define INS_GET_ADDR_SAPLING_DIV 0x10 #define INS_GET_ADDR_SAPLING 0x11 #define INS_SIGN_SAPLING 0x12 +#define INS_GET_UNIFIED_ADDR_SECP256K1 0x13 #define INS_GET_DIV_LIST 0x09 @@ -107,6 +108,7 @@ typedef enum { key_ivk = 0, key_ovk = 1, key_fvk = 2, nf = 3, key_dfvk = 4 } key #define HDPATH_LEN_BIP44 5 #define HDPATH_LEN_SAPLING 3 +#define HDPATH_LEN_UNIFIED 3 typedef enum { addr_not_set = 0, @@ -120,6 +122,7 @@ typedef struct { union { struct { uint32_t secp256k1_path[HDPATH_LEN_MAX]; + uint8_t pathLen; }; struct { uint32_t sapling_path[3]; diff --git a/app/src/crypto.c b/app/src/crypto.c index 8b090e9..5fb7f47 100644 --- a/app/src/crypto.c +++ b/app/src/crypto.c @@ -127,7 +127,7 @@ static zxerr_t crypto_extractPublicKey(uint8_t *pubKey, uint16_t pubKeyLen) { uint8_t privateKeyData[64] = {0}; zxerr_t error = zxerr_unknown; - CATCH_CXERROR(os_derive_bip32_no_throw(CX_CURVE_256K1, hdPath.secp256k1_path, HDPATH_LEN_BIP44, privateKeyData, NULL)); + CATCH_CXERROR(os_derive_bip32_no_throw(CX_CURVE_256K1, hdPath.secp256k1_path, hdPath.pathLen, privateKeyData, NULL)); CATCH_CXERROR(cx_ecfp_init_private_key_no_throw(CX_CURVE_256K1, privateKeyData, SK_SECP256K1_SIZE, &cx_privateKey)); io_seproxyhal_io_heartbeat(); CATCH_CXERROR(cx_ecfp_init_public_key_no_throw(CX_CURVE_256K1, NULL, 0, &cx_publicKey)); diff --git a/app/src/handlers/handler_addr.h b/app/src/handlers/handler_addr.h index c052e1c..0bd915b 100644 --- a/app/src/handlers/handler_addr.h +++ b/app/src/handlers/handler_addr.h @@ -34,7 +34,7 @@ #include "view_internal.h" #include "zxmacros.h" -__Z_INLINE void handleGetAddrSecp256K1(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { +__Z_INLINE void handleGetAddrSecp256K1(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx, bool isUnified) { ZEMU_LOGF(100, "----[handleGetAddrSecp256K1]\n"); *tx = 0; @@ -43,7 +43,7 @@ __Z_INLINE void handleGetAddrSecp256K1(volatile uint32_t *flags, volatile uint32 THROW(APDU_CODE_COMMAND_NOT_ALLOWED); } - extractHDPathTransparent(rx, OFFSET_DATA); + extractHDPathTransparent(rx, OFFSET_DATA, isUnified); uint8_t requireConfirmation = G_io_apdu_buffer[OFFSET_P1]; uint16_t replyLen = 0; diff --git a/app/src/handlers/handler_path.h b/app/src/handlers/handler_path.h index 110a653..f0ea87a 100644 --- a/app/src/handlers/handler_path.h +++ b/app/src/handlers/handler_path.h @@ -33,12 +33,18 @@ #include "zxmacros.h" __Z_INLINE void extractHDPathTransparent(uint32_t rx, uint32_t offset) { - if ((rx - offset) < sizeof(uint32_t) * HDPATH_LEN_BIP44) { + uint8_t pathLen = HDPATH_LEN_BIP44; + if(isUnified){ + pathLen = HDPATH_LEN_UNIFIED; + } + + if ((rx - offset) < sizeof(uint32_t) * pathLen) { THROW(APDU_CODE_WRONG_LENGTH); } hdPath.addressKind = addr_not_set; - MEMCPY(hdPath.secp256k1_path, G_io_apdu_buffer + offset, sizeof(uint32_t) * HDPATH_LEN_BIP44); + MEMCPY(hdPath.secp256k1_path, G_io_apdu_buffer + offset, sizeof(uint32_t) * pathLen); + hdPath.pathLen = pathLen; const bool mainnet = hdPath.secp256k1_path[0] == HDPATH_0_DEFAULT && hdPath.secp256k1_path[1] == HDPATH_1_DEFAULT; const bool testnet = hdPath.secp256k1_path[0] == HDPATH_0_TESTNET && hdPath.secp256k1_path[1] == HDPATH_1_TESTNET; @@ -47,6 +53,14 @@ __Z_INLINE void extractHDPathTransparent(uint32_t rx, uint32_t offset) { THROW(APDU_CODE_DATA_INVALID); } + if(isUnified){ + // Validate data + if ((hdPath.secp256k1_path[2] & MASK_HARDENED) == 0) { + ZEMU_LOGF(100, "error validating hardening\n"); + THROW(APDU_CODE_DATA_INVALID); + } + } + hdPath.addressKind = addr_secp256k1; }