mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-23 17:22:16 -05:00
fix Encrypt* with RequiredInputParcel
This commit is contained in:
parent
d7b79e55fb
commit
39b131c7e5
@ -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<PgpSignEncryptResult> 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);
|
||||
RequiredInputParcel requiredInput = result.getRequiredInputParcel();
|
||||
// Passphrase returns immediately, nfc are aggregated
|
||||
if (requiredInput.mType == RequiredInputType.PASSPHRASE) {
|
||||
return new SignEncryptResult(log, requiredInput, results);
|
||||
}
|
||||
|
||||
if (!result.success()) {
|
||||
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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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<PgpSignEncryptResult> 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<PgpSignEncryptResult> results) {
|
||||
super(log, requiredInput);
|
||||
mResults = results;
|
||||
}
|
||||
|
||||
public SignEncryptResult(int result, OperationLog log, ArrayList<PgpSignEncryptResult> results) {
|
||||
|
@ -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,26 +148,15 @@ 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);
|
||||
|
||||
} catch (ProviderHelper.NotFoundException | PgpGeneralException e) {
|
||||
log.add(LogType.MSG_PSE_ERROR_SIGN_KEY, indent);
|
||||
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
|
||||
}
|
||||
signingKey = signingKeyRing.getSecretKey(input.getSignatureSubKeyId());
|
||||
|
||||
// Make sure we are allowed to sign here!
|
||||
if (!signingKey.canSign()) {
|
||||
@ -173,21 +164,23 @@ public class PgpSignEncryptOperation extends BaseOperation {
|
||||
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
|
||||
}
|
||||
|
||||
// if no passphrase was explicitly set try to get it from the cache service
|
||||
if (signingKey.getSecretKeyType() != SecretKeyType.DIVERT_TO_CARD) {
|
||||
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;
|
||||
return new PgpSignEncryptResult(log, RequiredInputParcel.createRequiredPassphrase(
|
||||
signingKeyRing.getMasterKeyId(), signingKey.getKeyId(),
|
||||
cryptoInput.getSignatureTime()));
|
||||
}
|
||||
}
|
||||
|
||||
updateProgress(R.string.progress_extracting_signature_key, 0, 100);
|
||||
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,54 +160,37 @@ 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);
|
||||
private static PendingIntent getRequiredInputPendingIntent(Context context,
|
||||
Intent data, RequiredInputParcel requiredInput) {
|
||||
|
||||
// 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 PendingIntent getNfcSignPendingIntent(Intent data, long keyId, Passphrase pin, byte[] hashToSign, int hashAlgo) {
|
||||
switch (requiredInput.mType) {
|
||||
case NFC_DECRYPT:
|
||||
case NFC_SIGN: {
|
||||
// build PendingIntent for Yubikey NFC operations
|
||||
Intent intent = new Intent(getBaseContext(), NfcActivity.class);
|
||||
intent.setAction(NfcActivity.ACTION_SIGN_HASH);
|
||||
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(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,
|
||||
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 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);
|
||||
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(NfcActivity.EXTRA_DATA, data);
|
||||
intent.putExtra(NfcActivity.EXTRA_PIN, pin);
|
||||
intent.putExtra(NfcActivity.EXTRA_KEY_ID, subKeyId);
|
||||
|
||||
intent.putExtra(NfcActivity.EXTRA_NFC_ENC_SESSION_KEY, encryptedSessionKey);
|
||||
return PendingIntent.getActivity(getBaseContext(), 0,
|
||||
intent,
|
||||
intent.putExtra(PassphraseDialogActivity.EXTRA_SERVICE_INTENT, data);
|
||||
intent.putExtra(PassphraseDialogActivity.EXTRA_REQUIRED_INPUT, requiredInput);
|
||||
return PendingIntent.getActivity(context, 0, intent,
|
||||
PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
}
|
||||
|
||||
default:
|
||||
throw new AssertionError("Unhandled required input type!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private PendingIntent getKeyserverPendingIntent(Intent data, long masterKeyId) {
|
||||
// If signature is unknown we return an _additional_ PendingIntent
|
||||
// to retrieve the missing key
|
||||
@ -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());
|
||||
|
||||
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,
|
||||
getNfcSignPendingIntent(data, pgpResult.getNfcKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcHash(), pgpResult.getNfcAlgo()));
|
||||
result.putExtra(OpenPgpApi.RESULT_INTENT, pIntent);
|
||||
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!");
|
||||
}
|
||||
|
||||
} 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
|
||||
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,
|
||||
getNfcSignPendingIntent(data, pgpResult.getNfcKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcHash(), pgpResult.getNfcAlgo()));
|
||||
result.putExtra(OpenPgpApi.RESULT_INTENT, pIntent);
|
||||
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!");
|
||||
}
|
||||
} 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<Long> 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) {
|
||||
|
@ -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<Integer> mSignAlgos = new ArrayList<>();
|
||||
ArrayList<byte[]> 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;
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
//
|
||||
|
@ -1,189 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.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();
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -160,6 +160,6 @@ public class EncryptTextActivity extends BaseActivity implements
|
||||
|
||||
@Override
|
||||
public void onPassphraseChanged(Passphrase passphrase) {
|
||||
mEncryptFragment.setPassphrase(passphrase);
|
||||
mEncryptFragment.setSymmetricPassphrase(passphrase);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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()!");
|
||||
|
@ -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
|
||||
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();
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -57,7 +57,7 @@ public class KeyUpdateHelper {
|
||||
Bundle importData = new Bundle();
|
||||
importData.putParcelableArrayList(KeychainIntentService.DOWNLOAD_KEY_LIST,
|
||||
new ArrayList<ImportKeysListEntry>(keys));
|
||||
importIntent.putExtra(KeychainIntentService.EXTRA_DATA, importData);
|
||||
importIntent.putExtra(KeychainIntentService.EXTRA_SERVICE_INTENT, importData);
|
||||
|
||||
importIntent.putExtra(KeychainIntentService.EXTRA_MESSENGER, new Messenger(mHandler));
|
||||
|
||||
|
@ -1048,7 +1048,6 @@
|
||||
<string name="msg_se_error_input_uri_not_found">"Error opening URI for reading!"</string>
|
||||
<string name="msg_se_error_output_uri_not_found">"Error opening URI for writing!"</string>
|
||||
<string name="msg_se_error_too_many_inputs">"More inputs than outputs specified! This is probably a programming error, please report!"</string>
|
||||
<string name="msg_se_warn_output_left">"Got outputs left but no inputs. This is probably a programming error, please report!"</string>
|
||||
<string name="msg_se_success">"Sign/encrypt operation successful"</string>
|
||||
|
||||
<!-- Messages for PgpSignEncrypt operation -->
|
||||
|
Loading…
Reference in New Issue
Block a user