mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-27 11:12:15 -05:00
Fixes
This commit is contained in:
parent
3cce00d61e
commit
f2a6064e38
@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
import org.spongycastle.bcpg.ArmoredOutputStream;
|
||||
import org.spongycastle.bcpg.BCPGOutputStream;
|
||||
import org.spongycastle.bcpg.S2K;
|
||||
import org.spongycastle.openpgp.PGPCompressedDataGenerator;
|
||||
import org.spongycastle.openpgp.PGPEncryptedDataGenerator;
|
||||
import org.spongycastle.openpgp.PGPException;
|
||||
@ -38,11 +39,13 @@ import org.sufficientlysecure.keychain.util.InputData;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.SignatureException;
|
||||
@ -70,6 +73,7 @@ public class PgpSignEncrypt {
|
||||
private String mSignaturePassphrase;
|
||||
private boolean mEncryptToSigner;
|
||||
private boolean mCleartextInput;
|
||||
private String mNfcData;
|
||||
|
||||
private static byte[] NEW_LINE;
|
||||
|
||||
@ -100,6 +104,7 @@ public class PgpSignEncrypt {
|
||||
this.mSignaturePassphrase = builder.mSignaturePassphrase;
|
||||
this.mEncryptToSigner = builder.mEncryptToSigner;
|
||||
this.mCleartextInput = builder.mCleartextInput;
|
||||
this.mNfcData = builder.mNfcData;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
@ -122,6 +127,7 @@ public class PgpSignEncrypt {
|
||||
private String mSignaturePassphrase = null;
|
||||
private boolean mEncryptToSigner = false;
|
||||
private boolean mCleartextInput = false;
|
||||
private String mNfcData = null;
|
||||
|
||||
public Builder(ProviderHelper providerHelper, String versionHeader, InputData data, OutputStream outStream) {
|
||||
this.mProviderHelper = providerHelper;
|
||||
@ -130,7 +136,7 @@ public class PgpSignEncrypt {
|
||||
this.mOutStream = outStream;
|
||||
}
|
||||
|
||||
public Builder setProgressable(Progressable progressable) {
|
||||
public Builder setProgressable(Progressable progressable) {
|
||||
mProgressable = progressable;
|
||||
return this;
|
||||
}
|
||||
@ -170,6 +176,12 @@ public class PgpSignEncrypt {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate old V3 signatures
|
||||
*
|
||||
* @param signatureForceV3
|
||||
* @return
|
||||
*/
|
||||
public Builder setSignatureForceV3(boolean signatureForceV3) {
|
||||
mSignatureForceV3 = signatureForceV3;
|
||||
return this;
|
||||
@ -200,6 +212,11 @@ public class PgpSignEncrypt {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setNfcData(String nfcData) {
|
||||
mNfcData = nfcData;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PgpSignEncrypt build() {
|
||||
return new PgpSignEncrypt(this);
|
||||
}
|
||||
@ -232,12 +249,26 @@ public class PgpSignEncrypt {
|
||||
}
|
||||
}
|
||||
|
||||
public static class NeedNfcDataException extends Exception {
|
||||
public String mData;
|
||||
|
||||
public NeedNfcDataException(String data) {
|
||||
mData = data;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove later
|
||||
static String convertStreamToString(java.io.InputStream is) {
|
||||
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
|
||||
return s.hasNext() ? s.next() : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs and/or encrypts data based on parameters of class
|
||||
*/
|
||||
public void execute()
|
||||
throws IOException, PGPException, NoSuchProviderException,
|
||||
NoSuchAlgorithmException, SignatureException, KeyExtractionException, NoSigningKeyException, NoPassphraseException {
|
||||
NoSuchAlgorithmException, SignatureException, KeyExtractionException, NoSigningKeyException, NoPassphraseException, NeedNfcDataException {
|
||||
|
||||
boolean enableSignature = mSignatureMasterKeyId != Constants.key.none;
|
||||
boolean enableEncryption = ((mEncryptionMasterKeyIds != null && mEncryptionMasterKeyIds.length > 0)
|
||||
@ -255,16 +286,6 @@ public class PgpSignEncrypt {
|
||||
mEncryptionMasterKeyIds[mEncryptionMasterKeyIds.length - 1] = mSignatureMasterKeyId;
|
||||
}
|
||||
|
||||
ArmoredOutputStream armorOut = null;
|
||||
OutputStream out;
|
||||
if (mEnableAsciiArmorOutput) {
|
||||
armorOut = new ArmoredOutputStream(mOutStream);
|
||||
armorOut.setHeader("Version", mVersionHeader);
|
||||
out = armorOut;
|
||||
} else {
|
||||
out = mOutStream;
|
||||
}
|
||||
|
||||
/* Get keys for signature generation for later usage */
|
||||
WrappedSecretKey signingKey = null;
|
||||
if (enableSignature) {
|
||||
@ -276,7 +297,7 @@ public class PgpSignEncrypt {
|
||||
}
|
||||
try {
|
||||
signingKey = signingKeyRing.getSigningSubKey();
|
||||
} catch(PgpGeneralException e) {
|
||||
} catch (PgpGeneralException e) {
|
||||
throw new NoSigningKeyException();
|
||||
}
|
||||
|
||||
@ -329,17 +350,24 @@ public class PgpSignEncrypt {
|
||||
}
|
||||
}
|
||||
|
||||
// HACK
|
||||
boolean useNfc = false;
|
||||
if (signingKey.getSecretKey().getS2K().getType() == S2K.GNU_DUMMY_S2K
|
||||
&& signingKey.getSecretKey().getS2K().getProtectionMode() == 2) {
|
||||
useNfc = true;
|
||||
}
|
||||
|
||||
/* Initialize signature generator object for later usage */
|
||||
PGPSignatureGenerator signatureGenerator = null;
|
||||
PGPV3SignatureGenerator signatureV3Generator = null;
|
||||
if (enableSignature) {
|
||||
if (enableSignature && !useNfc) {
|
||||
updateProgress(R.string.progress_preparing_signature, 10, 100);
|
||||
|
||||
try {
|
||||
boolean cleartext = mCleartextInput && mEnableAsciiArmorOutput && !enableEncryption;
|
||||
if (mSignatureForceV3) {
|
||||
signatureV3Generator = signingKey.getV3SignatureGenerator(
|
||||
mSignatureHashAlgorithm,cleartext);
|
||||
mSignatureHashAlgorithm, cleartext);
|
||||
} else {
|
||||
signatureGenerator = signingKey.getSignatureGenerator(
|
||||
mSignatureHashAlgorithm, cleartext);
|
||||
@ -349,12 +377,39 @@ public class PgpSignEncrypt {
|
||||
throw new KeyExtractionException();
|
||||
}
|
||||
}
|
||||
// else if (enableSignature && useNfc) {
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
ArmoredOutputStream armorOut = null;
|
||||
OutputStream out = null;
|
||||
if (mEnableAsciiArmorOutput && !useNfc) {
|
||||
armorOut = new ArmoredOutputStream(mOutStream);
|
||||
armorOut.setHeader("Version", mVersionHeader);
|
||||
out = armorOut;
|
||||
} else {
|
||||
out = mOutStream;
|
||||
}
|
||||
|
||||
PGPCompressedDataGenerator compressGen = null;
|
||||
OutputStream pOut;
|
||||
OutputStream pOut = null;
|
||||
OutputStream encryptionOut = null;
|
||||
BCPGOutputStream bcpgOut;
|
||||
if (enableEncryption) {
|
||||
|
||||
// Barrier function!
|
||||
if (useNfc && mNfcData == null) {
|
||||
Log.d(Constants.TAG, "mNfcData is null");
|
||||
String nfcData = convertStreamToString(mData.getInputStream());
|
||||
Log.d(Constants.TAG, "nfcData: " + nfcData);
|
||||
throw new NeedNfcDataException(nfcData);
|
||||
}
|
||||
|
||||
if (useNfc) {
|
||||
Log.d(Constants.TAG, "mNfcData: " + mNfcData);
|
||||
out.write(mNfcData.getBytes());
|
||||
out.flush();
|
||||
} else if (enableEncryption) {
|
||||
/* actual encryption */
|
||||
|
||||
encryptionOut = cPk.open(out, new byte[1 << 16]);
|
||||
@ -488,7 +543,7 @@ public class PgpSignEncrypt {
|
||||
Log.e(Constants.TAG, "not supported!");
|
||||
}
|
||||
|
||||
if (enableSignature) {
|
||||
if (enableSignature && !useNfc) {
|
||||
updateProgress(R.string.progress_generating_signature, 95, 100);
|
||||
if (mSignatureForceV3) {
|
||||
signatureV3Generator.generate().encode(pOut);
|
||||
@ -507,7 +562,7 @@ public class PgpSignEncrypt {
|
||||
|
||||
encryptionOut.close();
|
||||
}
|
||||
if (mEnableAsciiArmorOutput) {
|
||||
if (mEnableAsciiArmorOutput && !useNfc) {
|
||||
armorOut.close();
|
||||
}
|
||||
|
||||
|
@ -179,6 +179,8 @@ public class UncachedKeyRing {
|
||||
// Set to 1, except if the encryption type is GNU_DUMMY_S2K
|
||||
if(s2k == null || s2k.getType() != S2K.GNU_DUMMY_S2K) {
|
||||
result.add(sub.getKeyID());
|
||||
} else {
|
||||
Log.d(Constants.TAG, "S2K GNU extension!, mode: " + s2k.getProtectionMode());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -197,4 +197,9 @@ public class WrappedSecretKey extends WrappedPublicKey {
|
||||
return new UncachedSecretKey(mSecretKey);
|
||||
}
|
||||
|
||||
// HACK
|
||||
public PGPSecretKey getSecretKey() {
|
||||
return mSecretKey;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import org.openintents.openpgp.IOpenPgpService;
|
||||
import org.openintents.openpgp.OpenPgpError;
|
||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||
import org.openintents.openpgp.util.OpenPgpApi;
|
||||
import org.openkeychain.nfc.NfcActivity;
|
||||
import org.spongycastle.util.Arrays;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
@ -135,7 +136,26 @@ public class OpenPgpService extends RemoteService {
|
||||
return result;
|
||||
}
|
||||
|
||||
private Intent getPassphraseBundleIntent(Intent data, long keyId) {
|
||||
private Intent getNfcIntent(Intent data, String in) {
|
||||
// build PendingIntent for Yubikey NFC operations
|
||||
Intent intent = new Intent(getBaseContext(), NfcActivity.class);
|
||||
intent.setAction(NfcActivity.ACTION_SIGN);
|
||||
intent.putExtra(NfcActivity.EXTRA_NFC_DATA, in);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
// pass params through to activity that it can be returned again later to repeat pgp operation
|
||||
intent.putExtra(NfcActivity.EXTRA_DATA, data);
|
||||
PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0,
|
||||
intent,
|
||||
PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
|
||||
// return PendingIntent to be executed by client
|
||||
Intent result = new Intent();
|
||||
result.putExtra(OpenPgpApi.RESULT_INTENT, pi);
|
||||
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED);
|
||||
return result;
|
||||
}
|
||||
|
||||
private Intent getPassphraseIntent(Intent data, long keyId) {
|
||||
// build PendingIntent for passphrase input
|
||||
Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
|
||||
intent.setAction(RemoteServiceActivity.ACTION_CACHE_PASSPHRASE);
|
||||
@ -167,10 +187,12 @@ public class OpenPgpService extends RemoteService {
|
||||
}
|
||||
if (passphrase == null) {
|
||||
// get PendingIntent for passphrase input, add it to given params and return to client
|
||||
Intent passphraseBundle = getPassphraseBundleIntent(data, accSettings.getKeyId());
|
||||
Intent passphraseBundle = getPassphraseIntent(data, accSettings.getKeyId());
|
||||
return passphraseBundle;
|
||||
}
|
||||
|
||||
String nfcData = data.getStringExtra(OpenPgpApi.EXTRA_NFC_DATA);
|
||||
|
||||
// Get Input- and OutputStream from ParcelFileDescriptor
|
||||
InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(input);
|
||||
OutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(output);
|
||||
@ -187,7 +209,8 @@ public class OpenPgpService extends RemoteService {
|
||||
.setSignatureHashAlgorithm(accSettings.getHashAlgorithm())
|
||||
.setSignatureForceV3(false)
|
||||
.setSignatureMasterKeyId(accSettings.getKeyId())
|
||||
.setSignaturePassphrase(passphrase);
|
||||
.setSignaturePassphrase(passphrase)
|
||||
.setNfcData(nfcData);
|
||||
|
||||
// TODO: currently always assume cleartext input, no sign-only of binary currently!
|
||||
builder.setCleartextInput(true);
|
||||
@ -202,6 +225,10 @@ public class OpenPgpService extends RemoteService {
|
||||
throw new Exception(getString(R.string.error_no_signature_passphrase));
|
||||
} catch (PgpSignEncrypt.NoSigningKeyException e) {
|
||||
throw new Exception(getString(R.string.error_no_signature_key));
|
||||
} catch (PgpSignEncrypt.NeedNfcDataException e) {
|
||||
// return PendingIntent to execute NFC activity
|
||||
Intent nfcIntent = getNfcIntent(data, e.mData);
|
||||
return nfcIntent;
|
||||
}
|
||||
} finally {
|
||||
is.close();
|
||||
@ -212,6 +239,7 @@ public class OpenPgpService extends RemoteService {
|
||||
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
Log.d(Constants.TAG, "signImpl", e);
|
||||
Intent result = new Intent();
|
||||
result.putExtra(OpenPgpApi.RESULT_ERROR,
|
||||
new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage()));
|
||||
@ -282,7 +310,7 @@ public class OpenPgpService extends RemoteService {
|
||||
}
|
||||
if (passphrase == null) {
|
||||
// get PendingIntent for passphrase input, add it to given params and return to client
|
||||
Intent passphraseBundle = getPassphraseBundleIntent(data, accSettings.getKeyId());
|
||||
Intent passphraseBundle = getPassphraseIntent(data, accSettings.getKeyId());
|
||||
return passphraseBundle;
|
||||
}
|
||||
|
||||
@ -317,6 +345,7 @@ public class OpenPgpService extends RemoteService {
|
||||
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
Log.d(Constants.TAG, "encryptAndSignImpl", e);
|
||||
Intent result = new Intent();
|
||||
result.putExtra(OpenPgpApi.RESULT_ERROR,
|
||||
new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage()));
|
||||
@ -376,7 +405,7 @@ public class OpenPgpService extends RemoteService {
|
||||
if (PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) {
|
||||
// get PendingIntent for passphrase input, add it to given params and return to client
|
||||
Intent passphraseBundle =
|
||||
getPassphraseBundleIntent(data, decryptVerifyResult.getKeyIdPassphraseNeeded());
|
||||
getPassphraseIntent(data, decryptVerifyResult.getKeyIdPassphraseNeeded());
|
||||
return passphraseBundle;
|
||||
} else if (PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED ==
|
||||
decryptVerifyResult.getStatus()) {
|
||||
@ -411,6 +440,7 @@ public class OpenPgpService extends RemoteService {
|
||||
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
Log.d(Constants.TAG, "decryptAndVerifyImpl", e);
|
||||
Intent result = new Intent();
|
||||
result.putExtra(OpenPgpApi.RESULT_ERROR,
|
||||
new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage()));
|
||||
|
@ -17,9 +17,12 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.remote.ui;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.ActionBar;
|
||||
@ -34,6 +37,8 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.remote.AppSettings;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class AppSettingsActivity extends ActionBarActivity {
|
||||
private Uri mAppUri;
|
||||
|
||||
@ -90,6 +95,7 @@ public class AppSettingsActivity extends ActionBarActivity {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
// disabled: breaks Yubikey NFC Foreground dispatching
|
||||
private void startApp() {
|
||||
Intent i;
|
||||
PackageManager manager = getPackageManager();
|
||||
@ -97,6 +103,8 @@ public class AppSettingsActivity extends ActionBarActivity {
|
||||
i = manager.getLaunchIntentForPackage(mAppSettings.getPackageName());
|
||||
if (i == null)
|
||||
throw new PackageManager.NameNotFoundException();
|
||||
// start like the Android launcher would do
|
||||
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
|
||||
i.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
startActivity(i);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
|
@ -38,6 +38,7 @@ import android.os.RemoteException;
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
|
||||
import org.spongycastle.bcpg.S2K;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.Preferences;
|
||||
@ -198,6 +199,13 @@ public class PassphraseCacheService extends Service {
|
||||
return "";
|
||||
}
|
||||
|
||||
// TODO: HACK
|
||||
if (key.getSecretKey().getSecretKey().getS2K().getType() == S2K.GNU_DUMMY_S2K
|
||||
&& key.getSecretKey().getSecretKey().getS2K().getProtectionMode() == 2) {
|
||||
// NFC!
|
||||
return "123456";
|
||||
}
|
||||
|
||||
// get cached passphrase
|
||||
CachedPassphrase cachedPassphrase = mPassphraseCache.get(keyId);
|
||||
if (cachedPassphrase == null) {
|
||||
|
2
extern/openpgp-card-nfc-lib
vendored
2
extern/openpgp-card-nfc-lib
vendored
@ -1 +1 @@
|
||||
Subproject commit 8e588506e0bfb5220f7b57ba42f46a73740c96c7
|
||||
Subproject commit 56b4f0628a957088ec03a0c7c05c8e61c0f71472
|
Loading…
Reference in New Issue
Block a user