Merge branch 'master' into yubikey

Conflicts:
	OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java
	OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java
	OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
This commit is contained in:
Dominik Schürmann
2014-08-28 11:00:18 +02:00
171 changed files with 9435 additions and 2107 deletions

View File

@@ -21,6 +21,8 @@ import android.accounts.Account;
import android.app.Service;
import android.content.AbstractThreadedSyncAdapter;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SyncResult;
import android.os.Bundle;
@@ -29,9 +31,11 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.provider.ContactsContract;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.KeychainApplication;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.ContactHelper;
import org.sufficientlysecure.keychain.helper.EmailKeyHelper;
import org.sufficientlysecure.keychain.util.Log;
@@ -42,7 +46,7 @@ public class ContactSyncAdapterService extends Service {
private class ContactSyncAdapter extends AbstractThreadedSyncAdapter {
private final AtomicBoolean importDone = new AtomicBoolean(false);
// private final AtomicBoolean importDone = new AtomicBoolean(false);
public ContactSyncAdapter() {
super(ContactSyncAdapterService.this, true);
@@ -51,47 +55,59 @@ public class ContactSyncAdapterService extends Service {
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider,
final SyncResult syncResult) {
importDone.set(false);
KeychainApplication.setupAccountAsNeeded(ContactSyncAdapterService.this);
EmailKeyHelper.importContacts(getContext(), new Messenger(new Handler(Looper.getMainLooper(),
new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
Bundle data = msg.getData();
switch (msg.arg1) {
case KeychainIntentServiceHandler.MESSAGE_OKAY:
Log.d(Constants.TAG, "Syncing... Done.");
synchronized (importDone) {
importDone.set(true);
importDone.notifyAll();
}
return true;
case KeychainIntentServiceHandler.MESSAGE_UPDATE_PROGRESS:
if (data.containsKey(KeychainIntentServiceHandler.DATA_PROGRESS) &&
data.containsKey(KeychainIntentServiceHandler.DATA_PROGRESS_MAX)) {
Log.d(Constants.TAG, "Syncing... Progress: " +
data.getInt(KeychainIntentServiceHandler.DATA_PROGRESS) + "/" +
data.getInt(KeychainIntentServiceHandler.DATA_PROGRESS_MAX));
return false;
}
default:
Log.d(Constants.TAG, "Syncing... " + msg.toString());
return false;
}
}
})));
synchronized (importDone) {
try {
if (!importDone.get()) importDone.wait();
} catch (InterruptedException e) {
Log.w(Constants.TAG, e);
return;
}
}
Log.d(Constants.TAG, "Performing a sync!");
// TODO: Import is currently disabled for 2.8, until we implement proper origin management
// importDone.set(false);
// KeychainApplication.setupAccountAsNeeded(ContactSyncAdapterService.this);
// EmailKeyHelper.importContacts(getContext(), new Messenger(new Handler(Looper.getMainLooper(),
// new Handler.Callback() {
// @Override
// public boolean handleMessage(Message msg) {
// Bundle data = msg.getData();
// switch (msg.arg1) {
// case KeychainIntentServiceHandler.MESSAGE_OKAY:
// Log.d(Constants.TAG, "Syncing... Done.");
// synchronized (importDone) {
// importDone.set(true);
// importDone.notifyAll();
// }
// return true;
// case KeychainIntentServiceHandler.MESSAGE_UPDATE_PROGRESS:
// if (data.containsKey(KeychainIntentServiceHandler.DATA_PROGRESS) &&
// data.containsKey(KeychainIntentServiceHandler.DATA_PROGRESS_MAX)) {
// Log.d(Constants.TAG, "Syncing... Progress: " +
// data.getInt(KeychainIntentServiceHandler.DATA_PROGRESS) + "/" +
// data.getInt(KeychainIntentServiceHandler.DATA_PROGRESS_MAX));
// return false;
// }
// default:
// Log.d(Constants.TAG, "Syncing... " + msg.toString());
// return false;
// }
// }
// })));
// synchronized (importDone) {
// try {
// if (!importDone.get()) importDone.wait();
// } catch (InterruptedException e) {
// Log.w(Constants.TAG, e);
// return;
// }
// }
ContactHelper.writeKeysToContacts(ContactSyncAdapterService.this);
}
}
public static void requestSync() {
Bundle extras = new Bundle();
// no need to wait for internet connection!
extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
ContentResolver.requestSync(
new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE),
ContactsContract.AUTHORITY,
extras);
}
@Override
public IBinder onBind(Intent intent) {
return new ContactSyncAdapter().getSyncAdapterBinder();

View File

@@ -1,5 +1,6 @@
/*
* Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
*
* 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
@@ -49,11 +50,14 @@ import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.OperationResults.ConsolidateResult;
import org.sufficientlysecure.keychain.service.OperationResults.EditKeyResult;
import org.sufficientlysecure.keychain.service.OperationResults.ImportKeyResult;
import org.sufficientlysecure.keychain.service.OperationResults.SaveKeyringResult;
import org.sufficientlysecure.keychain.util.FileImportCache;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
@@ -102,6 +106,10 @@ public class KeychainIntentService extends IntentService
public static final String ACTION_CERTIFY_KEYRING = Constants.INTENT_PREFIX + "SIGN_KEYRING";
public static final String ACTION_DELETE = Constants.INTENT_PREFIX + "DELETE";
public static final String ACTION_CONSOLIDATE = Constants.INTENT_PREFIX + "CONSOLIDATE";
/* keys for data bundle */
// encrypt, decrypt, import export
@@ -139,8 +147,13 @@ public class KeychainIntentService extends IntentService
// delete file securely
public static final String DELETE_FILE = "deleteFile";
// delete keyring(s)
public static final String DELETE_KEY_LIST = "delete_list";
public static final String DELETE_IS_SECRET = "delete_is_secret";
// import key
public static final String IMPORT_KEY_LIST = "import_key_list";
public static final String IMPORT_KEY_FILE = "import_key_file";
// export key
public static final String EXPORT_OUTPUT_STREAM = "export_output_stream";
@@ -162,6 +175,10 @@ public class KeychainIntentService extends IntentService
public static final String CERTIFY_KEY_PUB_KEY_ID = "sign_key_pub_key_id";
public static final String CERTIFY_KEY_UIDS = "sign_key_uids";
// consolidate
public static final String CONSOLIDATE_RECOVERY = "consolidate_recovery";
/*
* possible data keys as result send over messenger
*/
@@ -176,8 +193,6 @@ public class KeychainIntentService extends IntentService
// export
public static final String RESULT_EXPORT = "exported";
public static final String RESULT_IMPORT = "result";
Messenger mMessenger;
private boolean mIsCanceled;
@@ -246,27 +261,31 @@ public class KeychainIntentService extends IntentService
String originalFilename = getOriginalFilename(data);
/* Operation */
PgpSignEncrypt.Builder builder =
new PgpSignEncrypt.Builder(
new ProviderHelper(this),
inputData, outStream);
builder.setProgressable(this);
builder.setEnableAsciiArmorOutput(useAsciiArmor)
PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder(
new ProviderHelper(this),
inputData, outStream
);
builder.setProgressable(this)
.setEnableAsciiArmorOutput(useAsciiArmor)
.setVersionHeader(PgpHelper.getVersionForHeader(this))
.setCompressionId(compressionId)
.setSymmetricEncryptionAlgorithm(
Preferences.getPreferences(this).getDefaultEncryptionAlgorithm())
.setEncryptionMasterKeyIds(encryptionKeyIds)
.setSymmetricPassphrase(symmetricPassphrase)
.setSignatureMasterKeyId(signatureKeyId)
.setEncryptToSigner(true)
.setSignatureHashAlgorithm(
Preferences.getPreferences(this).getDefaultHashAlgorithm())
.setSignaturePassphrase(
PassphraseCacheService.getCachedPassphrase(this, signatureKeyId))
.setOriginalFilename(originalFilename);
try {
builder.setSignatureMasterKeyId(signatureKeyId)
.setSignaturePassphrase(
PassphraseCacheService.getCachedPassphrase(this, signatureKeyId))
.setSignatureHashAlgorithm(
Preferences.getPreferences(this).getDefaultHashAlgorithm())
.setAdditionalEncryptId(signatureKeyId);
} catch (PassphraseCacheService.KeyNotFoundException e) {
// encrypt-only
}
// this assumes that the bytes are cleartext (valid for current implementation!)
if (source == IO_BYTES) {
builder.setCleartextInput(true);
@@ -391,23 +410,41 @@ public class KeychainIntentService extends IntentService
}
/* Operation */
ProviderHelper providerHelper = new ProviderHelper(this);
PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 10, 60, 100));
EditKeyResult result;
EditKeyResult modifyResult;
if (saveParcel.mMasterKeyId != null) {
String passphrase = data.getString(SAVE_KEYRING_PASSPHRASE);
CanonicalizedSecretKeyRing secRing =
providerHelper.getCanonicalizedSecretKeyRing(saveParcel.mMasterKeyId);
new ProviderHelper(this).getCanonicalizedSecretKeyRing(saveParcel.mMasterKeyId);
result = keyOperations.modifySecretKeyRing(secRing, saveParcel, passphrase);
modifyResult = keyOperations.modifySecretKeyRing(secRing, saveParcel, passphrase);
} else {
result = keyOperations.createSecretKeyRing(saveParcel);
modifyResult = keyOperations.createSecretKeyRing(saveParcel);
}
UncachedKeyRing ring = result.getRing();
// If the edit operation didn't succeed, exit here
if (!modifyResult.success()) {
// always return SaveKeyringResult, so create one out of the EditKeyResult
SaveKeyringResult saveResult = new SaveKeyringResult(
SaveKeyringResult.RESULT_ERROR,
modifyResult.getLog(),
null);
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, saveResult);
return;
}
providerHelper.saveSecretKeyRing(ring, new ProgressScaler(this, 60, 95, 100));
UncachedKeyRing ring = modifyResult.getRing();
// Save the keyring. The ProviderHelper is initialized with the previous log
SaveKeyringResult saveResult = new ProviderHelper(this, modifyResult.getLog())
.saveSecretKeyRing(ring, new ProgressScaler(this, 60, 95, 100));
// If the edit operation didn't succeed, exit here
if (!saveResult.success()) {
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, saveResult);
return;
}
// cache new passphrase
if (saveParcel.mNewPassphrase != null) {
@@ -417,8 +454,11 @@ public class KeychainIntentService extends IntentService
setProgress(R.string.progress_done, 100, 100);
// make sure new data is synced into contacts
ContactSyncAdapterService.requestSync();
/* Output */
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result);
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, saveResult);
} catch (Exception e) {
sendErrorToHandler(e);
}
@@ -454,17 +494,21 @@ public class KeychainIntentService extends IntentService
} else {
// get entries from cached file
FileImportCache<ParcelableKeyRing> cache =
new FileImportCache<ParcelableKeyRing>(this);
new FileImportCache<ParcelableKeyRing>(this, "key_import.pcl");
entries = cache.readCacheIntoList();
}
PgpImportExport pgpImportExport = new PgpImportExport(this, this);
ProviderHelper providerHelper = new ProviderHelper(this);
PgpImportExport pgpImportExport = new PgpImportExport(this, providerHelper, this);
ImportKeyResult result = pgpImportExport.importKeyRings(entries);
Bundle resultData = new Bundle();
resultData.putParcelable(RESULT_IMPORT, result);
if (result.mSecret > 0) {
providerHelper.consolidateDatabaseStep1(this);
}
// make sure new data is synced into contacts
ContactSyncAdapterService.requestSync();
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result);
} catch (Exception e) {
sendErrorToHandler(e);
}
@@ -549,8 +593,9 @@ public class KeychainIntentService extends IntentService
CanonicalizedPublicKeyRing keyring = providerHelper.getCanonicalizedPublicKeyRing(dataUri);
PgpImportExport pgpImportExport = new PgpImportExport(this, null);
boolean uploaded = pgpImportExport.uploadKeyRingToServer(server, keyring);
if (!uploaded) {
try {
pgpImportExport.uploadKeyRingToServer(server, keyring);
} catch (Keyserver.AddKeyException e) {
throw new PgpGeneralException("Unable to export key to selected server");
}
@@ -639,7 +684,56 @@ public class KeychainIntentService extends IntentService
} catch (Exception e) {
sendErrorToHandler(e);
}
} else if (ACTION_DELETE.equals(action)) {
try {
long[] masterKeyIds = data.getLongArray(DELETE_KEY_LIST);
boolean isSecret = data.getBoolean(DELETE_IS_SECRET);
if (masterKeyIds.length == 0) {
throw new PgpGeneralException("List of keys to delete is empty");
}
if (isSecret && masterKeyIds.length > 1) {
throw new PgpGeneralException("Secret keys can only be deleted individually!");
}
boolean success = false;
for (long masterKeyId : masterKeyIds) {
int count = getContentResolver().delete(
KeyRingData.buildPublicKeyRingUri(masterKeyId), null, null
);
success |= count > 0;
}
if (isSecret && success) {
ConsolidateResult result =
new ProviderHelper(this).consolidateDatabaseStep1(this);
}
if (success) {
// make sure new data is synced into contacts
ContactSyncAdapterService.requestSync();
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY);
}
} catch (Exception e) {
sendErrorToHandler(e);
}
} else if (ACTION_CONSOLIDATE.equals(action)) {
ConsolidateResult result;
if (data.containsKey(CONSOLIDATE_RECOVERY) && data.getBoolean(CONSOLIDATE_RECOVERY)) {
result = new ProviderHelper(this).consolidateDatabaseStep2(this);
} else {
result = new ProviderHelper(this).consolidateDatabaseStep1(this);
}
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result);
}
}
private void sendErrorToHandler(Exception e) {

View File

@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
*
* 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
@@ -155,10 +156,8 @@ public class OperationResultParcel implements Parcelable {
if ((resultType & OperationResultParcel.RESULT_ERROR) == 0) {
if (getLog().containsWarnings()) {
duration = 0;
color = Style.ORANGE;
} else {
duration = SuperToast.Duration.LONG;
color = Style.GREEN;
}
@@ -167,7 +166,6 @@ public class OperationResultParcel implements Parcelable {
} else {
duration = 0;
color = Style.RED;
str = "operation failed";
@@ -180,8 +178,8 @@ public class OperationResultParcel implements Parcelable {
button ? SuperToast.Type.BUTTON : SuperToast.Type.STANDARD,
Style.getStyle(color, SuperToast.Animations.POPUP));
toast.setText(str);
toast.setDuration(duration);
toast.setIndeterminate(duration == 0);
toast.setDuration(SuperToast.Duration.EXTRA_LONG);
toast.setIndeterminate(false);
toast.setSwipeToDismiss(true);
// If we have a log and it's non-empty, show a View Log button
if (button) {
@@ -289,6 +287,7 @@ public class OperationResultParcel implements Parcelable {
MSG_IS_SUCCESS (R.string.msg_is_success),
// keyring canonicalization
MSG_KC_V3_KEY (R.string.msg_kc_v3_key),
MSG_KC_PUBLIC (R.string.msg_kc_public),
MSG_KC_SECRET (R.string.msg_kc_secret),
MSG_KC_FATAL_NO_UID (R.string.msg_kc_fatal_no_uid),
@@ -324,6 +323,7 @@ public class OperationResultParcel implements Parcelable {
MSG_KC_UID_BAD_TIME (R.string.msg_kc_uid_bad_time),
MSG_KC_UID_BAD_TYPE (R.string.msg_kc_uid_bad_type),
MSG_KC_UID_BAD (R.string.msg_kc_uid_bad),
MSG_KC_UID_CERT_DUP (R.string.msg_kc_uid_cert_dup),
MSG_KC_UID_DUP (R.string.msg_kc_uid_dup),
MSG_KC_UID_FOREIGN (R.string.msg_kc_uid_foreign),
MSG_KC_UID_NO_CERT (R.string.msg_kc_uid_no_cert),
@@ -333,10 +333,11 @@ public class OperationResultParcel implements Parcelable {
// keyring consolidation
MSG_MG_ERROR_SECRET_DUMMY(R.string.msg_mg_error_secret_dummy),
MSG_MG_ERROR_ENCODE(R.string.msg_mg_error_encode),
MSG_MG_ERROR_HETEROGENEOUS(R.string.msg_mg_error_heterogeneous),
MSG_MG_PUBLIC (R.string.msg_mg_public),
MSG_MG_SECRET (R.string.msg_mg_secret),
MSG_MG_FATAL_ENCODE (R.string.msg_mg_fatal_encode),
MSG_MG_HETEROGENEOUS (R.string.msg_mg_heterogeneous),
MSG_MG_NEW_SUBKEY (R.string.msg_mg_new_subkey),
MSG_MG_FOUND_NEW (R.string.msg_mg_found_new),
MSG_MG_UNCHANGED (R.string.msg_mg_unchanged),
@@ -346,10 +347,16 @@ public class OperationResultParcel implements Parcelable {
MSG_CR_ERROR_NO_MASTER (R.string.msg_cr_error_no_master),
MSG_CR_ERROR_NO_USER_ID (R.string.msg_cr_error_no_user_id),
MSG_CR_ERROR_NO_CERTIFY (R.string.msg_cr_error_no_certify),
MSG_CR_ERROR_NULL_EXPIRY(R.string.msg_cr_error_null_expiry),
MSG_CR_ERROR_KEYSIZE_512 (R.string.msg_cr_error_keysize_512),
MSG_CR_ERROR_NO_KEYSIZE (R.string.msg_cr_error_no_keysize),
MSG_CR_ERROR_NO_CURVE (R.string.msg_cr_error_no_curve),
MSG_CR_ERROR_UNKNOWN_ALGO (R.string.msg_cr_error_unknown_algo),
MSG_CR_ERROR_INTERNAL_PGP (R.string.msg_cr_error_internal_pgp),
MSG_CR_ERROR_MASTER_ELGAMAL (R.string.msg_cr_error_master_elgamal),
MSG_CR_ERROR_FLAGS_DSA (R.string.msg_cr_error_flags_dsa),
MSG_CR_ERROR_FLAGS_ELGAMAL (R.string.msg_cr_error_flags_elgamal),
MSG_CR_ERROR_FLAGS_ECDSA (R.string.msg_cr_error_flags_ecdsa),
MSG_CR_ERROR_FLAGS_ECDH (R.string.msg_cr_error_flags_ecdh),
// secret key modify
MSG_MF (R.string.msg_mr),
@@ -357,18 +364,27 @@ public class OperationResultParcel implements Parcelable {
MSG_MF_ERROR_FINGERPRINT (R.string.msg_mf_error_fingerprint),
MSG_MF_ERROR_KEYID (R.string.msg_mf_error_keyid),
MSG_MF_ERROR_INTEGRITY (R.string.msg_mf_error_integrity),
MSG_MF_ERROR_MASTER_NONE(R.string.msg_mf_error_master_none),
MSG_MF_ERROR_NO_CERTIFY (R.string.msg_cr_error_no_certify),
MSG_MF_ERROR_NOEXIST_PRIMARY (R.string.msg_mf_error_noexist_primary),
MSG_MF_ERROR_REVOKED_PRIMARY (R.string.msg_mf_error_revoked_primary),
MSG_MF_ERROR_NOEXIST_REVOKE (R.string.msg_mf_error_noexist_revoke),
MSG_MF_ERROR_NULL_EXPIRY (R.string.msg_mf_error_null_expiry),
MSG_MF_ERROR_PASSPHRASE_MASTER(R.string.msg_mf_error_passphrase_master),
MSG_MF_ERROR_PAST_EXPIRY(R.string.msg_mf_error_past_expiry),
MSG_MF_ERROR_PGP (R.string.msg_mf_error_pgp),
MSG_MF_ERROR_REVOKED_PRIMARY (R.string.msg_mf_error_revoked_primary),
MSG_MF_ERROR_SIG (R.string.msg_mf_error_sig),
MSG_MF_ERROR_SUBKEY_MISSING(R.string.msg_mf_error_subkey_missing),
MSG_MF_MASTER (R.string.msg_mf_master),
MSG_MF_PASSPHRASE (R.string.msg_mf_passphrase),
MSG_MF_PASSPHRASE_KEY (R.string.msg_mf_passphrase_key),
MSG_MF_PASSPHRASE_EMPTY_RETRY (R.string.msg_mf_passphrase_empty_retry),
MSG_MF_PASSPHRASE_FAIL (R.string.msg_mf_passphrase_fail),
MSG_MF_PRIMARY_REPLACE_OLD (R.string.msg_mf_primary_replace_old),
MSG_MF_PRIMARY_NEW (R.string.msg_mf_primary_new),
MSG_MF_SUBKEY_CHANGE (R.string.msg_mf_subkey_change),
MSG_MF_SUBKEY_MISSING (R.string.msg_mf_subkey_missing),
MSG_MF_SUBKEY_NEW_ID (R.string.msg_mf_subkey_new_id),
MSG_MF_SUBKEY_NEW (R.string.msg_mf_subkey_new),
MSG_MF_SUBKEY_PAST_EXPIRY (R.string.msg_mf_subkey_past_expiry),
MSG_MF_SUBKEY_REVOKE (R.string.msg_mf_subkey_revoke),
MSG_MF_SUCCESS (R.string.msg_mf_success),
MSG_MF_UID_ADD (R.string.msg_mf_uid_add),
@@ -377,6 +393,32 @@ public class OperationResultParcel implements Parcelable {
MSG_MF_UID_ERROR_EMPTY (R.string.msg_mf_uid_error_empty),
MSG_MF_UNLOCK_ERROR (R.string.msg_mf_unlock_error),
MSG_MF_UNLOCK (R.string.msg_mf_unlock),
// consolidate
MSG_CON_CRITICAL_IN (R.string.msg_con_critical_in),
MSG_CON_CRITICAL_OUT (R.string.msg_con_critical_out),
MSG_CON_DB_CLEAR (R.string.msg_con_db_clear),
MSG_CON_DELETE_PUBLIC (R.string.msg_con_delete_public),
MSG_CON_DELETE_SECRET (R.string.msg_con_delete_secret),
MSG_CON_ERROR_BAD_STATE (R.string.msg_con_error_bad_state),
MSG_CON_ERROR_CONCURRENT(R.string.msg_con_error_concurrent),
MSG_CON_ERROR_DB (R.string.msg_con_error_db),
MSG_CON_ERROR_IO_PUBLIC (R.string.msg_con_error_io_public),
MSG_CON_ERROR_IO_SECRET (R.string.msg_con_error_io_secret),
MSG_CON_ERROR_PUBLIC (R.string.msg_con_error_public),
MSG_CON_ERROR_SECRET (R.string.msg_con_error_secret),
MSG_CON_RECOVER (R.plurals.msg_con_recover),
MSG_CON_RECOVER_UNKNOWN (R.string.msg_con_recover_unknown),
MSG_CON_REIMPORT_PUBLIC (R.plurals.msg_con_reimport_public),
MSG_CON_REIMPORT_PUBLIC_SKIP (R.string.msg_con_reimport_public_skip),
MSG_CON_REIMPORT_SECRET (R.plurals.msg_con_reimport_secret),
MSG_CON_REIMPORT_SECRET_SKIP (R.string.msg_con_reimport_secret_skip),
MSG_CON (R.string.msg_con),
MSG_CON_SAVE_PUBLIC (R.string.msg_con_save_public),
MSG_CON_SAVE_SECRET (R.string.msg_con_save_secret),
MSG_CON_SUCCESS (R.string.msg_con_success),
MSG_CON_WARN_DELETE_PUBLIC (R.string.msg_con_warn_delete_public),
MSG_CON_WARN_DELETE_SECRET (R.string.msg_con_warn_delete_secret),
;
private final int mMsgId;
@@ -406,7 +448,9 @@ public class OperationResultParcel implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mResult);
dest.writeTypedList(mLog.toList());
if (mLog != null) {
dest.writeTypedList(mLog.toList());
}
}
public static final Creator<OperationResultParcel> CREATOR = new Creator<OperationResultParcel>() {
@@ -432,6 +476,15 @@ public class OperationResultParcel implements Parcelable {
mParcels.add(new OperationResultParcel.LogEntryParcel(level, type, indent, (Object[]) null));
}
public boolean containsType(LogType type) {
for(LogEntryParcel entry : new IterableIterator<LogEntryParcel>(mParcels.iterator())) {
if (entry.mType == type) {
return true;
}
}
return false;
}
public boolean containsWarnings() {
for(LogEntryParcel entry : new IterableIterator<LogEntryParcel>(mParcels.iterator())) {
if (entry.mLevel == LogLevel.WARN || entry.mLevel == LogLevel.ERROR) {

View File

@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
*
* 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
@@ -28,7 +29,10 @@ import com.github.johnpersano.supertoasts.SuperToast;
import com.github.johnpersano.supertoasts.util.OnClickWrapper;
import com.github.johnpersano.supertoasts.util.Style;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
import org.sufficientlysecure.keychain.ui.LogDisplayActivity;
import org.sufficientlysecure.keychain.ui.LogDisplayFragment;
@@ -37,7 +41,7 @@ public abstract class OperationResults {
public static class ImportKeyResult extends OperationResultParcel {
public final int mNewKeys, mUpdatedKeys, mBadKeys;
public final int mNewKeys, mUpdatedKeys, mBadKeys, mSecret;
// At least one new key
public static final int RESULT_OK_NEWKEYS = 2;
@@ -49,18 +53,21 @@ public abstract class OperationResults {
public static final int RESULT_WITH_WARNINGS = 16;
// No keys to import...
public static final int RESULT_FAIL_NOTHING = 32 +1;
public static final int RESULT_FAIL_NOTHING = 32 + 1;
public boolean isOkBoth() {
return (mResult & (RESULT_OK_NEWKEYS | RESULT_OK_UPDATED))
== (RESULT_OK_NEWKEYS | RESULT_OK_UPDATED);
}
public boolean isOkNew() {
return (mResult & RESULT_OK_NEWKEYS) == RESULT_OK_NEWKEYS;
}
public boolean isOkUpdated() {
return (mResult & RESULT_OK_UPDATED) == RESULT_OK_UPDATED;
}
public boolean isFailNothing() {
return (mResult & RESULT_FAIL_NOTHING) == RESULT_FAIL_NOTHING;
}
@@ -70,14 +77,16 @@ public abstract class OperationResults {
mNewKeys = source.readInt();
mUpdatedKeys = source.readInt();
mBadKeys = source.readInt();
mSecret = source.readInt();
}
public ImportKeyResult(int result, OperationLog log,
int newKeys, int updatedKeys, int badKeys) {
int newKeys, int updatedKeys, int badKeys, int secret) {
super(result, log);
mNewKeys = newKeys;
mUpdatedKeys = updatedKeys;
mBadKeys = badKeys;
mSecret = secret;
}
@Override
@@ -86,6 +95,7 @@ public abstract class OperationResults {
dest.writeInt(mNewKeys);
dest.writeInt(mUpdatedKeys);
dest.writeInt(mBadKeys);
dest.writeInt(mSecret);
}
public static Creator<ImportKeyResult> CREATOR = new Creator<ImportKeyResult>() {
@@ -124,7 +134,7 @@ public abstract class OperationResults {
if (this.isOkBoth()) {
str = activity.getResources().getQuantityString(
R.plurals.import_keys_added_and_updated_1, mNewKeys, mNewKeys);
str += " "+ activity.getResources().getQuantityString(
str += " " + activity.getResources().getQuantityString(
R.plurals.import_keys_added_and_updated_2, mUpdatedKeys, mUpdatedKeys, withWarnings);
} else if (isOkUpdated()) {
str = activity.getResources().getQuantityString(
@@ -185,13 +195,13 @@ public abstract class OperationResults {
public static class EditKeyResult extends OperationResultParcel {
private transient UncachedKeyRing mRing;
public final Long mRingMasterKeyId;
public final long mRingMasterKeyId;
public EditKeyResult(int result, OperationLog log,
UncachedKeyRing ring) {
UncachedKeyRing ring) {
super(result, log);
mRing = ring;
mRingMasterKeyId = ring != null ? ring.getMasterKeyId() : null;
mRingMasterKeyId = ring != null ? ring.getMasterKeyId() : Constants.key.none;
}
public UncachedKeyRing getRing() {
@@ -224,8 +234,12 @@ public abstract class OperationResults {
public static class SaveKeyringResult extends OperationResultParcel {
public SaveKeyringResult(int result, OperationLog log) {
public final long mRingMasterKeyId;
public SaveKeyringResult(int result, OperationLog log,
CanonicalizedKeyRing ring) {
super(result, log);
mRingMasterKeyId = ring != null ? ring.getMasterKeyId() : Constants.key.none;
}
// Some old key was updated
@@ -240,6 +254,34 @@ public abstract class OperationResults {
return (mResult & UPDATED) == UPDATED;
}
public SaveKeyringResult(Parcel source) {
super(source);
mRingMasterKeyId = source.readLong();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeLong(mRingMasterKeyId);
}
public static Creator<SaveKeyringResult> CREATOR = new Creator<SaveKeyringResult>() {
public SaveKeyringResult createFromParcel(final Parcel source) {
return new SaveKeyringResult(source);
}
public SaveKeyringResult[] newArray(final int size) {
return new SaveKeyringResult[size];
}
};
}
public static class ConsolidateResult extends OperationResultParcel {
public ConsolidateResult(int result, OperationLog log) {
super(result, log);
}
}
}

View File

@@ -78,7 +78,7 @@ public class PassphraseCacheService extends Service {
private static final int NOTIFICATION_ID = 1;
private static final int MSG_PASSPHRASE_CACHE_GET_OKAY = 1;
private static final int MSG_PASSPHRASE_CACHE_GET_KEY_NO_FOUND = 2;
private static final int MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND = 2;
private BroadcastReceiver mIntentReceiver;
@@ -170,7 +170,7 @@ public class PassphraseCacheService extends Service {
switch (returnMessage.what) {
case MSG_PASSPHRASE_CACHE_GET_OKAY:
return returnMessage.getData().getString(EXTRA_PASSPHRASE);
case MSG_PASSPHRASE_CACHE_GET_KEY_NO_FOUND:
case MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND:
throw new KeyNotFoundException();
default:
throw new KeyNotFoundException("should not happen!");
@@ -322,7 +322,7 @@ public class PassphraseCacheService extends Service {
msg.setData(bundle);
} catch (ProviderHelper.NotFoundException e) {
Log.e(Constants.TAG, "PassphraseCacheService: Passphrase for unknown key was requested!");
msg.what = MSG_PASSPHRASE_CACHE_GET_KEY_NO_FOUND;
msg.what = MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND;
}
try {

View File

@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
*
* 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
@@ -79,14 +80,16 @@ public class SaveKeyringParcel implements Parcelable {
// performance gain for using Parcelable here would probably be negligible,
// use Serializable instead.
public static class SubkeyAdd implements Serializable {
public int mAlgorithm;
public int mKeysize;
public Algorithm mAlgorithm;
public Integer mKeySize;
public Curve mCurve;
public int mFlags;
public Long mExpiry;
public SubkeyAdd(int algorithm, int keysize, int flags, Long expiry) {
public SubkeyAdd(Algorithm algorithm, Integer keySize, Curve curve, int flags, Long expiry) {
mAlgorithm = algorithm;
mKeysize = keysize;
mKeySize = keySize;
mCurve = curve;
mFlags = flags;
mExpiry = expiry;
}
@@ -94,7 +97,8 @@ public class SaveKeyringParcel implements Parcelable {
@Override
public String toString() {
String out = "mAlgorithm: " + mAlgorithm + ", ";
out += "mKeysize: " + mKeysize + ", ";
out += "mKeySize: " + mKeySize + ", ";
out += "mCurve: " + mCurve + ", ";
out += "mFlags: " + mFlags;
out += "mExpiry: " + mExpiry;
@@ -213,4 +217,20 @@ public class SaveKeyringParcel implements Parcelable {
return out;
}
// All supported algorithms
public enum Algorithm {
RSA, DSA, ELGAMAL, ECDSA, ECDH
}
// All curves defined in the standard
// http://www.bouncycastle.org/wiki/pages/viewpage.action?pageId=362269
public enum Curve {
NIST_P256, NIST_P384, NIST_P521,
// these are supported by gpg, but they are not in rfc6637 and not supported by BouncyCastle yet
// (adding support would be trivial though -> JcaPGPKeyConverter.java:190)
// BRAINPOOL_P256, BRAINPOOL_P384, BRAINPOOL_P512
}
}