Skip to content
This repository was archived by the owner on Apr 16, 2019. It is now read-only.

Decred support #274

Merged
merged 10 commits into from
Apr 3, 2018
1 change: 1 addition & 0 deletions firmware/coin_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ def coin_to_struct(coin):
("has_segwit", format_bool(coin["segwit"])),
("has_forkid", format_bool(coin["forkid"] is not None)),
("force_bip143", format_bool(coin["force_bip143"])),
("decred", format_bool(coin["decred"])),
("address_type", format_number(coin["address_type"])),
("address_type_p2sh", format_number(coin["address_type_p2sh"])),
("xpub_magic", format_hex(coin["xpub_magic"])),
Expand Down
75 changes: 0 additions & 75 deletions firmware/coins-gen.py

This file was deleted.

2 changes: 1 addition & 1 deletion firmware/coins.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ bool coinExtractAddressType(const CoinInfo *coin, const char *addr, uint32_t *ad
{
if (!addr) return false;
uint8_t addr_raw[MAX_ADDR_RAW_SIZE];
int len = base58_decode_check(addr, coin->curve->hasher_type, addr_raw, MAX_ADDR_RAW_SIZE);
int len = base58_decode_check(addr, coin->curve->hasher_base58, addr_raw, MAX_ADDR_RAW_SIZE);
if (len >= 21) {
return coinExtractAddressTypeRaw(coin, addr_raw, address_type);
}
Expand Down
1 change: 1 addition & 0 deletions firmware/coins.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ typedef struct _CoinInfo {
bool has_segwit;
bool has_forkid;
bool force_bip143;
bool decred;
// address types > 0xFF represent a two-byte prefix in big-endian order
uint32_t address_type;
uint32_t address_type_p2sh;
Expand Down
28 changes: 14 additions & 14 deletions firmware/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ uint32_t deser_length(const uint8_t *in, uint32_t *out)
int sshMessageSign(HDNode *node, const uint8_t *message, size_t message_len, uint8_t *signature)
{
signature[0] = 0; // prefix: pad with zero, so all signatures are 65 bytes
return hdnode_sign(node, message, message_len, signature + 1, NULL, NULL);
return hdnode_sign(node, message, message_len, HASHER_SHA2, signature + 1, NULL, NULL);
}

int gpgMessageSign(HDNode *node, const uint8_t *message, size_t message_len, uint8_t *signature)
Expand All @@ -101,7 +101,7 @@ int gpgMessageSign(HDNode *node, const uint8_t *message, size_t message_len, uin
const curve_info *ed25519_curve_info = get_curve_by_name(ED25519_NAME);
if (ed25519_curve_info && node->curve == ed25519_curve_info) {
// GPG supports variable size digest for Ed25519 signatures
return hdnode_sign(node, message, message_len, signature + 1, NULL, NULL);
return hdnode_sign(node, message, message_len, 0, signature + 1, NULL, NULL);
} else {
// Ensure 256-bit digest before proceeding
if (message_len != 32) {
Expand All @@ -113,13 +113,13 @@ int gpgMessageSign(HDNode *node, const uint8_t *message, size_t message_len, uin

static void cryptoMessageHash(const CoinInfo *coin, const uint8_t *message, size_t message_len, uint8_t hash[HASHER_DIGEST_LENGTH]) {
Hasher hasher;
hasher_Init(&hasher, coin->curve->hasher_type);
hasher_Init(&hasher, coin->curve->hasher_sign);
hasher_Update(&hasher, (const uint8_t *)coin->signed_message_header, strlen(coin->signed_message_header));
uint8_t varint[5];
uint32_t l = ser_length(message_len, varint);
hasher_Update(&hasher, varint, l);
hasher_Update(&hasher, message, message_len);
hasher_Double(&hasher, hash);
hasher_Final(&hasher, hash);
}

int cryptoMessageSign(const CoinInfo *coin, HDNode *node, InputScriptType script_type, const uint8_t *message, size_t message_len, uint8_t *signature)
Expand Down Expand Up @@ -163,7 +163,7 @@ int cryptoMessageVerify(const CoinInfo *coin, const uint8_t *message, size_t mes

// check if signature verifies the digest and recover the public key
uint8_t pubkey[65];
if (ecdsa_verify_digest_recover(&secp256k1, pubkey, signature + 1, hash, recid) != 0) {
if (ecdsa_verify_digest_recover(coin->curve->params, pubkey, signature + 1, hash, recid) != 0) {
return 3;
}
// convert public key to compressed pubkey if necessary
Expand All @@ -177,17 +177,17 @@ int cryptoMessageVerify(const CoinInfo *coin, const uint8_t *message, size_t mes

// p2pkh
if (signature[0] >= 27 && signature[0] <= 34) {
size_t len = base58_decode_check(address, coin->curve->hasher_type, addr_raw, MAX_ADDR_RAW_SIZE);
ecdsa_get_address_raw(pubkey, coin->address_type, coin->curve->hasher_type, recovered_raw);
size_t len = base58_decode_check(address, coin->curve->hasher_base58, addr_raw, MAX_ADDR_RAW_SIZE);
ecdsa_get_address_raw(pubkey, coin->address_type, coin->curve->hasher_pubkey, recovered_raw);
if (memcmp(recovered_raw, addr_raw, len) != 0
|| len != address_prefix_bytes_len(coin->address_type) + 20) {
return 2;
}
} else
// segwit-in-p2sh
if (signature[0] >= 35 && signature[0] <= 38) {
size_t len = base58_decode_check(address, coin->curve->hasher_type, addr_raw, MAX_ADDR_RAW_SIZE);
ecdsa_get_address_segwit_p2sh_raw(pubkey, coin->address_type_p2sh, coin->curve->hasher_type, recovered_raw);
size_t len = base58_decode_check(address, coin->curve->hasher_base58, addr_raw, MAX_ADDR_RAW_SIZE);
ecdsa_get_address_segwit_p2sh_raw(pubkey, coin->address_type_p2sh, coin->curve->hasher_pubkey, recovered_raw);
if (memcmp(recovered_raw, addr_raw, len) != 0
|| len != address_prefix_bytes_len(coin->address_type_p2sh) + 20) {
return 2;
Expand All @@ -201,7 +201,7 @@ int cryptoMessageVerify(const CoinInfo *coin, const uint8_t *message, size_t mes
|| !segwit_addr_decode(&witver, recovered_raw, &len, coin->bech32_prefix, address)) {
return 4;
}
ecdsa_get_pubkeyhash(pubkey, coin->curve->hasher_type, addr_raw);
ecdsa_get_pubkeyhash(pubkey, coin->curve->hasher_pubkey, addr_raw);
if (memcmp(recovered_raw, addr_raw, len) != 0
|| witver != 0 || len != 20) {
return 2;
Expand Down Expand Up @@ -327,11 +327,11 @@ int cryptoMessageDecrypt(curve_point *nonce, uint8_t *payload, size_t payload_le
}
*/

uint8_t *cryptoHDNodePathToPubkey(const HDNodePathType *hdnodepath)
uint8_t *cryptoHDNodePathToPubkey(const CoinInfo *coin, const HDNodePathType *hdnodepath)
{
if (!hdnodepath->node.has_public_key || hdnodepath->node.public_key.size != 33) return 0;
static HDNode node;
if (hdnode_from_xpub(hdnodepath->node.depth, hdnodepath->node.child_num, hdnodepath->node.chain_code.bytes, hdnodepath->node.public_key.bytes, SECP256K1_NAME, &node) == 0) {
if (hdnode_from_xpub(hdnodepath->node.depth, hdnodepath->node.child_num, hdnodepath->node.chain_code.bytes, hdnodepath->node.public_key.bytes, coin->curve_name, &node) == 0) {
return 0;
}
layoutProgressUpdate(true);
Expand All @@ -344,10 +344,10 @@ uint8_t *cryptoHDNodePathToPubkey(const HDNodePathType *hdnodepath)
return node.public_key;
}

int cryptoMultisigPubkeyIndex(const MultisigRedeemScriptType *multisig, const uint8_t *pubkey)
int cryptoMultisigPubkeyIndex(const CoinInfo *coin, const MultisigRedeemScriptType *multisig, const uint8_t *pubkey)
{
for (size_t i = 0; i < multisig->pubkeys_count; i++) {
const uint8_t *node_pubkey = cryptoHDNodePathToPubkey(&(multisig->pubkeys[i]));
const uint8_t *node_pubkey = cryptoHDNodePathToPubkey(coin, &(multisig->pubkeys[i]));
if (node_pubkey && memcmp(node_pubkey, pubkey, 33) == 0) {
return i;
}
Expand Down
4 changes: 2 additions & 2 deletions firmware/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ int cryptoMessageEncrypt(curve_point *pubkey, const uint8_t *msg, size_t msg_siz
int cryptoMessageDecrypt(curve_point *nonce, uint8_t *payload, size_t payload_len, const uint8_t *hmac, size_t hmac_len, const uint8_t *privkey, uint8_t *msg, size_t *msg_len, bool *display_only, bool *signing, uint8_t *address_raw);
*/

uint8_t *cryptoHDNodePathToPubkey(const HDNodePathType *hdnodepath);
uint8_t *cryptoHDNodePathToPubkey(const CoinInfo *coin, const HDNodePathType *hdnodepath);

int cryptoMultisigPubkeyIndex(const MultisigRedeemScriptType *multisig, const uint8_t *pubkey);
int cryptoMultisigPubkeyIndex(const CoinInfo *coin, const MultisigRedeemScriptType *multisig, const uint8_t *pubkey);

int cryptoMultisigFingerprint(const MultisigRedeemScriptType *multisig, uint8_t *hash);

Expand Down
2 changes: 1 addition & 1 deletion firmware/fsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ void fsm_msgSignTx(SignTx *msg)
const HDNode *node = fsm_getDerivedNode(coin->curve_name, NULL, 0, NULL);
if (!node) return;

signing_init(msg->inputs_count, msg->outputs_count, coin, node, msg->version, msg->lock_time);
signing_init(msg, coin, node);
}

void fsm_msgTxAck(TxAck *msg)
Expand Down
Loading