Fix nft transactions (#229)

* Removed pluginType "hack"

* Fix some ERC 721 & 1155 function signature hashes

* Fix UI for ERC721 operations

* Explicit Batch Transfer UI with ERC1155

* Unified some ERC721 & 1155 non-static functions naming

* Fix UI for ERC1155 operations

* Added missing pin-lock check when signing transactions

* Fix the shell script that builds the elf files for testing

* Add tests dependency ethers

* Removed the space in the test filename

* Tests build script refactoring

* Now works when called from anywhere (not just the script's directory)
* Now handles LNS & LNX builds together (less duplicated code)

* Temporarily disable Nano X tests

Until Zemu supports Nano X 2.0 SDK

* Tests now start with blind signing disabled

Makes it closer to reality & very few of them requires it

* Update to the latest sdk version

* make eth_plugin_perform_init() readable

Introduce 2 functions.

* Now properly parses the apdu and displays the total quantity of NFT IDs transferred in ERC1155 batch transfer

* Add NFT prod public keys

* Added extra checks for the chain ID handling

Following the security review

* NFTs now only supported by LNS

* Version bump

Co-authored-by: Alexandre Paillier <alexandre.paillier@ledger.fr>
Co-authored-by: greenknot <greenknot@users.noreply.github.com>
This commit is contained in:
Jean P
2021-12-17 12:04:51 +01:00
committed by GitHub
parent 586155c0d4
commit a53a2428cc
40 changed files with 735 additions and 208 deletions

View File

@@ -4,6 +4,7 @@
#include "tokens.h"
#include "eth_plugin_interface.h"
#include "eth_plugin_internal.h"
#include "utils.h"
// Supported internal plugins
#define ERC721_STR "ERC721"
@@ -31,10 +32,9 @@ typedef enum Version {
} Version;
typedef enum KeyId {
TEST_KEY = 0x00,
PERSO_V2_KEY_1 = 0x01,
TEST_PLUGIN_KEY = 0x00,
// Must ONLY be used with ERC721 and ERC1155 plugin
AWS_PLUGIN_KEY_1 = 0x02,
PROD_PLUGIN_KEY = 0x02,
} KeyId;
// Algorithm Id consists of a Key spec and an algorithm spec.
@@ -43,18 +43,22 @@ typedef enum AlgorithmID {
ECC_SECG_P256K1__ECDSA_SHA_256 = 0x01,
} AlgorithmID;
// Only used for signing NFT plugins (ERC721 and ERC1155)
static const uint8_t LEDGER_NFT_SELECTOR_PUBLIC_KEY[] = {
#ifdef HAVE_NFT_TESTING_KEY
static const uint8_t LEDGER_TESTING_KEY[] = {
0x04, 0xf5, 0x70, 0x0c, 0xa1, 0xe8, 0x74, 0x24, 0xc7, 0xc7, 0xd1, 0x19, 0xe7,
0xe3, 0xc1, 0x89, 0xb1, 0x62, 0x50, 0x94, 0xdb, 0x6e, 0xa0, 0x40, 0x87, 0xc8,
0x30, 0x00, 0x7d, 0x0b, 0x46, 0x9a, 0x53, 0x11, 0xee, 0x6a, 0x1a, 0xcd, 0x1d,
0xa5, 0xaa, 0xb0, 0xf5, 0xc6, 0xdf, 0x13, 0x15, 0x8d, 0x28, 0xcc, 0x12, 0xd1,
0xdd, 0xa6, 0xec, 0xe9, 0x46, 0xb8, 0x9d, 0x5c, 0x05, 0x49, 0x92, 0x59, 0xc4};
0xdd, 0xa6, 0xec, 0xe9, 0x46, 0xb8, 0x9d, 0x5c, 0x05, 0x49, 0x92, 0x59, 0xc4
#else
0x04, 0xd8, 0x62, 0x6e, 0x01, 0x9e, 0x55, 0x3e, 0x19, 0x69, 0x56, 0xf1, 0x17,
0x4d, 0xcd, 0xb8, 0x9a, 0x1c, 0xda, 0xc4, 0x93, 0x90, 0x08, 0xbc, 0x79, 0x77,
0x33, 0x6d, 0x78, 0x24, 0xee, 0xe3, 0xa2, 0x62, 0x24, 0x1a, 0x62, 0x73, 0x52,
0x3b, 0x09, 0xb8, 0xd0, 0xce, 0x0d, 0x39, 0xe8, 0x60, 0xc9, 0x4d, 0x02, 0x53,
0x58, 0xdb, 0xdc, 0x25, 0x92, 0xc7, 0xc6, 0x48, 0x0d, 0x39, 0xce, 0xbb, 0xa3
#endif
static const uint8_t LEDGER_PERSO_V2_PUBLIC_KEY[] = {};
// Only used for signing NFT plugins (ERC721 and ERC1155)
static const uint8_t LEDGER_NFT_SELECTOR_PUBLIC_KEY[] = {};
};
// Verification function used to verify the signature
typedef bool verificationAlgo(const cx_ecfp_public_key_t *,
@@ -164,9 +168,14 @@ void handleSetPlugin(uint8_t p1,
PRINTF("Selector: %.*H\n", SELECTOR_SIZE, tokenContext->methodSelector);
offset += SELECTOR_SIZE;
// TODO: store chainID and assert that tx is using the same chainid.
// uint64_t chainid = u64_from_BE(workBuffer + offset, CHAIN_ID_SIZE);
// PRINTF("ChainID: %.*H\n", sizeof(chainid), &chainid);
uint64_t chainId = u64_from_BE(workBuffer + offset, CHAIN_ID_SIZE);
// this prints raw data, so to have a more meaningful print, display
// the buffer before the endianness swap
PRINTF("ChainID: %.*H\n", sizeof(chainId), (workBuffer + offset));
if ((chainConfig->chainId != 0) && (chainConfig->chainId != chainId)) {
PRINTF("Chain ID token mismatch\n");
THROW(0x6A80);
}
offset += CHAIN_ID_SIZE;
enum KeyId keyId = workBuffer[offset];
@@ -176,16 +185,9 @@ void handleSetPlugin(uint8_t p1,
PRINTF("KeyID: %d\n", keyId);
switch (keyId) {
#ifdef HAVE_NFT_TESTING_KEY
case TEST_KEY:
rawKey = LEDGER_TESTING_KEY;
rawKeyLen = sizeof(LEDGER_TESTING_KEY);
break;
case TEST_PLUGIN_KEY:
#endif
case PERSO_V2_KEY_1:
rawKey = LEDGER_PERSO_V2_PUBLIC_KEY;
rawKeyLen = sizeof(LEDGER_PERSO_V2_PUBLIC_KEY);
break;
case AWS_PLUGIN_KEY_1:
case PROD_PLUGIN_KEY:
rawKey = LEDGER_NFT_SELECTOR_PUBLIC_KEY;
rawKeyLen = sizeof(LEDGER_NFT_SELECTOR_PUBLIC_KEY);
break;
@@ -255,7 +257,7 @@ void handleSetPlugin(uint8_t p1,
}
pluginType = getPluginType(tokenContext->pluginName, pluginNameLength);
if (keyId == AWS_PLUGIN_KEY_1) {
if (keyId == PROD_PLUGIN_KEY) {
if (pluginType != ERC721 && pluginType != ERC1155) {
PRINTF("AWS key must only be used to set NFT internal plugins\n");
THROW(0x6A80);