fix symmetric passphrase caching (fixes #1401)

This commit is contained in:
Vincent Breitmoser
2015-07-08 04:36:43 +02:00
parent 6cbc0ceeae
commit 5633fcc92f
5 changed files with 42 additions and 16 deletions

View File

@@ -21,6 +21,7 @@ import android.content.Context;
import android.os.Parcelable; import android.os.Parcelable;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import org.sufficientlysecure.keychain.Constants.key;
import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.pgp.PassphraseCacheInterface; import org.sufficientlysecure.keychain.pgp.PassphraseCacheInterface;
import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.Progressable;
@@ -111,8 +112,11 @@ public abstract class BaseOperation <T extends Parcelable> implements Passphrase
@Override @Override
public Passphrase getCachedPassphrase(long subKeyId) throws NoSecretKeyException { public Passphrase getCachedPassphrase(long subKeyId) throws NoSecretKeyException {
try { try {
long masterKeyId = mProviderHelper.getMasterKeyId(subKeyId); if (subKeyId != key.symmetric) {
return getCachedPassphrase(masterKeyId, subKeyId); long masterKeyId = mProviderHelper.getMasterKeyId(subKeyId);
return getCachedPassphrase(masterKeyId, subKeyId);
}
return getCachedPassphrase(key.symmetric, key.symmetric);
} catch (NotFoundException e) { } catch (NotFoundException e) {
throw new PassphraseCacheInterface.NoSecretKeyException(); throw new PassphraseCacheInterface.NoSecretKeyException();
} }

View File

@@ -605,6 +605,7 @@ public abstract class OperationResult implements Parcelable {
MSG_DC_CLEAR_SIGNATURE_OK (LogLevel.OK, R.string.msg_dc_clear_signature_ok), MSG_DC_CLEAR_SIGNATURE_OK (LogLevel.OK, R.string.msg_dc_clear_signature_ok),
MSG_DC_CLEAR_SIGNATURE (LogLevel.DEBUG, R.string.msg_dc_clear_signature), MSG_DC_CLEAR_SIGNATURE (LogLevel.DEBUG, R.string.msg_dc_clear_signature),
MSG_DC_ERROR_BAD_PASSPHRASE (LogLevel.ERROR, R.string.msg_dc_error_bad_passphrase), MSG_DC_ERROR_BAD_PASSPHRASE (LogLevel.ERROR, R.string.msg_dc_error_bad_passphrase),
MSG_DC_ERROR_SYM_PASSPHRASE (LogLevel.ERROR, R.string.msg_dc_error_sym_passphrase),
MSG_DC_ERROR_CORRUPT_DATA (LogLevel.ERROR, R.string.msg_dc_error_corrupt_data), MSG_DC_ERROR_CORRUPT_DATA (LogLevel.ERROR, R.string.msg_dc_error_corrupt_data),
MSG_DC_ERROR_EXTRACT_KEY (LogLevel.ERROR, R.string.msg_dc_error_extract_key), MSG_DC_ERROR_EXTRACT_KEY (LogLevel.ERROR, R.string.msg_dc_error_extract_key),
MSG_DC_ERROR_INTEGRITY_CHECK (LogLevel.ERROR, R.string.msg_dc_error_integrity_check), MSG_DC_ERROR_INTEGRITY_CHECK (LogLevel.ERROR, R.string.msg_dc_error_integrity_check),

View File

@@ -26,6 +26,7 @@ import org.openintents.openpgp.OpenPgpMetadata;
import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.OpenPgpSignatureResult;
import org.spongycastle.bcpg.ArmoredInputStream; import org.spongycastle.bcpg.ArmoredInputStream;
import org.spongycastle.openpgp.PGPCompressedData; import org.spongycastle.openpgp.PGPCompressedData;
import org.spongycastle.openpgp.PGPDataValidationException;
import org.spongycastle.openpgp.PGPEncryptedData; import org.spongycastle.openpgp.PGPEncryptedData;
import org.spongycastle.openpgp.PGPEncryptedDataList; import org.spongycastle.openpgp.PGPEncryptedDataList;
import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPException;
@@ -47,6 +48,7 @@ import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBu
import org.spongycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilder; import org.spongycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilder;
import org.spongycastle.util.encoders.DecoderException; import org.spongycastle.util.encoders.DecoderException;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Constants.key;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.BaseOperation; import org.sufficientlysecure.keychain.operations.BaseOperation;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
@@ -485,12 +487,23 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
// if no passphrase is given, return here // if no passphrase is given, return here
// indicating that a passphrase is missing! // indicating that a passphrase is missing!
if (!cryptoInput.hasPassphrase()) { if (!cryptoInput.hasPassphrase()) {
log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1);
return new DecryptVerifyResult(log,
RequiredInputParcel.createRequiredSymmetricPassphrase());
}
passphrase = cryptoInput.getPassphrase(); try {
passphrase = getCachedPassphrase(key.symmetric);
log.add(LogType.MSG_DC_PASS_CACHED, indent + 1);
} catch (PassphraseCacheInterface.NoSecretKeyException e) {
// nvm
}
if (passphrase == null) {
log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1);
return new DecryptVerifyResult(log,
RequiredInputParcel.createRequiredSymmetricPassphrase());
}
} else {
passphrase = cryptoInput.getPassphrase();
}
// break out of while, only decrypt the first packet // break out of while, only decrypt the first packet
break; break;
@@ -526,7 +539,14 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
digestCalcProvider).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( digestCalcProvider).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
passphrase.getCharArray()); passphrase.getCharArray());
clear = encryptedDataSymmetric.getDataStream(decryptorFactory); try {
clear = encryptedDataSymmetric.getDataStream(decryptorFactory);
} catch (PGPDataValidationException e) {
log.add(LogType.MSG_DC_ERROR_SYM_PASSPHRASE, indent +1);
return new DecryptVerifyResult(log,
RequiredInputParcel.createRequiredSymmetricPassphrase());
}
encryptedData = encryptedDataSymmetric; encryptedData = encryptedDataSymmetric;
symmetricEncryptionAlgo = encryptedDataSymmetric.getSymmetricAlgorithm(decryptorFactory); symmetricEncryptionAlgo = encryptedDataSymmetric.getSymmetricAlgorithm(decryptorFactory);

