aboutsummaryrefslogtreecommitdiffstats
path: root/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service
diff options
context:
space:
mode:
Diffstat (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service')
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java869
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java110
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java370
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/NoUserIdsException.java10
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/UserInteractionRequiredException.java10
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/WrongPackageSignatureException.java10
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/WrongPassphraseException.java10
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettings.java94
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java109
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java234
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/ExtendedApiService.java122
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/IExtendedApiCallback.aidl24
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/IExtendedApiService.aidl48
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java602
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsAdapter.java76
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListActivity.java36
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListFragment.java103
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteService.java354
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java352
19 files changed, 0 insertions, 3543 deletions
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java
deleted file mode 100644
index ba3169b18..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java
+++ /dev/null
@@ -1,869 +0,0 @@
-/*
- * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.service;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.spongycastle.openpgp.PGPKeyRing;
-import org.spongycastle.openpgp.PGPPublicKeyRing;
-import org.spongycastle.openpgp.PGPSecretKey;
-import org.spongycastle.openpgp.PGPSecretKeyRing;
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.Id;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.helper.FileHelper;
-import org.sufficientlysecure.keychain.helper.OtherHelper;
-import org.sufficientlysecure.keychain.helper.Preferences;
-import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
-import org.sufficientlysecure.keychain.pgp.PgpHelper;
-import org.sufficientlysecure.keychain.pgp.PgpImportExport;
-import org.sufficientlysecure.keychain.pgp.PgpKeyOperation;
-import org.sufficientlysecure.keychain.pgp.PgpOperation;
-import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
-import org.sufficientlysecure.keychain.provider.KeychainContract.DataStream;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
-import org.sufficientlysecure.keychain.util.HkpKeyServer;
-import org.sufficientlysecure.keychain.util.InputData;
-import org.sufficientlysecure.keychain.util.KeyServer.KeyInfo;
-import org.sufficientlysecure.keychain.util.Log;
-import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
-
-import android.app.IntentService;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-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
- * after doing them.
- */
-public class KeychainIntentService extends IntentService implements ProgressDialogUpdater {
-
- /* extras that can be given by intent */
- public static final String EXTRA_MESSENGER = "messenger";
- public static final String EXTRA_DATA = "data";
-
- /* possible actions */
- public static final String ACTION_ENCRYPT_SIGN = Constants.INTENT_PREFIX + "ENCRYPT_SIGN";
-
- public static final String ACTION_DECRYPT_VERIFY = Constants.INTENT_PREFIX + "DECRYPT_VERIFY";
-
- public static final String ACTION_SAVE_KEYRING = Constants.INTENT_PREFIX + "SAVE_KEYRING";
- public static final String ACTION_GENERATE_KEY = Constants.INTENT_PREFIX + "GENERATE_KEY";
- public static final String ACTION_GENERATE_DEFAULT_RSA_KEYS = Constants.INTENT_PREFIX
- + "GENERATE_DEFAULT_RSA_KEYS";
-
- public static final String ACTION_DELETE_FILE_SECURELY = Constants.INTENT_PREFIX
- + "DELETE_FILE_SECURELY";
-
- public static final String ACTION_IMPORT_KEYRING = Constants.INTENT_PREFIX + "IMPORT_KEYRING";
- public static final String ACTION_EXPORT_KEYRING = Constants.INTENT_PREFIX + "EXPORT_KEYRING";
-
- public static final String ACTION_UPLOAD_KEYRING = Constants.INTENT_PREFIX + "UPLOAD_KEYRING";
- public static final String ACTION_QUERY_KEYRING = Constants.INTENT_PREFIX + "QUERY_KEYRING";
-
- public static final String ACTION_SIGN_KEYRING = Constants.INTENT_PREFIX + "SIGN_KEYRING";
-
- /* keys for data bundle */
-
- // encrypt, decrypt, import export
- public static final String TARGET = "target";
- // possible targets:
- public static final int TARGET_BYTES = 1;
- public static final int TARGET_FILE = 2;
- public static final int TARGET_STREAM = 3;
-
- // encrypt
- public static final String ENCRYPT_SECRET_KEY_ID = "secret_key_id";
- public static final String ENCRYPT_USE_ASCII_ARMOR = "use_ascii_armor";
- public static final String ENCRYPT_ENCRYPTION_KEYS_IDS = "encryption_keys_ids";
- public static final String ENCRYPT_COMPRESSION_ID = "compression_id";
- public static final String ENCRYPT_GENERATE_SIGNATURE = "generate_signature";
- public static final String ENCRYPT_SIGN_ONLY = "sign_only";
- public static final String ENCRYPT_MESSAGE_BYTES = "message_bytes";
- public static final String ENCRYPT_INPUT_FILE = "input_file";
- public static final String ENCRYPT_OUTPUT_FILE = "output_file";
- public static final String ENCRYPT_PROVIDER_URI = "provider_uri";
-
- // decrypt/verify
- public static final String DECRYPT_SIGNED_ONLY = "signed_only";
- public static final String DECRYPT_RETURN_BYTES = "return_binary";
- public static final String DECRYPT_CIPHERTEXT_BYTES = "ciphertext_bytes";
- public static final String DECRYPT_ASSUME_SYMMETRIC = "assume_symmetric";
- public static final String DECRYPT_LOOKUP_UNKNOWN_KEY = "lookup_unknownKey";
-
- // save keyring
- public static final String SAVE_KEYRING_NEW_PASSPHRASE = "new_passphrase";
- public static final String SAVE_KEYRING_CURRENT_PASSPHRASE = "current_passphrase";
- public static final String SAVE_KEYRING_USER_IDS = "user_ids";
- public static final String SAVE_KEYRING_KEYS = "keys";
- public static final String SAVE_KEYRING_KEYS_USAGES = "keys_usages";
- public static final String SAVE_KEYRING_MASTER_KEY_ID = "master_key_id";
- public static final String SAVE_KEYRING_CAN_SIGN = "can_sign";
-
- // generate key
- public static final String GENERATE_KEY_ALGORITHM = "algorithm";
- public static final String GENERATE_KEY_KEY_SIZE = "key_size";
- public static final String GENERATE_KEY_SYMMETRIC_PASSPHRASE = "passphrase";
- public static final String GENERATE_KEY_MASTER_KEY = "master_key";
-
- // delete file securely
- public static final String DELETE_FILE = "deleteFile";
-
- // import key
- public static final String IMPORT_INPUT_STREAM = "import_input_stream";
- public static final String IMPORT_FILENAME = "import_filename";
- public static final String IMPORT_BYTES = "import_bytes";
- public static final String IMPORT_KEY_LIST = "import_key_list";
-
- // export key
- public static final String EXPORT_OUTPUT_STREAM = "export_output_stream";
- public static final String EXPORT_FILENAME = "export_filename";
- public static final String EXPORT_KEY_TYPE = "export_key_type";
- public static final String EXPORT_ALL = "export_all";
- public static final String EXPORT_KEY_RING_MASTER_KEY_ID = "export_key_ring_id";
-
- // upload key
- public static final String UPLOAD_KEY_SERVER = "upload_key_server";
- public static final String UPLOAD_KEY_KEYRING_ROW_ID = "upload_key_ring_id";
-
- // query key
- public static final String QUERY_KEY_SERVER = "query_key_server";
- public static final String QUERY_KEY_TYPE = "query_key_type";
- public static final String QUERY_KEY_STRING = "query_key_string";
- public static final String QUERY_KEY_ID = "query_key_id";
-
- // sign key
- public static final String SIGN_KEY_MASTER_KEY_ID = "sign_key_master_key_id";
- public static final String SIGN_KEY_PUB_KEY_ID = "sign_key_pub_key_id";
-
- /*
- * possible data keys as result send over messenger
- */
- // keys
- public static final String RESULT_NEW_KEY = "new_key";
- public static final String RESULT_NEW_KEY2 = "new_key2";
-
- // encrypt
- public static final String RESULT_SIGNATURE_BYTES = "signature_data";
- public static final String RESULT_SIGNATURE_STRING = "signature_text";
- public static final String RESULT_ENCRYPTED_STRING = "encrypted_message";
- public static final String RESULT_ENCRYPTED_BYTES = "encrypted_data";
- public static final String RESULT_URI = "result_uri";
-
- // decrypt/verify
- public static final String RESULT_DECRYPTED_STRING = "decrypted_message";
- public static final String RESULT_DECRYPTED_BYTES = "decrypted_data";
- public static final String RESULT_SIGNATURE = "signature";
- public static final String RESULT_SIGNATURE_KEY_ID = "signature_key_id";
- public static final String RESULT_SIGNATURE_USER_ID = "signature_user_id";
-
- public static final String RESULT_SIGNATURE_SUCCESS = "signature_success";
- public static final String RESULT_SIGNATURE_UNKNOWN = "signature_unknown";
- public static final String RESULT_SIGNATURE_LOOKUP_KEY = "lookup_key";
-
- // import
- public static final String RESULT_IMPORT_ADDED = "added";
- public static final String RESULT_IMPORT_UPDATED = "updated";
- public static final String RESULT_IMPORT_BAD = "bad";
-
- // export
- public static final String RESULT_EXPORT = "exported";
-
- // query
- public static final String RESULT_QUERY_KEY_DATA = "query_key_data";
- public static final String RESULT_QUERY_KEY_SEARCH_RESULT = "query_key_search_result";
-
- Messenger mMessenger;
-
- public KeychainIntentService() {
- super("ApgService");
- }
-
- /**
- * The IntentService calls this method from the default worker thread with the intent that
- * started the service. When this method returns, IntentService stops the service, as
- * appropriate.
- */
- @Override
- protected void onHandleIntent(Intent intent) {
- Bundle extras = intent.getExtras();
- if (extras == null) {
- Log.e(Constants.TAG, "Extras bundle is null!");
- return;
- }
-
- if (!(extras.containsKey(EXTRA_MESSENGER) || extras.containsKey(EXTRA_DATA) || (intent
- .getAction() == null))) {
- Log.e(Constants.TAG,
- "Extra bundle must contain a messenger, a data bundle, and an action!");
- return;
- }
-
- mMessenger = (Messenger) extras.get(EXTRA_MESSENGER);
- Bundle data = extras.getBundle(EXTRA_DATA);
-
- OtherHelper.logDebugBundle(data, "EXTRA_DATA");
-
- String action = intent.getAction();
-
- // execute action from extra bundle
- if (ACTION_ENCRYPT_SIGN.equals(action)) {
- try {
- /* Input */
- int target = data.getInt(TARGET);
-
- long secretKeyId = data.getLong(ENCRYPT_SECRET_KEY_ID);
- String encryptionPassphrase = data.getString(GENERATE_KEY_SYMMETRIC_PASSPHRASE);
-
- boolean useAsciiArmor = data.getBoolean(ENCRYPT_USE_ASCII_ARMOR);
- long encryptionKeyIds[] = data.getLongArray(ENCRYPT_ENCRYPTION_KEYS_IDS);
- int compressionId = data.getInt(ENCRYPT_COMPRESSION_ID);
- boolean generateSignature = data.getBoolean(ENCRYPT_GENERATE_SIGNATURE);
- boolean signOnly = data.getBoolean(ENCRYPT_SIGN_ONLY);
-
- InputStream inStream = null;
- long inLength = -1;
- InputData inputData = null;
- OutputStream outStream = null;
- String streamFilename = null;
- switch (target) {
- case TARGET_BYTES: /* encrypting bytes directly */
- byte[] bytes = data.getByteArray(ENCRYPT_MESSAGE_BYTES);
-
- inStream = new ByteArrayInputStream(bytes);
- inLength = bytes.length;
-
- inputData = new InputData(inStream, inLength);
- outStream = new ByteArrayOutputStream();
-
- break;
- case TARGET_FILE: /* encrypting file */
- String inputFile = data.getString(ENCRYPT_INPUT_FILE);
- String outputFile = data.getString(ENCRYPT_OUTPUT_FILE);
-
- // check if storage is ready
- if (!FileHelper.isStorageMounted(inputFile)
- || !FileHelper.isStorageMounted(outputFile)) {
- throw new PgpGeneralException(
- getString(R.string.error_external_storage_not_ready));
- }
-
- inStream = new FileInputStream(inputFile);
- File file = new File(inputFile);
- inLength = file.length();
- inputData = new InputData(inStream, inLength);
-
- outStream = new FileOutputStream(outputFile);
-
- break;
-
- case TARGET_STREAM: /* Encrypting stream from content uri */
- Uri providerUri = (Uri) data.getParcelable(ENCRYPT_PROVIDER_URI);
-
- // InputStream
- InputStream in = getContentResolver().openInputStream(providerUri);
- inLength = PgpHelper.getLengthOfStream(in);
- inputData = new InputData(in, inLength);
-
- // OutputStream
- try {
- while (true) {
- streamFilename = PgpHelper.generateRandomFilename(32);
- if (streamFilename == null) {
- throw new PgpGeneralException("couldn't generate random file name");
- }
- openFileInput(streamFilename).close();
- }
- } catch (FileNotFoundException e) {
- // found a name that isn't used yet
- }
- outStream = openFileOutput(streamFilename, Context.MODE_PRIVATE);
-
- break;
-
- default:
- throw new PgpGeneralException("No target choosen!");
-
- }
-
- /* Operation */
- PgpOperation operation = new PgpOperation(this, this, inputData, outStream);
- if (generateSignature) {
- Log.d(Constants.TAG, "generating signature...");
- operation.generateSignature(useAsciiArmor, false, secretKeyId,
- PassphraseCacheService.getCachedPassphrase(this, secretKeyId),
- Preferences.getPreferences(this).getDefaultHashAlgorithm(), Preferences
- .getPreferences(this).getForceV3Signatures());
- } else if (signOnly) {
- Log.d(Constants.TAG, "sign only...");
- operation.signText(secretKeyId, PassphraseCacheService.getCachedPassphrase(
- this, secretKeyId), Preferences.getPreferences(this)
- .getDefaultHashAlgorithm(), Preferences.getPreferences(this)
- .getForceV3Signatures());
- } else {
- Log.d(Constants.TAG, "encrypt...");
- operation.signAndEncrypt(useAsciiArmor, compressionId, encryptionKeyIds,
- encryptionPassphrase, Preferences.getPreferences(this)
- .getDefaultEncryptionAlgorithm(), secretKeyId, Preferences
- .getPreferences(this).getDefaultHashAlgorithm(), Preferences
- .getPreferences(this).getForceV3Signatures(),
- PassphraseCacheService.getCachedPassphrase(this, secretKeyId));
- }
-
- outStream.close();
-
- /* Output */
-
- Bundle resultData = new Bundle();
-
- switch (target) {
- case TARGET_BYTES:
- if (useAsciiArmor) {
- String output = new String(
- ((ByteArrayOutputStream) outStream).toByteArray());
- if (generateSignature) {
- resultData.putString(RESULT_SIGNATURE_STRING, output);
- } else {
- resultData.putString(RESULT_ENCRYPTED_STRING, output);
- }
- } else {
- byte output[] = ((ByteArrayOutputStream) outStream).toByteArray();
- if (generateSignature) {
- resultData.putByteArray(RESULT_SIGNATURE_BYTES, output);
- } else {
- resultData.putByteArray(RESULT_ENCRYPTED_BYTES, output);
- }
- }
-
- break;
- case TARGET_FILE:
- // nothing, file was written, just send okay
-
- break;
- case TARGET_STREAM:
- String uri = DataStream.buildDataStreamUri(streamFilename).toString();
- resultData.putString(RESULT_URI, uri);
-
- break;
- }
-
- OtherHelper.logDebugBundle(resultData, "resultData");
-
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
- } catch (Exception e) {
- sendErrorToHandler(e);
- }
- } else if (ACTION_DECRYPT_VERIFY.equals(action)) {
- try {
- /* Input */
- int target = data.getInt(TARGET);
-
- long secretKeyId = data.getLong(ENCRYPT_SECRET_KEY_ID);
- byte[] bytes = data.getByteArray(DECRYPT_CIPHERTEXT_BYTES);
- boolean signedOnly = data.getBoolean(DECRYPT_SIGNED_ONLY);
- boolean returnBytes = data.getBoolean(DECRYPT_RETURN_BYTES);
- boolean assumeSymmetricEncryption = data.getBoolean(DECRYPT_ASSUME_SYMMETRIC);
-
- boolean lookupUnknownKey = data.getBoolean(DECRYPT_LOOKUP_UNKNOWN_KEY);
-
- InputStream inStream = null;
- long inLength = -1;
- InputData inputData = null;
- OutputStream outStream = null;
- String streamFilename = null;
- switch (target) {
- case TARGET_BYTES: /* decrypting bytes directly */
- inStream = new ByteArrayInputStream(bytes);
- inLength = bytes.length;
-
- inputData = new InputData(inStream, inLength);
- outStream = new ByteArrayOutputStream();
-
- break;
-
- case TARGET_FILE: /* decrypting file */
- String inputFile = data.getString(ENCRYPT_INPUT_FILE);
- String outputFile = data.getString(ENCRYPT_OUTPUT_FILE);
-
- // check if storage is ready
- if (!FileHelper.isStorageMounted(inputFile)
- || !FileHelper.isStorageMounted(outputFile)) {
- throw new PgpGeneralException(
- getString(R.string.error_external_storage_not_ready));
- }
-
- // InputStream
- inLength = -1;
- inStream = new FileInputStream(inputFile);
- File file = new File(inputFile);
- inLength = file.length();
- inputData = new InputData(inStream, inLength);
-
- // OutputStream
- outStream = new FileOutputStream(outputFile);
-
- break;
-
- case TARGET_STREAM: /* decrypting stream from content uri */
- Uri providerUri = (Uri) data.getParcelable(ENCRYPT_PROVIDER_URI);
-
- // InputStream
- InputStream in = getContentResolver().openInputStream(providerUri);
- inLength = PgpHelper.getLengthOfStream(in);
- inputData = new InputData(in, inLength);
-
- // OutputStream
- try {
- while (true) {
- streamFilename = PgpHelper.generateRandomFilename(32);
- if (streamFilename == null) {
- throw new PgpGeneralException("couldn't generate random file name");
- }
- openFileInput(streamFilename).close();
- }
- } catch (FileNotFoundException e) {
- // found a name that isn't used yet
- }
- outStream = openFileOutput(streamFilename, Context.MODE_PRIVATE);
-
- break;
-
- default:
- throw new PgpGeneralException("No target choosen!");
-
- }
-
- /* Operation */
-
- Bundle resultData = new Bundle();
-
- // verifyText and decrypt returning additional resultData values for the
- // verification of signatures
- PgpOperation operation = new PgpOperation(this, this, inputData, outStream);
- if (signedOnly) {
- resultData = operation.verifyText(lookupUnknownKey);
- } else {
- resultData = operation.decryptAndVerify(
- PassphraseCacheService.getCachedPassphrase(this, secretKeyId),
- assumeSymmetricEncryption);
- }
-
- outStream.close();
-
- /* Output */
-
- switch (target) {
- case TARGET_BYTES:
- if (returnBytes) {
- byte output[] = ((ByteArrayOutputStream) outStream).toByteArray();
- resultData.putByteArray(RESULT_DECRYPTED_BYTES, output);
- } else {
- String output = new String(
- ((ByteArrayOutputStream) outStream).toByteArray());
- resultData.putString(RESULT_DECRYPTED_STRING, output);
- }
-
- break;
- case TARGET_FILE:
- // nothing, file was written, just send okay and verification bundle
-
- break;
- case TARGET_STREAM:
- String uri = DataStream.buildDataStreamUri(streamFilename).toString();
- resultData.putString(RESULT_URI, uri);
-
- break;
- }
-
- OtherHelper.logDebugBundle(resultData, "resultData");
-
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
- } catch (Exception e) {
- sendErrorToHandler(e);
- }
- } else if (ACTION_SAVE_KEYRING.equals(action)) {
- try {
- /* Input */
- String oldPassPhrase = data.getString(SAVE_KEYRING_CURRENT_PASSPHRASE);
- String newPassPhrase = data.getString(SAVE_KEYRING_NEW_PASSPHRASE);
- boolean canSign = true;
-
- if (data.containsKey(SAVE_KEYRING_CAN_SIGN)) {
- canSign = data.getBoolean(SAVE_KEYRING_CAN_SIGN);
- }
-
- if (newPassPhrase == null) {
- newPassPhrase = oldPassPhrase;
- }
- ArrayList<String> userIds = data.getStringArrayList(SAVE_KEYRING_USER_IDS);
- ArrayList<PGPSecretKey> keys = PgpConversionHelper.BytesToPGPSecretKeyList(data
- .getByteArray(SAVE_KEYRING_KEYS));
- ArrayList<Integer> keysUsages = data.getIntegerArrayList(SAVE_KEYRING_KEYS_USAGES);
- long masterKeyId = data.getLong(SAVE_KEYRING_MASTER_KEY_ID);
-
- PgpKeyOperation keyOperations = new PgpKeyOperation(this, this);
- /* Operation */
- if (!canSign) {
- keyOperations.changeSecretKeyPassphrase(
- ProviderHelper.getPGPSecretKeyRingByKeyId(this, masterKeyId),
- oldPassPhrase, newPassPhrase);
- } else {
- keyOperations.buildSecretKey(userIds, keys, keysUsages, masterKeyId,
- oldPassPhrase, newPassPhrase);
- }
- PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassPhrase);
-
- /* Output */
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY);
- } catch (Exception e) {
- sendErrorToHandler(e);
- }
- } else if (ACTION_GENERATE_KEY.equals(action)) {
- try {
- /* Input */
- int algorithm = data.getInt(GENERATE_KEY_ALGORITHM);
- String passphrase = data.getString(GENERATE_KEY_SYMMETRIC_PASSPHRASE);
- int keysize = data.getInt(GENERATE_KEY_KEY_SIZE);
- PGPSecretKey masterKey = null;
- if (data.containsKey(GENERATE_KEY_MASTER_KEY)) {
- masterKey = PgpConversionHelper.BytesToPGPSecretKey(data
- .getByteArray(GENERATE_KEY_MASTER_KEY));
- }
-
- /* Operation */
- PgpKeyOperation keyOperations = new PgpKeyOperation(this, this);
- PGPSecretKeyRing newKeyRing = keyOperations.createKey(algorithm, keysize,
- passphrase, masterKey);
-
- /* Output */
- Bundle resultData = new Bundle();
- resultData.putByteArray(RESULT_NEW_KEY,
- PgpConversionHelper.PGPSecretKeyRingToBytes(newKeyRing));
-
- OtherHelper.logDebugBundle(resultData, "resultData");
-
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
- } catch (Exception e) {
- sendErrorToHandler(e);
- }
- } else if (ACTION_GENERATE_DEFAULT_RSA_KEYS.equals(action)) {
- // generate one RSA 4096 key for signing and one subkey for encrypting!
- try {
- /* Input */
- String passphrase = data.getString(GENERATE_KEY_SYMMETRIC_PASSPHRASE);
-
- /* Operation */
- PgpKeyOperation keyOperations = new PgpKeyOperation(this, this);
-
- PGPSecretKeyRing masterKeyRing = keyOperations.createKey(Id.choice.algorithm.rsa,
- 4096, passphrase, null);
-
- PGPSecretKeyRing subKeyRing = keyOperations.createKey(Id.choice.algorithm.rsa,
- 4096, passphrase, masterKeyRing.getSecretKey());
-
- /* Output */
- Bundle resultData = new Bundle();
- resultData.putByteArray(RESULT_NEW_KEY,
- PgpConversionHelper.PGPSecretKeyRingToBytes(masterKeyRing));
- resultData.putByteArray(RESULT_NEW_KEY2,
- PgpConversionHelper.PGPSecretKeyRingToBytes(subKeyRing));
-
- OtherHelper.logDebugBundle(resultData, "resultData");
-
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
- } catch (Exception e) {
- sendErrorToHandler(e);
- }
- } else if (ACTION_DELETE_FILE_SECURELY.equals(action)) {
- try {
- /* Input */
- String deleteFile = data.getString(DELETE_FILE);
-
- /* Operation */
- try {
- PgpHelper.deleteFileSecurely(this, this, new File(deleteFile));
- } catch (FileNotFoundException e) {
- throw new PgpGeneralException(
- getString(R.string.error_file_not_found, deleteFile));
- } catch (IOException e) {
- throw new PgpGeneralException(getString(R.string.error_file_delete_failed,
- deleteFile));
- }
-
- /* Output */
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY);
- } catch (Exception e) {
- sendErrorToHandler(e);
- }
- } else if (ACTION_IMPORT_KEYRING.equals(action)) {
- try {
-
- /* Input */
- int target = data.getInt(TARGET);
-
- /* Operation */
- InputStream inStream = null;
- long inLength = -1;
- InputData inputData = null;
- switch (target) {
- case TARGET_BYTES: /* import key from bytes directly */
- byte[] bytes = data.getByteArray(IMPORT_BYTES);
-
- inStream = new ByteArrayInputStream(bytes);
- inLength = bytes.length;
-
- inputData = new InputData(inStream, inLength);
-
- break;
- case TARGET_FILE: /* import key from file */
- String inputFile = data.getString(IMPORT_FILENAME);
-
- inStream = new FileInputStream(inputFile);
- File file = new File(inputFile);
- inLength = file.length();
- inputData = new InputData(inStream, inLength);
-
- break;
-
- case TARGET_STREAM:
- // TODO: not implemented
- break;
- }
-
- Bundle resultData = new Bundle();
-
- ArrayList<Long> keyIds = (ArrayList<Long>) data.getSerializable(IMPORT_KEY_LIST);
-
- PgpImportExport pgpImportExport = new PgpImportExport(this, this);
- resultData = pgpImportExport.importKeyRings(inputData, keyIds);
-
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
- } catch (Exception e) {
- sendErrorToHandler(e);
- }
- } else if (ACTION_EXPORT_KEYRING.equals(action)) {
- try {
-
- /* Input */
- int keyType = Id.type.public_key;
- if (data.containsKey(EXPORT_KEY_TYPE)) {
- keyType = data.getInt(EXPORT_KEY_TYPE);
- }
-
- String outputFile = data.getString(EXPORT_FILENAME);
-
- boolean exportAll = data.getBoolean(EXPORT_ALL);
- long keyRingMasterKeyId = -1;
- if (!exportAll) {
- keyRingMasterKeyId = data.getLong(EXPORT_KEY_RING_MASTER_KEY_ID);
- }
-
- /* Operation */
-
- // check if storage is ready
- if (!FileHelper.isStorageMounted(outputFile)) {
- throw new PgpGeneralException(getString(R.string.error_external_storage_not_ready));
- }
-
- // OutputStream
- FileOutputStream outStream = new FileOutputStream(outputFile);
-
- ArrayList<Long> keyRingMasterKeyIds = new ArrayList<Long>();
- if (exportAll) {
- // get all key ring row ids based on export type
-
- if (keyType == Id.type.public_key) {
- keyRingMasterKeyIds = ProviderHelper.getPublicKeyRingsMasterKeyIds(this);
- } else {
- keyRingMasterKeyIds = ProviderHelper.getSecretKeyRingsMasterKeyIds(this);
- }
- } else {
- keyRingMasterKeyIds.add(keyRingMasterKeyId);
- }
-
- Bundle resultData = new Bundle();
-
- PgpImportExport pgpImportExport = new PgpImportExport(this, this);
- resultData = pgpImportExport
- .exportKeyRings(keyRingMasterKeyIds, keyType, outStream);
-
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
- } catch (Exception e) {
- sendErrorToHandler(e);
- }
- } else if (ACTION_UPLOAD_KEYRING.equals(action)) {
- try {
-
- /* Input */
- int keyRingRowId = data.getInt(UPLOAD_KEY_KEYRING_ROW_ID);
- String keyServer = data.getString(UPLOAD_KEY_SERVER);
-
- /* Operation */
- HkpKeyServer server = new HkpKeyServer(keyServer);
-
- PGPPublicKeyRing keyring = ProviderHelper.getPGPPublicKeyRingByRowId(this,
- keyRingRowId);
- if (keyring != null) {
- PgpImportExport pgpImportExport = new PgpImportExport(this, null);
-
- boolean uploaded = pgpImportExport.uploadKeyRingToServer(server,
- (PGPPublicKeyRing) keyring);
- if (!uploaded) {
- throw new PgpGeneralException("Unable to export key to selected server");
- }
- }
-
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY);
- } catch (Exception e) {
- sendErrorToHandler(e);
- }
- } else if (ACTION_QUERY_KEYRING.equals(action)) {
- try {
-
- /* Input */
- int queryType = data.getInt(QUERY_KEY_TYPE);
- String keyServer = data.getString(QUERY_KEY_SERVER);
-
- String queryString = data.getString(QUERY_KEY_STRING);
- long keyId = data.getLong(QUERY_KEY_ID);
-
- /* Operation */
- Bundle resultData = new Bundle();
-
- HkpKeyServer server = new HkpKeyServer(keyServer);
- if (queryType == Id.keyserver.search) {
- ArrayList<KeyInfo> searchResult = server.search(queryString);
-
- resultData.putParcelableArrayList(RESULT_QUERY_KEY_SEARCH_RESULT, searchResult);
- } else if (queryType == Id.keyserver.get) {
- String keyData = server.get(keyId);
-
- resultData.putString(RESULT_QUERY_KEY_DATA, keyData);
- }
-
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
- } catch (Exception e) {
- sendErrorToHandler(e);
- }
- } else if (ACTION_SIGN_KEYRING.equals(action)) {
- try {
-
- /* Input */
- long masterKeyId = data.getLong(SIGN_KEY_MASTER_KEY_ID);
- long pubKeyId = data.getLong(SIGN_KEY_PUB_KEY_ID);
-
- /* Operation */
- String signaturePassPhrase = PassphraseCacheService.getCachedPassphrase(this,
- masterKeyId);
-
- PgpKeyOperation keyOperation = new PgpKeyOperation(this, this);
- PGPPublicKeyRing signedPubKeyRing = keyOperation.signKey(masterKeyId, pubKeyId,
- signaturePassPhrase);
-
- // store the signed key in our local cache
- PgpImportExport pgpImportExport = new PgpImportExport(this, null);
- int retval = pgpImportExport.storeKeyRingInCache(signedPubKeyRing);
- if (retval != Id.return_value.ok && retval != Id.return_value.updated) {
- throw new PgpGeneralException("Failed to store signed key in local cache");
- }
-
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY);
- } catch (Exception e) {
- sendErrorToHandler(e);
- }
- }
- }
-
- private void sendErrorToHandler(Exception e) {
- Log.e(Constants.TAG, "ApgService Exception: ", e);
- e.printStackTrace();
-
- Bundle data = new Bundle();
- data.putString(KeychainIntentServiceHandler.DATA_ERROR, e.getMessage());
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_EXCEPTION, null, data);
- }
-
- private void sendMessageToHandler(Integer arg1, Integer arg2, Bundle data) {
- Message msg = Message.obtain();
- msg.arg1 = arg1;
- if (arg2 != null) {
- msg.arg2 = arg2;
- }
- if (data != null) {
- msg.setData(data);
- }
-
- try {
- mMessenger.send(msg);
- } catch (RemoteException e) {
- Log.w(Constants.TAG, "Exception sending message, Is handler present?", e);
- } catch (NullPointerException e) {
- Log.w(Constants.TAG, "Messenger is null!", e);
- }
- }
-
- private void sendMessageToHandler(Integer arg1, Bundle data) {
- sendMessageToHandler(arg1, null, data);
- }
-
- private void sendMessageToHandler(Integer arg1) {
- sendMessageToHandler(arg1, null, null);
- }
-
- /**
- * Set progress of ProgressDialog by sending message to handler on UI thread
- */
- public void setProgress(String message, int progress, int max) {
- Log.d(Constants.TAG, "Send message by setProgress with progress=" + progress + ", max="
- + max);
-
- Bundle data = new Bundle();
- if (message != null) {
- data.putString(KeychainIntentServiceHandler.DATA_MESSAGE, message);
- }
- data.putInt(KeychainIntentServiceHandler.DATA_PROGRESS, progress);
- data.putInt(KeychainIntentServiceHandler.DATA_PROGRESS_MAX, max);
-
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_UPDATE_PROGRESS, null, data);
- }
-
- public void setProgress(int resourceId, int progress, int max) {
- setProgress(getString(resourceId), progress, max);
- }
-
- public void setProgress(int progress, int max) {
- setProgress(null, progress, max);
- }
-}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java
deleted file mode 100644
index 170b946d2..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.service;
-
-import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
-import org.sufficientlysecure.keychain.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.support.v4.app.FragmentActivity;
-import android.widget.Toast;
-
-public class KeychainIntentServiceHandler extends Handler {
-
- // possible messages send from this service to handler on ui
- public static final int MESSAGE_OKAY = 1;
- public static final int MESSAGE_EXCEPTION = 2;
- public static final int MESSAGE_UPDATE_PROGRESS = 3;
-
- // possible data keys for messages
- public static final String DATA_ERROR = "error";
- public static final String DATA_PROGRESS = "progress";
- public static final String DATA_PROGRESS_MAX = "max";
- public static final String DATA_MESSAGE = "message";
- public static final String DATA_MESSAGE_ID = "message_id";
-
- Activity mActivity;
- ProgressDialogFragment mProgressDialogFragment;
-
- public KeychainIntentServiceHandler(Activity activity) {
- this.mActivity = activity;
- }
-
- public KeychainIntentServiceHandler(Activity activity, ProgressDialogFragment progressDialogFragment) {
- this.mActivity = activity;
- this.mProgressDialogFragment = progressDialogFragment;
- }
-
- public KeychainIntentServiceHandler(Activity activity, int progressDialogMessageId, int progressDialogStyle) {
- this.mActivity = activity;
- this.mProgressDialogFragment = ProgressDialogFragment.newInstance(progressDialogMessageId,
- progressDialogStyle);
- }
-
- public void showProgressDialog(FragmentActivity activity) {
- mProgressDialogFragment.show(activity.getSupportFragmentManager(), "progressDialog");
- }
-
- @Override
- public void handleMessage(Message message) {
- Bundle data = message.getData();
-
- switch (message.arg1) {
- case MESSAGE_OKAY:
- mProgressDialogFragment.dismiss();
-
- break;
-
- case MESSAGE_EXCEPTION:
- mProgressDialogFragment.dismiss();
-
- // show error from service
- if (data.containsKey(DATA_ERROR)) {
- Toast.makeText(mActivity,
- mActivity.getString(R.string.error_message, data.getString(DATA_ERROR)),
- Toast.LENGTH_SHORT).show();
- }
-
- break;
-
- case MESSAGE_UPDATE_PROGRESS:
- if (data.containsKey(DATA_PROGRESS) && data.containsKey(DATA_PROGRESS_MAX)) {
-
- // update progress from service
- if (data.containsKey(DATA_MESSAGE)) {
- mProgressDialogFragment.setProgress(data.getString(DATA_MESSAGE),
- data.getInt(DATA_PROGRESS), data.getInt(DATA_PROGRESS_MAX));
- } else if (data.containsKey(DATA_MESSAGE_ID)) {
- mProgressDialogFragment.setProgress(data.getInt(DATA_MESSAGE_ID),
- data.getInt(DATA_PROGRESS), data.getInt(DATA_PROGRESS_MAX));
- } else {
- mProgressDialogFragment.setProgress(data.getInt(DATA_PROGRESS),
- data.getInt(DATA_PROGRESS_MAX));
- }
- }
-
- break;
-
- default:
- break;
- }
- }
-}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
deleted file mode 100644
index 08b9c26e6..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.service;
-
-import java.util.Date;
-import java.util.HashMap;
-
-import org.spongycastle.openpgp.PGPException;
-import org.spongycastle.openpgp.PGPPrivateKey;
-import org.spongycastle.openpgp.PGPSecretKey;
-import org.spongycastle.openpgp.PGPSecretKeyRing;
-import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
-import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.Id;
-import org.sufficientlysecure.keychain.helper.Preferences;
-import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.BroadcastReceiver;
-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;
-
-/**
- * This service runs in its own process, but is available to all other processes as the main
- * passphrase cache. Use the static methods addCachedPassphrase and getCachedPassphrase for
- * convenience.
- *
- */
-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_BROADCAST";
-
- public static final String EXTRA_TTL = "ttl";
- public static final String EXTRA_KEY_ID = "key_id";
- 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;
-
- private HashMap<Long, String> mPassphraseCache = new HashMap<Long, String>();
-
- Context mContext;
-
- /**
- * This caches a new passphrase in memory by sending a new command to the service. An android
- * service is only run once. Thus, when the service is already started, new commands just add
- * new events to the alarm manager for new passphrases to let them timeout in the future.
- *
- * @param context
- * @param keyId
- * @param passphrase
- */
- public static void addCachedPassphrase(Context context, long keyId, String passphrase) {
- 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);
-
- context.startService(intent);
- }
-
- /**
- * Gets a cached passphrase from memory by sending an intent to the service. This method is
- * designed to wait until the service returns the passphrase.
- *
- * @param context
- * @param keyId
- * @return passphrase or null (if no passphrase is cached for this keyId)
- */
- 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("getPassphraseThread");
- 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();
- }
- // quit handlerThread
- 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;
- }
- }
-
- /**
- * Internal implementation to get cached passphrase.
- *
- * @param keyId
- * @return
- */
- 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(this, keyId);
- if (keyRing == null) {
- return null;
- }
- PGPSecretKey masterKey = PgpKeyHelper.getMasterKey(keyRing);
- if (masterKey == null) {
- return null;
- }
- masterKeyId = masterKey.getKeyID();
- }
- Log.d(TAG, "getCachedPassphraseImpl() for masterKeyId " + masterKeyId);
-
- // get cached passphrase
- String cachedPassphrase = mPassphraseCache.get(masterKeyId);
- if (cachedPassphrase == null) {
- // if key has no passphrase -> cache and return empty passphrase
- if (!hasPassphrase(this, masterKeyId)) {
- Log.d(Constants.TAG, "Key has no passphrase! Caches and returns empty passphrase!");
-
- addCachedPassphrase(this, masterKeyId, "");
- return "";
- } else {
- return null;
- }
- }
- // set it again to reset the cache life cycle
- Log.d(TAG, "Cache passphrase again when getting it!");
- addCachedPassphrase(this, masterKeyId, cachedPassphrase);
-
- return cachedPassphrase;
- }
-
- /**
- * Checks if key has a passphrase.
- *
- * @param secretKeyId
- * @return true if it has a passphrase
- */
- public static boolean hasPassphrase(Context context, long secretKeyId) {
- // check if the key has no passphrase
- try {
- PGPSecretKey secretKey = PgpKeyHelper.getMasterKey(ProviderHelper
- .getPGPSecretKeyRingByKeyId(context, secretKeyId));
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- "SC").build("".toCharArray());
- PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor);
- if (testKey != null) {
- return false;
- }
- } catch (PGPException e) {
- // silently catch
- }
-
- return true;
- }
-
- /**
- * Register BroadcastReceiver that is unregistered when service is destroyed. This
- * BroadcastReceiver hears on intents with ACTION_PASSPHRASE_CACHE_SERVICE to then timeout
- * specific passphrases in memory.
- */
- private void registerReceiver() {
- if (mIntentReceiver == null) {
- mIntentReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
-
- Log.d(TAG, "Received broadcast...");
-
- if (action.equals(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE)) {
- long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
- timeout(context, keyId);
- }
- }
- };
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE);
- registerReceiver(mIntentReceiver, filter);
- }
- }
-
- /**
- * Build pending intent that is executed by alarm manager to time out a specific passphrase
- *
- * @param context
- * @param keyId
- * @return
- */
- private static PendingIntent buildIntent(Context context, long keyId) {
- Intent intent = new Intent(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE);
- intent.putExtra(EXTRA_KEY_ID, keyId);
- PendingIntent sender = PendingIntent.getBroadcast(context, REQUEST_ID, intent,
- PendingIntent.FLAG_CANCEL_CURRENT);
-
- return sender;
- }
-
- /**
- * Executed when service is started by intent
- */
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- Log.d(TAG, "onStartCommand()");
-
- // register broadcastreceiver
- registerReceiver();
-
- 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 ACTION_PASSPHRASE_CACHE_ADD intent in onStartCommand() with keyId: "
- + keyId + ", ttl: " + ttl);
-
- // add keyId and passphrase to memory
- mPassphraseCache.put(keyId, passphrase);
-
- if (ttl > 0) {
- // 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;
- }
-
- /**
- * Called when one specific passphrase for keyId timed out
- *
- * @param context
- * @param keyId
- */
- private void timeout(Context context, long keyId) {
- // remove passphrase corresponding to keyId from memory
- mPassphraseCache.remove(keyId);
-
- Log.d(TAG, "Timeout of keyId " + keyId + ", removed from memory!");
-
- // stop whole service if no cached passphrases remaining
- if (mPassphraseCache.isEmpty()) {
- Log.d(TAG, "No passphrases remaining in memory, stopping service!");
- stopSelf();
- }
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- mContext = this;
- Log.d(Constants.TAG, "PassphraseCacheService, onCreate()");
- }
-
- @Override
- public void 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;
- }
- }
-
- private final IBinder mBinder = new PassphraseCacheBinder();
-
-}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/NoUserIdsException.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/NoUserIdsException.java
deleted file mode 100644
index 555303238..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/NoUserIdsException.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.sufficientlysecure.keychain.service.exception;
-
-public class NoUserIdsException extends Exception {
-
- private static final long serialVersionUID = 7009311527126696207L;
-
- public NoUserIdsException(String message) {
- super(message);
- }
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/UserInteractionRequiredException.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/UserInteractionRequiredException.java
deleted file mode 100644
index 1152d6796..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/UserInteractionRequiredException.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.sufficientlysecure.keychain.service.exception;
-
-public class UserInteractionRequiredException extends Exception {
-
- private static final long serialVersionUID = -60128148603511936L;
-
- public UserInteractionRequiredException(String message) {
- super(message);
- }
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/WrongPackageSignatureException.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/WrongPackageSignatureException.java
deleted file mode 100644
index cef002265..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/WrongPackageSignatureException.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.sufficientlysecure.keychain.service.exception;
-
-public class WrongPackageSignatureException extends Exception {
-
- private static final long serialVersionUID = -8294642703122196028L;
-
- public WrongPackageSignatureException(String message) {
- super(message);
- }
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/WrongPassphraseException.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/WrongPassphraseException.java
deleted file mode 100644
index 14b774eb5..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/WrongPassphraseException.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.sufficientlysecure.keychain.service.exception;
-
-public class WrongPassphraseException extends Exception {
-
- private static final long serialVersionUID = -5309689232853485740L;
-
- public WrongPassphraseException(String message) {
- super(message);
- }
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettings.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettings.java
deleted file mode 100644
index 9da4c8392..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettings.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.service.remote;
-
-import org.spongycastle.bcpg.HashAlgorithmTags;
-import org.spongycastle.openpgp.PGPEncryptedData;
-import org.sufficientlysecure.keychain.Id;
-
-public class AppSettings {
- private String packageName;
- private byte[] packageSignature;
- private long keyId = Id.key.none;
- private int encryptionAlgorithm;
- private int hashAlgorithm;
- private int compression;
-
- public AppSettings() {
-
- }
-
- public AppSettings(String packageName, byte[] packageSignature) {
- super();
- this.packageName = packageName;
- this.packageSignature = packageSignature;
- // defaults:
- this.encryptionAlgorithm = PGPEncryptedData.AES_256;
- this.hashAlgorithm = HashAlgorithmTags.SHA512;
- this.compression = Id.choice.compression.zlib;
- }
-
- public String getPackageName() {
- return packageName;
- }
-
- public void setPackageName(String packageName) {
- this.packageName = packageName;
- }
-
- public byte[] getPackageSignature() {
- return packageSignature;
- }
-
- public void setPackageSignature(byte[] packageSignature) {
- this.packageSignature = packageSignature;
- }
-
- public long getKeyId() {
- return keyId;
- }
-
- public void setKeyId(long scretKeyId) {
- this.keyId = scretKeyId;
- }
-
- public int getEncryptionAlgorithm() {
- return encryptionAlgorithm;
- }
-
- public void setEncryptionAlgorithm(int encryptionAlgorithm) {
- this.encryptionAlgorithm = encryptionAlgorithm;
- }
-
- public int getHashAlgorithm() {
- return hashAlgorithm;
- }
-
- public void setHashAlgorithm(int hashAlgorithm) {
- this.hashAlgorithm = hashAlgorithm;
- }
-
- public int getCompression() {
- return compression;
- }
-
- public void setCompression(int compression) {
- this.compression = compression;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java
deleted file mode 100644
index 8d56fc593..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.service.remote;
-
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.helper.ActionBarHelper;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.util.Log;
-
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.view.View;
-
-import com.actionbarsherlock.app.SherlockFragmentActivity;
-import com.actionbarsherlock.view.Menu;
-import com.actionbarsherlock.view.MenuItem;
-
-public class AppSettingsActivity extends SherlockFragmentActivity {
- private Uri mAppUri;
-
- private AppSettingsFragment mSettingsFragment;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Inflate a "Done" custom action bar
- ActionBarHelper.setDoneView(getSupportActionBar(), R.string.api_settings_save,
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // "Done"
- save();
- }
- });
-
- setContentView(R.layout.api_app_settings_activity);
-
- mSettingsFragment = (AppSettingsFragment) getSupportFragmentManager().findFragmentById(
- R.id.api_app_settings_fragment);
-
- Intent intent = getIntent();
- mAppUri = intent.getData();
- if (mAppUri == null) {
- Log.e(Constants.TAG, "Intent data missing. Should be Uri of app!");
- finish();
- return;
- } else {
- Log.d(Constants.TAG, "uri: " + mAppUri);
- loadData(mAppUri);
- }
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- getSupportMenuInflater().inflate(R.menu.api_app_settings, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.menu_api_settings_revoke:
- revokeAccess();
- return true;
- case R.id.menu_api_settings_cancel:
- finish();
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
-
- private void loadData(Uri appUri) {
- AppSettings settings = ProviderHelper.getApiAppSettings(this, appUri);
- mSettingsFragment.setAppSettings(settings);
- }
-
- private void revokeAccess() {
- if (getContentResolver().delete(mAppUri, null, null) <= 0) {
- throw new RuntimeException();
- }
- finish();
- }
-
- private void save() {
- ProviderHelper.updateApiApp(this, mSettingsFragment.getAppSettings(), mAppUri);
-
- finish();
- }
-
-}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java
deleted file mode 100644
index 025929cfa..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.service.remote;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-import org.spongycastle.util.encoders.Hex;
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.SelectSecretKeyLayoutFragment;
-import org.sufficientlysecure.keychain.ui.adapter.KeyValueSpinnerAdapter;
-import org.sufficientlysecure.keychain.util.AlgorithmNames;
-import org.sufficientlysecure.keychain.util.Log;
-
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.Animation;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemSelectedListener;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.Spinner;
-import android.widget.TextView;
-
-import com.beardedhen.androidbootstrap.BootstrapButton;
-
-public class AppSettingsFragment extends Fragment implements
- SelectSecretKeyLayoutFragment.SelectSecretKeyCallback {
-
- // model
- private AppSettings appSettings;
-
- // view
- private LinearLayout mAdvancedSettingsContainer;
- private BootstrapButton mAdvancedSettingsButton;
- private TextView mAppNameView;
- private ImageView mAppIconView;
- private Spinner mEncryptionAlgorithm;
- private Spinner mHashAlgorithm;
- private Spinner mCompression;
- private TextView mPackageName;
- private TextView mPackageSignature;
-
- private SelectSecretKeyLayoutFragment mSelectKeyFragment;
-
- KeyValueSpinnerAdapter encryptionAdapter;
- KeyValueSpinnerAdapter hashAdapter;
- KeyValueSpinnerAdapter compressionAdapter;
-
- public AppSettings getAppSettings() {
- return appSettings;
- }
-
- public void setAppSettings(AppSettings appSettings) {
- this.appSettings = appSettings;
- setPackage(appSettings.getPackageName());
- mPackageName.setText(appSettings.getPackageName());
-
- try {
- MessageDigest md = MessageDigest.getInstance("SHA-256");
- md.update(appSettings.getPackageSignature());
- byte[] digest = md.digest();
- String signature = new String(Hex.encode(digest));
-
- mPackageSignature.setText(signature);
- } catch (NoSuchAlgorithmException e) {
- Log.e(Constants.TAG, "Should not happen!", e);
- }
-
- mSelectKeyFragment.selectKey(appSettings.getKeyId());
- mEncryptionAlgorithm.setSelection(encryptionAdapter.getPosition(appSettings
- .getEncryptionAlgorithm()));
- mHashAlgorithm.setSelection(hashAdapter.getPosition(appSettings.getHashAlgorithm()));
- mCompression.setSelection(compressionAdapter.getPosition(appSettings.getCompression()));
- }
-
- /**
- * Inflate the layout for this fragment
- */
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.api_app_settings_fragment, container, false);
- initView(view);
- return view;
- }
-
- private void initView(View view) {
- mSelectKeyFragment = (SelectSecretKeyLayoutFragment) getFragmentManager().findFragmentById(
- R.id.api_app_settings_select_key_fragment);
- mSelectKeyFragment.setCallback(this);
-
- mAdvancedSettingsButton = (BootstrapButton) view
- .findViewById(R.id.api_app_settings_advanced_button);
- mAdvancedSettingsContainer = (LinearLayout) view
- .findViewById(R.id.api_app_settings_advanced);
-
- mAppNameView = (TextView) view.findViewById(R.id.api_app_settings_app_name);
- mAppIconView = (ImageView) view.findViewById(R.id.api_app_settings_app_icon);
- mEncryptionAlgorithm = (Spinner) view
- .findViewById(R.id.api_app_settings_encryption_algorithm);
- mHashAlgorithm = (Spinner) view.findViewById(R.id.api_app_settings_hash_algorithm);
- mCompression = (Spinner) view.findViewById(R.id.api_app_settings_compression);
- mPackageName = (TextView) view.findViewById(R.id.api_app_settings_package_name);
- mPackageSignature = (TextView) view.findViewById(R.id.api_app_settings_package_signature);
-
- AlgorithmNames algorithmNames = new AlgorithmNames(getActivity());
-
- encryptionAdapter = new KeyValueSpinnerAdapter(getActivity(),
- algorithmNames.getEncryptionNames());
- mEncryptionAlgorithm.setAdapter(encryptionAdapter);
- mEncryptionAlgorithm.setOnItemSelectedListener(new OnItemSelectedListener() {
-
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- appSettings.setEncryptionAlgorithm((int) id);
- }
-
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
- }
- });
-
- hashAdapter = new KeyValueSpinnerAdapter(getActivity(), algorithmNames.getHashNames());
- mHashAlgorithm.setAdapter(hashAdapter);
- mHashAlgorithm.setOnItemSelectedListener(new OnItemSelectedListener() {
-
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- appSettings.setHashAlgorithm((int) id);
- }
-
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
- }
- });
-
- compressionAdapter = new KeyValueSpinnerAdapter(getActivity(),
- algorithmNames.getCompressionNames());
- mCompression.setAdapter(compressionAdapter);
- mCompression.setOnItemSelectedListener(new OnItemSelectedListener() {
-
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- appSettings.setCompression((int) id);
- }
-
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
- }
- });
-
- final Animation visibleAnimation = new AlphaAnimation(0.0f, 1.0f);
- visibleAnimation.setDuration(250);
- final Animation invisibleAnimation = new AlphaAnimation(1.0f, 0.0f);
- invisibleAnimation.setDuration(250);
-
- // TODO: Better: collapse/expand animation
- // final Animation animation2 = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f,
- // Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, -1.0f,
- // Animation.RELATIVE_TO_SELF, 0.0f);
- // animation2.setDuration(150);
-
- mAdvancedSettingsButton.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- if (mAdvancedSettingsContainer.getVisibility() == View.VISIBLE) {
- mAdvancedSettingsContainer.startAnimation(invisibleAnimation);
- mAdvancedSettingsContainer.setVisibility(View.GONE);
- mAdvancedSettingsButton.setText(getString(R.string.api_settings_show_advanced));
- mAdvancedSettingsButton.setLeftIcon("fa-caret-up");
- } else {
- mAdvancedSettingsContainer.startAnimation(visibleAnimation);
- mAdvancedSettingsContainer.setVisibility(View.VISIBLE);
- mAdvancedSettingsButton.setText(getString(R.string.api_settings_hide_advanced));
- mAdvancedSettingsButton.setLeftIcon("fa-caret-down");
- }
- }
- });
- }
-
- private void setPackage(String packageName) {
- PackageManager pm = getActivity().getApplicationContext().getPackageManager();
-
- // get application name and icon from package manager
- String appName = null;
- Drawable appIcon = null;
- try {
- ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
-
- appName = (String) pm.getApplicationLabel(ai);
- appIcon = pm.getApplicationIcon(ai);
- } catch (final NameNotFoundException e) {
- // fallback
- appName = packageName;
- }
- mAppNameView.setText(appName);
- mAppIconView.setImageDrawable(appIcon);
- }
-
- /**
- * callback from select secret key fragment
- */
- @Override
- public void onKeySelected(long secretKeyId) {
- appSettings.setKeyId(secretKeyId);
- }
-
-}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/ExtendedApiService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/ExtendedApiService.java
deleted file mode 100644
index 427e6bb8f..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/ExtendedApiService.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.service.remote;
-
-import java.io.ByteArrayOutputStream;
-import java.io.PrintWriter;
-import java.security.cert.X509Certificate;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.PasswordCallback;
-
-import org.spongycastle.openpgp.PGPPrivateKey;
-import org.spongycastle.openpgp.PGPSecretKey;
-import org.spongycastle.openssl.PEMWriter;
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
-import org.sufficientlysecure.keychain.pgp.PgpToX509;
-import org.sufficientlysecure.keychain.util.Log;
-
-import android.content.Intent;
-import android.os.IBinder;
-import android.os.RemoteException;
-
-public class ExtendedApiService extends RemoteService {
-
- @Override
- public IBinder onBind(Intent intent) {
- return mBinder;
- }
-
- private void selfSignedX509CertSafe(String subjAltNameURI, IExtendedApiCallback callback,
- AppSettings appSettings) {
-
- // TODO: for pgp keyrings with password
- CallbackHandler pgpPwdCallbackHandler = new PgpToX509.PredefinedPasswordCallbackHandler("");
-
- try {
- long keyId = appSettings.getKeyId();
- PGPSecretKey pgpSecretKey = PgpKeyHelper.getSigningKey(this, keyId);
-
- PasswordCallback pgpSecKeyPasswordCallBack = new PasswordCallback("pgp passphrase?",
- false);
- pgpPwdCallbackHandler.handle(new Callback[] { pgpSecKeyPasswordCallBack });
- PGPPrivateKey pgpPrivKey = pgpSecretKey.extractPrivateKey(
- pgpSecKeyPasswordCallBack.getPassword(), Constants.BOUNCY_CASTLE_PROVIDER_NAME);
- pgpSecKeyPasswordCallBack.clearPassword();
-
- X509Certificate selfSignedCert = PgpToX509.createSelfSignedCert(pgpSecretKey,
- pgpPrivKey, subjAltNameURI);
-
- // Write x509cert and privKey into files
- // FileOutputStream fosCert = context.openFileOutput(CERT_FILENAME,
- // Context.MODE_PRIVATE);
- ByteArrayOutputStream outStream = new ByteArrayOutputStream();
- PEMWriter pemWriterCert = new PEMWriter(new PrintWriter(outStream));
- pemWriterCert.writeObject(selfSignedCert);
- pemWriterCert.close();
-
- byte[] outputBytes = outStream.toByteArray();
-
- callback.onSuccess(outputBytes);
- } catch (Exception e) {
- Log.e(Constants.TAG, "ExtendedApiService", e);
- try {
- callback.onError(e.getMessage());
- } catch (RemoteException e1) {
- Log.e(Constants.TAG, "ExtendedApiService", e);
- }
- }
-
- // TODO: no private key at the moment! Don't give it to others
- // PrivateKey privKey = pgpPrivKey.getKey();
- // FileOutputStream fosKey = context.openFileOutput(PRIV_KEY_FILENAME,
- // Context.MODE_PRIVATE);
- // PEMWriter pemWriterKey = new PEMWriter(new PrintWriter(fosKey));
- // pemWriterKey.writeObject(privKey);
- // pemWriterKey.close();
- }
-
- private final IExtendedApiService.Stub mBinder = new IExtendedApiService.Stub() {
-
- @Override
- public void encrypt(byte[] inputBytes, String passphrase, IExtendedApiCallback callback)
- throws RemoteException {
- // TODO : implement
-
- }
-
- @Override
- public void selfSignedX509Cert(final String subjAltNameURI,
- final IExtendedApiCallback callback) throws RemoteException {
- final AppSettings settings = getAppSettings();
-
- Runnable r = new Runnable() {
- @Override
- public void run() {
- selfSignedX509CertSafe(subjAltNameURI, callback, settings);
- }
- };
-
- checkAndEnqueue(r);
- }
-
- };
-
-}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/IExtendedApiCallback.aidl b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/IExtendedApiCallback.aidl
deleted file mode 100644
index f69f66fd7..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/IExtendedApiCallback.aidl
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.sufficientlysecure.keychain.service.remote;
-
-interface IExtendedApiCallback {
-
- oneway void onSuccess(in byte[] outputBytes);
-
- oneway void onError(in String error);
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/IExtendedApiService.aidl b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/IExtendedApiService.aidl
deleted file mode 100644
index 669bd31b5..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/IExtendedApiService.aidl
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.sufficientlysecure.keychain.service.remote;
-
-import org.sufficientlysecure.keychain.service.remote.IExtendedApiCallback;
-
-/**
- * All methods are oneway, which means they are asynchronous and non-blocking.
- * Results are returned to the callback, which has to be implemented on client side.
- */
-interface IExtendedApiService {
-
- /**
- * Symmetric Encrypt
- *
- * @param inputBytes
- * Byte array you want to encrypt
- * @param passphrase
- * symmetric passhprase
- * @param callback
- * Callback where to return results
- */
- oneway void encrypt(in byte[] inputBytes, in String passphrase, in IExtendedApiCallback callback);
-
- /**
- * Generates self signed X509 certificate signed by OpenPGP private key (from app settings)
- *
- * @param subjAltNameURI
- * @param callback
- * Callback where to return results
- */
- oneway void selfSignedX509Cert(in String subjAltNameURI, in IExtendedApiCallback callback);
-
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java
deleted file mode 100644
index 575f76a22..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java
+++ /dev/null
@@ -1,602 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.service.remote;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.regex.Matcher;
-
-import org.openintents.openpgp.IOpenPgpCallback;
-import org.openintents.openpgp.IOpenPgpKeyIdsCallback;
-import org.openintents.openpgp.IOpenPgpService;
-import org.openintents.openpgp.OpenPgpData;
-import org.openintents.openpgp.OpenPgpError;
-import org.openintents.openpgp.OpenPgpSignatureResult;
-import org.spongycastle.util.Arrays;
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.Id;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.helper.Preferences;
-import org.sufficientlysecure.keychain.pgp.PgpHelper;
-import org.sufficientlysecure.keychain.pgp.PgpOperation;
-import org.sufficientlysecure.keychain.pgp.exception.NoAsymmetricEncryptionException;
-import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
-import org.sufficientlysecure.keychain.provider.KeychainContract;
-import org.sufficientlysecure.keychain.service.KeychainIntentService;
-import org.sufficientlysecure.keychain.service.PassphraseCacheService;
-import org.sufficientlysecure.keychain.service.exception.NoUserIdsException;
-import org.sufficientlysecure.keychain.service.exception.UserInteractionRequiredException;
-import org.sufficientlysecure.keychain.service.exception.WrongPassphraseException;
-import org.sufficientlysecure.keychain.util.InputData;
-import org.sufficientlysecure.keychain.util.Log;
-
-import android.content.Intent;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.RemoteException;
-
-public class OpenPgpService extends RemoteService {
-
- private String getCachedPassphrase(long keyId, boolean allowUserInteraction)
- throws UserInteractionRequiredException {
- String passphrase = PassphraseCacheService.getCachedPassphrase(getContext(), keyId);
-
- if (passphrase == null) {
- if (!allowUserInteraction) {
- throw new UserInteractionRequiredException(
- "Passphrase not found in cache, please enter your passphrase!");
- }
-
- Log.d(Constants.TAG, "No passphrase! Activity required!");
-
- // start passphrase dialog
- PassphraseActivityCallback callback = new PassphraseActivityCallback();
- Bundle extras = new Bundle();
- extras.putLong(RemoteServiceActivity.EXTRA_SECRET_KEY_ID, keyId);
- pauseAndStartUserInteraction(RemoteServiceActivity.ACTION_CACHE_PASSPHRASE, callback,
- extras);
-
- if (callback.isSuccess()) {
- Log.d(Constants.TAG, "New passphrase entered!");
-
- // get again after it was entered
- passphrase = PassphraseCacheService.getCachedPassphrase(getContext(), keyId);
- } else {
- Log.d(Constants.TAG, "Passphrase dialog canceled!");
-
- return null;
- }
-
- }
-
- return passphrase;
- }
-
- public class PassphraseActivityCallback extends UserInputCallback {
-
- private boolean success = false;
-
- public boolean isSuccess() {
- return success;
- }
-
- @Override
- public void handleUserInput(Message msg) {
- if (msg.arg1 == OKAY) {
- success = true;
- } else {
- success = false;
- }
- }
- };
-
- /**
- * Search database for key ids based on emails.
- *
- * @param encryptionUserIds
- * @return
- */
- private long[] getKeyIdsFromEmails(String[] encryptionUserIds, boolean allowUserInteraction)
- throws UserInteractionRequiredException {
- // find key ids to given emails in database
- ArrayList<Long> keyIds = new ArrayList<Long>();
-
- boolean missingUserIdsCheck = false;
- boolean dublicateUserIdsCheck = false;
- ArrayList<String> missingUserIds = new ArrayList<String>();
- ArrayList<String> dublicateUserIds = new ArrayList<String>();
-
- for (String email : encryptionUserIds) {
- Uri uri = KeychainContract.KeyRings.buildPublicKeyRingsByEmailsUri(email);
- Cursor cur = getContentResolver().query(uri, null, null, null, null);
- if (cur.moveToFirst()) {
- long id = cur.getLong(cur.getColumnIndex(KeychainContract.KeyRings.MASTER_KEY_ID));
- keyIds.add(id);
- } else {
- missingUserIdsCheck = true;
- missingUserIds.add(email);
- Log.d(Constants.TAG, "user id missing");
- }
- if (cur.moveToNext()) {
- dublicateUserIdsCheck = true;
- dublicateUserIds.add(email);
- Log.d(Constants.TAG, "more than one user id with the same email");
- }
- }
-
- // convert to long[]
- long[] keyIdsArray = new long[keyIds.size()];
- for (int i = 0; i < keyIdsArray.length; i++) {
- keyIdsArray[i] = keyIds.get(i);
- }
-
- // allow the user to verify pub key selection
- if (allowUserInteraction && (missingUserIdsCheck || dublicateUserIdsCheck)) {
- SelectPubKeysActivityCallback callback = new SelectPubKeysActivityCallback();
-
- Bundle extras = new Bundle();
- extras.putLongArray(RemoteServiceActivity.EXTRA_SELECTED_MASTER_KEY_IDS, keyIdsArray);
- extras.putStringArrayList(RemoteServiceActivity.EXTRA_MISSING_USER_IDS, missingUserIds);
- extras.putStringArrayList(RemoteServiceActivity.EXTRA_DUBLICATE_USER_IDS,
- dublicateUserIds);
-
- pauseAndStartUserInteraction(RemoteServiceActivity.ACTION_SELECT_PUB_KEYS, callback,
- extras);
-
- if (callback.isSuccess()) {
- Log.d(Constants.TAG, "New selection of pub keys!");
- keyIdsArray = callback.getPubKeyIds();
- } else {
- Log.d(Constants.TAG, "Pub key selection canceled!");
- return null;
- }
- }
-
- // if no user interaction is allow throw exceptions on duplicate or missing pub keys
- if (!allowUserInteraction) {
- if (missingUserIdsCheck)
- throw new UserInteractionRequiredException(
- "Pub keys for these user ids are missing:" + missingUserIds.toString());
- if (dublicateUserIdsCheck)
- throw new UserInteractionRequiredException(
- "More than one pub key with these user ids exist:"
- + dublicateUserIds.toString());
- }
-
- if (keyIdsArray.length == 0) {
- return null;
- }
- return keyIdsArray;
- }
-
- public class SelectPubKeysActivityCallback extends UserInputCallback {
- public static final String PUB_KEY_IDS = "pub_key_ids";
-
- private boolean success = false;
- private long[] pubKeyIds;
-
- public boolean isSuccess() {
- return success;
- }
-
- public long[] getPubKeyIds() {
- return pubKeyIds;
- }
-
- @Override
- public void handleUserInput(Message msg) {
- if (msg.arg1 == OKAY) {
- success = true;
- pubKeyIds = msg.getData().getLongArray(PUB_KEY_IDS);
- } else {
- success = false;
- }
- }
- };
-
- private synchronized void getKeyIdsSafe(String[] userIds, boolean allowUserInteraction,
- IOpenPgpKeyIdsCallback callback, AppSettings appSettings) {
- try {
- long[] keyIds = getKeyIdsFromEmails(userIds, allowUserInteraction);
- if (keyIds == null) {
- throw new NoUserIdsException("No user ids!");
- }
-
- callback.onSuccess(keyIds);
- } catch (UserInteractionRequiredException e) {
- callbackOpenPgpError(callback, OpenPgpError.USER_INTERACTION_REQUIRED, e.getMessage());
- } catch (NoUserIdsException e) {
- callbackOpenPgpError(callback, OpenPgpError.NO_USER_IDS, e.getMessage());
- } catch (Exception e) {
- callbackOpenPgpError(callback, OpenPgpError.GENERIC_ERROR, e.getMessage());
- }
- }
-
- private synchronized void encryptAndSignSafe(OpenPgpData inputData,
- final OpenPgpData outputData, long[] keyIds, boolean allowUserInteraction,
- IOpenPgpCallback callback, AppSettings appSettings, boolean sign) {
- try {
- // TODO: other options of OpenPgpData!
- byte[] inputBytes = getInput(inputData);
- boolean asciiArmor = false;
- if (outputData.getType() == OpenPgpData.TYPE_STRING) {
- asciiArmor = true;
- }
-
- // add own key for encryption
- keyIds = Arrays.copyOf(keyIds, keyIds.length + 1);
- keyIds[keyIds.length - 1] = appSettings.getKeyId();
-
- // build InputData and write into OutputStream
- InputStream inputStream = new ByteArrayInputStream(inputBytes);
- long inputLength = inputBytes.length;
- InputData inputDt = new InputData(inputStream, inputLength);
-
- OutputStream outputStream = new ByteArrayOutputStream();
-
- PgpOperation operation = new PgpOperation(getContext(), null, inputDt, outputStream);
- if (sign) {
- String passphrase = getCachedPassphrase(appSettings.getKeyId(),
- allowUserInteraction);
- if (passphrase == null) {
- throw new WrongPassphraseException("No or wrong passphrase!");
- }
-
- operation.signAndEncrypt(asciiArmor, appSettings.getCompression(), keyIds, null,
- appSettings.getEncryptionAlgorithm(), appSettings.getKeyId(),
- appSettings.getHashAlgorithm(), true, passphrase);
- } else {
- operation.signAndEncrypt(asciiArmor, appSettings.getCompression(), keyIds, null,
- appSettings.getEncryptionAlgorithm(), Id.key.none,
- appSettings.getHashAlgorithm(), true, null);
- }
-
- outputStream.close();
-
- byte[] outputBytes = ((ByteArrayOutputStream) outputStream).toByteArray();
-
- OpenPgpData output = null;
- if (asciiArmor) {
- output = new OpenPgpData(new String(outputBytes));
- } else {
- output = new OpenPgpData(outputBytes);
- }
-
- // return over handler on client side
- callback.onSuccess(output, null);
- } catch (UserInteractionRequiredException e) {
- callbackOpenPgpError(callback, OpenPgpError.USER_INTERACTION_REQUIRED, e.getMessage());
- } catch (WrongPassphraseException e) {
- callbackOpenPgpError(callback, OpenPgpError.NO_OR_WRONG_PASSPHRASE, e.getMessage());
- } catch (Exception e) {
- callbackOpenPgpError(callback, OpenPgpError.GENERIC_ERROR, e.getMessage());
- }
- }
-
- // TODO: asciiArmor?!
- private void signSafe(byte[] inputBytes, boolean allowUserInteraction,
- IOpenPgpCallback callback, AppSettings appSettings) {
- 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 = getCachedPassphrase(appSettings.getKeyId(), allowUserInteraction);
- if (passphrase == null) {
- throw new WrongPassphraseException("No or wrong passphrase!");
- }
-
- PgpOperation operation = new PgpOperation(getContext(), null, inputData, outputStream);
- operation.signText(appSettings.getKeyId(), passphrase, appSettings.getHashAlgorithm(),
- Preferences.getPreferences(this).getForceV3Signatures());
-
- outputStream.close();
-
- byte[] outputBytes = ((ByteArrayOutputStream) outputStream).toByteArray();
- OpenPgpData output = new OpenPgpData(new String(outputBytes));
-
- // return over handler on client side
- callback.onSuccess(output, null);
- } catch (UserInteractionRequiredException e) {
- callbackOpenPgpError(callback, OpenPgpError.USER_INTERACTION_REQUIRED, e.getMessage());
- } catch (WrongPassphraseException e) {
- callbackOpenPgpError(callback, OpenPgpError.NO_OR_WRONG_PASSPHRASE, e.getMessage());
- } catch (Exception e) {
- callbackOpenPgpError(callback, OpenPgpError.GENERIC_ERROR, e.getMessage());
- }
- }
-
- private synchronized void decryptAndVerifySafe(byte[] inputBytes, boolean allowUserInteraction,
- IOpenPgpCallback callback, AppSettings appSettings) {
- try {
- // TODO: this is not really needed
- // checked if it is text with BEGIN and END tags
- String message = new String(inputBytes);
- Log.d(Constants.TAG, "in: " + message);
- boolean signedOnly = false;
- Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(message);
- if (matcher.matches()) {
- Log.d(Constants.TAG, "PGP_MESSAGE matched");
- message = matcher.group(1);
- // replace non breakable spaces
- message = message.replaceAll("\\xa0", " ");
-
- // overwrite inputBytes
- inputBytes = message.getBytes();
- } else {
- matcher = PgpHelper.PGP_SIGNED_MESSAGE.matcher(message);
- if (matcher.matches()) {
- signedOnly = true;
- Log.d(Constants.TAG, "PGP_SIGNED_MESSAGE matched");
- message = matcher.group(1);
- // replace non breakable spaces
- message = message.replaceAll("\\xa0", " ");
-
- // overwrite inputBytes
- inputBytes = message.getBytes();
- } else {
- Log.d(Constants.TAG, "Nothing matched! Binary?");
- }
- }
- // END TODO
-
- Log.d(Constants.TAG, "in: " + new String(inputBytes));
-
- // TODO: This allows to decrypt messages with ALL secret keys, not only the one for the
- // app, Fix this?
-
- String passphrase = null;
- if (!signedOnly) {
- // BEGIN Get key
- // TODO: this input stream is consumed after PgpMain.getDecryptionKeyId()... do it
- // better!
- InputStream inputStream2 = new ByteArrayInputStream(inputBytes);
-
- // TODO: duplicates functions from DecryptActivity!
- long secretKeyId;
- try {
- if (inputStream2.markSupported()) {
- // should probably set this to the max size of two
- // pgpF objects, if it even needs to be anything other
- // than 0.
- inputStream2.mark(200);
- }
- secretKeyId = PgpHelper.getDecryptionKeyId(this, inputStream2);
- if (secretKeyId == Id.key.none) {
- throw new PgpGeneralException(getString(R.string.error_no_secret_key_found));
- }
- } catch (NoAsymmetricEncryptionException e) {
- if (inputStream2.markSupported()) {
- inputStream2.reset();
- }
- secretKeyId = Id.key.symmetric;
- if (!PgpOperation.hasSymmetricEncryption(this, inputStream2)) {
- throw new PgpGeneralException(
- getString(R.string.error_no_known_encryption_found));
- }
- // we do not support symmetric decryption from the API!
- throw new Exception("Symmetric decryption is not supported!");
- }
-
- Log.d(Constants.TAG, "secretKeyId " + secretKeyId);
-
- passphrase = getCachedPassphrase(secretKeyId, allowUserInteraction);
- if (passphrase == null) {
- throw new WrongPassphraseException("No or wrong passphrase!");
- }
- }
-
- // 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();
-
- Bundle outputBundle;
- PgpOperation operation = new PgpOperation(getContext(), null, inputData, outputStream);
- if (signedOnly) {
- // TODO: download missing keys from keyserver?
- outputBundle = operation.verifyText(false);
- } else {
- outputBundle = operation.decryptAndVerify(passphrase, false);
- }
-
- outputStream.close();
-
- byte[] outputBytes = ((ByteArrayOutputStream) outputStream).toByteArray();
-
- // get signature informations from bundle
- boolean signature = outputBundle.getBoolean(KeychainIntentService.RESULT_SIGNATURE);
-
- OpenPgpSignatureResult sigResult = null;
- if (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);
-
- int signatureStatus = OpenPgpSignatureResult.SIGNATURE_ERROR;
- if (signatureSuccess) {
- signatureStatus = OpenPgpSignatureResult.SIGNATURE_SUCCESS_TRUSTED;
- } else if (signatureUnknown) {
- signatureStatus = OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY;
- }
-
- sigResult = new OpenPgpSignatureResult(signatureStatus, signatureUserId,
- signedOnly, signatureKeyId);
- }
- OpenPgpData output = new OpenPgpData(new String(outputBytes));
-
- // return over handler on client side
- callback.onSuccess(output, sigResult);
- } catch (UserInteractionRequiredException e) {
- callbackOpenPgpError(callback, OpenPgpError.USER_INTERACTION_REQUIRED, e.getMessage());
- } catch (WrongPassphraseException e) {
- callbackOpenPgpError(callback, OpenPgpError.NO_OR_WRONG_PASSPHRASE, e.getMessage());
- } catch (Exception e) {
- callbackOpenPgpError(callback, OpenPgpError.GENERIC_ERROR, e.getMessage());
- }
- }
-
- /**
- * Returns error to IOpenPgpCallback
- *
- * @param callback
- * @param errorId
- * @param message
- */
- private void callbackOpenPgpError(IOpenPgpCallback callback, int errorId, String message) {
- try {
- callback.onError(new OpenPgpError(0, message));
- } catch (Exception t) {
- Log.e(Constants.TAG,
- "Exception while returning OpenPgpError to client via callback.onError()", t);
- }
- }
-
- private void callbackOpenPgpError(IOpenPgpKeyIdsCallback callback, int errorId, String message) {
- try {
- callback.onError(new OpenPgpError(0, message));
- } catch (Exception t) {
- Log.e(Constants.TAG,
- "Exception while returning OpenPgpError to client via callback.onError()", t);
- }
- }
-
- private final IOpenPgpService.Stub mBinder = new IOpenPgpService.Stub() {
-
- @Override
- public void encrypt(final OpenPgpData input, final OpenPgpData output, final long[] keyIds,
- final IOpenPgpCallback callback) throws RemoteException {
- final AppSettings settings = getAppSettings();
-
- Runnable r = new Runnable() {
- @Override
- public void run() {
- encryptAndSignSafe(input, output, keyIds, true, callback, settings, false);
- }
- };
-
- checkAndEnqueue(r);
- }
-
- @Override
- public void signAndEncrypt(final OpenPgpData input, final OpenPgpData output,
- final long[] keyIds, final IOpenPgpCallback callback) throws RemoteException {
- final AppSettings settings = getAppSettings();
-
- Runnable r = new Runnable() {
- @Override
- public void run() {
- encryptAndSignSafe(input, output, keyIds, true, callback, settings, true);
- }
- };
-
- checkAndEnqueue(r);
- }
-
- @Override
- public void sign(final OpenPgpData input, final OpenPgpData output,
- final IOpenPgpCallback callback) throws RemoteException {
- final AppSettings settings = getAppSettings();
-
- Runnable r = new Runnable() {
- @Override
- public void run() {
- signSafe(getInput(input), true, callback, settings);
- }
- };
-
- checkAndEnqueue(r);
- }
-
- @Override
- public void decryptAndVerify(final OpenPgpData input, final OpenPgpData output,
- final IOpenPgpCallback callback) throws RemoteException {
-
- final AppSettings settings = getAppSettings();
-
- Runnable r = new Runnable() {
- @Override
- public void run() {
- decryptAndVerifySafe(getInput(input), true, callback, settings);
- }
- };
-
- checkAndEnqueue(r);
- }
-
- @Override
- public void getKeyIds(final String[] userIds, final boolean allowUserInteraction,
- final IOpenPgpKeyIdsCallback callback) throws RemoteException {
-
- final AppSettings settings = getAppSettings();
-
- Runnable r = new Runnable() {
- @Override
- public void run() {
- getKeyIdsSafe(userIds, allowUserInteraction, callback, settings);
- }
- };
-
- checkAndEnqueue(r);
- }
-
- };
-
- private static byte[] getInput(OpenPgpData data) {
- // TODO: support Uri and ParcelFileDescriptor
-
- byte[] inBytes = null;
- switch (data.getType()) {
- case OpenPgpData.TYPE_STRING:
- inBytes = data.getString().getBytes();
- break;
-
- case OpenPgpData.TYPE_BYTE_ARRAY:
- inBytes = data.getBytes();
- break;
-
- default:
- Log.e(Constants.TAG, "Uri and ParcelFileDescriptor not supported right now!");
- break;
- }
-
- return inBytes;
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return mBinder;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsAdapter.java
deleted file mode 100644
index 477ee04d0..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsAdapter.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.service.remote;
-
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.database.Cursor;
-import android.support.v4.widget.CursorAdapter;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-public class RegisteredAppsAdapter extends CursorAdapter {
-
- private LayoutInflater mInflater;
- private PackageManager pm;
-
- public RegisteredAppsAdapter(Context context, Cursor c, int flags) {
- super(context, c, flags);
-
- mInflater = LayoutInflater.from(context);
- pm = context.getApplicationContext().getPackageManager();
- }
-
- @Override
- public void bindView(View view, Context context, Cursor cursor) {
- TextView text = (TextView) view.findViewById(R.id.api_apps_adapter_item_name);
- ImageView icon = (ImageView) view.findViewById(R.id.api_apps_adapter_item_icon);
-
- String packageName = cursor.getString(cursor.getColumnIndex(ApiApps.PACKAGE_NAME));
- if (packageName != null) {
- // get application name
- try {
- ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
-
- text.setText(pm.getApplicationLabel(ai));
- icon.setImageDrawable(pm.getApplicationIcon(ai));
- } catch (final NameNotFoundException e) {
- // fallback
- text.setText(packageName);
- }
- } else {
- // fallback
- text.setText(packageName);
- }
-
- }
-
- @Override
- public View newView(Context context, Cursor cursor, ViewGroup parent) {
- return mInflater.inflate(R.layout.api_apps_adapter_list_item, null);
- }
-
-}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListActivity.java
deleted file mode 100644
index 3c553fff5..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListActivity.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.service.remote;
-
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.DrawerActivity;
-
-import android.os.Bundle;
-
-public class RegisteredAppsListActivity extends DrawerActivity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.api_apps_list_activity);
-
- setupDrawerNavigation(savedInstanceState);
- }
-
-}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListFragment.java
deleted file mode 100644
index 4c9d553ad..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListFragment.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.service.remote;
-
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.provider.KeychainContract;
-import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
-
-import android.content.ContentUris;
-import android.content.Intent;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.v4.app.LoaderManager;
-import android.support.v4.content.CursorLoader;
-import android.support.v4.content.Loader;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-
-import com.actionbarsherlock.app.SherlockListFragment;
-
-public class RegisteredAppsListFragment extends SherlockListFragment implements
- LoaderManager.LoaderCallbacks<Cursor> {
-
- // This is the Adapter being used to display the list's data.
- RegisteredAppsAdapter mAdapter;
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- getListView().setOnItemClickListener(new OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
- // edit app settings
- Intent intent = new Intent(getActivity(), AppSettingsActivity.class);
- intent.setData(ContentUris.withAppendedId(KeychainContract.ApiApps.CONTENT_URI, id));
- startActivity(intent);
- }
- });
-
- // Give some text to display if there is no data. In a real
- // application this would come from a resource.
- setEmptyText(getString(R.string.api_no_apps));
-
- // We have a menu item to show in action bar.
- setHasOptionsMenu(true);
-
- // Create an empty adapter we will use to display the loaded data.
- mAdapter = new RegisteredAppsAdapter(getActivity(), null, 0);
- setListAdapter(mAdapter);
-
- // Prepare the loader. Either re-connect with an existing one,
- // or start a new one.
- getLoaderManager().initLoader(0, null, this);
- }
-
- // These are the Contacts rows that we will retrieve.
- static final String[] PROJECTION = new String[] { ApiApps._ID, ApiApps.PACKAGE_NAME };
-
- public Loader<Cursor> onCreateLoader(int id, Bundle args) {
- // This is called when a new Loader needs to be created. This
- // sample only has one Loader, so we don't care about the ID.
- // First, pick the base URI to use depending on whether we are
- // currently filtering.
- Uri baseUri = ApiApps.CONTENT_URI;
-
- // Now create and return a CursorLoader that will take care of
- // creating a Cursor for the data being displayed.
- return new CursorLoader(getActivity(), baseUri, PROJECTION, null, null,
- ApiApps.PACKAGE_NAME + " COLLATE LOCALIZED ASC");
- }
-
- public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
- // Swap the new cursor in. (The framework will take care of closing the
- // old cursor once we return.)
- mAdapter.swapCursor(data);
- }
-
- public void onLoaderReset(Loader<Cursor> loader) {
- // This is called when the last Cursor provided to onLoadFinished()
- // above is about to be closed. We need to make sure we are no
- // longer using it.
- mAdapter.swapCursor(null);
- }
-
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteService.java
deleted file mode 100644
index bc513d532..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteService.java
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.service.remote;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.TimeUnit;
-
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.provider.KeychainContract;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.service.exception.WrongPackageSignatureException;
-import org.sufficientlysecure.keychain.util.Log;
-import org.sufficientlysecure.keychain.util.PausableThreadPoolExecutor;
-
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.Signature;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Messenger;
-
-/**
- * Abstract service class for remote APIs that handle app registration and user input.
- */
-public abstract class RemoteService extends Service {
- Context mContext;
-
- private final ArrayBlockingQueue<Runnable> mPoolQueue = new ArrayBlockingQueue<Runnable>(100);
- // TODO: Are these parameters okay?
- private PausableThreadPoolExecutor mThreadPool = new PausableThreadPoolExecutor(2, 4, 10,
- TimeUnit.SECONDS, mPoolQueue);
-
- private final Object userInputLock = new Object();
-
- /**
- * Override handleUserInput() to handle OKAY (1) and CANCEL (0). After handling the waiting
- * threads will be notified and the queue resumed
- */
- protected class UserInputCallback extends BaseCallback {
-
- public void handleUserInput(Message msg) {
- }
-
- @Override
- public boolean handleMessage(Message msg) {
- handleUserInput(msg);
-
- // resume
- synchronized (userInputLock) {
- userInputLock.notifyAll();
- }
- mThreadPool.resume();
- return true;
- }
-
- }
-
- /**
- * Extends Handler.Callback with OKAY (1), CANCEL (0) variables
- */
- private class BaseCallback implements Handler.Callback {
- public static final int OKAY = 1;
- public static final int CANCEL = 0;
-
- @Override
- public boolean handleMessage(Message msg) {
- return false;
- }
-
- }
-
- public Context getContext() {
- return mContext;
- }
-
- /**
- * Should be used from Stub implementations of AIDL interfaces to enqueue a runnable for
- * execution
- *
- * @param r
- */
- protected void checkAndEnqueue(Runnable r) {
- try {
- if (isCallerAllowed(false)) {
- mThreadPool.execute(r);
-
- Log.d(Constants.TAG, "Enqueued runnable…");
- } else {
- String[] callingPackages = getPackageManager().getPackagesForUid(
- Binder.getCallingUid());
- // TODO: currently simply uses first entry
- String packageName = callingPackages[0];
-
- byte[] packageSignature;
- try {
- packageSignature = getPackageSignature(packageName);
- } catch (NameNotFoundException e) {
- Log.e(Constants.TAG, "Should not happen, returning!", e);
- return;
- }
- Log.e(Constants.TAG,
- "Not allowed to use service! Starting activity for registration!");
- Bundle extras = new Bundle();
- extras.putString(RemoteServiceActivity.EXTRA_PACKAGE_NAME, packageName);
- extras.putByteArray(RemoteServiceActivity.EXTRA_PACKAGE_SIGNATURE, packageSignature);
- RegisterActivityCallback callback = new RegisterActivityCallback();
-
- pauseAndStartUserInteraction(RemoteServiceActivity.ACTION_REGISTER, callback,
- extras);
-
- if (callback.isAllowed()) {
- mThreadPool.execute(r);
- Log.d(Constants.TAG, "Enqueued runnable…");
- } else {
- Log.d(Constants.TAG, "User disallowed app!");
- }
- }
- } catch (WrongPackageSignatureException e) {
- Log.e(Constants.TAG, e.getMessage());
-
- Bundle extras = new Bundle();
- extras.putString(RemoteServiceActivity.EXTRA_ERROR_MESSAGE,
- getString(R.string.api_error_wrong_signature));
- pauseAndStartUserInteraction(RemoteServiceActivity.ACTION_ERROR_MESSAGE, null, extras);
- }
- }
-
- private byte[] getPackageSignature(String packageName) throws NameNotFoundException {
- PackageInfo pkgInfo = getPackageManager().getPackageInfo(packageName,
- PackageManager.GET_SIGNATURES);
- Signature[] signatures = pkgInfo.signatures;
- // TODO: Only first signature?!
- byte[] packageSignature = signatures[0].toByteArray();
-
- return packageSignature;
- }
-
- /**
- * Locks current thread and pauses execution of runnables and starts activity for user input
- *
- * @param action
- * @param messenger
- * @param extras
- */
- protected void pauseAndStartUserInteraction(String action, BaseCallback callback, Bundle extras) {
- synchronized (userInputLock) {
- mThreadPool.pause();
-
- Log.d(Constants.TAG, "starting activity...");
- Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.setAction(action);
-
- Messenger messenger = new Messenger(new Handler(getMainLooper(), callback));
-
- extras.putParcelable(RemoteServiceActivity.EXTRA_MESSENGER, messenger);
- intent.putExtras(extras);
-
- startActivity(intent);
-
- // lock current thread for user input
- try {
- userInputLock.wait();
- } catch (InterruptedException e) {
- Log.e(Constants.TAG, "CryptoService", e);
- }
- }
- }
-
- /**
- * Retrieves AppSettings from database for the application calling this remote service
- *
- * @return
- */
- protected AppSettings getAppSettings() {
- String[] callingPackages = getPackageManager().getPackagesForUid(Binder.getCallingUid());
-
- // get app settings for this package
- for (int i = 0; i < callingPackages.length; i++) {
- String currentPkg = callingPackages[i];
-
- Uri uri = KeychainContract.ApiApps.buildByPackageNameUri(currentPkg);
-
- AppSettings settings = ProviderHelper.getApiAppSettings(this, uri);
-
- if (settings != null)
- return settings;
- }
-
- return null;
- }
-
- class RegisterActivityCallback extends BaseCallback {
- public static final String PACKAGE_NAME = "package_name";
-
- private boolean allowed = false;
- private String packageName;
-
- public boolean isAllowed() {
- return allowed;
- }
-
- public String getPackageName() {
- return packageName;
- }
-
- @Override
- public boolean handleMessage(Message msg) {
- if (msg.arg1 == OKAY) {
- allowed = true;
- packageName = msg.getData().getString(PACKAGE_NAME);
-
- // resume threads
- try {
- if (isPackageAllowed(packageName)) {
- synchronized (userInputLock) {
- userInputLock.notifyAll();
- }
- mThreadPool.resume();
- } else {
- // Should not happen!
- Log.e(Constants.TAG, "Should not happen! Emergency shutdown!");
- mThreadPool.shutdownNow();
- }
- } catch (WrongPackageSignatureException e) {
- Log.e(Constants.TAG, e.getMessage());
-
- Bundle extras = new Bundle();
- extras.putString(RemoteServiceActivity.EXTRA_ERROR_MESSAGE,
- getString(R.string.api_error_wrong_signature));
- pauseAndStartUserInteraction(RemoteServiceActivity.ACTION_ERROR_MESSAGE, null,
- extras);
- }
- } else {
- allowed = false;
-
- synchronized (userInputLock) {
- userInputLock.notifyAll();
- }
- mThreadPool.resume();
- }
- return true;
- }
-
- }
-
- /**
- * Checks if process that binds to this service (i.e. the package name corresponding to the
- * process) is in the list of allowed package names.
- *
- * @param allowOnlySelf
- * allow only Keychain app itself
- * @return true if process is allowed to use this service
- * @throws WrongPackageSignatureException
- */
- private boolean isCallerAllowed(boolean allowOnlySelf) throws WrongPackageSignatureException {
- return isUidAllowed(Binder.getCallingUid(), allowOnlySelf);
- }
-
- private boolean isUidAllowed(int uid, boolean allowOnlySelf)
- throws WrongPackageSignatureException {
- if (android.os.Process.myUid() == uid) {
- return true;
- }
- if (allowOnlySelf) { // barrier
- return false;
- }
-
- String[] callingPackages = getPackageManager().getPackagesForUid(uid);
-
- // is calling package allowed to use this service?
- for (int i = 0; i < callingPackages.length; i++) {
- String currentPkg = callingPackages[i];
-
- if (isPackageAllowed(currentPkg)) {
- return true;
- }
- }
-
- Log.d(Constants.TAG, "Caller is NOT allowed!");
- return false;
- }
-
- /**
- * Checks if packageName is a registered app for the API. Does not return true for own package!
- *
- * @param packageName
- * @return
- * @throws WrongPackageSignatureException
- */
- private boolean isPackageAllowed(String packageName) throws WrongPackageSignatureException {
- Log.d(Constants.TAG, "packageName: " + packageName);
-
- ArrayList<String> allowedPkgs = ProviderHelper.getRegisteredApiApps(this);
- Log.d(Constants.TAG, "allowed: " + allowedPkgs);
-
- // check if package is allowed to use our service
- if (allowedPkgs.contains(packageName)) {
- Log.d(Constants.TAG, "Package is allowed! packageName: " + packageName);
-
- // check package signature
- byte[] currentSig;
- try {
- currentSig = getPackageSignature(packageName);
- } catch (NameNotFoundException e) {
- throw new WrongPackageSignatureException(e.getMessage());
- }
-
- byte[] storedSig = ProviderHelper.getApiAppSignature(this, packageName);
- if (Arrays.equals(currentSig, storedSig)) {
- Log.d(Constants.TAG,
- "Package signature is correct! (equals signature from database)");
- return true;
- } else {
- throw new WrongPackageSignatureException(
- "PACKAGE NOT ALLOWED! Signature wrong! (Signature not equals signature from database)");
- }
- }
-
- return false;
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- mContext = this;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java
deleted file mode 100644
index de07989d8..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.service.remote;
-
-import java.util.ArrayList;
-
-import org.sufficientlysecure.htmltextview.HtmlTextView;
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.Id;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.helper.ActionBarHelper;
-import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.ui.SelectPublicKeyFragment;
-import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
-import org.sufficientlysecure.keychain.util.Log;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.RemoteException;
-import android.view.View;
-import android.widget.Toast;
-
-import com.actionbarsherlock.app.SherlockFragmentActivity;
-
-public class RemoteServiceActivity extends SherlockFragmentActivity {
-
- public static final String ACTION_REGISTER = Constants.INTENT_PREFIX + "API_ACTIVITY_REGISTER";
- public static final String ACTION_CACHE_PASSPHRASE = Constants.INTENT_PREFIX
- + "API_ACTIVITY_CACHE_PASSPHRASE";
- public static final String ACTION_SELECT_PUB_KEYS = Constants.INTENT_PREFIX
- + "API_ACTIVITY_SELECT_PUB_KEYS";
- public static final String ACTION_ERROR_MESSAGE = Constants.INTENT_PREFIX
- + "API_ACTIVITY_ERROR_MESSAGE";
-
- public static final String EXTRA_MESSENGER = "messenger";
-
- // passphrase action
- public static final String EXTRA_SECRET_KEY_ID = "secret_key_id";
- // register action
- public static final String EXTRA_PACKAGE_NAME = "package_name";
- public static final String EXTRA_PACKAGE_SIGNATURE = "package_signature";
- // select pub keys action
- public static final String EXTRA_SELECTED_MASTER_KEY_IDS = "master_key_ids";
- public static final String EXTRA_MISSING_USER_IDS = "missing_user_ids";
- public static final String EXTRA_DUBLICATE_USER_IDS = "dublicate_user_ids";
- // error message
- public static final String EXTRA_ERROR_MESSAGE = "error_message";
-
- private Messenger mMessenger;
-
- // register view
- private AppSettingsFragment mSettingsFragment;
- // select pub keys view
- private SelectPublicKeyFragment mSelectFragment;
-
- // has the user clicked one of the buttons
- // or do we need to handle the callback in onStop()
- private boolean finishHandled;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- handleActions(getIntent(), savedInstanceState);
- }
-
- @Override
- protected void onStop() {
- super.onStop();
-
- if (!finishHandled) {
- Message msg = Message.obtain();
- msg.arg1 = RemoteService.RegisterActivityCallback.CANCEL;
- try {
- mMessenger.send(msg);
- } catch (RemoteException e) {
- Log.e(Constants.TAG, "CryptoServiceActivity", e);
- }
- }
- }
-
- protected void handleActions(Intent intent, Bundle savedInstanceState) {
- finishHandled = false;
-
- String action = intent.getAction();
- Bundle extras = intent.getExtras();
-
- if (extras == null) {
- extras = new Bundle();
- }
-
- mMessenger = extras.getParcelable(EXTRA_MESSENGER);
-
- /**
- * com.android.crypto actions
- */
- if (ACTION_REGISTER.equals(action)) {
- final String packageName = extras.getString(EXTRA_PACKAGE_NAME);
- final byte[] packageSignature = extras.getByteArray(EXTRA_PACKAGE_SIGNATURE);
-
- // Inflate a "Done"/"Cancel" custom action bar view
- ActionBarHelper.setDoneCancelView(getSupportActionBar(), R.string.api_register_allow,
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // Allow
-
- // user needs to select a key!
- if (mSettingsFragment.getAppSettings().getKeyId() == Id.key.none) {
- Toast.makeText(RemoteServiceActivity.this,
- R.string.api_register_error_select_key, Toast.LENGTH_LONG)
- .show();
- } else {
- ProviderHelper.insertApiApp(RemoteServiceActivity.this,
- mSettingsFragment.getAppSettings());
-
- Message msg = Message.obtain();
- msg.arg1 = RemoteService.RegisterActivityCallback.OKAY;
- Bundle data = new Bundle();
- data.putString(RemoteService.RegisterActivityCallback.PACKAGE_NAME,
- packageName);
- msg.setData(data);
- try {
- mMessenger.send(msg);
- } catch (RemoteException e) {
- Log.e(Constants.TAG, "CryptoServiceActivity", e);
- }
-
- finishHandled = true;
- finish();
- }
- }
- }, R.string.api_register_disallow, new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // Disallow
-
- Message msg = Message.obtain();
- msg.arg1 = RemoteService.RegisterActivityCallback.CANCEL;
- try {
- mMessenger.send(msg);
- } catch (RemoteException e) {
- Log.e(Constants.TAG, "CryptoServiceActivity", e);
- }
-
- finishHandled = true;
- finish();
- }
- });
-
- setContentView(R.layout.api_app_register_activity);
-
- mSettingsFragment = (AppSettingsFragment) getSupportFragmentManager().findFragmentById(
- R.id.api_app_settings_fragment);
-
- AppSettings settings = new AppSettings(packageName, packageSignature);
- mSettingsFragment.setAppSettings(settings);
- } else if (ACTION_CACHE_PASSPHRASE.equals(action)) {
- long secretKeyId = extras.getLong(EXTRA_SECRET_KEY_ID);
-
- showPassphraseDialog(secretKeyId);
- } else if (ACTION_SELECT_PUB_KEYS.equals(action)) {
- long[] selectedMasterKeyIds = intent.getLongArrayExtra(EXTRA_SELECTED_MASTER_KEY_IDS);
- ArrayList<String> missingUserIds = intent
- .getStringArrayListExtra(EXTRA_MISSING_USER_IDS);
- ArrayList<String> dublicateUserIds = intent
- .getStringArrayListExtra(EXTRA_DUBLICATE_USER_IDS);
-
- String text = new String();
- text += "<b>" + getString(R.string.api_select_pub_keys_text) + "</b>";
- text += "<br/><br/>";
- if (missingUserIds != null && missingUserIds.size() > 0) {
- text += getString(R.string.api_select_pub_keys_missing_text);
- text += "<br/>";
- text += "<ul>";
- for (String userId : missingUserIds) {
- text += "<li>" + userId + "</li>";
- }
- text += "</ul>";
- text += "<br/>";
- }
- if (dublicateUserIds != null && dublicateUserIds.size() > 0) {
- text += getString(R.string.api_select_pub_keys_dublicates_text);
- text += "<br/>";
- text += "<ul>";
- for (String userId : dublicateUserIds) {
- text += "<li>" + userId + "</li>";
- }
- text += "</ul>";
- }
-
- // Inflate a "Done"/"Cancel" custom action bar view
- ActionBarHelper.setDoneCancelView(getSupportActionBar(), R.string.btn_okay,
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // ok
-
- Message msg = Message.obtain();
- msg.arg1 = OpenPgpService.SelectPubKeysActivityCallback.OKAY;
- Bundle data = new Bundle();
- data.putLongArray(
- OpenPgpService.SelectPubKeysActivityCallback.PUB_KEY_IDS,
- mSelectFragment.getSelectedMasterKeyIds());
- msg.setData(data);
- try {
- mMessenger.send(msg);
- } catch (RemoteException e) {
- Log.e(Constants.TAG, "CryptoServiceActivity", e);
- }
-
- finishHandled = true;
- finish();
- }
- }, R.string.btn_do_not_save, new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // cancel
-
- Message msg = Message.obtain();
- msg.arg1 = OpenPgpService.SelectPubKeysActivityCallback.CANCEL;
- ;
- try {
- mMessenger.send(msg);
- } catch (RemoteException e) {
- Log.e(Constants.TAG, "CryptoServiceActivity", e);
- }
-
- finishHandled = true;
- finish();
- }
- });
-
- setContentView(R.layout.api_app_select_pub_keys_activity);
-
- // set text on view
- HtmlTextView textView = (HtmlTextView) findViewById(R.id.api_select_pub_keys_text);
- textView.setHtmlFromString(text);
-
- /* Load select pub keys fragment */
- // Check that the activity is using the layout version with
- // the fragment_container FrameLayout
- if (findViewById(R.id.api_select_pub_keys_fragment_container) != null) {
-
- // However, if we're being restored from a previous state,
- // then we don't need to do anything and should return or else
- // we could end up with overlapping fragments.
- if (savedInstanceState != null) {
- return;
- }
-
- // Create an instance of the fragment
- mSelectFragment = SelectPublicKeyFragment.newInstance(selectedMasterKeyIds);
-
- // Add the fragment to the 'fragment_container' FrameLayout
- getSupportFragmentManager().beginTransaction()
- .add(R.id.api_select_pub_keys_fragment_container, mSelectFragment).commit();
- }
- } else if (ACTION_ERROR_MESSAGE.equals(action)) {
- String errorMessage = intent.getStringExtra(EXTRA_ERROR_MESSAGE);
-
- String text = new String();
- text += "<font color=\"red\">" + errorMessage + "</font>";
-
- // Inflate a "Done" custom action bar view
- ActionBarHelper.setDoneView(getSupportActionBar(), R.string.btn_okay,
- new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
- finish();
- }
- });
-
- setContentView(R.layout.api_app_error_message);
-
- // set text on view
- HtmlTextView textView = (HtmlTextView) findViewById(R.id.api_app_error_message_text);
- textView.setHtmlFromString(text);
- } else {
- Log.e(Constants.TAG, "Wrong action!");
- finish();
- }
- }
-
- /**
- * Shows passphrase dialog to cache a new passphrase the user enters for using it later for
- * encryption. Based on mSecretKeyId it asks for a passphrase to open a private key or it asks
- * for a symmetric passphrase
- */
- private void showPassphraseDialog(long secretKeyId) {
- // Message is received after passphrase is cached
- Handler returnHandler = new Handler() {
- @Override
- public void handleMessage(Message message) {
- if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
- Message msg = Message.obtain();
- msg.arg1 = OpenPgpService.PassphraseActivityCallback.OKAY;
- try {
- mMessenger.send(msg);
- } catch (RemoteException e) {
- Log.e(Constants.TAG, "CryptoServiceActivity", e);
- }
- } else {
- Message msg = Message.obtain();
- msg.arg1 = OpenPgpService.PassphraseActivityCallback.CANCEL;
- try {
- mMessenger.send(msg);
- } catch (RemoteException e) {
- Log.e(Constants.TAG, "CryptoServiceActivity", e);
- }
- }
-
- finishHandled = true;
- finish();
- }
- };
-
- // Create a new Messenger for the communication back
- Messenger messenger = new Messenger(returnHandler);
-
- try {
- PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(this,
- messenger, secretKeyId);
-
- passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
- } catch (PgpGeneralException e) {
- Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!");
- // send message to handler to start encryption directly
- returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY);
- }
- }
-}