aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java41
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java53
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SecurityTokenOperationActivity.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java22
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyserverFragment.java7
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java13
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenNfcActivity.java115
16 files changed, 195 insertions, 103 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java
index a9dfaa2c5..e7ff6ce46 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java
@@ -43,6 +43,7 @@ import android.support.v4.app.FragmentManager.OnBackStackChangedListener;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
+import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -170,11 +171,7 @@ public class BackupCodeFragment extends CryptoOperationFragment<BackupKeyringPar
mTitleAnimator.setDisplayedChild(1, animate);
mStatusAnimator.setDisplayedChild(1, animate);
mCodeFieldsAnimator.setDisplayedChild(1, animate);
- // use non-breaking spaces to enlarge the empty EditText appropriately
- String empty = "\u00a0\u00a0\u00a0\u00a0-\u00a0\u00a0\u00a0\u00a0" +
- "-\u00a0\u00a0\u00a0\u00a0-\u00a0\u00a0\u00a0\u00a0" +
- "-\u00a0\u00a0\u00a0\u00a0-\u00a0\u00a0\u00a0\u00a0";
- mCodeEditText.setText(empty);
+ mCodeEditText.setText(" - - - - - ");
pushBackStackEntry();
@@ -241,6 +238,30 @@ public class BackupCodeFragment extends CryptoOperationFragment<BackupKeyringPar
mCodeEditText.setImeOptions(EditorInfo.IME_ACTION_DONE);
setupEditTextSuccessListener(mCodeEditText);
+ // prevent selection action mode, partially circumventing text selection bug
+ mCodeEditText.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
+ @Override
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ return false;
+ }
+
+ @Override
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ return false;
+ }
+
+ @Override
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ return false;
+ }
+
+ @Override
+ public void onDestroyActionMode(ActionMode mode) {
+
+ }
+ });
+
+
TextView codeDisplayText = (TextView) view.findViewById(R.id.backup_code_display);
setupAutomaticLinebreak(codeDisplayText);
@@ -351,27 +372,27 @@ public class BackupCodeFragment extends CryptoOperationFragment<BackupKeyringPar
@Override
public void afterTextChanged(Editable s) {
+ String currentBackupCode = backupCode.getText().toString();
boolean inInputState = mCurrentState == BackupCodeState.STATE_INPUT
|| mCurrentState == BackupCodeState.STATE_INPUT_ERROR;
- boolean partIsComplete = (backupCode.getText().toString().indexOf(' ') == -1)
- && (backupCode.getText().toString().indexOf('\u00a0') == -1);
+ boolean partIsComplete = (currentBackupCode.indexOf(' ') == -1);
if (!inInputState || !partIsComplete) {
return;
}
- checkIfCodeIsCorrect(backupCode);
+ checkIfCodeIsCorrect(currentBackupCode);
}
});
}
- private void checkIfCodeIsCorrect(EditText backupCode) {
+ private void checkIfCodeIsCorrect(String currentBackupCode) {
if (Constants.DEBUG && mDebugModeAcceptAnyCode) {
switchState(BackupCodeState.STATE_OK, true);
return;
}
- if (backupCode.toString().equals(mBackupCode)) {
+ if (currentBackupCode.equals(mBackupCode)) {
switchState(BackupCodeState.STATE_OK, true);
return;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java
index b53bfc1d0..58a28da51 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java
@@ -278,7 +278,7 @@ public class CreateKeyFinalFragment extends Fragment {
2048, null, KeyFlags.AUTHENTICATION, 0L));
// use empty passphrase
- saveKeyringParcel.mNewUnlock = new ChangeUnlockParcel(new Passphrase(), null);
+ saveKeyringParcel.mNewUnlock = new ChangeUnlockParcel(new Passphrase());
} else {
saveKeyringParcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(Algorithm.RSA,
4096, null, KeyFlags.CERTIFY_OTHER, 0L));
@@ -288,7 +288,7 @@ public class CreateKeyFinalFragment extends Fragment {
4096, null, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, 0L));
saveKeyringParcel.mNewUnlock = createKeyActivity.mPassphrase != null
- ? new ChangeUnlockParcel(createKeyActivity.mPassphrase, null)
+ ? new ChangeUnlockParcel(createKeyActivity.mPassphrase)
: null;
}
String userId = KeyRing.createUserId(
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
index 2d94d0d93..2184f91f1 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
@@ -339,8 +339,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
// cache new returned passphrase!
mSaveKeyringParcel.mNewUnlock = new ChangeUnlockParcel(
- (Passphrase) data.getParcelable(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE),
- null
+ (Passphrase) data.getParcelable(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE)
);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
index be08f6a53..22202a35f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
@@ -247,10 +247,10 @@ public class EncryptFilesFragment
try {
mFilesAdapter.add(inputUri);
} catch (IOException e) {
+ String fileName = FileHelper.getFilename(getActivity(), inputUri);
Notify.create(getActivity(),
- getActivity().getString(R.string.error_file_added_already, FileHelper.getFilename(getActivity(), inputUri)),
+ getActivity().getString(R.string.error_file_added_already, fileName),
Notify.Style.ERROR).show(this);
- return;
}
// remove from pending input uris
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java
index ca5d20fb9..b2b85ec14 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java
@@ -79,9 +79,6 @@ public class EncryptModeAsymmetricFragment extends EncryptModeFragment {
mSignKeySpinner = (KeySpinner) view.findViewById(R.id.sign);
mEncryptKeyView = (EncryptKeyCompletionView) view.findViewById(R.id.recipient_list);
mEncryptKeyView.setThreshold(1); // Start working from first character
- // TODO: workaround for bug in TokenAutoComplete,
- // see https://github.com/open-keychain/open-keychain/issues/1636
- mEncryptKeyView.setDeletionStyle(TokenCompleteTextView.TokenDeleteStyle.ToString);
final ViewAnimator vSignatureIcon = (ViewAnimator) view.findViewById(R.id.result_signature_icon);
mSignKeySpinner.setOnKeyChangedListener(new OnKeyChangedListener() {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
index f67c6a724..72e42eec3 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
@@ -131,8 +131,11 @@ public class ImportKeysActivity extends BaseActivity
if (Intent.ACTION_VIEW.equals(action)) {
if (FacebookKeyserver.isFacebookHost(dataUri)) {
action = ACTION_IMPORT_KEY_FROM_FACEBOOK;
- } else if ("http".equals(scheme) || "https".equals(scheme)) {
+ } else if ("http".equalsIgnoreCase(scheme) || "https".equalsIgnoreCase(scheme)) {
action = ACTION_SEARCH_KEYSERVER_FROM_URL;
+ } else if ("openpgp4fpr".equalsIgnoreCase(scheme)) {
+ action = ACTION_IMPORT_KEY_FROM_KEYSERVER;
+ extras.putString(EXTRA_FINGERPRINT, dataUri.getSchemeSpecificPart());
} else {
// Android's Action when opening file associated to Keychain (see AndroidManifest.xml)
// delegate action to ACTION_IMPORT_KEY
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
index b399af950..4d4219f56 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
@@ -330,9 +330,16 @@ public class ImportKeysListFragment extends ListFragment implements
}
public void loadNew(LoaderState loaderState) {
-
mLoaderState = loaderState;
+ if (mLoaderState instanceof BytesLoaderState) {
+ BytesLoaderState ls = (BytesLoaderState) mLoaderState;
+
+ if ( ls.mDataUri != null && ! checkAndRequestReadPermission(ls.mDataUri)) {
+ return;
+ }
+ }
+
restartLoaders();
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
index fd4f27176..e7f91a07e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
@@ -192,6 +192,8 @@ public class PassphraseDialogActivity extends FragmentActivity {
mBackupCodeEditText.setImeActionLabel(getString(android.R.string.ok), EditorInfo.IME_ACTION_DONE);
mBackupCodeEditText.setOnEditorActionListener(this);
+ openKeyboard(mBackupCodeEditText);
+
AlertDialog dialog = alert.create();
dialog.setButton(DialogInterface.BUTTON_POSITIVE,
activity.getString(R.string.btn_unlock), (DialogInterface.OnClickListener) null);
@@ -281,28 +283,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
mPassphraseText.setText(message);
mPassphraseEditText.setHint(hint);
- // Hack to open keyboard.
- // This is the only method that I found to work across all Android versions
- // http://turbomanage.wordpress.com/2012/05/02/show-soft-keyboard-automatically-when-edittext-receives-focus/
- // Notes: * onCreateView can't be used because we want to add buttons to the dialog
- // * opening in onActivityCreated does not work on Android 4.4
- mPassphraseEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- mPassphraseEditText.post(new Runnable() {
- @Override
- public void run() {
- if (getActivity() == null || mPassphraseEditText == null) {
- return;
- }
- InputMethodManager imm = (InputMethodManager) getActivity()
- .getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.showSoftInput(mPassphraseEditText, InputMethodManager.SHOW_IMPLICIT);
- }
- });
- }
- });
- mPassphraseEditText.requestFocus();
+ openKeyboard(mPassphraseEditText);
mPassphraseEditText.setImeActionLabel(getString(android.R.string.ok), EditorInfo.IME_ACTION_DONE);
mPassphraseEditText.setOnEditorActionListener(this);
@@ -325,6 +306,34 @@ public class PassphraseDialogActivity extends FragmentActivity {
}
/**
+ * Hack to open keyboard.
+ *
+ * This is the only method that I found to work across all Android versions
+ * http://turbomanage.wordpress.com/2012/05/02/show-soft-keyboard-automatically-when-edittext-receives-focus/
+ * Notes: * onCreateView can't be used because we want to add buttons to the dialog
+ * * opening in onActivityCreated does not work on Android 4.4
+ */
+ private void openKeyboard(final TextView textView) {
+ textView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ textView.post(new Runnable() {
+ @Override
+ public void run() {
+ if (getActivity() == null || textView == null) {
+ return;
+ }
+ InputMethodManager imm = (InputMethodManager) getActivity()
+ .getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.showSoftInput(textView, InputMethodManager.SHOW_IMPLICIT);
+ }
+ });
+ }
+ });
+ textView.requestFocus();
+ }
+
+ /**
* Automatic line break with max 6 lines for smaller displays
* <p/>
* NOTE: I was not able to get this behaviour using XML!
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 78d82d436..d2ecce242 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SecurityTokenOperationActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SecurityTokenOperationActivity.java
@@ -249,13 +249,13 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenNfcActivity
}
// change PINs afterwards
- nfcModifyPIN(0x81, newPin);
- nfcModifyPIN(0x83, newAdminPin);
+ nfcModifyPin(0x81, newPin);
+ nfcModifyPin(0x83, newAdminPin);
break;
}
case NFC_RESET_CARD: {
- nfcResetCard();
+ nfcReset();
break;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
index ea70cde2a..4fd327c8f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
@@ -19,8 +19,6 @@
package org.sufficientlysecure.keychain.ui;
-import java.util.List;
-
import android.Manifest;
import android.accounts.Account;
import android.accounts.AccountManager;
@@ -49,6 +47,7 @@ import android.view.ViewGroup;
import android.widget.LinearLayout;
import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.KeychainApplication;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.AppCompatPreferenceActivity;
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
@@ -59,6 +58,8 @@ import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Preferences;
import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
+import java.util.List;
+
public class SettingsActivity extends AppCompatPreferenceActivity {
public static final int REQUEST_CODE_KEYSERVER_PREF = 0x00007005;
@@ -405,7 +406,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
}
/**
- * This fragment shows the keyserver/contacts sync preferences
+ * This fragment shows the keyserver/wifi-only-sync/contacts sync preferences
*/
public static class SyncPrefsFragment extends PresetPreferenceFragment {
@@ -422,8 +423,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
super.onResume();
// this needs to be done in onResume since the user can change sync values from Android
// settings and we need to reflect that change when the user navigates back
- AccountManager manager = AccountManager.get(getActivity());
- final Account account = manager.getAccountsByType(Constants.ACCOUNT_TYPE)[0];
+ final Account account = KeychainApplication.createAccountIfNecessary(getActivity());
// for keyserver sync
initializeSyncCheckBox(
(SwitchPreference) findPreference(Constants.Pref.SYNC_KEYSERVER),
@@ -441,8 +441,11 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
private void initializeSyncCheckBox(final SwitchPreference syncCheckBox,
final Account account,
final String authority) {
- boolean syncEnabled = ContentResolver.getSyncAutomatically(account, authority)
- && checkContactsPermission(authority);
+ // account is null if it could not be created for some reason
+ boolean syncEnabled =
+ account != null
+ && ContentResolver.getSyncAutomatically(account, authority)
+ && checkContactsPermission(authority);
syncCheckBox.setChecked(syncEnabled);
setSummary(syncCheckBox, authority, syncEnabled);
@@ -464,6 +467,11 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
return false;
}
} else {
+ if (account == null) {
+ // if account could not be created for some reason,
+ // we can't have our sync
+ return false;
+ }
// disable syncs
ContentResolver.setSyncAutomatically(account, authority, false);
// immediately delete any linked contacts
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyserverFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyserverFragment.java
index 5a8ab36bc..488558aa3 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyserverFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyserverFragment.java
@@ -40,6 +40,7 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.dialog.AddEditKeyserverDialogFragment;
+import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
import org.sufficientlysecure.keychain.ui.util.recyclerview.ItemTouchHelperAdapter;
import org.sufficientlysecure.keychain.ui.util.recyclerview.ItemTouchHelperViewHolder;
import org.sufficientlysecure.keychain.ui.util.recyclerview.ItemTouchHelperDragCallback;
@@ -312,19 +313,19 @@ public class SettingsKeyserverFragment extends Fragment implements RecyclerItemC
public void showAsSelectedKeyserver() {
isSelectedKeyserver = true;
selectedServerLabel.setVisibility(View.VISIBLE);
- outerLayout.setBackgroundColor(getResources().getColor(R.color.android_green_dark));
+ outerLayout.setBackgroundColor(FormattingUtils.getColorFromAttr(getContext(), R.attr.colorPrimaryDark));
}
public void showAsUnselectedKeyserver() {
isSelectedKeyserver = false;
selectedServerLabel.setVisibility(View.GONE);
- outerLayout.setBackgroundColor(Color.WHITE);
+ outerLayout.setBackgroundColor(0);
}
@Override
public void onItemSelected() {
selectedServerLabel.setVisibility(View.GONE);
- itemView.setBackgroundColor(Color.LTGRAY);
+ itemView.setBackgroundColor(FormattingUtils.getColorFromAttr(getContext(), R.attr.colorBrightToolbar));
}
@Override
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
index 03fc07936..35c1615c7 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -469,8 +469,7 @@ public class ViewKeyActivity extends BaseSecurityTokenNfcActivity implements
// use new passphrase!
mSaveKeyringParcel.mNewUnlock = new SaveKeyringParcel.ChangeUnlockParcel(
- (Passphrase) data.getParcelable(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE),
- null
+ (Passphrase) data.getParcelable(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE)
);
mEditOpHelper.cryptoOperation();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
index ce2f2def8..0aa8330ea 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
@@ -238,7 +238,7 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
// let user choose application
Intent sendIntent = new Intent(Intent.ACTION_SEND);
- sendIntent.setType("text/plain");
+ sendIntent.setType(Constants.MIME_TYPE_KEYS);
// NOTE: Don't use Intent.EXTRA_TEXT to send the key
// better send it via a Uri!
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java
index fb72a263e..4a68c55fe 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java
@@ -333,14 +333,6 @@ public class KeyAdapter extends CursorAdapter {
return mUserId.email;
}
}
-
- // TODO: workaround for bug in TokenAutoComplete,
- // see https://github.com/open-keychain/open-keychain/issues/1636
- @Override
- public String toString() {
- return " ";
- }
-
}
public static String[] getProjectionWith(String[] projection) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java
index 107c63e0b..063181dfe 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java
@@ -26,6 +26,7 @@ import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Gravity;
import android.view.LayoutInflater;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
@@ -45,8 +46,8 @@ public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
- initTheme();
super.onCreate(savedInstanceState);
+ initTheme();
initLayout();
initToolbar();
}
@@ -65,6 +66,16 @@ public abstract class BaseActivity extends AppCompatActivity {
}
}
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home :
+ onBackPressed();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
public static void onResumeChecks(Context context) {
KeyserverSyncAdapterService.cancelUpdates(context);
// in case user has disabled sync from Android account settings
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenNfcActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenNfcActivity.java
index ae1944ced..77044cd2b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenNfcActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenNfcActivity.java
@@ -26,14 +26,11 @@ import java.nio.ByteBuffer;
import java.security.interfaces.RSAPrivateCrtKey;
import android.app.Activity;
-import android.app.PendingIntent;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.TagLostException;
-import android.nfc.tech.IsoDep;
import android.os.AsyncTask;
import android.os.Bundle;
@@ -199,7 +196,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mTagDispatcher = TagDispatcher.get(this, this, false, false);
+ mTagDispatcher = TagDispatcher.get(this, this, false, false, true, false);
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
@@ -319,7 +316,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
// 6A82 app not installed on security token!
case 0x6A82: {
- if (isFidesmoDevice()) {
+ if (isFidesmoToken()) {
// Check if the Fidesmo app is installed
if (isAndroidAppInstalled(FIDESMO_APP_PACKAGE)) {
promptFidesmoPgpInstall();
@@ -530,18 +527,18 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
public String nfcGetUserId() throws IOException {
String info = "00CA006500";
- return nfcGetHolderName(nfcCommunicate(info));
+ return getHolderName(nfcCommunicate(info));
}
/**
- * Calls to calculate the signature and returns the MPI value
+ * Call COMPUTE DIGITAL SIGNATURE command and returns the MPI value
*
* @param hash the hash for signing
* @return a big integer representing the MPI for the given hash
*/
public byte[] nfcCalculateSignature(byte[] hash, int hashAlgo) throws IOException {
if (!mPw1ValidatedForSignature) {
- nfcVerifyPIN(0x81); // (Verify PW1 with mode 81 for signing)
+ nfcVerifyPin(0x81); // (Verify PW1 with mode 81 for signing)
}
// dsi, including Lc
@@ -634,14 +631,14 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
/**
- * Calls to calculate the signature and returns the MPI value
+ * Call DECIPHER command
*
* @param encryptedSessionKey the encoded session key
* @return the decoded session key
*/
public byte[] nfcDecryptSessionKey(byte[] encryptedSessionKey) throws IOException {
if (!mPw1ValidatedForDecrypt) {
- nfcVerifyPIN(0x82); // (Verify PW1 with mode 82 for decryption)
+ nfcVerifyPin(0x82); // (Verify PW1 with mode 82 for decryption)
}
String firstApdu = "102a8086fe";
@@ -657,10 +654,10 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
two[i] = encryptedSessionKey[i + one.length + 1];
}
- String first = nfcCommunicate(firstApdu + getHex(one));
+ nfcCommunicate(firstApdu + getHex(one));
String second = nfcCommunicate(secondApdu + getHex(two) + le);
- String decryptedSessionKey = nfcGetDataField(second);
+ String decryptedSessionKey = getDataField(second);
return Hex.decode(decryptedSessionKey);
}
@@ -670,7 +667,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
* @param mode For PW1, this is 0x81 for signing, 0x82 for everything else.
* For PW3 (Admin PIN), mode is 0x83.
*/
- public void nfcVerifyPIN(int mode) throws IOException {
+ public void nfcVerifyPin(int mode) throws IOException {
if (mPin != null || mode == 0x83) {
byte[] pin;
@@ -683,7 +680,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
// SW1/2 0x9000 is the generic "ok" response, which we expect most of the time.
// See specification, page 51
String accepted = "9000";
- String response = tryPin(mode, pin); // login
+ String response = nfcTryPin(mode, pin); // login
if (!response.equals(accepted)) {
throw new CardException("Bad PIN!", parseCardStatus(response));
}
@@ -698,13 +695,18 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
}
- public void nfcResetCard() throws IOException {
+ /**
+ * 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 nfcReset() throws IOException {
String accepted = "9000";
// try wrong PIN 4 times until counter goes to C0
byte[] pin = "XXXXXX".getBytes();
for (int i = 0; i <= 4; i++) {
- String response = tryPin(0x81, pin);
+ String response = nfcTryPin(0x81, pin);
if (response.equals(accepted)) { // Should NOT accept!
throw new CardException("Should never happen, XXXXXX has been accepted!", parseCardStatus(response));
}
@@ -713,7 +715,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
// try wrong Admin PIN 4 times until counter goes to C0
byte[] adminPin = "XXXXXXXX".getBytes();
for (int i = 0; i <= 4; i++) {
- String response = tryPin(0x83, adminPin);
+ String response = nfcTryPin(0x83, adminPin);
if (response.equals(accepted)) { // Should NOT accept!
throw new CardException("Should never happen, XXXXXXXX has been accepted", parseCardStatus(response));
}
@@ -730,7 +732,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
- private String tryPin(int mode, byte[] pin) throws IOException {
+ private String nfcTryPin(int mode, byte[] pin) throws IOException {
// Command APDU for VERIFY command (page 32)
String login =
"00" // CLA
@@ -749,7 +751,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
* @param pw For PW1, this is 0x81. For PW3 (Admin PIN), mode is 0x83.
* @param newPin The new PW1 or PW3.
*/
- public void nfcModifyPIN(int pw, byte[] newPin) throws IOException {
+ public void nfcModifyPin(int pw, byte[] newPin) throws IOException {
final int MAX_PW1_LENGTH_INDEX = 1;
final int MAX_PW3_LENGTH_INDEX = 3;
@@ -802,10 +804,10 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
if (dataObject == 0x0101 || dataObject == 0x0103) {
if (!mPw1ValidatedForDecrypt) {
- nfcVerifyPIN(0x82); // (Verify PW1 for non-signing operations)
+ nfcVerifyPin(0x82); // (Verify PW1 for non-signing operations)
}
} else if (!mPw3Validated) {
- nfcVerifyPIN(0x83); // (Verify PW3)
+ nfcVerifyPin(0x83); // (Verify PW3)
}
String putDataApdu = "00" // CLA
@@ -854,7 +856,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
if (!mPw3Validated) {
- nfcVerifyPIN(0x83); // (Verify PW3 with mode 83)
+ nfcVerifyPin(0x83); // (Verify PW3 with mode 83)
}
byte[] header= Hex.decode(
@@ -934,6 +936,53 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
/**
+ * Generates a key on the card in the given slot. If the slot is 0xB6 (the signature key),
+ * this command also has the effect of resetting the digital signature counter.
+ * NOTE: This does not set the key fingerprint data object! After calling this command, you
+ * must construct a public key packet using the returned public key data objects, compute the
+ * key fingerprint, and store it on the card using: nfcPutData(0xC8, key.getFingerprint())
+ *
+ * @param slot The slot on the card where the key should be generated:
+ * 0xB6: Signature Key
+ * 0xB8: Decipherment Key
+ * 0xA4: Authentication Key
+ * @return the public key data objects, in TLV format. For RSA this will be the public modulus
+ * (0x81) and exponent (0x82). These may come out of order; proper TLV parsing is required.
+ */
+ public byte[] nfcGenerateKey(int slot) throws IOException {
+ if (slot != 0xB6 && slot != 0xB8 && slot != 0xA4) {
+ throw new IOException("Invalid key slot");
+ }
+
+ if (!mPw3Validated) {
+ nfcVerifyPin(0x83); // (Verify PW3 with mode 83)
+ }
+
+ String generateKeyApdu = "0047800002" + String.format("%02x", slot) + "0000";
+ String getResponseApdu = "00C00000";
+
+ String first = nfcCommunicate(generateKeyApdu);
+ String second = nfcCommunicate(getResponseApdu);
+
+ if (!second.endsWith("9000")) {
+ throw new IOException("On-card key generation failed");
+ }
+
+ String publicKeyData = getDataField(first) + getDataField(second);
+
+ Log.d(Constants.TAG, "Public Key Data Objects: " + publicKeyData);
+
+ return Hex.decode(publicKeyData);
+ }
+
+ /**
+ * Transceive data via NFC encoded as Hex
+ */
+ public String nfcCommunicate(String apdu) throws IOException {
+ return getHex(mIsoCard.transceive(Hex.decode(apdu)));
+ }
+
+ /**
* Parses out the status word from a JavaCard response string.
*
* @param response A hex string with the response from the token
@@ -951,7 +1000,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
}
- public String nfcGetHolderName(String name) {
+ public String getHolderName(String name) {
try {
String slength;
int ilength;
@@ -971,14 +1020,10 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
}
- private String nfcGetDataField(String output) {
+ private String getDataField(String output) {
return output.substring(0, output.length() - 4);
}
- public String nfcCommunicate(String apdu) throws IOException {
- return getHex(mIsoCard.transceive(Hex.decode(apdu)));
- }
-
public static String getHex(byte[] raw) {
return new String(Hex.encode(raw));
}
@@ -1005,7 +1050,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
- private boolean isFidesmoDevice() {
+ private boolean isFidesmoToken() {
if (isNfcConnected()) { // Check if we can still talk to the card
try {
// By trying to select any apps that have the Fidesmo AID prefix we can
@@ -1021,11 +1066,11 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
/**
- * Ask user if she wants to install PGP onto her Fidesmo device
+ * Ask user if she wants to install PGP onto her Fidesmo token
*/
private void promptFidesmoPgpInstall() {
- FidesmoPgpInstallDialog mFidesmoPgpInstallDialog = new FidesmoPgpInstallDialog();
- mFidesmoPgpInstallDialog.show(getSupportFragmentManager(), "mFidesmoPgpInstallDialog");
+ FidesmoPgpInstallDialog fidesmoPgpInstallDialog = new FidesmoPgpInstallDialog();
+ fidesmoPgpInstallDialog.show(getSupportFragmentManager(), "fidesmoPgpInstallDialog");
}
/**
@@ -1033,8 +1078,8 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
* to launch the Google Play store.
*/
private void promptFidesmoAppInstall() {
- FidesmoInstallDialog mFidesmoInstallDialog = new FidesmoInstallDialog();
- mFidesmoInstallDialog.show(getSupportFragmentManager(), "mFidesmoInstallDialog");
+ FidesmoInstallDialog fidesmoInstallDialog = new FidesmoInstallDialog();
+ fidesmoInstallDialog.show(getSupportFragmentManager(), "fidesmoInstallDialog");
}
/**
@@ -1044,7 +1089,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
*/
private boolean isAndroidAppInstalled(String uri) {
PackageManager mPackageManager = getPackageManager();
- boolean mAppInstalled = false;
+ boolean mAppInstalled;
try {
mPackageManager.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
mAppInstalled = true;