diff --git a/firmware/stellar.c b/firmware/stellar.c index d60648842..a909f3fa6 100644 --- a/firmware/stellar.c +++ b/firmware/stellar.c @@ -152,10 +152,47 @@ void stellar_signingInit(StellarSignTx *msg) } } +bool stellar_confirmSourceAccount(bool has_source_account, char *str_account) +{ + if (!has_source_account) { + stellar_hashupdate_bool(false); + return true; + } + + // Convert account string to public key bytes + uint8_t bytes[32]; + if (!stellar_getAddressBytes(str_account, bytes)) { + return false; + } + + const char **str_addr_rows = stellar_lineBreakAddress(bytes); + + stellar_layoutTransactionDialog( + _("Op src account OK?"), + NULL, + str_addr_rows[0], + str_addr_rows[1], + str_addr_rows[2] + ); + if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { + stellar_signingAbort(_("User canceled")); + return false; + } + + // Hash: source account + stellar_hashupdate_address(bytes); + + return true; +} + bool stellar_confirmCreateAccountOp(StellarCreateAccountOp *msg) { if (!stellar_signing) return false; - stellar_hashupdate_bool(false); // stellar_hashupdate_address(stellar_activeTx.signing_pubkey); + + if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { + stellar_signingAbort(_("Source account error")); + return false; + } // Hash: operation type stellar_hashupdate_uint32(0); @@ -202,7 +239,11 @@ bool stellar_confirmCreateAccountOp(StellarCreateAccountOp *msg) bool stellar_confirmPaymentOp(StellarPaymentOp *msg) { if (!stellar_signing) return false; - stellar_hashupdate_bool(false); // stellar_hashupdate_address(stellar_activeTx.signing_pubkey); + + if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { + stellar_signingAbort(_("Source account error")); + return false; + } // Hash: operation type stellar_hashupdate_uint32(1); @@ -259,7 +300,11 @@ bool stellar_confirmPaymentOp(StellarPaymentOp *msg) bool stellar_confirmPathPaymentOp(StellarPathPaymentOp *msg) { if (!stellar_signing) return false; - stellar_hashupdate_bool(false); // stellar_hashupdate_address(stellar_activeTx.signing_pubkey); + + if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { + stellar_signingAbort(_("Source account error")); + return false; + } // Hash: operation type stellar_hashupdate_uint32(2); @@ -355,7 +400,11 @@ bool stellar_confirmPathPaymentOp(StellarPathPaymentOp *msg) bool stellar_confirmManageOfferOp(StellarManageOfferOp *msg) { if (!stellar_signing) return false; - stellar_hashupdate_bool(false); // stellar_hashupdate_address(stellar_activeTx.signing_pubkey); + + if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { + stellar_signingAbort(_("Source account error")); + return false; + } // Hash: operation type stellar_hashupdate_uint32(3); @@ -441,7 +490,11 @@ bool stellar_confirmManageOfferOp(StellarManageOfferOp *msg) bool stellar_confirmCreatePassiveOfferOp(StellarCreatePassiveOfferOp *msg) { if (!stellar_signing) return false; - stellar_hashupdate_bool(false); // stellar_hashupdate_address(stellar_activeTx.signing_pubkey); + + if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { + stellar_signingAbort(_("Source account error")); + return false; + } // Hash: operation type stellar_hashupdate_uint32(4); @@ -515,7 +568,11 @@ bool stellar_confirmCreatePassiveOfferOp(StellarCreatePassiveOfferOp *msg) bool stellar_confirmSetOptionsOp(StellarSetOptionsOp *msg) { if (!stellar_signing) return false; - stellar_hashupdate_bool(false); // stellar_hashupdate_address(stellar_activeTx.signing_pubkey); + + if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { + stellar_signingAbort(_("Source account error")); + return false; + } // Hash: operation type stellar_hashupdate_uint32(5); @@ -835,7 +892,11 @@ bool stellar_confirmSetOptionsOp(StellarSetOptionsOp *msg) bool stellar_confirmChangeTrustOp(StellarChangeTrustOp *msg) { if (!stellar_signing) return false; - stellar_hashupdate_bool(false); // stellar_hashupdate_address(stellar_activeTx.signing_pubkey); + + if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { + stellar_signingAbort(_("Source account error")); + return false; + } // Hash: operation type stellar_hashupdate_uint32(6); @@ -899,7 +960,11 @@ bool stellar_confirmChangeTrustOp(StellarChangeTrustOp *msg) bool stellar_confirmAllowTrustOp(StellarAllowTrustOp *msg) { if (!stellar_signing) return false; - stellar_hashupdate_bool(false); // stellar_hashupdate_address(stellar_activeTx.signing_pubkey); + + if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { + stellar_signingAbort(_("Source account error")); + return false; + } // Hash: operation type stellar_hashupdate_uint32(7); @@ -971,7 +1036,11 @@ bool stellar_confirmAllowTrustOp(StellarAllowTrustOp *msg) bool stellar_confirmAccountMergeOp(StellarAccountMergeOp *msg) { if (!stellar_signing) return false; - stellar_hashupdate_bool(false); // stellar_hashupdate_address(stellar_activeTx.signing_pubkey); + + if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { + stellar_signingAbort(_("Source account error")); + return false; + } // Hash: operation type stellar_hashupdate_uint32(8); @@ -1008,7 +1077,11 @@ bool stellar_confirmAccountMergeOp(StellarAccountMergeOp *msg) bool stellar_confirmManageDataOp(StellarManageDataOp *msg) { if (!stellar_signing) return false; - stellar_hashupdate_bool(false); // stellar_hashupdate_address(stellar_activeTx.signing_pubkey); + + if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { + stellar_signingAbort(_("Source account error")); + return false; + } // Hash: operation type stellar_hashupdate_uint32(10); @@ -1078,7 +1151,11 @@ bool stellar_confirmManageDataOp(StellarManageDataOp *msg) bool stellar_confirmBumpSequenceOp(StellarBumpSequenceOp *msg) { if (!stellar_signing) return false; - stellar_hashupdate_bool(false); // stellar_hashupdate_address(stellar_activeTx.signing_pubkey); + + if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { + stellar_signingAbort(_("Source account error")); + return false; + } // Hash: operation type stellar_hashupdate_uint32(11); @@ -1117,34 +1194,18 @@ void stellar_signingAbort(const char *reason) layoutHome(); } -/* - * Calculates and sets the signature for the active transaction - */ -static void stellar_getSignatureForActiveTx(uint8_t *out_signature) -{ - HDNode *node = stellar_deriveNode(stellar_activeTx.address_n, stellar_activeTx.address_n_count); - - // Signature is the ed25519 detached signature of the sha256 of all the bytes - // that have been read so far - uint8_t to_sign[32]; - sha256_Final(&(stellar_activeTx.sha256_ctx), to_sign); - - uint8_t signature[64]; - ed25519_sign(to_sign, sizeof(to_sign), node->private_key, node->public_key + 1, signature); - - memcpy(out_signature, signature, sizeof(signature)); -} - /** * Populates the fields of resp with the signature of the active transaction */ void stellar_fillSignedTx(StellarSignedTx *resp) { + StellarTransaction *activeTx = stellar_getActiveTx(); + // Finalize the transaction by hashing 4 null bytes representing a (currently unused) empty union stellar_hashupdate_uint32(0); // Add the public key for verification that the right account was used for signing - memcpy(resp->public_key.bytes, stellar_activeTx.signing_pubkey, 32); + memcpy(resp->public_key.bytes, &(activeTx->signing_pubkey), 32); resp->public_key.size = 32; resp->has_public_key = true; @@ -1157,11 +1218,34 @@ void stellar_fillSignedTx(StellarSignedTx *resp) resp->has_signature = true; } -bool stellar_allOperationsConfirmed() +uint8_t stellar_allOperationsConfirmed() { return stellar_activeTx.confirmed_operations == stellar_activeTx.num_operations; } +StellarTransaction *stellar_getActiveTx() +{ + return &stellar_activeTx; +} + +/* + * Calculates and sets the signature for the active transaction + */ +void stellar_getSignatureForActiveTx(uint8_t *out_signature) +{ + HDNode *node = stellar_deriveNode(stellar_activeTx.address_n, stellar_activeTx.address_n_count); + + // Signature is the ed25519 detached signature of the sha256 of all the bytes + // that have been read so far + uint8_t to_sign[32]; + sha256_Final(&(stellar_activeTx.sha256_ctx), to_sign); + + uint8_t signature[64]; + ed25519_sign(to_sign, sizeof(to_sign), node->private_key, node->public_key + 1, signature); + + memcpy(out_signature, signature, sizeof(signature)); +} + /* * Returns number (representing stroops) formatted as XLM * For example, if number has value 1000000000 then it will be returned as "100.0" diff --git a/firmware/stellar.h b/firmware/stellar.h index eb1fd256c..c7ab4fd0b 100644 --- a/firmware/stellar.h +++ b/firmware/stellar.h @@ -53,6 +53,7 @@ typedef struct { // Signing process void stellar_signingInit(StellarSignTx *tx); void stellar_signingAbort(const char *reason); +bool stellar_confirmSourceAccount(bool has_source_account, char *str_account); bool stellar_confirmCreateAccountOp(StellarCreateAccountOp *msg); bool stellar_confirmPaymentOp(StellarPaymentOp *msg); bool stellar_confirmPathPaymentOp(StellarPathPaymentOp *msg); @@ -84,8 +85,10 @@ void stellar_hashupdate_address(uint8_t *address_bytes); void stellar_hashupdate_asset(StellarAssetType *asset); void stellar_hashupdate_bytes(uint8_t *data, size_t len); +StellarTransaction *stellar_getActiveTx(void); void stellar_fillSignedTx(StellarSignedTx *resp); -bool stellar_allOperationsConfirmed(void); +uint8_t stellar_allOperationsConfirmed(void); +void stellar_getSignatureForActiveTx(uint8_t *out_signature); void stellar_format_uint32(uint32_t number, char *out, size_t outlen); void stellar_format_uint64(uint64_t number, char *out, size_t outlen);