From 39b131c7e58c358adf93bb64fe297884664a4ae1 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 30 Mar 2015 23:35:32 +0200 Subject: fix Encrypt* with RequiredInputParcel --- .../keychain/operations/SignEncryptOperation.java | 42 ++++- .../operations/results/InputPendingResult.java | 2 + .../operations/results/OperationResult.java | 1 - .../operations/results/PgpSignEncryptResult.java | 64 +------ .../operations/results/SignEncryptResult.java | 17 +- .../keychain/pgp/PgpSignEncryptOperation.java | 67 +++---- .../keychain/remote/OpenPgpService.java | 208 ++++++--------------- .../service/input/RequiredInputParcel.java | 12 +- .../keychain/ui/CryptoOperationFragment.java | 6 +- .../keychain/ui/DecryptFilesFragment.java | 2 +- .../keychain/ui/DecryptFragment.java | 2 +- .../keychain/ui/EncryptActivity.java | 189 ------------------- .../keychain/ui/EncryptFilesFragment.java | 27 +-- .../keychain/ui/EncryptTextActivity.java | 2 +- .../keychain/ui/EncryptTextFragment.java | 52 +----- .../keychain/ui/NfcActivity.java | 4 +- .../keychain/ui/NfcOperationActivity.java | 22 ++- .../keychain/ui/PassphraseDialogActivity.java | 21 +-- .../keychain/ui/base/BaseNfcActivity.java | 2 +- .../keychain/util/KeyUpdateHelper.java | 2 +- OpenKeychain/src/main/res/values/strings.xml | 1 - 21 files changed, 185 insertions(+), 560 deletions(-) delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java (limited to 'OpenKeychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java index db44546b6..d718d231e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java @@ -20,15 +20,21 @@ package org.sufficientlysecure.keychain.operations; import android.content.Context; import android.net.Uri; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult; import org.sufficientlysecure.keychain.operations.results.SignEncryptResult; +import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.PgpSignEncryptOperation; import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.SignEncryptParcel; +import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSignOperationsBuilder; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.RequiredInputType; import org.sufficientlysecure.keychain.util.FileHelper; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.ProgressScaler; @@ -69,6 +75,20 @@ public class SignEncryptOperation extends BaseOperation { int total = inputBytes != null ? 1 : inputUris.size(), count = 0; ArrayList results = new ArrayList<>(); + NfcSignOperationsBuilder pendingInputBuilder = null; + + if (input.getSignatureMasterKeyId() != Constants.key.none + && input.getSignatureSubKeyId() == null) { + try { + long signKeyId = mProviderHelper.getCachedPublicKeyRing( + input.getSignatureMasterKeyId()).getSecretSignId(); + input.setSignatureSubKeyId(signKeyId); + } catch (PgpKeyNotFoundException e) { + e.printStackTrace(); + return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log, results); + } + } + do { if (checkCancelled()) { @@ -129,10 +149,17 @@ public class SignEncryptOperation extends BaseOperation { log.add(result, 2); if (result.isPending()) { - return new SignEncryptResult(SignEncryptResult.RESULT_PENDING, log, results); - } - - if (!result.success()) { + RequiredInputParcel requiredInput = result.getRequiredInputParcel(); + // Passphrase returns immediately, nfc are aggregated + if (requiredInput.mType == RequiredInputType.PASSPHRASE) { + return new SignEncryptResult(log, requiredInput, results); + } + if (pendingInputBuilder == null) { + pendingInputBuilder = new NfcSignOperationsBuilder(requiredInput.mSignatureTime, + input.getSignatureMasterKeyId(), input.getSignatureSubKeyId()); + } + pendingInputBuilder.addAll(requiredInput); + } else if (!result.success()) { return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log, results); } @@ -142,9 +169,12 @@ public class SignEncryptOperation extends BaseOperation { } while (!inputUris.isEmpty()); + if (pendingInputBuilder != null && !pendingInputBuilder.isEmpty()) { + return new SignEncryptResult(log, pendingInputBuilder.build(), results); + } + if (!outputUris.isEmpty()) { - // Any output URIs left are indicative of a programming error - log.add(LogType.MSG_SE_WARN_OUTPUT_LEFT, 1); + throw new AssertionError("Got outputs left but no inputs. This is a programming error, please report!"); } log.add(LogType.MSG_SE_SUCCESS, 1); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java index 45a6b98b8..0b7aa6d03 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java @@ -18,6 +18,8 @@ package org.sufficientlysecure.keychain.operations.results; +import java.util.ArrayList; + import android.os.Parcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java index 47f9271e1..55d5d974a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java @@ -671,7 +671,6 @@ public abstract class OperationResult implements Parcelable { MSG_SE_ERROR_INPUT_URI_NOT_FOUND (LogLevel.ERROR, R.string.msg_se_error_input_uri_not_found), MSG_SE_ERROR_OUTPUT_URI_NOT_FOUND (LogLevel.ERROR, R.string.msg_se_error_output_uri_not_found), MSG_SE_ERROR_TOO_MANY_INPUTS (LogLevel.ERROR, R.string.msg_se_error_too_many_inputs), - MSG_SE_WARN_OUTPUT_LEFT (LogLevel.WARN, R.string.msg_se_warn_output_left), MSG_SE_SUCCESS (LogLevel.OK, R.string.msg_se_success), // pgpsignencrypt diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java index b6259e2d1..acb265462 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java @@ -19,76 +19,31 @@ package org.sufficientlysecure.keychain.operations.results; import android.os.Parcel; -import org.sufficientlysecure.keychain.util.Passphrase; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; -public class PgpSignEncryptResult extends OperationResult { - // the fourth bit indicates a "data pending" result! (it's also a form of non-success) - public static final int RESULT_PENDING = RESULT_ERROR + 8; +public class PgpSignEncryptResult extends InputPendingResult { - // fifth to sixth bit in addition indicate specific type of pending - public static final int RESULT_PENDING_PASSPHRASE = RESULT_PENDING + 16; - public static final int RESULT_PENDING_NFC = RESULT_PENDING + 32; - - long mKeyIdPassphraseNeeded; - - long mNfcKeyId; - byte[] mNfcHash; - int mNfcAlgo; - Passphrase mNfcPassphrase; byte[] mDetachedSignature; - public long getKeyIdPassphraseNeeded() { - return mKeyIdPassphraseNeeded; - } - - public void setKeyIdPassphraseNeeded(long keyIdPassphraseNeeded) { - mKeyIdPassphraseNeeded = keyIdPassphraseNeeded; - } - - public void setNfcData(long nfcKeyId, byte[] nfcHash, int nfcAlgo, Passphrase passphrase) { - mNfcKeyId = nfcKeyId; - mNfcHash = nfcHash; - mNfcAlgo = nfcAlgo; - mNfcPassphrase = passphrase; - } - public void setDetachedSignature(byte[] detachedSignature) { mDetachedSignature = detachedSignature; } - public long getNfcKeyId() { - return mNfcKeyId; - } - - public byte[] getNfcHash() { - return mNfcHash; - } - - public int getNfcAlgo() { - return mNfcAlgo; - } - - public Passphrase getNfcPassphrase() { - return mNfcPassphrase; - } - public byte[] getDetachedSignature() { return mDetachedSignature; } - public boolean isPending() { - return (mResult & RESULT_PENDING) == RESULT_PENDING; - } - public PgpSignEncryptResult(int result, OperationLog log) { super(result, log); } + public PgpSignEncryptResult(OperationLog log, RequiredInputParcel requiredInput) { + super(log, requiredInput); + } + public PgpSignEncryptResult(Parcel source) { super(source); - mNfcHash = source.readInt() != 0 ? source.createByteArray() : null; - mNfcAlgo = source.readInt(); mDetachedSignature = source.readInt() != 0 ? source.createByteArray() : null; } @@ -98,13 +53,6 @@ public class PgpSignEncryptResult extends OperationResult { public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); - if (mNfcHash != null) { - dest.writeInt(1); - dest.writeByteArray(mNfcHash); - } else { - dest.writeInt(0); - } - dest.writeInt(mNfcAlgo); if (mDetachedSignature != null) { dest.writeInt(1); dest.writeByteArray(mDetachedSignature); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java index 87483ade9..b05921b0d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java @@ -21,22 +21,17 @@ import android.os.Parcel; import java.util.ArrayList; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; -public class SignEncryptResult extends OperationResult { + +public class SignEncryptResult extends InputPendingResult { ArrayList mResults; byte[] mResultBytes; - public static final int RESULT_PENDING = RESULT_ERROR + 8; - - - public PgpSignEncryptResult getPending() { - for (PgpSignEncryptResult sub : mResults) { - if (sub.isPending()) { - return sub; - } - } - return null; + public SignEncryptResult(OperationLog log, RequiredInputParcel requiredInput, ArrayList results) { + super(log, requiredInput); + mResults = results; } public SignEncryptResult(int result, OperationLog log, ArrayList results) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java index f22b56ea6..0b22df790 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java @@ -40,11 +40,13 @@ import org.sufficientlysecure.keychain.operations.BaseOperation; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult; +import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; @@ -146,48 +148,39 @@ public class PgpSignEncryptOperation extends BaseOperation { CanonicalizedSecretKey signingKey = null; if (enableSignature) { + updateProgress(R.string.progress_extracting_signature_key, 0, 100); + try { // fetch the indicated master key id (the one whose name we sign in) CanonicalizedSecretKeyRing signingKeyRing = mProviderHelper.getCanonicalizedSecretKeyRing(input.getSignatureMasterKeyId()); - long signKeyId; - // use specified signing subkey, or find the one to use - if (input.getSignatureSubKeyId() == null) { - signKeyId = signingKeyRing.getSecretSignId(); - } else { - signKeyId = input.getSignatureSubKeyId(); - } - // fetch the specific subkey to sign with, or just use the master key if none specified - signingKey = signingKeyRing.getSecretKey(signKeyId); + signingKey = signingKeyRing.getSecretKey(input.getSignatureSubKeyId()); - } catch (ProviderHelper.NotFoundException | PgpGeneralException e) { - log.add(LogType.MSG_PSE_ERROR_SIGN_KEY, indent); - return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); - } - - // Make sure we are allowed to sign here! - if (!signingKey.canSign()) { - log.add(LogType.MSG_PSE_ERROR_KEY_SIGN, indent); - return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); - } - - // if no passphrase was explicitly set try to get it from the cache service - if (cryptoInput.getPassphrase() == null) { - log.add(LogType.MSG_PSE_PENDING_PASSPHRASE, indent + 1); - PgpSignEncryptResult result = new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE, log); - result.setKeyIdPassphraseNeeded(signingKey.getKeyId()); - return result; - } + // Make sure we are allowed to sign here! + if (!signingKey.canSign()) { + log.add(LogType.MSG_PSE_ERROR_KEY_SIGN, indent); + return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); + } - updateProgress(R.string.progress_extracting_signature_key, 0, 100); + if (signingKey.getSecretKeyType() != SecretKeyType.DIVERT_TO_CARD) { + if (cryptoInput.getPassphrase() == null) { + log.add(LogType.MSG_PSE_PENDING_PASSPHRASE, indent + 1); + return new PgpSignEncryptResult(log, RequiredInputParcel.createRequiredPassphrase( + signingKeyRing.getMasterKeyId(), signingKey.getKeyId(), + cryptoInput.getSignatureTime())); + } + } - try { if (!signingKey.unlock(cryptoInput.getPassphrase())) { log.add(LogType.MSG_PSE_ERROR_BAD_PASSPHRASE, indent); return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); } + + } catch (ProviderHelper.NotFoundException e) { + log.add(LogType.MSG_PSE_ERROR_SIGN_KEY, indent); + return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); } catch (PgpGeneralException e) { log.add(LogType.MSG_PSE_ERROR_UNLOCK, indent); return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); @@ -473,20 +466,8 @@ public class PgpSignEncryptOperation extends BaseOperation { } catch (NfcSyncPGPContentSignerBuilder.NfcInteractionNeeded e) { // this secret key diverts to a OpenPGP card, throw exception with hash that will be signed log.add(LogType.MSG_PSE_PENDING_NFC, indent); - PgpSignEncryptResult result = - new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_PENDING_NFC, log); - - // SignatureSubKeyId can be null. - if (input.getSignatureSubKeyId() == null) { - return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); - } - - // Note that the checked key here is the master key, not the signing key - // (although these are always the same on Yubikeys) - result.setNfcData(signingKey.getKeyId(), e.hashToSign, e.hashAlgo, - cryptoInput.getPassphrase()); - Log.d(Constants.TAG, "e.hashToSign" + Hex.toHexString(e.hashToSign)); - return result; + return new PgpSignEncryptResult(log, RequiredInputParcel.createNfcSignOperation( + e.hashToSign, e.hashAlgo, cryptoInput.getSignatureTime())); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 3575c3c18..4760412ea 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -18,6 +18,7 @@ package org.sufficientlysecure.keychain.remote; import android.app.PendingIntent; +import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.net.Uri; @@ -31,7 +32,6 @@ import org.openintents.openpgp.OpenPgpMetadata; import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.util.OpenPgpApi; import org.spongycastle.bcpg.CompressionAlgorithmTags; -import org.spongycastle.util.encoders.Hex; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogEntryParcel; @@ -49,19 +49,18 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.remote.ui.RemoteServiceActivity; import org.sufficientlysecure.keychain.remote.ui.SelectSignKeyIdActivity; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.ImportKeysActivity; -import org.sufficientlysecure.keychain.ui.NfcActivity; +import org.sufficientlysecure.keychain.ui.NfcOperationActivity; import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity; import org.sufficientlysecure.keychain.ui.ViewKeyActivity; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.Passphrase; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; -import java.util.Date; import java.util.Set; public class OpenPgpService extends RemoteService { @@ -79,9 +78,6 @@ public class OpenPgpService extends RemoteService { /** * Search database for key ids based on emails. - * - * @param encryptionUserIds - * @return */ private Intent returnKeyIdsFromEmails(Intent data, String[] encryptionUserIds) { boolean noUserIdsCheck = (encryptionUserIds == null || encryptionUserIds.length == 0); @@ -164,52 +160,35 @@ public class OpenPgpService extends RemoteService { } } - private Intent returnPassphraseIntent(Intent data, long keyId) { - // build PendingIntent for passphrase input - Intent intent = new Intent(getBaseContext(), PassphraseDialogActivity.class); - intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, keyId); - // pass params through to activity that it can be returned again later to repeat pgp operation - intent.putExtra(PassphraseDialogActivity.EXTRA_DATA, data); - PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0, - intent, - PendingIntent.FLAG_CANCEL_CURRENT); - - // return PendingIntent to be executed by client - Intent result = new Intent(); - result.putExtra(OpenPgpApi.RESULT_INTENT, pi); - result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); - return result; - } + private static PendingIntent getRequiredInputPendingIntent(Context context, + Intent data, RequiredInputParcel requiredInput) { + + switch (requiredInput.mType) { + case NFC_DECRYPT: + case NFC_SIGN: { + // build PendingIntent for Yubikey NFC operations + Intent intent = new Intent(context, NfcOperationActivity.class); + // pass params through to activity that it can be returned again later to repeat pgp operation + intent.putExtra(NfcOperationActivity.EXTRA_SERVICE_INTENT, data); + intent.putExtra(NfcOperationActivity.EXTRA_REQUIRED_INPUT, requiredInput); + return PendingIntent.getActivity(context, 0, intent, + PendingIntent.FLAG_CANCEL_CURRENT); + } - private PendingIntent getNfcSignPendingIntent(Intent data, long keyId, Passphrase pin, byte[] hashToSign, int hashAlgo) { - // build PendingIntent for Yubikey NFC operations - Intent intent = new Intent(getBaseContext(), NfcActivity.class); - intent.setAction(NfcActivity.ACTION_SIGN_HASH); - // pass params through to activity that it can be returned again later to repeat pgp operation - intent.putExtra(NfcActivity.EXTRA_DATA, data); - intent.putExtra(NfcActivity.EXTRA_PIN, pin); - intent.putExtra(NfcActivity.EXTRA_KEY_ID, keyId); - - intent.putExtra(NfcActivity.EXTRA_NFC_HASH_TO_SIGN, hashToSign); - intent.putExtra(NfcActivity.EXTRA_NFC_HASH_ALGO, hashAlgo); - return PendingIntent.getActivity(getBaseContext(), 0, - intent, - PendingIntent.FLAG_CANCEL_CURRENT); - } + case PASSPHRASE: { + // build PendingIntent for Passphrase request + Intent intent = new Intent(context, PassphraseDialogActivity.class); + // pass params through to activity that it can be returned again later to repeat pgp operation + intent.putExtra(PassphraseDialogActivity.EXTRA_SERVICE_INTENT, data); + intent.putExtra(PassphraseDialogActivity.EXTRA_REQUIRED_INPUT, requiredInput); + return PendingIntent.getActivity(context, 0, intent, + PendingIntent.FLAG_CANCEL_CURRENT); + } - private PendingIntent getNfcDecryptPendingIntent(Intent data, long subKeyId, Passphrase pin, byte[] encryptedSessionKey) { - // build PendingIntent for Yubikey NFC operations - Intent intent = new Intent(getBaseContext(), NfcActivity.class); - intent.setAction(NfcActivity.ACTION_DECRYPT_SESSION_KEY); - // pass params through to activity that it can be returned again later to repeat pgp operation - intent.putExtra(NfcActivity.EXTRA_DATA, data); - intent.putExtra(NfcActivity.EXTRA_PIN, pin); - intent.putExtra(NfcActivity.EXTRA_KEY_ID, subKeyId); + default: + throw new AssertionError("Unhandled required input type!"); + } - intent.putExtra(NfcActivity.EXTRA_NFC_ENC_SESSION_KEY, encryptedSessionKey); - return PendingIntent.getActivity(getBaseContext(), 0, - intent, - PendingIntent.FLAG_CANCEL_CURRENT); } private PendingIntent getKeyserverPendingIntent(Intent data, long masterKeyId) { @@ -241,18 +220,6 @@ public class OpenPgpService extends RemoteService { try { boolean asciiArmor = cleartextSign || data.getBooleanExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); - Passphrase passphrase = null; - if (data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE) != null) { - passphrase = new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE)); - } - - byte[] nfcSignedHash = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_SIGNED_HASH); - if (nfcSignedHash != null) { - Log.d(Constants.TAG, "nfcSignedHash:" + Hex.toHexString(nfcSignedHash)); - } else { - Log.d(Constants.TAG, "nfcSignedHash: null"); - } - Intent signKeyIdIntent = getSignKeyMasterId(data); // NOTE: Fallback to return account settings (Old API) if (signKeyIdIntent.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR) @@ -264,16 +231,6 @@ public class OpenPgpService extends RemoteService { Log.e(Constants.TAG, "No signing key given!"); } - // carefully: only set if timestamp exists - Date nfcCreationDate; - long nfcCreationTimestamp = data.getLongExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, -1); - Log.d(Constants.TAG, "nfcCreationTimestamp: " + nfcCreationTimestamp); - if (nfcCreationTimestamp != -1) { - nfcCreationDate = new Date(nfcCreationTimestamp); - } else { - nfcCreationDate = new Date(); - } - // Get Input- and OutputStream from ParcelFileDescriptor is = new ParcelFileDescriptor.AutoCloseInputStream(input); if (cleartextSign) { @@ -284,8 +241,7 @@ public class OpenPgpService extends RemoteService { long inputLength = is.available(); InputData inputData = new InputData(is, inputLength); - CryptoInputParcel cryptoInput = new CryptoInputParcel(nfcCreationDate, passphrase); - cryptoInput.addCryptoData(null, nfcSignedHash); // TODO fix + CryptoInputParcel cryptoInput = data.getParcelableExtra(OpenPgpApi.EXTRA_CRYPTO_INPUT); // sign-only PgpSignEncryptInputParcel pseInput = new PgpSignEncryptInputParcel() @@ -301,26 +257,16 @@ public class OpenPgpService extends RemoteService { PgpSignEncryptResult pgpResult = pse.execute(pseInput, cryptoInput, inputData, os); if (pgpResult.isPending()) { - if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) == - PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) { - return returnPassphraseIntent(data, pgpResult.getKeyIdPassphraseNeeded()); - } else if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_NFC) == - PgpSignEncryptResult.RESULT_PENDING_NFC) { - // return PendingIntent to execute NFC activity - // pass through the signature creation timestamp to be used again on second execution - // of PgpSignEncrypt when we have the signed hash! - data.putExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, nfcCreationDate.getTime()); - - // return PendingIntent to be executed by client - Intent result = new Intent(); - result.putExtra(OpenPgpApi.RESULT_INTENT, - getNfcSignPendingIntent(data, pgpResult.getNfcKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcHash(), pgpResult.getNfcAlgo())); - result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); - return result; - } else { - throw new PgpGeneralException( - "Encountered unhandled type of pending action not supported by API!"); - } + + RequiredInputParcel requiredInput = pgpResult.getRequiredInputParcel(); + PendingIntent pIntent = getRequiredInputPendingIntent(getBaseContext(), data, requiredInput); + + // return PendingIntent to be executed by client + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_INTENT, pIntent); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); + return result; + } else if (pgpResult.success()) { Intent result = new Intent(); if (pgpResult.getDetachedSignature() != null && !cleartextSign) { @@ -376,11 +322,6 @@ public class OpenPgpService extends RemoteService { compressionId = CompressionAlgorithmTags.UNCOMPRESSED; } - Passphrase passphrase = null; - if (data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE) != null) { - passphrase = new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE)); - } - // first try to get key ids from non-ambiguous key id extra long[] keyIds = data.getLongArrayExtra(OpenPgpApi.EXTRA_KEY_IDS); if (keyIds == null) { @@ -405,8 +346,6 @@ public class OpenPgpService extends RemoteService { long inputLength = is.available(); InputData inputData = new InputData(is, inputLength, originalFilename); - CryptoInputParcel cryptoInput; - PgpSignEncryptInputParcel pseInput = new PgpSignEncryptInputParcel(); pseInput.setEnableAsciiArmorOutput(asciiArmor) .setVersionHeader(null) @@ -428,52 +367,28 @@ public class OpenPgpService extends RemoteService { Log.e(Constants.TAG, "No signing key given!"); } - byte[] nfcSignedHash = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_SIGNED_HASH); - // carefully: only set if timestamp exists - Date nfcCreationDate; - long nfcCreationTimestamp = data.getLongExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, -1); - if (nfcCreationTimestamp != -1) { - nfcCreationDate = new Date(nfcCreationTimestamp); - } else { - nfcCreationDate = new Date(); - } - - cryptoInput = new CryptoInputParcel(nfcCreationDate, passphrase); - cryptoInput.addCryptoData(null, nfcSignedHash); // TODO fix! - // sign and encrypt pseInput.setSignatureHashAlgorithm(PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED) .setSignatureMasterKeyId(signKeyId) .setAdditionalEncryptId(signKeyId); // add sign key for encryption - } else { - cryptoInput = new CryptoInputParcel(); } + CryptoInputParcel cryptoInput = data.getParcelableExtra(OpenPgpApi.EXTRA_CRYPTO_INPUT); + PgpSignEncryptOperation op = new PgpSignEncryptOperation(this, new ProviderHelper(getContext()), null); // execute PGP operation! PgpSignEncryptResult pgpResult = op.execute(pseInput, cryptoInput, inputData, os); if (pgpResult.isPending()) { - if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) == - PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) { - return returnPassphraseIntent(data, pgpResult.getKeyIdPassphraseNeeded()); - } else if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_NFC) == - PgpSignEncryptResult.RESULT_PENDING_NFC) { - // return PendingIntent to execute NFC activity - // pass through the signature creation timestamp to be used again on second execution - // of PgpSignEncrypt when we have the signed hash! - data.putExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, 0L); // TODO fix - // return PendingIntent to be executed by client - Intent result = new Intent(); - result.putExtra(OpenPgpApi.RESULT_INTENT, - getNfcSignPendingIntent(data, pgpResult.getNfcKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcHash(), pgpResult.getNfcAlgo())); - result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); - return result; - } else { - throw new PgpGeneralException( - "Encountered unhandled type of pending action not supported by API!"); - } + RequiredInputParcel requiredInput = pgpResult.getRequiredInputParcel(); + PendingIntent pIntent = getRequiredInputPendingIntent(getBaseContext(), data, requiredInput); + + // return PendingIntent to be executed by client + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_INTENT, pIntent); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); + return result; } else if (pgpResult.success()) { Intent result = new Intent(); result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS); @@ -522,11 +437,6 @@ public class OpenPgpService extends RemoteService { os = new ParcelFileDescriptor.AutoCloseOutputStream(output); } - Passphrase passphrase = null; - if (data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE) != null) { - passphrase = new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE)); - } - String currentPkg = getCurrentCallingPackage(); Set allowedKeyIds; if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) < 7) { @@ -544,17 +454,17 @@ public class OpenPgpService extends RemoteService { this, new ProviderHelper(getContext()), null, inputData, os ); - byte[] nfcDecryptedSessionKey = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_DECRYPTED_SESSION_KEY); + CryptoInputParcel cryptoInput = data.getParcelableExtra(OpenPgpApi.EXTRA_CRYPTO_INPUT); byte[] detachedSignature = data.getByteArrayExtra(OpenPgpApi.EXTRA_DETACHED_SIGNATURE); // allow only private keys associated with accounts of this app // no support for symmetric encryption - builder.setPassphrase(passphrase) + builder.setPassphrase(cryptoInput.getPassphrase()) // TODO proper CryptoInputParcel support .setAllowSymmetricDecryption(false) .setAllowedKeyIds(allowedKeyIds) .setDecryptMetadataOnly(decryptMetadataOnly) - .setNfcState(nfcDecryptedSessionKey) + .setNfcState(null) // TODO proper CryptoInputParcel support .setDetachedSignature(detachedSignature); DecryptVerifyResult pgpResult = builder.build().execute(); @@ -562,20 +472,15 @@ public class OpenPgpService extends RemoteService { if (pgpResult.isPending()) { if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) == DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) { - return returnPassphraseIntent(data, pgpResult.getKeyIdPassphraseNeeded()); + throw new AssertionError("not implemented"); // TODO + // return returnPassphraseIntent(data, pgpResult.getKeyIdPassphraseNeeded()); } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) == DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) { throw new PgpGeneralException( "Decryption of symmetric content not supported by API!"); } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_NFC) == DecryptVerifyResult.RESULT_PENDING_NFC) { - - // return PendingIntent to be executed by client - Intent result = new Intent(); - result.putExtra(OpenPgpApi.RESULT_INTENT, - getNfcDecryptPendingIntent(data, pgpResult.getNfcSubKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcEncryptedSessionKey())); - result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); - return result; + throw new AssertionError("not implemented"); // TODO } else { throw new PgpGeneralException( "Encountered unhandled type of pending action not supported by API!"); @@ -765,7 +670,6 @@ public class OpenPgpService extends RemoteService { * - has supported API version * - is allowed to call the service (access has been granted) * - * @param data * @return null if everything is okay, or a Bundle with an error/PendingIntent */ private Intent checkRequirements(Intent data) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java index 471fc0ec9..5cc2607cc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java @@ -1,6 +1,7 @@ package org.sufficientlysecure.keychain.service.input; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Date; @@ -56,11 +57,11 @@ public class RequiredInputParcel implements Parcelable { } - public long getMasterKeyId() { + public Long getMasterKeyId() { return mMasterKeyId; } - public long getSubKeyId() { + public Long getSubKeyId() { return mSubKeyId; } @@ -88,7 +89,6 @@ public class RequiredInputParcel implements Parcelable { null, null, req.mSignatureTime, req.mMasterKeyId, req.mSubKeyId); } - @Override public int describeContents() { return 0; @@ -142,10 +142,10 @@ public class RequiredInputParcel implements Parcelable { Date mSignatureTime; ArrayList mSignAlgos = new ArrayList<>(); ArrayList mInputHashes = new ArrayList<>(); - long mMasterKeyId; - long mSubKeyId; + Long mMasterKeyId; + Long mSubKeyId; - public NfcSignOperationsBuilder(Date signatureTime, long masterKeyId, long subKeyId) { + public NfcSignOperationsBuilder(Date signatureTime, Long masterKeyId, Long subKeyId) { mSignatureTime = signatureTime; mMasterKeyId = masterKeyId; mSubKeyId = subKeyId; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CryptoOperationFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CryptoOperationFragment.java index 5227c1477..b632509bb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CryptoOperationFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CryptoOperationFragment.java @@ -66,7 +66,7 @@ public abstract class CryptoOperationFragment extends Fragment { case REQUEST_CODE_PASSPHRASE: { if (resultCode == Activity.RESULT_OK && data != null) { CryptoInputParcel cryptoInput = - data.getParcelableExtra(PassphraseDialogActivity.RESULT_DATA); + data.getParcelableExtra(PassphraseDialogActivity.RESULT_CRYPTO_INPUT); cryptoOperation(cryptoInput); return; } @@ -110,6 +110,10 @@ public abstract class CryptoOperationFragment extends Fragment { return false; } + protected void cryptoOperation() { + cryptoOperation(new CryptoInputParcel()); + } + protected abstract void cryptoOperation(CryptoInputParcel cryptoInput); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java index ecc99b348..d1c005868 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java @@ -198,7 +198,7 @@ public class DecryptFilesFragment extends DecryptFragment { // data.putParcelable(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase); // data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey); // -// intent.putExtra(KeychainIntentService.EXTRA_DATA, data); +// intent.putExtra(KeychainIntentService.EXTRA_SERVICE_INTENT, data); // // // Message is received after decrypting is done in KeychainIntentService // ServiceProgressHandler saveHandler = new ServiceProgressHandler( diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java index f00136d5b..38ad54ad3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java @@ -105,7 +105,7 @@ public abstract class DecryptFragment extends CryptoOperationFragment { // // build PendingIntent for Yubikey NFC operations // Intent intent = new Intent(getActivity(), NfcActivity.class); // intent.setAction(NfcActivity.ACTION_DECRYPT_SESSION_KEY); -// intent.putExtra(NfcActivity.EXTRA_DATA, new Intent()); // not used, only relevant to OpenPgpService +// intent.putExtra(NfcActivity.EXTRA_SERVICE_INTENT, new Intent()); // not used, only relevant to OpenPgpService // intent.putExtra(NfcActivity.EXTRA_KEY_ID, subKeyId); // intent.putExtra(NfcActivity.EXTRA_PIN, pin); // diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java deleted file mode 100644 index bd52d74cf..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2014 Dominik Schürmann - * - * 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 . - */ - -package org.sufficientlysecure.keychain.ui; - -import android.app.Activity; -import android.app.ProgressDialog; -import android.content.Intent; -import android.os.Bundle; -import android.os.Message; -import android.os.Messenger; -import android.view.View; - -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult; -import org.sufficientlysecure.keychain.operations.results.SignEncryptResult; -import org.sufficientlysecure.keychain.pgp.SignEncryptParcel; -import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; -import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; -import org.sufficientlysecure.keychain.ui.base.BaseActivity; -import org.sufficientlysecure.keychain.service.ServiceProgressHandler; -import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; -import org.sufficientlysecure.keychain.util.Passphrase; - -public abstract class EncryptActivity extends BaseActivity { - - public static final int REQUEST_CODE_PASSPHRASE = 0x00008001; - public static final int REQUEST_CODE_NFC = 0x00008002; - - // For NFC data - protected Passphrase mSigningKeyPassphrase = null; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setFullScreenDialogClose(new View.OnClickListener() { - @Override - public void onClick(View v) { - setResult(Activity.RESULT_CANCELED); - finish(); - } - }, false); - } - - protected void startPassphraseDialog(long subkeyId) { - Intent intent = new Intent(this, PassphraseDialogActivity.class); - intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, subkeyId); - startActivityForResult(intent, REQUEST_CODE_PASSPHRASE); - } - - protected void startNfcSign(long keyId, RequiredInputParcel nfcOps) { - - Intent intent = new Intent(this, NfcOperationActivity.class); - intent.putExtra(NfcOperationActivity.EXTRA_REQUIRED_INPUT, nfcOps); - // TODO respect keyid(?) - - startActivityForResult(intent, REQUEST_CODE_NFC); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - switch (requestCode) { - case REQUEST_CODE_PASSPHRASE: { - if (resultCode == RESULT_OK && data != null) { - mSigningKeyPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE); - startEncrypt(); - return; - } - break; - } - - case REQUEST_CODE_NFC: { - if (resultCode == RESULT_OK && data != null) { - CryptoInputParcel cryptoInput = - data.getParcelableExtra(NfcOperationActivity.RESULT_DATA); - startEncrypt(cryptoInput); - return; - } - break; - } - - default: { - super.onActivityResult(requestCode, resultCode, data); - break; - } - } - } - - public void startEncrypt() { - startEncrypt(null); - } - - public void startEncrypt(final CryptoInputParcel cryptoInput) { - if (!inputIsValid()) { - // Notify was created by inputIsValid. - return; - } - - // Send all information needed to service to edit key in other thread - Intent intent = new Intent(this, KeychainIntentService.class); - intent.setAction(KeychainIntentService.ACTION_SIGN_ENCRYPT); - - final SignEncryptParcel input = createEncryptBundle(); - - Bundle data = new Bundle(); - data.putParcelable(KeychainIntentService.SIGN_ENCRYPT_PARCEL, input); - data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput); - intent.putExtra(KeychainIntentService.EXTRA_DATA, data); - - // Message is received after encrypting is done in KeychainIntentService - ServiceProgressHandler serviceHandler = new ServiceProgressHandler( - this, - getString(R.string.progress_encrypting), - ProgressDialog.STYLE_HORIZONTAL, - ProgressDialogFragment.ServiceType.KEYCHAIN_INTENT) { - public void handleMessage(Message message) { - // handle messages by standard KeychainIntentServiceHandler first - super.handleMessage(message); - - if (message.arg1 == MessageStatus.OKAY.ordinal()) { - SignEncryptResult result = - message.getData().getParcelable(SignEncryptResult.EXTRA_RESULT); - - PgpSignEncryptResult pgpResult = result.getPending(); - - if (pgpResult != null && pgpResult.isPending()) { - if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) == - PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) { - startPassphraseDialog(pgpResult.getKeyIdPassphraseNeeded()); - } else if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_NFC) == - PgpSignEncryptResult.RESULT_PENDING_NFC) { - - RequiredInputParcel parcel = RequiredInputParcel.createNfcSignOperation( - pgpResult.getNfcHash(), - pgpResult.getNfcAlgo(), - cryptoInput.getSignatureTime()); - startNfcSign(pgpResult.getNfcKeyId(), parcel); - - } else { - throw new RuntimeException("Unhandled pending result!"); - } - return; - } - - if (result.success()) { - onEncryptSuccess(result); - } else { - result.createNotify(EncryptActivity.this).show(); - } - - // no matter the result, reset parameters - mSigningKeyPassphrase = null; - } - } - }; - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(serviceHandler); - intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); - - // show progress dialog - serviceHandler.showProgressDialog(this); - - // start service with intent - startService(intent); - } - - protected abstract boolean inputIsValid(); - - protected abstract void onEncryptSuccess(SignEncryptResult result); - - protected abstract SignEncryptParcel createEncryptBundle(); - -} 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 7e4c48e10..b320c8a50 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java @@ -363,7 +363,7 @@ public class EncryptFilesFragment extends CryptoOperationFragment { public void startEncrypt(boolean share) { mShareAfterEncrypt = share; - cryptoOperation(new CryptoInputParcel()); + cryptoOperation(); } public void onEncryptSuccess(final SignEncryptResult result) { @@ -512,36 +512,11 @@ public class EncryptFilesFragment extends CryptoOperationFragment { if (message.arg1 == MessageStatus.OKAY.ordinal()) { SignEncryptResult result = message.getData().getParcelable(SignEncryptResult.EXTRA_RESULT); - -// PgpSignEncryptResult pgpResult = result.getPending(); -// -// if (pgpResult != null && pgpResult.isPending()) { -// if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) == -// PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) { -// startPassphraseDialog(pgpResult.getKeyIdPassphraseNeeded()); -// } else if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_NFC) == -// PgpSignEncryptResult.RESULT_PENDING_NFC) { -// -// RequiredInputParcel parcel = RequiredInputParcel.createNfcSignOperation( -// pgpResult.getNfcHash(), -// pgpResult.getNfcAlgo(), -// input.getSignatureTime()); -// startNfcSign(pgpResult.getNfcKeyId(), parcel); -// -// } else { -// throw new RuntimeException("Unhandled pending result!"); -// } -// return; -// } - if (result.success()) { onEncryptSuccess(result); } else { result.createNotify(getActivity()).show(); } - - // no matter the result, reset parameters -// mSigningKeyPassphrase = null; } } }; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java index 2ffb29b09..03ab48e23 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -160,6 +160,6 @@ public class EncryptTextActivity extends BaseActivity implements @Override public void onPassphraseChanged(Passphrase passphrase) { - mEncryptFragment.setPassphrase(passphrase); + mEncryptFragment.setSymmetricPassphrase(passphrase); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java index 7197cf88d..fecc9ef52 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java @@ -37,7 +37,6 @@ import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; -import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult; import org.sufficientlysecure.keychain.operations.results.SignEncryptResult; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.PgpConstants; @@ -73,7 +72,7 @@ public class EncryptTextFragment extends CryptoOperationFragment { private String mEncryptionUserIds[] = null; // TODO Constants.key.none? What's wrong with a null value? private long mSigningKeyId = Constants.key.none; - private Passphrase mPassphrase = new Passphrase(); + private Passphrase mSymmetricPassphrase = new Passphrase(); private String mMessage = ""; private TextView mText; @@ -90,8 +89,8 @@ public class EncryptTextFragment extends CryptoOperationFragment { mSigningKeyId = signingKeyId; } - public void setPassphrase(Passphrase passphrase) { - mPassphrase = passphrase; + public void setSymmetricPassphrase(Passphrase passphrase) { + mSymmetricPassphrase = passphrase; } /** @@ -233,7 +232,7 @@ public class EncryptTextFragment extends CryptoOperationFragment { if (mSymmetricMode) { Log.d(Constants.TAG, "Symmetric encryption enabled!"); - Passphrase passphrase = mPassphrase; + Passphrase passphrase = mSymmetricPassphrase; if (passphrase.isEmpty()) { passphrase = null; } @@ -241,7 +240,6 @@ public class EncryptTextFragment extends CryptoOperationFragment { } else { data.setEncryptionMasterKeyIds(mEncryptionKeyIds); data.setSignatureMasterKeyId(mSigningKeyId); -// data.setSignaturePassphrase(mSigningKeyPassphrase); } return data; } @@ -296,12 +294,12 @@ public class EncryptTextFragment extends CryptoOperationFragment { if (mSymmetricMode) { // symmetric encryption checks - if (mPassphrase == null) { + if (mSymmetricPassphrase == null) { Notify.create(getActivity(), R.string.passphrases_do_not_match, Notify.Style.ERROR) .show(); return false; } - if (mPassphrase.isEmpty()) { + if (mSymmetricPassphrase.isEmpty()) { Notify.create(getActivity(), R.string.passphrase_must_not_be_empty, Notify.Style.ERROR) .show(); return false; @@ -325,11 +323,7 @@ public class EncryptTextFragment extends CryptoOperationFragment { public void startEncrypt(boolean share) { mShareAfterEncrypt = share; - startEncrypt(); - } - - public void startEncrypt() { - cryptoOperation(null); + cryptoOperation(); } @Override @@ -359,45 +353,19 @@ public class EncryptTextFragment extends CryptoOperationFragment { // handle messages by standard KeychainIntentServiceHandler first super.handleMessage(message); - // TODO: We need a InputPendingResult! -// // handle pending messages -// if (handlePendingMessage(message)) { -// return; -// } + if (handlePendingMessage(message)) { + return; + } if (message.arg1 == MessageStatus.OKAY.ordinal()) { SignEncryptResult result = message.getData().getParcelable(SignEncryptResult.EXTRA_RESULT); - PgpSignEncryptResult pgpResult = result.getPending(); - -// if (pgpResult != null && pgpResult.isPending()) { -// if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) == -// PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) { -// startPassphraseDialog(pgpResult.getKeyIdPassphraseNeeded()); -// } else if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_NFC) == -// PgpSignEncryptResult.RESULT_PENDING_NFC) { -// -// RequiredInputParcel parcel = RequiredInputParcel.createNfcSignOperation( -// pgpResult.getNfcHash(), -// pgpResult.getNfcAlgo(), -// input.getSignatureTime()); -// startNfcSign(pgpResult.getNfcKeyId(), parcel); -// -// } else { -// throw new RuntimeException("Unhandled pending result!"); -// } -// return; -// } - if (result.success()) { onEncryptSuccess(result); } else { result.createNotify(getActivity()).show(); } - - // no matter the result, reset parameters -// mSigningKeyPassphrase = null; } } }; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java index 57acf3e93..1cb5a41a7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java @@ -100,7 +100,7 @@ public class NfcActivity extends BaseActivity { Log.d(Constants.TAG, "NfcActivity mAction: " + mAction); Log.d(Constants.TAG, "NfcActivity mPin: " + mPin); Log.d(Constants.TAG, "NfcActivity mHashToSign as hex: " + getHex(mHashToSign)); - Log.d(Constants.TAG, "NfcActivity mServiceIntent: " + mServiceIntent.toString()); + Log.d(Constants.TAG, "NfcActivity mServiceIntent: " + mServiceIntent); break; case ACTION_DECRYPT_SESSION_KEY: mAction = action; @@ -111,7 +111,7 @@ public class NfcActivity extends BaseActivity { Log.d(Constants.TAG, "NfcActivity mAction: " + mAction); Log.d(Constants.TAG, "NfcActivity mPin: " + mPin); Log.d(Constants.TAG, "NfcActivity mEncryptedSessionKey as hex: " + getHex(mEncryptedSessionKey)); - Log.d(Constants.TAG, "NfcActivity mServiceIntent: " + mServiceIntent.toString()); + Log.d(Constants.TAG, "NfcActivity mServiceIntent: " + mServiceIntent); break; case NfcAdapter.ACTION_TAG_DISCOVERED: Log.e(Constants.TAG, "This should not happen! NfcActivity.onCreate() is being called instead of onNewIntent()!"); 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 511183b04..d70b0aad1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java @@ -10,8 +10,10 @@ import android.annotation.TargetApi; import android.content.Intent; import android.os.Build; import android.os.Bundle; +import android.os.Parcelable; import android.view.WindowManager; +import org.openintents.openpgp.util.OpenPgpApi; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.service.PassphraseCacheService; @@ -34,9 +36,13 @@ public class NfcOperationActivity extends BaseNfcActivity { public static final String EXTRA_REQUIRED_INPUT = "required_input"; + // passthrough for OpenPgpService + public static final String EXTRA_SERVICE_INTENT = "data"; + public static final String RESULT_DATA = "result_data"; - RequiredInputParcel mRequiredInput; + private RequiredInputParcel mRequiredInput; + private Intent mServiceIntent; @Override protected void onCreate(Bundle savedInstanceState) { @@ -49,6 +55,7 @@ public class NfcOperationActivity extends BaseNfcActivity { Bundle data = intent.getExtras(); mRequiredInput = data.getParcelable(EXTRA_REQUIRED_INPUT); + mServiceIntent = data.getParcelable(EXTRA_SERVICE_INTENT); // obtain passphrase for this subkey obtainYubikeyPin(RequiredInputParcel.createRequiredPassphrase(mRequiredInput)); @@ -84,10 +91,15 @@ public class NfcOperationActivity extends BaseNfcActivity { break; } - // give data through for new service call - Intent result = new Intent(); - result.putExtra(NfcOperationActivity.RESULT_DATA, resultData); - setResult(RESULT_OK, result); + if (mServiceIntent != null) { + mServiceIntent.putExtra(OpenPgpApi.EXTRA_CRYPTO_INPUT, resultData); + setResult(RESULT_OK, mServiceIntent); + } else { + Intent result = new Intent(); + result.putExtra(NfcOperationActivity.RESULT_DATA, resultData); + setResult(RESULT_OK, result); + } + finish(); } 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 9e04426eb..c1771ce57 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java @@ -41,7 +41,7 @@ import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; -import junit.framework.Assert; +import org.openintents.openpgp.util.OpenPgpApi; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; @@ -67,14 +67,13 @@ import org.sufficientlysecure.keychain.util.Preferences; * This activity encapsulates a DialogFragment to emulate a dialog. */ public class PassphraseDialogActivity extends FragmentActivity { - public static final String MESSAGE_DATA_PASSPHRASE = "passphrase"; - public static final String RESULT_DATA = "result_data"; + public static final String RESULT_CRYPTO_INPUT = "result_data"; public static final String EXTRA_REQUIRED_INPUT = "required_input"; public static final String EXTRA_SUBKEY_ID = "secret_key_id"; // special extra for OpenPgpService - public static final String EXTRA_DATA = "data"; + public static final String EXTRA_SERVICE_INTENT = "data"; private static final int REQUEST_CODE_ENTER_PATTERN = 2; @@ -104,7 +103,7 @@ public class PassphraseDialogActivity extends FragmentActivity { keyId = requiredInput.getSubKeyId(); } - Intent serviceIntent = getIntent().getParcelableExtra(EXTRA_DATA); + Intent serviceIntent = getIntent().getParcelableExtra(EXTRA_SERVICE_INTENT); show(this, keyId, serviceIntent); } @@ -155,7 +154,7 @@ public class PassphraseDialogActivity extends FragmentActivity { PassphraseDialogFragment frag = new PassphraseDialogFragment(); Bundle args = new Bundle(); args.putLong(EXTRA_SUBKEY_ID, keyId); - args.putParcelable(EXTRA_DATA, serviceIntent); + args.putParcelable(EXTRA_SERVICE_INTENT, serviceIntent); frag.setArguments(args); @@ -188,7 +187,7 @@ public class PassphraseDialogActivity extends FragmentActivity { R.style.Theme_AppCompat_Light_Dialog); mSubKeyId = getArguments().getLong(EXTRA_SUBKEY_ID); - mServiceIntent = getArguments().getParcelable(EXTRA_DATA); + mServiceIntent = getArguments().getParcelable(EXTRA_SERVICE_INTENT); CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(theme); @@ -418,15 +417,13 @@ public class PassphraseDialogActivity extends FragmentActivity { } if (mServiceIntent != null) { - // TODO: Not routing passphrase through OpenPGP API currently - // due to security concerns... - // BUT this means you need to _cache_ passphrases! + // TODO really pass this through the PendingIntent? + mServiceIntent.putExtra(OpenPgpApi.EXTRA_CRYPTO_INPUT, new CryptoInputParcel(null, passphrase)); getActivity().setResult(RESULT_OK, mServiceIntent); } else { // also return passphrase back to activity Intent returnIntent = new Intent(); - returnIntent.putExtra(MESSAGE_DATA_PASSPHRASE, passphrase); - returnIntent.putExtra(RESULT_DATA, new CryptoInputParcel(null, passphrase)); + returnIntent.putExtra(RESULT_CRYPTO_INPUT, new CryptoInputParcel(null, passphrase)); getActivity().setResult(RESULT_OK, returnIntent); } 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 a8a5a1f28..0b22ecdaf 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 @@ -130,7 +130,7 @@ public abstract class BaseNfcActivity extends BaseActivity { protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUEST_CODE_PASSPHRASE: - CryptoInputParcel input = data.getParcelableExtra(PassphraseDialogActivity.RESULT_DATA); + CryptoInputParcel input = data.getParcelableExtra(PassphraseDialogActivity.RESULT_CRYPTO_INPUT); mPin = input.getPassphrase(); break; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java index 943b913d7..3bbd86d6a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java @@ -57,7 +57,7 @@ public class KeyUpdateHelper { Bundle importData = new Bundle(); importData.putParcelableArrayList(KeychainIntentService.DOWNLOAD_KEY_LIST, new ArrayList(keys)); - importIntent.putExtra(KeychainIntentService.EXTRA_DATA, importData); + importIntent.putExtra(KeychainIntentService.EXTRA_SERVICE_INTENT, importData); importIntent.putExtra(KeychainIntentService.EXTRA_MESSENGER, new Messenger(mHandler)); diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 78940aa9e..6d29ce3fd 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -1048,7 +1048,6 @@ "Error opening URI for reading!" "Error opening URI for writing!" "More inputs than outputs specified! This is probably a programming error, please report!" - "Got outputs left but no inputs. This is probably a programming error, please report!" "Sign/encrypt operation successful" -- cgit v1.2.3