Beispiel #1
0
bool storage_getRootNode(HDNode *node)
{
	// root node is properly cached
	if (sessionRootNodeCached) {
		memcpy(node, &sessionRootNode, sizeof(HDNode));
		return true;
	}

	// if storage has node, decrypt and use it
	if (storage.has_node) {
		if (!protectPassphrase()) {
			return false;
		}
		if (hdnode_from_xprv(storage.node.depth, storage.node.fingerprint, storage.node.child_num, storage.node.chain_code.bytes, storage.node.private_key.bytes, &sessionRootNode) == 0) {
			return false;
		}
		if (storage.has_passphrase_protection && storage.passphrase_protection && strlen(sessionPassphrase)) {
			// decrypt hd node
			uint8_t secret[64];
			uint8_t salt[12];
			memcpy(salt, "TREZORHD", 8);
			layoutProgressSwipe("Waking up", 0);
			pbkdf2_hmac_sha512((const uint8_t *)sessionPassphrase, strlen(sessionPassphrase), salt, 8, BIP39_PBKDF2_ROUNDS, secret, 64, get_root_node_callback);
			aes_decrypt_ctx ctx;
			aes_decrypt_key256(secret, &ctx);
			aes_cbc_decrypt(sessionRootNode.chain_code, sessionRootNode.chain_code, 32, secret + 32, &ctx);
			aes_cbc_decrypt(sessionRootNode.private_key, sessionRootNode.private_key, 32, secret + 32, &ctx);
		}
		memcpy(node, &sessionRootNode, sizeof(HDNode));
		sessionRootNodeCached = true;
		return true;
	}

	// if storage has mnemonic, convert it to node and use it
	if (storage.has_mnemonic) {
		if (!protectPassphrase()) {
			return false;
		}
		uint8_t seed[64];
		layoutProgressSwipe("Waking up", 0);
		mnemonic_to_seed(storage.mnemonic, sessionPassphrase, seed, get_root_node_callback); // BIP-0039
		if (hdnode_from_seed(seed, sizeof(seed), &sessionRootNode) == 0) {
			return false;
		}
		memcpy(node, &sessionRootNode, sizeof(HDNode));
		sessionRootNodeCached = true;
		return true;
	}

	return false;
}
Beispiel #2
0
void lisk_sign_message(const HDNode *node, const LiskSignMessage *msg,
                       LiskMessageSignature *resp) {
  layoutSignMessage(msg->message.bytes, msg->message.size);
  if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) {
    fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL);
    layoutHome();
    return;
  }

  layoutProgressSwipe(_("Signing"), 0);

  uint8_t signature[64];
  uint8_t hash[32];
  lisk_message_hash(msg->message.bytes, msg->message.size, hash);

  ed25519_sign(hash, 32, node->private_key, &node->public_key[1], signature);

  memcpy(resp->signature.bytes, signature, sizeof(signature));
  memcpy(resp->public_key.bytes, &node->public_key[1], 32);

  resp->has_signature = true;
  resp->signature.size = 64;
  resp->has_public_key = true;
  resp->public_key.size = 32;
}
Beispiel #3
0
void fsm_msgSignMessage(SignMessage *msg)
{
	RESP_INIT(MessageSignature);

	layoutSignMessage(msg->message.bytes, msg->message.size);
	if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) {
		fsm_sendFailure(FailureType_Failure_ActionCancelled, "Sign message cancelled");
		layoutHome();
		return;
	}

	if (!protectPin(true)) {
		layoutHome();
		return;
	}

	const CoinType *coin = fsm_getCoin(msg->coin_name);
	if (!coin) return;
	const HDNode *node = fsm_getDerivedNode(msg->address_n, msg->address_n_count);
	if (!node) return;

	layoutProgressSwipe("Signing", 0);
	if (cryptoMessageSign(msg->message.bytes, msg->message.size, node->private_key, resp->signature.bytes) == 0) {
		resp->has_address = true;
		uint8_t addr_raw[21];
		ecdsa_get_address_raw(node->public_key, coin->address_type, addr_raw);
		base58_encode_check(addr_raw, 21, resp->address, sizeof(resp->address));
		resp->has_signature = true;
		resp->signature.size = 65;
		msg_write(MessageType_MessageType_MessageSignature, resp);
	} else {
		fsm_sendFailure(FailureType_Failure_Other, "Error signing message");
	}
	layoutHome();
}
Beispiel #4
0
void fsm_msgGetAddress(GetAddress *msg)
{
	RESP_INIT(Address);

	if (!protectPin(true)) {
		layoutHome();
		return;
	}

	const CoinType *coin = fsm_getCoin(msg->coin_name);
	if (!coin) return;
	const HDNode *node = fsm_getDerivedNode(msg->address_n, msg->address_n_count);
	if (!node) return;

	if (msg->has_multisig) {
		layoutProgressSwipe("Preparing", 0);
		if (cryptoMultisigPubkeyIndex(&(msg->multisig), node->public_key) < 0) {
			fsm_sendFailure(FailureType_Failure_Other, "Pubkey not found in multisig script");
			layoutHome();
			return;
		}
		uint8_t buf[32];
		if (compile_script_multisig_hash(&(msg->multisig), buf) == 0) {
			fsm_sendFailure(FailureType_Failure_Other, "Invalid multisig script");
			layoutHome();
			return;
		}
		ripemd160(buf, 32, buf + 1);
		buf[0] = coin->address_type_p2sh; // multisig cointype
		base58_encode_check(buf, 21, resp->address, sizeof(resp->address));
	} else {
		ecdsa_get_address(node->public_key, coin->address_type, resp->address, sizeof(resp->address));
	}

	if (msg->has_show_display && msg->show_display) {
		char desc[16];
		if (msg->has_multisig) {
			strlcpy(desc, "Msig __ of __:", sizeof(desc));
			const uint32_t m = msg->multisig.m;
			const uint32_t n = msg->multisig.pubkeys_count;
			desc[5] = (m < 10) ? ' ': ('0' + (m / 10));
			desc[6] = '0' + (m % 10);
			desc[11] = (n < 10) ? ' ': ('0' + (n / 10));
			desc[12] = '0' + (n % 10);
		} else {
			strlcpy(desc, "Address:", sizeof(desc));
		}
		layoutAddress(resp->address, desc);
		if (!protectButton(ButtonRequestType_ButtonRequest_Address, true)) {
			fsm_sendFailure(FailureType_Failure_ActionCancelled, "Show address cancelled");
			layoutHome();
			return;
		}
	}

	msg_write(MessageType_MessageType_Address, resp);
	layoutHome();
}
Beispiel #5
0
void fsm_msgEncryptMessage(EncryptMessage *msg)
{
	if (!msg->has_pubkey) {
		fsm_sendFailure(FailureType_Failure_SyntaxError, "No public key provided");
		return;
	}
	if (!msg->has_message) {
		fsm_sendFailure(FailureType_Failure_SyntaxError, "No message provided");
		return;
	}
	curve_point pubkey;
	if (msg->pubkey.size != 33 || ecdsa_read_pubkey(&secp256k1, msg->pubkey.bytes, &pubkey) == 0) {
		fsm_sendFailure(FailureType_Failure_SyntaxError, "Invalid public key provided");
		return;
	}
	bool display_only = msg->has_display_only && msg->display_only;
	bool signing = msg->address_n_count > 0;
	RESP_INIT(EncryptedMessage);
	const CoinType *coin = 0;
	const HDNode *node = 0;
	uint8_t address_raw[21];
	if (signing) {
		coin = coinByName(msg->coin_name);
		if (!coin) {
			fsm_sendFailure(FailureType_Failure_Other, "Invalid coin name");
			return;
		}
		if (!protectPin(true)) {
			layoutHome();
			return;
		}
		node = fsm_getDerivedNode(msg->address_n, msg->address_n_count);
		if (!node) return;
		uint8_t public_key[33];
		ecdsa_get_public_key33(&secp256k1, node->private_key, public_key);
		ecdsa_get_address_raw(public_key, coin->address_type, address_raw);
	}
	layoutEncryptMessage(msg->message.bytes, msg->message.size, signing);
	if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) {
		fsm_sendFailure(FailureType_Failure_ActionCancelled, "Encrypt message cancelled");
		layoutHome();
		return;
	}
	layoutProgressSwipe("Encrypting", 0);
	if (cryptoMessageEncrypt(&pubkey, msg->message.bytes, msg->message.size, display_only, resp->nonce.bytes, &(resp->nonce.size), resp->message.bytes, &(resp->message.size), resp->hmac.bytes, &(resp->hmac.size), signing ? node->private_key : 0, signing ? address_raw : 0) != 0) {
		fsm_sendFailure(FailureType_Failure_ActionCancelled, "Error encrypting message");
		layoutHome();
		return;
	}
	resp->has_nonce = true;
	resp->has_message = true;
	resp->has_hmac = true;
	msg_write(MessageType_MessageType_EncryptedMessage, resp);
	layoutHome();
}
Beispiel #6
0
void fsm_msgDecryptMessage(DecryptMessage *msg)
{
	if (!msg->has_nonce) {
		fsm_sendFailure(FailureType_Failure_SyntaxError, "No nonce provided");
		return;
	}
	if (!msg->has_message) {
		fsm_sendFailure(FailureType_Failure_SyntaxError, "No message provided");
		return;
	}
	if (!msg->has_hmac) {
		fsm_sendFailure(FailureType_Failure_SyntaxError, "No message hmac provided");
		return;
	}
	curve_point nonce_pubkey;
	if (msg->nonce.size != 33 || ecdsa_read_pubkey(&secp256k1, msg->nonce.bytes, &nonce_pubkey) == 0) {
		fsm_sendFailure(FailureType_Failure_SyntaxError, "Invalid nonce provided");
		return;
	}
	if (!protectPin(true)) {
		layoutHome();
		return;
	}
	const HDNode *node = fsm_getDerivedNode(msg->address_n, msg->address_n_count);
	if (!node) return;

	layoutProgressSwipe("Decrypting", 0);
	RESP_INIT(DecryptedMessage);
	bool display_only = false;
	bool signing = false;
	uint8_t address_raw[21];
	if (cryptoMessageDecrypt(&nonce_pubkey, msg->message.bytes, msg->message.size, msg->hmac.bytes, msg->hmac.size, node->private_key, resp->message.bytes, &(resp->message.size), &display_only, &signing, address_raw) != 0) {
		fsm_sendFailure(FailureType_Failure_ActionCancelled, "Error decrypting message");
		layoutHome();
		return;
	}
	if (signing) {
		base58_encode_check(address_raw, 21, resp->address, sizeof(resp->address));
	}
	layoutDecryptMessage(resp->message.bytes, resp->message.size, signing ? resp->address : 0);
	protectButton(ButtonRequestType_ButtonRequest_Other, true);
	if (display_only) {
		resp->has_address = false;
		resp->has_message = false;
		memset(resp->address, 0, sizeof(resp->address));
		memset(&(resp->message), 0, sizeof(resp->message));
	} else {
		resp->has_address = signing;
		resp->has_message = true;
	}
	msg_write(MessageType_MessageType_DecryptedMessage, resp);
	layoutHome();
}
Beispiel #7
0
void fsm_deriveKey(HDNode *node, uint32_t *address_n, size_t address_n_count)
{
	size_t i;
	if (address_n_count > 3) {
		layoutProgressSwipe("Preparing keys", 0, 0);
	}
	for (i = 0; i < address_n_count; i++) {
		hdnode_private_ckd(node, address_n[i]);
		if (address_n_count > 3) {
			layoutProgress("Preparing keys", 1000 * i / address_n_count, i);
		}
	}
}
Beispiel #8
0
void fsm_msgVerifyMessage(VerifyMessage *msg)
{
	const char *address = msg->has_address ? msg->address : 0;
	layoutProgressSwipe("Verifying", 0, 0);
	if (msg->signature.size == 65 && transactionMessageVerify(msg->message.bytes, msg->message.size, msg->signature.bytes, address)) {
		layoutVerifyMessage(msg->message.bytes, msg->message.size);
		protectButton(ButtonRequestType_ButtonRequest_Other, true);
		fsm_sendSuccess("Message verified");
	} else {
		fsm_sendFailure(FailureType_Failure_InvalidSignature, "Invalid signature");
	}
	layoutHome();
}
Beispiel #9
0
void fsm_msgSignMessage(SignMessage *msg)
{
	RESP_INIT(MessageSignature);

	layoutSignMessage(msg->message.bytes, msg->message.size);
	if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) {
		fsm_sendFailure(FailureType_Failure_ActionCancelled, "Sign message cancelled");
		layoutHome();
		return;
	}

	if (!protectPin(true)) {
		layoutHome();
		return;
	}

	HDNode *node = fsm_getRootNode();
	if (!node) return;
	const CoinType *coin = coinByName(msg->coin_name);
	if (!coin) {
		fsm_sendFailure(FailureType_Failure_Other, "Invalid coin name");
		layoutHome();
		return;
	}

	fsm_deriveKey(node, msg->address_n, msg->address_n_count);

	ecdsa_get_address(node->public_key, coin->address_type, resp->address);
	layoutProgressSwipe("Signing", 0, 0);
	if (transactionMessageSign(msg->message.bytes, msg->message.size, node->private_key, resp->address, resp->signature.bytes)) {
		resp->has_address = true;
		resp->has_signature = true;
		resp->signature.size = 65;
		msg_write(MessageType_MessageType_MessageSignature, resp);
	} else {
		fsm_sendFailure(FailureType_Failure_Other, "Error signing message");
	}
	layoutHome();
}
Beispiel #10
0
void fsm_msgVerifyMessage(VerifyMessage *msg)
{
	if (!msg->has_address) {
		fsm_sendFailure(FailureType_Failure_Other, "No address provided");
		return;
	}
	if (!msg->has_message) {
		fsm_sendFailure(FailureType_Failure_Other, "No message provided");
		return;
	}
	layoutProgressSwipe("Verifying", 0);
	uint8_t addr_raw[21];
	if (!ecdsa_address_decode(msg->address, addr_raw)) {
		fsm_sendFailure(FailureType_Failure_InvalidSignature, "Invalid address");
	}
	if (msg->signature.size == 65 && cryptoMessageVerify(msg->message.bytes, msg->message.size, addr_raw, msg->signature.bytes) == 0) {
		layoutVerifyMessage(msg->message.bytes, msg->message.size);
		protectButton(ButtonRequestType_ButtonRequest_Other, true);
		fsm_sendSuccess("Message verified");
	} else {
		fsm_sendFailure(FailureType_Failure_InvalidSignature, "Invalid signature");
	}
	layoutHome();
}
Beispiel #11
0
void lisk_sign_tx(const HDNode *node, LiskSignTx *msg, LiskSignedTx *resp) {
  lisk_update_raw_tx(node, msg);

  if (msg->has_transaction) {
    SHA256_CTX ctx;
    sha256_Init(&ctx);

    switch (msg->transaction.type) {
      case LiskTransactionType_Transfer:
        layoutRequireConfirmTx(msg->transaction.recipient_id,
                               msg->transaction.amount);
        break;
      case LiskTransactionType_RegisterDelegate:
        layoutRequireConfirmDelegateRegistration(&msg->transaction.asset);
        break;
      case LiskTransactionType_CastVotes:
        layoutRequireConfirmCastVotes(&msg->transaction.asset);
        break;
      case LiskTransactionType_RegisterSecondPassphrase:
        layoutLiskPublicKey(msg->transaction.asset.signature.public_key.bytes);
        break;
      case LiskTransactionType_RegisterMultisignatureAccount:
        layoutRequireConfirmMultisig(&msg->transaction.asset);
        break;
      default:
        fsm_sendFailure(FailureType_Failure_DataError,
                        _("Invalid transaction type"));
        layoutHome();
        break;
    }
    if (!protectButton((msg->transaction.type ==
                                LiskTransactionType_RegisterSecondPassphrase
                            ? ButtonRequestType_ButtonRequest_PublicKey
                            : ButtonRequestType_ButtonRequest_SignTx),
                       false)) {
      fsm_sendFailure(FailureType_Failure_ActionCancelled, "Signing cancelled");
      layoutHome();
      return;
    }

    layoutRequireConfirmFee(msg->transaction.fee, msg->transaction.amount);
    if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
      fsm_sendFailure(FailureType_Failure_ActionCancelled, "Signing cancelled");
      layoutHome();
      return;
    }
    layoutProgressSwipe(_("Signing transaction"), 0);

    sha256_Update(&ctx, (const uint8_t *)&msg->transaction.type, 1);

    lisk_hashupdate_uint32(&ctx, msg->transaction.timestamp);

    sha256_Update(&ctx, msg->transaction.sender_public_key.bytes, 32);

    if (msg->transaction.has_requester_public_key) {
      sha256_Update(&ctx, msg->transaction.requester_public_key.bytes,
                    msg->transaction.requester_public_key.size);
    }

    uint64_t recipient_id = 0;
    if (msg->transaction.has_recipient_id &&
        msg->transaction.recipient_id[0] != 0) {
      // parse integer from lisk address ("123L" -> 123)
      for (size_t i = 0; i < strlen(msg->transaction.recipient_id) - 1; i++) {
        if (msg->transaction.recipient_id[i] < '0' ||
            msg->transaction.recipient_id[i] > '9') {
          fsm_sendFailure(FailureType_Failure_DataError,
                          _("Invalid recipient_id"));
          layoutHome();
          return;
        }
        recipient_id *= 10;
        recipient_id += (msg->transaction.recipient_id[i] - '0');
      }
    }
    lisk_hashupdate_uint64_be(&ctx, recipient_id);
    lisk_hashupdate_uint64_le(&ctx, msg->transaction.amount);

    lisk_hashupdate_asset(&ctx, msg->transaction.type, &msg->transaction.asset);

    // if signature exist calculate second signature
    if (msg->transaction.has_signature) {
      sha256_Update(&ctx, msg->transaction.signature.bytes,
                    msg->transaction.signature.size);
    }

    uint8_t hash[32];
    sha256_Final(&ctx, hash);
    ed25519_sign(hash, 32, node->private_key, &node->public_key[1],
                 resp->signature.bytes);

    resp->has_signature = true;
    resp->signature.size = 64;
  }
}
Beispiel #12
0
void fsm_msgSignIdentity(SignIdentity *msg)
{
	RESP_INIT(SignedIdentity);

	layoutSignIdentity(&(msg->identity), msg->has_challenge_visual ? msg->challenge_visual : 0);
	if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) {
		fsm_sendFailure(FailureType_Failure_ActionCancelled, "Sign identity cancelled");
		layoutHome();
		return;
	}

	if (!protectPin(true)) {
		layoutHome();
		return;
	}

	uint8_t hash[32];
	if (!msg->has_identity || cryptoIdentityFingerprint(&(msg->identity), hash) == 0) {
		fsm_sendFailure(FailureType_Failure_Other, "Invalid identity");
		layoutHome();
		return;
	}

	uint32_t address_n[5];
	address_n[0] = 0x80000000 | 13;
	address_n[1] = 0x80000000 | hash[ 0] | (hash[ 1] << 8) | (hash[ 2] << 16) | (hash[ 3] << 24);
	address_n[2] = 0x80000000 | hash[ 4] | (hash[ 5] << 8) | (hash[ 6] << 16) | (hash[ 7] << 24);
	address_n[3] = 0x80000000 | hash[ 8] | (hash[ 9] << 8) | (hash[10] << 16) | (hash[11] << 24);
	address_n[4] = 0x80000000 | hash[12] | (hash[13] << 8) | (hash[14] << 16) | (hash[15] << 24);

	const HDNode *node = fsm_getDerivedNode(address_n, 5);
	if (!node) return;

	uint8_t public_key[33];  // copy public key to temporary buffer
	memcpy(public_key, node->public_key, sizeof(public_key));

	if (msg->has_ecdsa_curve_name) {
		const ecdsa_curve *curve = get_curve_by_name(msg->ecdsa_curve_name);
		if (curve) {
			// correct public key (since fsm_getDerivedNode uses secp256k1 curve)
			ecdsa_get_public_key33(curve, node->private_key, public_key);
		}
	}

	bool sign_ssh = msg->identity.has_proto && (strcmp(msg->identity.proto, "ssh") == 0);

	int result = 0;
	layoutProgressSwipe("Signing", 0);
	if (sign_ssh) { // SSH does not sign visual challenge
		result = sshMessageSign(msg->challenge_hidden.bytes, msg->challenge_hidden.size, node->private_key, resp->signature.bytes);
	} else {
		uint8_t digest[64];
		sha256_Raw(msg->challenge_hidden.bytes, msg->challenge_hidden.size, digest);
		sha256_Raw((const uint8_t *)msg->challenge_visual, strlen(msg->challenge_visual), digest + 32);
		result = cryptoMessageSign(digest, 64, node->private_key, resp->signature.bytes);
	}

	if (result == 0) {
		if (sign_ssh) {
			resp->has_address = false;
		} else {
			resp->has_address = true;
			uint8_t addr_raw[21];
			ecdsa_get_address_raw(node->public_key, 0x00, addr_raw); // hardcoded Bitcoin address type
			base58_encode_check(addr_raw, 21, resp->address, sizeof(resp->address));
		}
		resp->has_public_key = true;
		resp->public_key.size = 33;
		memcpy(resp->public_key.bytes, public_key, 33);
		resp->has_signature = true;
		resp->signature.size = 65;
		msg_write(MessageType_MessageType_SignedIdentity, resp);
	} else {
		fsm_sendFailure(FailureType_Failure_Other, "Error signing identity");
	}
	layoutHome();
}