From ad69622b6983d139e2cef1380f502edef19d2180 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 1 Apr 2015 00:38:01 +0200 Subject: fix Decrypt*Fragment for RequiredInputParcel (except decryptOriginalFilename) --- .../keychain/operations/CertifyOperation.java | 2 +- .../operations/results/DecryptVerifyResult.java | 58 ++-------------- .../keychain/pgp/CanonicalizedSecretKey.java | 7 +- .../keychain/pgp/PgpDecryptVerify.java | 80 ++++++++++------------ .../keychain/pgp/PgpKeyOperation.java | 2 +- .../keychain/pgp/PgpSignEncryptOperation.java | 4 +- .../keychain/remote/OpenPgpService.java | 36 ++++------ .../keychain/service/KeychainIntentService.java | 39 ++++------- .../service/input/RequiredInputParcel.java | 47 +++++++++---- .../keychain/ui/CryptoOperationFragment.java | 3 +- .../keychain/ui/DecryptFilesFragment.java | 36 +--------- .../keychain/ui/DecryptFragment.java | 10 --- .../keychain/ui/DecryptTextFragment.java | 66 +++--------------- .../keychain/ui/PassphraseDialogActivity.java | 15 +++- 14 files changed, 138 insertions(+), 267 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java index eb2a3d33f..051517abd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java @@ -80,7 +80,7 @@ public class CertifyOperation extends BaseOperation { certificationKey = secretKeyRing.getSecretKey(); if (!cryptoInput.hasPassphrase()) { - return new CertifyResult(log, RequiredInputParcel.createRequiredPassphrase( + return new CertifyResult(log, RequiredInputParcel.createRequiredSignPassphrase( certificationKey.getKeyId(), certificationKey.getKeyId(), null)); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java index 7df37cd9b..917b3415f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java @@ -22,23 +22,10 @@ import android.os.Parcel; import org.openintents.openpgp.OpenPgpMetadata; import org.openintents.openpgp.OpenPgpSignatureResult; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.util.Passphrase; -public class DecryptVerifyResult 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; - - // fifth to sixth bit in addition indicate specific type of pending - public static final int RESULT_PENDING_ASYM_PASSPHRASE = RESULT_PENDING + 16; - public static final int RESULT_PENDING_SYM_PASSPHRASE = RESULT_PENDING + 32; - public static final int RESULT_PENDING_NFC = RESULT_PENDING + 64; - - long mKeyIdPassphraseNeeded; - - long mNfcSubKeyId; - byte[] mNfcSessionKey; - Passphrase mNfcPassphrase; +public class DecryptVerifyResult extends InputPendingResult { OpenPgpSignatureResult mSignatureResult; OpenPgpMetadata mDecryptMetadata; @@ -46,32 +33,6 @@ public class DecryptVerifyResult extends OperationResult { // https://tools.ietf.org/html/rfc4880#page56 String mCharset; - public long getKeyIdPassphraseNeeded() { - return mKeyIdPassphraseNeeded; - } - - public void setKeyIdPassphraseNeeded(long keyIdPassphraseNeeded) { - mKeyIdPassphraseNeeded = keyIdPassphraseNeeded; - } - - public void setNfcState(long subKeyId, byte[] sessionKey, Passphrase passphrase) { - mNfcSubKeyId = subKeyId; - mNfcSessionKey = sessionKey; - mNfcPassphrase = passphrase; - } - - public long getNfcSubKeyId() { - return mNfcSubKeyId; - } - - public byte[] getNfcEncryptedSessionKey() { - return mNfcSessionKey; - } - - public Passphrase getNfcPassphrase() { - return mNfcPassphrase; - } - public OpenPgpSignatureResult getSignatureResult() { return mSignatureResult; } @@ -104,13 +65,14 @@ public class DecryptVerifyResult extends OperationResult { super(result, log); } + public DecryptVerifyResult(OperationLog log, RequiredInputParcel requiredInput) { + super(log, requiredInput); + } + public DecryptVerifyResult(Parcel source) { super(source); - mKeyIdPassphraseNeeded = source.readLong(); mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader()); mDecryptMetadata = source.readParcelable(OpenPgpMetadata.class.getClassLoader()); - mNfcSessionKey = source.readInt() != 0 ? source.createByteArray() : null; - mNfcPassphrase = source.readParcelable(Passphrase.class.getClassLoader()); } public int describeContents() { @@ -119,16 +81,8 @@ public class DecryptVerifyResult extends OperationResult { public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); - dest.writeLong(mKeyIdPassphraseNeeded); dest.writeParcelable(mSignatureResult, 0); dest.writeParcelable(mDecryptMetadata, 0); - if (mNfcSessionKey != null) { - dest.writeInt(1); - dest.writeByteArray(mNfcSessionKey); - } else { - dest.writeInt(0); - } - dest.writeParcelable(mNfcPassphrase, flags); } public static final Creator CREATOR = new Creator() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java index 30be72dd5..39d0a2f1d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java @@ -40,6 +40,7 @@ import org.spongycastle.openpgp.operator.jcajce.NfcSyncPublicKeyDataDecryptorFac import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Passphrase; @@ -264,14 +265,16 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey { } } - public PublicKeyDataDecryptorFactory getDecryptorFactory(byte[] nfcDecryptedSessionKey) { + public PublicKeyDataDecryptorFactory getDecryptorFactory(CryptoInputParcel cryptoInput) { if (mPrivateKeyState == PRIVATE_KEY_STATE_LOCKED) { throw new PrivateKeyNotUnlockedException(); } if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) { return new NfcSyncPublicKeyDataDecryptorFactoryBuilder() - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(nfcDecryptedSessionKey); + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( + cryptoInput.getCryptoData() + ); } else { return new JcePublicKeyDataDecryptorFactoryBuilder() .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(mPrivateKey); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index 364a1067d..f6580b85a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -47,16 +47,15 @@ import org.spongycastle.openpgp.operator.jcajce.NfcSyncPublicKeyDataDecryptorFac import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.BaseOperation; +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.operations.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -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; @@ -84,10 +83,8 @@ public class PgpDecryptVerify extends BaseOperation { private OutputStream mOutStream; private boolean mAllowSymmetricDecryption; - private Passphrase mPassphrase; private Set mAllowedKeyIds; private boolean mDecryptMetadataOnly; - private byte[] mDecryptedSessionKey; private byte[] mDetachedSignature; private String mRequiredSignerFingerprint; private boolean mSignedLiteralData; @@ -100,10 +97,8 @@ public class PgpDecryptVerify extends BaseOperation { this.mOutStream = builder.mOutStream; this.mAllowSymmetricDecryption = builder.mAllowSymmetricDecryption; - this.mPassphrase = builder.mPassphrase; this.mAllowedKeyIds = builder.mAllowedKeyIds; this.mDecryptMetadataOnly = builder.mDecryptMetadataOnly; - this.mDecryptedSessionKey = builder.mDecryptedSessionKey; this.mDetachedSignature = builder.mDetachedSignature; this.mSignedLiteralData = builder.mSignedLiteralData; this.mRequiredSignerFingerprint = builder.mRequiredSignerFingerprint; @@ -119,10 +114,8 @@ public class PgpDecryptVerify extends BaseOperation { private OutputStream mOutStream = null; private Progressable mProgressable = null; private boolean mAllowSymmetricDecryption = true; - private Passphrase mPassphrase = null; private Set mAllowedKeyIds = null; private boolean mDecryptMetadataOnly = false; - private byte[] mDecryptedSessionKey = null; private byte[] mDetachedSignature = null; private String mRequiredSignerFingerprint = null; private boolean mSignedLiteralData = false; @@ -160,11 +153,6 @@ public class PgpDecryptVerify extends BaseOperation { return this; } - public Builder setPassphrase(Passphrase passphrase) { - mPassphrase = passphrase; - return this; - } - /** * Allow these key ids alone for decryption. * This means only ciphertexts encrypted for one of these private key can be decrypted. @@ -183,11 +171,6 @@ public class PgpDecryptVerify extends BaseOperation { return this; } - public Builder setNfcState(byte[] decryptedSessionKey) { - mDecryptedSessionKey = decryptedSessionKey; - return this; - } - /** * If detachedSignature != null, it will be used exclusively to verify the signature */ @@ -204,7 +187,7 @@ public class PgpDecryptVerify extends BaseOperation { /** * Decrypts and/or verifies data based on parameters of class */ - public DecryptVerifyResult execute() { + public DecryptVerifyResult execute(CryptoInputParcel cryptoInput) { try { if (mDetachedSignature != null) { Log.d(Constants.TAG, "Detached signature present, verifying with this signature only"); @@ -226,10 +209,10 @@ public class PgpDecryptVerify extends BaseOperation { return verifyCleartextSignature(aIn, 0); } else { // else: ascii armored encryption! go on... - return decryptVerify(in, 0); + return decryptVerify(cryptoInput, in, 0); } } else { - return decryptVerify(in, 0); + return decryptVerify(cryptoInput, in, 0); } } } catch (PGPException e) { @@ -248,7 +231,8 @@ public class PgpDecryptVerify extends BaseOperation { /** * Verify Keybase.io style signed literal data */ - private DecryptVerifyResult verifySignedLiteralData(InputStream in, int indent) throws IOException, PGPException { + private DecryptVerifyResult verifySignedLiteralData(InputStream in, int indent) + throws IOException, PGPException { OperationLog log = new OperationLog(); log.add(LogType.MSG_VL, indent); @@ -378,7 +362,8 @@ public class PgpDecryptVerify extends BaseOperation { /** * Decrypt and/or verifies binary or ascii armored pgp */ - private DecryptVerifyResult decryptVerify(InputStream in, int indent) throws IOException, PGPException { + private DecryptVerifyResult decryptVerify(CryptoInputParcel cryptoInput, + InputStream in, int indent) throws IOException, PGPException { OperationLog log = new OperationLog(); @@ -433,6 +418,8 @@ public class PgpDecryptVerify extends BaseOperation { } } + Passphrase passphrase = null; + // go through all objects and find one we can decrypt while (it.hasNext()) { Object obj = it.next(); @@ -492,11 +479,15 @@ public class PgpDecryptVerify extends BaseOperation { encryptedDataAsymmetric = encData; - // if no passphrase was explicitly set try to get it from the cache service - if (mPassphrase == null) { + if (secretEncryptionKey.getSecretKeyType() == SecretKeyType.DIVERT_TO_CARD) { + passphrase = null; + } else if (cryptoInput.hasPassphrase()) { + passphrase = cryptoInput.getPassphrase(); + } else { + // if no passphrase was explicitly set try to get it from the cache service try { // returns "" if key has no passphrase - mPassphrase = getCachedPassphrase(subKeyId); + passphrase = getCachedPassphrase(subKeyId); log.add(LogType.MSG_DC_PASS_CACHED, indent + 1); } catch (PassphraseCacheInterface.NoSecretKeyException e) { log.add(LogType.MSG_DC_ERROR_NO_KEY, indent + 1); @@ -504,12 +495,11 @@ public class PgpDecryptVerify extends BaseOperation { } // if passphrase was not cached, return here indicating that a passphrase is missing! - if (mPassphrase == null) { + if (passphrase == null) { log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1); - DecryptVerifyResult result = - new DecryptVerifyResult(DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE, log); - result.setKeyIdPassphraseNeeded(subKeyId); - return result; + return new DecryptVerifyResult(log, + RequiredInputParcel.createRequiredDecryptPassphrase( + secretKeyRing.getMasterKeyId(), secretEncryptionKey.getKeyId())); } } @@ -536,11 +526,14 @@ public class PgpDecryptVerify extends BaseOperation { // if no passphrase is given, return here // indicating that a passphrase is missing! - if (mPassphrase == null) { + if (!cryptoInput.hasPassphrase()) { log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1); - return new DecryptVerifyResult(DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE, log); + return new DecryptVerifyResult(log, + RequiredInputParcel.createRequiredSymmetricPassphrase()); } + passphrase = cryptoInput.getPassphrase(); + // break out of while, only decrypt the first packet break; } @@ -573,7 +566,7 @@ public class PgpDecryptVerify extends BaseOperation { .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(); PBEDataDecryptorFactory decryptorFactory = new JcePBEDataDecryptorFactoryBuilder( digestCalcProvider).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( - mPassphrase.getCharArray()); + passphrase.getCharArray()); clear = encryptedDataSymmetric.getDataStream(decryptorFactory); encryptedData = encryptedDataSymmetric; @@ -585,7 +578,7 @@ public class PgpDecryptVerify extends BaseOperation { try { log.add(LogType.MSG_DC_UNLOCKING, indent + 1); - if (!secretEncryptionKey.unlock(mPassphrase)) { + if (!secretEncryptionKey.unlock(passphrase)) { log.add(LogType.MSG_DC_ERROR_BAD_PASSPHRASE, indent + 1); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } @@ -599,16 +592,15 @@ public class PgpDecryptVerify extends BaseOperation { try { PublicKeyDataDecryptorFactory decryptorFactory - = secretEncryptionKey.getDecryptorFactory(mDecryptedSessionKey); + = secretEncryptionKey.getDecryptorFactory(cryptoInput); clear = encryptedDataAsymmetric.getDataStream(decryptorFactory); symmetricEncryptionAlgo = encryptedDataAsymmetric.getSymmetricAlgorithm(decryptorFactory); } catch (NfcSyncPublicKeyDataDecryptorFactoryBuilder.NfcInteractionNeeded e) { log.add(LogType.MSG_DC_PENDING_NFC, indent + 1); - DecryptVerifyResult result = - new DecryptVerifyResult(DecryptVerifyResult.RESULT_PENDING_NFC, log); - result.setNfcState(secretEncryptionKey.getKeyId(), e.encryptedSessionKey, mPassphrase); - return result; + return new DecryptVerifyResult(log, RequiredInputParcel.createNfcDecryptOperation( + e.encryptedSessionKey, secretEncryptionKey.getKeyId() + )); } encryptedData = encryptedDataAsymmetric; } else { @@ -878,8 +870,8 @@ public class PgpDecryptVerify extends BaseOperation { * The method is heavily based on * pg/src/main/java/org/spongycastle/openpgp/examples/ClearSignedFileProcessor.java */ - private DecryptVerifyResult verifyCleartextSignature(ArmoredInputStream aIn, int indent) - throws IOException, PGPException { + private DecryptVerifyResult verifyCleartextSignature( + ArmoredInputStream aIn, int indent) throws IOException, PGPException { OperationLog log = new OperationLog(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index f73bada06..89db378a9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -408,7 +408,7 @@ public class PgpKeyOperation { // Do we require a passphrase? If so, pass it along if (!isDivertToCard(masterSecretKey) && !cryptoInput.hasPassphrase()) { log.add(LogType.MSG_MF_REQUIRE_PASSPHRASE, indent); - return new PgpEditKeyResult(log, RequiredInputParcel.createRequiredPassphrase( + return new PgpEditKeyResult(log, RequiredInputParcel.createRequiredSignPassphrase( masterSecretKey.getKeyID(), masterSecretKey.getKeyID(), cryptoInput.getSignatureTime())); } 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 f6959ffb3..cdb6000c2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java @@ -33,14 +33,12 @@ import org.spongycastle.openpgp.PGPSignatureGenerator; import org.spongycastle.openpgp.operator.jcajce.JcePBEKeyEncryptionMethodGenerator; import org.spongycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder; import org.spongycastle.openpgp.operator.jcajce.NfcSyncPGPContentSignerBuilder; -import org.spongycastle.util.encoders.Hex; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; 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; @@ -181,7 +179,7 @@ public class PgpSignEncryptOperation extends BaseOperation { case PASSPHRASE: { if (cryptoInput.getPassphrase() == null) { log.add(LogType.MSG_PSE_PENDING_PASSPHRASE, indent + 1); - return new PgpSignEncryptResult(log, RequiredInputParcel.createRequiredPassphrase( + return new PgpSignEncryptResult(log, RequiredInputParcel.createRequiredSignPassphrase( signingKeyRing.getMasterKeyId(), signingKey.getKeyId(), 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 e6b3a2167..98ddaaf27 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -473,31 +473,23 @@ public class OpenPgpService extends RemoteService { // allow only private keys associated with accounts of this app // no support for symmetric encryption - builder.setPassphrase(cryptoInput.getPassphrase()) // TODO proper CryptoInputParcel support - .setAllowSymmetricDecryption(false) - .setAllowedKeyIds(allowedKeyIds) - .setDecryptMetadataOnly(decryptMetadataOnly) - .setNfcState(null) // TODO proper CryptoInputParcel support - .setDetachedSignature(detachedSignature); + builder.setAllowSymmetricDecryption(false) + .setAllowedKeyIds(allowedKeyIds) + .setDecryptMetadataOnly(decryptMetadataOnly) + .setDetachedSignature(detachedSignature); - DecryptVerifyResult pgpResult = builder.build().execute(); + DecryptVerifyResult pgpResult = builder.build().execute(cryptoInput); if (pgpResult.isPending()) { - if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) == - DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) { - 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) { - throw new AssertionError("not implemented"); // TODO - } else { - throw new PgpGeneralException( - "Encountered unhandled type of pending action not supported by API!"); - } + // prepare and return PendingIntent to be executed by client + RequiredInputParcel requiredInput = pgpResult.getRequiredInputParcel(); + PendingIntent pIntent = getRequiredInputPendingIntent(getBaseContext(), data, requiredInput); + + 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(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index c7d9d5e38..e0509ac9b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -151,8 +151,6 @@ public class KeychainIntentService extends IntentService implements Progressable // decrypt/verify public static final String DECRYPT_CIPHERTEXT_BYTES = "ciphertext_bytes"; - public static final String DECRYPT_PASSPHRASE = "passphrase"; - public static final String DECRYPT_NFC_DECRYPTED_SESSION_KEY = "nfc_decrypted_session_key"; // keybase proof public static final String KEYBASE_REQUIRED_FINGERPRINT = "keybase_required_fingerprint"; @@ -284,25 +282,19 @@ public class KeychainIntentService extends IntentService implements Progressable try { /* Input */ - Passphrase passphrase = data.getParcelable(DECRYPT_PASSPHRASE); - byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY); + CryptoInputParcel cryptoInput = data.getParcelable(EXTRA_CRYPTO_INPUT); InputData inputData = createDecryptInputData(data); - /* Operation */ - Bundle resultData = new Bundle(); - // verifyText and decrypt returning additional resultData values for the // verification of signatures PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder( this, new ProviderHelper(this), this, inputData, null ); builder.setAllowSymmetricDecryption(true) - .setPassphrase(passphrase) - .setDecryptMetadataOnly(true) - .setNfcState(nfcDecryptedSessionKey); + .setDecryptMetadataOnly(true); - DecryptVerifyResult decryptVerifyResult = builder.build().execute(); + DecryptVerifyResult decryptVerifyResult = builder.build().execute(cryptoInput); sendMessageToHandler(MessageStatus.OKAY, decryptVerifyResult); } catch (Exception e) { @@ -377,7 +369,8 @@ public class KeychainIntentService extends IntentService implements Progressable ); builder.setSignedLiteralData(true).setRequiredSignerFingerprint(requiredFingerprint); - DecryptVerifyResult decryptVerifyResult = builder.build().execute(); + DecryptVerifyResult decryptVerifyResult = builder.build().execute( + new CryptoInputParcel()); outStream.close(); if (!decryptVerifyResult.success()) { @@ -412,15 +405,13 @@ public class KeychainIntentService extends IntentService implements Progressable case ACTION_DECRYPT_VERIFY: { try { - /* Input */ - Passphrase passphrase = data.getParcelable(DECRYPT_PASSPHRASE); - byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY); + /* Input */ + CryptoInputParcel cryptoInput = data.getParcelable(EXTRA_CRYPTO_INPUT); InputData inputData = createDecryptInputData(data); OutputStream outStream = createCryptOutputStream(data); - /* Operation */ - + /* Operation */ Bundle resultData = new Bundle(); // verifyText and decrypt returning additional resultData values for the @@ -429,24 +420,22 @@ public class KeychainIntentService extends IntentService implements Progressable this, new ProviderHelper(this), this, inputData, outStream ); - builder.setAllowSymmetricDecryption(true) - .setPassphrase(passphrase) - .setNfcState(nfcDecryptedSessionKey); + builder.setAllowSymmetricDecryption(true); - DecryptVerifyResult decryptVerifyResult = builder.build().execute(); + DecryptVerifyResult decryptVerifyResult = builder.build().execute(cryptoInput); outStream.close(); resultData.putParcelable(DecryptVerifyResult.EXTRA_RESULT, decryptVerifyResult); - /* Output */ - + /* Output */ finalizeDecryptOutputStream(data, resultData, outStream); - Log.logDebugBundle(resultData, "resultData"); sendMessageToHandler(MessageStatus.OKAY, resultData); - } catch (Exception e) { + + } catch (IOException | PgpGeneralException e) { + // TODO get rid of this! sendErrorToHandler(e); } 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 5cc2607cc..535c1e735 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,18 +1,19 @@ package org.sufficientlysecure.keychain.service.input; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Date; import android.os.Parcel; import android.os.Parcelable; +import org.sufficientlysecure.keychain.Constants.key; + public class RequiredInputParcel implements Parcelable { public enum RequiredInputType { - PASSPHRASE, NFC_SIGN, NFC_DECRYPT + PASSPHRASE, PASSPHRASE_SYMMETRIC, NFC_SIGN, NFC_DECRYPT } public Date mSignatureTime; @@ -38,13 +39,22 @@ public class RequiredInputParcel implements Parcelable { public RequiredInputParcel(Parcel source) { mType = RequiredInputType.values()[source.readInt()]; - if (source.readInt() != 0) { + // 0 = none, 1 = both, 2 = only hashes (decrypt) + int hashTypes = source.readInt(); + if (hashTypes != 0) { int count = source.readInt(); mInputHashes = new byte[count][]; - mSignAlgos = new int[count]; - for (int i = 0; i < count; i++) { - mInputHashes[i] = source.createByteArray(); - mSignAlgos[i] = source.readInt(); + if (hashTypes == 1) { + mSignAlgos = new int[count]; + for (int i = 0; i < count; i++) { + mInputHashes[i] = source.createByteArray(); + mSignAlgos[i] = source.readInt(); + } + } else { + mSignAlgos = null; + for (int i = 0; i < count; i++) { + mInputHashes[i] = source.createByteArray(); + } } } else { mInputHashes = null; @@ -72,17 +82,28 @@ public class RequiredInputParcel implements Parcelable { signatureTime, null, null); } - public static RequiredInputParcel createNfcDecryptOperation(byte[] inputHash) { + public static RequiredInputParcel createNfcDecryptOperation(byte[] inputHash, long subKeyId) { return new RequiredInputParcel(RequiredInputType.NFC_DECRYPT, - new byte[][] { inputHash }, null, null, null, null); + new byte[][] { inputHash }, null, null, null, subKeyId); } - public static RequiredInputParcel createRequiredPassphrase( + public static RequiredInputParcel createRequiredSignPassphrase( long masterKeyId, long subKeyId, Date signatureTime) { return new RequiredInputParcel(RequiredInputType.PASSPHRASE, null, null, signatureTime, masterKeyId, subKeyId); } + public static RequiredInputParcel createRequiredDecryptPassphrase( + long masterKeyId, long subKeyId) { + return new RequiredInputParcel(RequiredInputType.PASSPHRASE, + null, null, null, masterKeyId, subKeyId); + } + + public static RequiredInputParcel createRequiredSymmetricPassphrase() { + return new RequiredInputParcel(RequiredInputType.PASSPHRASE_SYMMETRIC, + null, null, null, null, null); + } + public static RequiredInputParcel createRequiredPassphrase( RequiredInputParcel req) { return new RequiredInputParcel(RequiredInputType.PASSPHRASE, @@ -98,11 +119,13 @@ public class RequiredInputParcel implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mType.ordinal()); if (mInputHashes != null) { - dest.writeInt(1); + dest.writeInt(mSignAlgos != null ? 1 : 2); dest.writeInt(mInputHashes.length); for (int i = 0; i < mInputHashes.length; i++) { dest.writeByteArray(mInputHashes[i]); - dest.writeInt(mSignAlgos[i]); + if (mSignAlgos != null) { + dest.writeInt(mSignAlgos[i]); + } } } else { dest.writeInt(0); 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 f0a7859f7..b136492b4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CryptoOperationFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CryptoOperationFragment.java @@ -49,7 +49,8 @@ public abstract class CryptoOperationFragment extends Fragment { return; } - case PASSPHRASE: { + case PASSPHRASE: + case PASSPHRASE_SYMMETRIC: { Intent intent = new Intent(getActivity(), PassphraseDialogActivity.class); intent.putExtra(PassphraseDialogActivity.EXTRA_REQUIRED_INPUT, requiredInput); startActivityForResult(intent, REQUEST_CODE_PASSPHRASE); 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 cd66902ba..766e65e8b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java @@ -93,9 +93,6 @@ public class DecryptFilesFragment extends DecryptFragment { mDecryptButton = view.findViewById(R.id.decrypt_file_action_decrypt); view.findViewById(R.id.decrypt_file_browse).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { - // reset state - mPassphrase = null; - mNfcDecryptedSessionKey = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { FileHelper.openDocument(DecryptFilesFragment.this, "*/*", REQUEST_CODE_INPUT); } else { @@ -207,8 +204,7 @@ public class DecryptFilesFragment extends DecryptFragment { data.putInt(KeychainIntentService.TARGET, IOType.URI.ordinal()); data.putParcelable(KeychainIntentService.ENCRYPT_DECRYPT_OUTPUT_URI, mOutputUri); -// data.putParcelable(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase); -// data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey); + data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput); intent.putExtra(KeychainIntentService.EXTRA_DATA, data); @@ -235,20 +231,6 @@ public class DecryptFilesFragment extends DecryptFragment { DecryptVerifyResult pgpResult = returnData.getParcelable(DecryptVerifyResult.EXTRA_RESULT); -// if (pgpResult.isPending()) { -// if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) == -// DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) { -// startPassphraseDialog(pgpResult.getKeyIdPassphraseNeeded()); -// } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) == -// DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) { -// startPassphraseDialog(Constants.key.symmetric); -// } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_NFC) == -// DecryptVerifyResult.RESULT_PENDING_NFC) { -// startNfcDecrypt(pgpResult.getNfcSubKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcEncryptedSessionKey()); -// } else { -// throw new RuntimeException("Unhandled pending result!"); -// } - if (pgpResult.success()) { switch (mCurrentCryptoOperation) { @@ -304,22 +286,6 @@ public class DecryptFilesFragment extends DecryptFragment { @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { -// case REQUEST_CODE_PASSPHRASE: { -// if (resultCode == Activity.RESULT_OK && data != null) { -// mPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE); -//// decryptOriginalFilename(); -// } -// return; -// } -// -// case REQUEST_CODE_NFC_DECRYPT: { -// if (resultCode == Activity.RESULT_OK && data != null) { -// mNfcDecryptedSessionKey = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_DECRYPTED_SESSION_KEY); -//// decryptOriginalFilename(); -// } -// return; -// } - case REQUEST_CODE_INPUT: { if (resultCode == Activity.RESULT_OK && data != null) { setInputUri(data.getData()); 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 38ad54ad3..f320a6d84 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java @@ -19,7 +19,6 @@ package org.sufficientlysecure.keychain.ui; import android.content.Intent; import android.os.Bundle; -import android.support.v4.app.Fragment; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; @@ -32,14 +31,10 @@ import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State; -import org.sufficientlysecure.keychain.util.Passphrase; public abstract class DecryptFragment extends CryptoOperationFragment { private static final int RESULT_CODE_LOOKUP_KEY = 0x00007006; -// public static final int REQUEST_CODE_PASSPHRASE = 0x00008001; -// public static final int REQUEST_CODE_NFC_DECRYPT = 0x00008002; - protected long mSignatureKeyId = 0; protected LinearLayout mResultLayout; @@ -56,11 +51,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment { protected TextView mSignatureEmail; protected TextView mSignatureAction; - - // State - protected Passphrase mPassphrase; - protected byte[] mNfcDecryptedSessionKey; - @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java index 086830389..9c6c89c43 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java @@ -17,7 +17,6 @@ package org.sufficientlysecure.keychain.ui; -import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; import android.os.Bundle; @@ -30,7 +29,6 @@ import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; -import org.openintents.openpgp.util.OpenPgpApi; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; @@ -52,10 +50,7 @@ public class DecryptTextFragment extends DecryptFragment { // view private LinearLayout mValidLayout; private LinearLayout mInvalidLayout; - private Button mInvalidButton; private TextView mText; - private View mShareButton; - private View mCopyButton; // model private String mCiphertext; @@ -82,23 +77,26 @@ public class DecryptTextFragment extends DecryptFragment { View view = inflater.inflate(R.layout.decrypt_text_fragment, container, false); mValidLayout = (LinearLayout) view.findViewById(R.id.decrypt_text_valid); mInvalidLayout = (LinearLayout) view.findViewById(R.id.decrypt_text_invalid); - mInvalidButton = (Button) view.findViewById(R.id.decrypt_text_invalid_button); mText = (TextView) view.findViewById(R.id.decrypt_text_plaintext); - mShareButton = view.findViewById(R.id.action_decrypt_share_plaintext); - mCopyButton = view.findViewById(R.id.action_decrypt_copy_plaintext); - mShareButton.setOnClickListener(new View.OnClickListener() { + + View vShareButton = view.findViewById(R.id.action_decrypt_share_plaintext); + vShareButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(sendWithChooserExcludingEncrypt(mText.getText().toString())); } }); - mCopyButton.setOnClickListener(new View.OnClickListener() { + + View vCopyButton = view.findViewById(R.id.action_decrypt_copy_plaintext); + vCopyButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { copyToClipboard(mText.getText().toString()); } }); - mInvalidButton.setOnClickListener(new View.OnClickListener() { + + Button vInvalidButton = (Button) view.findViewById(R.id.decrypt_text_invalid_button); + vInvalidButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mInvalidLayout.setVisibility(View.GONE); @@ -162,8 +160,7 @@ public class DecryptTextFragment extends DecryptFragment { data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput); data.putInt(KeychainIntentService.TARGET, IOType.BYTES.ordinal()); data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, mCiphertext.getBytes()); -// data.putParcelable(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase); -// data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey); + data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput); intent.putExtra(KeychainIntentService.EXTRA_DATA, data); @@ -189,19 +186,6 @@ public class DecryptTextFragment extends DecryptFragment { DecryptVerifyResult pgpResult = returnData.getParcelable(DecryptVerifyResult.EXTRA_RESULT); -// if (pgpResult.isPending()) { -// if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) == -// DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) { -// startPassphraseDialog(pgpResult.getKeyIdPassphraseNeeded()); -// } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) == -// DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) { -// startPassphraseDialog(Constants.key.symmetric); -// } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_NFC) == -// DecryptVerifyResult.RESULT_PENDING_NFC) { -// startNfcDecrypt(pgpResult.getNfcSubKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcEncryptedSessionKey()); -// } else { -// throw new RuntimeException("Unhandled pending result!"); -// } if (pgpResult.success()) { byte[] decryptedMessage = returnData @@ -250,34 +234,4 @@ public class DecryptTextFragment extends DecryptFragment { getActivity().startService(intent); } -// @Override -// public void onActivityResult(int requestCode, int resultCode, Intent data) { -// switch (requestCode) { -// -// case REQUEST_CODE_PASSPHRASE: { -// if (resultCode == Activity.RESULT_OK && data != null) { -// mPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE); -// decryptStart(); -// } else { -// getActivity().finish(); -// } -// return; -// } -// -// case REQUEST_CODE_NFC_DECRYPT: { -// if (resultCode == Activity.RESULT_OK && data != null) { -// mNfcDecryptedSessionKey = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_DECRYPTED_SESSION_KEY); -// decryptStart(); -// } else { -// getActivity().finish(); -// } -// return; -// } -// -// default: { -// super.onActivityResult(requestCode, resultCode, data); -// } -// } -// } - } 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 074e40b22..007608f80 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java @@ -97,10 +97,19 @@ public class PassphraseDialogActivity extends FragmentActivity { keyId = getIntent().getLongExtra(EXTRA_SUBKEY_ID, 0); } else { RequiredInputParcel requiredInput = getIntent().getParcelableExtra(EXTRA_REQUIRED_INPUT); - if (requiredInput.mType != RequiredInputType.PASSPHRASE) { - throw new AssertionError("Wrong required input type for PassphraseDialogActivity!"); + switch (requiredInput.mType) { + case PASSPHRASE_SYMMETRIC: { + keyId = Constants.key.symmetric; + break; + } + case PASSPHRASE: { + keyId = requiredInput.getSubKeyId(); + break; + } + default: { + throw new AssertionError("Unsupported required input type for PassphraseDialogActivity!"); + } } - keyId = requiredInput.getSubKeyId(); } Intent serviceIntent = getIntent().getParcelableExtra(EXTRA_SERVICE_INTENT); -- cgit v1.2.3