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.VisibleForTesting;
import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.internet.MimeMessage;
import com.fsck.k9.mail.internet.MimeUtility;
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);
if (autocryptHeader == null) {
return false;
@ -51,7 +52,7 @@ public class AutocryptOperations {
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);
boolean hasInlineKeyData = addAutocryptPeerUpdateToIntentIfPresent(currentMessage, intent);
if (hasInlineKeyData) {
@ -61,7 +62,7 @@ public class AutocryptOperations {
@Nullable
@VisibleForTesting
AutocryptHeader getValidAutocryptHeader(MimeMessage currentMessage) {
AutocryptHeader getValidAutocryptHeader(Message currentMessage) {
String[] headers = currentMessage.getHeader(AUTOCRYPT_HEADER);
ArrayList<AutocryptHeader> autocryptHeaders = parseAllAutocryptHeaders(headers);
@ -126,7 +127,7 @@ public class AutocryptOperations {
return false;
}
public boolean hasAutocryptHeader(MimeMessage currentMessage) {
public boolean hasAutocryptHeader(Message currentMessage) {
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.Nullable;
import android.support.annotation.VisibleForTesting;
import timber.log.Timber;
import com.fsck.k9.Globals;
import com.fsck.k9.K9;
import com.fsck.k9.activity.compose.ComposeCryptoStatus;
import com.fsck.k9.mail.Body;
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.util.OpenPgpApi;
import org.openintents.openpgp.util.OpenPgpApi.OpenPgpDataSource;
import timber.log.Timber;
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.WorkerThread;
import com.fsck.k9.crypto.AutocryptOperations;
import timber.log.Timber;
import com.fsck.k9.K9;
import com.fsck.k9.crypto.MessageDecryptVerifier;
import com.fsck.k9.mail.Address;
@ -62,6 +65,7 @@ public class MessageCryptoHelper {
private final Context context;
private final String openPgpProviderPackage;
private final AutocryptOperations autocryptOperations;
private final Object callbackLock = new Object();
private final Deque<CryptoPart> partsToDecryptOrVerify = new ArrayDeque<>();
@ -79,6 +83,7 @@ public class MessageCryptoHelper {
private Intent currentCryptoResult;
private Intent userInteractionResultIntent;
private boolean secondPassStarted;
private boolean thirdPassStarted;
private CancelableBackgroundOperation cancelableBackgroundOperation;
private boolean isCancelled;
@ -95,6 +100,7 @@ public class MessageCryptoHelper {
}
this.openPgpApiFactory = openPgpApiFactory;
autocryptOperations = new AutocryptOperations();
openPgpProviderPackage = K9.getOpenPgpProvider();
}
@ -125,6 +131,8 @@ public class MessageCryptoHelper {
}
private void runSecondPass() {
secondPassStarted = true;
List<Part> signedParts = MessageDecryptVerifier.findSignedParts(currentMessage, messageAnnotations);
processFoundSignedParts(signedParts);
@ -134,6 +142,19 @@ public class MessageCryptoHelper {
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) {
for (Part part : foundParts) {
if (!MessageHelper.isCompletePartAvailable(part)) {
@ -194,7 +215,7 @@ public class MessageCryptoHelper {
}
if (partsToDecryptOrVerify.isEmpty()) {
runSecondPassOrReturnResultToFragment();
runNextPassOrReturnResultToFragment();
return;
}
@ -239,19 +260,22 @@ public class MessageCryptoHelper {
Intent decryptIntent = userInteractionResultIntent;
userInteractionResultIntent = null;
if (decryptIntent == null) {
decryptIntent = getDecryptionIntent();
decryptIntent = getDecryptVerifyIntent();
}
decryptVerify(decryptIntent);
}
@NonNull
private Intent getDecryptionIntent() {
private Intent getDecryptVerifyIntent() {
Intent decryptIntent = new Intent(OpenPgpApi.ACTION_DECRYPT_VERIFY);
Address[] from = currentMessage.getFrom();
if (from.length > 0) {
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_DECRYPTION_RESULT, cachedDecryptionResult);
@ -275,6 +299,10 @@ public class MessageCryptoHelper {
callAsyncInlineOperation(intent);
return;
}
case PLAIN_AUTOCRYPT: {
callAsyncParseAutocryptHeaderOperation();
return;
}
}
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 {
OpenPgpDataSource dataSource = getDataSourceForEncryptedOrInlineData();
OpenPgpDataSink<MimeBodyPart> dataSink = getDataSinkForDecryptedInlineData();
@ -600,13 +634,16 @@ public class MessageCryptoHelper {
decryptOrVerifyNextPart();
}
private void runSecondPassOrReturnResultToFragment() {
if (secondPassStarted) {
callbackReturnResult();
private void runNextPassOrReturnResultToFragment() {
if (!secondPassStarted) {
runSecondPass();
return;
}
secondPassStarted = true;
runSecondPass();
if (!thirdPassStarted) {
runThirdPass();
return;
}
callbackReturnResult();
}
private void cleanupAfterProcessingFinished() {
@ -699,7 +736,8 @@ public class MessageCryptoHelper {
private enum CryptoPartType {
PGP_INLINE,
PGP_ENCRYPTED,
PGP_SIGNED
PGP_SIGNED,
PLAIN_AUTOCRYPT
}
@Nullable