View File

@@ -232,21 +232,21 @@ public class PassphraseCacheService extends Service {
* Internal implementation to get cached passphrase. * Internal implementation to get cached passphrase.
*/ */
private Passphrase getCachedPassphraseImpl(long masterKeyId, long subKeyId) throws ProviderHelper.NotFoundException { private Passphrase getCachedPassphraseImpl(long masterKeyId, long subKeyId) throws ProviderHelper.NotFoundException {
// on "none" key, just do nothing
if (masterKeyId == Constants.key.none) {
return null;
}
// passphrase for symmetric encryption? // passphrase for symmetric encryption?
if (masterKeyId == Constants.key.symmetric) { if (masterKeyId == Constants.key.symmetric) {
Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphraseImpl() for symmetric encryption"); Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphraseImpl() for symmetric encryption");
Passphrase cachedPassphrase = mPassphraseCache.get(Constants.key.symmetric).getPassphrase(); CachedPassphrase cachedPassphrase = mPassphraseCache.get(Constants.key.symmetric);
if (cachedPassphrase == null) { if (cachedPassphrase == null) {
return null; return null;
} }
addCachedPassphrase(this, Constants.key.symmetric, Constants.key.symmetric, addCachedPassphrase(this, Constants.key.symmetric, Constants.key.symmetric,
cachedPassphrase, getString(R.string.passp_cache_notif_pwd)); cachedPassphrase.getPassphrase(), getString(R.string.passp_cache_notif_pwd));
return cachedPassphrase; return cachedPassphrase.getPassphrase();
}
// on "none" key, just do nothing
if (masterKeyId == Constants.key.none) {
return null;
} }
// try to get master key id which is used as an identifier for cached passphrases // try to get master key id which is used as an identifier for cached passphrases

View File

@@ -1103,6 +1103,7 @@
<string name="msg_dc_clear_signature">"Saving signature data for later"</string> <string name="msg_dc_clear_signature">"Saving signature data for later"</string>
<string name="msg_dc_clear">"Processing cleartext data"</string> <string name="msg_dc_clear">"Processing cleartext data"</string>
<string name="msg_dc_error_bad_passphrase">"Error unlocking key, bad password!"</string> <string name="msg_dc_error_bad_passphrase">"Error unlocking key, bad password!"</string>
<string name="msg_dc_error_sym_passphrase">"Error decrypting data! (Bad passphrase?)"</string>
<string name="msg_dc_error_corrupt_data">"Data is corrupt!"</string> <string name="msg_dc_error_corrupt_data">"Data is corrupt!"</string>
<string name="msg_dc_error_extract_key">"Unknown error unlocking key!"</string> <string name="msg_dc_error_extract_key">"Unknown error unlocking key!"</string>
<string name="msg_dc_error_integrity_check">"Integrity check error!"</string> <string name="msg_dc_error_integrity_check">"Integrity check error!"</string>