Compare commits

...
Author SHA1 Message Date
Michele Balistreri 3369498c9f bump version 2022-09-19 14:46:16 +02:00
Michele Balistreri 3bbdf13ef7 refactor the stored property 2022-09-19 14:21:29 +02:00
Michele Balistreri af61b0213a bump version 2021-11-17 14:02:23 +03:00
Michele Balistreri 31e057dc04 handle system busy error 2021-11-17 13:04:59 +03:00
Michele Balistreri 7548329c59 default pairing (#44)
use a default pairing password
2021-11-16 08:23:35 +03:00
5 changed files with 72 additions and 27 deletions
@@ -8,7 +8,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.nfc.NfcAdapter;
import android.support.annotation.Nullable;
import android.util.EventLog;
import android.util.Log;
@@ -207,6 +206,22 @@ public class SmartCard extends BroadcastReceiver implements CardListener {
log("seed loaded to card");
}
public boolean tryDefaultPairing(KeycardCommandSet cmdSet, String instanceUID, WritableMap cardInfo) throws IOException {
try {
cmdSet.autoPair("KeycardDefaultPairing");
Pairing pairing = cmdSet.getPairing();
pairings.put(instanceUID, pairing.toBase64());
cardInfo.putString("new-pairing", pairing.toBase64());
openSecureChannel(cmdSet);
return true;
} catch(APDUException e) {
Log.i(TAG, "autoOpenSecureChannel failed: " + e.getMessage());
return false;
}
}
public WritableMap getApplicationInfo() throws IOException, APDUException {
KeycardCommandSet cmdSet = new KeycardCommandSet(this.cardChannel);
ApplicationInfo info = new ApplicationInfo(cmdSet.select().checkOK().getData());
@@ -227,23 +242,25 @@ public class SmartCard extends BroadcastReceiver implements CardListener {
Boolean isPaired = false;
if (pairings.containsKey(instanceUID)) {
if (!pairings.containsKey(instanceUID)) {
isPaired = tryDefaultPairing(cmdSet, instanceUID, cardInfo);
} else {
try {
openSecureChannel(cmdSet);
isPaired = true;
} catch(APDUException e) {
Log.i(TAG, "autoOpenSecureChannel failed: " + e.getMessage());
isPaired = tryDefaultPairing(cmdSet, instanceUID, cardInfo);
}
}
if (isPaired) {
ApplicationStatus status = new ApplicationStatus(cmdSet.getStatus(KeycardCommandSet.GET_STATUS_P1_APPLICATION).checkOK().getData());
if (isPaired) {
ApplicationStatus status = new ApplicationStatus(cmdSet.getStatus(KeycardCommandSet.GET_STATUS_P1_APPLICATION).checkOK().getData());
Log.i(TAG, "PIN retry counter: " + status.getPINRetryCount());
Log.i(TAG, "PUK retry counter: " + status.getPUKRetryCount());
Log.i(TAG, "PIN retry counter: " + status.getPINRetryCount());
Log.i(TAG, "PUK retry counter: " + status.getPUKRetryCount());
cardInfo.putInt("pin-retry-counter", status.getPINRetryCount());
cardInfo.putInt("puk-retry-counter", status.getPUKRetryCount());
}
cardInfo.putInt("pin-retry-counter", status.getPINRetryCount());
cardInfo.putInt("puk-retry-counter", status.getPUKRetryCount());
}
cardInfo.putBoolean("has-master-key?", info.hasMasterKey());
@@ -1,6 +1,5 @@
package im.status.ethereum.keycard;
import android.support.annotation.NonNull;
import android.util.Base64;
import static android.util.Base64.NO_PADDING;
@@ -29,9 +28,8 @@ public class SmartCardSecrets {
this.pairingPassword = pairingPassword;
}
@NonNull
public static SmartCardSecrets generate(final String userPin) throws NoSuchAlgorithmException, InvalidKeySpecException {
String pairingPassword = randomToken(5);
String pairingPassword = "KeycardDefaultPairing";
long pinNumber = randomLong(PIN_BOUND);
long pukNumber = randomLong(PUK_BOUND);
+31 -11
View File
@@ -20,11 +20,11 @@ class SmartCard {
func initialize(channel: CardChannel, pin: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) throws -> Void {
let puk = self.randomPUK()
let pairingPassword = self.randomPairingPassword();
let pairingPassword = "KeycardDefaultPairing"
let cmdSet = KeycardCommandSet(cardChannel: channel)
try cmdSet.select().checkOK()
try cmdSet.initialize(pin: pin, puk: puk, pairingPassword: pairingPassword).checkOK();
try cmdSet.initialize(pin: pin, puk: puk, pairingPassword: pairingPassword).checkOK()
resolve(["pin": pin, "puk": puk, "password": pairingPassword])
}
@@ -129,19 +129,21 @@ class SmartCard {
try openSecureChannel(cmdSet: cmdSet)
isPaired = true
} catch let error as CardError {
os_log("autoOpenSecureChannel failed: %@", String(describing: error));
isPaired = try tryDefaultPairing(cmdSet: cmdSet, cardInfo: &cardInfo)
} catch let error as StatusWord {
os_log("autoOpenSecureChannel failed: %@", String(describing: error));
isPaired = try tryDefaultPairing(cmdSet: cmdSet, cardInfo: &cardInfo)
}
} else {
isPaired = try tryDefaultPairing(cmdSet: cmdSet, cardInfo: &cardInfo)
}
if (isPaired) {
let status = try ApplicationStatus(cmdSet.getStatus(info: GetStatusP1.application.rawValue).checkOK().data);
os_log("PIN retry counter: %d", status.pinRetryCount)
os_log("PUK retry counter: %d", status.pukRetryCount)
if (isPaired) {
let status = try ApplicationStatus(cmdSet.getStatus(info: GetStatusP1.application.rawValue).checkOK().data);
os_log("PIN retry counter: %d", status.pinRetryCount)
os_log("PUK retry counter: %d", status.pukRetryCount)
cardInfo["pin-retry-counter"] = status.pinRetryCount
cardInfo["puk-retry-counter"] = status.pukRetryCount
}
cardInfo["pin-retry-counter"] = status.pinRetryCount
cardInfo["puk-retry-counter"] = status.pukRetryCount
}
cardInfo["paired?"] = isPaired
@@ -369,6 +371,24 @@ class SmartCard {
return cmdSet
}
func tryDefaultPairing(cmdSet: KeycardCommandSet, cardInfo: inout [String: Any]) throws -> Bool {
do {
try cmdSet.autoPair(password: "KeycardDefaultPairing")
let pairing = Data(cmdSet.pairing!.bytes).base64EncodedString()
self.pairings[bytesToHex(cmdSet.info!.instanceUID)] = pairing
cardInfo["new-pairing"] = pairing
try openSecureChannel(cmdSet: cmdSet)
return true
} catch let error as CardError {
os_log("autoOpenSecureChannel failed: %@", String(describing: error));
} catch let error as StatusWord {
os_log("autoOpenSecureChannel failed: %@", String(describing: error));
}
return false
}
func openSecureChannel(cmdSet: KeycardCommandSet) throws -> Void {
if let pairingBase64 = self.pairings[bytesToHex(cmdSet.info!.instanceUID)] {
cmdSet.pairing = try base64ToPairing(pairingBase64)
+12 -2
View File
@@ -9,8 +9,18 @@ class StatusKeycard: RCTEventEmitter {
var cardChannel: CardChannel? = nil
var nfcStartPrompt: String = "Hold your iPhone near a Status Keycard."
private var _keycardController: Any? = nil
@available(iOS 13.0, *)
private(set) lazy var keycardController: KeycardController? = nil
private var keycardController: KeycardController? {
get {
return _keycardController as? KeycardController
}
set(kc) {
_keycardController = kc
}
}
@objc
func nfcIsSupported(_ resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
@@ -199,7 +209,7 @@ class StatusKeycard: RCTEventEmitter {
let nsError = error as NSError
if nsError.code == 200 && nsError.domain == "NFCError" {
self.sendEvent(withName: "keyCardOnNFCUserCancelled", body: nil)
} else if nsError.code == 201 && nsError.domain == "NFCError" {
} else if (nsError.code == 201 || nsError.code == 203) && (nsError.domain == "NFCError") {
self.sendEvent(withName: "keyCardOnNFCTimeout", body: nil)
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "react-native-status-keycard",
"homepage": "https://keycard.status.im/",
"version": "2.5.35",
"version": "2.5.38",
"description": "React Native library to interact with Status Keycard using NFC connection",
"main": "index.js",
"scripts": {