From 06f9134eb1c386446d56fe58fa49c35b7482ed86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 4 Mar 2014 20:53:44 +0100 Subject: Enforce private key for applications, verify signed-only texts without passphrase input, better internal decrypt and verify method --- .../keychain/service/remote/OpenPgpService.java | 111 ++++----------------- 1 file changed, 20 insertions(+), 91 deletions(-) (limited to 'OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote') 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 5d2f5a815..8b34c4421 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 @@ -21,7 +21,6 @@ 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; @@ -33,9 +32,10 @@ import org.spongycastle.util.Arrays; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify; +import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult; import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt; +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.util.InputData; import org.sufficientlysecure.keychain.util.Log; @@ -284,98 +284,29 @@ public class OpenPgpService extends RemoteService { Intent result = new Intent(); try { - // TODO: - // 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: put this code into PgpDecryptVerify class - - // 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 (!PgpDecryptVerify.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); - - // NOTE: currently this only gets the passphrase for the key set for this client - String passphrase; - if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) { - passphrase = data.getStringExtra(OpenPgpApi.EXTRA_PASSPHRASE); - } else { - passphrase = PassphraseCacheService.getCachedPassphrase(getContext(), appSettings.getKeyId()); - } - if (passphrase == null) { - // get PendingIntent for passphrase input, add it to given params and return to client - Intent passphraseBundle = getPassphraseBundleIntent(data, appSettings.getKeyId()); - return passphraseBundle; - } - + String passphrase = data.getStringExtra(OpenPgpApi.EXTRA_PASSPHRASE); long inputLength = is.available(); InputData inputData = new InputData(is, inputLength); - Bundle outputBundle; PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(this, inputData, os); - - builder.assumeSymmetric(false) + builder.assumeSymmetric(false) // no support for symmetric encryption + .enforcedKeyId(appSettings.getKeyId()) // allow only the private key for this app for decryption .passphrase(passphrase); - // TODO: this also decrypts with other secret keys that have no passphrase!!! - outputBundle = builder.build().execute(); - - //TODO: instead of using all these wrapping use OpenPgpSignatureResult directly - // in DecryptVerify class and then in DecryptActivity - boolean signature = outputBundle.getBoolean(KeychainIntentService.RESULT_SIGNATURE, false); - if (signature) { - long signatureKeyId = outputBundle - .getLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID, 0); - String signatureUserId = outputBundle - .getString(KeychainIntentService.RESULT_SIGNATURE_USER_ID); - boolean signatureSuccess = outputBundle - .getBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS, false); - boolean signatureUnknown = outputBundle - .getBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN, false); - boolean signatureOnly = outputBundle - .getBoolean(KeychainIntentService.RESULT_CLEARTEXT_SIGNATURE_ONLY, false); - - // TODO: SIGNATURE_SUCCESS_CERTIFIED is currently not implemented - int signatureStatus = OpenPgpSignatureResult.SIGNATURE_ERROR; - if (signatureSuccess) { - signatureStatus = OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED; - } else if (signatureUnknown) { - signatureStatus = OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY; + // TODO: currently does not support binary signed-only content + PgpDecryptVerifyResult decryptVerifyResult = builder.build().execute(); + if (decryptVerifyResult.isKeyPassphraseNeeded()) { + // get PendingIntent for passphrase input, add it to given params and return to client + Intent passphraseBundle = getPassphraseBundleIntent(data, appSettings.getKeyId()); + return passphraseBundle; + } else if (decryptVerifyResult.isSymmetricPassphraseNeeded()) { + throw new PgpGeneralException("Decryption of symmetric content not supported by API!"); + } + + OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult(); + if (signatureResult != null) { + if (signatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY) { // If signature is unknown we return an additional PendingIntent // to retrieve the missing key // TODO!!! @@ -390,11 +321,9 @@ public class OpenPgpService extends RemoteService { result.putExtra(OpenPgpApi.RESULT_INTENT, pi); } - - OpenPgpSignatureResult sigResult = new OpenPgpSignatureResult(signatureStatus, - signatureUserId, signatureOnly, signatureKeyId); - result.putExtra(OpenPgpApi.RESULT_SIGNATURE, sigResult); + result.putExtra(OpenPgpApi.RESULT_SIGNATURE, signatureResult); } + } finally { is.close(); os.close(); -- cgit v1.2.3