Merge pull request #608 from m2049r/feature_nanox

Support for Nano X
This commit is contained in:
m2049r 2019-07-13 18:56:23 +02:00 committed by GitHub
commit f4cada5fa1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 124 additions and 77 deletions

View File

@ -1310,7 +1310,6 @@ Java_com_m2049r_xmrwallet_model_PendingTransaction_getFirstTxIdJ(JNIEnv *env, jo
return nullptr;
}
JNIEXPORT jlong JNICALL
Java_com_m2049r_xmrwallet_model_PendingTransaction_getTxCount(JNIEnv *env, jobject instance) {
Bitmonero::PendingTransaction *tx = getHandle<Bitmonero::PendingTransaction>(env, instance);
@ -1396,6 +1395,11 @@ Java_com_m2049r_xmrwallet_model_WalletManager_setLogLevel(JNIEnv *env, jclass cl
Bitmonero::WalletManagerFactory::setLogLevel(level);
}
JNIEXPORT jstring JNICALL
Java_com_m2049r_xmrwallet_model_WalletManager_moneroVersion(JNIEnv *env, jclass clazz) {
return env->NewStringUTF(MONERO_VERSION);
}
//
// Ledger Stuff
//

View File

@ -54,6 +54,8 @@ extern "C"
{
#endif
extern const char* const MONERO_VERSION; // the actual monero core version
// from monero-core crypto/hash-ops.h - avoid #including monero code here
enum {
HASH_SIZE = 32,

View File

@ -46,8 +46,12 @@ public class BTChipTransportAndroidHID implements BTChipTransport {
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
for (UsbDevice device : deviceList.values()) {
Timber.d("%04X:%04X %s, %s", device.getVendorId(), device.getProductId(), device.getManufacturerName(), device.getProductName());
if ((device.getVendorId() == VID) && (device.getProductId() == PID_HID)) {
return device;
if (device.getVendorId() == VID) {
final int deviceProductId = device.getProductId();
for (int pid : PID_HIDS) {
if (deviceProductId == pid)
return device;
}
}
}
return null;
@ -74,7 +78,7 @@ public class BTChipTransportAndroidHID implements BTChipTransport {
}
private static final int VID = 0x2C97;
private static final int PID_HID = 0x0001;
private static final int[] PID_HIDS = {0x0001, 0x0004};
private UsbDeviceConnection connection;
private UsbInterface dongleInterface;

View File

@ -1359,17 +1359,30 @@ public class LoginActivity extends BaseActivity
if (Ledger.ENABLED)
try {
Ledger.connect(usbManager, usbDevice);
registerDetachReceiver();
onLedgerAction();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(LoginActivity.this,
getString(R.string.toast_ledger_attached, usbDevice.getProductName()),
Toast.LENGTH_SHORT)
.show();
}
});
if (!Ledger.check()) {
Ledger.disconnect();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(LoginActivity.this,
getString(R.string.toast_ledger_start_app, usbDevice.getProductName()),
Toast.LENGTH_SHORT)
.show();
}
});
} else {
registerDetachReceiver();
onLedgerAction();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(LoginActivity.this,
getString(R.string.toast_ledger_attached, usbDevice.getProductName()),
Toast.LENGTH_SHORT)
.show();
}
});
}
} catch (IOException ex) {
runOnUiThread(new Runnable() {
@Override

View File

@ -134,6 +134,10 @@ public enum Instruction {
return value;
}
public byte getByteValue() {
return (byte) (value & 0xFF);
}
private int value;
Instruction(int value) {

View File

@ -27,9 +27,11 @@ import com.btchip.BTChipException;
import com.btchip.comm.BTChipTransport;
import com.btchip.comm.android.BTChipTransportAndroidHID;
import com.m2049r.xmrwallet.BuildConfig;
import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.util.Helper;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import timber.log.Timber;
@ -40,9 +42,11 @@ public class Ledger {
static public final int LOOKAHEAD_SUBADDRESSES = 20;
static public final String SUBADDRESS_LOOKAHEAD = LOOKAHEAD_ACCOUNTS + ":" + LOOKAHEAD_SUBADDRESSES;
private static final byte PROTOCOL_VERSION = 0x02;
public static final int SW_OK = 0x9000;
public static final int SW_INS_NOT_SUPPORTED = 0x6D00;
public static final int OK[] = {SW_OK};
public static final int MINIMUM_LEDGER_VERSION = (1 << 16) + (3 << 8) + (1); // 1.3.1
public static UsbDevice findDevice(UsbManager usbManager) {
if (!ENABLED) return null;
@ -89,6 +93,21 @@ public class Ledger {
}
}
static public boolean check() {
if (Instance == null) return false;
byte[] moneroVersion = WalletManager.moneroVersion().getBytes(StandardCharsets.US_ASCII);
try {
byte[] resp = Instance.exchangeApduNoOpt(Instruction.INS_RESET, moneroVersion, OK);
int deviceVersion = (resp[0] << 16) + (resp[1] << 8) + (resp[2]);
if (deviceVersion < MINIMUM_LEDGER_VERSION)
return false;
} catch (BTChipException ex) { // comm error - probably wrong app started on device
return false;
}
return true;
}
final private BTChipTransport transport;
final private String name;
private int lastSW = 0;
@ -112,7 +131,7 @@ public class Ledger {
synchronized private byte[] exchangeRaw(byte[] apdu) {
if (transport == null)
throw new IllegalStateException("No transport (probably closed previously)");
Timber.i("exchangeRaw %02x", apdu[1]);
Timber.d("exchangeRaw %02x", apdu[1]);
Instruction ins = Instruction.fromByte(apdu[1]);
if (listener != null) listener.onInstructionSend(ins, apdu);
sniffOut(ins, apdu);
@ -120,7 +139,6 @@ public class Ledger {
if (listener != null) listener.onInstructionReceive(ins, data);
sniffIn(data);
return data;
}
private byte[] exchange(byte[] apdu) throws BTChipException {
@ -148,68 +166,19 @@ public class Ledger {
throw new BTChipException("Invalid status", lastSW);
}
private byte[] exchangeApdu(byte cla, byte ins, byte p1, byte p2, byte[] data, int acceptedSW[]) throws BTChipException {
byte[] apdu = new byte[data.length + 5];
apdu[0] = cla;
apdu[1] = ins;
apdu[2] = p1;
apdu[3] = p2;
apdu[4] = (byte) (data.length);
System.arraycopy(data, 0, apdu, 5, data.length);
private byte[] exchangeApduNoOpt(Instruction instruction, byte[] data, int acceptedSW[])
throws BTChipException {
byte[] apdu = new byte[data.length + 6];
apdu[0] = PROTOCOL_VERSION;
apdu[1] = instruction.getByteValue();
apdu[2] = 0; // p1
apdu[3] = 0; // p2
apdu[4] = (byte) (data.length + 1); // +1 because the opt byte is part of the data
apdu[5] = 0; // opt
System.arraycopy(data, 0, apdu, 6, data.length);
return exchangeCheck(apdu, acceptedSW);
}
private byte[] exchangeApdu(byte cla, byte ins, byte p1, byte p2, int length, int acceptedSW[]) throws BTChipException {
byte[] apdu = new byte[5];
apdu[0] = cla;
apdu[1] = ins;
apdu[2] = p1;
apdu[3] = p2;
apdu[4] = (byte) (length);
return exchangeCheck(apdu, acceptedSW);
}
private byte[] exchangeApduSplit(byte cla, byte ins, byte p1, byte p2, byte[] data, int acceptedSW[]) throws BTChipException {
int offset = 0;
byte[] result = null;
while (offset < data.length) {
int blockLength = ((data.length - offset) > 255 ? 255 : data.length - offset);
byte[] apdu = new byte[blockLength + 5];
apdu[0] = cla;
apdu[1] = ins;
apdu[2] = p1;
apdu[3] = p2;
apdu[4] = (byte) (blockLength);
System.arraycopy(data, offset, apdu, 5, blockLength);
result = exchangeCheck(apdu, acceptedSW);
offset += blockLength;
}
return result;
}
private byte[] exchangeApduSplit2(byte cla, byte ins, byte p1, byte p2, byte[] data, byte[] data2, int acceptedSW[]) throws BTChipException {
int offset = 0;
byte[] result = null;
int maxBlockSize = 255 - data2.length;
while (offset < data.length) {
int blockLength = ((data.length - offset) > maxBlockSize ? maxBlockSize : data.length - offset);
boolean lastBlock = ((offset + blockLength) == data.length);
byte[] apdu = new byte[blockLength + 5 + (lastBlock ? data2.length : 0)];
apdu[0] = cla;
apdu[1] = ins;
apdu[2] = p1;
apdu[3] = p2;
apdu[4] = (byte) (blockLength + (lastBlock ? data2.length : 0));
System.arraycopy(data, offset, apdu, 5, blockLength);
if (lastBlock) {
System.arraycopy(data2, 0, apdu, 5 + blockLength, data2.length);
}
result = exchangeCheck(apdu, acceptedSW);
offset += blockLength;
}
return result;
}
public interface Listener {
void onInstructionSend(Instruction ins, byte[] apdu);
@ -251,7 +220,6 @@ public class Ledger {
if (ins == Instruction.INS_GET_KEY) {
snoopKey = (apdu[2] == 2);
}
}
private void sniffIn(byte[] data) {

View File

@ -354,4 +354,6 @@ public class WalletManager {
static public native void logWarning(String category, String message);
static public native void logError(String category, String message);
static public native String moneroVersion();
}

View File

@ -379,4 +379,6 @@
<string name="prompt_ledger_phrase">Contrasenya Ledger (avançat)</string>
<string name="bad_ledger_seed">Llavor de Ledger no vàlida!</string>
<string name="prompt_ledger_seed_warn">Introduir la vostra llavor del Ledger aquí té un elevat risc de seguretat!</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -382,4 +382,6 @@
<string name="prompt_ledger_phrase">Ledger-Passphrase (optional)</string>
<string name="bad_ledger_seed">Ungültiger Ledger-Seed!</string>
<string name="prompt_ledger_seed_warn">Deinen Ledger-Seed hier einzugeben, stellt ein erhebliches Sicherheitsrisiko dar!</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -381,4 +381,6 @@
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering your Ledger Seed here is a major security risk!</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -381,4 +381,6 @@
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering your Ledger Seed here is a major security risk!</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -371,4 +371,6 @@
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering your Ledger Seed here is a major security risk!</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -379,4 +379,6 @@
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering your Ledger Seed here is a major security risk!</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -385,4 +385,6 @@
<string name="prompt_ledger_phrase">Mot de passe Ledger (optionnel)</string>
<string name="bad_ledger_seed">Phrase mnémonique Ledger invalide !</string>
<string name="prompt_ledger_seed_warn">Saisir votre phrase mnémonique Ledger ici est un risque majeur de sécurité !</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -383,4 +383,6 @@
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering your Ledger Seed here is a major security risk!</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -384,4 +384,6 @@
<string name="prompt_ledger_phrase">Frase d\'accesso Ledger (opzionale)</string>
<string name="bad_ledger_seed">Seed di Ledger invalido!</string>
<string name="prompt_ledger_seed_warn">Inserire il tuo seed di Ledger qui è un grosso rischio!</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -427,4 +427,6 @@
<string name="prompt_ledger_phrase">Ledgerパスフレーズ (オプショナル)</string>
<string name="bad_ledger_seed">Ledgerのニーモニックシードは不正!</string>
<string name="prompt_ledger_seed_warn">ここにLedgerシードを入力するのは、大きなセキュリティリスクですよ</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -381,4 +381,6 @@
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering your Ledger Seed here is a major security risk!</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -381,4 +381,6 @@
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering your Ledger Seed here is a major security risk!</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -373,4 +373,6 @@
<string name="prompt_ledger_phrase">Senha da Ledger (opcional)</string>
<string name="bad_ledger_seed">Semente da Ledger inválida!</string>
<string name="prompt_ledger_seed_warn">Escrever a semente da sua Ledger aqui é um grande risco de segurança!</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -385,4 +385,6 @@
<string name="prompt_ledger_phrase">Palavra passe do Ledger (opcional)</string>
<string name="bad_ledger_seed">Semente do Ledger invalida!</string>
<string name="prompt_ledger_seed_warn">Introduzir a semente do Ledger aqui comporta um elevado risco de segurança!</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -381,4 +381,6 @@
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering your Ledger Seed here is a major security risk!</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -385,4 +385,6 @@
<string name="prompt_ledger_phrase">Пароль Ledger (необязательно)</string>
<string name="bad_ledger_seed">Ошибка фразы Ledger!</string>
<string name="prompt_ledger_seed_warn">Если вы пытаетесь ввести сюда фразу Ledger, это серьезная угроза для вашей безопасности!</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -382,4 +382,6 @@
<string name="prompt_ledger_phrase">Ledger fráza (voliteľné)</string>
<string name="bad_ledger_seed">Neplatný Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Vloženie Ledger Seedu sem je vážne bezpečnostné riziko!</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -382,4 +382,5 @@
<string name="bad_ledger_seed">Nevalidno seme iz knjige računa!</string>
<string name="prompt_ledger_seed_warn">Unošenje tvog semena iz knjige računa na ovom mestu ima veliki sigurnosni rizik!</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -366,4 +366,6 @@
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering your Ledger Seed here is a major security risk!</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -385,4 +385,6 @@
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering your Ledger Seed here is a major security risk!</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -303,4 +303,6 @@
<string name="prompt_ledger_phrase">Ledger密码(高级模式)</string>
<string name="bad_ledger_seed">无效的Ledger种子密语</string>
<string name="prompt_ledger_seed_warn">在此输入您的Ledger种子密语将会产生风险</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -380,4 +380,6 @@
<string name="prompt_ledger_phrase">Ledger 密碼 (選填)</string>
<string name="bad_ledger_seed">無效的 Ledger 種子碼!</string>
<string name="prompt_ledger_seed_warn">在此輸入 Ledger 種子碼可能存在嚴重的安全風險!</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -432,4 +432,6 @@
<string name="prompt_ledger_seed_warn">Entering your Ledger Seed here is a major security risk!</string>
<string name="label_account" translatable="false">%1$s (%2$s)</string>
<string name="toast_ledger_start_app">Start Monero App on %1$s</string>
</resources>

View File

@ -6,4 +6,9 @@
product-id="1"
vendor-id="11415" />
<!-- Ledger Nano X HID: VID=0x2C97 PID=0x0004 -->
<usb-device
product-id="4"
vendor-id="11415" />
</resources>