token-import: add entrypoint for blank token setup flow

This commit is contained in:
Vincent Breitmoser
2017-09-11 01:42:04 +02:00
parent 19bb4ff83c
commit e0b5d97356
9 changed files with 116 additions and 214 deletions

View File

@@ -1,6 +1,8 @@
package org.sufficientlysecure.keychain.securitytoken;
import java.util.Arrays;
import android.os.Parcelable;
import android.support.annotation.Nullable;
@@ -12,6 +14,8 @@ import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
@AutoValue
public abstract class SecurityTokenInfo implements Parcelable {
private static final byte[] EMPTY_ARRAY = new byte[20];
@Nullable
public abstract byte[] getFingerprintSign();
@Nullable
@@ -36,7 +40,8 @@ public abstract class SecurityTokenInfo implements Parcelable {
}
public boolean isEmpty() {
return getFingerprintSign() == null && getFingerprintDecrypt() == null && getFingerprintAuth() == null;
return Arrays.equals(EMPTY_ARRAY, getFingerprintSign()) && Arrays.equals(EMPTY_ARRAY, getFingerprintDecrypt()) &&
Arrays.equals(EMPTY_ARRAY, getFingerprintAuth());
}
public static SecurityTokenInfo create(byte[] fpSign, byte[] fpDecrypt, byte[] fpAuth,
@@ -45,10 +50,6 @@ public abstract class SecurityTokenInfo implements Parcelable {
userId, url, verifyRetries, verifyAdminRetries);
}
public static SecurityTokenInfo createBlank(byte[] aid) {
return new AutoValue_SecurityTokenInfo(null, null, null, aid, null, null, 0, 0);
}
public static SecurityTokenInfo newInstanceDebugKeyserver() {
if (!BuildConfig.DEBUG) {
throw new UnsupportedOperationException("This operation is only available in debug builds!");

View File

@@ -110,16 +110,9 @@ public class CreateKeyActivity extends BaseSecurityTokenActivity {
if (intent.hasExtra(EXTRA_SECURITY_TOKEN_INFO)) {
SecurityTokenInfo tokenInfo = intent.getParcelableExtra(EXTRA_SECURITY_TOKEN_INFO);
if (!tokenInfo.isEmpty()) {
Fragment frag = ManageSecurityTokenFragment.newInstance(tokenInfo);
loadFragment(frag, FragAction.START);
setTitle(R.string.title_import_keys);
} else {
Fragment frag = CreateSecurityTokenBlankFragment.newInstance();
loadFragment(frag, FragAction.START);
setTitle(R.string.title_manage_my_keys);
}
Fragment frag = ManageSecurityTokenFragment.newInstance(tokenInfo);
loadFragment(frag, FragAction.START);
setTitle(R.string.title_manage_my_keys);
// done
return;
@@ -164,15 +157,10 @@ public class CreateKeyActivity extends BaseSecurityTokenActivity {
CreateSecurityTokenWaitFragment.sDisableFragmentAnimations = false;
}
if (!tokenInfo.isEmpty()) {
Fragment frag = ManageSecurityTokenFragment.newInstance(tokenInfo);
if (mCurrentFragment instanceof ManageSecurityTokenFragment) {
loadFragment(frag, FragAction.REPLACE);
} else {
loadFragment(frag, FragAction.TO_RIGHT);
}
Fragment frag = ManageSecurityTokenFragment.newInstance(tokenInfo);
if (mCurrentFragment instanceof ManageSecurityTokenFragment) {
loadFragment(frag, FragAction.REPLACE);
} else {
Fragment frag = CreateSecurityTokenBlankFragment.newInstance();
loadFragment(frag, FragAction.TO_RIGHT);
}
}
@@ -196,6 +184,14 @@ public class CreateKeyActivity extends BaseSecurityTokenActivity {
setContentView(R.layout.create_key_activity);
}
public void startCreateKeyForSecurityToken(SecurityTokenInfo tokenInfo) {
mCreateSecurityToken = true;
this.tokenInfo = tokenInfo;
CreateKeyNameFragment frag = CreateKeyNameFragment.newInstance();
loadFragment(frag, FragAction.TO_RIGHT);
}
public enum FragAction {
START,
TO_RIGHT,

View File

@@ -1,86 +0,0 @@
/*
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.ui;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
public class CreateSecurityTokenBlankFragment extends Fragment {
CreateKeyActivity mCreateKeyActivity;
View mBackButton;
View mNextButton;
/**
* Creates new instance of this fragment
*/
public static CreateSecurityTokenBlankFragment newInstance() {
return new CreateSecurityTokenBlankFragment();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.create_yubi_key_blank_fragment, container, false);
mBackButton = view.findViewById(R.id.create_key_back_button);
mNextButton = view.findViewById(R.id.create_key_next_button);
mBackButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (getFragmentManager().getBackStackEntryCount() == 0) {
getActivity().setResult(Activity.RESULT_CANCELED);
getActivity().finish();
} else {
mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT);
}
}
});
mNextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
nextClicked();
}
});
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mCreateKeyActivity = (CreateKeyActivity) getActivity();
}
private void nextClicked() {
mCreateKeyActivity.mCreateSecurityToken = true;
CreateKeyNameFragment frag = CreateKeyNameFragment.newInstance();
mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT);
}
}

