diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/ResetAndWipeUseCase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/ResetAndWipeUseCase.java new file mode 100644 index 000000000..84df31b53 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/ResetAndWipeUseCase.java @@ -0,0 +1,68 @@ +package org.sufficientlysecure.keychain.securitytoken; + + +import java.io.IOException; + + +public class ResetAndWipeUseCase { + private final SecurityTokenConnection connection; + + public static ResetAndWipeUseCase create(SecurityTokenConnection connection) { + return new ResetAndWipeUseCase(connection); + } + + private ResetAndWipeUseCase(SecurityTokenConnection connection) { + this.connection = connection; + } + + /** + * Resets security token, which deletes all keys and data objects. + * This works by entering a wrong PIN and then Admin PIN 4 times respectively. + * Afterwards, the token is reactivated. + */ + public void resetAndWipeToken() throws IOException { + // try wrong PIN 4 times until counter goes to C0 + byte[] pin = "XXXXXX".getBytes(); + CommandApdu verifyPw1ForSignatureCommand = + connection.getCommandFactory().createVerifyPw1ForSignatureCommand(pin); + for (int i = 0; i <= 4; i++) { + // Command APDU for VERIFY command (page 32) + ResponseApdu response = connection.communicate(verifyPw1ForSignatureCommand); + if (response.isSuccess()) { + throw new CardException("Should never happen, XXXXXX has been accepted!", response.getSw()); + } + } + + // try wrong Admin PIN 4 times until counter goes to C0 + byte[] adminPin = "XXXXXXXX".getBytes(); + CommandApdu verifyPw3Command = connection.getCommandFactory().createVerifyPw3Command(adminPin); + for (int i = 0; i <= 4; i++) { + // Command APDU for VERIFY command (page 32) + ResponseApdu response = connection.communicate( + verifyPw3Command); + if (response.isSuccess()) { // Should NOT accept! + throw new CardException("Should never happen, XXXXXXXX has been accepted", response.getSw()); + } + } + + // secure messaging must be disabled before reactivation + connection.clearSecureMessaging(); + + // reactivate token! + // NOTE: keep the order here! First execute _both_ reactivate commands. Before checking _both_ responses + // If a token is in a bad state and reactivate1 fails, it could still be reactivated with reactivate2 + CommandApdu reactivate1 = connection.getCommandFactory().createReactivate1Command(); + ResponseApdu response1 = connection.communicate(reactivate1); + if (!response1.isSuccess()) { + throw new CardException("Reactivating failed!", response1.getSw()); + } + + CommandApdu reactivate2 = connection.getCommandFactory().createReactivate2Command(); + ResponseApdu response2 = connection.communicate(reactivate2); + if (!response2.isSuccess()) { + throw new CardException("Reactivating failed!", response2.getSw()); + } + + connection.refreshConnectionCapabilities(); + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenConnection.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenConnection.java index a158aed3a..f10cefe52 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenConnection.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenConnection.java @@ -448,52 +448,6 @@ public class SecurityTokenConnection { return response.getData(); } - /** - * Resets security token, which deletes all keys and data objects. - * This works by entering a wrong PIN and then Admin PIN 4 times respectively. - * Afterwards, the token is reactivated. - */ - public void resetAndWipeToken() throws IOException { - // try wrong PIN 4 times until counter goes to C0 - byte[] pin = "XXXXXX".getBytes(); - for (int i = 0; i <= 4; i++) { - // Command APDU for VERIFY command (page 32) - ResponseApdu response = communicate(commandFactory.createVerifyPw1ForSignatureCommand(pin)); - if (response.isSuccess()) { - throw new CardException("Should never happen, XXXXXX has been accepted!", response.getSw()); - } - } - - // try wrong Admin PIN 4 times until counter goes to C0 - byte[] adminPin = "XXXXXXXX".getBytes(); - for (int i = 0; i <= 4; i++) { - // Command APDU for VERIFY command (page 32) - ResponseApdu response = communicate(commandFactory.createVerifyPw3Command(adminPin)); - if (response.isSuccess()) { // Should NOT accept! - throw new CardException("Should never happen, XXXXXXXX has been accepted", response.getSw()); - } - } - - // secure messaging must be disabled before reactivation - clearSecureMessaging(); - - // reactivate token! - // NOTE: keep the order here! First execute _both_ reactivate commands. Before checking _both_ responses - // If a token is in a bad state and reactivate1 fails, it could still be reactivated with reactivate2 - CommandApdu reactivate1 = commandFactory.createReactivate1Command(); - CommandApdu reactivate2 = commandFactory.createReactivate2Command(); - ResponseApdu response1 = communicate(reactivate1); - ResponseApdu response2 = communicate(reactivate2); - if (!response1.isSuccess()) { - throw new CardException("Reactivating failed!", response1.getSw()); - } - if (!response2.isSuccess()) { - throw new CardException("Reactivating failed!", response2.getSw()); - } - - refreshConnectionCapabilities(); - } - /** * Return the fingerprint from application specific data stored on tag, or * null if it doesn't exist. diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SecurityTokenOperationActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SecurityTokenOperationActivity.java index 1d6642523..a40570538 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SecurityTokenOperationActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SecurityTokenOperationActivity.java @@ -45,6 +45,7 @@ import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo; import org.sufficientlysecure.keychain.securitytoken.PsoDecryptUseCase; import org.sufficientlysecure.keychain.securitytoken.SecurityTokenPsoSignUseCase; import org.sufficientlysecure.keychain.securitytoken.SecurityTokenChangeKeyUseCase; +import org.sufficientlysecure.keychain.securitytoken.ResetAndWipeUseCase; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; @@ -306,7 +307,7 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenActivity { break; } case SECURITY_TOKEN_RESET_CARD: { - stConnection.resetAndWipeToken(); + ResetAndWipeUseCase.create(stConnection).resetAndWipeToken(); mResultTokenInfo = stConnection.getTokenInfo(); break;