Browse Source

Add support for two byte versions (Zcash)

stream-output
BTChip 8 years ago
parent
commit
e522ccec88
  1. 17
      Makefile
  2. 7
      include/btchip_context.h
  3. 9
      include/btchip_filesystem.h
  4. 4
      include/btchip_helpers.h
  5. 3
      src/btchip_apdu_get_coin_version.c
  6. 20
      src/btchip_apdu_set_alternate_coin_version.c
  7. 1
      src/btchip_apdu_setup.c
  8. 1
      src/btchip_context.c
  9. 35
      src/btchip_helpers.c
  10. 49
      src/main.c

17
Makefile

@ -60,7 +60,7 @@ DEFINES += OS_IO_SEPROXYHAL IO_SEPROXYHAL_BUFFER_SIZE_B=300
DEFINES += HAVE_BAGL HAVE_PRINTF
DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=6 IO_HID_EP_LENGTH=64 HAVE_USB_APDU
DEFINES += LEDGER_MAJOR_VERSION=1 LEDGER_MINOR_VERSION=1 LEDGER_PATCH_VERSION=0 TCS_LOADER_PATCH_VERSION=0
DEFINES += LEDGER_MAJOR_VERSION=1 LEDGER_MINOR_VERSION=1 LEDGER_PATCH_VERSION=1 TCS_LOADER_PATCH_VERSION=0
ifndef COIN
COIN = bitcoin
@ -73,28 +73,33 @@ APPNAME ="Bitcoin"
ICONNAME=icon_bitcoin.gif
else ifeq ($(COIN), bitcoin)
# Bitcoin mainnet
DEFINES += BTCHIP_P2PKH_VERSION=0 BTCHIP_P2SH_VERSION=5 BTCHIP_COINID=\"Bitcoin\" BTCHIP_COINID_SHORT=\"BTC\" COIN_BITCOIN
DEFINES += BTCHIP_P2PKH_VERSION=0 BTCHIP_P2SH_VERSION=5 BTCHIP_COIN_FAMILY=1 BTCHIP_COINID=\"Bitcoin\" BTCHIP_COINID_SHORT=\"BTC\" COIN_BITCOIN
APPNAME ="Bitcoin"
ICONNAME=icon_bitcoin.gif
SIGNATURE=3045022100d7a784ba23f5eac9c82a8c132274d62de921039ccd6cc6ac24614a35329d20ae0220759dc74de0b509608a0e0d82e0ae5d0a07028c7411bf7e3368e7fe290360b274
else ifeq ($(COIN), litecoin)
# Litecoin
DEFINES += BTCHIP_P2PKH_VERSION=48 BTCHIP_P2SH_VERSION=5 BTCHIP_COINID=\"Litecoin\" BTCHIP_COINID_SHORT=\"LTC\" COIN_LITECOIN
DEFINES += BTCHIP_P2PKH_VERSION=48 BTCHIP_P2SH_VERSION=5 BTCHIP_COIN_FAMILY=1 BTCHIP_COINID=\"Litecoin\" BTCHIP_COINID_SHORT=\"LTC\" COIN_LITECOIN
APPNAME ="Litecoin"
ICONNAME=icon_litecoin.gif
SIGNATURE=3045022100f2b8109a13ac96dfd78403647bbb07e654579ea4b1b80b9bff7eb0ea5b083c6002204b1ae026ff40dbc19fcaef86e2d1d189241d7bc0d23ee95dc8718e84fe041f5d
else ifeq ($(COIN), dogecoin)
# Doge
DEFINES += BTCHIP_P2PKH_VERSION=30 BTCHIP_P2SH_VERSION=22 BTCHIP_COINID=\"Dogecoin\" BTCHIP_COINID_SHORT=\"DOGE\" COIN_DOGE
DEFINES += BTCHIP_P2PKH_VERSION=30 BTCHIP_P2SH_VERSION=22 BTCHIP_COIN_FAMILY=1 BTCHIP_COINID=\"Dogecoin\" BTCHIP_COINID_SHORT=\"DOGE\" COIN_DOGE
APPNAME ="Dogecoin"
ICONNAME=icon_doge.gif
else ifeq ($(COIN), dash)
# Dash
DEFINES += BTCHIP_P2PKH_VERSION=76 BTCHIP_P2SH_VERSION=16 BTCHIP_COINID=\"DarkCoin\" BTCHIP_COINID_SHORT=\"DASH\" COIN_DASH
DEFINES += BTCHIP_P2PKH_VERSION=76 BTCHIP_P2SH_VERSION=16 BTCHIP_COIN_FAMILY=1 BTCHIP_COINID=\"DarkCoin\" BTCHIP_COINID_SHORT=\"DASH\" COIN_DASH
APPNAME ="Dash"
ICONNAME=icon_dash.gif
else ifeq ($(COIN), zcash)
# ZCash
DEFINES += BTCHIP_P2PKH_VERSION=7352 BTCHIP_P2SH_VERSION=7357 BTCHIP_COIN_FAMILY=1 BTCHIP_COINID=\"Zcash\" BTCHIP_COINID_SHORT=\"ZEC\" COIN_ZCASH
APPNAME ="Zcash"
ICONNAME=icon_zcash.gif
else
$(error Unsupported COIN - use bitcoin-testnet, bitcoin, litecoin, dogecoin, dash)
$(error Unsupported COIN - use bitcoin-testnet, bitcoin, litecoin, dogecoin, dash, zcash)
endif
##############