View File

@@ -56,6 +56,8 @@ class ManageSecurityTokenContract {
void onSecurityTokenResetSuccess(SecurityTokenInfo tokenInfo);
void onSecurityTokenResetCanceled(SecurityTokenInfo tokenInfo);
void onClickSetupToken();
void onClickUnlockToken();
void onMenuClickChangePin();
void onInputAdminPin(String adminPin, String newPin);
@@ -73,6 +75,7 @@ class ManageSecurityTokenContract {
void showActionViewKey();
void showActionRetryOrFromFile();
void showActionLocked(int unlockAttempts);
void showActionEmptyToken();
void hideAction();
void operationImportKey(byte[] importKeyData);
@@ -85,6 +88,7 @@ class ManageSecurityTokenContract {
void showFileSelectDialog();
void showConfirmResetDialog();
void showAdminPinDialog();
void startCreateKeyForToken(SecurityTokenInfo tokenInfo);
void showDisplayLogActivity(OperationResult result);

View File

@@ -130,6 +130,7 @@ public class ManageSecurityTokenFragment extends Fragment implements ManageSecur
view.findViewById(R.id.button_unlock).setOnClickListener(this);
view.findViewById(R.id.button_unlock_impossible).setOnClickListener(this);
view.findViewById(R.id.button_load_file).setOnClickListener(this);
view.findViewById(R.id.button_setup).setOnClickListener(this);
setHasOptionsMenu(true);
@@ -253,6 +254,11 @@ public class ManageSecurityTokenFragment extends Fragment implements ManageSecur
}
}
@Override
public void showActionEmptyToken() {
actionAnimator.setDisplayedChildId(R.id.token_layout_empty);
}
@Override
public void hideAction() {
actionAnimator.setDisplayedChild(0);
@@ -325,6 +331,12 @@ public class ManageSecurityTokenFragment extends Fragment implements ManageSecur
adminPinDialog.show();
}
@Override
public void startCreateKeyForToken(SecurityTokenInfo tokenInfo) {
CreateKeyActivity activity = (CreateKeyActivity) getActivity();
activity.startCreateKeyForSecurityToken(tokenInfo);
}
@Override
public void showErrorCannotUnlock() {
Notify.create(getActivity(), R.string.token_error_locked_indefinitely, Style.ERROR).show();
@@ -430,6 +442,11 @@ public class ManageSecurityTokenFragment extends Fragment implements ManageSecur
presenter.onClickUnlockTokenImpossible();
break;
}
case R.id.button_setup: {
presenter.onClickSetupToken();
break;
}
}
}

View File

@@ -107,7 +107,8 @@ class ManageSecurityTokenPresenter implements ManageSecurityTokenMvpPresenter {
private void continueSearch() {
if (!checkedKeyStatus) {
boolean keyIsLocked = tokenInfo.getVerifyRetries() == 0;
if (keyIsLocked) {
boolean keyIsEmpty = tokenInfo.isEmpty();
if (keyIsLocked || keyIsEmpty) {
// the "checking key status" is fake: we only do it if we already know the key is locked
view.statusLineAdd(StatusLine.CHECK_KEY);
delayPerformKeyCheck();
@@ -148,19 +149,27 @@ class ManageSecurityTokenPresenter implements ManageSecurityTokenMvpPresenter {
}
private void performKeyCheck() {
boolean isLocked = tokenInfo.getVerifyRetries() == 0;
if (!isLocked) {
boolean keyIsEmpty = tokenInfo.isEmpty();
if (keyIsEmpty) {
view.statusLineOk();
checkedKeyStatus = true;
continueSearch();
view.showActionEmptyToken();
return;
}
view.statusLineError();
boolean keyIsLocked = tokenInfo.getVerifyRetries() == 0;
if (keyIsLocked) {
view.statusLineError();
int unlockAttemptsLeft = tokenInfo.getVerifyAdminRetries();
view.showActionLocked(unlockAttemptsLeft);
int unlockAttemptsLeft = tokenInfo.getVerifyAdminRetries();
view.showActionLocked(unlockAttemptsLeft);
return;
}
view.statusLineOk();
checkedKeyStatus = true;
continueSearch();
}
@Override
@@ -346,6 +355,11 @@ class ManageSecurityTokenPresenter implements ManageSecurityTokenMvpPresenter {
}
}
@Override
public void onClickSetupToken() {
view.startCreateKeyForToken(tokenInfo);
}
@Override
public void onSecurityTokenChangePinSuccess(SecurityTokenInfo tokenInfo) {
this.tokenInfo = tokenInfo;