From d21fb7733697a8f947604dbd1d6c608f5b2a21d5 Mon Sep 17 00:00:00 2001 From: Joey Castillo Date: Wed, 13 May 2015 05:33:28 -0400 Subject: Moving keytocard process into PgpKeyOperation. --- .../keychain/ui/EditKeyFragment.java | 77 ++++++++++------------ .../keychain/ui/NfcOperationActivity.java | 72 +++++++++++--------- .../keychain/ui/adapter/SubkeysAdapter.java | 24 +++++-- .../keychain/ui/base/BaseNfcActivity.java | 26 +------- 4 files changed, 94 insertions(+), 105 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui') 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 3b342bec0..bc2fbff76 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -35,6 +35,7 @@ import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ListView; +import android.widget.Toast; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; @@ -42,6 +43,7 @@ import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.SingletonResult; +import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; @@ -418,6 +420,13 @@ public class EditKeyFragment extends CryptoOperationFragment implements } break; case EditSubkeyDialogFragment.MESSAGE_STRIP: { + CanonicalizedSecretKey.SecretKeyType secretKeyType = + mSubkeysAdapter.getSecretKeyType(position); + if (secretKeyType == CanonicalizedSecretKey.SecretKeyType.GNU_DUMMY) { + // Key is already stripped; this is a no-op. + break; + } + SubkeyChange change = mSaveKeyringParcel.getSubkeyChange(keyId); if (change == null) { mSaveKeyringParcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, null)); @@ -425,47 +434,39 @@ public class EditKeyFragment extends CryptoOperationFragment implements } // toggle change.mDummyStrip = !change.mDummyStrip; + if (change.mDummyStrip && change.mDummyDivert != null) { + // User had chosen to divert key, but now wants to strip it instead. + change.mDummyDivert = null; + } break; } case EditSubkeyDialogFragment.MESSAGE_KEYTOCARD: { + CanonicalizedSecretKey.SecretKeyType secretKeyType = + mSubkeysAdapter.getSecretKeyType(position); + if (secretKeyType == CanonicalizedSecretKey.SecretKeyType.DIVERT_TO_CARD || + secretKeyType == CanonicalizedSecretKey.SecretKeyType.GNU_DUMMY) { + Toast.makeText(EditKeyFragment.this.getActivity(), + R.string.edit_key_error_bad_nfc_stripped, Toast.LENGTH_SHORT) + .show(); + break; + } + SubkeyChange change; change = mSaveKeyringParcel.getSubkeyChange(keyId); if (change == null) { mSaveKeyringParcel.mChangeSubKeys.add( - new SubkeyChange(keyId, false, new byte[0]) + new SubkeyChange(keyId, false, null) ); + change = mSaveKeyringParcel.getSubkeyChange(keyId); + } + // toggle + if (change.mDummyDivert == null) { + change.mDummyDivert = new byte[0]; + // If user had chosen to strip key, we cancel that action now. + change.mDummyStrip = false; + } else { + change.mDummyDivert = null; } - final Bundle data = new Bundle(); - data.putLong(KeychainIntentService.NFC_KEYTOCARD_SUBKEY_ID, keyId); - Intent intent = new Intent(EditKeyFragment.this.getActivity(), - KeychainIntentService.class); - intent.setAction(KeychainIntentService.ACTION_NFC_KEYTOCARD); - intent.putExtra(KeychainIntentService.EXTRA_DATA, data); - - ServiceProgressHandler serviceHandler = new ServiceProgressHandler( - getActivity(), - getString(R.string.progress_exporting), - ProgressDialog.STYLE_HORIZONTAL, - ProgressDialogFragment.ServiceType.KEYCHAIN_INTENT) { - public void handleMessage(Message message) { - super.handleMessage(message); - if (EditKeyFragment.this.handlePendingMessage(message)) { - return; - } - Bundle data = message.getData(); - OperationResult result = data.getParcelable(OperationResult.EXTRA_RESULT); - if (result.getResult() == OperationResult.RESULT_ERROR) { - result.createNotify(getActivity()).show(); - } - - } - }; - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(serviceHandler); - intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); - serviceHandler.showProgressDialog(getActivity()); - - getActivity().startService(intent); break; } } @@ -637,18 +638,6 @@ public class EditKeyFragment extends CryptoOperationFragment implements Intent intent = new Intent(getActivity(), KeychainIntentService.class); intent.setAction(KeychainIntentService.ACTION_EDIT_KEYRING); - for (SubkeyChange change : mSaveKeyringParcel.mChangeSubKeys) { - if(change.mDummyDivert != null) { - // Convert long key ID to byte buffer - byte[] subKeyId = new byte[8]; - ByteBuffer buf = ByteBuffer.wrap(subKeyId); - buf.putLong(change.mKeyId).rewind(); - - byte[] cardSerial = cryptoInput.getCryptoData().get(buf); - change.mDummyDivert = cardSerial; - } - } - // fill values for this action Bundle data = new Bundle(); data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java index 1a618329d..bed846dd3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java @@ -23,6 +23,7 @@ import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.base.BaseNfcActivity; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Passphrase; import org.sufficientlysecure.keychain.util.Preferences; import java.io.IOException; @@ -59,9 +60,7 @@ public class NfcOperationActivity extends BaseNfcActivity { mRequiredInput = data.getParcelable(EXTRA_REQUIRED_INPUT); mServiceIntent = data.getParcelable(EXTRA_SERVICE_INTENT); - if (mRequiredInput.mType == RequiredInputParcel.RequiredInputType.NFC_KEYTOCARD) { - obtainKeyExportPassphrase(RequiredInputParcel.createRequiredPassphrase(mRequiredInput)); - } else { + if (mRequiredInput.mType != RequiredInputParcel.RequiredInputType.NFC_KEYTOCARD) { obtainYubiKeyPin(RequiredInputParcel.createRequiredPassphrase(mRequiredInput)); } } @@ -99,38 +98,51 @@ public class NfcOperationActivity extends BaseNfcActivity { CanonicalizedSecretKeyRing secretKeyRing; try { secretKeyRing = providerHelper.getCanonicalizedSecretKeyRing( - KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(mRequiredInput.getSubKeyId()) + KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(mRequiredInput.getMasterKeyId()) ); } catch (ProviderHelper.NotFoundException e) { throw new IOException("Couldn't find subkey for key to card operation."); } - CanonicalizedSecretKey key = secretKeyRing.getSecretKey(mRequiredInput.getSubKeyId()); - - long keyGenerationTimestampMillis = key.getCreationTime().getTime(); - long keyGenerationTimestamp = keyGenerationTimestampMillis / 1000; - byte[] timestampBytes = ByteBuffer.allocate(4).putInt((int) keyGenerationTimestamp).array(); - byte[] cardSerialNumber = Arrays.copyOf(nfcGetAid(), 16); - - if (key.canSign() || key.canCertify()) { - nfcPutKey(0xB6, key); - nfcPutData(0xCE, timestampBytes); - nfcPutData(0xC7, key.getFingerprint()); - } else if (key.canEncrypt()) { - nfcPutKey(0xB8, key); - nfcPutData(0xCF, timestampBytes); - nfcPutData(0xC8, key.getFingerprint()); - } else if (key.canAuthenticate()) { - nfcPutKey(0xA4, key); - nfcPutData(0xD0, timestampBytes); - nfcPutData(0xC9, key.getFingerprint()); - } else { - throw new IOException("Inappropriate key flags for smart card key."); - } - byte[] subKeyId = new byte[8]; - ByteBuffer buf = ByteBuffer.wrap(subKeyId); - buf.putLong(mRequiredInput.getSubKeyId()); - inputParcel.addCryptoData(subKeyId, cardSerialNumber); + // Note: we're abusing mInputHashes to hold the subkey IDs we need to export. + for (int i = 0; i < mRequiredInput.mInputHashes.length; i++) { + byte[] subkeyBytes = mRequiredInput.mInputHashes[i]; + ByteBuffer buf = ByteBuffer.wrap(subkeyBytes); + long subkeyId = buf.getLong(); + + CanonicalizedSecretKey key = secretKeyRing.getSecretKey(subkeyId); + + long keyGenerationTimestampMillis = key.getCreationTime().getTime(); + long keyGenerationTimestamp = keyGenerationTimestampMillis / 1000; + byte[] timestampBytes = ByteBuffer.allocate(4).putInt((int) keyGenerationTimestamp).array(); + byte[] cardSerialNumber = Arrays.copyOf(nfcGetAid(), 16); + + Passphrase passphrase; + try { + passphrase = PassphraseCacheService.getCachedPassphrase(this, + mRequiredInput.getMasterKeyId(), mRequiredInput.getSubKeyId()); + } catch (PassphraseCacheService.KeyNotFoundException e) { + throw new IOException("Unable to get cached passphrase!"); + } + + if (key.canSign() || key.canCertify()) { + nfcPutKey(0xB6, key, passphrase); + nfcPutData(0xCE, timestampBytes); + nfcPutData(0xC7, key.getFingerprint()); + } else if (key.canEncrypt()) { + nfcPutKey(0xB8, key, passphrase); + nfcPutData(0xCF, timestampBytes); + nfcPutData(0xC8, key.getFingerprint()); + } else if (key.canAuthenticate()) { + nfcPutKey(0xA4, key, passphrase); + nfcPutData(0xD0, timestampBytes); + nfcPutData(0xC9, key.getFingerprint()); + } else { + throw new IOException("Inappropriate key flags for smart card key."); + } + + inputParcel.addCryptoData(subkeyBytes, cardSerialNumber); + } } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java index db0a930ed..dfa5a39fb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java @@ -179,13 +179,23 @@ public class SubkeysAdapter extends CursorAdapter { ? mSaveKeyringParcel.getSubkeyChange(keyId) : null; - if (change != null && change.mDummyStrip) { - algorithmStr.append(", "); - final SpannableString boldStripped = new SpannableString( - context.getString(R.string.key_stripped) - ); - boldStripped.setSpan(new StyleSpan(Typeface.BOLD), 0, boldStripped.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - algorithmStr.append(boldStripped); + if (change != null && (change.mDummyStrip || change.mDummyDivert != null)) { + if (change.mDummyStrip) { + algorithmStr.append(", "); + final SpannableString boldStripped = new SpannableString( + context.getString(R.string.key_stripped) + ); + boldStripped.setSpan(new StyleSpan(Typeface.BOLD), 0, boldStripped.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + algorithmStr.append(boldStripped); + } + if (change.mDummyDivert != null) { + algorithmStr.append(", "); + final SpannableString boldDivert = new SpannableString( + context.getString(R.string.key_divert) + ); + boldDivert.setSpan(new StyleSpan(Typeface.BOLD), 0, boldDivert.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + algorithmStr.append(boldDivert); + } } else { switch (SecretKeyType.fromNum(cursor.getInt(INDEX_HAS_SECRET))) { case GNU_DUMMY: diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java index 4506fe3c1..686c86b3a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java @@ -60,11 +60,9 @@ import org.sufficientlysecure.keychain.util.Preferences; public abstract class BaseNfcActivity extends BaseActivity { public static final int REQUEST_CODE_PIN = 1; - public static final int REQUEST_CODE_PASSPHRASE = 2; protected Passphrase mPin; protected Passphrase mAdminPin; - protected Passphrase mPassphrase; // For key export protected boolean mPw1ValidForMultipleSignatures; protected boolean mPw1ValidatedForSignature; protected boolean mPw1ValidatedForDecrypt; // Mode 82 does other things; consider renaming? @@ -136,15 +134,6 @@ public abstract class BaseNfcActivity extends BaseActivity { enableNfcForegroundDispatch(); } - protected void obtainKeyExportPassphrase(RequiredInputParcel requiredInput) { - - Intent intent = new Intent(this, PassphraseDialogActivity.class); - intent.putExtra(PassphraseDialogActivity.EXTRA_REQUIRED_INPUT, - RequiredInputParcel.createRequiredPassphrase(requiredInput)); - startActivityForResult(intent, REQUEST_CODE_PASSPHRASE); - - } - protected void obtainYubiKeyPin(RequiredInputParcel requiredInput) { Preferences prefs = Preferences.getPreferences(this); @@ -178,17 +167,6 @@ public abstract class BaseNfcActivity extends BaseActivity { break; } - case REQUEST_CODE_PASSPHRASE: { - if (resultCode != Activity.RESULT_OK) { - setResult(resultCode); - finish(); - return; - } - CryptoInputParcel input = data.getParcelableExtra(PassphraseDialogActivity.RESULT_CRYPTO_INPUT); - mPassphrase = input.getPassphrase(); - break; - } - default: super.onActivityResult(requestCode, resultCode, data); } @@ -627,7 +605,7 @@ public abstract class BaseNfcActivity extends BaseActivity { * 0xB8: Decipherment Key * 0xA4: Authentication Key */ - public void nfcPutKey(int slot, CanonicalizedSecretKey secretKey) + public void nfcPutKey(int slot, CanonicalizedSecretKey secretKey, Passphrase passphrase) throws IOException { if (slot != 0xB6 && slot != 0xB8 && slot != 0xA4) { throw new IOException("Invalid key slot"); @@ -635,7 +613,7 @@ public abstract class BaseNfcActivity extends BaseActivity { RSAPrivateCrtKey crtSecretKey = null; try { - secretKey.unlock(mPassphrase); + secretKey.unlock(passphrase); crtSecretKey = secretKey.getCrtSecretKey(); } catch (PgpGeneralException e) { throw new IOException(e.getMessage()); -- cgit v1.2.3