7
include/btchip_context.h

@ -142,9 +142,11 @@ struct btchip_context_s {
btchip_transaction_context_t transactionContext;
/** Current Pay To Address version */
unsigned char payToAddressVersion;
unsigned short payToAddressVersion;
/** Current Pay To Script Hash version */
unsigned char payToScriptHashVersion;
unsigned short payToScriptHashVersion;
/** Current coin family */
unsigned char coinFamily;
/** Current Coin ID */
unsigned char coinId[MAX_COIN_ID];
/** Current short Coin ID */
@ -202,7 +204,6 @@ struct btchip_context_s {
// was previously in NVRAM
btchip_transaction_summary_t transactionSummary;
unsigned short hashedMessageLength;
union {

9
include/btchip_filesystem.h

@ -31,12 +31,17 @@ enum btchip_supported_modes_e {
BTCHIP_SUPPORTED_MODE_DEVELOPER = 0x08
};
enum btchip_family_e {
BTCHIP_FAMILY_BITCOIN = 0x01,
};
struct btchip_config_s {
secu8 supportedModes;
secu8 operationMode;
unsigned char options;
unsigned char payToAddressVersion;
unsigned char payToScriptHashVersion;
unsigned short payToAddressVersion;
unsigned short payToScriptHashVersion;
unsigned char coinFamily;
/** Current Coin ID */
unsigned char coinId[MAX_COIN_ID];
/** Current short Coin ID */

4
include/btchip_helpers.h

@ -49,7 +49,7 @@ void btchip_public_key_hash160(unsigned char WIDE *in, unsigned short inlen,
unsigned char *out);
unsigned short btchip_public_key_to_encoded_base58(
unsigned char WIDE *in, unsigned short inlen, unsigned char *out,
unsigned short outlen, unsigned char version, unsigned char alreadyHashed);
unsigned short outlen, unsigned short version, unsigned char alreadyHashed);
unsigned short btchip_decode_base58_address(unsigned char WIDE *in,
unsigned short inlen,
@ -72,8 +72,6 @@ void btchip_signverify_finalhash(void WIDE *keyContext, unsigned char sign,
void btchip_transaction_add_output(unsigned char *hash160Address,
unsigned char *amount, unsigned char p2sh);
unsigned char btchip_address_isP2SH(unsigned char version);
unsigned char btchip_address_isValid(unsigned char version);
unsigned char btchip_rng_u8_modulo(unsigned char modulo);
unsigned char btchip_secure_memcmp(const void WIDE *buf1, const void WIDE *buf2,
unsigned short length);

3
src/btchip_apdu_get_coin_version.c

@ -31,8 +31,11 @@ unsigned short btchip_apdu_get_coin_version() {
return BTCHIP_SW_CONDITIONS_OF_USE_NOT_SATISFIED;
}
G_io_apdu_buffer[offset++] = btchip_context_D.payToAddressVersion >> 8;
G_io_apdu_buffer[offset++] = btchip_context_D.payToAddressVersion;
G_io_apdu_buffer[offset++] = btchip_context_D.payToScriptHashVersion >> 8;
G_io_apdu_buffer[offset++] = btchip_context_D.payToScriptHashVersion;
G_io_apdu_buffer[offset++] = btchip_context_D.coinFamily;
G_io_apdu_buffer[offset++] = btchip_context_D.coinIdLength;
os_memmove(G_io_apdu_buffer + offset, btchip_context_D.coinId,
btchip_context_D.coinIdLength);

20
src/btchip_apdu_set_alternate_coin_version.c

@ -29,12 +29,12 @@ unsigned short btchip_apdu_set_alternate_coin_version() {
}
if (p1 == P1_VERSION_ONLY) {
if (G_io_apdu_buffer[ISO_OFFSET_LC] != 0x02) {
if (G_io_apdu_buffer[ISO_OFFSET_LC] != 0x05) {
return BTCHIP_SW_INCORRECT_LENGTH;
}
} else {
if (G_io_apdu_buffer[ISO_OFFSET_LC] >
4 + MAX_COIN_ID + MAX_SHORT_COIN_ID) {
7 + MAX_COIN_ID + MAX_SHORT_COIN_ID) {
return BTCHIP_SW_INCORRECT_LENGTH;
}
}
@ -50,8 +50,20 @@ unsigned short btchip_apdu_set_alternate_coin_version() {
return BTCHIP_SW_SECURITY_STATUS_NOT_SATISFIED;
}
btchip_context_D.payToAddressVersion = G_io_apdu_buffer[offset++];
btchip_context_D.payToScriptHashVersion = G_io_apdu_buffer[offset++];
switch (G_io_apdu_buffer[offset + 4]) {
case BTCHIP_FAMILY_BITCOIN:
break;
default:
return BTCHIP_SW_INCORRECT_DATA;
}
btchip_context_D.payToAddressVersion =
(G_io_apdu_buffer[offset] << 8) | (G_io_apdu_buffer[offset + 1]);
offset += 2;
btchip_context_D.payToScriptHashVersion =
(G_io_apdu_buffer[offset] << 8) | (G_io_apdu_buffer[offset + 1]);
offset += 2;
btchip_context_D.coinFamily = G_io_apdu_buffer[offset++];
if (p1 == P1_VERSION_COINID) {
uint8_t coinIdLength = G_io_apdu_buffer[offset];
uint8_t shortCoinIdLength = G_io_apdu_buffer[offset + 1 + coinIdLength];

1
src/btchip_apdu_setup.c

@ -36,6 +36,7 @@ void btchip_autosetup() {
SB_SET(config.operationMode, BTCHIP_MODE_WALLET);
config.payToAddressVersion = BTCHIP_P2PKH_VERSION;
config.payToScriptHashVersion = BTCHIP_P2SH_VERSION;
config.coinFamily = BTCHIP_COIN_FAMILY;
config.coinIdLength = strlen(BTCHIP_COINID);
os_memmove(config.coinId, BTCHIP_COINID, config.coinIdLength);
config.shortCoinIdLength = strlen(BTCHIP_COINID_SHORT);

1
src/btchip_context.c

@ -44,6 +44,7 @@ void btchip_context_init() {
N_btchip.bkp.config.payToAddressVersion;
btchip_context_D.payToScriptHashVersion =
N_btchip.bkp.config.payToScriptHashVersion;
btchip_context_D.coinFamily = N_btchip.bkp.config.coinFamily;
btchip_context_D.coinIdLength = N_btchip.bkp.config.coinIdLength;
os_memmove(btchip_context_D.coinId, N_btchip.bkp.config.coinId,
N_btchip.bkp.config.coinIdLength);

35
src/btchip_helpers.c

@ -146,28 +146,35 @@ void btchip_public_key_hash160(unsigned char WIDE *in, unsigned short inlen,
unsigned short btchip_public_key_to_encoded_base58(
unsigned char WIDE *in, unsigned short inlen, unsigned char *out,
unsigned short outlen, unsigned char version, unsigned char alreadyHashed) {
unsigned char tmpBuffer[25];
unsigned short outlen, unsigned short version,
unsigned char alreadyHashed) {
unsigned char tmpBuffer[26];
unsigned char checksumBuffer[32];
cx_sha256_t hash;
unsigned char versionSize = (version > 255 ? 2 : 1);
if (!alreadyHashed) {
L_DEBUG_BUF(("To hash\n", in, inlen));
btchip_public_key_hash160(in, inlen, tmpBuffer + 1);
L_DEBUG_BUF(("Hash160\n", (tmpBuffer + 1), 20));
tmpBuffer[0] = version;
btchip_public_key_hash160(in, inlen, tmpBuffer + versionSize);
L_DEBUG_BUF(("Hash160\n", (tmpBuffer + versionSize), 20));
if (version > 255) {
tmpBuffer[0] = (version >> 8);
tmpBuffer[1] = version;
} else {
tmpBuffer[0] = version;
}
} else {
os_memmove(tmpBuffer, in, 21);
os_memmove(tmpBuffer, in, 20 + versionSize);
}
cx_sha256_init(&hash);
cx_hash(&hash.header, CX_LAST, tmpBuffer, 21, checksumBuffer);
cx_hash(&hash.header, CX_LAST, tmpBuffer, 20 + versionSize, checksumBuffer);
cx_sha256_init(&hash);
cx_hash(&hash.header, CX_LAST, checksumBuffer, 32, checksumBuffer);
L_DEBUG_BUF(("Checksum\n", checksumBuffer, 4));
os_memmove(tmpBuffer + 21, checksumBuffer, 4);
return btchip_encode_base58(tmpBuffer, sizeof(tmpBuffer), out, outlen);
os_memmove(tmpBuffer + 20 + versionSize, checksumBuffer, 4);
return btchip_encode_base58(tmpBuffer, 24 + versionSize, out, outlen);
}
void btchip_swap_bytes(unsigned char *target, unsigned char *source,
@ -246,16 +253,6 @@ void btchip_transaction_add_output(unsigned char *hash160Address,
btchip_context_D.tmp += sizePost;
}
unsigned char btchip_address_isP2SH(unsigned char version) {
return ((btchip_context_D.payToScriptHashVersion != 0) &&
(version == btchip_context_D.payToScriptHashVersion));
}
unsigned char btchip_address_isValid(unsigned char version) {
return ((version == btchip_context_D.payToAddressVersion) ||
btchip_address_isP2SH(version));
}
void btchip_signverify_finalhash(void WIDE *keyContext, unsigned char sign,
unsigned char WIDE *in, unsigned short inlen,
unsigned char *out, unsigned short outlen,

49
src/main.c

@ -989,18 +989,42 @@ unsigned char io_event(unsigned char channel) {
case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT:
if (UX_DISPLAYED()) {
UX_DISPLAYED_:
#ifdef COIN_LITECOIN
#if defined(COIN_LITECOIN) || defined(COIN_DASH) || defined(COIN_DOGE) || \
defined(COIN_ZCASH)
// extra elements per screen, only for idle screen
if (ux.elements == ui_idle_nanos && ui_idle_nanos_state == 0) {
// could be used to perform extra print after an array has been
// displayed
switch (ux.elements_count - ux.elements_current) {
case 0: {
#ifdef COIN_LITECOIN
extern unsigned int const C_icon_litecoin_colors[];
extern unsigned char const C_icon_litecoin_bitmap[];
io_seproxyhal_display_bitmap(12, 9, 14, 14,
C_icon_litecoin_colors, 1,
C_icon_litecoin_bitmap);
#endif
#ifdef COIN_DOGE
extern unsigned int const C_icon_doge_colors[];
extern unsigned char const C_icon_doge_bitmap[];
io_seproxyhal_display_bitmap(12, 9, 14, 14,
C_icon_doge_colors, 1,
C_icon_doge_bitmap);
#endif
#ifdef COIN_ZCASH
extern unsigned int const C_icon_zcash_colors[];
extern unsigned char const C_icon_zcash_bitmap[];
io_seproxyhal_display_bitmap(12, 9, 14, 14,
C_icon_zcash_colors, 1,
C_icon_zcash_bitmap);
#endif
#ifdef COIN_DASH
extern unsigned int const C_icon_dash_colors[];
extern unsigned char const C_icon_dash_bitmap[];
io_seproxyhal_display_bitmap(12, 9, 14, 14,
C_icon_dash_colors, 1,
C_icon_dash_bitmap);
#endif
break;
}
@ -1012,7 +1036,7 @@ unsigned char io_event(unsigned char channel) {
}
ux.elements_current++;
}
#endif // COIN_LITECOIN
#endif // COIN_LITECOIN || COIN_DASH || COIN_DOGE || COIN_ZCASH
;
} else {
UX_DISPLAY_PROCESSED_EVENT();
@ -1129,25 +1153,36 @@ uint8_t prepare_full_output() {
for (i = 0; i < numberOutputs; i++) {
if (!btchip_output_script_is_op_return(btchip_context_D.currentOutput +
offset + 8)) {
unsigned char versionSize;
int addressOffset;
unsigned char address[21];
unsigned char address[22];
unsigned short version;
btchip_swap_bytes(amount, btchip_context_D.currentOutput + offset,
8);
offset += 8;
if (btchip_output_script_is_regular(btchip_context_D.currentOutput +
offset)) {
addressOffset = offset + 4;
address[0] = N_btchip.bkp.config.payToAddressVersion;
version = btchip_context_D.payToAddressVersion;
} else {
addressOffset = offset + 3;
address[0] = N_btchip.bkp.config.payToScriptHashVersion;
version = btchip_context_D.payToScriptHashVersion;
}
if (version > 255) {
versionSize = 2;
address[0] = (version >> 8);
address[1] = version;
} else {
versionSize = 1;
address[0] = version;
}
os_memmove(address + 1,
os_memmove(address + versionSize,
btchip_context_D.currentOutput + addressOffset, 20);
if (currentPos == outputPos) {
unsigned short textSize;
textSize = btchip_public_key_to_encoded_base58(
address, 21, (unsigned char *)tmp, sizeof(tmp), 0, 1);
address, 20 + versionSize, (unsigned char *)tmp,
sizeof(tmp), version, 1);
tmp[textSize] = '\0';
// Prepare address
os_memmove((void *)address1, tmp, 18);

Loading…
Cancel
Save