diff options
| author | Dominik Schürmann <dominik@dominikschuermann.de> | 2014-07-17 20:29:07 +0200 | 
|---|---|---|
| committer | Dominik Schürmann <dominik@dominikschuermann.de> | 2014-07-17 20:29:07 +0200 | 
| commit | f2a6064e38d46bad34282bcbc961e16c1bf8f533 (patch) | |
| tree | 85fbde65a77ece8b35a4e3f7ba8e4aa4fa870946 /OpenKeychain/src/main/java/org | |
| parent | 3cce00d61edc3c0f517d4b542c7a198fca073fe5 (diff) | |
| download | open-keychain-f2a6064e38d46bad34282bcbc961e16c1bf8f533.tar.gz open-keychain-f2a6064e38d46bad34282bcbc961e16c1bf8f533.tar.bz2 open-keychain-f2a6064e38d46bad34282bcbc961e16c1bf8f533.zip  | |
Fixes
Diffstat (limited to 'OpenKeychain/src/main/java/org')
6 files changed, 132 insertions, 24 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java index 4cb92c368..0750c2a3a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java @@ -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();          } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index 9ddfd3405..1a8607e3f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -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; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKey.java index 98ad2b706..b928fd8cc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKey.java @@ -197,4 +197,9 @@ public class WrappedSecretKey extends WrappedPublicKey {          return new UncachedSecretKey(mSecretKey);      } +    // HACK +    public PGPSecretKey getSecretKey() { +        return mSecretKey; +    } +  } 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 62d6b5ad6..f7ee0eab3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -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())); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java index 8df341f9e..b37405304 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java @@ -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) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java index 13d9b497f..774b9a0df 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -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) {  | 
