Skip to content

Commit 5b456ea

Browse files
committed
avoid NPE on disconnected cards
1 parent e78f46d commit 5b456ea

File tree

1 file changed

+41
-10
lines changed

1 file changed

+41
-10
lines changed

android/src/main/java/im/status/ethereum/keycard/SmartCard.java

+41-10
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public class SmartCard extends BroadcastReceiver implements CardListener {
6262
private static final String WALLET_PATH = "m/44'/60'/0'/0/0";
6363
private static final String WHISPER_PATH = "m/43'/60'/1581'/0'/0";
6464
private static final String ENCRYPTION_PATH = "m/43'/60'/1581'/1'/0";
65+
private static final String TAG_LOST = "Tag was lost.";
6566
private static final int WORDS_LIST_SIZE = 2048;
6667

6768
public SmartCard(ReactContext reactContext) {
@@ -177,7 +178,7 @@ public boolean isNfcEnabled() {
177178
}
178179

179180
public SmartCardSecrets init(final String userPin) throws IOException, APDUException, NoSuchAlgorithmException, InvalidKeySpecException {
180-
KeycardCommandSet cmdSet = new KeycardCommandSet(this.cardChannel);
181+
KeycardCommandSet cmdSet = commandSet();
181182
cmdSet.select().checkOK();
182183

183184
SmartCardSecrets s = SmartCardSecrets.generate(userPin);
@@ -186,7 +187,7 @@ public SmartCardSecrets init(final String userPin) throws IOException, APDUExcep
186187
}
187188

188189
public String pair(String pairingPassword) throws IOException, APDUException {
189-
KeycardCommandSet cmdSet = new KeycardCommandSet(this.cardChannel);
190+
KeycardCommandSet cmdSet = commandSet();
190191
Log.i(TAG, "Applet selection successful");
191192

192193
// First thing to do is selecting the applet on the card.
@@ -282,7 +283,7 @@ private boolean verifyAuthenticity(KeycardCommandSet cmdSet, String instanceUID)
282283
}
283284

284285
public WritableMap getApplicationInfo() throws IOException, APDUException {
285-
KeycardCommandSet cmdSet = new KeycardCommandSet(this.cardChannel);
286+
KeycardCommandSet cmdSet = commandSet();
286287
ApplicationInfo info = new ApplicationInfo(cmdSet.select().checkOK().getData());
287288

288289
Log.i(TAG, "Card initialized? " + info.isInitializedCard());
@@ -348,7 +349,7 @@ public WritableMap getApplicationInfo() throws IOException, APDUException {
348349
}
349350

350351
public WritableMap factoryResetPost() throws IOException, APDUException {
351-
ApplicationInfo info = new ApplicationInfo(new KeycardCommandSet(this.cardChannel).select().checkOK().getData());
352+
ApplicationInfo info = new ApplicationInfo(commandSet().select().checkOK().getData());
352353
Log.i(TAG, "Selecting the factory reset Keycard applet succeeded");
353354

354355
WritableMap cardInfo = Arguments.createMap();
@@ -358,7 +359,7 @@ public WritableMap factoryResetPost() throws IOException, APDUException {
358359
}
359360

360361
public WritableMap factoryResetFallback() throws IOException, APDUException {
361-
GlobalPlatformCommandSet cmdSet = new GlobalPlatformCommandSet(this.cardChannel);
362+
GlobalPlatformCommandSet cmdSet = gpCommandSet();
362363
cmdSet.select().checkOK();
363364
Log.i(TAG, "ISD selected");
364365

@@ -375,7 +376,7 @@ public WritableMap factoryResetFallback() throws IOException, APDUException {
375376
}
376377

377378
public WritableMap factoryReset() throws IOException, APDUException {
378-
KeycardCommandSet cmdSet = new KeycardCommandSet(this.cardChannel);
379+
KeycardCommandSet cmdSet = commandSet();
379380
APDUResponse resp = cmdSet.select();
380381

381382
if (!resp.isOK()) {
@@ -661,7 +662,7 @@ public String signWithPath(final String pin, final String path, final String mes
661662
}
662663

663664
public String signPinless(final String message) throws IOException, APDUException {
664-
CashCommandSet cmdSet = new CashCommandSet(this.cardChannel);
665+
CashCommandSet cmdSet = cashCommandSet();
665666
cmdSet.select().checkOK();
666667

667668
byte[] hash = Hex.decode(message);
@@ -685,7 +686,7 @@ public String signPinless(final String message) throws IOException, APDUExceptio
685686
}
686687

687688
public String getCardName() throws IOException, APDUException {
688-
KeycardCommandSet cmdSet = new KeycardCommandSet(this.cardChannel);
689+
KeycardCommandSet cmdSet = commandSet();
689690
cmdSet.select().checkOK();
690691
return getCardNameOrDefault(cmdSet);
691692
}
@@ -698,7 +699,7 @@ public void setCardName(final String pin, final String name) throws IOException,
698699
}
699700

700701
public WritableMap verifyCard(final String challenge) throws IOException, APDUException {
701-
KeycardCommandSet cmdSet = new KeycardCommandSet(this.cardChannel);
702+
KeycardCommandSet cmdSet = commandSet();
702703
cmdSet.select().checkOK();
703704
byte[] rawChallenge = Hex.decode(challenge);
704705
byte[] data = cmdSet.identifyCard(rawChallenge).checkOK().getData();
@@ -742,13 +743,43 @@ private KeycardCommandSet authenticatedCommandSet(String pin) throws IOException
742743
}
743744

744745
private KeycardCommandSet securedCommandSet() throws IOException, APDUException {
745-
KeycardCommandSet cmdSet = new KeycardCommandSet(this.cardChannel);
746+
KeycardCommandSet cmdSet = commandSet();
746747
cmdSet.select().checkOK();
747748
openSecureChannel(cmdSet);
748749

749750
return cmdSet;
750751
}
751752

753+
private KeycardCommandSet commandSet() throws IOException {
754+
synchronized(lock) {
755+
if (this.cardChannel != null) {
756+
return new KeycardCommandSet(this.cardChannel);
757+
}
758+
}
759+
760+
throw new IOException(TAG_LOST);
761+
}
762+
763+
private CashCommandSet cashCommandSet() throws IOException {
764+
synchronized(lock) {
765+
if (this.cardChannel != null) {
766+
return new CashCommandSet(this.cardChannel);
767+
}
768+
}
769+
770+
throw new IOException(TAG_LOST);
771+
}
772+
773+
private GlobalPlatformCommandSet gpCommandSet() throws IOException {
774+
synchronized(lock) {
775+
if (this.cardChannel != null) {
776+
return new GlobalPlatformCommandSet(this.cardChannel);
777+
}
778+
}
779+
780+
throw new IOException(TAG_LOST);
781+
}
782+
752783
private String getCardNameOrDefault(KeycardCommandSet cmdSet) throws IOException, APDUException {
753784
byte[] data = cmdSet.getData(KeycardCommandSet.STORE_DATA_P1_PUBLIC).checkOK().getData();
754785

0 commit comments

Comments
 (0)