From bd6448734d5b03d9fcac6a3a8886ac5deff6f1a9 Mon Sep 17 00:00:00 2001 From: Michele Balistreri Date: Thu, 22 Nov 2018 17:56:28 +0300 Subject: [PATCH] implement tests, correct bugs --- build.gradle | 2 +- .../java/im/status/wallet/WalletApplet.java | 3 +- .../im/status/wallet/WalletAppletTest.java | 99 +++++++++++++++++++ 3 files changed, 102 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 183924f..633f862 100644 --- a/build.gradle +++ b/build.gradle @@ -42,7 +42,7 @@ dependencies { testCompile('org.web3j:core:2.3.1') testCompile('org.bitcoinj:bitcoinj-core:0.14.5') testCompile("org.bouncycastle:bcprov-jdk15on:1.58") - testCompile("com.github.status-im:hardwallet-lite-sdk:7e3787f") + testCompile("com.github.status-im:hardwallet-lite-sdk:f64cefd") testCompile("org.junit.jupiter:junit-jupiter-api:5.1.1") testRuntime("org.junit.jupiter:junit-jupiter-engine:5.1.1") } diff --git a/src/main/java/im/status/wallet/WalletApplet.java b/src/main/java/im/status/wallet/WalletApplet.java index c470a7c..60b7e45 100644 --- a/src/main/java/im/status/wallet/WalletApplet.java +++ b/src/main/java/im/status/wallet/WalletApplet.java @@ -173,7 +173,7 @@ public class WalletApplet extends Applet { signature = Signature.getInstance(Signature.ALG_ECDSA_SHA_256, false); secureChannel = new SecureChannel(PAIRING_MAX_CLIENT_COUNT, crypto, secp256k1); - duplicationEncKey = new byte[(short)(KeyBuilder.LENGTH_AES_128/8)]; + duplicationEncKey = new byte[(short)(KeyBuilder.LENGTH_AES_256/8)]; expectedEntropy = -1; register(bArray, (short) (bOffset + 1), bArray[bOffset]); @@ -248,6 +248,7 @@ public class WalletApplet extends Applet { break; case INS_DUPLICATE_KEY: duplicateKey(apdu); + break; case INS_SIGN: sign(apdu); break; diff --git a/src/test/java/im/status/wallet/WalletAppletTest.java b/src/test/java/im/status/wallet/WalletAppletTest.java index a3ffa82..23ce89a 100644 --- a/src/test/java/im/status/wallet/WalletAppletTest.java +++ b/src/test/java/im/status/wallet/WalletAppletTest.java @@ -1017,6 +1017,105 @@ public class WalletAppletTest { assertEquals(0x6985, response.getSW()); } + @Test + @DisplayName("DUPLICATE KEY command") + void duplicateTest() throws Exception { + int secretCount = 5; + Random random = new Random(); + byte[][] secrets = new byte[secretCount][32]; + for (int i = 0; i < secretCount; i++) { + random.nextBytes(secrets[i]); + } + + // Security condition violation: SecureChannel not open + ResponseAPDU response = cmdSet.duplicateKeyStart(secretCount, secrets[0]); + assertEquals(0x6985, response.getSW()); + + cmdSet.autoOpenSecureChannel(); + + // Security condition violation: PIN not verified + response = cmdSet.duplicateKeyStart(secretCount, secrets[0]); + assertEquals(0x6985, response.getSW()); + + response = cmdSet.verifyPIN("000000"); + assertEquals(0x9000, response.getSW()); + response = cmdSet.generateKey(); + assertEquals(0x9000, response.getSW()); + byte[] keyUID = response.getData(); + + // Init duplication + response = cmdSet.duplicateKeyStart(secretCount, secrets[0]); + assertEquals(0x9000, response.getSW()); + + // Adding key entropy must work without secure channel and PIN authentication + reset(); + response = cmdSet.select(); + assertEquals(0x9000, response.getSW()); + + // Put all except the last piece of entropy + for (int i = 1; i < (secretCount - 1); i++) { + response = cmdSet.duplicateKeyAddEntropy(secrets[i]); + assertEquals(0x9000, response.getSW()); + } + + cmdSet.autoOpenSecureChannel(); + response = cmdSet.verifyPIN("000000"); + assertEquals(0x9000, response.getSW()); + + // Try to backup before enough entropy has been set + response = cmdSet.duplicateKeyExport(); + assertEquals(0x6985, response.getSW()); + + reset(); + response = cmdSet.select(); + assertEquals(0x9000, response.getSW()); + + // Put last piece of entropy + response = cmdSet.duplicateKeyAddEntropy(secrets[(secretCount - 1)]); + assertEquals(0x9000, response.getSW()); + + // Try putting more entropy (failure expected) + response = cmdSet.duplicateKeyAddEntropy(secrets[(secretCount - 1)]); + assertEquals(0x6985, response.getSW()); + + cmdSet.autoOpenSecureChannel(); + response = cmdSet.verifyPIN("000000"); + assertEquals(0x9000, response.getSW()); + + // Backup + response = cmdSet.duplicateKeyExport(); + assertEquals(0x9000, response.getSW()); + byte[] backup = response.getData(); + + // Try to restore the backup (failure expected, session is over) + response = cmdSet.duplicateKeyImport(backup); + assertEquals(0x6985, response.getSW()); + + // Now try to restore the backup and check that the key UID matches, but first change the keys to random ones + response = cmdSet.generateKey(); + assertEquals(0x9000, response.getSW()); + + response = cmdSet.duplicateKeyStart(secretCount, secrets[0]); + assertEquals(0x9000, response.getSW()); + + reset(); + response = cmdSet.select(); + assertEquals(0x9000, response.getSW()); + + for (int i = 1; i < secretCount; i++) { + response = cmdSet.duplicateKeyAddEntropy(secrets[i]); + assertEquals(0x9000, response.getSW()); + } + + cmdSet.autoOpenSecureChannel(); + response = cmdSet.verifyPIN("000000"); + assertEquals(0x9000, response.getSW()); + + response = cmdSet.duplicateKeyImport(backup); + assertEquals(0x9000, response.getSW()); + assertArrayEquals(keyUID, response.getData()); + } + @Test @DisplayName("Sign actual Ethereum transaction") @Tag("manual")