From d6953745810bd4c6dee3bfefb538236b2b7bdbb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 14 Feb 2014 17:01:17 +0100 Subject: conversion of other methods --- OpenPGP-Keychain/src/main/AndroidManifest.xml | 26 +- .../service/exception/NoUserIdsException.java | 10 - .../UserInteractionRequiredException.java | 10 - .../exception/WrongPackageSignatureException.java | 10 - .../exception/WrongPassphraseException.java | 10 - .../keychain/service/remote/OpenPgpService.java | 715 +++++++-------------- .../keychain/service/remote/RemoteService.java | 1 - .../service/remote/RemoteServiceActivity.java | 77 +-- .../remote/WrongPackageSignatureException.java | 10 + 9 files changed, 292 insertions(+), 577 deletions(-) delete mode 100644 OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/NoUserIdsException.java delete mode 100644 OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/UserInteractionRequiredException.java delete mode 100644 OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/WrongPackageSignatureException.java delete mode 100644 OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/WrongPassphraseException.java create mode 100644 OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/WrongPackageSignatureException.java (limited to 'OpenPGP-Keychain') diff --git a/OpenPGP-Keychain/src/main/AndroidManifest.xml b/OpenPGP-Keychain/src/main/AndroidManifest.xml index ba2bd5571..3b9cc1a8d 100644 --- a/OpenPGP-Keychain/src/main/AndroidManifest.xml +++ b/OpenPGP-Keychain/src/main/AndroidManifest.xml @@ -391,19 +391,19 @@ - - - - - - - + + + + + + + + + + + + + diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/NoUserIdsException.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/NoUserIdsException.java deleted file mode 100644 index 555303238..000000000 --- a/OpenPGP-Keychain/src/main/java/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/main/java/org/sufficientlysecure/keychain/service/exception/UserInteractionRequiredException.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/UserInteractionRequiredException.java deleted file mode 100644 index 1152d6796..000000000 --- a/OpenPGP-Keychain/src/main/java/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/main/java/org/sufficientlysecure/keychain/service/exception/WrongPackageSignatureException.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/WrongPackageSignatureException.java deleted file mode 100644 index cef002265..000000000 --- a/OpenPGP-Keychain/src/main/java/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/main/java/org/sufficientlysecure/keychain/service/exception/WrongPassphraseException.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/exception/WrongPassphraseException.java deleted file mode 100644 index 14b774eb5..000000000 --- a/OpenPGP-Keychain/src/main/java/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/main/java/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java index 4bc5a90ac..b5b532f7a 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Dominik Schürmann + * Copyright (C) 2013-2014 Dominik Schürmann * * 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 @@ -17,106 +17,35 @@ package org.sufficientlysecure.keychain.service.remote; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.regex.Matcher; +import android.app.PendingIntent; +import android.content.Intent; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.os.IBinder; +import android.os.ParcelFileDescriptor; -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.openintents.openpgp.util.OpenPgpConstants; 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.app.PendingIntent; -import android.content.ComponentName; -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.ParcelFileDescriptor; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; 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. @@ -124,8 +53,7 @@ public class OpenPgpService extends RemoteService { * @param encryptionUserIds * @return */ - private long[] getKeyIdsFromEmails(String[] encryptionUserIds, boolean allowUserInteraction) - throws UserInteractionRequiredException { + private Bundle getKeyIdsFromEmails(String[] encryptionUserIds) { // find key ids to given emails in database ArrayList keyIds = new ArrayList(); @@ -159,98 +87,70 @@ public class OpenPgpService extends RemoteService { } // allow the user to verify pub key selection - if (allowUserInteraction && (missingUserIdsCheck || dublicateUserIdsCheck)) { - SelectPubKeysActivityCallback callback = new SelectPubKeysActivityCallback(); + if (missingUserIdsCheck || dublicateUserIdsCheck) { + // build PendingIntent for passphrase input + Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class); + intent.setAction(RemoteServiceActivity.ACTION_SELECT_PUB_KEYS); + intent.putExtra(RemoteServiceActivity.EXTRA_SELECTED_MASTER_KEY_IDS, keyIdsArray); + intent.putExtra(RemoteServiceActivity.EXTRA_MISSING_USER_IDS, missingUserIds); + intent.putExtra(RemoteServiceActivity.EXTRA_DUBLICATE_USER_IDS, dublicateUserIds); - 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); + PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 42, intent, 0); - 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; - } - } + // return PendingIntent to be executed by client + Bundle result = new Bundle(); + result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED); + result.putParcelable(OpenPgpConstants.RESULT_INTENT, pi); - // 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()); + return result; } if (keyIdsArray.length == 0) { return null; } - return keyIdsArray; - } - public class SelectPubKeysActivityCallback extends UserInputCallback { - public static final String PUB_KEY_IDS = "pub_key_ids"; + Bundle result = new Bundle(); + result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_SUCCESS); + result.putLongArray(OpenPgpConstants.PARAMS_KEY_IDS, keyIdsArray); + return result; + } - private boolean success = false; - private long[] pubKeyIds; + private Bundle getPassphraseBundleIntent(long keyId) { + // build PendingIntent for passphrase input + Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class); + intent.setAction(RemoteServiceActivity.ACTION_CACHE_PASSPHRASE); + intent.putExtra(RemoteServiceActivity.EXTRA_SECRET_KEY_ID, keyId); + PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 42, intent, 0); - public boolean isSuccess() { - return success; - } + // return PendingIntent to be executed by client + Bundle result = new Bundle(); + result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED); + result.putParcelable(OpenPgpConstants.RESULT_INTENT, pi); - 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; - } - } + return result; } - ; - - private synchronized void getKeyIdsSafe(String[] userIds, boolean allowUserInteraction, - IOpenPgpKeyIdsCallback callback, AppSettings appSettings) { + private Bundle encryptAndSignImpl(Bundle params, ParcelFileDescriptor input, + ParcelFileDescriptor output, AppSettings appSettings, + boolean sign) { try { - long[] keyIds = getKeyIdsFromEmails(userIds, allowUserInteraction); - if (keyIds == null) { - throw new NoUserIdsException("No user ids!"); - } + boolean asciiArmor = params.getBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, false); - 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()); - } - } + long[] keyIds; + if (params.containsKey(OpenPgpConstants.PARAMS_KEY_IDS)) { + keyIds = params.getLongArray(OpenPgpConstants.PARAMS_KEY_IDS); + } else { + // get key ids based on given user ids + String[] userIds = params.getStringArray(OpenPgpConstants.PARAMS_USER_IDS); + Bundle result = getKeyIdsFromEmails(userIds); + result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED); - 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; + if (result.getInt(OpenPgpConstants.RESULT_CODE, 0) == OpenPgpConstants.RESULT_CODE_SUCCESS) { + keyIds = result.getLongArray(OpenPgpConstants.PARAMS_KEY_IDS); + } else { + // non-unique result, we need user interaction! + return result; + } } // add own key for encryption @@ -258,48 +158,43 @@ public class OpenPgpService extends RemoteService { 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(); + // Get Input- and OutputStream from ParcelFileDescriptor + InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(input); + OutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(output); + try { + long inputLength = is.available(); + InputData inputData = new InputData(is, inputLength); - byte[] outputBytes = ((ByteArrayOutputStream) outputStream).toByteArray(); + PgpOperation operation = new PgpOperation(getContext(), null, inputData, os); + if (sign) { + String passphrase = PassphraseCacheService.getCachedPassphrase(getContext(), + appSettings.getKeyId()); + if (passphrase == null) { + return getPassphraseBundleIntent(appSettings.getKeyId()); + } - OpenPgpData output = null; - if (asciiArmor) { - output = new OpenPgpData(new String(outputBytes)); - } else { - output = new OpenPgpData(outputBytes); + 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); + } + } finally { + is.close(); + os.close(); } - // 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()); + Bundle result = new Bundle(); + result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_SUCCESS); + return result; } catch (Exception e) { - callbackOpenPgpError(callback, OpenPgpError.GENERIC_ERROR, e.getMessage()); + Bundle result = new Bundle(); + result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); + result.putParcelable(OpenPgpConstants.RESULT_ERRORS, + new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage())); + return result; } } @@ -309,28 +204,11 @@ public class OpenPgpService extends RemoteService { // get passphrase from cache, if key has "no" passphrase, this returns an empty String String passphrase = PassphraseCacheService.getCachedPassphrase(getContext(), appSettings.getKeyId()); if (passphrase == null) { - // TODO: we need to abort and return a passphrase Intent! - - Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class); - // TODO: setComponent really needed for security? -// intent.setComponent(new ComponentName(Constants.PACKAGE_NAME, -// "org.sufficientlysecure.keychain.service.remote.RemoteServiceActivity")); -// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.setAction(RemoteServiceActivity.ACTION_CACHE_PASSPHRASE); - intent.putExtra(RemoteServiceActivity.EXTRA_SECRET_KEY_ID, appSettings.getKeyId()); - PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 42, intent, 0); - - - Bundle result = new Bundle(); - result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED); - result.putParcelable(OpenPgpConstants.RESULT_INTENT, pi); - - return result; + return getPassphraseBundleIntent(appSettings.getKeyId()); } - // INPUT + // Get Input- and OutputStream from ParcelFileDescriptor InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(input); - // OUTPUT OutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(output); try { long inputLength = is.available(); @@ -339,22 +217,9 @@ public class OpenPgpService extends RemoteService { PgpOperation operation = new PgpOperation(getContext(), null, inputData, os); operation.signText(appSettings.getKeyId(), passphrase, appSettings.getHashAlgorithm(), Preferences.getPreferences(this).getForceV3Signatures()); - + } finally { is.close(); os.close(); -// } catch (IOException e) { -// Log.e(Constants.TAG, "Fail", e); - } finally { -// try { - is.close(); -// } catch (IOException e) { -// e.printStackTrace(); -// } -// try { - os.close(); -// } catch (IOException e) { -// e.printStackTrace(); -// } } Bundle result = new Bundle(); @@ -369,164 +234,159 @@ public class OpenPgpService extends RemoteService { } } - private synchronized void decryptAndVerifySafe(byte[] inputBytes, boolean allowUserInteraction, - IOpenPgpCallback callback, AppSettings appSettings) { + private Bundle decryptAndVerifyImpl(Bundle params, ParcelFileDescriptor input, + ParcelFileDescriptor output, 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!"); - } + // Get Input- and OutputStream from ParcelFileDescriptor + InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(input); + OutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(output); + OpenPgpSignatureResult sigResult = null; + try { - Log.d(Constants.TAG, "secretKeyId " + secretKeyId); - passphrase = getCachedPassphrase(secretKeyId, allowUserInteraction); - if (passphrase == null) { - throw new WrongPassphraseException("No or wrong passphrase!"); - } - } + // TODOs API 2.0: + // implement verify-only! + // fix the mess: http://stackoverflow.com/questions/148130/how-do-i-peek-at-the-first-two-bytes-in-an-inputstream + // should we allow to decrypt everything under every key id or only the one set? + // TODO: instead of trying to get the passphrase before + // pause stream when passphrase is missing and then resume + + + // 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 - // build InputData and write into OutputStream - InputStream inputStream = new ByteArrayInputStream(inputBytes); - long inputLength = inputBytes.length; - InputData inputData = new InputData(inputStream, inputLength); +// Log.d(Constants.TAG, "in: " + new String(inputBytes)); - OutputStream outputStream = new ByteArrayOutputStream(); + // TODO: This allows to decrypt messages with ALL secret keys, not only the one for the + // app, Fix this? - Bundle outputBundle; - PgpOperation operation = new PgpOperation(getContext(), null, inputData, outputStream); - if (signedOnly) { - outputBundle = operation.verifyText(); - } else { - outputBundle = operation.decryptAndVerify(passphrase, false); - } +// 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); - outputStream.close(); + // NOTE: currently this only gets the passphrase for the saved key + String passphrase = PassphraseCacheService.getCachedPassphrase(getContext(), appSettings.getKeyId()); + if (passphrase == null) { + return getPassphraseBundleIntent(appSettings.getKeyId()); + } +// } - byte[] outputBytes = ((ByteArrayOutputStream) outputStream).toByteArray(); + // build InputData and write into OutputStream + long inputLength = is.available(); + InputData inputData = new InputData(is, inputLength); - // 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; + Bundle outputBundle; + PgpOperation operation = new PgpOperation(getContext(), null, inputData, os); + if (signedOnly) { + outputBundle = operation.verifyText(); + } else { + // BIG TODO: instead of trying to get the passphrase before + // pause stream when passphrase is missing and then resume + outputBundle = operation.decryptAndVerify(passphrase, false); } - 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()); - } - } +// outputStream.close(); - /** - * 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); - } - } +// byte[] outputBytes = ((ByteArrayOutputStream) outputStream).toByteArray(); - 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); + // get signature informations from bundle + boolean signature = outputBundle.getBoolean(KeychainIntentService.RESULT_SIGNATURE); + + 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_CERTIFIED; + } else if (signatureUnknown) { + signatureStatus = OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY; + } + + sigResult = new OpenPgpSignatureResult(signatureStatus, signatureUserId, + signedOnly, signatureKeyId); + } + } finally { + is.close(); + os.close(); + } + + Bundle result = new Bundle(); + result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_SUCCESS); + result.putParcelable(OpenPgpConstants.RESULT_SIGNATURE, sigResult); + return result; + } catch (Exception e) { + Bundle result = new Bundle(); + result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); + result.putParcelable(OpenPgpConstants.RESULT_ERRORS, + new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage())); + return result; } } @@ -536,6 +396,7 @@ public class OpenPgpService extends RemoteService { * @param params * @return */ + private Bundle validateParamsAndVersion(Bundle params) { if (params == null) { Bundle result = new Bundle(); @@ -557,6 +418,7 @@ public class OpenPgpService extends RemoteService { return null; } + // TODO: enqueue in thread pool!!! private final IOpenPgpService.Stub mBinder = new IOpenPgpService.Stub() { @Override @@ -568,28 +430,31 @@ public class OpenPgpService extends RemoteService { return errorResult; } -// Runnable r = new Runnable() { -// @Override -// public void run() { return signImpl(input, output, appSettings); -// } -// }; - -// checkAndEnqueue(r); - -// return null; } @Override public Bundle encrypt(Bundle params, ParcelFileDescriptor input, ParcelFileDescriptor output) { + final AppSettings appSettings = getAppSettings(); - return null; + Bundle errorResult = validateParamsAndVersion(params); + if (errorResult != null) { + return errorResult; + } + + return encryptAndSignImpl(params, input, output, appSettings, false); } @Override public Bundle signAndEncrypt(Bundle params, ParcelFileDescriptor input, ParcelFileDescriptor output) { + final AppSettings appSettings = getAppSettings(); - return null; + Bundle errorResult = validateParamsAndVersion(params); + if (errorResult != null) { + return errorResult; + } + + return encryptAndSignImpl(params, input, output, appSettings, true); } @Override @@ -598,67 +463,6 @@ public class OpenPgpService extends RemoteService { return null; } -// @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() { -// signImpl(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 { @@ -677,27 +481,6 @@ public class OpenPgpService extends RemoteService { }; - 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/main/java/org/sufficientlysecure/keychain/service/remote/RemoteService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteService.java index ddc704c01..7e715e71d 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteService.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteService.java @@ -26,7 +26,6 @@ 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; diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java index 9852a2008..4ca713c1d 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java @@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.service.remote; import java.util.ArrayList; +import org.openintents.openpgp.util.OpenPgpConstants; import org.sufficientlysecure.htmltextview.HtmlTextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Id; @@ -86,15 +87,15 @@ public class RemoteServiceActivity extends ActionBarActivity { 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); -// } -// } + if (!finishHandled && mMessenger != null) { + 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) { @@ -212,39 +213,18 @@ public class RemoteServiceActivity extends ActionBarActivity { 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, + // return key ids to requesting activity + Intent finishIntent = new Intent(); + finishIntent.putExtra(OpenPgpConstants.PARAMS_KEY_IDS, mSelectFragment.getSelectedMasterKeyIds()); - msg.setData(data); - try { - mMessenger.send(msg); - } catch (RemoteException e) { - Log.e(Constants.TAG, "CryptoServiceActivity", e); - } - - finishHandled = true; + setResult(RESULT_OK, finishIntent); 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; + setResult(RESULT_CANCELED); finish(); } } @@ -287,6 +267,7 @@ public class RemoteServiceActivity extends ActionBarActivity { @Override public void onClick(View v) { + setResult(RESULT_OK); finish(); } }); @@ -298,6 +279,7 @@ public class RemoteServiceActivity extends ActionBarActivity { textView.setHtmlFromString(text); } else { Log.e(Constants.TAG, "Wrong action!"); + setResult(RESULT_CANCELED); finish(); } } @@ -313,31 +295,12 @@ public class RemoteServiceActivity extends ActionBarActivity { @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); -// } - RemoteServiceActivity.this.setResult(RESULT_OK); - RemoteServiceActivity.this.finish(); } else { -// Message msg = Message.obtain(); -// msg.arg1 = OpenPgpService.PassphraseActivityCallback.CANCEL; -// try { -// mMessenger.send(msg); -// } catch (RemoteException e) { -// Log.e(Constants.TAG, "CryptoServiceActivity", e); -// } - RemoteServiceActivity.this.setResult(RESULT_CANCELED); - RemoteServiceActivity.this.finish(); } -// finishHandled = true; -// finish(); + RemoteServiceActivity.this.finish(); } }; @@ -351,8 +314,8 @@ public class RemoteServiceActivity extends ActionBarActivity { 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); + RemoteServiceActivity.this.setResult(RESULT_OK); + RemoteServiceActivity.this.finish(); } } } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/WrongPackageSignatureException.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/WrongPackageSignatureException.java new file mode 100644 index 000000000..cc08548e8 --- /dev/null +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/WrongPackageSignatureException.java @@ -0,0 +1,10 @@ +package org.sufficientlysecure.keychain.service.remote; + +public class WrongPackageSignatureException extends Exception { + + private static final long serialVersionUID = -8294642703122196028L; + + public WrongPackageSignatureException(String message) { + super(message); + } +} \ No newline at end of file -- cgit v1.2.3