From 07704c2726e66b3834834d76c4046b144348b58e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 24 Sep 2014 00:50:58 +0200 Subject: [PATCH] Yubikey decryption --- .../keychain/pgp/PgpDecryptVerify.java | 2 +- .../keychain/remote/OpenPgpService.java | 5 +- .../service/KeychainIntentService.java | 9 +++- .../service/results/DecryptVerifyResult.java | 12 ++--- .../keychain/ui/DecryptFilesFragment.java | 39 +++++--------- .../keychain/ui/DecryptFragment.java | 52 +++---------------- .../keychain/ui/DecryptTextFragment.java | 18 ++++--- .../keychain/ui/EncryptActivity.java | 5 +- 8 files changed, 50 insertions(+), 92 deletions(-) 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 9d21e89b3..c21486306 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -418,7 +418,7 @@ public class PgpDecryptVerify { log.add(LogType.MSG_DC_PENDING_NFC, indent +1); DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_PENDING_NFC, log); - result.setNfcState(e.encryptedSessionKey, mPassphrase); + result.setNfcState(e.encryptedSessionKey, secretEncryptionKey.getKeyId()); return result; } encryptedData = encryptedDataAsymmetric; 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 1b4ad1fc1..090f2ceb6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -526,8 +526,9 @@ public class OpenPgpService extends RemoteService { "Decryption of symmetric content not supported by API!"); } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_NFC) == DecryptVerifyResult.RESULT_PENDING_NFC) { - return getNfcDecryptIntent( - data, pgpResult.getNfcPassphrase(), pgpResult.getNfcEncryptedSessionKey()); + // we assume that the pin has been cached before + String pin = passphraseCacheInterface.getCachedPassphrase(pgpResult.getNfcKeyId()); + return getNfcDecryptIntent(data, pin, pgpResult.getNfcEncryptedSessionKey()); } else { throw new PgpGeneralException( "Encountered unhandled type of pending action not supported by API!"); 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 6d23c36b9..21e3a95a7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -146,6 +146,7 @@ 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"; // save keyring public static final String EDIT_KEYRING_PARCEL = "save_parcel"; @@ -326,6 +327,7 @@ public class KeychainIntentService extends IntentService implements Progressable try { /* Input */ String passphrase = data.getString(DECRYPT_PASSPHRASE); + byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY); InputData inputData = createDecryptInputData(data); OutputStream outStream = createCryptOutputStream(data); @@ -342,7 +344,8 @@ public class KeychainIntentService extends IntentService implements Progressable ); builder.setProgressable(this) .setAllowSymmetricDecryption(true) - .setPassphrase(passphrase); + .setPassphrase(passphrase) + .setNfcState(nfcDecryptedSessionKey); DecryptVerifyResult decryptVerifyResult = builder.build().execute(); @@ -364,6 +367,7 @@ public class KeychainIntentService extends IntentService implements Progressable try { /* Input */ String passphrase = data.getString(DECRYPT_PASSPHRASE); + byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY); InputData inputData = createDecryptInputData(data); @@ -380,7 +384,8 @@ public class KeychainIntentService extends IntentService implements Progressable builder.setProgressable(this) .setAllowSymmetricDecryption(true) .setPassphrase(passphrase) - .setDecryptMetadataOnly(true); + .setDecryptMetadataOnly(true) + .setNfcState(nfcDecryptedSessionKey); DecryptVerifyResult decryptVerifyResult = builder.build().execute(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/DecryptVerifyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/DecryptVerifyResult.java index 4a0aec548..54241e625 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/DecryptVerifyResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/DecryptVerifyResult.java @@ -36,7 +36,7 @@ public class DecryptVerifyResult extends OperationResult { long mKeyIdPassphraseNeeded; byte[] mNfcSessionKey; - String mNfcPassphrase; + long mNfcKeyId; OpenPgpSignatureResult mSignatureResult; OpenPgpMetadata mDecryptMetadata; @@ -49,17 +49,17 @@ public class DecryptVerifyResult extends OperationResult { mKeyIdPassphraseNeeded = keyIdPassphraseNeeded; } - public void setNfcState(byte[] sessionKey, String passphrase) { + public void setNfcState(byte[] sessionKey, long nfcKeyId) { mNfcSessionKey = sessionKey; - mNfcPassphrase = passphrase; + mNfcKeyId = nfcKeyId; } public byte[] getNfcEncryptedSessionKey() { return mNfcSessionKey; } - public String getNfcPassphrase() { - return mNfcPassphrase; + public long getNfcKeyId() { + return mNfcKeyId; } public OpenPgpSignatureResult getSignatureResult() { @@ -92,7 +92,6 @@ public class DecryptVerifyResult extends OperationResult { mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader()); mDecryptMetadata = source.readParcelable(OpenPgpMetadata.class.getClassLoader()); mNfcSessionKey = source.readInt() != 0 ? source.createByteArray() : null; - mNfcPassphrase = source.readString(); } public int describeContents() { @@ -110,7 +109,6 @@ public class DecryptVerifyResult extends OperationResult { } else { dest.writeInt(0); } - dest.writeString(mNfcPassphrase); } public static final Creator CREATOR = new Creator() { 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 dc76be2bf..fb4fa61b2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java @@ -33,6 +33,7 @@ import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.TextView; +import org.openintents.openpgp.util.OpenPgpApi; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.util.FileHelper; @@ -141,7 +142,7 @@ public class DecryptFilesFragment extends DecryptFragment { } // askForOutputFilename(); - decryptOriginalFilename(null); + decryptOriginalFilename(); } private String removeEncryptedAppend(String name) { @@ -169,7 +170,7 @@ public class DecryptFilesFragment extends DecryptFragment { } } - private void decryptOriginalFilename(String passphrase) { + private void decryptOriginalFilename() { Log.d(Constants.TAG, "decryptOriginalFilename"); Intent intent = new Intent(getActivity(), KeychainIntentService.class); @@ -187,7 +188,8 @@ public class DecryptFilesFragment extends DecryptFragment { data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_URI); data.putParcelable(KeychainIntentService.ENCRYPT_OUTPUT_URI, mOutputUri); - data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, passphrase); + data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase); + data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey); intent.putExtra(KeychainIntentService.EXTRA_DATA, data); @@ -214,7 +216,7 @@ public class DecryptFilesFragment extends DecryptFragment { startPassphraseDialog(Constants.key.symmetric); } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_NFC) == DecryptVerifyResult.RESULT_PENDING_NFC) { - // TODO + startNfcDecrypt(mPassphrase, pgpResult.getNfcEncryptedSessionKey()); } else { throw new RuntimeException("Unhandled pending result!"); } @@ -239,23 +241,8 @@ public class DecryptFilesFragment extends DecryptFragment { getActivity().startService(intent); } - protected void showPassphraseDialogForFilename(long keyId) { - PassphraseDialogFragment.show(getActivity(), keyId, - new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { - String passphrase = - message.getData().getString(PassphraseDialogFragment.MESSAGE_DATA_PASSPHRASE); - decryptOriginalFilename(passphrase); - } - } - } - ); - } - @Override - protected void decryptStart(String passphrase) { + protected void decryptStart() { Log.d(Constants.TAG, "decryptStart"); // Send all information needed to service to decrypt in other thread @@ -275,7 +262,8 @@ public class DecryptFilesFragment extends DecryptFragment { data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_URI); data.putParcelable(KeychainIntentService.ENCRYPT_OUTPUT_URI, mOutputUri); - data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, passphrase); + data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase); + data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey); intent.putExtra(KeychainIntentService.EXTRA_DATA, data); @@ -350,15 +338,16 @@ public class DecryptFilesFragment extends DecryptFragment { switch (requestCode) { case REQUEST_CODE_PASSPHRASE: { if (resultCode == Activity.RESULT_OK && data != null) { - String passphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE); - decryptOriginalFilename(passphrase); + mPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE); + decryptOriginalFilename(); } return; } case REQUEST_CODE_NFC: { if (resultCode == Activity.RESULT_OK && data != null) { - // TODO + mNfcDecryptedSessionKey = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_DECRYPTED_SESSION_KEY); + decryptStart(); } return; } @@ -374,7 +363,7 @@ public class DecryptFilesFragment extends DecryptFragment { // This happens after output file was selected, so start our operation if (resultCode == Activity.RESULT_OK && data != null) { mOutputUri = data.getData(); - decryptStart(null); + decryptStart(); } return; } 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 e19110c1f..e566036c2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java @@ -54,6 +54,9 @@ public abstract class DecryptFragment extends Fragment { protected Button mLookupKey; + // State + protected String mPassphrase; + protected byte[] mNfcDecryptedSessionKey; @Override public void onActivityCreated(Bundle savedInstanceState) { @@ -91,42 +94,19 @@ public abstract class DecryptFragment extends Fragment { startActivityForResult(intent, REQUEST_CODE_PASSPHRASE); } - protected void startNfcSign(String pin, byte[] hashToSign, int hashAlgo) { - Intent data = new Intent(); - + protected void startNfcDecrypt(String pin, byte[] encryptedSessionKey) { // build PendingIntent for Yubikey NFC operations Intent intent = new Intent(getActivity(), NfcActivity.class); - intent.setAction(NfcActivity.ACTION_SIGN_HASH); - // pass params through to activity that it can be returned again later to repeat pgp operation - intent.putExtra(NfcActivity.EXTRA_DATA, data); + intent.setAction(NfcActivity.ACTION_DECRYPT_SESSION_KEY); + intent.putExtra(NfcActivity.EXTRA_DATA, new Intent()); // not used, only relevant to OpenPgpService intent.putExtra(NfcActivity.EXTRA_PIN, pin); - intent.putExtra(NfcActivity.EXTRA_NFC_HASH_TO_SIGN, hashToSign); - intent.putExtra(NfcActivity.EXTRA_NFC_HASH_ALGO, hashAlgo); + intent.putExtra(NfcActivity.EXTRA_NFC_ENC_SESSION_KEY, encryptedSessionKey); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivityForResult(intent, REQUEST_CODE_NFC); } -// @Override -// public void onActivityResult(int requestCode, int resultCode, Intent data) { -// switch (requestCode) { -// -// case RESULT_CODE_LOOKUP_KEY: { -// if (resultCode == Activity.RESULT_OK) { -// // TODO: generate new OpenPgpSignatureResult and display it -// } -// return; -// } -// -// default: { -// super.onActivityResult(requestCode, resultCode, data); -// -// break; -// } -// } -// } - protected void onResult(DecryptVerifyResult decryptVerifyResult) { OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult(); @@ -224,26 +204,10 @@ public abstract class DecryptFragment extends Fragment { } } -// protected void showPassphraseDialog(long keyId) { -// PassphraseDialogFragment.show(getActivity(), keyId, -// new Handler() { -// @Override -// public void handleMessage(Message message) { -// if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { -// String passphrase = -// message.getData().getString(PassphraseDialogFragment.MESSAGE_DATA_PASSPHRASE); -// decryptStart(passphrase); -// } -// } -// } -// ); -// } - /** * Should be overridden by MessageFragment and FileFragment to start actual decryption * - * @param passphrase */ - protected abstract void decryptStart(String passphrase); + protected abstract void decryptStart(); } 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 200876f10..f6a08b560 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java @@ -28,9 +28,11 @@ import android.view.View; import android.view.ViewGroup; 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; +import org.sufficientlysecure.keychain.nfc.NfcActivity; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult; @@ -124,12 +126,12 @@ public class DecryptTextFragment extends DecryptFragment { String ciphertext = getArguments().getString(ARG_CIPHERTEXT); if (ciphertext != null) { mCiphertext = ciphertext; - decryptStart(null); + decryptStart(); } } @Override - protected void decryptStart(String passphrase) { + protected void decryptStart() { Log.d(Constants.TAG, "decryptStart"); // Send all information needed to service to decrypt in other thread @@ -143,7 +145,8 @@ public class DecryptTextFragment extends DecryptFragment { // data data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_BYTES); data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, mCiphertext.getBytes()); - data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, passphrase); + data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase); + data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey); intent.putExtra(KeychainIntentService.EXTRA_DATA, data); @@ -170,7 +173,7 @@ public class DecryptTextFragment extends DecryptFragment { startPassphraseDialog(Constants.key.symmetric); } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_NFC) == DecryptVerifyResult.RESULT_PENDING_NFC) { - // TODO + startNfcDecrypt(mPassphrase, pgpResult.getNfcEncryptedSessionKey()); } else { throw new RuntimeException("Unhandled pending result!"); } @@ -209,8 +212,8 @@ public class DecryptTextFragment extends DecryptFragment { case REQUEST_CODE_PASSPHRASE: { if (resultCode == Activity.RESULT_OK && data != null) { - String passphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE); - decryptStart(passphrase); + mPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE); + decryptStart(); } else { getActivity().finish(); } @@ -219,7 +222,8 @@ public class DecryptTextFragment extends DecryptFragment { case REQUEST_CODE_NFC: { if (resultCode == Activity.RESULT_OK && data != null) { - // TODO + mNfcDecryptedSessionKey = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_DECRYPTED_SESSION_KEY); + decryptStart(); } else { getActivity().finish(); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index 0691e7a30..f59ff08bb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -16,13 +16,10 @@ public class EncryptActivity extends DrawerActivity { } protected void startNfcSign(String pin, byte[] hashToSign, int hashAlgo) { - Intent data = new Intent(); - // build PendingIntent for Yubikey NFC operations Intent intent = new Intent(this, NfcActivity.class); intent.setAction(NfcActivity.ACTION_SIGN_HASH); - // pass params through to activity that it can be returned again later to repeat pgp operation - intent.putExtra(NfcActivity.EXTRA_DATA, data); + intent.putExtra(NfcActivity.EXTRA_DATA, new Intent()); // not used, only relevant to OpenPgpService intent.putExtra(NfcActivity.EXTRA_PIN, pin); intent.putExtra(NfcActivity.EXTRA_NFC_HASH_TO_SIGN, hashToSign);