import keys from autocrypt headers

This commit is contained in:
Vincent Breitmoser 2017-06-28 15:41:33 +02:00
parent 42bd8683dd
commit 99dea3a466
3 changed files with 53 additions and 15 deletions

View file

@ -11,6 +11,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting; import android.support.annotation.VisibleForTesting;
import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.internet.MimeMessage; import com.fsck.k9.mail.internet.MimeMessage;
import com.fsck.k9.mail.internet.MimeUtility; import com.fsck.k9.mail.internet.MimeUtility;
import okio.ByteString; import okio.ByteString;
@ -30,7 +31,7 @@ public class AutocryptOperations {
} }
private boolean addAutocryptPeerUpdateToIntentIfPresent(MimeMessage currentMessage, Intent intent) { public boolean addAutocryptPeerUpdateToIntentIfPresent(Message currentMessage, Intent intent) {
AutocryptHeader autocryptHeader = getValidAutocryptHeader(currentMessage); AutocryptHeader autocryptHeader = getValidAutocryptHeader(currentMessage);
if (autocryptHeader == null) { if (autocryptHeader == null) {
return false; return false;
@ -51,7 +52,7 @@ public class AutocryptOperations {
return true; return true;
} }
public void processCleartextMessage(OpenPgpApi openPgpApi, MimeMessage currentMessage) { public void processCleartextMessage(OpenPgpApi openPgpApi, Message currentMessage) {
Intent intent = new Intent(OpenPgpApi.ACTION_UPDATE_AUTOCRYPT_PEER); Intent intent = new Intent(OpenPgpApi.ACTION_UPDATE_AUTOCRYPT_PEER);
boolean hasInlineKeyData = addAutocryptPeerUpdateToIntentIfPresent(currentMessage, intent); boolean hasInlineKeyData = addAutocryptPeerUpdateToIntentIfPresent(currentMessage, intent);
if (hasInlineKeyData) { if (hasInlineKeyData) {
@ -61,7 +62,7 @@ public class AutocryptOperations {
@Nullable @Nullable
@VisibleForTesting @VisibleForTesting
AutocryptHeader getValidAutocryptHeader(MimeMessage currentMessage) { AutocryptHeader getValidAutocryptHeader(Message currentMessage) {
String[] headers = currentMessage.getHeader(AUTOCRYPT_HEADER); String[] headers = currentMessage.getHeader(AUTOCRYPT_HEADER);
ArrayList<AutocryptHeader> autocryptHeaders = parseAllAutocryptHeaders(headers); ArrayList<AutocryptHeader> autocryptHeaders = parseAllAutocryptHeaders(headers);
@ -126,7 +127,7 @@ public class AutocryptOperations {
return false; return false;
} }
public boolean hasAutocryptHeader(MimeMessage currentMessage) { public boolean hasAutocryptHeader(Message currentMessage) {
return currentMessage.getHeader(AUTOCRYPT_HEADER).length > 0; return currentMessage.getHeader(AUTOCRYPT_HEADER).length > 0;
} }

View file

@ -11,10 +11,8 @@ import android.content.Intent;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting; import android.support.annotation.VisibleForTesting;
import timber.log.Timber;
import com.fsck.k9.Globals; import com.fsck.k9.Globals;
import com.fsck.k9.K9;
import com.fsck.k9.activity.compose.ComposeCryptoStatus; import com.fsck.k9.activity.compose.ComposeCryptoStatus;
import com.fsck.k9.mail.Body; import com.fsck.k9.mail.Body;
import com.fsck.k9.mail.BodyPart; import com.fsck.k9.mail.BodyPart;
@ -36,6 +34,7 @@ import org.apache.james.mime4j.util.MimeUtil;
import org.openintents.openpgp.OpenPgpError; import org.openintents.openpgp.OpenPgpError;
import org.openintents.openpgp.util.OpenPgpApi; import org.openintents.openpgp.util.OpenPgpApi;
import org.openintents.openpgp.util.OpenPgpApi.OpenPgpDataSource; import org.openintents.openpgp.util.OpenPgpApi.OpenPgpDataSource;
import timber.log.Timber;
public class PgpMessageBuilder extends MessageBuilder { public class PgpMessageBuilder extends MessageBuilder {

View file

@ -17,6 +17,9 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.annotation.WorkerThread; import android.support.annotation.WorkerThread;
import com.fsck.k9.crypto.AutocryptOperations;
import timber.log.Timber;
import com.fsck.k9.K9; import com.fsck.k9.K9;
import com.fsck.k9.crypto.MessageDecryptVerifier; import com.fsck.k9.crypto.MessageDecryptVerifier;
import com.fsck.k9.mail.Address; import com.fsck.k9.mail.Address;
@ -62,6 +65,7 @@ public class MessageCryptoHelper {
private final Context context; private final Context context;
private final String openPgpProviderPackage; private final String openPgpProviderPackage;
private final AutocryptOperations autocryptOperations;
private final Object callbackLock = new Object(); private final Object callbackLock = new Object();
private final Deque<CryptoPart> partsToDecryptOrVerify = new ArrayDeque<>(); private final Deque<CryptoPart> partsToDecryptOrVerify = new ArrayDeque<>();
@ -79,6 +83,7 @@ public class MessageCryptoHelper {
private Intent currentCryptoResult; private Intent currentCryptoResult;
private Intent userInteractionResultIntent; private Intent userInteractionResultIntent;
private boolean secondPassStarted; private boolean secondPassStarted;
private boolean thirdPassStarted;
private CancelableBackgroundOperation cancelableBackgroundOperation; private CancelableBackgroundOperation cancelableBackgroundOperation;
private boolean isCancelled; private boolean isCancelled;
@ -95,6 +100,7 @@ public class MessageCryptoHelper {
} }
this.openPgpApiFactory = openPgpApiFactory; this.openPgpApiFactory = openPgpApiFactory;
autocryptOperations = new AutocryptOperations();
openPgpProviderPackage = K9.getOpenPgpProvider(); openPgpProviderPackage = K9.getOpenPgpProvider();
} }
@ -125,6 +131,8 @@ public class MessageCryptoHelper {
} }
private void runSecondPass() { private void runSecondPass() {
secondPassStarted = true;
List<Part> signedParts = MessageDecryptVerifier.findSignedParts(currentMessage, messageAnnotations); List<Part> signedParts = MessageDecryptVerifier.findSignedParts(currentMessage, messageAnnotations);
processFoundSignedParts(signedParts); processFoundSignedParts(signedParts);
@ -134,6 +142,19 @@ public class MessageCryptoHelper {
decryptOrVerifyNextPart(); decryptOrVerifyNextPart();
} }
private void runThirdPass() {
thirdPassStarted = true;
if (messageAnnotations.isEmpty()) {
if (autocryptOperations.hasAutocryptHeader(currentMessage)) {
CryptoPart cryptoPart = new CryptoPart(CryptoPartType.PLAIN_AUTOCRYPT, currentMessage);
partsToDecryptOrVerify.add(cryptoPart);
}
}
decryptOrVerifyNextPart();
}
private void processFoundEncryptedParts(List<Part> foundParts) { private void processFoundEncryptedParts(List<Part> foundParts) {
for (Part part : foundParts) { for (Part part : foundParts) {
if (!MessageHelper.isCompletePartAvailable(part)) { if (!MessageHelper.isCompletePartAvailable(part)) {
@ -194,7 +215,7 @@ public class MessageCryptoHelper {
} }
if (partsToDecryptOrVerify.isEmpty()) { if (partsToDecryptOrVerify.isEmpty()) {
runSecondPassOrReturnResultToFragment(); runNextPassOrReturnResultToFragment();
return; return;
} }
@ -239,19 +260,22 @@ public class MessageCryptoHelper {
Intent decryptIntent = userInteractionResultIntent; Intent decryptIntent = userInteractionResultIntent;
userInteractionResultIntent = null; userInteractionResultIntent = null;
if (decryptIntent == null) { if (decryptIntent == null) {
decryptIntent = getDecryptionIntent(); decryptIntent = getDecryptVerifyIntent();
} }
decryptVerify(decryptIntent); decryptVerify(decryptIntent);
} }
@NonNull @NonNull
private Intent getDecryptionIntent() { private Intent getDecryptVerifyIntent() {
Intent decryptIntent = new Intent(OpenPgpApi.ACTION_DECRYPT_VERIFY); Intent decryptIntent = new Intent(OpenPgpApi.ACTION_DECRYPT_VERIFY);
Address[] from = currentMessage.getFrom(); Address[] from = currentMessage.getFrom();
if (from.length > 0) { if (from.length > 0) {
decryptIntent.putExtra(OpenPgpApi.EXTRA_SENDER_ADDRESS, from[0].getAddress()); decryptIntent.putExtra(OpenPgpApi.EXTRA_SENDER_ADDRESS, from[0].getAddress());
// we add this here independently of the autocrypt peer update, to allow picking up signing keys as gossip
decryptIntent.putExtra(OpenPgpApi.EXTRA_AUTOCRYPT_PEER_ID, from[0].getAddress());
} }
autocryptOperations.addAutocryptPeerUpdateToIntentIfPresent(currentMessage, decryptIntent);
decryptIntent.putExtra(OpenPgpApi.EXTRA_SUPPORT_OVERRIDE_CRYPTO_WARNING, true); decryptIntent.putExtra(OpenPgpApi.EXTRA_SUPPORT_OVERRIDE_CRYPTO_WARNING, true);
decryptIntent.putExtra(OpenPgpApi.EXTRA_DECRYPTION_RESULT, cachedDecryptionResult); decryptIntent.putExtra(OpenPgpApi.EXTRA_DECRYPTION_RESULT, cachedDecryptionResult);
@ -275,6 +299,10 @@ public class MessageCryptoHelper {
callAsyncInlineOperation(intent); callAsyncInlineOperation(intent);
return; return;
} }
case PLAIN_AUTOCRYPT: {
callAsyncParseAutocryptHeaderOperation();
return;
}
} }
throw new IllegalStateException("Unknown crypto part type: " + cryptoPartType); throw new IllegalStateException("Unknown crypto part type: " + cryptoPartType);
@ -285,6 +313,12 @@ public class MessageCryptoHelper {
} }
} }
private void callAsyncParseAutocryptHeaderOperation() {
// TODO make actually async (then callback to onCryptoFinished)
autocryptOperations.processCleartextMessage(openPgpApi, (Message) currentCryptoPart.part);
onCryptoFinished();
}
private void callAsyncInlineOperation(Intent intent) throws IOException { private void callAsyncInlineOperation(Intent intent) throws IOException {
OpenPgpDataSource dataSource = getDataSourceForEncryptedOrInlineData(); OpenPgpDataSource dataSource = getDataSourceForEncryptedOrInlineData();
OpenPgpDataSink<MimeBodyPart> dataSink = getDataSinkForDecryptedInlineData(); OpenPgpDataSink<MimeBodyPart> dataSink = getDataSinkForDecryptedInlineData();
@ -600,13 +634,16 @@ public class MessageCryptoHelper {
decryptOrVerifyNextPart(); decryptOrVerifyNextPart();
} }
private void runSecondPassOrReturnResultToFragment() { private void runNextPassOrReturnResultToFragment() {
if (secondPassStarted) { if (!secondPassStarted) {
callbackReturnResult(); runSecondPass();
return; return;
} }
secondPassStarted = true; if (!thirdPassStarted) {
runSecondPass(); runThirdPass();
return;
}
callbackReturnResult();
} }
private void cleanupAfterProcessingFinished() { private void cleanupAfterProcessingFinished() {
@ -699,7 +736,8 @@ public class MessageCryptoHelper {
private enum CryptoPartType { private enum CryptoPartType {
PGP_INLINE, PGP_INLINE,
PGP_ENCRYPTED, PGP_ENCRYPTED,
PGP_SIGNED PGP_SIGNED,
PLAIN_AUTOCRYPT
} }
@Nullable @Nullable