From 8cf7cbff803b080b2069202ea6179703b8c69d2e Mon Sep 17 00:00:00 2001 From: Bitgamma Date: Fri, 30 Apr 2021 15:44:35 +0300 Subject: [PATCH] add factory reset (#41) add factory reset --- .../keycard/RNStatusKeycardModule.java | 14 +++++++++++ .../im/status/ethereum/keycard/SmartCard.java | 24 +++++++++++++++++++ ios/SmartCard.swift | 23 ++++++++++++++++++ ios/StatusKeycard.m | 1 + ios/StatusKeycard.swift | 5 ++++ package.json | 4 ++-- 6 files changed, 69 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/im/status/ethereum/keycard/RNStatusKeycardModule.java b/android/src/main/java/im/status/ethereum/keycard/RNStatusKeycardModule.java index 6b317ae..343bf8f 100644 --- a/android/src/main/java/im/status/ethereum/keycard/RNStatusKeycardModule.java +++ b/android/src/main/java/im/status/ethereum/keycard/RNStatusKeycardModule.java @@ -176,6 +176,20 @@ public class RNStatusKeycardModule extends ReactContextBaseJavaModule implements }).start(); } + @ReactMethod + public void factoryReset(final Promise promise) { + new Thread(new Runnable() { + public void run() { + try { + promise.resolve(smartCard.factoryReset()); + } catch (IOException | APDUException e) { + Log.d(TAG, e.getMessage()); + promise.reject(e); + } + } + }).start(); + } + @ReactMethod public void deriveKey(final String path, final String pin, final Promise promise) { new Thread(new Runnable() { diff --git a/android/src/main/java/im/status/ethereum/keycard/SmartCard.java b/android/src/main/java/im/status/ethereum/keycard/SmartCard.java index 6f4d167..81fc6f7 100644 --- a/android/src/main/java/im/status/ethereum/keycard/SmartCard.java +++ b/android/src/main/java/im/status/ethereum/keycard/SmartCard.java @@ -28,6 +28,7 @@ import java.util.Iterator; import im.status.keycard.applet.RecoverableSignature; import im.status.keycard.globalplatform.GlobalPlatformCommandSet; import im.status.keycard.io.APDUException; +import im.status.keycard.io.APDUResponse; import im.status.keycard.io.CardChannel; import im.status.keycard.io.CardListener; import im.status.keycard.android.NFCCardManager; @@ -257,6 +258,29 @@ public class SmartCard extends BroadcastReceiver implements CardListener { return cardInfo; } + public WritableMap factoryReset() throws IOException, APDUException { + GlobalPlatformCommandSet cmdSet = new GlobalPlatformCommandSet(this.cardChannel); + cmdSet.select().checkOK(); + Log.i(TAG, "ISD selected"); + + cmdSet.openSecureChannel(); + Log.i(TAG, "SecureChannel opened"); + + cmdSet.deleteKeycardInstance().checkSW(APDUResponse.SW_OK, APDUResponse.SW_REFERENCED_DATA_NOT_FOUND); + Log.i(TAG, "Keycard applet instance deleted"); + + cmdSet.installKeycardApplet().checkOK(); + Log.i(TAG, "Keycard applet instance re-installed"); + + ApplicationInfo info = new ApplicationInfo(new KeycardCommandSet(this.cardChannel).select().checkOK().getData()); + Log.i(TAG, "Selecting the newly installed Keycard applet succeeded"); + + WritableMap cardInfo = Arguments.createMap(); + cardInfo.putBoolean("initialized?", info.isInitializedCard()); + + return cardInfo; + } + public void deriveKey(final String path, final String pin) throws IOException, APDUException { KeycardCommandSet cmdSet = authenticatedCommandSet(pin); diff --git a/ios/SmartCard.swift b/ios/SmartCard.swift index aa65c0a..efe5b53 100644 --- a/ios/SmartCard.swift +++ b/ios/SmartCard.swift @@ -89,6 +89,29 @@ class SmartCard { resolve(true) } + func factoryReset(channel: CardChannel, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) throws -> Void { + let cmdSet: GlobalPlatformCommandSet = GlobalPlatformCommandSet(cardChannel: channel); + try cmdSet.select().checkOK() + os_log("ISD selected") + + try cmdSet.openSecureChannel() + os_log("SecureChannel opened") + + try cmdSet.deleteKeycardInstance().checkSW(StatusWord.ok, StatusWord.referencedDataNotFound) + os_log("Keycard applet instance deleted") + + try cmdSet.installKeycardInstance().checkOK() + os_log("Keycard applet instance re-installed") + + let info = try ApplicationInfo(KeycardCommandSet(cardChannel: channel).select().checkOK().data) + os_log("Selecting the newly installed Keycard applet succeeded") + + var cardInfo = [String: Any]() + cardInfo["initialized?"] = info.initializedCard + + resolve(cardInfo) + } + func getApplicationInfo(channel: CardChannel, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) throws -> Void { let cmdSet = KeycardCommandSet(cardChannel: channel) let info = try ApplicationInfo(cmdSet.select().checkOK().data) diff --git a/ios/StatusKeycard.m b/ios/StatusKeycard.m index 218d404..468d12c 100644 --- a/ios/StatusKeycard.m +++ b/ios/StatusKeycard.m @@ -12,6 +12,7 @@ RCT_EXTERN_METHOD(generateMnemonic:(NSString *)words resolve:(RCTPromiseResolveB RCT_EXTERN_METHOD(generateAndLoadKey:(NSString *)mnemonic pin:(NSString *)pin resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) RCT_EXTERN_METHOD(saveMnemonic:(NSString *)mnemonic pin:(NSString *)pin resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) RCT_EXTERN_METHOD(getApplicationInfo:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(factoryReset:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) RCT_EXTERN_METHOD(deriveKey:(NSString *)path pin:(NSString *)pin resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) RCT_EXTERN_METHOD(exportKey:(NSString *)pin resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) RCT_EXTERN_METHOD(exportKeyWithPath:(NSString *)pin path:(NSString *)path resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) diff --git a/ios/StatusKeycard.swift b/ios/StatusKeycard.swift index 5921c4c..701e2a7 100644 --- a/ios/StatusKeycard.swift +++ b/ios/StatusKeycard.swift @@ -58,6 +58,11 @@ class StatusKeycard: RCTEventEmitter { keycardInvokation(reject) { [unowned self] channel in try self.smartCard.saveMnemonic(channel: channel, mnemonic: mnemonic, pin: pin, resolve: resolve, reject: reject) } } + @objc + func factoryReset(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void { + keycardInvokation(reject) { [unowned self] channel in try self.smartCard.factoryReset(channel: channel, resolve: resolve, reject: reject) } + } + @objc func getApplicationInfo(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void { keycardInvokation(reject) { [unowned self] channel in try self.smartCard.getApplicationInfo(channel: channel, resolve: resolve, reject: reject) } diff --git a/package.json b/package.json index c93c700..4620166 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "react-native-status-keycard", "homepage": "https://keycard.status.im/", - "version": "2.5.34", - "description": "React Native library to interact with Status Keycard using NFC connection (Android only)", + "version": "2.5.35", + "description": "React Native library to interact with Status Keycard using NFC connection", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1"