diff options
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java')
-rw-r--r-- | OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java | 141 |
1 files changed, 74 insertions, 67 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java index 1ebc75b7d..b6f102593 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de> * Copyright (C) 2010-2014 Thialfihar <thi@thialfihar.org> + * Copyright (C) 2015-2016 Vincent Breitmoser <look@my.amazin.horse> * * 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 @@ -64,6 +65,8 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.LogTyp import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; +import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; @@ -539,7 +542,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp PGPPublicKeyEncryptedData encryptedDataAsymmetric = null; PGPPBEEncryptedData encryptedDataSymmetric = null; - CanonicalizedSecretKey secretEncryptionKey = null; + CanonicalizedSecretKey decryptionKey = null; Passphrase passphrase = null; @@ -560,83 +563,87 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp log.add(LogType.MSG_DC_ASYM, indent, KeyFormattingUtils.convertKeyIdToHex(subKeyId)); - CanonicalizedSecretKeyRing secretKeyRing; + CachedPublicKeyRing cachedPublicKeyRing; try { // get actual keyring object based on master key id - secretKeyRing = mProviderHelper.getCanonicalizedSecretKeyRing( + cachedPublicKeyRing = mProviderHelper.getCachedPublicKeyRing( KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(subKeyId) ); - } catch (ProviderHelper.NotFoundException e) { - // continue with the next packet in the while loop - log.add(LogType.MSG_DC_ASKIP_NO_KEY, indent + 1); - continue; - } + long masterKeyId = cachedPublicKeyRing.getMasterKeyId(); + + // allow only specific keys for decryption? + if (input.getAllowedKeyIds() != null) { + Log.d(Constants.TAG, "encData.getKeyID(): " + subKeyId); + Log.d(Constants.TAG, "mAllowedKeyIds: " + input.getAllowedKeyIds()); + Log.d(Constants.TAG, "masterKeyId: " + masterKeyId); + + if (!input.getAllowedKeyIds().contains(masterKeyId)) { + // this key is in our db, but NOT allowed! + // continue with the next packet in the while loop + result.skippedDisallowedKey = true; + log.add(LogType.MSG_DC_ASKIP_NOT_ALLOWED, indent + 1); + continue; + } + } - // allow only specific keys for decryption? - if (input.getAllowedKeyIds() != null) { - long masterKeyId = secretKeyRing.getMasterKeyId(); - Log.d(Constants.TAG, "encData.getKeyID(): " + subKeyId); - Log.d(Constants.TAG, "mAllowedKeyIds: " + input.getAllowedKeyIds()); - Log.d(Constants.TAG, "masterKeyId: " + masterKeyId); - - if (!input.getAllowedKeyIds().contains(masterKeyId)) { - // this key is in our db, but NOT allowed! - // continue with the next packet in the while loop - result.skippedDisallowedKey = true; - log.add(LogType.MSG_DC_ASKIP_NOT_ALLOWED, indent + 1); + SecretKeyType secretKeyType = cachedPublicKeyRing.getSecretKeyType(subKeyId); + if (!secretKeyType.isUsable()) { + decryptionKey = null; + log.add(LogType.MSG_DC_ASKIP_UNAVAILABLE, indent + 1); continue; } - } - - // get subkey which has been used for this encryption packet - secretEncryptionKey = secretKeyRing.getSecretKey(subKeyId); - if (!secretEncryptionKey.canEncrypt()) { - secretEncryptionKey = null; - log.add(LogType.MSG_DC_ASKIP_BAD_FLAGS, indent + 1); - continue; - } - - if (!secretEncryptionKey.getSecretKeyType().isUsable()) { - secretEncryptionKey = null; - log.add(LogType.MSG_DC_ASKIP_UNAVAILABLE, indent + 1); - continue; - } + // get actual subkey which has been used for this encryption packet + CanonicalizedSecretKeyRing canonicalizedSecretKeyRing = mProviderHelper + .getCanonicalizedSecretKeyRing(masterKeyId); + CanonicalizedSecretKey candidateDecryptionKey = canonicalizedSecretKeyRing.getSecretKey(subKeyId); - /* secret key exists in database and is allowed! */ - asymmetricPacketFound = true; + if (!candidateDecryptionKey.canEncrypt()) { + log.add(LogType.MSG_DC_ASKIP_BAD_FLAGS, indent + 1); + continue; + } - encryptedDataAsymmetric = encData; + if (secretKeyType == SecretKeyType.DIVERT_TO_CARD) { + passphrase = null; + } else if (secretKeyType == SecretKeyType.PASSPHRASE_EMPTY) { + passphrase = new Passphrase(""); + } else if (cryptoInput.hasPassphrase()) { + passphrase = cryptoInput.getPassphrase(); + } else { + // if no passphrase was explicitly set try to get it from the cache service + try { + // returns "" if key has no passphrase + passphrase = getCachedPassphrase(subKeyId); + log.add(LogType.MSG_DC_PASS_CACHED, indent + 1); + } catch (PassphraseCacheInterface.NoSecretKeyException e) { + log.add(LogType.MSG_DC_ERROR_NO_KEY, indent + 1); + return result.with(new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log)); + } - if (secretEncryptionKey.getSecretKeyType() == SecretKeyType.DIVERT_TO_CARD) { - passphrase = null; - } else if (cryptoInput.hasPassphrase()) { - passphrase = cryptoInput.getPassphrase(); - } else { - // if no passphrase was explicitly set try to get it from the cache service - try { - // returns "" if key has no passphrase - passphrase = getCachedPassphrase(subKeyId); - log.add(LogType.MSG_DC_PASS_CACHED, indent + 1); - } catch (PassphraseCacheInterface.NoSecretKeyException e) { - log.add(LogType.MSG_DC_ERROR_NO_KEY, indent + 1); - return result.with(new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log)); + // if passphrase was not cached, return here indicating that a passphrase is missing! + if (passphrase == null) { + log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1); + return result.with(new DecryptVerifyResult(log, + RequiredInputParcel.createRequiredDecryptPassphrase(masterKeyId, subKeyId), + cryptoInput)); + } } - // if passphrase was not cached, return here indicating that a passphrase is missing! - if (passphrase == null) { - log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1); - return result.with(new DecryptVerifyResult(log, - RequiredInputParcel.createRequiredDecryptPassphrase( - secretKeyRing.getMasterKeyId(), secretEncryptionKey.getKeyId()), - cryptoInput)); + // check for insecure encryption key + if ( ! PgpSecurityConstants.isSecureKey(candidateDecryptionKey)) { + log.add(LogType.MSG_DC_INSECURE_KEY, indent + 1); + result.insecureEncryptionKey = true; } - } - // check for insecure encryption key - if ( ! PgpSecurityConstants.isSecureKey(secretEncryptionKey)) { - log.add(LogType.MSG_DC_INSECURE_KEY, indent + 1); - result.insecureEncryptionKey = true; + // we're good, write down the data for later + asymmetricPacketFound = true; + encryptedDataAsymmetric = encData; + decryptionKey = candidateDecryptionKey; + + } catch (PgpKeyNotFoundException | ProviderHelper.NotFoundException e) { + // continue with the next packet in the while loop + log.add(LogType.MSG_DC_ASKIP_NO_KEY, indent + 1); + continue; } // break out of while, only decrypt the first packet where we have a key @@ -735,7 +742,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp try { log.add(LogType.MSG_DC_UNLOCKING, indent + 1); - if (!secretEncryptionKey.unlock(passphrase)) { + if (!decryptionKey.unlock(passphrase)) { log.add(LogType.MSG_DC_ERROR_BAD_PASSPHRASE, indent + 1); return result.with(new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log)); } @@ -748,7 +755,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp updateProgress(R.string.progress_preparing_streams, currentProgress, 100); CachingDataDecryptorFactory decryptorFactory - = secretEncryptionKey.getCachingDecryptorFactory(cryptoInput); + = decryptionKey.getCachingDecryptorFactory(cryptoInput); // special case: if the decryptor does not have a session key cached for this encrypted // data, and can't actually decrypt on its own, return a pending intent @@ -757,8 +764,8 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp log.add(LogType.MSG_DC_PENDING_NFC, indent + 1); return result.with(new DecryptVerifyResult(log, RequiredInputParcel.createNfcDecryptOperation( - secretEncryptionKey.getRing().getMasterKeyId(), - secretEncryptionKey.getKeyId(), encryptedDataAsymmetric.getSessionKey()[0] + decryptionKey.getRing().getMasterKeyId(), + decryptionKey.getKeyId(), encryptedDataAsymmetric.getSessionKey()[0] ), cryptoInput)); } |