add Reinstall command
This commit is contained in:
parent
48c3e70180
commit
714d9be6f7
|
@ -29,6 +29,7 @@
|
|||
<activity android:name=".ui.InitActivity" />
|
||||
<activity android:name=".ui.PairingActivity" />
|
||||
<activity android:name=".ui.PINActivity" />
|
||||
<activity android:name=".ui.ReinstallActivity" />
|
||||
<activity
|
||||
android:name=".ui.MainActivity"
|
||||
android:label="@string/app_name">
|
||||
|
|
|
@ -8,7 +8,7 @@ import im.status.keycard.io.CardChannel
|
|||
import im.status.keycard.io.CardListener
|
||||
|
||||
class CardScriptExecutor(private val listener: ScriptListener) : CardListener {
|
||||
data class ScriptContext(val activity: Activity, val cmdSet: KeycardCommandSet)
|
||||
data class ScriptContext(val activity: Activity, val channel: CardChannel, val cmdSet: KeycardCommandSet)
|
||||
|
||||
enum class State {
|
||||
READY, UX_ONGOING, RUNNING
|
||||
|
@ -21,7 +21,7 @@ class CardScriptExecutor(private val listener: ScriptListener) : CardListener {
|
|||
private var waitingCmd: CardCommand? = null
|
||||
|
||||
override fun onConnected(channel: CardChannel) {
|
||||
val executionContext = ScriptContext(Registry.mainActivity, KeycardCommandSet(channel))
|
||||
val executionContext = ScriptContext(Registry.mainActivity, channel, KeycardCommandSet(channel))
|
||||
|
||||
if (state == State.READY) {
|
||||
startScript()
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package im.status.keycard.connect.card
|
||||
|
||||
import android.net.Uri
|
||||
import im.status.keycard.connect.Registry
|
||||
import im.status.keycard.globalplatform.GlobalPlatformCommandSet
|
||||
|
||||
class ReinstallCommand(private val applet: Uri, private val installWallet: Boolean, private val installCash: Boolean, private val installNDEF: Boolean, private val cashParams: ByteArray = ByteArray(0), private val ndefParams: ByteArray = ByteArray(0)) : CardCommand {
|
||||
override fun run(context: CardScriptExecutor.ScriptContext): CardCommand.Result {
|
||||
return runOnCard {
|
||||
val gpCmd = GlobalPlatformCommandSet(context.channel)
|
||||
gpCmd.select().checkOK()
|
||||
gpCmd.openSecureChannel()
|
||||
gpCmd.deleteKeycardInstancesAndPackage()
|
||||
|
||||
Registry.mainActivity.applicationContext.contentResolver.openInputStream(applet)?.use {
|
||||
gpCmd.loadKeycardPackage(it) {_, _ -> }
|
||||
}
|
||||
|
||||
if (installWallet) { gpCmd.installKeycardApplet().checkOK() }
|
||||
if (installCash) { gpCmd.installCashApplet(cashParams).checkOK() }
|
||||
if (installNDEF) { gpCmd.installNDEFApplet(ndefParams).checkOK() }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,6 +30,7 @@ const val MNEMONIC_PHRASE = "mnemonicPhrase"
|
|||
const val REQ_INTERACTIVE_SCRIPT = 0x01
|
||||
const val REQ_WALLETCONNECT = 0x02
|
||||
const val REQ_LOADKEY = 0x03
|
||||
const val REQ_APPLET_FILE = 0x04
|
||||
|
||||
const val CACHE_VALIDITY = 15 * 60 * 1000
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import im.status.keycard.connect.card.scriptWithAuthentication
|
|||
|
||||
class ChangePairingPasswordActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
//TODO: puk validation and confirmation
|
||||
//TODO: pairing password confirmation
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_change_pairing_password)
|
||||
}
|
||||
|
|
|
@ -106,6 +106,10 @@ class MainActivity : AppCompatActivity(), ScriptListener {
|
|||
Registry.scriptExecutor.runScript(scriptWithAuthentication().plus(RemoveKeyCommand()))
|
||||
}
|
||||
|
||||
fun reinstall(@Suppress("UNUSED_PARAMETER") view: View) {
|
||||
startCommand(ReinstallActivity::class)
|
||||
}
|
||||
|
||||
fun settings(@Suppress("UNUSED_PARAMETER") view: View) {
|
||||
startCommand(SettingsActivity::class)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package im.status.keycard.connect.ui
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.CheckBox
|
||||
import im.status.keycard.connect.R
|
||||
import im.status.keycard.connect.Registry
|
||||
import im.status.keycard.connect.card.ReinstallCommand
|
||||
import im.status.keycard.connect.data.REQ_APPLET_FILE
|
||||
|
||||
class ReinstallActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_reinstall)
|
||||
}
|
||||
|
||||
fun reinstall(@Suppress("UNUSED_PARAMETER") view: View) {
|
||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
type = "*/*"
|
||||
}
|
||||
|
||||
startActivityForResult(intent, REQ_APPLET_FILE)
|
||||
}
|
||||
|
||||
fun cancel(@Suppress("UNUSED_PARAMETER") view: View) {
|
||||
finish()
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
|
||||
if (requestCode == REQ_APPLET_FILE && resultCode == RESULT_OK) {
|
||||
val reinstallWallet = findViewById<CheckBox>(R.id.reinstallWalletCheckbox).isChecked
|
||||
val reinstallCash = findViewById<CheckBox>(R.id.reinstallCashCheckbox).isChecked
|
||||
val reinstallNDEF = findViewById<CheckBox>(R.id.reinstallNDEFCheckbox).isChecked
|
||||
data?.data?.also { uri ->
|
||||
val script = listOf(ReinstallCommand(uri, reinstallWallet, reinstallCash, reinstallNDEF))
|
||||
Registry.scriptExecutor.runScript(script)
|
||||
}
|
||||
}
|
||||
|
||||
finish()
|
||||
}
|
||||
}
|
|
@ -23,7 +23,6 @@
|
|||
android:id="@+id/walletConnectButton"
|
||||
android:layout_width="236dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:onClick="connectWallet"
|
||||
android:text="@string/connect_wallet"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
@ -96,6 +95,18 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/changeKeyButton" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/reinstall"
|
||||
android:layout_width="236dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:onClick="reinstall"
|
||||
android:text="@string/reinstall"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.497"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/removeKey" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/settingsButton"
|
||||
android:layout_width="236dp"
|
||||
|
@ -105,5 +116,5 @@
|
|||
android:text="@string/settings"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/removeKey" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/reinstall" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,88 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ui.ReinstallActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/reinstallPrompt"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="52dp"
|
||||
android:text="@string/reinstall_applet_prompt"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Display1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.497"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/reinstallWarning"
|
||||
android:layout_width="327dp"
|
||||
android:layout_height="127dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:text="@string/reinstall_warning"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/reinstallPrompt" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/reinstallWalletCheckbox"
|
||||
android:layout_width="324dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:checked="true"
|
||||
android:text="@string/reinstall_wallet_checkbox"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/reinstallWarning" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/reinstallCashCheckbox"
|
||||
android:layout_width="324dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:checked="true"
|
||||
android:text="@string/reinstall_cash_checkbox"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.494"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/reinstallWalletCheckbox" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/reinstallNDEFCheckbox"
|
||||
android:layout_width="324dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:checked="true"
|
||||
android:text="@string/reinstall_ndef_checkbox"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.494"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/reinstallCashCheckbox" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancelButton"
|
||||
android:layout_width="324dp"
|
||||
android:layout_height="49dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:onClick="cancel"
|
||||
android:text="@android:string/cancel"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/reinstallNDEFCheckbox" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/reinstallButton"
|
||||
android:layout_width="324dp"
|
||||
android:layout_height="49dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:onClick="reinstall"
|
||||
android:text="@string/reinstall_button"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/cancelButton" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -37,4 +37,11 @@
|
|||
<string name="wallet_path_label">Wallet Path</string>
|
||||
<string name="wallet_path_hint">m/44\'/...</string>
|
||||
<string name="settings">Settings</string>
|
||||
<string name="reinstall">(Re)install applet</string>
|
||||
<string name="reinstall_applet_prompt">Reinstall applet</string>
|
||||
<string name="reinstall_warning">WARNING: Reinstalling the applet completely destroys the currently loaded keys and resets all credentials. Make sure you have your seed phrase somewhere to restore from. Additionally, JCOP3 cards can be destroyed if the connection is lost during this process. Hold the card tightly to the phone!</string>
|
||||
<string name="reinstall_wallet_checkbox">Install Wallet applet</string>
|
||||
<string name="reinstall_cash_checkbox">Install Cash applet</string>
|
||||
<string name="reinstall_ndef_checkbox">Install NDEF applet</string>
|
||||
<string name="reinstall_button">Select cap file and install</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue