diff --git a/OpenPGP-Keychain/AndroidManifest.xml b/OpenPGP-Keychain/AndroidManifest.xml index d7538b3c9..d75350048 100644 --- a/OpenPGP-Keychain/AndroidManifest.xml +++ b/OpenPGP-Keychain/AndroidManifest.xml @@ -406,7 +406,10 @@ android:name=".ui.HelpActivity" android:label="@string/title_help" /> - + + android:label="TODO crypto activity" + android:process=":crypto" > @@ -467,7 +471,8 @@ + android:label="TODO reg" + android:process=":crypto" > diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java index 584aa81ec..a407bc893 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Dominik Schürmann + * Copyright (C) 2013 Dominik Schürmann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,27 +18,16 @@ package org.sufficientlysecure.keychain.crypto_provider; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.SignatureException; - -import org.spongycastle.openpgp.PGPException; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.helper.PgpMain; -import org.sufficientlysecure.keychain.helper.PgpMain.PgpGeneralException; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.service.IKeychainApiService; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.service.handler.IKeychainDecryptHandler; -import org.sufficientlysecure.keychain.service.handler.IKeychainEncryptHandler; -import org.sufficientlysecure.keychain.service.handler.IKeychainGetDecryptionKeyIdHandler; import com.android.crypto.CryptoError; import com.android.crypto.ICryptoCallback; @@ -59,13 +48,13 @@ public class CryptoService extends Service { public void onCreate() { super.onCreate(); mContext = this; - Log.d(Constants.TAG, "KeychainApiService, onCreate()"); + Log.d(Constants.TAG, "CryptoService, onCreate()"); } @Override public void onDestroy() { super.onDestroy(); - Log.d(Constants.TAG, "KeychainApiService, onDestroy()"); + Log.d(Constants.TAG, "CryptoService, onDestroy()"); } @Override @@ -73,50 +62,8 @@ public class CryptoService extends Service { return mBinder; } - private synchronized void encryptAndSignSafe(byte[] inputBytes, String inputUri, - boolean useAsciiArmor, int compression, long[] encryptionKeyIds, - String encryptionPassphrase, int symmetricEncryptionAlgorithm, long signatureKeyId, - int signatureHashAlgorithm, boolean signatureForceV3, String signaturePassphrase, - IKeychainEncryptHandler handler) throws RemoteException { - - try { - - // build InputData and write into OutputStream - InputStream inputStream = new ByteArrayInputStream(inputBytes); - long inputLength = inputBytes.length; - InputData input = new InputData(inputStream, inputLength); - - OutputStream output = new ByteArrayOutputStream(); - - PgpMain.encryptAndSign(mContext, null, input, output, useAsciiArmor, compression, - encryptionKeyIds, encryptionPassphrase, symmetricEncryptionAlgorithm, - signatureKeyId, signatureHashAlgorithm, signatureForceV3, signaturePassphrase); - - output.close(); - - // start activity from service, TOOD: Test! - // Intent dialogIntent = new Intent(getBaseContext(), myActivity.class); - // dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - // getApplication().startActivity(dialogIntent); - - byte[] outputBytes = ((ByteArrayOutputStream) output).toByteArray(); - - // return over handler on client side - handler.onSuccess(outputBytes, null); - } catch (Exception e) { - Log.e(Constants.TAG, "KeychainService, Exception!", e); - - try { - handler.onException(getExceptionId(e), e.getMessage()); - } catch (Exception t) { - Log.e(Constants.TAG, "Error returning exception to client", t); - } - } - } - - private synchronized void decryptAndVerifySafe(byte[] inputBytes, String passphrase, - boolean assumeSymmetric, IKeychainDecryptHandler handler) throws RemoteException { - + private synchronized void decryptAndVerifySafe(byte[] inputBytes, ICryptoCallback callback) + throws RemoteException { try { // build InputData and write into OutputStream InputStream inputStream = new ByteArrayInputStream(inputBytes); @@ -125,8 +72,36 @@ public class CryptoService extends Service { OutputStream outputStream = new ByteArrayOutputStream(); + long secretKeyId = PgpMain.getDecryptionKeyId(mContext, inputStream); + if (secretKeyId == Id.key.none) { + throw new PgpMain.PgpGeneralException(getString(R.string.error_noSecretKeyFound)); + } + + Log.d(Constants.TAG, "secretKeyId " + secretKeyId); + + String passphrase = PassphraseCacheService.getCachedPassphrase(mContext, secretKeyId); + + if (passphrase == null) { + Log.d(Constants.TAG, "No passphrase! Activity required!"); + // No passphrase cached for this ciphertext! Intent required to cache + // passphrase! + Intent intent = new Intent(CryptoActivity.ACTION_CACHE_PASSPHRASE); + intent.putExtra(CryptoActivity.EXTRA_SECRET_KEY_ID, secretKeyId); + callback.onActivityRequired(intent); + return; + } + + // if (signedOnly) { + // resultData = PgpMain.verifyText(this, this, inputData, outStream, + // lookupUnknownKey); + // } else { + // resultData = PgpMain.decryptAndVerify(this, this, inputData, outStream, + // PassphraseCacheService.getCachedPassphrase(this, secretKeyId), + // assumeSymmetricEncryption); + // } + Bundle outputBundle = PgpMain.decryptAndVerify(mContext, null, inputData, outputStream, - passphrase, assumeSymmetric); + passphrase, false); outputStream.close(); @@ -143,52 +118,16 @@ public class CryptoService extends Service { boolean signatureUnknown = outputBundle .getBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN); - // return over handler on client side - handler.onSuccess(outputBytes, null, signature, signatureKeyId, signatureUserId, + CryptoSignatureResult sigResult = new CryptoSignatureResult(signatureUserId, signature, signatureSuccess, signatureUnknown); + + // return over handler on client side + callback.onDecryptVerifySuccess(outputBytes, sigResult); } catch (Exception e) { Log.e(Constants.TAG, "KeychainService, Exception!", e); try { - handler.onException(getExceptionId(e), e.getMessage()); - } catch (Exception t) { - Log.e(Constants.TAG, "Error returning exception to client", t); - } - } - } - - private synchronized void getDecryptionKeySafe(byte[] inputBytes, String inputUri, - IKeychainGetDecryptionKeyIdHandler handler) { - - // TODO: implement inputUri - - try { - InputStream inputStream = new ByteArrayInputStream(inputBytes); - - long secretKeyId = Id.key.none; - boolean symmetric; - - try { - secretKeyId = PgpMain.getDecryptionKeyId(CryptoService.this, inputStream); - if (secretKeyId == Id.key.none) { - throw new PgpGeneralException(getString(R.string.error_noSecretKeyFound)); - } - symmetric = false; - } catch (PgpMain.NoAsymmetricEncryptionException e) { - secretKeyId = Id.key.symmetric; - if (!PgpMain.hasSymmetricEncryption(CryptoService.this, inputStream)) { - throw new PgpGeneralException(getString(R.string.error_noKnownEncryptionFound)); - } - symmetric = true; - } - - handler.onSuccess(secretKeyId, symmetric); - - } catch (Exception e) { - Log.e(Constants.TAG, "KeychainService, Exception!", e); - - try { - handler.onException(getExceptionId(e), e.getMessage()); + callback.onError(new CryptoError(0, e.getMessage())); } catch (Exception t) { Log.e(Constants.TAG, "Error returning exception to client", t); } @@ -221,171 +160,35 @@ public class CryptoService extends Service { @Override public void decryptAndVerify(byte[] inputBytes, ICryptoCallback callback) throws RemoteException { - - try { - // build InputData and write into OutputStream - InputStream inputStream = new ByteArrayInputStream(inputBytes); - long inputLength = inputBytes.length; - InputData inputData = new InputData(inputStream, inputLength); - - OutputStream outputStream = new ByteArrayOutputStream(); - - // String passphrase = ""; - - long secretKeyId = PgpMain.getDecryptionKeyId(mContext, inputStream); - if (secretKeyId == Id.key.none) { - throw new PgpMain.PgpGeneralException( - getString(R.string.error_noSecretKeyFound)); - } - - String passphrase = PassphraseCacheService.getCachedPassphrase(mContext, - secretKeyId); - - if (passphrase == null) { - // No passphrase cached for this ciphertext! Intent required to cache - // passphrase! - Intent intent = new Intent(CryptoActivity.ACTION_CACHE_PASSPHRASE); - intent.putExtra(CryptoActivity.EXTRA_SECRET_KEY_ID, secretKeyId); - callback.onActivityRequired(intent); - return; - } - - // if (signedOnly) { - // resultData = PgpMain.verifyText(this, this, inputData, outStream, - // lookupUnknownKey); - // } else { - // resultData = PgpMain.decryptAndVerify(this, this, inputData, outStream, - // PassphraseCacheService.getCachedPassphrase(this, secretKeyId), - // assumeSymmetricEncryption); - // } - - Bundle outputBundle = PgpMain.decryptAndVerify(mContext, null, inputData, - outputStream, passphrase, false); - - outputStream.close(); - - byte[] outputBytes = ((ByteArrayOutputStream) outputStream).toByteArray(); - - // get signature informations from bundle - boolean signature = outputBundle.getBoolean(KeychainIntentService.RESULT_SIGNATURE); - long signatureKeyId = outputBundle - .getLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID); - String signatureUserId = outputBundle - .getString(KeychainIntentService.RESULT_SIGNATURE_USER_ID); - boolean signatureSuccess = outputBundle - .getBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS); - boolean signatureUnknown = outputBundle - .getBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN); - - CryptoSignatureResult sigResult = new CryptoSignatureResult(signatureUserId, - signature, signatureSuccess, signatureUnknown); - - // return over handler on client side - callback.onDecryptVerifySuccess(outputBytes, sigResult); - // handler.onSuccess(outputBytes, null, signature, signatureKeyId, signatureUserId, - // signatureSuccess, signatureUnknown); - } catch (Exception e) { - Log.e(Constants.TAG, "KeychainService, Exception!", e); - - try { - callback.onError(new CryptoError(getExceptionId(e), e.getMessage())); - } catch (Exception t) { - Log.e(Constants.TAG, "Error returning exception to client", t); - } - } - + decryptAndVerifySafe(inputBytes, callback); } - // - // @Override - // public void encryptAsymmetric(byte[] inputBytes, String inputUri, boolean useAsciiArmor, - // int compression, long[] encryptionKeyIds, int symmetricEncryptionAlgorithm, - // IKeychainEncryptHandler handler) throws RemoteException { - // - // encryptAndSignSafe(inputBytes, inputUri, useAsciiArmor, compression, encryptionKeyIds, - // null, symmetricEncryptionAlgorithm, Id.key.none, 0, false, null, handler); - // } - // - // @Override - // public void encryptSymmetric(byte[] inputBytes, String inputUri, boolean useAsciiArmor, - // int compression, String encryptionPassphrase, int symmetricEncryptionAlgorithm, - // IKeychainEncryptHandler handler) throws RemoteException { - // - // encryptAndSignSafe(inputBytes, inputUri, useAsciiArmor, compression, null, - // encryptionPassphrase, symmetricEncryptionAlgorithm, Id.key.none, 0, false, - // null, handler); - // } - // - // @Override - // public void encryptAndSignAsymmetric(byte[] inputBytes, String inputUri, - // boolean useAsciiArmor, int compression, long[] encryptionKeyIds, - // int symmetricEncryptionAlgorithm, long signatureKeyId, int signatureHashAlgorithm, - // boolean signatureForceV3, String signaturePassphrase, - // IKeychainEncryptHandler handler) throws RemoteException { - // - // encryptAndSignSafe(inputBytes, inputUri, useAsciiArmor, compression, encryptionKeyIds, - // null, symmetricEncryptionAlgorithm, signatureKeyId, signatureHashAlgorithm, - // signatureForceV3, signaturePassphrase, handler); - // } - // - // @Override - // public void encryptAndSignSymmetric(byte[] inputBytes, String inputUri, - // boolean useAsciiArmor, int compression, String encryptionPassphrase, - // int symmetricEncryptionAlgorithm, long signatureKeyId, int signatureHashAlgorithm, - // boolean signatureForceV3, String signaturePassphrase, - // IKeychainEncryptHandler handler) throws RemoteException { - // - // encryptAndSignSafe(inputBytes, inputUri, useAsciiArmor, compression, null, - // encryptionPassphrase, symmetricEncryptionAlgorithm, signatureKeyId, - // signatureHashAlgorithm, signatureForceV3, signaturePassphrase, handler); - // } - // - // @Override - // public void decryptAndVerifyAsymmetric(byte[] inputBytes, String inputUri, - // String keyPassphrase, IKeychainDecryptHandler handler) throws RemoteException { - // - // decryptAndVerifySafe(inputBytes, inputUri, keyPassphrase, false, handler); - // } - // - // @Override - // public void decryptAndVerifySymmetric(byte[] inputBytes, String inputUri, - // String encryptionPassphrase, IKeychainDecryptHandler handler) - // throws RemoteException { - // - // decryptAndVerifySafe(inputBytes, inputUri, encryptionPassphrase, true, handler); - // } - // - // @Override - // public void getDecryptionKeyId(byte[] inputBytes, String inputUri, - // IKeychainGetDecryptionKeyIdHandler handler) throws RemoteException { - // - // getDecryptionKeySafe(inputBytes, inputUri, handler); - // } }; - /** - * As we can not throw an exception through Android RPC, we assign identifiers to the exception - * types. - * - * @param e - * @return - */ - private int getExceptionId(Exception e) { - if (e instanceof NoSuchProviderException) { - return 0; - } else if (e instanceof NoSuchAlgorithmException) { - return 1; - } else if (e instanceof SignatureException) { - return 2; - } else if (e instanceof IOException) { - return 3; - } else if (e instanceof PgpGeneralException) { - return 4; - } else if (e instanceof PGPException) { - return 5; - } else { - return -1; - } - } + // /** + // * As we can not throw an exception through Android RPC, we assign identifiers to the + // exception + // * types. + // * + // * @param e + // * @return + // */ + // private int getExceptionId(Exception e) { + // if (e instanceof NoSuchProviderException) { + // return 0; + // } else if (e instanceof NoSuchAlgorithmException) { + // return 1; + // } else if (e instanceof SignatureException) { + // return 2; + // } else if (e instanceof IOException) { + // return 3; + // } else if (e instanceof PgpGeneralException) { + // return 4; + // } else if (e instanceof PGPException) { + // return 5; + // } else { + // return -1; + // } + // } } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 1d48278eb..711cdae24 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -56,7 +56,6 @@ import android.os.Message; import android.os.Messenger; import android.os.RemoteException; - /** * This Service contains all important long lasting operations for APG. It receives Intents with * data from the activities or other apps, queues these intents, executes them, and stops itself @@ -541,11 +540,12 @@ public class KeychainIntentService extends IntentService implements ProgressDial /* Operation */ if (!canSign) { - PgpMain.changeSecretKeyPassphrase(this, ProviderHelper.getPGPSecretKeyRingByKeyId(this, masterKeyId), - oldPassPhrase, newPassPhrase, this); + PgpMain.changeSecretKeyPassphrase(this, + ProviderHelper.getPGPSecretKeyRingByKeyId(this, masterKeyId), + oldPassPhrase, newPassPhrase, this); } else { - PgpMain.buildSecretKey(this, userIds, keys, keysUsages, masterKeyId, oldPassPhrase, - newPassPhrase, this); + PgpMain.buildSecretKey(this, userIds, keys, keysUsages, masterKeyId, + oldPassPhrase, newPassPhrase, this); } PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassPhrase); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java index f29514e79..d11b8e92a 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Dominik Schürmann + * Copyright (C) 2012-2013 Dominik Schürmann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,27 +39,39 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Binder; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; import android.os.IBinder; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; import android.util.Log; public class PassphraseCacheService extends Service { public static final String TAG = Constants.TAG + ": PassphraseCacheService"; + public static final String ACTION_PASSPHRASE_CACHE_ADD = Constants.INTENT_PREFIX + + "PASSPHRASE_CACHE_ADD"; + public static final String ACTION_PASSPHRASE_CACHE_GET = Constants.INTENT_PREFIX + + "PASSPHRASE_CACHE_GET"; + public static final String BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE = Constants.INTENT_PREFIX - + "PASSPHRASE_CACHE_SERVICE"; + + "PASSPHRASE_CACHE_BROADCAST"; public static final String EXTRA_TTL = "ttl"; public static final String EXTRA_KEY_ID = "keyId"; public static final String EXTRA_PASSPHRASE = "passphrase"; + public static final String EXTRA_MESSENGER = "messenger"; private static final int REQUEST_ID = 0; private static final long DEFAULT_TTL = 15; private BroadcastReceiver mIntentReceiver; - // This is static to be easily retrieved by getCachedPassphrase() without the need of callback - // functions - private static HashMap mPassphraseCache = new HashMap(); + private HashMap mPassphraseCache = new HashMap(); + + Context mContext; /** * This caches a new passphrase by sending a new command to the service. An android service is @@ -74,6 +86,7 @@ public class PassphraseCacheService extends Service { Log.d(TAG, "cacheNewPassphrase() for " + keyId); Intent intent = new Intent(context, PassphraseCacheService.class); + intent.setAction(ACTION_PASSPHRASE_CACHE_ADD); intent.putExtra(EXTRA_TTL, Preferences.getPreferences(context).getPassPhraseCacheTtl()); intent.putExtra(EXTRA_PASSPHRASE, passphrase); intent.putExtra(EXTRA_KEY_ID, keyId); @@ -82,17 +95,65 @@ public class PassphraseCacheService extends Service { } /** - * Gets a cached passphrase from memory + * Gets a cached passphrase from memory, blocking method * * @param context * @param keyId * @return */ public static String getCachedPassphrase(Context context, long keyId) { + Log.d(TAG, "getCachedPassphrase() get masterKeyId for " + keyId); + Intent intent = new Intent(context, PassphraseCacheService.class); + intent.setAction(ACTION_PASSPHRASE_CACHE_GET); + + final Object mutex = new Object(); + final Bundle returnBundle = new Bundle(); + + HandlerThread handlerThread = new HandlerThread("getPassphrase"); + handlerThread.start(); + Handler returnHandler = new Handler(handlerThread.getLooper()) { + @Override + public void handleMessage(Message message) { + if (message.obj != null) { + String passphrase = ((Bundle) message.obj).getString(EXTRA_PASSPHRASE); + returnBundle.putString(EXTRA_PASSPHRASE, passphrase); + } + synchronized (mutex) { + mutex.notify(); + } + getLooper().quit(); + } + }; + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(returnHandler); + intent.putExtra(EXTRA_KEY_ID, keyId); + intent.putExtra(EXTRA_MESSENGER, messenger); + // send intent to this service + context.startService(intent); + + // Wait on mutex until passphrase is returned to handlerThread + synchronized (mutex) { + try { + mutex.wait(3000); + } catch (InterruptedException e) { + } + } + + if (returnBundle.containsKey(EXTRA_PASSPHRASE)) { + return returnBundle.getString(EXTRA_PASSPHRASE); + } else { + return null; + } + } + + private String getCachedPassphraseImpl(long keyId) { + Log.d(TAG, "getCachedPassphraseImpl() get masterKeyId for " + keyId); + // try to get master key id which is used as an identifier for cached passphrases long masterKeyId = keyId; if (masterKeyId != Id.key.symmetric) { - PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(context, keyId); + PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(this, keyId); if (keyRing == null) { return null; } @@ -102,22 +163,24 @@ public class PassphraseCacheService extends Service { } masterKeyId = masterKey.getKeyID(); } + Log.d(TAG, "getCachedPassphraseImpl() for masterKeyId" + masterKeyId); // get cached passphrase String cachedPassphrase = mPassphraseCache.get(masterKeyId); if (cachedPassphrase == null) { + // TODO: fix! // check if secret key has a passphrase - if (!hasPassphrase(context, masterKeyId)) { - // cache empty passphrase - addCachedPassphrase(context, masterKeyId, ""); - return ""; - } else { - return null; - } + // if (!hasPassphrase(context, masterKeyId)) { + // // cache empty passphrase + // addCachedPassphrase(context, masterKeyId, ""); + // return ""; + // } else { + return null; + // } } // set it again to reset the cache life cycle Log.d(TAG, "Cache passphrase again when getting it!"); - addCachedPassphrase(context, masterKeyId, cachedPassphrase); + addCachedPassphrase(this, masterKeyId, cachedPassphrase); return cachedPassphrase; } @@ -196,11 +259,6 @@ public class PassphraseCacheService extends Service { return sender; } - @Override - public void onCreate() { - Log.d(TAG, "onCreate()"); - } - /** * Executed when service is started by intent */ @@ -211,20 +269,41 @@ public class PassphraseCacheService extends Service { // register broadcastreceiver registerReceiver(); - if (intent != null) { - long ttl = intent.getLongExtra(EXTRA_TTL, DEFAULT_TTL); - long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1); - String passphrase = intent.getStringExtra(EXTRA_PASSPHRASE); + if (intent != null && intent.getAction() != null) { + if (ACTION_PASSPHRASE_CACHE_ADD.equals(intent.getAction())) { + long ttl = intent.getLongExtra(EXTRA_TTL, DEFAULT_TTL); + long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1); + String passphrase = intent.getStringExtra(EXTRA_PASSPHRASE); - Log.d(TAG, "Received intent in onStartCommand() with keyId: " + keyId + ", ttl: " + ttl); + Log.d(TAG, + "Received ACTION_PASSPHRASE_CACHE_ADD intent in onStartCommand() with keyId: " + + keyId + ", ttl: " + ttl); - // add keyId and passphrase to memory - mPassphraseCache.put(keyId, passphrase); + // add keyId and passphrase to memory + mPassphraseCache.put(keyId, passphrase); - // register new alarm with keyId for this passphrase - long triggerTime = new Date().getTime() + (ttl * 1000); - AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE); - am.set(AlarmManager.RTC_WAKEUP, triggerTime, buildIntent(this, keyId)); + // register new alarm with keyId for this passphrase + long triggerTime = new Date().getTime() + (ttl * 1000); + AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE); + am.set(AlarmManager.RTC_WAKEUP, triggerTime, buildIntent(this, keyId)); + } else if (ACTION_PASSPHRASE_CACHE_GET.equals(intent.getAction())) { + long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1); + Messenger messenger = intent.getParcelableExtra(EXTRA_MESSENGER); + + String passphrase = getCachedPassphraseImpl(keyId); + + Message msg = Message.obtain(); + Bundle bundle = new Bundle(); + bundle.putString(EXTRA_PASSPHRASE, passphrase); + msg.obj = bundle; + try { + messenger.send(msg); + } catch (RemoteException e) { + Log.e(Constants.TAG, "Sending message failed", e); + } + } else { + Log.e(Constants.TAG, "Intent or Intent Action not supported!"); + } } return START_STICKY; @@ -240,7 +319,7 @@ public class PassphraseCacheService extends Service { // remove passphrase corresponding to keyId from memory mPassphraseCache.remove(keyId); - Log.d(TAG, "Timeout of " + keyId + ", removed from memory!"); + Log.d(TAG, "Timeout of keyId " + keyId + ", removed from memory!"); // stop whole service if no cached passphrases remaining if (mPassphraseCache.isEmpty()) { @@ -249,13 +328,26 @@ public class PassphraseCacheService extends Service { } } + @Override + public void onCreate() { + super.onCreate(); + mContext = this; + Log.d(Constants.TAG, "PassphraseCacheService, onCreate()"); + } + @Override public void onDestroy() { - Log.d(TAG, "onDestroy()"); + super.onDestroy(); + Log.d(Constants.TAG, "PassphraseCacheService, onDestroy()"); unregisterReceiver(mIntentReceiver); } + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + public class PassphraseCacheBinder extends Binder { public PassphraseCacheService getService() { return PassphraseCacheService.this; @@ -264,9 +356,4 @@ public class PassphraseCacheService extends Service { private final IBinder mBinder = new PassphraseCacheBinder(); - @Override - public IBinder onBind(Intent intent) { - return mBinder; - } - } \ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java index 1e7fe0120..06d59b9a2 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java @@ -199,7 +199,8 @@ public class SignKeyActivity extends SherlockFragmentActivity { // Send all information needed to service to sign key in other thread Intent intent = new Intent(this, KeychainIntentService.class); - intent.putExtra(KeychainIntentService.EXTRA_ACTION, KeychainIntentService.ACTION_SIGN_KEYRING); + intent.putExtra(KeychainIntentService.EXTRA_ACTION, + KeychainIntentService.ACTION_SIGN_KEYRING); // fill values for this action Bundle data = new Bundle(); @@ -210,8 +211,8 @@ public class SignKeyActivity extends SherlockFragmentActivity { intent.putExtra(KeychainIntentService.EXTRA_DATA, data); // Message is received after signing is done in ApgService - KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, R.string.progress_signing, - ProgressDialog.STYLE_SPINNER) { + KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, + R.string.progress_signing, ProgressDialog.STYLE_SPINNER) { public void handleMessage(Message message) { // handle messages by standard ApgHandler first super.handleMessage(message); @@ -250,7 +251,8 @@ public class SignKeyActivity extends SherlockFragmentActivity { // Send all information needed to service to upload key in other thread Intent intent = new Intent(this, KeychainIntentService.class); - intent.putExtra(KeychainIntentService.EXTRA_ACTION, KeychainIntentService.ACTION_UPLOAD_KEYRING); + intent.putExtra(KeychainIntentService.EXTRA_ACTION, + KeychainIntentService.ACTION_UPLOAD_KEYRING); // fill values for this action Bundle data = new Bundle(); @@ -264,8 +266,8 @@ public class SignKeyActivity extends SherlockFragmentActivity { intent.putExtra(KeychainIntentService.EXTRA_DATA, data); // Message is received after uploading is done in ApgService - KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, R.string.progress_exporting, - ProgressDialog.STYLE_HORIZONTAL) { + KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, + R.string.progress_exporting, ProgressDialog.STYLE_HORIZONTAL) { public void handleMessage(Message message) { // handle messages by standard ApgHandler first super.handleMessage(message); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java index 898b05372..6d94889cf 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java @@ -103,11 +103,11 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor } public void setCanEdit(boolean bCanEdit) { - canEdit = bCanEdit; - mPlusButton = (ImageView)findViewById(R.id.plusbutton); - if (!canEdit) { - mPlusButton.setVisibility(View.INVISIBLE); - } + canEdit = bCanEdit; + mPlusButton = (ImageView) findViewById(R.id.plusbutton); + if (!canEdit) { + mPlusButton.setVisibility(View.INVISIBLE); + } } /** {@inheritDoc} */ @@ -141,82 +141,85 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor /** {@inheritDoc} */ public void onClick(View v) { if (canEdit) { - switch (mType) { - case Id.type.user_id: { - UserIdEditor view = (UserIdEditor) mInflater.inflate(R.layout.edit_key_user_id_item, - mEditors, false); - view.setEditorListener(this); - if (mEditors.getChildCount() == 0) { - view.setIsMainUserId(true); - } - mEditors.addView(view); - break; - } - - case Id.type.key: { - AlertDialog.Builder dialog = new AlertDialog.Builder(getContext()); - - View view = mInflater.inflate(R.layout.create_key, null); - dialog.setView(view); - dialog.setTitle(R.string.title_createKey); - - boolean wouldBeMasterKey = (mEditors.getChildCount() == 0); - - final Spinner algorithm = (Spinner) view.findViewById(R.id.create_key_algorithm); - Vector choices = new Vector(); - choices.add(new Choice(Id.choice.algorithm.dsa, getResources().getString(R.string.dsa))); - if (!wouldBeMasterKey) { - choices.add(new Choice(Id.choice.algorithm.elgamal, getResources().getString( - R.string.elgamal))); - } - - choices.add(new Choice(Id.choice.algorithm.rsa, getResources().getString(R.string.rsa))); - - ArrayAdapter adapter = new ArrayAdapter(getContext(), - android.R.layout.simple_spinner_item, choices); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - algorithm.setAdapter(adapter); - // make RSA the default - for (int i = 0; i < choices.size(); ++i) { - if (choices.get(i).getId() == Id.choice.algorithm.rsa) { - algorithm.setSelection(i); - break; + switch (mType) { + case Id.type.user_id: { + UserIdEditor view = (UserIdEditor) mInflater.inflate( + R.layout.edit_key_user_id_item, mEditors, false); + view.setEditorListener(this); + if (mEditors.getChildCount() == 0) { + view.setIsMainUserId(true); } + mEditors.addView(view); + break; } - final EditText keySize = (EditText) view.findViewById(R.id.create_key_size); + case Id.type.key: { + AlertDialog.Builder dialog = new AlertDialog.Builder(getContext()); - dialog.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface di, int id) { - di.dismiss(); - try { - mNewKeySize = Integer.parseInt("" + keySize.getText()); - } catch (NumberFormatException e) { - mNewKeySize = 0; + View view = mInflater.inflate(R.layout.create_key, null); + dialog.setView(view); + dialog.setTitle(R.string.title_createKey); + + boolean wouldBeMasterKey = (mEditors.getChildCount() == 0); + + final Spinner algorithm = (Spinner) view.findViewById(R.id.create_key_algorithm); + Vector choices = new Vector(); + choices.add(new Choice(Id.choice.algorithm.dsa, getResources().getString( + R.string.dsa))); + if (!wouldBeMasterKey) { + choices.add(new Choice(Id.choice.algorithm.elgamal, getResources().getString( + R.string.elgamal))); + } + + choices.add(new Choice(Id.choice.algorithm.rsa, getResources().getString( + R.string.rsa))); + + ArrayAdapter adapter = new ArrayAdapter(getContext(), + android.R.layout.simple_spinner_item, choices); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + algorithm.setAdapter(adapter); + // make RSA the default + for (int i = 0; i < choices.size(); ++i) { + if (choices.get(i).getId() == Id.choice.algorithm.rsa) { + algorithm.setSelection(i); + break; } - - mNewKeyAlgorithmChoice = (Choice) algorithm.getSelectedItem(); - createKey(); } - }); - dialog.setCancelable(true); - dialog.setNegativeButton(android.R.string.cancel, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface di, int id) { - di.dismiss(); - } - }); + final EditText keySize = (EditText) view.findViewById(R.id.create_key_size); - dialog.create().show(); - break; - } + dialog.setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface di, int id) { + di.dismiss(); + try { + mNewKeySize = Integer.parseInt("" + keySize.getText()); + } catch (NumberFormatException e) { + mNewKeySize = 0; + } - default: { - break; - } - } - this.updateEditorsVisible(); + mNewKeyAlgorithmChoice = (Choice) algorithm.getSelectedItem(); + createKey(); + } + }); + + dialog.setCancelable(true); + dialog.setNegativeButton(android.R.string.cancel, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface di, int id) { + di.dismiss(); + } + }); + + dialog.create().show(); + break; + } + + default: { + break; + } + } + this.updateEditorsVisible(); } } @@ -266,7 +269,8 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor // Send all information needed to service to edit key in other thread Intent intent = new Intent(mActivity, KeychainIntentService.class); - intent.putExtra(KeychainIntentService.EXTRA_ACTION, KeychainIntentService.ACTION_GENERATE_KEY); + intent.putExtra(KeychainIntentService.EXTRA_ACTION, + KeychainIntentService.ACTION_GENERATE_KEY); // fill values for this action Bundle data = new Bundle(); @@ -293,7 +297,8 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor ProgressDialog.STYLE_SPINNER); // Message is received after generating is done in ApgService - KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(mActivity, mGeneratingDialog) { + KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(mActivity, + mGeneratingDialog) { public void handleMessage(Message message) { // handle messages by standard ApgHandler first super.handleMessage(message); @@ -302,7 +307,8 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor // get new key from data bundle returned from service Bundle data = message.getData(); PGPSecretKeyRing newKeyRing = (PGPSecretKeyRing) PgpConversionHelper - .BytesToPGPKeyRing(data.getByteArray(KeychainIntentService.RESULT_NEW_KEY)); + .BytesToPGPKeyRing(data + .getByteArray(KeychainIntentService.RESULT_NEW_KEY)); boolean isMasterKey = (mEditors.getChildCount() == 0);